piece-signal-cli-rest-api 0.2.14 → 0.2.15
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/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "piece-signal-cli-rest-api",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"build": "echo \"piece-signal-cli-rest-api: kein zusätzlicher Build-Schritt erforderlich (bereits als JS ausgeliefert)\"",
|
|
6
|
+
"publish:npm": "npm publish --access public"
|
|
7
|
+
},
|
|
4
8
|
"dependencies": {
|
|
5
9
|
"@sinclair/typebox": "0.34.11",
|
|
6
10
|
"ai": "5.0.104",
|
|
@@ -26,4 +30,4 @@
|
|
|
26
30
|
"types": "./src/index.d.ts",
|
|
27
31
|
"main": "./src/index.js",
|
|
28
32
|
"type": "commonjs"
|
|
29
|
-
}
|
|
33
|
+
}
|
|
@@ -83,7 +83,9 @@ exports.requestApprovalMessage = (0, pieces_framework_1.createAction)({
|
|
|
83
83
|
const targetAuthor = formattedNumber;
|
|
84
84
|
const createdAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
|
|
85
85
|
// Create store key using milliseconds for precise matching
|
|
86
|
-
|
|
86
|
+
// Store-Key mit Timestamp + eindeutiger Flow-Run-ID
|
|
87
|
+
// flowRunId ist pro Flow-Ausführung eindeutig, verhindert Kollisionen
|
|
88
|
+
const storeKey = `approval:${messageTimestampMs}:${context.run.id}`;
|
|
87
89
|
// DEBUG: Log storing approval mapping
|
|
88
90
|
console.log('[RequestApprovalMessage] DEBUG - Storing approval mapping:', {
|
|
89
91
|
storeKey,
|
|
@@ -9,6 +9,8 @@ const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
|
9
9
|
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
10
10
|
const ws_1 = tslib_1.__importDefault(require("ws"));
|
|
11
11
|
// Function to cleanup expired approval mappings
|
|
12
|
+
// Diese Funktion ist die EINZIGE Stelle, an der entschieden wird, ob ein Approval abgelaufen ist.
|
|
13
|
+
// Alle abgelaufenen Approvals werden hier gelöscht, bevor das Matching stattfindet.
|
|
12
14
|
function cleanupExpiredApprovals(store) {
|
|
13
15
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
14
16
|
const keysListKey = 'approval:keys';
|
|
@@ -67,6 +69,8 @@ function tryResumeApprovalFlow(message, store, apiUrl) {
|
|
|
67
69
|
isGroupMessage: isGroupMessage,
|
|
68
70
|
});
|
|
69
71
|
// Cleanup expired approvals
|
|
72
|
+
// WICHTIG: cleanupExpiredApprovals ist die EINZIGE Stelle für Timeout-Entscheidungen.
|
|
73
|
+
// Alle nachfolgenden Matching-Schritte arbeiten nur auf bereits gefilterten (nicht abgelaufenen) Approvals.
|
|
70
74
|
yield cleanupExpiredApprovals(store);
|
|
71
75
|
const keysListKey = 'approval:keys';
|
|
72
76
|
const existingKeys = (yield store.get(keysListKey, pieces_framework_1.StoreScope.PROJECT)) || [];
|
|
@@ -83,19 +87,72 @@ function tryResumeApprovalFlow(message, store, apiUrl) {
|
|
|
83
87
|
// signal-cli returns timestamps in SECONDS, convert to milliseconds for matching
|
|
84
88
|
const targetTimestampSeconds = reaction.targetSentTimestamp || reaction.targetTimestamp;
|
|
85
89
|
const targetTimestampMs = targetTimestampSeconds * 1000;
|
|
86
|
-
const targetAuthor = reaction.targetAuthor;
|
|
87
90
|
const reactionEmoji = reaction.emoji;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
const messageSource = message.envelope.source;
|
|
92
|
+
|
|
93
|
+
console.log('[ReceiveMessages] DEBUG - Processing emoji reaction:', {
|
|
94
|
+
targetTimestampMs,
|
|
95
|
+
targetTimestampSeconds,
|
|
96
|
+
reactionEmoji,
|
|
97
|
+
messageSource,
|
|
98
|
+
isGroupMessage,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Alle Approvals durchsuchen: Exakter Timestamp-Match + Empfänger-Validierung
|
|
102
|
+
for (const key of existingKeys) {
|
|
103
|
+
const candidateMapping = yield store.get(key, pieces_framework_1.StoreScope.PROJECT);
|
|
104
|
+
if (!candidateMapping) continue;
|
|
105
|
+
|
|
106
|
+
// Exakter Timestamp-Match (beide vom Signal-Netzwerk, müssen identisch sein)
|
|
107
|
+
if (candidateMapping.messageTimestampMs !== targetTimestampMs) continue;
|
|
108
|
+
|
|
109
|
+
console.log('[ReceiveMessages] DEBUG - Timestamp match found, checking recipient:', {
|
|
110
|
+
key,
|
|
111
|
+
candidateTimestampMs: candidateMapping.messageTimestampMs,
|
|
112
|
+
recipients: candidateMapping.recipients,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Empfänger-Validierung (1:1 vs. Gruppe)
|
|
116
|
+
const recipients = candidateMapping.recipients || [];
|
|
117
|
+
let isValidRecipient = false;
|
|
118
|
+
|
|
119
|
+
if (isGroupMessage) {
|
|
120
|
+
// Bei Gruppen: Prüfe Gruppen-ID
|
|
121
|
+
const groupId = dataMessage.groupInfo.groupId;
|
|
122
|
+
isValidRecipient = Array.isArray(recipients) && recipients.includes(groupId);
|
|
123
|
+
console.log('[ReceiveMessages] DEBUG - Group recipient check:', {
|
|
124
|
+
groupId,
|
|
125
|
+
isValidRecipient,
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
// Bei 1:1: Prüfe, ob Absender in recipients-Liste steht
|
|
129
|
+
isValidRecipient = Array.isArray(recipients) && recipients.includes(messageSource);
|
|
130
|
+
console.log('[ReceiveMessages] DEBUG - 1:1 recipient check:', {
|
|
131
|
+
messageSource,
|
|
132
|
+
isValidRecipient,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!isValidRecipient) continue;
|
|
137
|
+
|
|
138
|
+
// Prüfe, ob Emoji-Modus erlaubt ist
|
|
139
|
+
const acceptModes = candidateMapping.acceptReactionModes || [];
|
|
92
140
|
if (acceptModes.includes('emoji')) {
|
|
93
|
-
|
|
141
|
+
mapping = candidateMapping;
|
|
142
|
+
storeKey = key;
|
|
143
|
+
responseContent = reactionEmoji;
|
|
94
144
|
reactionType = 'emoji';
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
145
|
+
console.log('[ReceiveMessages] DEBUG - Emoji reaction match found:', {
|
|
146
|
+
key,
|
|
147
|
+
flowRunId: mapping.flowRunId,
|
|
148
|
+
reactionEmoji,
|
|
149
|
+
});
|
|
150
|
+
break; // Gefunden, Suche beenden
|
|
151
|
+
} else {
|
|
152
|
+
console.log('[ReceiveMessages] DEBUG - Emoji mode not allowed for this approval:', {
|
|
153
|
+
key,
|
|
154
|
+
acceptModes,
|
|
155
|
+
});
|
|
99
156
|
}
|
|
100
157
|
}
|
|
101
158
|
}
|
|
@@ -105,20 +162,72 @@ function tryResumeApprovalFlow(message, store, apiUrl) {
|
|
|
105
162
|
// signal-cli returns timestamps in SECONDS, convert to milliseconds for matching
|
|
106
163
|
const quoteTimestampSeconds = quote.id || quote.timestamp;
|
|
107
164
|
const quoteTimestampMs = quoteTimestampSeconds * 1000;
|
|
108
|
-
const quoteAuthor = quote.author;
|
|
109
165
|
const replyText = dataMessage.message || '';
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
166
|
+
const messageSource = message.envelope.source;
|
|
167
|
+
|
|
168
|
+
console.log('[ReceiveMessages] DEBUG - Processing text reply (quote):', {
|
|
169
|
+
quoteTimestampMs,
|
|
170
|
+
quoteTimestampSeconds,
|
|
171
|
+
replyText: replyText.substring(0, 50), // First 50 chars for logging
|
|
172
|
+
messageSource,
|
|
173
|
+
isGroupMessage,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Alle Approvals durchsuchen: Exakter Timestamp-Match + Empfänger-Validierung
|
|
177
|
+
for (const key of existingKeys) {
|
|
178
|
+
const candidateMapping = yield store.get(key, pieces_framework_1.StoreScope.PROJECT);
|
|
179
|
+
if (!candidateMapping) continue;
|
|
180
|
+
|
|
181
|
+
// Exakter Timestamp-Match (beide vom Signal-Netzwerk, müssen identisch sein)
|
|
182
|
+
if (candidateMapping.messageTimestampMs !== quoteTimestampMs) continue;
|
|
183
|
+
|
|
184
|
+
console.log('[ReceiveMessages] DEBUG - Timestamp match found, checking recipient:', {
|
|
185
|
+
key,
|
|
186
|
+
candidateTimestampMs: candidateMapping.messageTimestampMs,
|
|
187
|
+
recipients: candidateMapping.recipients,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Empfänger-Validierung (1:1 vs. Gruppe)
|
|
191
|
+
const recipients = candidateMapping.recipients || [];
|
|
192
|
+
let isValidRecipient = false;
|
|
193
|
+
|
|
194
|
+
if (isGroupMessage) {
|
|
195
|
+
// Bei Gruppen: Prüfe Gruppen-ID
|
|
196
|
+
const groupId = dataMessage.groupInfo.groupId;
|
|
197
|
+
isValidRecipient = Array.isArray(recipients) && recipients.includes(groupId);
|
|
198
|
+
console.log('[ReceiveMessages] DEBUG - Group recipient check:', {
|
|
199
|
+
groupId,
|
|
200
|
+
isValidRecipient,
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
// Bei 1:1: Prüfe, ob Absender in recipients-Liste steht
|
|
204
|
+
isValidRecipient = Array.isArray(recipients) && recipients.includes(messageSource);
|
|
205
|
+
console.log('[ReceiveMessages] DEBUG - 1:1 recipient check:', {
|
|
206
|
+
messageSource,
|
|
207
|
+
isValidRecipient,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!isValidRecipient) continue;
|
|
212
|
+
|
|
213
|
+
// Prüfe, ob Text-Modus erlaubt ist
|
|
214
|
+
const acceptModes = candidateMapping.acceptReactionModes || [];
|
|
115
215
|
if (acceptModes.includes('text')) {
|
|
116
|
-
|
|
216
|
+
mapping = candidateMapping;
|
|
217
|
+
storeKey = key;
|
|
218
|
+
responseContent = replyText;
|
|
117
219
|
reactionType = 'text';
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
220
|
+
console.log('[ReceiveMessages] DEBUG - Text reply match found:', {
|
|
221
|
+
key,
|
|
222
|
+
flowRunId: mapping.flowRunId,
|
|
223
|
+
replyText: replyText.substring(0, 50),
|
|
224
|
+
});
|
|
225
|
+
break; // Gefunden, Suche beenden
|
|
226
|
+
} else {
|
|
227
|
+
console.log('[ReceiveMessages] DEBUG - Text mode not allowed for this approval:', {
|
|
228
|
+
key,
|
|
229
|
+
acceptModes,
|
|
230
|
+
});
|
|
122
231
|
}
|
|
123
232
|
}
|
|
124
233
|
}
|
|
@@ -127,17 +236,17 @@ function tryResumeApprovalFlow(message, store, apiUrl) {
|
|
|
127
236
|
const messageText = dataMessage.message || '';
|
|
128
237
|
const messageSource = message.envelope.source;
|
|
129
238
|
|
|
239
|
+
console.log('[ReceiveMessages] DEBUG - Processing direct message:', {
|
|
240
|
+
messageText: messageText.substring(0, 50), // First 50 chars for logging
|
|
241
|
+
messageSource,
|
|
242
|
+
});
|
|
243
|
+
|
|
130
244
|
// Iterate through all approval keys to find a match
|
|
245
|
+
// Keine Timeout-Prüfung mehr - cleanupExpiredApprovals hat bereits alle abgelaufenen entfernt
|
|
131
246
|
for (const key of existingKeys) {
|
|
132
247
|
const candidateMapping = yield store.get(key, pieces_framework_1.StoreScope.PROJECT);
|
|
133
248
|
if (!candidateMapping) continue;
|
|
134
249
|
|
|
135
|
-
// Check if expired
|
|
136
|
-
const ageInSeconds = currentTimestamp - candidateMapping.createdAt;
|
|
137
|
-
if (ageInSeconds > candidateMapping.timeoutSeconds) {
|
|
138
|
-
continue; // Skip expired mappings
|
|
139
|
-
}
|
|
140
|
-
|
|
141
250
|
// Check if direct mode is enabled
|
|
142
251
|
const acceptModes = candidateMapping.acceptReactionModes || [];
|
|
143
252
|
if (!acceptModes.includes('direct')) {
|
|
@@ -152,6 +261,11 @@ function tryResumeApprovalFlow(message, store, apiUrl) {
|
|
|
152
261
|
storeKey = key;
|
|
153
262
|
responseContent = messageText; // Use the message text as response
|
|
154
263
|
reactionType = 'direct';
|
|
264
|
+
console.log('[ReceiveMessages] DEBUG - Direct message match found:', {
|
|
265
|
+
key,
|
|
266
|
+
flowRunId: mapping.flowRunId,
|
|
267
|
+
messageText: messageText.substring(0, 50),
|
|
268
|
+
});
|
|
155
269
|
break; // Found a match, stop searching
|
|
156
270
|
}
|
|
157
271
|
}
|
|
@@ -168,19 +282,7 @@ function tryResumeApprovalFlow(message, store, apiUrl) {
|
|
|
168
282
|
reactionType,
|
|
169
283
|
responseContent,
|
|
170
284
|
});
|
|
171
|
-
//
|
|
172
|
-
const ageInSeconds = currentTimestamp - mapping.createdAt;
|
|
173
|
-
const isExpired = ageInSeconds > mapping.timeoutSeconds;
|
|
174
|
-
if (isExpired) {
|
|
175
|
-
// Expired - delete and return
|
|
176
|
-
yield store.delete(storeKey, pieces_framework_1.StoreScope.PROJECT);
|
|
177
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
178
|
-
yield store.delete(flowRunMappingKey, pieces_framework_1.StoreScope.PROJECT);
|
|
179
|
-
const updatedKeys = existingKeys.filter(key => key !== storeKey);
|
|
180
|
-
yield store.put(keysListKey, updatedKeys, pieces_framework_1.StoreScope.PROJECT);
|
|
181
|
-
console.log('[ReceiveMessages] DEBUG - Approval expired');
|
|
182
|
-
return { resumed: false };
|
|
183
|
-
}
|
|
285
|
+
// Keine Timeout-Prüfung mehr - cleanupExpiredApprovals hat bereits alle abgelaufenen entfernt
|
|
184
286
|
// Resume the flow with responseContent
|
|
185
287
|
const resumeUrl = `${apiUrl}v1/flow-runs/${mapping.flowRunId}/requests/${mapping.requestId}?responseContent=${encodeURIComponent(responseContent)}&reactionType=${reactionType}&responder=${encodeURIComponent(responder || '')}`;
|
|
186
288
|
console.log('[ReceiveMessages] DEBUG - Attempting resume:', {
|