n8n-nodes-signal-cli-rest-api 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -5,6 +5,7 @@ const n8n_workflow_1 = require("n8n-workflow");
|
|
|
5
5
|
const messages_1 = require("./messages");
|
|
6
6
|
const groups_1 = require("./groups");
|
|
7
7
|
const contacts_1 = require("./contacts");
|
|
8
|
+
const attachments_1 = require("./attachments");
|
|
8
9
|
class Signal {
|
|
9
10
|
constructor() {
|
|
10
11
|
this.description = {
|
|
@@ -57,6 +58,24 @@ class Signal {
|
|
|
57
58
|
description: 'Remove a reaction from a message',
|
|
58
59
|
action: 'Remove a reaction',
|
|
59
60
|
},
|
|
61
|
+
{
|
|
62
|
+
name: 'Attachments: List Attachments',
|
|
63
|
+
value: 'listAttachments',
|
|
64
|
+
description: 'List attachments for the account',
|
|
65
|
+
action: 'List attachments',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'Attachments: Download Attachment',
|
|
69
|
+
value: 'downloadAttachment',
|
|
70
|
+
description: 'Download an attachment as binary file',
|
|
71
|
+
action: 'Download attachment',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'Attachments: Remove Attachment',
|
|
75
|
+
value: 'removeAttachment',
|
|
76
|
+
description: 'Remove an attachment',
|
|
77
|
+
action: 'Remove attachment',
|
|
78
|
+
},
|
|
60
79
|
{
|
|
61
80
|
name: 'Contacts: Get Contacts',
|
|
62
81
|
value: 'getContacts',
|
|
@@ -175,46 +194,16 @@ class Signal {
|
|
|
175
194
|
allowCustom: true,
|
|
176
195
|
},
|
|
177
196
|
options: [
|
|
178
|
-
{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
|
|
188
|
-
value: '😄',
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
name: 'Sad',
|
|
192
|
-
value: '😢',
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
name: 'Angry',
|
|
196
|
-
value: '😣',
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
name: 'Star',
|
|
200
|
-
value: '⭐',
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
name: 'Fire',
|
|
204
|
-
value: '🔥',
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
name: 'Plus',
|
|
208
|
-
value: '➕',
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
name: 'Minus',
|
|
212
|
-
value: '➖',
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
name: 'Handshake',
|
|
216
|
-
value: '🤝',
|
|
217
|
-
},
|
|
197
|
+
{ name: 'Thumbs Up', value: '👍' },
|
|
198
|
+
{ name: 'Heart', value: '❤️' },
|
|
199
|
+
{ name: 'Smile', value: '😄' },
|
|
200
|
+
{ name: 'Sad', value: '😢' },
|
|
201
|
+
{ name: 'Angry', value: '😣' },
|
|
202
|
+
{ name: 'Star', value: '⭐' },
|
|
203
|
+
{ name: 'Fire', value: '🔥' },
|
|
204
|
+
{ name: 'Plus', value: '➕' },
|
|
205
|
+
{ name: 'Minus', value: '➖' },
|
|
206
|
+
{ name: 'Handshake', value: '🤝' },
|
|
218
207
|
],
|
|
219
208
|
displayOptions: {
|
|
220
209
|
show: {
|
|
@@ -249,6 +238,20 @@ class Signal {
|
|
|
249
238
|
},
|
|
250
239
|
},
|
|
251
240
|
},
|
|
241
|
+
{
|
|
242
|
+
displayName: 'Attachment ID',
|
|
243
|
+
name: 'attachmentId',
|
|
244
|
+
type: 'string',
|
|
245
|
+
default: '',
|
|
246
|
+
placeholder: 'attachment_id_from_trigger.png',
|
|
247
|
+
description: 'ID of the attachment to download or remove',
|
|
248
|
+
required: true,
|
|
249
|
+
displayOptions: {
|
|
250
|
+
show: {
|
|
251
|
+
operation: ['downloadAttachment', 'removeAttachment'],
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
},
|
|
252
255
|
{
|
|
253
256
|
displayName: 'Timeout (seconds)',
|
|
254
257
|
name: 'timeout',
|
|
@@ -257,7 +260,7 @@ class Signal {
|
|
|
257
260
|
description: 'Request timeout in seconds (set higher for Get Groups, e.g., 300)',
|
|
258
261
|
displayOptions: {
|
|
259
262
|
show: {
|
|
260
|
-
operation: ['sendMessage', 'sendAttachment', 'sendReaction', 'removeReaction', 'getContacts', 'getGroups', 'createGroup', 'updateGroup'],
|
|
263
|
+
operation: ['sendMessage', 'sendAttachment', 'sendReaction', 'removeReaction', 'getContacts', 'getGroups', 'createGroup', 'updateGroup', 'listAttachments', 'downloadAttachment', 'removeAttachment'],
|
|
261
264
|
},
|
|
262
265
|
},
|
|
263
266
|
typeOptions: {
|
|
@@ -277,7 +280,7 @@ class Signal {
|
|
|
277
280
|
const apiUrl = credentials.apiUrl;
|
|
278
281
|
const apiToken = credentials.apiToken;
|
|
279
282
|
const phoneNumber = credentials.phoneNumber;
|
|
280
|
-
this.logger.debug(`Signal: Starting execute for operation ${operation},
|
|
283
|
+
this.logger.debug(`Signal: Starting execute for operation ${operation}, items length: ${items.length}`);
|
|
281
284
|
for (let i = 0; i < items.length; i++) {
|
|
282
285
|
const timeout = this.getNodeParameter('timeout', i, operation === 'getGroups' ? 300 : 60) * 1000;
|
|
283
286
|
const params = {
|
|
@@ -290,6 +293,7 @@ class Signal {
|
|
|
290
293
|
emoji: this.getNodeParameter('emoji', i, ''),
|
|
291
294
|
targetAuthor: this.getNodeParameter('targetAuthor', i, ''),
|
|
292
295
|
targetSentTimestamp: this.getNodeParameter('targetSentTimestamp', i, 0),
|
|
296
|
+
attachmentId: this.getNodeParameter('attachmentId', i, ''),
|
|
293
297
|
timeout,
|
|
294
298
|
apiUrl,
|
|
295
299
|
apiToken,
|
|
@@ -300,6 +304,9 @@ class Signal {
|
|
|
300
304
|
if (['sendMessage', 'sendAttachment', 'sendReaction', 'removeReaction'].includes(operation)) {
|
|
301
305
|
result = await messages_1.executeMessagesOperation.call(this, operation, i, params);
|
|
302
306
|
}
|
|
307
|
+
else if (['listAttachments', 'downloadAttachment', 'removeAttachment'].includes(operation)) {
|
|
308
|
+
result = await attachments_1.executeAttachmentsOperation.call(this, operation, i, params);
|
|
309
|
+
}
|
|
303
310
|
else if (['getGroups', 'createGroup', 'updateGroup'].includes(operation)) {
|
|
304
311
|
result = await groups_1.executeGroupsOperation.call(this, operation, i, params);
|
|
305
312
|
}
|
|
@@ -309,7 +316,7 @@ class Signal {
|
|
|
309
316
|
else {
|
|
310
317
|
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Unknown operation' });
|
|
311
318
|
}
|
|
312
|
-
this.logger.info(`Signal: Operation ${operation} result for item ${i}: ${JSON.stringify(result.json, null, 2)}`);
|
|
319
|
+
this.logger.info(`Signal: Operation ${operation} result for item ${i}: ${JSON.stringify(result.json || result.binary, null, 2)}`);
|
|
313
320
|
returnData.push(result);
|
|
314
321
|
}
|
|
315
322
|
catch (error) {
|
|
@@ -35,25 +35,25 @@ class SignalTrigger {
|
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
|
-
displayName: '
|
|
39
|
-
name: '
|
|
38
|
+
displayName: 'Ignore Messages',
|
|
39
|
+
name: 'ignoreMessages',
|
|
40
40
|
type: 'boolean',
|
|
41
|
-
default:
|
|
42
|
-
description: '
|
|
41
|
+
default: false,
|
|
42
|
+
description: 'Enable to ignore messages with text content',
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
|
-
displayName: '
|
|
46
|
-
name: '
|
|
45
|
+
displayName: 'Ignore Attachments',
|
|
46
|
+
name: 'ignoreAttachments',
|
|
47
47
|
type: 'boolean',
|
|
48
48
|
default: false,
|
|
49
|
-
description: '
|
|
49
|
+
description: 'Enable to ignore messages with attachments',
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
|
-
displayName: '
|
|
53
|
-
name: '
|
|
52
|
+
displayName: 'Ignore Reactions',
|
|
53
|
+
name: 'ignoreReactions',
|
|
54
54
|
type: 'boolean',
|
|
55
55
|
default: false,
|
|
56
|
-
description: '
|
|
56
|
+
description: 'Enable to ignore messages with reactions',
|
|
57
57
|
},
|
|
58
58
|
],
|
|
59
59
|
};
|
|
@@ -64,21 +64,25 @@ class SignalTrigger {
|
|
|
64
64
|
const apiToken = credentials.apiToken;
|
|
65
65
|
const phoneNumber = credentials.phoneNumber;
|
|
66
66
|
const reconnectDelay = this.getNodeParameter('reconnectDelay', 0) * 1000;
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
67
|
+
const ignoreMessages = this.getNodeParameter('ignoreMessages', 0);
|
|
68
|
+
const ignoreAttachments = this.getNodeParameter('ignoreAttachments', 0);
|
|
69
|
+
const ignoreReactions = this.getNodeParameter('ignoreReactions', 0);
|
|
70
70
|
const wsUrl = `${apiUrl.replace('http', 'ws')}/v1/receive/${phoneNumber}`;
|
|
71
|
+
this.logger.debug(`SignalTrigger: Attempting to connect to WS URL: ${wsUrl}`);
|
|
71
72
|
const processedMessages = new Set();
|
|
72
73
|
const maxMessages = 1000;
|
|
73
74
|
const connectWebSocket = () => {
|
|
74
75
|
const ws = new ws_1.WebSocket(wsUrl, {
|
|
75
76
|
headers: apiToken ? { Authorization: `Bearer ${apiToken}` } : {},
|
|
76
77
|
});
|
|
78
|
+
ws.on('open', () => {
|
|
79
|
+
this.logger.debug(`SignalTrigger: Successfully connected to ${wsUrl}`);
|
|
80
|
+
});
|
|
77
81
|
ws.on('message', (data) => {
|
|
78
82
|
var _a, _b, _c, _d, _e;
|
|
79
83
|
try {
|
|
80
84
|
const message = JSON.parse(data.toString());
|
|
81
|
-
this.logger.debug(`SignalTrigger: Received message: ${JSON.stringify(message, null, 2)}`);
|
|
85
|
+
this.logger.debug(`SignalTrigger: Received raw message: ${JSON.stringify(message, null, 2)}`);
|
|
82
86
|
const timestamp = ((_a = message.envelope) === null || _a === void 0 ? void 0 : _a.timestamp) || 0;
|
|
83
87
|
if (processedMessages.has(timestamp)) {
|
|
84
88
|
this.logger.debug(`SignalTrigger: Skipping duplicate message with timestamp ${timestamp}`);
|
|
@@ -97,6 +101,7 @@ class SignalTrigger {
|
|
|
97
101
|
timestamp: timestamp,
|
|
98
102
|
account: message.account || '',
|
|
99
103
|
};
|
|
104
|
+
this.logger.debug(`SignalTrigger: Processed message content: ${JSON.stringify(processedMessage, null, 2)}`);
|
|
100
105
|
// Ігнорувати події без вмісту
|
|
101
106
|
if (!processedMessage.messageText &&
|
|
102
107
|
processedMessage.attachments.length === 0 &&
|
|
@@ -104,11 +109,11 @@ class SignalTrigger {
|
|
|
104
109
|
this.logger.debug(`SignalTrigger: Skipping empty message with timestamp ${timestamp}`);
|
|
105
110
|
return;
|
|
106
111
|
}
|
|
107
|
-
//
|
|
108
|
-
if ((
|
|
109
|
-
(
|
|
110
|
-
(
|
|
111
|
-
this.logger.debug(`SignalTrigger:
|
|
112
|
+
// Фільтрація: ігнорувати, якщо увімкнено ignore і відповідний вміст присутній
|
|
113
|
+
if ((ignoreMessages && processedMessage.messageText) ||
|
|
114
|
+
(ignoreAttachments && processedMessage.attachments.length > 0) ||
|
|
115
|
+
(ignoreReactions && processedMessage.reactions.length > 0)) {
|
|
116
|
+
this.logger.debug(`SignalTrigger: Ignoring message with timestamp ${timestamp} due to filter`);
|
|
112
117
|
return;
|
|
113
118
|
}
|
|
114
119
|
const returnData = {
|
|
@@ -134,7 +139,7 @@ class SignalTrigger {
|
|
|
134
139
|
const ws = connectWebSocket();
|
|
135
140
|
return new Promise((resolve, reject) => {
|
|
136
141
|
ws.on('open', () => {
|
|
137
|
-
this.logger.debug(`SignalTrigger:
|
|
142
|
+
this.logger.debug(`SignalTrigger: Initial connection to ${wsUrl}`);
|
|
138
143
|
resolve({
|
|
139
144
|
closeFunction: async () => {
|
|
140
145
|
ws.close();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
|
2
|
+
interface OperationParams {
|
|
3
|
+
attachmentId?: string;
|
|
4
|
+
timeout: number;
|
|
5
|
+
apiUrl: string;
|
|
6
|
+
apiToken: string;
|
|
7
|
+
phoneNumber: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function executeAttachmentsOperation(this: IExecuteFunctions, operation: string, itemIndex: number, params: OperationParams): Promise<INodeExecutionData>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.executeAttachmentsOperation = void 0;
|
|
7
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
async function executeAttachmentsOperation(operation, itemIndex, params) {
|
|
10
|
+
var _a, _b, _c, _d, _e;
|
|
11
|
+
const { attachmentId, timeout, apiUrl, apiToken, phoneNumber } = params;
|
|
12
|
+
const axiosConfig = {
|
|
13
|
+
headers: apiToken ? { Authorization: `Bearer ${apiToken}` } : {},
|
|
14
|
+
timeout,
|
|
15
|
+
responseType: operation === 'downloadAttachment' ? 'arraybuffer' : 'json',
|
|
16
|
+
};
|
|
17
|
+
const retryRequest = async (request, retries = 2, delay = 5000) => {
|
|
18
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
19
|
+
try {
|
|
20
|
+
return await request();
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (attempt === retries)
|
|
24
|
+
throw error;
|
|
25
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
try {
|
|
30
|
+
if (operation === 'listAttachments') {
|
|
31
|
+
const response = await retryRequest(() => axios_1.default.get(`${apiUrl}/v1/attachments/${phoneNumber}`, axiosConfig));
|
|
32
|
+
return { json: response.data, pairedItem: { item: itemIndex } };
|
|
33
|
+
}
|
|
34
|
+
else if (operation === 'downloadAttachment') {
|
|
35
|
+
if (!attachmentId) {
|
|
36
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Attachment ID is required' });
|
|
37
|
+
}
|
|
38
|
+
const endpoint = `${apiUrl}/v1/attachments/${attachmentId}`;
|
|
39
|
+
this.logger.debug(`Attachments: Downloading from endpoint: ${endpoint}`);
|
|
40
|
+
const response = await retryRequest(() => axios_1.default.get(endpoint, axiosConfig));
|
|
41
|
+
this.logger.debug(`Attachments: Download response size: ${response.data.byteLength}, content-type: ${response.headers['content-type']}`);
|
|
42
|
+
if (!response.data || response.data.byteLength === 0) {
|
|
43
|
+
this.logger.warn(`Attachments: Empty response data for attachment ${attachmentId}`);
|
|
44
|
+
return { json: { status: 'Empty attachment' }, pairedItem: { item: itemIndex } };
|
|
45
|
+
}
|
|
46
|
+
const contentType = response.headers['content-type'] || 'application/octet-stream';
|
|
47
|
+
const contentDisposition = response.headers['content-disposition'] || '';
|
|
48
|
+
const fileName = ((_a = contentDisposition.match(/filename="(.+)"/)) === null || _a === void 0 ? void 0 : _a[1]) || `attachment_${attachmentId}`;
|
|
49
|
+
const fileExtension = fileName.split('.').pop() || '';
|
|
50
|
+
// Конвертуємо ArrayBuffer в Buffer для n8n
|
|
51
|
+
const buffer = Buffer.from(response.data);
|
|
52
|
+
this.logger.debug(`Attachments: Created buffer of size: ${buffer.length}`);
|
|
53
|
+
// Збираємо всі доступні headers
|
|
54
|
+
const allHeaders = response.headers || {};
|
|
55
|
+
// Визначаємо тип файлу
|
|
56
|
+
const isImage = contentType.startsWith('image/');
|
|
57
|
+
const isVideo = contentType.startsWith('video/');
|
|
58
|
+
const isAudio = contentType.startsWith('audio/');
|
|
59
|
+
const isDocument = contentType.includes('pdf') || contentType.includes('document') || contentType.includes('text');
|
|
60
|
+
// Форматуємо розмір файлу
|
|
61
|
+
const formatFileSize = (bytes) => {
|
|
62
|
+
if (bytes === 0)
|
|
63
|
+
return '0 Bytes';
|
|
64
|
+
const k = 1024;
|
|
65
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
66
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
67
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
json: {
|
|
71
|
+
// Основна інформація про файл
|
|
72
|
+
attachmentId,
|
|
73
|
+
fileName,
|
|
74
|
+
fileExtension,
|
|
75
|
+
mimeType: contentType,
|
|
76
|
+
// Розмір файлу
|
|
77
|
+
sizeBytes: buffer.length,
|
|
78
|
+
sizeFormatted: formatFileSize(buffer.length),
|
|
79
|
+
// Тип файлу
|
|
80
|
+
fileType: {
|
|
81
|
+
isImage,
|
|
82
|
+
isVideo,
|
|
83
|
+
isAudio,
|
|
84
|
+
isDocument,
|
|
85
|
+
category: isImage ? 'Image' : isVideo ? 'Video' : isAudio ? 'Audio' : isDocument ? 'Document' : 'Other'
|
|
86
|
+
},
|
|
87
|
+
// HTTP headers від API
|
|
88
|
+
headers: Object.keys(allHeaders).reduce((acc, key) => {
|
|
89
|
+
const value = allHeaders[key];
|
|
90
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
91
|
+
acc[key] = value;
|
|
92
|
+
}
|
|
93
|
+
return acc;
|
|
94
|
+
}, {}),
|
|
95
|
+
// Додаткова інформація
|
|
96
|
+
downloadInfo: {
|
|
97
|
+
endpoint,
|
|
98
|
+
downloadedAt: new Date().toISOString(),
|
|
99
|
+
contentDisposition: contentDisposition || null,
|
|
100
|
+
hasValidContent: buffer.length > 0,
|
|
101
|
+
isEmpty: buffer.length === 0
|
|
102
|
+
},
|
|
103
|
+
// Статус завантаження
|
|
104
|
+
status: buffer.length > 0 ? 'downloaded_successfully' : 'empty_attachment'
|
|
105
|
+
},
|
|
106
|
+
binary: {
|
|
107
|
+
attachment: {
|
|
108
|
+
data: buffer.toString('base64'),
|
|
109
|
+
mimeType: contentType,
|
|
110
|
+
fileName: fileName,
|
|
111
|
+
fileExtension,
|
|
112
|
+
// Додаткові метадані для binary даних
|
|
113
|
+
fileSize: buffer.length,
|
|
114
|
+
id: attachmentId,
|
|
115
|
+
directory: `/attachments/${phoneNumber}`,
|
|
116
|
+
// Додаткові поля які можуть бути корисними
|
|
117
|
+
encoding: 'base64',
|
|
118
|
+
originalName: fileName,
|
|
119
|
+
downloadedFrom: endpoint,
|
|
120
|
+
downloadedAt: new Date().toISOString(),
|
|
121
|
+
// Якщо є content-disposition, додаємо його
|
|
122
|
+
...(contentDisposition && { contentDisposition }),
|
|
123
|
+
// Категорія файлу для зручності
|
|
124
|
+
category: isImage ? 'image' : isVideo ? 'video' : isAudio ? 'audio' : isDocument ? 'document' : 'other',
|
|
125
|
+
// MD5 хеш для ідентифікації (опціонально)
|
|
126
|
+
...(buffer.length > 0 && {
|
|
127
|
+
checksum: require('crypto').createHash('md5').update(buffer).digest('hex')
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
pairedItem: { item: itemIndex }
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
else if (operation === 'removeAttachment') {
|
|
135
|
+
if (!attachmentId) {
|
|
136
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Attachment ID is required' });
|
|
137
|
+
}
|
|
138
|
+
const response = await retryRequest(() => axios_1.default.delete(`${apiUrl}/v1/attachments/${attachmentId}`, axiosConfig));
|
|
139
|
+
return { json: response.data || { status: 'Attachment removed' }, pairedItem: { item: itemIndex } };
|
|
140
|
+
}
|
|
141
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Unknown operation' });
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
const axiosError = error;
|
|
145
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
|
|
146
|
+
message: axiosError.message,
|
|
147
|
+
description: (((_c = (_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) || axiosError.message),
|
|
148
|
+
httpCode: ((_e = (_d = axiosError.response) === null || _d === void 0 ? void 0 : _d.status) === null || _e === void 0 ? void 0 : _e.toString()) || 'unknown',
|
|
149
|
+
}, { itemIndex });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.executeAttachmentsOperation = executeAttachmentsOperation;
|
|
@@ -26,38 +26,34 @@ async function executeMessagesOperation(operation, itemIndex, params) {
|
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
try {
|
|
29
|
-
let response;
|
|
30
29
|
if (operation === 'sendMessage') {
|
|
31
|
-
response = await retryRequest(() => axios_1.default.post(`${apiUrl}/v1/send`, {
|
|
30
|
+
const response = await retryRequest(() => axios_1.default.post(`${apiUrl}/v1/send`, {
|
|
32
31
|
message,
|
|
33
32
|
number: phoneNumber,
|
|
34
33
|
recipients: [recipient],
|
|
35
34
|
}, axiosConfig));
|
|
36
|
-
this.logger.debug(`Signal messages: sendMessage response: ${JSON.stringify(response.data, null, 2)}`);
|
|
37
35
|
return { json: response.data || { status: 'Message sent' }, pairedItem: { item: itemIndex } };
|
|
38
36
|
}
|
|
39
37
|
else if (operation === 'sendAttachment') {
|
|
40
|
-
response = await retryRequest(() => axios_1.default.post(`${apiUrl}/v1/send`, {
|
|
38
|
+
const response = await retryRequest(() => axios_1.default.post(`${apiUrl}/v1/send`, {
|
|
41
39
|
message,
|
|
42
40
|
number: phoneNumber,
|
|
43
41
|
recipients: [recipient],
|
|
44
42
|
attachments: [attachmentUrl],
|
|
45
43
|
}, axiosConfig));
|
|
46
|
-
this.logger.debug(`Signal messages: sendAttachment response: ${JSON.stringify(response.data, null, 2)}`);
|
|
47
44
|
return { json: response.data || { status: 'Attachment sent' }, pairedItem: { item: itemIndex } };
|
|
48
45
|
}
|
|
49
46
|
else if (operation === 'sendReaction') {
|
|
50
|
-
response = await retryRequest(() => axios_1.default.post(`${apiUrl}/v1/reactions/${phoneNumber}`, {
|
|
47
|
+
const response = await retryRequest(() => axios_1.default.post(`${apiUrl}/v1/reactions/${phoneNumber}`, {
|
|
51
48
|
reaction: emoji,
|
|
52
49
|
recipient,
|
|
53
50
|
target_author: targetAuthor,
|
|
54
51
|
timestamp: targetSentTimestamp,
|
|
55
52
|
}, axiosConfig));
|
|
56
|
-
this.logger.debug(`Signal messages: sendReaction response: ${JSON.stringify(response.data, null, 2)}`);
|
|
57
53
|
return { json: response.data || { status: 'Reaction sent' }, pairedItem: { item: itemIndex } };
|
|
58
54
|
}
|
|
59
55
|
else if (operation === 'removeReaction') {
|
|
60
|
-
response = await retryRequest(() => axios_1.default.delete(`${apiUrl}/v1/reactions/${phoneNumber}`, {
|
|
56
|
+
const response = await retryRequest(() => axios_1.default.delete(`${apiUrl}/v1/reactions/${phoneNumber}`, {
|
|
61
57
|
...axiosConfig,
|
|
62
58
|
data: {
|
|
63
59
|
recipient,
|
|
@@ -65,7 +61,6 @@ async function executeMessagesOperation(operation, itemIndex, params) {
|
|
|
65
61
|
timestamp: targetSentTimestamp,
|
|
66
62
|
},
|
|
67
63
|
}));
|
|
68
|
-
this.logger.debug(`Signal messages: removeReaction response: ${JSON.stringify(response.data, null, 2)}`);
|
|
69
64
|
return { json: response.data || { status: 'Reaction removed' }, pairedItem: { item: itemIndex } };
|
|
70
65
|
}
|
|
71
66
|
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Unknown operation' });
|