first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
IHookFunctions,
|
||||
IWebhookFunctions,
|
||||
JsonObject,
|
||||
IHttpRequestMethods,
|
||||
IRequestOptions,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
import type { IMessage } from './MessageInterface';
|
||||
import type { IStream } from './StreamInterface';
|
||||
import type { IUser } from './UserInterface';
|
||||
|
||||
export async function zulipApiRequest(
|
||||
this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
|
||||
body: IMessage | IStream | IUser = {},
|
||||
query: IDataObject = {},
|
||||
uri?: string,
|
||||
option: IDataObject = {},
|
||||
) {
|
||||
const credentials = await this.getCredentials('zulipApi');
|
||||
|
||||
const endpoint = `${credentials.url.toString().replace(new RegExp('/$'), '')}/api/v1`;
|
||||
|
||||
let options: IRequestOptions = {
|
||||
auth: {
|
||||
user: credentials.email as string,
|
||||
password: credentials.apiKey as string,
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
method,
|
||||
form: body as IDataObject,
|
||||
qs: query,
|
||||
uri: uri || `${endpoint}${resource}`,
|
||||
json: true,
|
||||
};
|
||||
if (!Object.keys(body).length) {
|
||||
delete options.form;
|
||||
}
|
||||
if (!Object.keys(query).length) {
|
||||
delete options.qs;
|
||||
}
|
||||
options = Object.assign({}, options, option);
|
||||
try {
|
||||
return await this.helpers.request(options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export function validateJSON(json: string | undefined): any {
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(json!);
|
||||
} catch (exception) {
|
||||
result = undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const messageOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a message',
|
||||
action: 'Delete a message',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a message',
|
||||
action: 'Get a message',
|
||||
},
|
||||
{
|
||||
name: 'Send Private',
|
||||
value: 'sendPrivate',
|
||||
description: 'Send a private message',
|
||||
action: 'Send a private message',
|
||||
},
|
||||
{
|
||||
name: 'Send to Stream',
|
||||
value: 'sendStream',
|
||||
description: 'Send a message to stream',
|
||||
action: 'Send a message to a stream',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a message',
|
||||
action: 'Update a message',
|
||||
},
|
||||
{
|
||||
name: 'Upload a File',
|
||||
value: 'updateFile',
|
||||
action: 'Upload a file',
|
||||
},
|
||||
],
|
||||
default: 'sendPrivate',
|
||||
},
|
||||
];
|
||||
|
||||
export const messageFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:sendPrivate */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-multi-options
|
||||
displayName: 'To',
|
||||
name: 'to',
|
||||
type: 'multiOptions',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
required: true,
|
||||
default: [],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['sendPrivate'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The destination stream, or a comma-separated list containing the usernames (emails) of the recipients. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Content',
|
||||
name: 'content',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['sendPrivate'],
|
||||
},
|
||||
},
|
||||
description: 'The content of the message',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:sendStream */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Stream Name or ID',
|
||||
name: 'stream',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getStreams',
|
||||
},
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['sendStream'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The destination stream, or a comma-separated list containing the usernames (emails) of the recipients. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Topic Name or ID',
|
||||
name: 'topic',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsDependsOn: ['stream'],
|
||||
loadOptionsMethod: 'getTopics',
|
||||
},
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['sendStream'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The topic of the message. Only required if type is stream, ignored otherwise. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Content',
|
||||
name: 'content',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['sendStream'],
|
||||
},
|
||||
},
|
||||
description: 'The content of the message',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the message',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Fields',
|
||||
name: 'updateFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Content',
|
||||
name: 'content',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The content of the message',
|
||||
},
|
||||
{
|
||||
displayName: 'Propagate Mode',
|
||||
name: 'propagateMode',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Change One',
|
||||
value: 'changeOne',
|
||||
},
|
||||
{
|
||||
name: 'Change Later',
|
||||
value: 'changeLater',
|
||||
},
|
||||
{
|
||||
name: 'Change All',
|
||||
value: 'changeAll',
|
||||
},
|
||||
],
|
||||
default: 'changeOne',
|
||||
description:
|
||||
'Which message(s) should be edited: just the one indicated in message_id, messages in the same topic that had been sent after this one, or all of them',
|
||||
},
|
||||
{
|
||||
displayName: 'Topic',
|
||||
name: 'topic',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The topic of the message. Only required for stream messages.',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the message',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Message ID',
|
||||
name: 'messageId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'Unique identifier for the message',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:updateFile */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Put Output File in Field',
|
||||
name: 'dataBinaryProperty',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: 'data',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['updateFile'],
|
||||
},
|
||||
},
|
||||
hint: 'The name of the output binary field to put the file in',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,7 @@
|
||||
export interface IMessage {
|
||||
type?: string;
|
||||
to?: string;
|
||||
topic?: string;
|
||||
content?: string;
|
||||
propagate_mode?: string;
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const streamOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a stream',
|
||||
action: 'Create a stream',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a stream',
|
||||
action: 'Delete a stream',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many streams',
|
||||
action: 'Get many streams',
|
||||
},
|
||||
{
|
||||
name: 'Get Subscribed',
|
||||
value: 'getSubscribed',
|
||||
description: 'Get subscribed streams',
|
||||
action: 'Get subscribed streams',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a stream',
|
||||
action: 'Update a stream',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const streamFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* stream:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
name: 'jsonParameters',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFieldsJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [true],
|
||||
},
|
||||
},
|
||||
description: 'JSON format parameters for stream creation',
|
||||
},
|
||||
{
|
||||
displayName: 'Subscriptions',
|
||||
name: 'subscriptions',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
description:
|
||||
'A list of dictionaries containing the the key name and value specifying the name of the stream to subscribe. If the stream does not exist a new stream is created.',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Subscription Properties',
|
||||
name: 'properties',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Name of Subscription',
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Description of Subscription',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['create'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Announce',
|
||||
name: 'announce',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
|
||||
description:
|
||||
'If announce is True and one of the streams specified in subscriptions has to be created (i.e. doesnt exist to begin with), an announcement will be made notifying that a new stream was created.',
|
||||
},
|
||||
{
|
||||
displayName: 'Authorization Errors Fatal',
|
||||
name: 'authorizationErrorsFatal',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether authorization errors (such as when the requesting user is not authorized to access a private stream) should be considered fatal or not. When True, an authorization error is reported as such. When set to False, the returned JSON payload indicates that there was an authorization error, but the response is still considered a successful one.',
|
||||
},
|
||||
{
|
||||
displayName: 'History Public to Subscribers',
|
||||
name: 'historyPublicToSubscribers',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether the streams message history should be available to newly subscribed members, or users can only access messages they actually received while subscribed to the stream',
|
||||
},
|
||||
{
|
||||
displayName: 'Invite Only',
|
||||
name: 'inviteOnly',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the streams specified in subscriptions are invite-only or not',
|
||||
},
|
||||
{
|
||||
displayName: 'Principals',
|
||||
name: 'principals',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
description:
|
||||
'A list of email addresses of the users that will be subscribed/unsubscribed to the streams specified in the subscriptions argument. If not provided, then the requesting user/bot is subscribed.',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Principals Properties',
|
||||
name: 'properties',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Principal Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'Principal email address',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Stream Post Policy',
|
||||
name: 'streamPostPolicy',
|
||||
type: 'options',
|
||||
default: '',
|
||||
description: 'Policy for which users can post messages to the stream',
|
||||
options: [
|
||||
{
|
||||
name: '1',
|
||||
value: 1,
|
||||
description: 'Any user can post',
|
||||
},
|
||||
{
|
||||
name: '2',
|
||||
value: 2,
|
||||
description: 'Only administrators can post',
|
||||
},
|
||||
{
|
||||
name: '3',
|
||||
value: 3,
|
||||
description: 'Only new members can post',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* stream:get all */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Include All Active',
|
||||
name: 'includeAllActive',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description:
|
||||
'Whether to include all active streams. The user must have administrative privileges to use this parameter.',
|
||||
},
|
||||
{
|
||||
displayName: 'Include Default',
|
||||
name: 'includeDefault',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'Whether to include all default streams for the users realm',
|
||||
},
|
||||
{
|
||||
displayName: 'Include Owner Subscribed',
|
||||
name: 'includeOwnersubscribed',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description:
|
||||
'Whether the user is a bot, include all streams that the bots owner is subscribed to',
|
||||
},
|
||||
{
|
||||
displayName: 'Include Public',
|
||||
name: 'includePublic',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'Whether to include all public streams',
|
||||
},
|
||||
{
|
||||
displayName: 'Include Subscribed',
|
||||
name: 'includeSubscribed',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'Whether to include all streams that the user is subscribed to',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* stream:get subscribed */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['getSubscribed'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Include Subscribers',
|
||||
name: 'includeSubscribers',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description:
|
||||
'Whether each returned stream object should include a subscribers field containing a list of the user IDs of its subscribers',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* stream:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Stream ID',
|
||||
name: 'streamId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
description: 'ID of stream to update',
|
||||
},
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
name: 'jsonParameters',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFieldsJson',
|
||||
type: 'json',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['update'],
|
||||
jsonParameters: [true],
|
||||
},
|
||||
},
|
||||
|
||||
description: 'JSON format parameters for stream creation',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['update'],
|
||||
jsonParameters: [false],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Announcement Only',
|
||||
name: 'isAnnouncementOnly',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the stream is limited to announcements',
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The new description for the stream',
|
||||
placeholder: 'Place of discussion',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Private',
|
||||
name: 'isPrivate',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the stream is a private stream',
|
||||
},
|
||||
{
|
||||
displayName: 'History Public to Subscribers',
|
||||
name: 'historyPublicToSubscribers',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether the streams message history should be available to newly subscribed members, or users can only access messages they actually received while subscribed to the stream',
|
||||
},
|
||||
{
|
||||
displayName: 'New Name',
|
||||
name: 'newName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The new name for the stream',
|
||||
placeholder: 'Italy',
|
||||
},
|
||||
{
|
||||
displayName: 'Stream Post Policy',
|
||||
name: 'streamPostPolicy',
|
||||
type: 'options',
|
||||
default: '',
|
||||
description: 'Policy for which users can post messages to the stream',
|
||||
options: [
|
||||
{
|
||||
name: '1',
|
||||
value: 1,
|
||||
description: 'Any user can post',
|
||||
},
|
||||
{
|
||||
name: '2',
|
||||
value: 2,
|
||||
description: 'Only administrators can post',
|
||||
},
|
||||
{
|
||||
name: '3',
|
||||
value: 3,
|
||||
description: 'Only new members can post',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* stream:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Stream ID',
|
||||
name: 'streamId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['stream'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'ID of stream to delete',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,23 @@
|
||||
export interface IStream {
|
||||
subscriptions?: string;
|
||||
invite_only?: boolean;
|
||||
principals?: string;
|
||||
authorization_errors_fatal?: boolean;
|
||||
history_public_to_subscribers?: boolean;
|
||||
stream_post_policy?: number;
|
||||
announce?: boolean;
|
||||
include_public?: boolean;
|
||||
include_subscribed?: boolean;
|
||||
include_all_active?: boolean;
|
||||
include_default?: boolean;
|
||||
include_owner_subscribed?: boolean;
|
||||
include_subscribers?: boolean;
|
||||
description?: string;
|
||||
new_name?: string;
|
||||
is_private?: boolean;
|
||||
is_announcement_only?: boolean;
|
||||
}
|
||||
|
||||
export interface IPrincipal {
|
||||
email: string;
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const userOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a user',
|
||||
action: 'Create a user',
|
||||
},
|
||||
{
|
||||
name: 'Deactivate',
|
||||
value: 'deactivate',
|
||||
description: 'Deactivate a user',
|
||||
action: 'Deactivate a user',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a user',
|
||||
action: 'Get a user',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many users',
|
||||
action: 'Get many users',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update a user',
|
||||
action: 'Update a user',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const userFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
placeholder: 'name@email.com',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The email address of the new user',
|
||||
},
|
||||
{
|
||||
displayName: 'Full Name',
|
||||
name: 'fullName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The full name of the new user',
|
||||
},
|
||||
{
|
||||
displayName: 'Password',
|
||||
name: 'password',
|
||||
type: 'string',
|
||||
typeOptions: { password: true },
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The password of the new user',
|
||||
},
|
||||
{
|
||||
displayName: 'Short Name',
|
||||
name: 'shortName',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The short name of the new user. Not user-visible.',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:get / getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The ID of user to get',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['get', 'getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Client Gravatar',
|
||||
name: 'clientGravatar',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether the client supports computing gravatars URLs. If enabled, avatar_url will be included in the response only if there is a Zulip avatar, and will be null for users who are using gravatar as their avatar.',
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Profile Fields',
|
||||
name: 'includeCustomProfileFields',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether the client wants custom profile field data to be included in the response',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The ID of user to update',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Full Name',
|
||||
name: 'fullName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The users full name',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Admin',
|
||||
name: 'isAdmin',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the target user is an administrator',
|
||||
},
|
||||
{
|
||||
displayName: 'Is Guest',
|
||||
name: 'isGuest',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the target user is a guest',
|
||||
},
|
||||
{
|
||||
displayName: 'Profile Data',
|
||||
name: 'profileData',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
description:
|
||||
'A dictionary containing the to be updated custom profile field data for the user',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'property',
|
||||
values: [
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
description: 'ID of custom profile data value',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Value of custom profile data',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Role',
|
||||
name: 'role',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Guest',
|
||||
value: 600,
|
||||
},
|
||||
{
|
||||
name: 'Member',
|
||||
value: 400,
|
||||
},
|
||||
{
|
||||
name: 'Organization Administrator',
|
||||
value: 200,
|
||||
},
|
||||
{
|
||||
name: 'Organization Moderator',
|
||||
value: 300,
|
||||
},
|
||||
{
|
||||
name: 'Organization Owner',
|
||||
value: 100,
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description: 'Role for the user',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:deactivate */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['deactivate'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The ID of user to deactivate',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { IDataObject } from 'n8n-workflow';
|
||||
|
||||
export interface IUser {
|
||||
client_gravatar?: boolean;
|
||||
include_custom_profile_fields?: boolean;
|
||||
full_name?: string;
|
||||
is_admin?: boolean;
|
||||
is_guest?: boolean;
|
||||
profile_data?: [IDataObject];
|
||||
email?: string;
|
||||
password?: string;
|
||||
short_name?: string;
|
||||
role?: number;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.zulip",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Communication"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/zulip/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.zulip/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,475 @@
|
||||
import { snakeCase } from 'change-case';
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { validateJSON, zulipApiRequest } from './GenericFunctions';
|
||||
import { messageFields, messageOperations } from './MessageDescription';
|
||||
import type { IMessage } from './MessageInterface';
|
||||
import { streamFields, streamOperations } from './StreamDescription';
|
||||
import type { IPrincipal, IStream } from './StreamInterface';
|
||||
import { userFields, userOperations } from './UserDescription';
|
||||
import type { IUser } from './UserInterface';
|
||||
|
||||
export class Zulip implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Zulip',
|
||||
name: 'zulip',
|
||||
icon: 'file:zulip.svg',
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Zulip API',
|
||||
defaults: {
|
||||
name: 'Zulip',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'zulipApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Message',
|
||||
value: 'message',
|
||||
},
|
||||
{
|
||||
name: 'Stream',
|
||||
value: 'stream',
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
value: 'user',
|
||||
},
|
||||
],
|
||||
default: 'message',
|
||||
},
|
||||
// MESSAGE
|
||||
...messageOperations,
|
||||
...messageFields,
|
||||
|
||||
// STREAM
|
||||
...streamOperations,
|
||||
...streamFields,
|
||||
|
||||
// USER
|
||||
...userOperations,
|
||||
...userFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
// Get all the available streams to display them to user so that they can
|
||||
// select them easily
|
||||
async getStreams(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const { streams } = await zulipApiRequest.call(this, 'GET', '/streams');
|
||||
for (const stream of streams) {
|
||||
const streamName = stream.name;
|
||||
const streamId = stream.stream_id;
|
||||
returnData.push({
|
||||
name: streamName,
|
||||
value: streamId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
// Get all the available topics to display them to user so that they can
|
||||
// select them easily
|
||||
async getTopics(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const streamId = this.getCurrentNodeParameter('stream') as string;
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const { topics } = await zulipApiRequest.call(this, 'GET', `/users/me/${streamId}/topics`);
|
||||
for (const topic of topics) {
|
||||
const topicName = topic.name;
|
||||
const topicId = topic.name;
|
||||
returnData.push({
|
||||
name: topicName,
|
||||
value: topicId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
// Get all the available users to display them to user so that they can
|
||||
// select them easily
|
||||
async getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const { members } = await zulipApiRequest.call(this, 'GET', '/users');
|
||||
for (const member of members) {
|
||||
const memberName = member.full_name;
|
||||
const memberId = member.email;
|
||||
returnData.push({
|
||||
name: memberName,
|
||||
value: memberId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
let responseData;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
for (let i = 0; i < length; i++) {
|
||||
try {
|
||||
if (resource === 'message') {
|
||||
//https://zulipchat.com/api/send-message
|
||||
if (operation === 'sendPrivate') {
|
||||
const to = (this.getNodeParameter('to', i) as string[]).join(',');
|
||||
const content = this.getNodeParameter('content', i) as string;
|
||||
const body: IMessage = {
|
||||
type: 'private',
|
||||
to,
|
||||
content,
|
||||
};
|
||||
responseData = await zulipApiRequest.call(this, 'POST', '/messages', body);
|
||||
}
|
||||
//https://zulipchat.com/api/send-message
|
||||
if (operation === 'sendStream') {
|
||||
const stream = this.getNodeParameter('stream', i) as string;
|
||||
const topic = this.getNodeParameter('topic', i) as string;
|
||||
const content = this.getNodeParameter('content', i) as string;
|
||||
const body: IMessage = {
|
||||
type: 'stream',
|
||||
to: stream,
|
||||
topic,
|
||||
content,
|
||||
};
|
||||
responseData = await zulipApiRequest.call(this, 'POST', '/messages', body);
|
||||
}
|
||||
//https://zulipchat.com/api/update-message
|
||||
if (operation === 'update') {
|
||||
const messageId = this.getNodeParameter('messageId', i) as string;
|
||||
const updateFields = this.getNodeParameter('updateFields', i);
|
||||
const body: IMessage = {};
|
||||
if (updateFields.content) {
|
||||
body.content = updateFields.content as string;
|
||||
}
|
||||
if (updateFields.propagateMode) {
|
||||
body.propagate_mode = snakeCase(updateFields.propagateMode as string);
|
||||
}
|
||||
if (updateFields.topic) {
|
||||
body.topic = updateFields.topic as string;
|
||||
}
|
||||
responseData = await zulipApiRequest.call(
|
||||
this,
|
||||
'PATCH',
|
||||
`/messages/${messageId}`,
|
||||
body,
|
||||
);
|
||||
}
|
||||
//https://zulipchat.com/api/get-raw-message
|
||||
if (operation === 'get') {
|
||||
const messageId = this.getNodeParameter('messageId', i) as string;
|
||||
responseData = await zulipApiRequest.call(this, 'GET', `/messages/${messageId}`);
|
||||
}
|
||||
//https://zulipchat.com/api/delete-message
|
||||
if (operation === 'delete') {
|
||||
const messageId = this.getNodeParameter('messageId', i) as string;
|
||||
responseData = await zulipApiRequest.call(this, 'DELETE', `/messages/${messageId}`);
|
||||
}
|
||||
//https://zulipchat.com/api/upload-file
|
||||
if (operation === 'updateFile') {
|
||||
const credentials = await this.getCredentials('zulipApi');
|
||||
const dataBinaryProperty = this.getNodeParameter('dataBinaryProperty', i);
|
||||
|
||||
const binaryData = this.helpers.assertBinaryData(i, dataBinaryProperty);
|
||||
const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, dataBinaryProperty);
|
||||
const formData = {
|
||||
file: {
|
||||
value: binaryDataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
contentType: binaryData.mimeType,
|
||||
},
|
||||
},
|
||||
};
|
||||
responseData = await zulipApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/user_uploads',
|
||||
{},
|
||||
{},
|
||||
undefined,
|
||||
{ formData },
|
||||
);
|
||||
responseData.uri = `${credentials.url}${responseData.uri}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'stream') {
|
||||
const body: IStream = {};
|
||||
|
||||
if (operation === 'getAll') {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.includePublic) {
|
||||
body.include_public = additionalFields.includePublic as boolean;
|
||||
}
|
||||
if (additionalFields.includeSubscribed) {
|
||||
body.include_subscribed = additionalFields.includeSubscribed as boolean;
|
||||
}
|
||||
if (additionalFields.includeAllActive) {
|
||||
body.include_all_active = additionalFields.includeAllActive as boolean;
|
||||
}
|
||||
if (additionalFields.includeDefault) {
|
||||
body.include_default = additionalFields.includeDefault as boolean;
|
||||
}
|
||||
if (additionalFields.includeOwnersubscribed) {
|
||||
body.include_owner_subscribed = additionalFields.includeOwnersubscribed as boolean;
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'GET', '/streams', body);
|
||||
responseData = responseData.streams;
|
||||
}
|
||||
|
||||
if (operation === 'getSubscribed') {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.includeSubscribers) {
|
||||
body.include_subscribers = additionalFields.includeSubscribers as boolean;
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'GET', '/users/me/subscriptions', body);
|
||||
responseData = responseData.subscriptions;
|
||||
}
|
||||
|
||||
if (operation === 'create') {
|
||||
const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
const subscriptions = this.getNodeParameter('subscriptions', i) as IDataObject;
|
||||
|
||||
body.subscriptions = JSON.stringify(subscriptions.properties);
|
||||
|
||||
if (jsonParameters) {
|
||||
const additionalFieldsJson = this.getNodeParameter(
|
||||
'additionalFieldsJson',
|
||||
i,
|
||||
) as string;
|
||||
|
||||
if (additionalFieldsJson !== '') {
|
||||
if (validateJSON(additionalFieldsJson) !== undefined) {
|
||||
Object.assign(body, JSON.parse(additionalFieldsJson));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Additional fields must be a valid JSON',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
body.subscriptions = JSON.stringify(subscriptions.properties);
|
||||
|
||||
if (additionalFields.inviteOnly) {
|
||||
body.invite_only = additionalFields.inviteOnly as boolean;
|
||||
}
|
||||
if (additionalFields.principals) {
|
||||
const principals: string[] = [];
|
||||
//@ts-ignore
|
||||
additionalFields.principals.properties.map((principal: IPrincipal) => {
|
||||
principals.push(principal.email);
|
||||
});
|
||||
body.principals = JSON.stringify(principals);
|
||||
}
|
||||
if (additionalFields.authorizationErrorsFatal) {
|
||||
body.authorization_errors_fatal =
|
||||
additionalFields.authorizationErrorsFatal as boolean;
|
||||
}
|
||||
if (additionalFields.historyPublicToSubscribers) {
|
||||
body.history_public_to_subscribers =
|
||||
additionalFields.historyPublicToSubscribers as boolean;
|
||||
}
|
||||
if (additionalFields.streamPostPolicy) {
|
||||
body.stream_post_policy = additionalFields.streamPostPolicy as number;
|
||||
}
|
||||
if (additionalFields.announce) {
|
||||
body.announce = additionalFields.announce as boolean;
|
||||
}
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/users/me/subscriptions',
|
||||
body,
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === 'delete') {
|
||||
const streamId = this.getNodeParameter('streamId', i) as string;
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'DELETE', `/streams/${streamId}`, {});
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
const streamId = this.getNodeParameter('streamId', i) as string;
|
||||
|
||||
const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
|
||||
if (jsonParameters) {
|
||||
const additionalFieldsJson = this.getNodeParameter(
|
||||
'additionalFieldsJson',
|
||||
i,
|
||||
) as string;
|
||||
|
||||
if (additionalFieldsJson !== '') {
|
||||
if (validateJSON(additionalFieldsJson) !== undefined) {
|
||||
Object.assign(body, JSON.parse(additionalFieldsJson));
|
||||
} else {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Additional fields must be a valid JSON',
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.description) {
|
||||
body.description = JSON.stringify(additionalFields.description as string);
|
||||
}
|
||||
if (additionalFields.newName) {
|
||||
body.new_name = JSON.stringify(additionalFields.newName as string);
|
||||
}
|
||||
if (additionalFields.isPrivate) {
|
||||
body.is_private = additionalFields.isPrivate as boolean;
|
||||
}
|
||||
if (additionalFields.isAnnouncementOnly) {
|
||||
body.is_announcement_only = additionalFields.isAnnouncementOnly as boolean;
|
||||
}
|
||||
if (additionalFields.streamPostPolicy) {
|
||||
body.stream_post_policy = additionalFields.streamPostPolicy as number;
|
||||
}
|
||||
if (additionalFields.historyPublicToSubscribers) {
|
||||
body.history_public_to_subscribers =
|
||||
additionalFields.historyPublicToSubscribers as boolean;
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(
|
||||
this,
|
||||
'PATCH',
|
||||
`/streams/${streamId}`,
|
||||
body,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'user') {
|
||||
const body: IUser = {};
|
||||
|
||||
if (operation === 'get') {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.clientGravatar) {
|
||||
body.client_gravatar = additionalFields.client_gravatar as boolean;
|
||||
}
|
||||
if (additionalFields.includeCustomProfileFields) {
|
||||
body.include_custom_profile_fields =
|
||||
additionalFields.includeCustomProfileFields as boolean;
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'GET', `/users/${userId}`, body);
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.clientGravatar) {
|
||||
body.client_gravatar = additionalFields.client_gravatar as boolean;
|
||||
}
|
||||
if (additionalFields.includeCustomProfileFields) {
|
||||
body.include_custom_profile_fields =
|
||||
additionalFields.includeCustomProfileFields as boolean;
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'GET', '/users', body);
|
||||
responseData = responseData.members;
|
||||
}
|
||||
|
||||
if (operation === 'create') {
|
||||
body.email = this.getNodeParameter('email', i) as string;
|
||||
body.password = this.getNodeParameter('password', i) as string;
|
||||
body.full_name = this.getNodeParameter('fullName', i) as string;
|
||||
body.short_name = this.getNodeParameter('shortName', i) as string;
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'POST', '/users', body);
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
|
||||
if (additionalFields.fullName) {
|
||||
body.full_name = JSON.stringify(additionalFields.fullName as string);
|
||||
}
|
||||
if (additionalFields.isAdmin) {
|
||||
body.is_admin = additionalFields.isAdmin as boolean;
|
||||
}
|
||||
if (additionalFields.isGuest) {
|
||||
body.is_guest = additionalFields.isGuest as boolean;
|
||||
}
|
||||
if (additionalFields.role) {
|
||||
body.role = additionalFields.role as number;
|
||||
}
|
||||
if (additionalFields.profileData) {
|
||||
//@ts-ignore
|
||||
body.profile_data = additionalFields.profileData.properties as [IDataObject];
|
||||
}
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'PATCH', `/users/${userId}`, body);
|
||||
}
|
||||
|
||||
if (operation === 'deactivate') {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
|
||||
responseData = await zulipApiRequest.call(this, 'DELETE', `/users/${userId}`, body);
|
||||
}
|
||||
}
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" preserveAspectRatio="xMidYMid"><defs><linearGradient id="a" x1="50%" x2="50%" y1="0%" y2="100%"><stop offset="0%" stop-color="#24ADFF"/><stop offset="100%" stop-color="#7B71FF"/></linearGradient></defs><path fill="url(#a)" d="M128 0c70.692 0 128 57.308 128 128s-57.308 128-128 128S0 198.692 0 128 57.308 0 128 0m-6.32 118.222-45.892 40.979c-4.728 3.72-7.83 9.86-7.83 16.766 0 11.279 8.274 20.508 18.386 20.508h86.247c10.112 0 18.386-9.23 18.386-20.508 0-11.28-8.274-20.507-18.386-20.507H107.3c-.968 0-1.58-1.16-1.108-2.104l16.833-33.703c.615-.983-.493-2.161-1.345-1.43zm50.91-58.86H86.345c-10.112 0-18.386 9.227-18.386 20.508 0 11.279 8.274 20.508 18.386 20.508h65.292c.968 0 1.58 1.16 1.108 2.103l-16.834 33.704c-.615.983.494 2.161 1.346 1.43l45.892-40.984c4.727-3.723 7.829-9.86 7.829-16.767 0-11.278-8.274-20.507-18.386-20.501z"/></svg>
|
||||
|
After Width: | Height: | Size: 904 B |
Reference in New Issue
Block a user