add meeting functionality

This commit is contained in:
shraddha shaligram 2020-06-22 11:51:15 -07:00
parent 37c80f3d8b
commit b95e3464a4
15 changed files with 1561 additions and 175 deletions

View file

@ -38,7 +38,7 @@ The most important directories:
execution, active webhooks and execution, active webhooks and
workflows workflows
- [/packages/editor-ui](/packages/editor-ui) - Vue frontend workflow editor - [/packages/editor-ui](/packages/editor-ui) - Vue frontend workflow editor
- [/packages/node-dev](/packages/node-dev) - Simple CLI to create new n8n-nodes - [/packages/node-dev](/packages/node-dev) - CLI to create new n8n-nodes
- [/packages/nodes-base](/packages/nodes-base) - Base n8n nodes - [/packages/nodes-base](/packages/nodes-base) - Base n8n nodes
- [/packages/workflow](/packages/workflow) - Workflow code with interfaces which - [/packages/workflow](/packages/workflow) - Workflow code with interfaces which
get used by front- & backend get used by front- & backend
@ -159,7 +159,7 @@ tests of all packages.
## Create Custom Nodes ## Create Custom Nodes
It is very easy to create own nodes for n8n. More information about that can It is very straightforward to create your own nodes for n8n. More information about that can
be found in the documentation of "n8n-node-dev" which is a small CLI which be found in the documentation of "n8n-node-dev" which is a small CLI which
helps with n8n-node-development. helps with n8n-node-development.
@ -177,9 +177,9 @@ If you want to create a node which should be added to n8n follow these steps:
1. Create a new folder for the new node. For a service named "Example" the folder would be called: `/packages/nodes-base/nodes/Example` 1. Create a new folder for the new node. For a service named "Example" the folder would be called: `/packages/nodes-base/nodes/Example`
1. If there is already a similar node simply copy the existing one in the new folder and rename it. If none exists yet, create a boilerplate node with [n8n-node-dev](https://github.com/n8n-io/n8n/tree/master/packages/node-dev) and copy that one in the folder. 1. If there is already a similar node, copy the existing one in the new folder and rename it. If none exists yet, create a boilerplate node with [n8n-node-dev](https://github.com/n8n-io/n8n/tree/master/packages/node-dev) and copy that one in the folder.
1. If the node needs credentials because it has to authenticate with an API or similar create new ones. Existing ones can be found in folder `/packages/nodes-base/credentials`. Also there it is the easiest to simply copy existing similar ones. 1. If the node needs credentials because it has to authenticate with an API or similar create new ones. Existing ones can be found in folder `/packages/nodes-base/credentials`. Also there it is the easiest to copy existing similar ones.
1. Add the path to the new node (and optionally credentials) to package.json of `nodes-base`. It already contains a property `n8n` with its own keys `credentials` and `nodes`. 1. Add the path to the new node (and optionally credentials) to package.json of `nodes-base`. It already contains a property `n8n` with its own keys `credentials` and `nodes`.
@ -236,6 +236,6 @@ docsify serve ./docs
That we do not have any potential problems later it is sadly necessary to sign a [Contributor License Agreement](CONTRIBUTOR_LICENSE_AGREEMENT.md). That can be done literally with the push of a button. That we do not have any potential problems later it is sadly necessary to sign a [Contributor License Agreement](CONTRIBUTOR_LICENSE_AGREEMENT.md). That can be done literally with the push of a button.
We used the most simple one that exists. It is from [Indie Open Source](https://indieopensource.com/forms/cla) which uses plain English and is literally just a few lines long. We used the most simple one that exists. It is from [Indie Open Source](https://indieopensource.com/forms/cla) which uses plain English and is literally only a few lines long.
A bot will automatically comment on the pull request once it got opened asking for the agreement to be signed. Before it did not get signed it is sadly not possible to merge it in. A bot will automatically comment on the pull request once it got opened asking for the agreement to be signed. Before it did not get signed it is sadly not possible to merge it in.

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -40,21 +40,11 @@ export async function zoomApiRequest(this: IExecuteFunctions | IExecuteSingleFun
throw new Error('No credentials got returned!'); throw new Error('No credentials got returned!');
} }
options.headers!.Authorization = `Bearer ${credentials.accessToken}`; options.headers!.Authorization = `Bearer ${credentials.accessToken}`;
console.log("options if");
console.log(options);
//@ts-ignore //@ts-ignore
return await this.helpers.request(options); return await this.helpers.request(options);
} else { } else {
console.log("options else");
console.log(options);
let credentials = this.getCredentials('zoomOAuth2Api');
// let oauthtoken1 = credentials!.oauthTokenData;
console.log(credentials);
console.log("credss");
//@ts-ignore //@ts-ignore
return await this.helpers.requestOAuth2.call(this, 'zoomOAuth2Api', options); return await this.helpers.requestOAuth2.call(this, 'zoomOAuth2Api', options);

View file

@ -0,0 +1,751 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const meetingOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'meeting',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a meeting',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a meeting',
},
{
name: 'Get',
value: 'get',
description: 'Retrieve a meeting',
},
{
name: 'Get All',
value: 'getAll',
description: 'Retrieve all meetings',
},
{
name: 'Update',
value: 'update',
description: 'Update a meeting',
}
],
default: 'create',
description: 'The operation to perform.',
}
] as INodeProperties[];
export const meetingFields = [
/* -------------------------------------------------------------------------- */
/* meeting:create */
/* -------------------------------------------------------------------------- */
{
displayName: 'Id',
name: 'userId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'meeting',
],
},
},
description: 'User ID.',
},
{
displayName: 'Additional settings',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'meeting',
],
}
},
options: [
{
displayName: 'Meeting topic',
name: 'topic',
type: 'string',
default: '',
description: `Meeting topic.`,
},
{
displayName: 'Meeting type',
name: 'type',
type: 'options',
options: [
{
name: 'Instant Meeting',
value: 1,
},
{
name: 'Scheduled Meeting',
value: 2,
},
{
name: 'Recurring meeting with no fixed time',
value: 3,
},
{
name: 'Recurring meeting with no fixed time',
value: 8,
},
],
default: 2,
description: 'Meeting type.'
},
{
displayName: 'Start time',
name: 'startTime',
type: 'dateTime',
default: '',
description: 'Start time should be used only for scheduled or recurring meetings with fixed time',
},
{
displayName: 'Duration',
name: 'duration',
type: 'number',
default: '',
description: 'Duration.',
},
{
displayName: 'Timezone',
name: 'timeZone',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getTimezones',
},
default: '',
description: `Time zone used in the response. The default is the time zone of the calendar.`,
},
{
displayName: 'Schedule for',
name: 'scheduleFor',
type: 'string',
default: '',
description: 'Schedule meeting for someone else from your account, provide their email id.',
},
{
displayName: 'Password',
name: 'password',
type: 'string',
default: '',
description: 'Password to join the meeting with maximum 10 characters.',
},
{
displayName: 'Agenda',
name: 'agenda',
type: 'string',
default: '',
description: 'Meeting agenda.',
},
{
displayName: 'Host Meeting in China',
name: 'cn_meeting',
type: 'boolean',
default: false,
description: 'Host Meeting in China.',
},
{
displayName: 'Host Meeting in India',
name: 'in_meeting',
type: 'boolean',
default: false,
description: 'Host Meeting in India.',
},
{
displayName: 'Host Video',
name: 'host_video',
type: 'boolean',
default: false,
description: 'Start video when host joins the meeting.',
},
{
displayName: 'Participant Video',
name: 'participant_video',
type: 'boolean',
default: false,
description: 'Start video when participant joins the meeting.',
},
{
displayName: 'Join before Host',
name: 'join_before_host',
type: 'boolean',
default: false,
description: 'Allow participants to join the meeting before host starts it.',
},
{
displayName: 'Muting before entry',
name: 'mute_upon_entry',
type: 'boolean',
default: false,
description: 'Mute participants upon entry.',
},
{
displayName: 'Watermark',
name: 'watermark',
type: 'boolean',
default: false,
description: 'Adds watermark when viewing a shared screen.',
},
{
displayName: 'Alternative Hosts',
name: 'alternative_hosts',
type: 'string',
default: '',
description: 'Alternative hosts email ids.',
},
{
displayName: 'Auto recording',
name: 'auto_recording',
type: 'options',
options: [
{
name: 'Record on local',
value: 'local',
},
{
name: 'Record on cloud',
value: 'cloud',
},
{
name: 'Disabled',
value: 'none',
},
],
default: 'none',
description: 'Auto recording.',
},
{
displayName: 'Audio',
name: 'auto_recording',
type: 'options',
options: [
{
name: 'Both Telephony and VoiP',
value: 'both',
},
{
name: 'Telephony',
value: 'telephony',
},
{
name: 'VOIP',
value: 'voip',
},
],
default: 'both',
description: 'Determine how participants can join audio portion of the meeting.',
},
{
displayName: 'Registration type',
name: 'registration_type',
type: 'options',
options: [
{
name: 'Attendees register once and can attend any of the occurences',
value: 1,
},
{
name: 'Attendees need to register for every occurence',
value: 2,
},
{
name: 'Attendees register once and can choose one or more occurences to attend',
value: 3,
},
],
default: 1,
description: 'Registration type. Used for recurring meetings with fixed time only',
},
],
},
/* -------------------------------------------------------------------------- */
/* meeting:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Id',
name: 'userId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'meeting',
],
},
},
description: 'User ID.',
},
/* -------------------------------------------------------------------------- */
/* meeting:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Id',
name: 'userId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meeting',
],
},
},
description: 'User ID.',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meeting',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meeting',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 300
},
default: 30,
description: 'How many results to return.',
},
{
displayName: 'Additional settings',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meeting',
],
}
},
options: [
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Scheduled',
value: 'scheduled',
},
{
name: 'Live',
value: 'live',
},
{
name: 'Upcoming',
value: 'upcoming',
},
],
default: 'live',
description: `Meeting type.`,
},
]
},
/* -------------------------------------------------------------------------- */
/* meeting:delete */
/* -------------------------------------------------------------------------- */
{
displayName: 'Meeting Id',
name: 'meetingId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'delete'
],
resource: [
'meeting',
],
},
},
description: 'Meeting ID.',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: [
'delete',
],
resource: [
'meeting',
],
},
},
options: [
{
displayName: 'Occurence Id',
name: 'occurenceId',
type: 'string',
default: '',
description: 'Meeting occurence Id.',
},
{
displayName: 'Schedule a reminder',
name: 'scheduleForReminder',
type: 'boolean',
default: false,
description: 'Schedule a reminder via email',
},
],
},
/* -------------------------------------------------------------------------- */
/* meeting:update */
/* -------------------------------------------------------------------------- */
{
displayName: 'Meeting Id',
name: 'meetingId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'meeting',
],
},
},
description: 'Meeting ID.',
},
{
displayName: 'Occurence Id',
name: 'occurenceId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'meeting',
],
},
},
description: 'Occurence ID.',
},
{
displayName: 'Additional settings',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'meeting',
],
}
},
options: [
{
displayName: 'Meeting topic',
name: 'topic',
type: 'string',
default: '',
description: `Meeting topic.`,
},
{
displayName: 'Meeting type',
name: 'type',
type: 'options',
options: [
{
name: 'Instant Meeting',
value: 1,
},
{
name: 'Scheduled Meeting',
value: 2,
},
{
name: 'Recurring meeting with no fixed time',
value: 3,
},
{
name: 'Recurring meeting with no fixed time',
value: 8,
},
],
default: 2,
description: 'Meeting type.'
},
{
displayName: 'Start time',
name: 'startTime',
type: 'dateTime',
default: '',
description: 'Start time should be used only for scheduled or recurring meetings with fixed time',
},
{
displayName: 'Duration',
name: 'duration',
type: 'number',
default: '',
description: 'Duration.',
},
{
displayName: 'Timezone',
name: 'timeZone',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getTimezones',
},
default: '',
description: `Time zone used in the response. The default is the time zone of the calendar.`,
},
{
displayName: 'Schedule for',
name: 'scheduleFor',
type: 'string',
default: '',
description: 'Schedule meeting for someone else from your account, provide their email id.',
},
{
displayName: 'Password',
name: 'password',
type: 'string',
default: '',
description: 'Password to join the meeting with maximum 10 characters.',
},
{
displayName: 'Agenda',
name: 'agenda',
type: 'string',
default: '',
description: 'Meeting agenda.',
},
{
displayName: 'Host Meeting in China',
name: 'cn_meeting',
type: 'boolean',
default: false,
description: 'Host Meeting in China.',
},
{
displayName: 'Host Meeting in India',
name: 'in_meeting',
type: 'boolean',
default: false,
description: 'Host Meeting in India.',
},
{
displayName: 'Host Video',
name: 'host_video',
type: 'boolean',
default: false,
description: 'Start video when host joins the meeting.',
},
{
displayName: 'Participant Video',
name: 'participant_video',
type: 'boolean',
default: false,
description: 'Start video when participant joins the meeting.',
},
{
displayName: 'Join before Host',
name: 'join_before_host',
type: 'boolean',
default: false,
description: 'Allow participants to join the meeting before host starts it.',
},
{
displayName: 'Muting before entry',
name: 'mute_upon_entry',
type: 'boolean',
default: false,
description: 'Mute participants upon entry.',
},
{
displayName: 'Watermark',
name: 'watermark',
type: 'boolean',
default: false,
description: 'Adds watermark when viewing a shared screen.',
},
{
displayName: 'Alternative Hosts',
name: 'alternative_hosts',
type: 'string',
default: '',
description: 'Alternative hosts email ids.',
},
{
displayName: 'Auto recording',
name: 'auto_recording',
type: 'options',
options: [
{
name: 'Record on local',
value: 'local',
},
{
name: 'Record on cloud',
value: 'cloud',
},
{
name: 'Disabled',
value: 'none',
},
],
default: 'none',
description: 'Auto recording.',
},
{
displayName: 'Audio',
name: 'auto_recording',
type: 'options',
options: [
{
name: 'Both Telephony and VoiP',
value: 'both',
},
{
name: 'Telephony',
value: 'telephony',
},
{
name: 'VOIP',
value: 'voip',
},
],
default: 'both',
description: 'Determine how participants can join audio portion of the meeting.',
},
{
displayName: 'Registration type',
name: 'registration_type',
type: 'options',
options: [
{
name: 'Attendees register once and can attend any of the occurences',
value: 1,
},
{
name: 'Attendees need to register for every occurence',
value: 2,
},
{
name: 'Attendees register once and can choose one or more occurences to attend',
value: 3,
},
],
default: 1,
description: 'Registration type. Used for recurring meetings with fixed time only',
},
],
},
] as INodeProperties[];

View file

@ -0,0 +1,407 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const meetingRegistrantOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'meetingRegistrants',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create Meeting Registrants',
},
{
name: 'Update',
value: 'update',
description: 'Update Meeting Registrant status',
},
{
name: 'Get All',
value: 'getAll',
description: 'Retrieve all meeting registrants',
},
],
default: 'create',
description: 'The operation to perform.',
}
] as INodeProperties[];
export const meetingRegistrantFields = [
/* -------------------------------------------------------------------------- */
/* meetingRegistrants:create */
/* -------------------------------------------------------------------------- */
{
displayName: 'Meeting Id',
name: 'meetingId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'meetingRegistrants',
],
},
},
description: 'Meeting ID.',
},
{
displayName: 'Occurence Id',
name: 'occurenceId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'meetingRegistrants',
],
},
},
description: 'Occurence ID.',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
required: true,
default: '',
description: 'Valid email-id of registrant.',
},
{
displayName: 'First name',
name: 'firstName',
required: true,
type: 'string',
default: '',
description: 'First Name.',
},
{
displayName: 'Additional settings',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'meetingRegistrants',
],
}
},
options: [
{
displayName: 'Last Name',
name: 'lastName',
type: 'string',
default: '',
description: 'Last Name.',
},
{
displayName: 'Address',
name: 'address',
type: 'string',
default: '',
description: 'Valid address of registrant.',
},
{
displayName: 'City',
name: 'city',
type: 'string',
default: '',
description: 'Valid city of registrant.',
},
{
displayName: 'State',
name: 'state',
type: 'string',
default: '',
description: 'Valid state of registrant.',
},
{
displayName: 'Country',
name: 'country',
type: 'string',
default: '',
description: 'Valid country of registrant.',
},
{
displayName: 'Zip code',
name: 'zip',
type: 'string',
default: '',
description: 'Valid zip-code of registrant.',
},
{
displayName: 'Phone Number',
name: 'phone',
type: 'string',
default: '',
description: 'Valid phone number of registrant.',
},
{
displayName: 'Comments',
name: 'comments',
type: 'string',
default: '',
description: 'Allows registrants to provide any questions they have.',
},
{
displayName: 'Organization',
name: 'org',
type: 'string',
default: '',
description: 'Organization of registrant.',
},
{
displayName: 'Job title',
name: 'job_title',
type: 'string',
default: '',
description: 'Job title of registrant.',
},
{
displayName: 'Purchasing time frame',
name: 'purchasing_time_frame',
type: 'options',
options: [
{
name: 'Within a month',
value: 'Within a month',
},
{
name: '1-3 months',
value: '1-3 months',
},
{
name: '4-6 months',
value: '4-6 months',
},
{
name: 'More than 6 months',
value: 'More than 6 months',
},
{
name: 'No timeframe',
value: 'No timeframe',
},
],
default: '',
description: 'Meeting type.'
},
{
displayName: 'Role in purchase process',
name: 'role_in_purchase_process',
type: 'options',
options: [
{
name: 'Decision Maker',
value: 'Decision Maker',
},
{
name: 'Evaluator/Recommender',
value: 'Evaluator/Recommender',
},
{
name: 'Influener',
value: 'Influener',
},
{
name: 'Not Involved',
value: 'Not Involved',
},
],
default: '',
description: 'Role in purchase process.'
},
],
},
/* -------------------------------------------------------------------------- */
/* meetingRegistrants:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Meeting Id',
name: 'meetingId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meetingRegistrants',
],
},
},
description: 'Meeting ID.',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meetingRegistrants',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'meetingRegistrants',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 300
},
default: 30,
description: 'How many results to return.',
},
{
displayName: 'Additional settings',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'meetingRegistrants',
],
}
},
options: [
{
displayName: 'Occurence Id',
name: 'occurence_id',
type: 'string',
default: '',
description: `Occurence Id.`,
},
{
displayName: 'Status',
name: 'status',
type: 'options',
options: [
{
name: 'Pending',
value: 'pending',
},
{
name: 'Approved',
value: 'approved',
},
{
name: 'Denied',
value: 'denied',
},
],
default: '',
description: `Registrant Status.`,
},
]
},
/* -------------------------------------------------------------------------- */
/* meetingRegistrants:update */
/* -------------------------------------------------------------------------- */
{
displayName: 'Meeting Id',
name: 'meetingId',
type: 'number',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'meetingRegistrants',
],
},
},
description: 'Meeting ID.',
},
{
displayName: 'Occurence Id',
name: 'occurenceId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'update',
],
resource: [
'meetingRegistrants',
],
},
},
description: 'Occurence ID.',
},
] as INodeProperties[];

View file

@ -3,7 +3,9 @@ import {
IDataObject, IDataObject,
INodeExecutionData, INodeExecutionData,
INodeType, INodeType,
ILoadOptionsFunctions,
INodeTypeDescription, INodeTypeDescription,
INodePropertyOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
zoomApiRequest, zoomApiRequest,
@ -14,7 +16,30 @@ import {
import { import {
meetingOperations, meetingOperations,
meetingFields, meetingFields,
} from './ZoomOperations'; } from './MeetingDescription';
import {
meetingRegistrantOperations,
meetingRegistrantFields,
} from './MeetingRegistrantDescription';
import * as moment from 'moment-timezone';
interface Settings {
host_video?: boolean;
participant_video?: boolean;
cn_meeting?: boolean;
in_meeting?: boolean;
join_before_host?: boolean;
mute_upon_entry?: boolean;
watermark?: boolean;
audio?: string;
alternative_hosts?: string;
auto_recording?: string;
registration_type?: number;
}
export class Zoom implements INodeType { export class Zoom implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
displayName: 'Zoom', displayName: 'Zoom',
@ -25,31 +50,11 @@ export class Zoom implements INodeType {
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
defaults: { defaults: {
name: 'Zoom', name: 'Zoom',
color: '#772244' color: '#0B6CF9'
}, },
icon: 'file:zoom.png', icon: 'file:zoom.png',
inputs: ['main'], inputs: ['main'],
outputs: ['main'], outputs: ['main'],
// credentials: [
// {
// name: 'zoomApi',
// required: true,
// displayOptions: {
// show: {
// authentication: ['accessToken']
// }
// }
// },
// {
// name: 'zoomOAuth2Api',
// required: true,
// displayOptions: {
// show: {
// authentication: ['oAuth2']
// }
// }
// }
// ],
credentials: [ credentials: [
{ {
name: 'zoomApi', name: 'zoomApi',
@ -100,16 +105,41 @@ export class Zoom implements INodeType {
{ {
name: 'Meeting', name: 'Meeting',
value: 'meeting' value: 'meeting'
},
{
name: 'Meeting Registrants',
value: 'meetingRegistrants'
} }
], ],
default: 'meeting', default: 'meeting',
description: 'The resource to operate on.' description: 'The resource to operate on.'
}, },
...meetingOperations, ...meetingOperations,
...meetingFields ...meetingFields,
...meetingRegistrantOperations,
...meetingRegistrantFields,
] ]
}; };
methods = {
loadOptions: {
// Get all the timezones to display them to user so that he can select them easily
async getTimezones(
this: ILoadOptionsFunctions
): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
for (const timezone of moment.tz.names()) {
const timezoneName = timezone;
const timezoneId = timezone;
returnData.push({
name: timezoneName,
value: timezoneId
});
}
return returnData;
}
}
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData(); const items = this.getInputData();
@ -120,11 +150,13 @@ export class Zoom implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string; const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string; const operation = this.getNodeParameter('operation', 0) as string;
console.log(this.getCredentials('zoomOAuth2Api')); console.log(this.getCredentials('zoomOAuth2Api'));
let body: IDataObject = {};
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
qs = {}; qs = {};
if (resource === 'meeting') { if (resource === 'meeting') {
if (operation === 'get') { if (operation === 'get') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meeting
const userId = this.getNodeParameter('userId', i) as string; const userId = this.getNodeParameter('userId', i) as string;
responseData = await zoomApiRequest.call( responseData = await zoomApiRequest.call(
@ -135,6 +167,283 @@ export class Zoom implements INodeType {
qs qs
); );
} }
if (operation === 'getAll') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetings
const userId = this.getNodeParameter('userId', i) as string;
responseData = await zoomApiRequest.call(
this,
'GET',
`/users/${userId}/meetings`,
{},
qs
);
}
if (operation === 'delete') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingdelete
const meetingId = this.getNodeParameter('meetingId', i) as string;
responseData = await zoomApiRequest.call(
this,
'DELETE',
`/meetings/${meetingId}`,
{},
qs
);
responseData = { success: true };
}
if (operation === 'create') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingcreate
const userId = this.getNodeParameter('userId', i) as string;
const additionalFields = this.getNodeParameter(
'additionalFields',
i
) as IDataObject;
const settings: Settings = {};
if (additionalFields.cn_meeting) {
settings.cn_meeting = additionalFields.cn_meeting as boolean;
}
if (additionalFields.in_meeting) {
settings.in_meeting = additionalFields.in_meeting as boolean;
}
if (additionalFields.join_before_host) {
settings.join_before_host = additionalFields.join_before_host as boolean;
}
if (additionalFields.mute_upon_entry) {
settings.mute_upon_entry = additionalFields.mute_upon_entry as boolean;
}
if (additionalFields.watermark) {
settings.watermark = additionalFields.watermark as boolean;
}
if (additionalFields.audio) {
settings.audio = additionalFields.audio as string;
}
if (additionalFields.alternative_hosts) {
settings.alternative_hosts = additionalFields.alternative_hosts as string;
}
if (additionalFields.participant_video) {
settings.participant_video = additionalFields.participant_video as boolean;
}
if (additionalFields.host_video) {
settings.host_video = additionalFields.host_video as boolean;
}
if (additionalFields.auto_recording) {
settings.auto_recording = additionalFields.auto_recording as string;
}
if (additionalFields.registration_type) {
settings.registration_type = additionalFields.registration_type as number;
}
body = {
settings,
};
if (additionalFields.topic) {
body.topic = additionalFields.topic as string;
}
if (additionalFields.type) {
body.type = additionalFields.type as string;
}
if (additionalFields.startTime) {
body.start_time = additionalFields.startTime as string;
}
if (additionalFields.duration) {
body.duration = additionalFields.duration as number;
}
if (additionalFields.scheduleFor) {
body.schedule_for = additionalFields.scheduleFor as string;
}
if (additionalFields.timeZone) {
body.timezone = additionalFields.timeZone as string;
}
if (additionalFields.password) {
body.password = additionalFields.password as string;
}
if (additionalFields.agenda) {
body.agenda = additionalFields.agenda as string;
}
responseData = await zoomApiRequest.call(
this,
'POST',
`/users/${userId}/meetings`,
body,
qs
);
}
if (operation === 'update') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingupdate
const meetingId = this.getNodeParameter('meetingId', i) as string;
qs.occurence_id = this.getNodeParameter('occurenceId', i) as string;
const additionalFields = this.getNodeParameter(
'additionalFields',
i
) as IDataObject;
const settings: Settings = {};
if (additionalFields.cn_meeting) {
settings.cn_meeting = additionalFields.cn_meeting as boolean;
}
if (additionalFields.in_meeting) {
settings.in_meeting = additionalFields.in_meeting as boolean;
}
if (additionalFields.join_before_host) {
settings.join_before_host = additionalFields.join_before_host as boolean;
}
if (additionalFields.mute_upon_entry) {
settings.mute_upon_entry = additionalFields.mute_upon_entry as boolean;
}
if (additionalFields.watermark) {
settings.watermark = additionalFields.watermark as boolean;
}
if (additionalFields.audio) {
settings.audio = additionalFields.audio as string;
}
if (additionalFields.alternative_hosts) {
settings.alternative_hosts = additionalFields.alternative_hosts as string;
}
if (additionalFields.participant_video) {
settings.participant_video = additionalFields.participant_video as boolean;
}
if (additionalFields.host_video) {
settings.host_video = additionalFields.host_video as boolean;
}
if (additionalFields.auto_recording) {
settings.auto_recording = additionalFields.auto_recording as string;
}
if (additionalFields.registration_type) {
settings.registration_type = additionalFields.registration_type as number;
}
body = {
settings,
};
if (additionalFields.topic) {
body.topic = additionalFields.topic as string;
}
if (additionalFields.type) {
body.type = additionalFields.type as string;
}
if (additionalFields.startTime) {
body.start_time = additionalFields.startTime as string;
}
if (additionalFields.duration) {
body.duration = additionalFields.duration as number;
}
if (additionalFields.scheduleFor) {
body.schedule_for = additionalFields.scheduleFor as string;
}
if (additionalFields.timeZone) {
body.timezone = additionalFields.timeZone as string;
}
if (additionalFields.password) {
body.password = additionalFields.password as string;
}
if (additionalFields.agenda) {
body.agenda = additionalFields.agenda as string;
}
responseData = await zoomApiRequest.call(
this,
'PATCH',
`/meetings/${meetingId}`,
body,
qs
);
}
}
if (resource === 'meetingRegistrant') {
if (operation === 'create') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingregistrantcreate
const meetingId = this.getNodeParameter('meetingId', i) as string;
qs.occurence_id = this.getNodeParameter('occurenceId', i) as string;
responseData = await zoomApiRequest.call(
this,
'PATCH',
`/meetings/${meetingId}/registrants`,
body,
qs
);
}
if (operation === 'getAll') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingregistrants
}
if (operation === 'update') {
//https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingregistrantstatus
}
} }
} }
if (Array.isArray(responseData)) { if (Array.isArray(responseData)) {

View file

@ -1,71 +0,0 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const meetingOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'meeting',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a meeting',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a meeting',
},
{
name: 'Get',
value: 'get',
description: 'Retrieve a meeting',
},
{
name: 'Get All',
value: 'getAll',
description: 'Retrieve all meetings',
},
{
name: 'Update',
value: 'update',
description: 'Update a meeting',
}
],
default: 'create',
description: 'The operation to perform.',
}
] as INodeProperties[];
export const meetingFields = [
/* -------------------------------------------------------------------------- */
/* meeting:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'User Id',
name: 'userId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'meeting',
],
},
},
description: 'User ID.',
},
] as INodeProperties[];

View file

@ -215,7 +215,7 @@ Licensor: n8n GmbH
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2020 n8n GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.