mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-23 11:44:06 -08:00
✨ Add Cisco Webex Node & Trigger (#1865)
* ✨ Cisco Webex Node & Trigger * ⚡ Improvements * ⚡ Improvements * ⚡ Improvements * ⚡ Minor improvements Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
parent
2afd93520a
commit
ffa7bba6cf
|
@ -0,0 +1,46 @@
|
|||
import {
|
||||
ICredentialType,
|
||||
NodePropertyTypes,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
export class CiscoWebexOAuth2Api implements ICredentialType {
|
||||
name = 'ciscoWebexOAuth2Api';
|
||||
extends = [
|
||||
'oAuth2Api',
|
||||
];
|
||||
displayName = 'Cisco Webex OAuth2 API';
|
||||
properties = [
|
||||
{
|
||||
displayName: 'Authorization URL',
|
||||
name: 'authUrl',
|
||||
type: 'hidden' as NodePropertyTypes,
|
||||
default: 'https://webexapis.com/v1/authorize',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Access Token URL',
|
||||
name: 'accessTokenUrl',
|
||||
type: 'hidden' as NodePropertyTypes,
|
||||
default: 'https://webexapis.com/v1/access_token',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Scope',
|
||||
name: 'scope',
|
||||
type: 'hidden' as NodePropertyTypes,
|
||||
default: 'spark:memberships_read meeting:recordings_read spark:kms meeting:schedules_read spark:rooms_read spark:messages_write spark:memberships_write meeting:recordings_write meeting:preferences_read spark:messages_read meeting:schedules_write',
|
||||
},
|
||||
{
|
||||
displayName: 'Auth URI Query Parameters',
|
||||
name: 'authQueryParameters',
|
||||
type: 'hidden' as NodePropertyTypes,
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
type: 'hidden' as NodePropertyTypes,
|
||||
default: 'body',
|
||||
},
|
||||
];
|
||||
}
|
499
packages/nodes-base/nodes/Cisco/Webex/CiscoWebex.node.ts
Normal file
499
packages/nodes-base/nodes/Cisco/Webex/CiscoWebex.node.ts
Normal file
|
@ -0,0 +1,499 @@
|
|||
import {
|
||||
BINARY_ENCODING,
|
||||
IExecuteFunctions,
|
||||
} from 'n8n-core';
|
||||
|
||||
import {
|
||||
IBinaryData,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
NodeOperationError,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
getAttachemnts,
|
||||
webexApiRequest,
|
||||
webexApiRequestAllItems,
|
||||
} from './GenericFunctions';
|
||||
|
||||
import {
|
||||
meetingFields,
|
||||
meetingOperations,
|
||||
// meetingTranscriptFields,
|
||||
// meetingTranscriptOperations,
|
||||
messageFields,
|
||||
messageOperations,
|
||||
} from './descriptions';
|
||||
|
||||
import * as moment from 'moment-timezone';
|
||||
|
||||
export class CiscoWebex implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Cisco Webex',
|
||||
name: 'ciscoWebex',
|
||||
icon: 'file:ciscoWebex.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume the Cisco Webex API',
|
||||
defaults: {
|
||||
name: 'Cisco Webex',
|
||||
color: '#29b6f6',
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'ciscoWebexOAuth2Api',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Meeting',
|
||||
value: 'meeting',
|
||||
},
|
||||
// {
|
||||
// name: 'Meeeting Transcript',
|
||||
// value: 'meetingTranscript',
|
||||
// },
|
||||
{
|
||||
name: 'Message',
|
||||
value: 'message',
|
||||
},
|
||||
],
|
||||
default: 'message',
|
||||
description: 'Resource to consume',
|
||||
},
|
||||
...meetingOperations,
|
||||
...meetingFields,
|
||||
// ...meetingTranscriptOperations,
|
||||
// ...meetingTranscriptFields,
|
||||
...messageOperations,
|
||||
...messageFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
async getRooms(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const rooms = await webexApiRequestAllItems.call(this, 'items', 'GET', '/rooms');
|
||||
for (const room of rooms) {
|
||||
returnData.push({
|
||||
name: room.title,
|
||||
value: room.id,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
async getSites(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const sites = await webexApiRequestAllItems.call(this, 'sites', 'GET', '/meetingPreferences/sites');
|
||||
for (const site of sites) {
|
||||
returnData.push({
|
||||
name: site.siteUrl,
|
||||
value: site.siteUrl,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
const timezone = this.getTimezone();
|
||||
const resource = this.getNodeParameter('resource', 0) as string;
|
||||
const operation = this.getNodeParameter('operation', 0) as string;
|
||||
|
||||
let responseData;
|
||||
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
|
||||
try {
|
||||
if (resource === 'message') {
|
||||
|
||||
// **********************************************************************
|
||||
// message
|
||||
// **********************************************************************
|
||||
|
||||
if (operation === 'create') {
|
||||
|
||||
// ----------------------------------------
|
||||
// message: create
|
||||
// ----------------------------------------
|
||||
|
||||
// https://developer.webex.com/docs/api/v1/messages/create-a-message
|
||||
const destination = this.getNodeParameter('destination', i);
|
||||
const file = this.getNodeParameter('additionalFields.fileUi.fileValue', i, {}) as IDataObject;
|
||||
const markdown = this.getNodeParameter('additionalFields.markdown', i, '') as boolean;
|
||||
const body = {} as IDataObject;
|
||||
if (destination === 'room') {
|
||||
body['roomId'] = this.getNodeParameter('roomId', i);
|
||||
}
|
||||
|
||||
if (destination === 'person') {
|
||||
const specifyPersonBy = this.getNodeParameter('specifyPersonBy', 0) as string;
|
||||
if (specifyPersonBy === 'id') {
|
||||
body['toPersonId'] = this.getNodeParameter('toPersonId', i);
|
||||
} else {
|
||||
body['toPersonEmail'] = this.getNodeParameter('toPersonEmail', i);
|
||||
}
|
||||
}
|
||||
|
||||
if (markdown) {
|
||||
body['markdown'] = markdown;
|
||||
}
|
||||
|
||||
body['text'] = this.getNodeParameter('text', i);
|
||||
|
||||
body.attachments = getAttachemnts(this.getNodeParameter('additionalFields.attachmentsUi.attachmentValues', i, []) as IDataObject[]);
|
||||
|
||||
if (Object.keys(file).length) {
|
||||
|
||||
const isBinaryData = file.fileLocation === 'binaryData' ? true : false;
|
||||
|
||||
if (isBinaryData) {
|
||||
|
||||
if (!items[i].binary) {
|
||||
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
|
||||
}
|
||||
|
||||
const binaryPropertyName = file.binaryPropertyName as string;
|
||||
|
||||
const binaryData = items[i].binary![binaryPropertyName] as IBinaryData;
|
||||
|
||||
const formData = {
|
||||
files: {
|
||||
value: Buffer.from(binaryData.data, BINARY_ENCODING),
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
contentType: binaryData.mimeType,
|
||||
},
|
||||
},
|
||||
};
|
||||
Object.assign(body, formData);
|
||||
} else {
|
||||
const url = file.url as string;
|
||||
Object.assign(body, { files: url });
|
||||
}
|
||||
}
|
||||
|
||||
if (file.fileLocation === 'binaryData') {
|
||||
responseData = await webexApiRequest.call(this, 'POST', '/messages', {}, {}, undefined, { formData: body });
|
||||
} else {
|
||||
responseData = await webexApiRequest.call(this, 'POST', '/messages', body);
|
||||
}
|
||||
|
||||
|
||||
} else if (operation === 'delete') {
|
||||
|
||||
// ----------------------------------------
|
||||
// message: delete
|
||||
// ----------------------------------------
|
||||
|
||||
// https://developer.webex.com/docs/api/v1/messages/delete-a-message
|
||||
const messageId = this.getNodeParameter('messageId', i);
|
||||
|
||||
const endpoint = `/messages/${messageId}`;
|
||||
responseData = await webexApiRequest.call(this, 'DELETE', endpoint);
|
||||
responseData = { success: true };
|
||||
|
||||
} else if (operation === 'get') {
|
||||
|
||||
// ----------------------------------------
|
||||
// message: get
|
||||
// ----------------------------------------
|
||||
|
||||
// https://developer.webex.com/docs/api/v1/messages/get-message-details
|
||||
const messageId = this.getNodeParameter('messageId', i);
|
||||
|
||||
const endpoint = `/messages/${messageId}`;
|
||||
responseData = await webexApiRequest.call(this, 'GET', endpoint);
|
||||
|
||||
|
||||
} else if (operation === 'getAll') {
|
||||
|
||||
// ----------------------------------------
|
||||
// message: getAll
|
||||
// ----------------------------------------
|
||||
|
||||
// https://developer.webex.com/docs/api/v1/messages/list-messages
|
||||
const qs: IDataObject = {
|
||||
roomId: this.getNodeParameter('roomId', i),
|
||||
};
|
||||
const filters = this.getNodeParameter('filters', i) as IDataObject;
|
||||
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||
|
||||
|
||||
if (Object.keys(filters).length) {
|
||||
Object.assign(qs, filters);
|
||||
}
|
||||
|
||||
if (returnAll === true) {
|
||||
responseData = await webexApiRequestAllItems.call(this, 'items', 'GET', '/messages', {}, qs);
|
||||
} else {
|
||||
qs.max = this.getNodeParameter('limit', i) as number;
|
||||
responseData = await webexApiRequest.call(this, 'GET', '/messages', {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
|
||||
|
||||
} else if (operation === 'update') {
|
||||
|
||||
// ----------------------------------------
|
||||
// message: update
|
||||
// ----------------------------------------
|
||||
|
||||
// https://developer.webex.com/docs/api/v1/messages/edit-a-message
|
||||
const messageId = this.getNodeParameter('messageId', i) as string;
|
||||
const markdown = this.getNodeParameter('markdown', i) as boolean;
|
||||
|
||||
const endpoint = `/messages/${messageId}`;
|
||||
|
||||
responseData = await webexApiRequest.call(this, 'GET', endpoint);
|
||||
|
||||
const body = {
|
||||
roomId: responseData.roomId,
|
||||
} as IDataObject;
|
||||
|
||||
if (markdown === true) {
|
||||
body['markdown'] = this.getNodeParameter('markdownText', i);
|
||||
} else {
|
||||
body['text'] = this.getNodeParameter('text', i);
|
||||
}
|
||||
|
||||
responseData = await webexApiRequest.call(this, 'PUT', endpoint, body);
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'meeting') {
|
||||
if (operation === 'create') {
|
||||
const title = this.getNodeParameter('title', i) as string;
|
||||
const start = this.getNodeParameter('start', i) as string;
|
||||
const end = this.getNodeParameter('end', i) as string;
|
||||
const invitees = this.getNodeParameter('additionalFields.inviteesUi.inviteeValues', i, []) as IDataObject[];
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||
|
||||
const body: IDataObject = {
|
||||
title,
|
||||
start: moment.tz(start, timezone).format(),
|
||||
end: moment.tz(end, timezone).format(),
|
||||
...additionalFields,
|
||||
};
|
||||
|
||||
if (body.requireRegistrationInfo) {
|
||||
body['registration'] = (body.requireRegistrationInfo as string[])
|
||||
.reduce((obj, value) => Object.assign(obj, { [`${value}`]: true }), {});
|
||||
delete body.requireRegistrationInfo;
|
||||
}
|
||||
|
||||
if (invitees) {
|
||||
body['invitees'] = invitees;
|
||||
delete body.inviteesUi;
|
||||
}
|
||||
|
||||
responseData = await webexApiRequest.call(this, 'POST', '/meetings', body);
|
||||
|
||||
}
|
||||
|
||||
if (operation === 'delete') {
|
||||
const meetingId = this.getNodeParameter('meetingId', i) as string;
|
||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
||||
|
||||
const qs: IDataObject = {
|
||||
...options,
|
||||
};
|
||||
|
||||
responseData = await webexApiRequest.call(this, 'DELETE', `/meetings/${meetingId}`, {}, qs);
|
||||
responseData = { success: true };
|
||||
}
|
||||
|
||||
if (operation === 'get') {
|
||||
const meetingId = this.getNodeParameter('meetingId', i) as string;
|
||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
||||
let headers = {};
|
||||
|
||||
const qs: IDataObject = {
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options.passsword) {
|
||||
headers = {
|
||||
passsword: options.passsword,
|
||||
};
|
||||
}
|
||||
|
||||
responseData = await webexApiRequest.call(this, 'GET', `/meetings/${meetingId}`, {}, qs, undefined, { headers });
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
const filters = this.getNodeParameter('filters', i) as IDataObject;
|
||||
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||
|
||||
const qs: IDataObject = {
|
||||
...filters,
|
||||
};
|
||||
|
||||
if (qs.from) {
|
||||
qs.from = moment(qs.from as string).utc(true).format();
|
||||
}
|
||||
|
||||
if (qs.to) {
|
||||
qs.to = moment(qs.to as string).utc(true).format();
|
||||
}
|
||||
|
||||
if (returnAll === true) {
|
||||
responseData = await webexApiRequestAllItems.call(this, 'items', 'GET', '/meetings', {}, qs);
|
||||
returnData.push(...responseData);
|
||||
} else {
|
||||
qs.max = this.getNodeParameter('limit', i) as number;
|
||||
responseData = await webexApiRequest.call(this, 'GET', '/meetings', {}, qs);
|
||||
responseData = responseData.items;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
const meetingId = this.getNodeParameter('meetingId', i) as string;
|
||||
const invitees = this.getNodeParameter('updateFields.inviteesUi.inviteeValues', i, []) as IDataObject[];
|
||||
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
|
||||
|
||||
const {
|
||||
title,
|
||||
password,
|
||||
start,
|
||||
end,
|
||||
} = await webexApiRequest.call(this, 'GET', `/meetings/${meetingId}`);
|
||||
|
||||
const body: IDataObject = {
|
||||
...updateFields,
|
||||
};
|
||||
|
||||
if (body.requireRegistrationInfo) {
|
||||
body['registration'] = (body.requireRegistrationInfo as string[])
|
||||
.reduce((obj, value) => Object.assign(obj, { [`${value}`]: true }), {});
|
||||
delete body.requireRegistrationInfo;
|
||||
}
|
||||
|
||||
if (invitees.length) {
|
||||
body['invitees'] = invitees;
|
||||
}
|
||||
|
||||
if (body.start) {
|
||||
body.start = moment.tz(updateFields.start, timezone).format();
|
||||
} else {
|
||||
body.start = start;
|
||||
}
|
||||
|
||||
if (body.end) {
|
||||
body.end = moment.tz(updateFields.end, timezone).format();
|
||||
} else {
|
||||
body.end = end;
|
||||
}
|
||||
|
||||
if (!body.title) {
|
||||
body.title = title;
|
||||
}
|
||||
|
||||
if (!body.password) {
|
||||
body.password = password;
|
||||
}
|
||||
|
||||
responseData = await webexApiRequest.call(this, 'PUT', `/meetings/${meetingId}`, body);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(responseData)) {
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
} else if (responseData !== undefined) {
|
||||
returnData.push(responseData as IDataObject);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({ error: error.toString() });
|
||||
continue;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if (resource === 'meetingTranscript') {
|
||||
|
||||
// if (operation === 'download') {
|
||||
// for (let i = 0; i < items.length; i++) {
|
||||
// const transcriptId = this.getNodeParameter('transcriptId', i) as string;
|
||||
// const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
|
||||
// const meetingId = this.getNodeParameter('meetingId', i) as string;
|
||||
// const options = this.getNodeParameter('options', i) as IDataObject;
|
||||
|
||||
// const qs: IDataObject = {
|
||||
// meetingId,
|
||||
// ...options,
|
||||
// };
|
||||
// const transcription = await webexApiRequest.call(this, 'GET', `/meetingTranscripts/${transcriptId}/download`, {}, qs);
|
||||
|
||||
// responseData = {
|
||||
// json: {},
|
||||
// binary: {
|
||||
// [binaryPropertyName]: {
|
||||
// data: Buffer.from(transcription, BINARY_ENCODING),
|
||||
// //contentType:
|
||||
// //FILE
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (operation === 'getAll') {
|
||||
// for (let i = 0; i < items.length; i++) {
|
||||
// try {
|
||||
// const meetingId = this.getNodeParameter('meetingId', i) as string;
|
||||
// const filters = this.getNodeParameter('filters', i) as IDataObject;
|
||||
// const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||
|
||||
// const qs: IDataObject = {
|
||||
// meetingId,
|
||||
// ...filters,
|
||||
// };
|
||||
|
||||
// if (returnAll === true) {
|
||||
// responseData = await webexApiRequestAllItems.call(this, 'items', 'GET', '/meetingTranscripts', {}, qs);
|
||||
// returnData.push(...responseData);
|
||||
// } else {
|
||||
// qs.max = this.getNodeParameter('limit', i) as number;
|
||||
// responseData = await webexApiRequest.call(this, 'GET', '/meetingTranscripts', {}, qs);
|
||||
// returnData.push(...responseData.items);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// if (this.continueOnFail()) {
|
||||
// returnData.push({
|
||||
// error: error.message,
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
}
|
683
packages/nodes-base/nodes/Cisco/Webex/CiscoWebexTrigger.node.ts
Normal file
683
packages/nodes-base/nodes/Cisco/Webex/CiscoWebexTrigger.node.ts
Normal file
|
@ -0,0 +1,683 @@
|
|||
import {
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
} from 'n8n-core';
|
||||
|
||||
import {
|
||||
IDataObject,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
IWebhookResponseData,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
getAutomaticSecret,
|
||||
getEvents,
|
||||
mapResource,
|
||||
webexApiRequest,
|
||||
webexApiRequestAllItems,
|
||||
} from './GenericFunctions';
|
||||
|
||||
import {
|
||||
createHmac,
|
||||
} from 'crypto';
|
||||
|
||||
export class CiscoWebexTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Cisco Webex Trigger',
|
||||
name: 'ciscoWebexTrigger',
|
||||
icon: 'file:ciscoWebex.svg',
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["resource"] + ":" + $parameter["event"]}}',
|
||||
description: 'Starts the workflow when Cisco Webex events occur.',
|
||||
defaults: {
|
||||
name: 'Cisco Webex Trigger',
|
||||
color: '#29b6f6',
|
||||
},
|
||||
inputs: [],
|
||||
outputs: ['main'],
|
||||
credentials: [
|
||||
{
|
||||
name: 'ciscoWebexOAuth2Api',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
name: 'default',
|
||||
httpMethod: 'POST',
|
||||
responseMode: 'onReceived',
|
||||
path: 'webhook',
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Attachment Action',
|
||||
value: 'attachmentAction',
|
||||
},
|
||||
{
|
||||
name: 'Meeting',
|
||||
value: 'meeting',
|
||||
},
|
||||
{
|
||||
name: 'Membership',
|
||||
value: 'membership',
|
||||
},
|
||||
{
|
||||
name: 'Message',
|
||||
value: 'message',
|
||||
},
|
||||
// {
|
||||
// name: 'Telephony Call',
|
||||
// value: 'telephonyCall',
|
||||
// },
|
||||
{
|
||||
name: 'Recording',
|
||||
value: 'recording',
|
||||
},
|
||||
{
|
||||
name: 'Room',
|
||||
value: 'room',
|
||||
},
|
||||
{
|
||||
name: '*',
|
||||
value: 'all',
|
||||
},
|
||||
],
|
||||
default: 'meeting',
|
||||
required: true,
|
||||
},
|
||||
...getEvents(),
|
||||
{
|
||||
displayName: 'Resolve Data',
|
||||
name: 'resolveData',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'attachmentAction',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'By default the response only contain a reference to the data the user inputed<br />If this option gets activated it will resolve the data automatically.',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Has Files',
|
||||
name: 'hasFiles',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'message',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Limit to messages which contain file content attachments',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Locked',
|
||||
name: 'isLocked',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'room',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Limit to rooms that are locked',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Moderator',
|
||||
name: 'isModerator',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'membership',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Limit to moderators of a room',
|
||||
},
|
||||
{
|
||||
displayName: 'Mentioned People',
|
||||
name: 'mentionedPeople',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'message',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: `Limit to messages which contain these mentioned people, by person ID; accepts me as a shorthand for your own person ID; separate multiple values with commas`,
|
||||
},
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'attachmentAction',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular message, by ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Owned By',
|
||||
name: 'ownedBy',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'meeting',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Person Email',
|
||||
name: 'personEmail',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'membership',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular person, by email',
|
||||
},
|
||||
{
|
||||
displayName: 'Person Email',
|
||||
name: 'personEmail',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'message',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular person, by email',
|
||||
},
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'attachmentAction',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular person, by ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'membership',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular person, by ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'personId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'message',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular person, by ID',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Room ID',
|
||||
name: 'roomId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'attachmentAction',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular room, by ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Room ID',
|
||||
name: 'roomId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'membership',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular room, by ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Room ID',
|
||||
name: 'roomId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'message',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Limit to a particular room, by ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Room Type',
|
||||
name: 'roomType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Direct',
|
||||
value: 'direct',
|
||||
},
|
||||
{
|
||||
name: 'Group',
|
||||
value: 'group',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'message',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'deleted',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: `Limit to a particular room type`,
|
||||
},
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Direct',
|
||||
value: 'direct',
|
||||
},
|
||||
{
|
||||
name: 'Group',
|
||||
value: 'group',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/resource': [
|
||||
'room',
|
||||
],
|
||||
'/event': [
|
||||
'created',
|
||||
'updated',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: `Limit to a particular room type`,
|
||||
},
|
||||
// {
|
||||
// displayName: 'Call Type',
|
||||
// name: 'callType',
|
||||
// type: 'options',
|
||||
// options: [
|
||||
// {
|
||||
// name: 'Emergency',
|
||||
// value: 'emergency',
|
||||
// },
|
||||
// {
|
||||
// name: 'External',
|
||||
// value: 'external',
|
||||
// },
|
||||
// {
|
||||
// name: 'Location',
|
||||
// value: 'location',
|
||||
// },
|
||||
// {
|
||||
// name: 'Disconnected',
|
||||
// value: 'disconnected',
|
||||
// },
|
||||
// {
|
||||
// name: 'Organization',
|
||||
// value: 'organization',
|
||||
// },
|
||||
// {
|
||||
// name: 'Other',
|
||||
// value: 'other',
|
||||
// },
|
||||
// {
|
||||
// name: 'Repair',
|
||||
// value: 'repair',
|
||||
// },
|
||||
// ],
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// '/resource': [
|
||||
// 'telephonyCall',
|
||||
// ],
|
||||
// '/event': [
|
||||
// 'created',
|
||||
// 'deleted',
|
||||
// 'updated',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// default: '',
|
||||
// description: `Limit to a particular call type`,
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Person ID',
|
||||
// name: 'personId',
|
||||
// type: 'string',
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// '/resource': [
|
||||
// 'telephonyCall',
|
||||
// ],
|
||||
// '/event': [
|
||||
// 'created',
|
||||
// 'deleted',
|
||||
// 'updated',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// default: '',
|
||||
// description: 'Limit to a particular person, by ID',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Personality',
|
||||
// name: 'personality',
|
||||
// type: 'options',
|
||||
// options: [
|
||||
// {
|
||||
// name: 'Click To Dial',
|
||||
// value: 'clickToDial',
|
||||
// },
|
||||
// {
|
||||
// name: 'Originator',
|
||||
// value: 'originator',
|
||||
// },
|
||||
// {
|
||||
// name: 'Terminator',
|
||||
// value: 'terminator',
|
||||
// },
|
||||
// ],
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// '/resource': [
|
||||
// 'telephonyCall',
|
||||
// ],
|
||||
// '/event': [
|
||||
// 'created',
|
||||
// 'deleted',
|
||||
// 'updated',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// default: '',
|
||||
// description: `Limit to a particular call personality`,
|
||||
// },
|
||||
// {
|
||||
// displayName: 'State',
|
||||
// name: 'state',
|
||||
// type: 'options',
|
||||
// options: [
|
||||
// {
|
||||
// name: 'Alerting',
|
||||
// value: 'alerting',
|
||||
// },
|
||||
// {
|
||||
// name: 'Connected',
|
||||
// value: 'connected',
|
||||
// },
|
||||
// {
|
||||
// name: 'Connecting',
|
||||
// value: 'connecting',
|
||||
// },
|
||||
// {
|
||||
// name: 'Disconnected',
|
||||
// value: 'disconnected',
|
||||
// },
|
||||
// {
|
||||
// name: 'Held',
|
||||
// value: 'held',
|
||||
// },
|
||||
// {
|
||||
// name: 'Remote Held',
|
||||
// value: 'remoteHeld',
|
||||
// },
|
||||
// ],
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// '/resource': [
|
||||
// 'telephonyCall',
|
||||
// ],
|
||||
// '/event': [
|
||||
// 'created',
|
||||
// 'deleted',
|
||||
// 'updated',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// default: '',
|
||||
// description: `Limit to a particular call state`,
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// @ts-ignore (because of request)
|
||||
webhookMethods = {
|
||||
default: {
|
||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookUrl = this.getNodeWebhookUrl('default');
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const resource = this.getNodeParameter('resource') as string;
|
||||
const event = this.getNodeParameter('event') as string;
|
||||
|
||||
// Check all the webhooks which exist already if it is identical to the
|
||||
// one that is supposed to get created.
|
||||
const data = await webexApiRequestAllItems.call(this, 'items', 'GET', '/webhooks');
|
||||
for (const webhook of data) {
|
||||
if (webhook.url === webhookUrl
|
||||
&& webhook.resource === mapResource(resource)
|
||||
&& webhook.event === event
|
||||
&& webhook.status === 'active') {
|
||||
webhookData.webhookId = webhook.id as string;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
async create(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const webhookUrl = this.getNodeWebhookUrl('default');
|
||||
const event = this.getNodeParameter('event') as string;
|
||||
const resource = this.getNodeParameter('resource') as string;
|
||||
const filters = this.getNodeParameter('filters', {}) as IDataObject;
|
||||
const secret = getAutomaticSecret(this.getCredentials('ciscoWebexOAuth2Api')!);
|
||||
const filter = [];
|
||||
for (const key of Object.keys(filters)) {
|
||||
if (key !== 'ownedBy') {
|
||||
filter.push(`${key}=${filters[key]}`);
|
||||
}
|
||||
}
|
||||
const endpoint = '/webhooks';
|
||||
|
||||
const body: IDataObject = {
|
||||
name: `n8n-webhook:${webhookUrl}`,
|
||||
targetUrl: webhookUrl,
|
||||
event,
|
||||
resource: mapResource(resource),
|
||||
};
|
||||
|
||||
if (filters.ownedBy) {
|
||||
body['ownedBy'] = filters.ownedBy as string;
|
||||
}
|
||||
|
||||
body['secret'] = secret;
|
||||
|
||||
if (filter.length) {
|
||||
body['filter'] = filter.join('&');
|
||||
}
|
||||
|
||||
const responseData = await webexApiRequest.call(this, 'POST', endpoint, body);
|
||||
if (responseData.id === undefined) {
|
||||
// Required data is missing so was not successful
|
||||
return false;
|
||||
}
|
||||
|
||||
webhookData.webhookId = responseData.id as string;
|
||||
webhookData.secret = secret;
|
||||
return true;
|
||||
},
|
||||
async delete(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
if (webhookData.webhookId !== undefined) {
|
||||
|
||||
const endpoint = `/webhooks/${webhookData.webhookId}`;
|
||||
try {
|
||||
await webexApiRequest.call(this, 'DELETE', endpoint);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove from the static workflow data so that it is clear
|
||||
// that no webhooks are registred anymore
|
||||
delete webhookData.webhookId;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
let bodyData = this.getBodyData();
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const headers = this.getHeaderData() as IDataObject;
|
||||
const req = this.getRequestObject();
|
||||
const resolveData = this.getNodeParameter('resolveData', false) as boolean;
|
||||
|
||||
//@ts-ignore
|
||||
const computedSignature = createHmac('sha1', webhookData.secret).update(req.rawBody).digest('hex');
|
||||
if (headers['x-spark-signature'] !== computedSignature) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (resolveData) {
|
||||
const { data: { id } } = bodyData as { data: { id: string } };
|
||||
bodyData = await webexApiRequest.call(this, 'GET', `/attachment/actions/${id}`);
|
||||
}
|
||||
|
||||
return {
|
||||
workflowData: [
|
||||
this.helpers.returnJsonArray(bodyData),
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
657
packages/nodes-base/nodes/Cisco/Webex/GenericFunctions.ts
Normal file
657
packages/nodes-base/nodes/Cisco/Webex/GenericFunctions.ts
Normal file
|
@ -0,0 +1,657 @@
|
|||
import {
|
||||
OptionsWithUri,
|
||||
} from 'request';
|
||||
|
||||
import {
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
} from 'n8n-core';
|
||||
|
||||
import {
|
||||
ICredentialDataDecryptedObject,
|
||||
IDataObject,
|
||||
INodeProperties,
|
||||
IWebhookFunctions,
|
||||
NodeApiError,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
upperFirst,
|
||||
} from 'lodash';
|
||||
|
||||
import {
|
||||
createHash,
|
||||
} from 'crypto';
|
||||
|
||||
export async function webexApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions | IWebhookFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
|
||||
let options: OptionsWithUri = {
|
||||
method,
|
||||
body,
|
||||
qs,
|
||||
uri: uri || `https://webexapis.com/v1${resource}`,
|
||||
json: true,
|
||||
};
|
||||
try {
|
||||
if (Object.keys(option).length !== 0) {
|
||||
options = Object.assign({}, options, option);
|
||||
}
|
||||
if (Object.keys(body).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
if (Object.keys(qs).length === 0) {
|
||||
delete options.qs;
|
||||
}
|
||||
//@ts-ignore
|
||||
return await this.helpers.requestOAuth2.call(this, 'ciscoWebexOAuth2Api', options, { tokenType: 'Bearer' });
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function webexApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}, options: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
|
||||
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
let uri: string | undefined;
|
||||
query.max = 100;
|
||||
do {
|
||||
responseData = await webexApiRequest.call(this, method, endpoint, body, query, uri, { resolveWithFullResponse: true, ...options });
|
||||
if (responseData.headers.link) {
|
||||
uri = responseData.headers['link'].split(';')[0].replace('<', '').replace('>', '');
|
||||
}
|
||||
returnData.push.apply(returnData, responseData.body[propertyName]);
|
||||
} while (
|
||||
responseData.headers['link'] !== undefined &&
|
||||
responseData.headers['link'].includes('rel="next"')
|
||||
);
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export function getEvents() {
|
||||
const resourceEvents: { [key: string]: string[] } = {
|
||||
'attachmentAction': ['created', 'deleted', 'updated', '*'],
|
||||
'membership': ['created', 'deleted', 'updated', '*'],
|
||||
'message': ['created', 'deleted', 'updated', '*'],
|
||||
'room': ['created', 'deleted', 'updated', '*'],
|
||||
'meeting': ['created', 'deleted', 'updated', 'started', 'ended', '*'],
|
||||
'recording': ['created', 'deleted', 'updated', '*'],
|
||||
'telephonyCall': ['created', 'deleted', 'updated'],
|
||||
'*': ['created', 'updated', 'deleted', '*'],
|
||||
};
|
||||
|
||||
const elements: INodeProperties[] = [];
|
||||
|
||||
for (const resource of Object.keys(resourceEvents)) {
|
||||
elements.push({
|
||||
displayName: 'Event',
|
||||
name: 'event',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
(resource === '*') ? 'all' : resource,
|
||||
],
|
||||
},
|
||||
},
|
||||
options: resourceEvents[resource].map((event) => ({ value: (event === '*' ? 'all' : event), name: upperFirst(event) })),
|
||||
default: '',
|
||||
required: true,
|
||||
});
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
export function mapResource(event: string) {
|
||||
return ({
|
||||
'attachmentAction': 'attachmentActions',
|
||||
'membership': 'memberships',
|
||||
'message': 'messages',
|
||||
'room': 'rooms',
|
||||
'meeting': 'meetings',
|
||||
'recording': 'recordings',
|
||||
'telephonyCall': 'telephony_calls',
|
||||
'all': 'all',
|
||||
} as { [key: string]: string })[event];
|
||||
}
|
||||
|
||||
export function getAttachemnts(attachements: IDataObject[]) {
|
||||
const _attachments: IDataObject[] = [];
|
||||
for (const attachment of attachements) {
|
||||
const body: IDataObject[] = [];
|
||||
const actions: IDataObject[] = [];
|
||||
for (const element of (attachment?.elementsUi as IDataObject).elementValues as IDataObject[] || []) {
|
||||
// tslint:disable-next-line: no-any
|
||||
const { type, ...rest } = element as { type: string, [key: string]: any };
|
||||
if (type.startsWith('input')) {
|
||||
body.push({ type: `Input.${upperFirst(type.replace('input', ''))}`, ...removeEmptyProperties(rest) });
|
||||
} else {
|
||||
body.push({ type: upperFirst(type), ...removeEmptyProperties(rest) });
|
||||
}
|
||||
}
|
||||
for (const action of (attachment?.actionsUi as IDataObject).actionValues as IDataObject[] || []) {
|
||||
// tslint:disable-next-line: no-any
|
||||
const { type, ...rest } = action as { type: string, [key: string]: any };
|
||||
actions.push({ type: `Action.${upperFirst(type)}`, ...removeEmptyProperties(rest) });
|
||||
}
|
||||
_attachments.push({
|
||||
contentType: 'application/vnd.microsoft.card.adaptive',
|
||||
content: {
|
||||
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
|
||||
type: 'AdaptiveCard',
|
||||
version: '1.2',
|
||||
body,
|
||||
actions,
|
||||
},
|
||||
});
|
||||
}
|
||||
return _attachments;
|
||||
}
|
||||
|
||||
export function getActionInheritedProperties() {
|
||||
return [
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
description: 'Label for button or link that represents this action.',
|
||||
},
|
||||
{
|
||||
displayName: 'Icon URL',
|
||||
name: 'iconUrl',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Optional icon to be shown on the action in conjunction with the title. Supports data URI in version 1.2+',
|
||||
},
|
||||
{
|
||||
displayName: 'Style',
|
||||
name: 'style',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Positive',
|
||||
value: 'positive',
|
||||
},
|
||||
{
|
||||
name: 'Destructive',
|
||||
value: 'destructive',
|
||||
},
|
||||
],
|
||||
default: 'default',
|
||||
description: 'Controls the style of an Action, which influences how the action is displayed, spoken, etc.',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getTextBlockProperties() {
|
||||
return [
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
description: 'Text to display. A subset of markdown is supported (https://aka.ms/ACTextFeatures)',
|
||||
},
|
||||
{
|
||||
displayName: 'Color',
|
||||
name: 'color',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Dark',
|
||||
value: 'dark',
|
||||
},
|
||||
{
|
||||
name: 'Light',
|
||||
value: 'light',
|
||||
},
|
||||
{
|
||||
name: 'Accent',
|
||||
value: 'accent',
|
||||
},
|
||||
{
|
||||
name: 'Good',
|
||||
value: 'good',
|
||||
},
|
||||
{
|
||||
name: 'Warning',
|
||||
value: 'warning',
|
||||
},
|
||||
{
|
||||
name: 'Attention',
|
||||
value: 'attention',
|
||||
},
|
||||
],
|
||||
default: 'default',
|
||||
description: 'Color of the TextBlock element',
|
||||
},
|
||||
{
|
||||
displayName: 'Font Type',
|
||||
name: 'fontType',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Monospace',
|
||||
value: 'monospace',
|
||||
},
|
||||
],
|
||||
default: 'default',
|
||||
description: 'Type of font to use for rendering',
|
||||
},
|
||||
{
|
||||
displayName: 'Horizontal Alignment',
|
||||
name: 'horizontalAlignment',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Left',
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
name: 'Center',
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
name: 'Right',
|
||||
value: 'right',
|
||||
},
|
||||
],
|
||||
default: 'left',
|
||||
description: 'Controls the horizontal text alignment',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Subtle',
|
||||
name: 'isSubtle',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Displays text slightly toned down to appear less prominent',
|
||||
},
|
||||
{
|
||||
displayName: 'Max Lines',
|
||||
name: 'maxLines',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 1,
|
||||
description: 'Specifies the maximum number of lines to display',
|
||||
},
|
||||
{
|
||||
displayName: 'Size',
|
||||
name: 'size',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Small',
|
||||
value: 'small',
|
||||
},
|
||||
{
|
||||
name: 'Medium',
|
||||
value: 'medium',
|
||||
},
|
||||
{
|
||||
name: 'Large',
|
||||
value: 'large',
|
||||
},
|
||||
{
|
||||
name: 'Extra Large',
|
||||
value: 'extraLarge',
|
||||
},
|
||||
],
|
||||
default: 'default',
|
||||
description: 'Controls size of text',
|
||||
},
|
||||
{
|
||||
displayName: 'Weight',
|
||||
name: 'weight',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Lighter',
|
||||
value: 'lighter',
|
||||
},
|
||||
{
|
||||
name: 'Bolder',
|
||||
value: 'bolder',
|
||||
},
|
||||
],
|
||||
default: 'default',
|
||||
description: 'Controls the weight of TextBlock elements',
|
||||
},
|
||||
{
|
||||
displayName: 'Wrap',
|
||||
name: 'wrap',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'If true, allow text to wrap. Otherwise, text is clipped',
|
||||
},
|
||||
{
|
||||
displayName: 'Height',
|
||||
name: 'height',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Auto',
|
||||
value: 'auto',
|
||||
},
|
||||
{
|
||||
name: 'Stretch',
|
||||
value: 'stretch',
|
||||
},
|
||||
],
|
||||
default: 'auto',
|
||||
description: 'Specifies the height of the element',
|
||||
},
|
||||
{
|
||||
displayName: 'Separator',
|
||||
name: 'separator',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'When true, draw a separating line at the top of the element.',
|
||||
},
|
||||
{
|
||||
displayName: 'Spacing',
|
||||
name: 'spacing',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
{
|
||||
name: 'Small',
|
||||
value: 'small',
|
||||
},
|
||||
{
|
||||
name: 'Medium',
|
||||
value: 'medium',
|
||||
},
|
||||
{
|
||||
name: 'Large',
|
||||
value: 'large',
|
||||
},
|
||||
{
|
||||
name: 'Extra Large',
|
||||
value: 'extraLarge',
|
||||
},
|
||||
{
|
||||
name: 'Padding',
|
||||
value: 'padding',
|
||||
},
|
||||
],
|
||||
default: 'default',
|
||||
description: 'Controls the amount of spacing between this element and the preceding element',
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'A unique identifier associated with the item',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Visible',
|
||||
name: 'isVisible',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'textBlock',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'If false, this item will be removed from the visual trees',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getInputTextProperties() {
|
||||
return [
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Unique identifier for the value. Used to identify collected input when the Submit action is performed',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Multiline',
|
||||
name: 'isMultiline',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'If true, allow multiple lines of input',
|
||||
},
|
||||
{
|
||||
displayName: 'Max Length',
|
||||
name: 'maxLength',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 1,
|
||||
description: 'Hint of maximum length characters to collect (may be ignored by some clients)',
|
||||
},
|
||||
{
|
||||
displayName: 'Placeholder',
|
||||
name: 'placeholder',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Description of the input desired. Displayed when no text has been input',
|
||||
},
|
||||
{
|
||||
displayName: 'Regex',
|
||||
name: 'regex',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Regular expression indicating the required format of this text input',
|
||||
},
|
||||
{
|
||||
displayName: 'Style',
|
||||
name: 'style',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Text',
|
||||
value: 'text',
|
||||
},
|
||||
{
|
||||
name: 'Tel',
|
||||
value: 'tel',
|
||||
},
|
||||
{
|
||||
name: 'URL',
|
||||
value: 'url',
|
||||
},
|
||||
{
|
||||
name: 'Email',
|
||||
value: 'email',
|
||||
},
|
||||
],
|
||||
default: 'text',
|
||||
description: 'Style hint for text input',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'inputText',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The initial value for this field',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: no-any
|
||||
function removeEmptyProperties(rest: { [key: string]: any }) {
|
||||
return Object.keys(rest)
|
||||
.filter((k) => rest[k] !== '')
|
||||
.reduce((a, k) => ({ ...a, [k]: rest[k] }), {});
|
||||
}
|
||||
|
||||
export function getAutomaticSecret(credentials: ICredentialDataDecryptedObject) {
|
||||
const data = `${credentials.clientId},${credentials.clientSecret}`;
|
||||
return createHash('md5').update(data).digest('hex');
|
||||
}
|
1
packages/nodes-base/nodes/Cisco/Webex/ciscoWebex.svg
Normal file
1
packages/nodes-base/nodes/Cisco/Webex/ciscoWebex.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path fill="#7cb342" d="M32.334,13.733c0.092,0.706,0.144,1.424,0.144,2.155c0,9.181-7.463,16.623-16.669,16.623 c-0.733,0-1.453-0.052-2.161-0.144C14.305,33.584,15.895,36.132,19,38c0.699,0.421,3.13,1.851,6,2c7.195,0.374,14.844-7.424,15-15 c0.021-1.024,0.041-4.057-2-7C36.061,15.203,33.379,14.101,32.334,13.733z"/><path fill="#29b6f6" d="M10.661,24c0-7.315,5.947-13.246,13.283-13.246c3.668,0,6.989,1.483,9.392,3.88l4.789-4.776 C34.496,6.239,29.482,4,23.944,4C12.867,4,3.888,12.954,3.888,24c0,5.523,2.245,10.523,5.874,14.142l4.789-4.776 C12.148,30.969,10.661,27.658,10.661,24z"/><path fill="#244b71" d="M38.126,9.858c-1.323-1.319-3.467-1.319-4.789,0c-1.323,1.319-1.323,3.457,0,4.776c0,0,0,0,0,0 c2.404,2.397,3.89,5.708,3.89,9.366c0,7.315-5.947,13.246-13.283,13.246c-3.668,0-6.989-1.483-9.392-3.88l0,0 c-1.323-1.319-3.467-1.319-4.789,0c-1.323,1.319-1.323,3.457,0,4.776C13.392,41.761,18.406,44,23.944,44C35.021,44,44,35.046,44,24 C44,18.477,41.755,13.477,38.126,9.858z"/></svg>
|
After Width: | Height: | Size: 1 KiB |
|
@ -0,0 +1,969 @@
|
|||
import {
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
export const meetingOperations = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
value: 'getAll',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
description: 'Operation to perform',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
export const meetingFields = [
|
||||
// ----------------------------------------
|
||||
// meeting: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'Meeting title. The title can be a maximum of 128 characters long',
|
||||
},
|
||||
{
|
||||
displayName: 'Start',
|
||||
name: 'start',
|
||||
type: 'dateTime',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'Date and time for the start of meeting. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'End',
|
||||
name: 'end',
|
||||
type: 'dateTime',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'Date and time for the end of meeting. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Agenda',
|
||||
name: 'agenda',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Meeting agenda. The agenda can be a maximum of 1300 characters long',
|
||||
},
|
||||
{
|
||||
displayName: 'Allow Any User To Be Co-Host',
|
||||
name: 'allowAnyUserToBeCoHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow any attendee with a host account on the target site to become a co-host when joining the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'Allow Authenticated Devices',
|
||||
name: 'allowAuthenticatedDevices',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow authenticated video devices in the meeting's organization to start or join the meeting without a prompt`,
|
||||
},
|
||||
{
|
||||
displayName: 'Allow First User To Be Co-Host',
|
||||
name: 'allowFirstUserToBeCoHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow the first attendee of the meeting with a host account on the target site to become a co-host`,
|
||||
},
|
||||
{
|
||||
displayName: 'Auto Accept Request',
|
||||
name: 'autoAcceptRequest',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether or not meeting registration request is accepted automatically',
|
||||
},
|
||||
{
|
||||
displayName: 'Enable Connect Audio Before Host',
|
||||
name: 'enableConnectAudioBeforeHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow any attendee to connect audio in the meeting before the host joins the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'Enabled Auto Record Meeting',
|
||||
name: 'enabledAutoRecordMeeting',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not meeting is recorded automatically`,
|
||||
},
|
||||
{
|
||||
displayName: 'Enabled Join Before Host',
|
||||
name: 'enabledJoinBeforeHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow any attendee to join the meeting before the host joins the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'Exclude Password',
|
||||
name: 'excludePassword',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to exclude password from the meeting email invitation`,
|
||||
},
|
||||
{
|
||||
displayName: 'Host Email',
|
||||
name: 'hostEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `Email address for the meeting host. Can only be set if you're an admin`,
|
||||
},
|
||||
{
|
||||
displayName: 'Integration Tags',
|
||||
name: 'integrationTags',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `External keys created by an integration application in its own domain. They could be Zendesk ticket IDs, Jira IDs, Salesforce Opportunity IDs, etc`,
|
||||
},
|
||||
{
|
||||
displayName: 'Invitees',
|
||||
name: 'inviteesUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'Add Invitee',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Invitee',
|
||||
name: 'inviteeValues',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Email address of meeting invitee',
|
||||
},
|
||||
{
|
||||
displayName: 'Display Name',
|
||||
name: 'displayName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Display name of meeting invitee',
|
||||
},
|
||||
{
|
||||
displayName: 'Co-Host',
|
||||
name: 'coHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether or not invitee is allowed to be a co-host for the meeting',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Join Before Host Minutes',
|
||||
name: 'joinBeforeHostMinutes',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: '0',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '5',
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
name: '10',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '15',
|
||||
value: 15,
|
||||
},
|
||||
],
|
||||
default: 0,
|
||||
description: `The number of minutes an attendee can join the meeting before the meeting start time and the host joins`,
|
||||
},
|
||||
{
|
||||
displayName: 'Public Meeting',
|
||||
name: 'publicMeeting',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow the meeting to be listed on the public calendar`,
|
||||
},
|
||||
{
|
||||
displayName: 'Recurrence',
|
||||
name: 'recurrence',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `Rule for how the meeting should recur. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>`,
|
||||
},
|
||||
{
|
||||
displayName: 'Required Registration Info',
|
||||
name: 'requireRegistrationInfo',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'Require First Name',
|
||||
value: 'requireFirstName',
|
||||
},
|
||||
{
|
||||
name: 'Require Last Name',
|
||||
value: 'requireLastName',
|
||||
},
|
||||
{
|
||||
name: 'Require Email',
|
||||
value: 'requireEmail',
|
||||
},
|
||||
{
|
||||
name: 'Require Job Title',
|
||||
value: 'requireJobTitle',
|
||||
},
|
||||
{
|
||||
name: 'Require Company Name',
|
||||
value: 'requireCompanyName',
|
||||
},
|
||||
{
|
||||
name: 'Require Address 1',
|
||||
value: 'requireAddress1',
|
||||
},
|
||||
{
|
||||
name: 'Require Address 2',
|
||||
value: 'requireAddress2',
|
||||
},
|
||||
{
|
||||
name: 'Require City',
|
||||
value: 'requireCity',
|
||||
},
|
||||
{
|
||||
name: 'Require State',
|
||||
value: 'requireState',
|
||||
},
|
||||
{
|
||||
name: 'Require Zip Code',
|
||||
value: 'requireZipCode',
|
||||
},
|
||||
{
|
||||
name: 'Require Country Region',
|
||||
value: 'requireCountryRegion',
|
||||
},
|
||||
{
|
||||
name: 'Require Work Phone',
|
||||
value: 'requireWorkPhone',
|
||||
},
|
||||
{
|
||||
name: 'Require Fax',
|
||||
value: 'requireFax',
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
description: 'Data required for meeting registration',
|
||||
},
|
||||
{
|
||||
displayName: 'Reminder Time',
|
||||
name: 'reminderTime',
|
||||
type: 'number',
|
||||
default: 1,
|
||||
description: `The number of minutes before the meeting begins, for sending an email reminder to the host`,
|
||||
},
|
||||
{
|
||||
displayName: 'Send Email',
|
||||
name: 'sendEmail',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: `Whether or not to send emails to host and invitees`,
|
||||
},
|
||||
{
|
||||
displayName: 'Site URL',
|
||||
name: 'siteUrl',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSites',
|
||||
},
|
||||
default: '',
|
||||
description: `URL of the Webex site which the meeting is created on. If not specified, the meeting is created on user's preferred site`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// meeting: delete
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Meeting ID',
|
||||
name: 'meetingId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'delete',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'ID of the meeting',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'delete',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Host Email',
|
||||
name: 'hostEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Email address for the meeting host. This parameter is only used if the user or application calling the API has the admin-level scopes',
|
||||
},
|
||||
{
|
||||
displayName: 'Send Email',
|
||||
name: 'sendEmail',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'Whether or not to send emails to host and invitees.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// meeting: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Meeting ID',
|
||||
name: 'meetingId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'get',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'ID of the meeting',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'get',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Host Email',
|
||||
name: 'hostEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Email address for the meeting host. This parameter is only used if the user or application calling the API has the admin-level scopes',
|
||||
},
|
||||
{
|
||||
displayName: 'Password',
|
||||
name: 'password',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `Meeting password. It's required when the meeting is protected by a password and the current user is not privileged to view it if they are not a host, co-host or invitee of the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'Send Email',
|
||||
name: 'sendEmail',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'Whether or not to send emails to host and invitees. It is an optional field and default value is true',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// meeting: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Return all results.',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'The number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
returnAll: [
|
||||
false,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'From',
|
||||
name: 'from',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'Start date and time (inclusive) for the meeting. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Host Email',
|
||||
name: 'hostEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Email address for the meeting host',
|
||||
},
|
||||
{
|
||||
displayName: 'Integration Tag',
|
||||
name: 'integrationTag',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'External tag created by another application, e.g. Zendesk ticket ID or Jira ID',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit to Current Meetings',
|
||||
name: 'current',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'For meeting series, whether to return just the current meeting or all meetings',
|
||||
},
|
||||
{
|
||||
displayName: 'Meeting Number',
|
||||
name: 'meetingNumber',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Meeting number for the meeting objects being requested',
|
||||
},
|
||||
{
|
||||
displayName: 'Meeting Type',
|
||||
name: 'meetingType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Meeting Series',
|
||||
value: 'meetingSeries',
|
||||
description: 'Master of a scheduled series of meetings which consists of one or more scheduled meeting based on a recurrence rule',
|
||||
},
|
||||
{
|
||||
name: 'Scheduled Meeting',
|
||||
value: 'scheduledMeeting',
|
||||
description: 'Instance from a master meeting series',
|
||||
},
|
||||
{
|
||||
name: 'Meeting',
|
||||
value: 'meeting',
|
||||
description: 'Meeting instance that is actually happening or has happened',
|
||||
},
|
||||
],
|
||||
default: 'meetingSeries',
|
||||
},
|
||||
{
|
||||
displayName: 'Participant Email',
|
||||
name: 'participantEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Email of a person that must be a meeting participant',
|
||||
},
|
||||
{
|
||||
displayName: 'Site URL',
|
||||
name: 'siteUrl',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSites',
|
||||
},
|
||||
default: '',
|
||||
description: 'URL of the Webex site which the API lists meetings from',
|
||||
},
|
||||
{
|
||||
displayName: 'State',
|
||||
name: 'state',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Active',
|
||||
value: 'active',
|
||||
},
|
||||
{
|
||||
name: 'Scheduled',
|
||||
value: 'scheduled',
|
||||
},
|
||||
{
|
||||
name: 'Ready',
|
||||
value: 'ready',
|
||||
},
|
||||
{
|
||||
name: 'Lobby',
|
||||
value: 'lobby',
|
||||
},
|
||||
{
|
||||
name: 'In Progress',
|
||||
value: 'inProgress',
|
||||
},
|
||||
{
|
||||
name: 'Ended',
|
||||
value: 'ended',
|
||||
},
|
||||
{
|
||||
name: 'Missed',
|
||||
value: 'missed',
|
||||
},
|
||||
{
|
||||
name: 'Expired',
|
||||
value: 'expired',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description: 'Meeting state for the meeting objects being requested',
|
||||
},
|
||||
{
|
||||
displayName: 'To',
|
||||
name: 'to',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'End date and time (inclusive) for the meeting. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Weblink',
|
||||
name: 'webLink',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'URL encoded link to information page for the meeting objects being requested',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// meeting: update
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Meeting ID',
|
||||
name: 'meetingId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'update',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'ID of the meeting',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meeting',
|
||||
],
|
||||
operation: [
|
||||
'update',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Agenda',
|
||||
name: 'agenda',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `The meeting's agenda. Cannot be longer that 1300 characters`,
|
||||
},
|
||||
{
|
||||
displayName: 'Allow Any User To Be Co-Host',
|
||||
name: 'allowAnyUserToBeCoHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow any attendee with a host account on the target site to become a co-host when joining the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'Allow Authenticated Devices',
|
||||
name: 'allowAuthenticatedDevices',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow authenticated video devices in the meeting's organization to start or join the meeting without a prompt`,
|
||||
},
|
||||
{
|
||||
displayName: 'Allow First User To Be Co-Host',
|
||||
name: 'allowFirstUserToBeCoHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow the first attendee of the meeting with a host account on the target site to become a co-host`,
|
||||
},
|
||||
{
|
||||
displayName: 'Enable Connect Audio Before Host',
|
||||
name: 'enableConnectAudioBeforeHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow any attendee to connect audio in the meeting before the host joins the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'Enabled Auto Record Meeting',
|
||||
name: 'enabledAutoRecordMeeting',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not meeting is recorded automatically`,
|
||||
},
|
||||
{
|
||||
displayName: 'Enabled Join Before Host',
|
||||
name: 'enabledJoinBeforeHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow any attendee to join the meeting before the host joins the meeting`,
|
||||
},
|
||||
{
|
||||
displayName: 'End',
|
||||
name: 'end',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'Date and time for the end of meeting. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Exclude Password',
|
||||
name: 'excludePassword',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to exclude password from the meeting email invitation`,
|
||||
},
|
||||
{
|
||||
displayName: 'Host Email',
|
||||
name: 'hostEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `Email address for the meeting host. This attribute should only be set if the user or application calling the API has the admin-level scopes`,
|
||||
},
|
||||
{
|
||||
displayName: 'Invitees',
|
||||
name: 'inviteesUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'Add Invitee',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Invitee',
|
||||
name: 'inviteeValues',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Email address of meeting invitee',
|
||||
},
|
||||
{
|
||||
displayName: 'Display Name',
|
||||
name: 'displayName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Display name of meeting invitee',
|
||||
},
|
||||
{
|
||||
displayName: 'Co-Host',
|
||||
name: 'coHost',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether or not invitee is allowed to be a co-host for the meeting',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Join Before Host Minutes',
|
||||
name: 'joinBeforeHostMinutes',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: '0',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '5',
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
name: '10',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '15',
|
||||
value: 15,
|
||||
},
|
||||
],
|
||||
default: 0,
|
||||
description: `The number of minutes an attendee can join the meeting before the meeting start time and the host joins`,
|
||||
},
|
||||
{
|
||||
displayName: 'Password',
|
||||
name: 'password',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `Meeting password. Must conform to the site's password complexity settings.</br>
|
||||
If not specified, a random password conforming to the site's password rules will be generated automatically`,
|
||||
},
|
||||
{
|
||||
displayName: 'Public Meeting',
|
||||
name: 'publicMeeting',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to allow the meeting to be listed on the public calendar`,
|
||||
},
|
||||
{
|
||||
displayName: 'Recurrence',
|
||||
name: 'recurrence',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `Meeting series recurrence rule (conforming with RFC 2445), applying only to meeting series`,
|
||||
},
|
||||
{
|
||||
displayName: 'Required Registration Info',
|
||||
name: 'requireRegistrationInfo',
|
||||
type: 'multiOptions',
|
||||
options: [
|
||||
{
|
||||
name: 'Require First Name',
|
||||
value: 'requireFirstName',
|
||||
},
|
||||
{
|
||||
name: 'Require Last Name',
|
||||
value: 'requireLastName',
|
||||
},
|
||||
{
|
||||
name: 'Require Email',
|
||||
value: 'requireEmail',
|
||||
},
|
||||
{
|
||||
name: 'Require Job Title',
|
||||
value: 'requireJobTitle',
|
||||
},
|
||||
{
|
||||
name: 'Require Company Name',
|
||||
value: 'requireCompanyName',
|
||||
},
|
||||
{
|
||||
name: 'Require Address 1',
|
||||
value: 'requireAddress1',
|
||||
},
|
||||
{
|
||||
name: 'Require Address 2',
|
||||
value: 'requireAddress2',
|
||||
},
|
||||
{
|
||||
name: 'Require City',
|
||||
value: 'requireCity',
|
||||
},
|
||||
{
|
||||
name: 'Require State',
|
||||
value: 'requireState',
|
||||
},
|
||||
{
|
||||
name: 'Require Zip Code',
|
||||
value: 'requireZipCode',
|
||||
},
|
||||
{
|
||||
name: 'Require Country Region',
|
||||
value: 'requireCountryRegion',
|
||||
},
|
||||
{
|
||||
name: 'Require Work Phone',
|
||||
value: 'requireWorkPhone',
|
||||
},
|
||||
{
|
||||
name: 'Require Fax',
|
||||
value: 'requireFax',
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
description: 'Data required for meeting registration',
|
||||
},
|
||||
{
|
||||
displayName: 'Reminder Time',
|
||||
name: 'reminderTime',
|
||||
type: 'number',
|
||||
default: 1,
|
||||
description: `The number of minutes before the meeting begins, for sending an email reminder to the host`,
|
||||
},
|
||||
{
|
||||
displayName: 'Send Email',
|
||||
name: 'sendEmail',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Whether or not to send emails to host and invitees. It is an optional field and default value is true`,
|
||||
},
|
||||
{
|
||||
displayName: 'Site URL',
|
||||
name: 'siteUrl',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSites',
|
||||
},
|
||||
default: '',
|
||||
description: `URL of the Webex site which the meeting is created on. If not specified, the meeting is created on user's preferred site`,
|
||||
},
|
||||
{
|
||||
displayName: 'Start',
|
||||
name: 'start',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'Date and time for the start of meeting. Acceptable <a href="https://datatracker.ietf.org/doc/html/rfc2445" target="_blank"> format</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Meeting title',
|
||||
},
|
||||
],
|
||||
},
|
||||
] as INodeProperties[];
|
|
@ -0,0 +1,196 @@
|
|||
import {
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
export const meetingTranscriptOperations = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Download',
|
||||
value: 'download',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
value: 'getAll',
|
||||
},
|
||||
],
|
||||
default: 'download',
|
||||
description: 'Operation to perform',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
export const meetingTranscriptFields = [
|
||||
// ----------------------------------------
|
||||
// meetingTranscript: download
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Transcript ID',
|
||||
name: 'transcriptId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'download',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the meeting transcript',
|
||||
},
|
||||
{
|
||||
displayName: 'Meeting ID',
|
||||
name: 'meetingId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'download',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the meeting instance which the transcripts belong to',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'download',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Option',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Format',
|
||||
name: 'format',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'txt',
|
||||
value: 'txt',
|
||||
},
|
||||
{
|
||||
name: 'vtt',
|
||||
value: 'vtt',
|
||||
},
|
||||
],
|
||||
default: 'vtt',
|
||||
description: 'Format for the downloaded meeting transcript',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// meetingTranscript: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Meeting ID',
|
||||
name: 'meetingId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the meeting instance which the transcripts belong to',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Return all results.',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'The number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
returnAll: [
|
||||
false,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'meetingTranscript',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Host Email',
|
||||
name: 'hostEmail',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Email address for the meetingTranscript host',
|
||||
},
|
||||
],
|
||||
},
|
||||
] as INodeProperties[];
|
|
@ -0,0 +1,657 @@
|
|||
import {
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
getActionInheritedProperties, getInputTextProperties, getTextBlockProperties,
|
||||
} from '../GenericFunctions';
|
||||
|
||||
export const messageOperations = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
value: 'getAll',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
description: 'Operation to perform',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
export const messageFields = [
|
||||
// ----------------------------------------
|
||||
// message: create
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Destination',
|
||||
name: 'destination',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Room',
|
||||
value: 'room',
|
||||
},
|
||||
{
|
||||
name: 'Person',
|
||||
value: 'person',
|
||||
},
|
||||
],
|
||||
required: true,
|
||||
default: 'room',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Room ID',
|
||||
name: 'roomId',
|
||||
description: ' The room ID',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getRooms',
|
||||
},
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
destination: [
|
||||
'room',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Specify Person By',
|
||||
name: 'specifyPersonBy',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Email',
|
||||
value: 'email',
|
||||
},
|
||||
{
|
||||
name: 'ID',
|
||||
value: 'id',
|
||||
},
|
||||
],
|
||||
required: true,
|
||||
default: 'email',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
destination: [
|
||||
'person',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Person ID',
|
||||
name: 'toPersonId',
|
||||
description: 'The person ID',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
specifyPersonBy: [
|
||||
'id',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Person Email',
|
||||
name: 'toPersonEmail',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
specifyPersonBy: [
|
||||
'email',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The message, in plain text',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Attachments',
|
||||
name: 'attachmentsUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
placeholder: 'Add Attachment',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Attachment',
|
||||
name: 'attachmentValues',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Elements',
|
||||
name: 'elementsUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Element',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Element',
|
||||
name: 'elementValues',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Text Block',
|
||||
value: 'textBlock',
|
||||
},
|
||||
{
|
||||
name: 'Input Text',
|
||||
value: 'inputText',
|
||||
},
|
||||
],
|
||||
default: 'textBlock',
|
||||
description: '',
|
||||
},
|
||||
...getTextBlockProperties(),
|
||||
...getInputTextProperties(),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Actions',
|
||||
name: 'actionsUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Action',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Action',
|
||||
name: 'actionValues',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Execute',
|
||||
value: 'execute',
|
||||
},
|
||||
{
|
||||
name: 'Open URL',
|
||||
value: 'openUrl',
|
||||
},
|
||||
{
|
||||
name: 'Submit',
|
||||
value: 'submit',
|
||||
},
|
||||
],
|
||||
default: 'openUrl',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
displayName: 'URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'openUrl',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The URL to open',
|
||||
},
|
||||
{
|
||||
displayName: 'Data',
|
||||
name: 'data',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'submit',
|
||||
'execute',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Any extra data to pass along. These are essentially ‘hidden’ properties',
|
||||
},
|
||||
{
|
||||
displayName: 'Verb',
|
||||
name: 'verb',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [
|
||||
'execute',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The card author-defined verb associated with this action',
|
||||
},
|
||||
...getActionInheritedProperties(),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'File',
|
||||
name: 'fileUi',
|
||||
placeholder: 'Add File',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
name: 'fileValue',
|
||||
displayName: 'File',
|
||||
values: [
|
||||
{
|
||||
displayName: 'File Location',
|
||||
name: 'fileLocation',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'URL',
|
||||
value: 'url',
|
||||
},
|
||||
{
|
||||
name: 'Binary Data',
|
||||
value: 'binaryData',
|
||||
},
|
||||
],
|
||||
default: 'url',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Input Field With File',
|
||||
name: 'binaryPropertyName',
|
||||
type: 'string',
|
||||
default: 'data',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
fileLocation: [
|
||||
'binaryData',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The field in the node input containing the binary file data',
|
||||
},
|
||||
{
|
||||
displayName: 'URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
fileLocation: [
|
||||
'url',
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The public URL of the file',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Markdown',
|
||||
name: 'markdown',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The message in markdown format. When used the text parameter is used to provide alternate text for UI clients that do not support rich text',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// message: delete
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
description: 'ID of the message to delete',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'delete',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// message: get
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
description: 'ID of the message to retrieve',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'get',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// message: getAll
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Room ID',
|
||||
name: 'roomId',
|
||||
description: 'List messages in a room, by ID',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getRooms',
|
||||
},
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Return all results',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 50,
|
||||
description: 'The number of results to return',
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
returnAll: [
|
||||
false,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Before',
|
||||
name: 'before',
|
||||
description: 'List messages sent before a date and time',
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Before Message',
|
||||
name: 'beforeMessage',
|
||||
description: 'List messages sent before a message, by ID',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Parent Message ID',
|
||||
name: 'parentId',
|
||||
description: 'List messages with a parent, by ID',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Mentioned Person',
|
||||
name: 'mentionedPeople',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `List only messages with certain person mentioned. Enter their ID. You can use 'me' as a shorthand for yourself`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------------
|
||||
// message: update
|
||||
// ----------------------------------------
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
description: 'ID of the message to update',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'update',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Is Markdown',
|
||||
name: 'markdown',
|
||||
description: 'Whether the message uses markdown',
|
||||
type: 'boolean',
|
||||
required: true,
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'update',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'update',
|
||||
],
|
||||
markdown: [
|
||||
false,
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The message, in plain text',
|
||||
},
|
||||
{
|
||||
displayName: 'Markdown',
|
||||
name: 'markdownText',
|
||||
description: 'The message, in Markdown format. The maximum message length is 7439 bytes',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'message',
|
||||
],
|
||||
operation: [
|
||||
'update',
|
||||
],
|
||||
markdown: [
|
||||
true,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
] as INodeProperties[];
|
|
@ -0,0 +1,3 @@
|
|||
export * from './MessageDescription';
|
||||
export * from './MeetingDescription';
|
||||
export * from './MeetingTranscript';
|
|
@ -53,6 +53,7 @@
|
|||
"dist/credentials/BubbleApi.credentials.js",
|
||||
"dist/credentials/ChargebeeApi.credentials.js",
|
||||
"dist/credentials/CircleCiApi.credentials.js",
|
||||
"dist/credentials/CiscoWebexOAuth2Api.credentials.js",
|
||||
"dist/credentials/ClearbitApi.credentials.js",
|
||||
"dist/credentials/ClickUpApi.credentials.js",
|
||||
"dist/credentials/ClickUpOAuth2Api.credentials.js",
|
||||
|
@ -327,6 +328,8 @@
|
|||
"dist/nodes/Chargebee/Chargebee.node.js",
|
||||
"dist/nodes/Chargebee/ChargebeeTrigger.node.js",
|
||||
"dist/nodes/CircleCi/CircleCi.node.js",
|
||||
"dist/nodes/Cisco/Webex/CiscoWebex.node.js",
|
||||
"dist/nodes/Cisco/Webex/CiscoWebexTrigger.node.js",
|
||||
"dist/nodes/Clearbit/Clearbit.node.js",
|
||||
"dist/nodes/ClickUp/ClickUp.node.js",
|
||||
"dist/nodes/ClickUp/ClickUpTrigger.node.js",
|
||||
|
|
Loading…
Reference in a new issue