n8n-nodes-signal-cli-rest-api 0.3.0 → 0.5.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.
package/README.md CHANGED
@@ -93,7 +93,7 @@ services:
93
93
 
94
94
  1. In your n8n instance, go to **Settings** → **Community Nodes**
95
95
  2. Click **Install a community node**
96
- 3. Enter the package name: `n8n-nodes-signal`
96
+ 3. Enter the package name: `n8n-nodes-signal-cli-rest-api`
97
97
  4. Click **Install**
98
98
 
99
99
  ### Method 2: Manual Installation
@@ -101,7 +101,7 @@ services:
101
101
  1. Navigate to your n8n installation directory
102
102
  2. Install the package:
103
103
  ```bash
104
- npm install n8n-nodes-signal
104
+ npm install n8n-nodes-signal-cli-rest-api
105
105
  ```
106
106
  3. Restart n8n
107
107
 
@@ -55,6 +55,13 @@ class SignalTrigger {
55
55
  default: false,
56
56
  description: 'Enable to ignore messages with reactions',
57
57
  },
58
+ {
59
+ displayName: 'Mark Messages as Read',
60
+ name: 'markAsRead',
61
+ type: 'boolean',
62
+ default: false,
63
+ description: 'Automatically mark processed incoming messages as read',
64
+ },
58
65
  ],
59
66
  };
60
67
  }
@@ -67,10 +74,39 @@ class SignalTrigger {
67
74
  const ignoreMessages = this.getNodeParameter('ignoreMessages', 0);
68
75
  const ignoreAttachments = this.getNodeParameter('ignoreAttachments', 0);
69
76
  const ignoreReactions = this.getNodeParameter('ignoreReactions', 0);
77
+ const markAsRead = this.getNodeParameter('markAsRead', 0);
70
78
  const wsUrl = `${apiUrl.replace('http', 'ws')}/v1/receive/${phoneNumber}`;
71
79
  this.logger.debug(`SignalTrigger: Attempting to connect to WS URL: ${wsUrl}`);
72
80
  const processedMessages = new Set();
73
81
  const maxMessages = 1000;
82
+ // Функція для позначення повідомлення як прочитаного
83
+ const markMessageAsRead = async (sourceNumber, sourceUuid, timestamp) => {
84
+ try {
85
+ const readReceiptUrl = `${apiUrl}/v1/read-receipt/${phoneNumber}`;
86
+ const requestBody = {
87
+ recipient: sourceUuid || sourceNumber,
88
+ timestamps: [timestamp]
89
+ };
90
+ const response = await fetch(readReceiptUrl, {
91
+ method: 'POST',
92
+ headers: {
93
+ 'Content-Type': 'application/json',
94
+ ...(apiToken && { Authorization: `Bearer ${apiToken}` }),
95
+ },
96
+ body: JSON.stringify(requestBody),
97
+ });
98
+ if (response.ok) {
99
+ this.logger.debug(`SignalTrigger: Successfully marked message as read for ${sourceNumber} (${sourceUuid}), timestamp: ${timestamp}`);
100
+ }
101
+ else {
102
+ const errorText = await response.text();
103
+ this.logger.warn(`SignalTrigger: Failed to mark message as read: ${response.status} ${errorText}`);
104
+ }
105
+ }
106
+ catch (error) {
107
+ this.logger.error(`SignalTrigger: Error marking message as read`, { error });
108
+ }
109
+ };
74
110
  const connectWebSocket = () => {
75
111
  const ws = new ws_1.WebSocket(wsUrl, {
76
112
  headers: apiToken ? { Authorization: `Bearer ${apiToken}` } : {},
@@ -78,8 +114,8 @@ class SignalTrigger {
78
114
  ws.on('open', () => {
79
115
  this.logger.debug(`SignalTrigger: Successfully connected to ${wsUrl}`);
80
116
  });
81
- ws.on('message', (data) => {
82
- var _a, _b, _c, _d, _e;
117
+ ws.on('message', async (data) => {
118
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
83
119
  try {
84
120
  const message = JSON.parse(data.toString());
85
121
  this.logger.debug(`SignalTrigger: Received raw message: ${JSON.stringify(message, null, 2)}`);
@@ -93,13 +129,53 @@ class SignalTrigger {
93
129
  }
94
130
  processedMessages.add(timestamp);
95
131
  const dataMsg = ((_b = message.envelope) === null || _b === void 0 ? void 0 : _b.dataMessage) || ((_d = (_c = message.envelope) === null || _c === void 0 ? void 0 : _c.syncMessage) === null || _d === void 0 ? void 0 : _d.sentMessage) || {};
132
+ // Визначаємо тип повідомлення на основі структури envelope
133
+ const hasDataMessage = !!((_e = message.envelope) === null || _e === void 0 ? void 0 : _e.dataMessage);
134
+ const hasSyncMessage = !!((_f = message.envelope) === null || _f === void 0 ? void 0 : _f.syncMessage);
135
+ let shouldProcess = false;
136
+ let messageType = 'unknown';
137
+ if (hasDataMessage) {
138
+ // Вхідне повідомлення - обробляємо
139
+ shouldProcess = true;
140
+ messageType = 'incoming';
141
+ this.logger.debug(`SignalTrigger: Incoming message detected`);
142
+ }
143
+ else if (hasSyncMessage) {
144
+ const sentMessage = message.envelope.syncMessage.sentMessage;
145
+ const sourceUuid = message.envelope.sourceUuid;
146
+ const destinationUuid = sentMessage === null || sentMessage === void 0 ? void 0 : sentMessage.destinationUuid;
147
+ if (sourceUuid === destinationUuid) {
148
+ // Повідомлення самому собі - обробляємо
149
+ shouldProcess = true;
150
+ messageType = 'self_note';
151
+ this.logger.debug(`SignalTrigger: Self note detected`);
152
+ }
153
+ else {
154
+ // Вихідне повідомлення комусь - НЕ обробляємо
155
+ shouldProcess = false;
156
+ messageType = 'outgoing';
157
+ this.logger.debug(`SignalTrigger: Outgoing message detected - skipping`);
158
+ }
159
+ }
160
+ if (!shouldProcess) {
161
+ this.logger.debug(`SignalTrigger: Skipping message type: ${messageType} with timestamp ${timestamp}`);
162
+ return;
163
+ }
96
164
  const processedMessage = {
97
165
  messageText: dataMsg.message || '',
98
166
  attachments: dataMsg.attachments || [],
99
167
  reactions: dataMsg.reactions || [],
100
- sourceNumber: ((_e = message.envelope) === null || _e === void 0 ? void 0 : _e.sourceNumber) || '',
168
+ sourceNumber: ((_g = message.envelope) === null || _g === void 0 ? void 0 : _g.sourceNumber) || '',
169
+ sourceUuid: ((_h = message.envelope) === null || _h === void 0 ? void 0 : _h.sourceUuid) || '',
170
+ sourceName: ((_j = message.envelope) === null || _j === void 0 ? void 0 : _j.sourceName) || '',
101
171
  timestamp: timestamp,
172
+ serverReceivedTimestamp: ((_k = message.envelope) === null || _k === void 0 ? void 0 : _k.serverReceivedTimestamp) || 0,
173
+ serverDeliveredTimestamp: ((_l = message.envelope) === null || _l === void 0 ? void 0 : _l.serverDeliveredTimestamp) || 0,
102
174
  account: message.account || '',
175
+ hasContent: ((_m = message.envelope) === null || _m === void 0 ? void 0 : _m.hasContent) || false,
176
+ isUnidentifiedSender: ((_o = message.envelope) === null || _o === void 0 ? void 0 : _o.isUnidentifiedSender) || false,
177
+ messageType: messageType,
178
+ envelope: message.envelope || {},
103
179
  };
104
180
  this.logger.debug(`SignalTrigger: Processed message content: ${JSON.stringify(processedMessage, null, 2)}`);
105
181
  // Ігнорувати події без вмісту
@@ -121,6 +197,10 @@ class SignalTrigger {
121
197
  };
122
198
  this.emit([this.helpers.returnJsonArray([returnData])]);
123
199
  this.logger.debug(`SignalTrigger: Emitted message with timestamp ${timestamp}`);
200
+ // Позначити повідомлення як прочитане, якщо це вхідне повідомлення і увімкнено опцію
201
+ if (markAsRead && messageType === 'incoming') {
202
+ await markMessageAsRead(processedMessage.sourceNumber, processedMessage.sourceUuid, timestamp);
203
+ }
124
204
  }
125
205
  catch (error) {
126
206
  this.logger.error('SignalTrigger: Error parsing message', { error });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-signal-cli-rest-api",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Signal Node for n8n using signal-cli-rest-api",
5
5
  "repository": {
6
6
  "type": "git",