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,24 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const accountOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['account'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Me',
|
||||
value: 'me',
|
||||
description: "Get current user's account information",
|
||||
action: "Get the current user's account information",
|
||||
},
|
||||
],
|
||||
default: 'me',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const eventOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['event'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get single event by ID',
|
||||
action: 'Get an event by ID',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const eventFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* event:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room ID',
|
||||
name: 'roomId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: '!123abc:matrix.org',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['event'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
description: 'The room related to the event',
|
||||
},
|
||||
{
|
||||
displayName: 'Event ID',
|
||||
name: 'eventId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: '$1234abcd:matrix.org',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['get'],
|
||||
resource: ['event'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
description: 'The room related to the event',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,252 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHttpRequestMethods,
|
||||
ILoadOptionsFunctions,
|
||||
IRequestOptions,
|
||||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export async function matrixApiRequest(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: string | object = {},
|
||||
query: IDataObject = {},
|
||||
headers: IDataObject | undefined = undefined,
|
||||
option: IDataObject = {},
|
||||
) {
|
||||
let options: IRequestOptions = {
|
||||
method,
|
||||
headers: headers || {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body,
|
||||
qs: query,
|
||||
uri: '',
|
||||
json: true,
|
||||
};
|
||||
options = Object.assign({}, options, option);
|
||||
if (Object.keys(body).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
if (Object.keys(query).length === 0) {
|
||||
delete options.qs;
|
||||
}
|
||||
try {
|
||||
const credentials = await this.getCredentials('matrixApi');
|
||||
|
||||
options.uri = `${credentials.homeserverUrl}/_matrix/${
|
||||
option.overridePrefix || 'client'
|
||||
}/r0${resource}`;
|
||||
options.headers!.Authorization = `Bearer ${credentials.accessToken}`;
|
||||
const response = await this.helpers.request(options);
|
||||
|
||||
// When working with images, the request cannot be JSON (it's raw binary data)
|
||||
// But the output is JSON so we have to parse it manually.
|
||||
//@ts-ignore
|
||||
return options.overridePrefix === 'media' ? JSON.parse(response as string) : response;
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleMatrixCall(
|
||||
this: IExecuteFunctions,
|
||||
index: number,
|
||||
resource: string,
|
||||
operation: string,
|
||||
): Promise<any> {
|
||||
if (resource === 'account') {
|
||||
if (operation === 'me') {
|
||||
return await matrixApiRequest.call(this, 'GET', '/account/whoami');
|
||||
}
|
||||
} else if (resource === 'room') {
|
||||
if (operation === 'create') {
|
||||
const name = this.getNodeParameter('roomName', index) as string;
|
||||
const preset = this.getNodeParameter('preset', index) as string;
|
||||
const roomAlias = this.getNodeParameter('roomAlias', index) as string;
|
||||
const body: IDataObject = {
|
||||
name,
|
||||
preset,
|
||||
};
|
||||
if (roomAlias) {
|
||||
body.room_alias_name = roomAlias;
|
||||
}
|
||||
return await matrixApiRequest.call(this, 'POST', '/createRoom', body);
|
||||
} else if (operation === 'join') {
|
||||
const roomIdOrAlias = this.getNodeParameter('roomIdOrAlias', index) as string;
|
||||
return await matrixApiRequest.call(this, 'POST', `/rooms/${roomIdOrAlias}/join`);
|
||||
} else if (operation === 'leave') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
return await matrixApiRequest.call(this, 'POST', `/rooms/${roomId}/leave`);
|
||||
} else if (operation === 'invite') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const userId = this.getNodeParameter('userId', index) as string;
|
||||
const body: IDataObject = {
|
||||
user_id: userId,
|
||||
};
|
||||
return await matrixApiRequest.call(this, 'POST', `/rooms/${roomId}/invite`, body);
|
||||
} else if (operation === 'kick') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const userId = this.getNodeParameter('userId', index) as string;
|
||||
const reason = this.getNodeParameter('reason', index) as string;
|
||||
const body: IDataObject = {
|
||||
user_id: userId,
|
||||
reason,
|
||||
};
|
||||
return await matrixApiRequest.call(this, 'POST', `/rooms/${roomId}/kick`, body);
|
||||
}
|
||||
} else if (resource === 'message') {
|
||||
if (operation === 'create') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const text = this.getNodeParameter('text', index, '') as string;
|
||||
const messageType = this.getNodeParameter('messageType', index) as string;
|
||||
const messageFormat = this.getNodeParameter('messageFormat', index) as string;
|
||||
const body: IDataObject = {
|
||||
msgtype: messageType,
|
||||
body: text,
|
||||
};
|
||||
if (messageFormat === 'org.matrix.custom.html') {
|
||||
const fallbackText = this.getNodeParameter('fallbackText', index, '') as string;
|
||||
body.format = messageFormat;
|
||||
body.formatted_body = text;
|
||||
body.body = fallbackText;
|
||||
}
|
||||
const messageId = uuid();
|
||||
return await matrixApiRequest.call(
|
||||
this,
|
||||
'PUT',
|
||||
`/rooms/${roomId}/send/m.room.message/${messageId}`,
|
||||
body,
|
||||
);
|
||||
} else if (operation === 'getAll') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', index);
|
||||
const otherOptions = this.getNodeParameter('otherOptions', index) as IDataObject;
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
if (returnAll) {
|
||||
let responseData;
|
||||
let from;
|
||||
do {
|
||||
const qs: IDataObject = {
|
||||
dir: 'b', // Get latest messages first - doesn't return anything if we use f without a previous token.
|
||||
from,
|
||||
};
|
||||
|
||||
if (otherOptions.filter) {
|
||||
qs.filter = otherOptions.filter;
|
||||
}
|
||||
|
||||
responseData = await matrixApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/rooms/${roomId}/messages`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
returnData.push.apply(returnData, responseData.chunk as IDataObject[]);
|
||||
from = responseData.end;
|
||||
} while (responseData.chunk.length > 0);
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', index);
|
||||
const qs: IDataObject = {
|
||||
dir: 'b', // GetfallbackText latest messages first - doesn't return anything if we use f without a previous token.
|
||||
limit,
|
||||
};
|
||||
|
||||
if (otherOptions.filter) {
|
||||
qs.filter = otherOptions.filter;
|
||||
}
|
||||
|
||||
const responseData = await matrixApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/rooms/${roomId}/messages`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
returnData.push.apply(returnData, responseData.chunk as IDataObject[]);
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
} else if (resource === 'event') {
|
||||
if (operation === 'get') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const eventId = this.getNodeParameter('eventId', index) as string;
|
||||
return await matrixApiRequest.call(this, 'GET', `/rooms/${roomId}/event/${eventId}`);
|
||||
}
|
||||
} else if (resource === 'media') {
|
||||
if (operation === 'upload') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const mediaType = this.getNodeParameter('mediaType', index) as string;
|
||||
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', index);
|
||||
const additionalFields = this.getNodeParameter('additionalFields', index);
|
||||
|
||||
let body;
|
||||
const qs: IDataObject = {};
|
||||
const headers: IDataObject = {};
|
||||
|
||||
const { fileName, mimeType } = this.helpers.assertBinaryData(index, binaryPropertyName);
|
||||
body = await this.helpers.getBinaryDataBuffer(index, binaryPropertyName);
|
||||
|
||||
if (additionalFields.fileName) {
|
||||
qs.filename = additionalFields.fileName as string;
|
||||
} else {
|
||||
qs.filename = fileName;
|
||||
}
|
||||
|
||||
headers['Content-Type'] = mimeType;
|
||||
headers.accept = 'application/json,text/*;q=0.99';
|
||||
|
||||
const uploadRequestResult = await matrixApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/upload',
|
||||
body,
|
||||
qs,
|
||||
headers,
|
||||
{
|
||||
overridePrefix: 'media',
|
||||
json: false,
|
||||
},
|
||||
);
|
||||
|
||||
body = {
|
||||
msgtype: `m.${mediaType}`,
|
||||
body: qs.filename,
|
||||
url: uploadRequestResult.content_uri,
|
||||
};
|
||||
const messageId = uuid();
|
||||
return await matrixApiRequest.call(
|
||||
this,
|
||||
'PUT',
|
||||
`/rooms/${roomId}/send/m.room.message/${messageId}`,
|
||||
body,
|
||||
);
|
||||
}
|
||||
} else if (resource === 'roomMember') {
|
||||
if (operation === 'getAll') {
|
||||
const roomId = this.getNodeParameter('roomId', index) as string;
|
||||
const filters = this.getNodeParameter('filters', index);
|
||||
const qs: IDataObject = {
|
||||
membership: filters.membership ? filters.membership : '',
|
||||
not_membership: filters.notMembership ? filters.notMembership : '',
|
||||
};
|
||||
const roomMembersResponse = await matrixApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/rooms/${roomId}/members`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
return roomMembersResponse.chunk;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NodeOperationError(this.getNode(), 'Not implemented yet');
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.matrix",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Communication"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/matrix/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.matrix/"
|
||||
}
|
||||
],
|
||||
"generic": [
|
||||
{
|
||||
"label": "How to host virtual coffee breaks with n8n",
|
||||
"icon": "☕️",
|
||||
"url": "https://n8n.io/blog/how-to-host-virtual-coffee-breaks-with-n8n/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
|
||||
import { accountOperations } from './AccountDescription';
|
||||
import { eventFields, eventOperations } from './EventDescription';
|
||||
import { handleMatrixCall, matrixApiRequest } from './GenericFunctions';
|
||||
import { mediaFields, mediaOperations } from './MediaDescription';
|
||||
import { messageFields, messageOperations } from './MessageDescription';
|
||||
import { roomFields, roomOperations } from './RoomDescription';
|
||||
import { roomMemberFields, roomMemberOperations } from './RoomMemberDescription';
|
||||
|
||||
export class Matrix implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Matrix',
|
||||
name: 'matrix',
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
||||
icon: 'file:matrix.png',
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
description: 'Consume Matrix API',
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
defaults: {
|
||||
name: 'Matrix',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'matrixApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Account',
|
||||
value: 'account',
|
||||
},
|
||||
{
|
||||
name: 'Event',
|
||||
value: 'event',
|
||||
},
|
||||
{
|
||||
name: 'Media',
|
||||
value: 'media',
|
||||
},
|
||||
{
|
||||
name: 'Message',
|
||||
value: 'message',
|
||||
},
|
||||
{
|
||||
name: 'Room',
|
||||
value: 'room',
|
||||
},
|
||||
{
|
||||
name: 'Room Member',
|
||||
value: 'roomMember',
|
||||
},
|
||||
],
|
||||
default: 'message',
|
||||
},
|
||||
...accountOperations,
|
||||
...eventOperations,
|
||||
...eventFields,
|
||||
...mediaOperations,
|
||||
...mediaFields,
|
||||
...messageOperations,
|
||||
...messageFields,
|
||||
...roomOperations,
|
||||
...roomFields,
|
||||
...roomMemberOperations,
|
||||
...roomMemberFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
async getChannels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
|
||||
const joinedRoomsResponse = await matrixApiRequest.call(this, 'GET', '/joined_rooms');
|
||||
|
||||
await Promise.all(
|
||||
joinedRoomsResponse.joined_rooms.map(async (roomId: string) => {
|
||||
try {
|
||||
const roomNameResponse = await matrixApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/rooms/${roomId}/state/m.room.name`,
|
||||
);
|
||||
returnData.push({
|
||||
name: roomNameResponse.name,
|
||||
value: roomId,
|
||||
});
|
||||
} catch (error) {
|
||||
// TODO: Check, there is probably another way to get the name of this private-chats
|
||||
returnData.push({
|
||||
name: `Unknown: ${roomId}`,
|
||||
value: roomId,
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData() as IDataObject[];
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
const responseData = await handleMatrixCall.call(this, i, resource, operation);
|
||||
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,121 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const mediaOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['media'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Upload',
|
||||
value: 'upload',
|
||||
description: 'Send media to a chat room',
|
||||
action: 'Upload media to a chatroom',
|
||||
},
|
||||
],
|
||||
default: 'upload',
|
||||
},
|
||||
];
|
||||
|
||||
export const mediaFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* media:upload */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['media'],
|
||||
operation: ['upload'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Room ID to post. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Input Binary Field',
|
||||
name: 'binaryPropertyName',
|
||||
type: 'string',
|
||||
default: 'data',
|
||||
required: true,
|
||||
hint: 'The name of the input binary field containing the file to be uploaded',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['media'],
|
||||
operation: ['upload'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Media Type',
|
||||
name: 'mediaType',
|
||||
type: 'options',
|
||||
default: 'image',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['media'],
|
||||
operation: ['upload'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'File',
|
||||
value: 'file',
|
||||
description: 'General file',
|
||||
},
|
||||
{
|
||||
name: 'Image',
|
||||
value: 'image',
|
||||
description: 'Image media type',
|
||||
},
|
||||
{
|
||||
name: 'Audio',
|
||||
value: 'audio',
|
||||
description: 'Audio media type',
|
||||
},
|
||||
{
|
||||
name: 'Video',
|
||||
value: 'video',
|
||||
description: 'Video media type',
|
||||
},
|
||||
],
|
||||
description: 'Type of file being uploaded',
|
||||
placeholder: 'mxc://matrix.org/uploaded-media-uri',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['media'],
|
||||
operation: ['upload'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'File Name',
|
||||
name: 'fileName',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Name of the file being uploaded',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,217 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const messageOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Send a message to a room',
|
||||
action: 'Create a message',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many messages from a room',
|
||||
action: 'Get many messages',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const messageFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
default: '',
|
||||
placeholder: '!123abc:matrix.org',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['message'],
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
description:
|
||||
'The channel to send the message to. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: 'Hello from n8n!',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['message'],
|
||||
},
|
||||
},
|
||||
description: 'The text to send',
|
||||
},
|
||||
{
|
||||
displayName: 'Message Type',
|
||||
name: 'messageType',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['message'],
|
||||
},
|
||||
},
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Emote',
|
||||
value: 'm.emote',
|
||||
description: 'Perform an action (similar to /me in IRC)',
|
||||
},
|
||||
{
|
||||
name: 'Notice',
|
||||
value: 'm.notice',
|
||||
description: 'Send a notice',
|
||||
},
|
||||
{
|
||||
name: 'Text',
|
||||
value: 'm.text',
|
||||
description: 'Send a text message',
|
||||
},
|
||||
],
|
||||
default: 'm.text',
|
||||
description: 'The type of message to send',
|
||||
},
|
||||
{
|
||||
displayName: 'Message Format',
|
||||
name: 'messageFormat',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['create'],
|
||||
resource: ['message'],
|
||||
},
|
||||
},
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Plain Text',
|
||||
value: 'plain',
|
||||
description: 'Text only',
|
||||
},
|
||||
{
|
||||
name: 'HTML',
|
||||
value: 'org.matrix.custom.html',
|
||||
description: 'HTML-formatted text',
|
||||
},
|
||||
],
|
||||
default: 'plain',
|
||||
description: "The format of the message's body",
|
||||
},
|
||||
{
|
||||
displayName: 'Fallback Text',
|
||||
name: 'fallbackText',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['create'],
|
||||
messageFormat: ['org.matrix.custom.html'],
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
description:
|
||||
'A plain text message to display in case the HTML cannot be rendered by the Matrix client',
|
||||
},
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* message:getAll */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
default: '',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The token to start returning events from. This token can be obtained from a prev_batch token returned for each room by the sync API. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 500,
|
||||
},
|
||||
default: 100,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Other Options',
|
||||
name: 'otherOptions',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add option',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filter',
|
||||
name: 'filter',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'A JSON RoomEventFilter to filter returned events with. More information can be found on this <a href="https://matrix.org/docs/spec/client_server/r0.6.0">page</a>.',
|
||||
placeholder: '{"contains_url":true,"types":["m.room.message", "m.sticker"]}',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,234 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const roomOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'New chat room with defined settings',
|
||||
action: 'Create a room',
|
||||
},
|
||||
{
|
||||
name: 'Invite',
|
||||
value: 'invite',
|
||||
description: 'Invite a user to a room',
|
||||
action: 'Invite a room',
|
||||
},
|
||||
{
|
||||
name: 'Join',
|
||||
value: 'join',
|
||||
description: 'Join a new room',
|
||||
action: 'Join a room',
|
||||
},
|
||||
{
|
||||
name: 'Kick',
|
||||
value: 'kick',
|
||||
description: 'Kick a user from a room',
|
||||
action: 'Kick a user from a room',
|
||||
},
|
||||
{
|
||||
name: 'Leave',
|
||||
value: 'leave',
|
||||
description: 'Leave a room',
|
||||
action: 'Leave a room',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const roomFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* room:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name',
|
||||
name: 'roomName',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'My new room',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Preset',
|
||||
name: 'preset',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Private Chat',
|
||||
value: 'private_chat',
|
||||
},
|
||||
{
|
||||
name: 'Public Chat',
|
||||
value: 'public_chat',
|
||||
description: 'Open and public chat',
|
||||
},
|
||||
],
|
||||
default: 'public_chat',
|
||||
placeholder: 'My new room',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Room Alias',
|
||||
name: 'roomAlias',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'coolest-room-around',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* room:join */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
{
|
||||
displayName: 'Room ID or Alias',
|
||||
name: 'roomIdOrAlias',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['join'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* room:leave */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['leave'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* room:invite */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['invite'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['invite'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The fully qualified user ID of the invitee',
|
||||
placeholder: '@cheeky_monkey:matrix.org',
|
||||
required: true,
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* room:kick */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['kick'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['kick'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The fully qualified user ID',
|
||||
placeholder: '@cheeky_monkey:matrix.org',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Reason',
|
||||
name: 'reason',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['room'],
|
||||
operation: ['kick'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Reason for kick',
|
||||
placeholder: 'Telling unfunny jokes',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,134 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const roomMemberOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['roomMember'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many members',
|
||||
action: 'Get many room members',
|
||||
},
|
||||
],
|
||||
default: 'getAll',
|
||||
},
|
||||
];
|
||||
|
||||
export const roomMemberFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* roomMember:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Room Name or ID',
|
||||
name: 'roomId',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getChannels',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['roomMember'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['roomMember'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
description: 'Filtering options',
|
||||
placeholder: 'Add filter',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Exclude Membership',
|
||||
name: 'notMembership',
|
||||
type: 'options',
|
||||
default: '',
|
||||
description:
|
||||
'Excludes members whose membership is other than selected (uses OR filter with membership)',
|
||||
options: [
|
||||
{
|
||||
name: 'Any',
|
||||
value: '',
|
||||
description: 'Any user membership',
|
||||
},
|
||||
{
|
||||
name: 'Ban',
|
||||
value: 'ban',
|
||||
description: 'Users removed from the room',
|
||||
},
|
||||
{
|
||||
name: 'Invite',
|
||||
value: 'invite',
|
||||
description: 'Users invited to join',
|
||||
},
|
||||
{
|
||||
name: 'Join',
|
||||
value: 'join',
|
||||
description: 'Users currently in the room',
|
||||
},
|
||||
{
|
||||
name: 'Leave',
|
||||
value: 'leave',
|
||||
description: 'Users who left',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Membership',
|
||||
name: 'membership',
|
||||
type: 'options',
|
||||
default: '',
|
||||
description:
|
||||
'Only fetch users with selected membership status (uses OR filter with exclude membership)',
|
||||
options: [
|
||||
{
|
||||
name: 'Any',
|
||||
value: '',
|
||||
description: 'Any user membership',
|
||||
},
|
||||
{
|
||||
name: 'Ban',
|
||||
value: 'ban',
|
||||
description: 'Users removed from the room',
|
||||
},
|
||||
{
|
||||
name: 'Invite',
|
||||
value: 'invite',
|
||||
description: 'Users invited to join',
|
||||
},
|
||||
{
|
||||
name: 'Join',
|
||||
value: 'join',
|
||||
description: 'Users currently in the room',
|
||||
},
|
||||
{
|
||||
name: 'Leave',
|
||||
value: 'leave',
|
||||
description: 'Users who left',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"event_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"body": {
|
||||
"type": "string"
|
||||
},
|
||||
"msgtype": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"origin_server_ts": {
|
||||
"type": "integer"
|
||||
},
|
||||
"room_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"unsigned": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"membership": {
|
||||
"type": "string"
|
||||
},
|
||||
"transaction_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 4
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"avatar_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayname": {
|
||||
"type": "string"
|
||||
},
|
||||
"membership": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"origin_server_ts": {
|
||||
"type": "integer"
|
||||
},
|
||||
"replaces_state": {
|
||||
"type": "string"
|
||||
},
|
||||
"room_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sender": {
|
||||
"type": "string"
|
||||
},
|
||||
"state_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"unsigned": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"replaces_state": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 430 B |
Reference in New Issue
Block a user