mirror of
https://github.com/aljazceru/n8n-nodes-signal-cli.git
synced 2025-12-17 06:14:20 +01:00
568 lines
13 KiB
TypeScript
568 lines
13 KiB
TypeScript
import {
|
|
IExecuteFunctions,
|
|
INodeExecutionData,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
NodeOperationError,
|
|
NodeConnectionType,
|
|
} from 'n8n-workflow';
|
|
import axios from 'axios';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
import Debug from 'debug';
|
|
|
|
const debug = Debug('n8n:signal');
|
|
|
|
export class Signal implements INodeType {
|
|
description: INodeTypeDescription = {
|
|
displayName: 'Signal',
|
|
name: 'signal',
|
|
group: ['output'],
|
|
version: 1,
|
|
description: 'Interact with Signal CLI API',
|
|
defaults: {
|
|
name: 'Signal',
|
|
},
|
|
inputs: [NodeConnectionType.Main],
|
|
outputs: [NodeConnectionType.Main],
|
|
credentials: [
|
|
{
|
|
name: 'signalCliApi',
|
|
required: true,
|
|
},
|
|
],
|
|
properties: [
|
|
{
|
|
displayName: 'Resource',
|
|
name: 'resource',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
options: [
|
|
{
|
|
name: 'Contact',
|
|
value: 'contact',
|
|
},
|
|
{
|
|
name: 'Group',
|
|
value: 'group',
|
|
},
|
|
{
|
|
name: 'Message',
|
|
value: 'message',
|
|
},
|
|
{
|
|
name: 'Reaction',
|
|
value: 'reaction',
|
|
},
|
|
{
|
|
name: 'Receipt',
|
|
value: 'receipt',
|
|
},
|
|
],
|
|
default: 'message',
|
|
},
|
|
// Message properties
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['message'],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Send',
|
|
value: 'send',
|
|
action: 'Send a message',
|
|
},
|
|
],
|
|
default: 'send',
|
|
},
|
|
{
|
|
displayName: 'Account',
|
|
name: 'account',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['message'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Recipient',
|
|
name: 'recipient',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'Phone number or group ID of the recipient',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['message'],
|
|
operation: ['send'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Message',
|
|
name: 'message',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'The message to be sent',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['message'],
|
|
operation: ['send'],
|
|
},
|
|
},
|
|
},
|
|
// Group properties
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['group'],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Create',
|
|
value: 'create',
|
|
action: 'Create a group',
|
|
},
|
|
{
|
|
name: 'List',
|
|
value: 'list',
|
|
action: 'List a group',
|
|
},
|
|
],
|
|
default: 'create',
|
|
},
|
|
{
|
|
displayName: 'Account',
|
|
name: 'account',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['group'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Name',
|
|
name: 'name',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'The name of the group',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['group'],
|
|
operation: ['create'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Members',
|
|
name: 'members',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'Comma-separated list of members to add to the group',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['group'],
|
|
operation: ['create'],
|
|
},
|
|
},
|
|
},
|
|
// Contact properties
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['contact'],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Update',
|
|
value: 'update',
|
|
action: 'Update a contact',
|
|
},
|
|
{
|
|
name: 'List',
|
|
value: 'list',
|
|
action: 'List a contact',
|
|
},
|
|
],
|
|
default: 'update',
|
|
},
|
|
{
|
|
displayName: 'Account',
|
|
name: 'account',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['contact'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Recipient',
|
|
name: 'recipient',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'Phone number of the contact',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['contact'],
|
|
operation: ['update'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Name',
|
|
name: 'name',
|
|
type: 'string',
|
|
default: '',
|
|
description: 'The name of the contact',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['contact'],
|
|
operation: ['update'],
|
|
},
|
|
},
|
|
},
|
|
// Reaction properties
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['reaction'],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Send',
|
|
value: 'send',
|
|
action: 'Send a reaction',
|
|
},
|
|
{
|
|
name: 'Remove',
|
|
value: 'remove',
|
|
action: 'Remove a reaction',
|
|
},
|
|
],
|
|
default: 'send',
|
|
},
|
|
{
|
|
displayName: 'Account',
|
|
name: 'account',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['reaction'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Recipient',
|
|
name: 'recipient',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'Phone number or group ID of the recipient',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['reaction'],
|
|
operation: ['send', 'remove'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Reaction',
|
|
name: 'reaction',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'The reaction to be sent',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['reaction'],
|
|
operation: ['send', 'remove'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Target Author',
|
|
name: 'targetAuthor',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'The author of the message being reacted to',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['reaction'],
|
|
operation: ['send', 'remove'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Timestamp',
|
|
name: 'timestamp',
|
|
type: 'number',
|
|
default: 0,
|
|
required: true,
|
|
description: 'The timestamp of the message being reacted to',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['reaction'],
|
|
operation: ['send', 'remove'],
|
|
},
|
|
},
|
|
},
|
|
// Receipt properties
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
noDataExpression: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['receipt'],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Send',
|
|
value: 'send',
|
|
action: 'Send a receipt',
|
|
},
|
|
],
|
|
default: 'send',
|
|
},
|
|
{
|
|
displayName: 'Account',
|
|
name: 'account',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['receipt'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Recipient',
|
|
name: 'recipient',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
description: 'Phone number or group ID of the recipient',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['receipt'],
|
|
operation: ['send'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Receipt Type',
|
|
name: 'receiptType',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'Read',
|
|
value: 'read',
|
|
},
|
|
{
|
|
name: 'Viewed',
|
|
value: 'viewed',
|
|
},
|
|
],
|
|
default: 'read',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['receipt'],
|
|
operation: ['send'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Timestamp',
|
|
name: 'timestamp',
|
|
type: 'number',
|
|
default: 0,
|
|
required: true,
|
|
description: 'The timestamp of the message being receipted',
|
|
displayOptions: {
|
|
show: {
|
|
resource: ['receipt'],
|
|
operation: ['send'],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
const resource = this.getNodeParameter('resource', 0) as string;
|
|
const operation = this.getNodeParameter('operation', 0) as string;
|
|
const credentials = await this.getCredentials('signalCliApi');
|
|
|
|
if (!credentials.url) {
|
|
throw new NodeOperationError(this.getNode(), 'Signal CLI API URL is not set in credentials');
|
|
}
|
|
|
|
const url = `${credentials.url}/api/v1/rpc`;
|
|
|
|
try {
|
|
let response;
|
|
debug('Signal Node: Executing with resource=%s, operation=%s', resource, operation);
|
|
if (resource === 'message' && operation === 'send') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
const recipient = this.getNodeParameter('recipient', 0) as string;
|
|
const message = this.getNodeParameter('message', 0) as string;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'send',
|
|
params: { account, recipient, message },
|
|
id: uuidv4(),
|
|
};
|
|
debug('Signal Node: Sending message with requestBody=%o', requestBody);
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'group' && operation === 'create') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
const name = this.getNodeParameter('name', 0) as string;
|
|
const members = (this.getNodeParameter('members', 0) as string).split(',');
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'updateGroup',
|
|
params: {
|
|
account,
|
|
name,
|
|
members,
|
|
},
|
|
id: uuidv4(),
|
|
};
|
|
debug('Signal Node: Creating group with requestBody=%o', requestBody);
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'group' && operation === 'list') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'listGroups',
|
|
params: { account },
|
|
id: uuidv4(),
|
|
};
|
|
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'contact' && operation === 'update') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
const recipient = this.getNodeParameter('recipient', 0) as string;
|
|
const name = this.getNodeParameter('name', 0) as string;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'updateContact',
|
|
params: { account, recipient, name },
|
|
id: uuidv4(),
|
|
};
|
|
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'contact' && operation === 'list') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'listContacts',
|
|
params: { account },
|
|
id: uuidv4(),
|
|
};
|
|
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'reaction' && operation === 'send') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
const recipient = this.getNodeParameter('recipient', 0) as string;
|
|
const reaction = this.getNodeParameter('reaction', 0) as string;
|
|
const targetAuthor = this.getNodeParameter('targetAuthor', 0) as string;
|
|
const timestamp = this.getNodeParameter('timestamp', 0) as number;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'sendReaction',
|
|
params: { account, recipient, reaction, targetAuthor, timestamp },
|
|
id: uuidv4(),
|
|
};
|
|
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'reaction' && operation === 'remove') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
const recipient = this.getNodeParameter('recipient', 0) as string;
|
|
const reaction = this.getNodeParameter('reaction', 0) as string;
|
|
const targetAuthor = this.getNodeParameter('targetAuthor', 0) as string;
|
|
const timestamp = this.getNodeParameter('timestamp', 0) as number;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'sendReaction',
|
|
params: { account, recipient, reaction, targetAuthor, timestamp, remove: true },
|
|
id: uuidv4(),
|
|
};
|
|
|
|
response = await axios.post(`${url}`, requestBody);
|
|
} else if (resource === 'receipt' && operation === 'send') {
|
|
const account = this.getNodeParameter('account', 0) as string;
|
|
const recipient = this.getNodeParameter('recipient', 0) as string;
|
|
const receiptType = this.getNodeParameter('receiptType', 0) as string;
|
|
const timestamp = this.getNodeParameter('timestamp', 0) as number;
|
|
|
|
const requestBody = {
|
|
jsonrpc: '2.0',
|
|
method: 'sendReceipt',
|
|
params: { account, recipient, receiptType, timestamp },
|
|
id: uuidv4(),
|
|
};
|
|
|
|
response = await axios.post(`${url}`, requestBody);
|
|
}
|
|
|
|
debug('Signal Node: Response', response?.data);
|
|
const item: INodeExecutionData = {
|
|
json: response?.data,
|
|
};
|
|
return [[item]];
|
|
} catch (error) {
|
|
throw new NodeOperationError(this.getNode(), 'Error interacting with Signal API', {
|
|
itemIndex: 0,
|
|
});
|
|
}
|
|
}
|
|
}
|