piece-signal-cli-rest-api 0.2.0 → 0.2.1
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 +26 -4
- package/src/index.d.ts +8 -0
- package/src/index.js +90 -0
- package/src/index.js.map +1 -0
- package/src/lib/actions/add-admins-to-group.d.ts +12 -0
- package/src/lib/actions/add-admins-to-group.js +45 -0
- package/src/lib/actions/add-admins-to-group.js.map +1 -0
- package/src/lib/actions/add-device.d.ts +11 -0
- package/src/lib/actions/add-device.js +40 -0
- package/src/lib/actions/add-device.js.map +1 -0
- package/src/lib/actions/add-members-to-group.d.ts +12 -0
- package/src/lib/actions/add-members-to-group.js +45 -0
- package/src/lib/actions/add-members-to-group.js.map +1 -0
- package/src/lib/actions/block-group.d.ts +11 -0
- package/src/lib/actions/block-group.js +37 -0
- package/src/lib/actions/block-group.js.map +1 -0
- package/src/lib/actions/create-group.d.ts +18 -0
- package/src/lib/actions/create-group.js +117 -0
- package/src/lib/actions/create-group.js.map +1 -0
- package/src/lib/actions/delete-group.d.ts +11 -0
- package/src/lib/actions/delete-group.js +37 -0
- package/src/lib/actions/delete-group.js.map +1 -0
- package/src/lib/actions/get-contact.d.ts +11 -0
- package/src/lib/actions/get-contact.js +37 -0
- package/src/lib/actions/get-contact.js.map +1 -0
- package/src/lib/actions/get-group.d.ts +11 -0
- package/src/lib/actions/get-group.js +37 -0
- package/src/lib/actions/get-group.js.map +1 -0
- package/src/lib/actions/get-qr-code-link.d.ts +11 -0
- package/src/lib/actions/get-qr-code-link.js +60 -0
- package/src/lib/actions/get-qr-code-link.js.map +1 -0
- package/src/lib/actions/join-group.d.ts +11 -0
- package/src/lib/actions/join-group.js +37 -0
- package/src/lib/actions/join-group.js.map +1 -0
- package/src/lib/actions/list-accounts.d.ts +8 -0
- package/src/lib/actions/list-accounts.js +23 -0
- package/src/lib/actions/list-accounts.js.map +1 -0
- package/src/lib/actions/list-attachments.d.ts +8 -0
- package/src/lib/actions/list-attachments.js +23 -0
- package/src/lib/actions/list-attachments.js.map +1 -0
- package/src/lib/actions/list-contacts.d.ts +10 -0
- package/src/lib/actions/list-contacts.js +32 -0
- package/src/lib/actions/list-contacts.js.map +1 -0
- package/src/lib/actions/list-devices.d.ts +10 -0
- package/src/lib/actions/list-devices.js +32 -0
- package/src/lib/actions/list-devices.js.map +1 -0
- package/src/lib/actions/list-groups.d.ts +10 -0
- package/src/lib/actions/list-groups.js +32 -0
- package/src/lib/actions/list-groups.js.map +1 -0
- package/src/lib/actions/list-identities.d.ts +10 -0
- package/src/lib/actions/list-identities.js +32 -0
- package/src/lib/actions/list-identities.js.map +1 -0
- package/src/lib/actions/quit-group.d.ts +11 -0
- package/src/lib/actions/quit-group.js +37 -0
- package/src/lib/actions/quit-group.js.map +1 -0
- package/src/lib/actions/receive-messages.d.ts +15 -0
- package/src/lib/actions/receive-messages.js +100 -0
- package/src/lib/actions/receive-messages.js.map +1 -0
- package/src/lib/actions/remote-delete-message.d.ts +12 -0
- package/src/lib/actions/remote-delete-message.js +46 -0
- package/src/lib/actions/remote-delete-message.js.map +1 -0
- package/src/lib/actions/remove-admins-from-group.d.ts +12 -0
- package/src/lib/actions/remove-admins-from-group.js +45 -0
- package/src/lib/actions/remove-admins-from-group.js.map +1 -0
- package/src/lib/actions/remove-device.d.ts +11 -0
- package/src/lib/actions/remove-device.js +37 -0
- package/src/lib/actions/remove-device.js.map +1 -0
- package/src/lib/actions/remove-members-from-group.d.ts +12 -0
- package/src/lib/actions/remove-members-from-group.js +45 -0
- package/src/lib/actions/remove-members-from-group.js.map +1 -0
- package/src/lib/actions/remove-reaction.d.ts +13 -0
- package/src/lib/actions/remove-reaction.js +52 -0
- package/src/lib/actions/remove-reaction.js.map +1 -0
- package/src/lib/actions/request-approval-message.d.ts +15 -0
- package/src/lib/actions/request-approval-message.js +184 -0
- package/src/lib/actions/request-approval-message.js.map +1 -0
- package/src/lib/actions/resume-approval-flow.d.ts +11 -0
- package/src/lib/actions/resume-approval-flow.js +181 -0
- package/src/lib/actions/resume-approval-flow.js.map +1 -0
- package/src/lib/actions/search-numbers.d.ts +11 -0
- package/src/lib/actions/search-numbers.js +42 -0
- package/src/lib/actions/search-numbers.js.map +1 -0
- package/src/lib/actions/send-message.d.ts +27 -0
- package/src/lib/actions/send-message.js +176 -0
- package/src/lib/actions/send-message.js.map +1 -0
- package/src/lib/actions/send-reaction.d.ts +14 -0
- package/src/lib/actions/send-reaction.js +58 -0
- package/src/lib/actions/send-reaction.js.map +1 -0
- package/src/lib/actions/send-receipt.d.ts +13 -0
- package/src/lib/actions/send-receipt.js +58 -0
- package/src/lib/actions/send-receipt.js.map +1 -0
- package/src/lib/actions/start-typing.d.ts +11 -0
- package/src/lib/actions/start-typing.js +40 -0
- package/src/lib/actions/start-typing.js.map +1 -0
- package/src/lib/actions/stop-typing.d.ts +11 -0
- package/src/lib/actions/stop-typing.js +40 -0
- package/src/lib/actions/stop-typing.js.map +1 -0
- package/src/lib/actions/sync-contacts.d.ts +10 -0
- package/src/lib/actions/sync-contacts.js +32 -0
- package/src/lib/actions/sync-contacts.js.map +1 -0
- package/src/lib/actions/update-account-settings.d.ts +12 -0
- package/src/lib/actions/update-account-settings.js +49 -0
- package/src/lib/actions/update-account-settings.js.map +1 -0
- package/src/lib/actions/update-contact.d.ts +13 -0
- package/src/lib/actions/update-contact.js +56 -0
- package/src/lib/actions/update-contact.js.map +1 -0
- package/src/lib/actions/update-group.d.ts +19 -0
- package/src/lib/actions/update-group.js +125 -0
- package/src/lib/actions/update-group.js.map +1 -0
- package/src/lib/actions/update-profile.d.ts +13 -0
- package/src/lib/actions/update-profile.js +56 -0
- package/src/lib/actions/update-profile.js.map +1 -0
- package/src/lib/common/api-client.d.ts +24 -0
- package/src/lib/common/api-client.js +103 -0
- package/src/lib/common/api-client.js.map +1 -0
- package/src/lib/common/auth.d.ts +8 -0
- package/src/lib/common/auth.js +68 -0
- package/src/lib/common/auth.js.map +1 -0
- package/src/lib/common/message-utils.d.ts +81 -0
- package/src/lib/common/message-utils.js +327 -0
- package/src/lib/common/message-utils.js.map +1 -0
- package/src/lib/common/types.d.ts +65 -0
- package/src/lib/common/types.js +3 -0
- package/src/lib/common/types.js.map +1 -0
- package/src/lib/common/utils.d.ts +23 -0
- package/src/lib/common/utils.js +105 -0
- package/src/lib/common/utils.js.map +1 -0
- package/src/lib/triggers/new-group-member.d.ts +50 -0
- package/src/lib/triggers/new-group-member.js +155 -0
- package/src/lib/triggers/new-group-member.js.map +1 -0
- package/src/lib/triggers/new-message-received.d.ts +58 -0
- package/src/lib/triggers/new-message-received.js +469 -0
- package/src/lib/triggers/new-message-received.js.map +1 -0
- package/project.json +0 -58
- package/src/index.ts +0 -87
- package/src/lib/actions/add-admins-to-group.ts +0 -50
- package/src/lib/actions/add-device.ts +0 -45
- package/src/lib/actions/add-members-to-group.ts +0 -50
- package/src/lib/actions/block-group.ts +0 -36
- package/src/lib/actions/create-group.ts +0 -139
- package/src/lib/actions/delete-group.ts +0 -36
- package/src/lib/actions/get-contact.ts +0 -42
- package/src/lib/actions/get-group.ts +0 -37
- package/src/lib/actions/get-qr-code-link.ts +0 -62
- package/src/lib/actions/join-group.ts +0 -36
- package/src/lib/actions/list-accounts.ts +0 -20
- package/src/lib/actions/list-attachments.ts +0 -20
- package/src/lib/actions/list-contacts.ts +0 -37
- package/src/lib/actions/list-devices.ts +0 -38
- package/src/lib/actions/list-groups.ts +0 -32
- package/src/lib/actions/list-identities.ts +0 -32
- package/src/lib/actions/quit-group.ts +0 -36
- package/src/lib/actions/receive-messages.ts +0 -108
- package/src/lib/actions/remote-delete-message.ts +0 -56
- package/src/lib/actions/remove-admins-from-group.ts +0 -50
- package/src/lib/actions/remove-device.ts +0 -36
- package/src/lib/actions/remove-members-from-group.ts +0 -50
- package/src/lib/actions/remove-reaction.ts +0 -59
- package/src/lib/actions/request-approval-message.ts +0 -215
- package/src/lib/actions/search-numbers.ts +0 -47
- package/src/lib/actions/send-message.ts +0 -189
- package/src/lib/actions/send-reaction.ts +0 -66
- package/src/lib/actions/send-receipt.ts +0 -65
- package/src/lib/actions/start-typing.ts +0 -45
- package/src/lib/actions/stop-typing.ts +0 -45
- package/src/lib/actions/sync-contacts.ts +0 -31
- package/src/lib/actions/update-account-settings.ts +0 -57
- package/src/lib/actions/update-contact.ts +0 -65
- package/src/lib/actions/update-group.ts +0 -145
- package/src/lib/actions/update-profile.ts +0 -65
- package/src/lib/common/api-client.ts +0 -150
- package/src/lib/common/auth.ts +0 -66
- package/src/lib/common/message-utils.ts +0 -449
- package/src/lib/common/types.ts +0 -73
- package/src/lib/common/utils.ts +0 -106
- package/src/lib/triggers/new-group-member.ts +0 -176
- package/src/lib/triggers/new-message-received.ts +0 -618
- package/tsconfig.json +0 -19
- package/tsconfig.lib.json +0 -11
|
@@ -1,618 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createTrigger,
|
|
3
|
-
TriggerStrategy,
|
|
4
|
-
Property,
|
|
5
|
-
AppConnectionValueForAuthProperty,
|
|
6
|
-
StoreScope,
|
|
7
|
-
} from '@activepieces/pieces-framework';
|
|
8
|
-
import {
|
|
9
|
-
DedupeStrategy,
|
|
10
|
-
Polling,
|
|
11
|
-
pollingHelper,
|
|
12
|
-
HttpMethod,
|
|
13
|
-
httpClient,
|
|
14
|
-
} from '@activepieces/pieces-common';
|
|
15
|
-
import { signalCliRestApiAuth } from '../common/auth';
|
|
16
|
-
import { formatPhoneNumber } from '../common/utils';
|
|
17
|
-
import WebSocket from 'ws';
|
|
18
|
-
|
|
19
|
-
interface SignalMessage {
|
|
20
|
-
envelope: {
|
|
21
|
-
source: string;
|
|
22
|
-
sourceNumber?: string;
|
|
23
|
-
sourceUuid?: string;
|
|
24
|
-
sourceName?: string;
|
|
25
|
-
sourceDevice: number;
|
|
26
|
-
timestamp: number;
|
|
27
|
-
timestampISO?: string;
|
|
28
|
-
dataMessage?: {
|
|
29
|
-
message?: string;
|
|
30
|
-
timestamp: number;
|
|
31
|
-
expiresInSeconds?: number;
|
|
32
|
-
attachments?: Array<{
|
|
33
|
-
id: string;
|
|
34
|
-
contentType: string;
|
|
35
|
-
size: number;
|
|
36
|
-
fileName?: string;
|
|
37
|
-
width?: number;
|
|
38
|
-
height?: number;
|
|
39
|
-
voiceNote?: boolean;
|
|
40
|
-
caption?: string;
|
|
41
|
-
}>;
|
|
42
|
-
mentions?: Array<{
|
|
43
|
-
start: number;
|
|
44
|
-
length: number;
|
|
45
|
-
recipient: string;
|
|
46
|
-
}>;
|
|
47
|
-
groupInfo?: {
|
|
48
|
-
groupId: string;
|
|
49
|
-
type: string;
|
|
50
|
-
members?: string[];
|
|
51
|
-
name?: string;
|
|
52
|
-
avatarId?: number;
|
|
53
|
-
};
|
|
54
|
-
quote?: {
|
|
55
|
-
id: number;
|
|
56
|
-
author: string;
|
|
57
|
-
text?: string;
|
|
58
|
-
};
|
|
59
|
-
preview?: Array<{
|
|
60
|
-
url: string;
|
|
61
|
-
title: string;
|
|
62
|
-
description?: string;
|
|
63
|
-
}>;
|
|
64
|
-
sticker?: {
|
|
65
|
-
packId: string;
|
|
66
|
-
stickerId: number;
|
|
67
|
-
};
|
|
68
|
-
reaction?: {
|
|
69
|
-
emoji: string;
|
|
70
|
-
targetAuthor: string;
|
|
71
|
-
targetTimestamp: number;
|
|
72
|
-
};
|
|
73
|
-
viewOnce?: boolean;
|
|
74
|
-
};
|
|
75
|
-
syncMessage?: {
|
|
76
|
-
sentMessage?: {
|
|
77
|
-
destination: string;
|
|
78
|
-
timestamp: number;
|
|
79
|
-
message?: string;
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
receipt?: {
|
|
83
|
-
type: number;
|
|
84
|
-
timestamp: number;
|
|
85
|
-
timestamps: number[];
|
|
86
|
-
};
|
|
87
|
-
typing?: {
|
|
88
|
-
action: number;
|
|
89
|
-
timestamp: number;
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
account: string;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
interface ApprovalMapping {
|
|
96
|
-
flowRunId: string;
|
|
97
|
-
requestId: string;
|
|
98
|
-
approveEmoji: string;
|
|
99
|
-
disapproveEmoji: string;
|
|
100
|
-
targetAuthor: string;
|
|
101
|
-
messageTimestamp: number;
|
|
102
|
-
timeoutSeconds: number;
|
|
103
|
-
createdAt: number;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Function to automatically resume approval flows
|
|
107
|
-
async function tryResumeApprovalFlow(
|
|
108
|
-
message: SignalMessage,
|
|
109
|
-
store: any,
|
|
110
|
-
apiUrl: string
|
|
111
|
-
): Promise<{ resumed: boolean; action?: string }> {
|
|
112
|
-
console.log('[NewMessageReceived] DEBUG - Processing message:', {
|
|
113
|
-
hasReaction: !!message.envelope?.dataMessage?.reaction,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Check if it's a reaction
|
|
117
|
-
if (!message.envelope?.dataMessage?.reaction) {
|
|
118
|
-
return { resumed: false };
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
console.log('[NewMessageReceived] DEBUG - Reaction detected');
|
|
122
|
-
const reaction = message.envelope.dataMessage.reaction;
|
|
123
|
-
// Convert targetTimestamp from milliseconds to seconds (Unix timestamp)
|
|
124
|
-
// Note: targetTimestamp in SignalMessage interface might be targetSentTimestamp in actual data
|
|
125
|
-
const targetTimestampMs = (reaction as any).targetSentTimestamp || reaction.targetTimestamp;
|
|
126
|
-
const targetTimestamp = Math.floor(targetTimestampMs / 1000);
|
|
127
|
-
const targetAuthor = reaction.targetAuthor;
|
|
128
|
-
const reactionEmoji = reaction.emoji;
|
|
129
|
-
|
|
130
|
-
console.log('[NewMessageReceived] DEBUG - Reaction data:', {
|
|
131
|
-
targetSentTimestampOriginal: targetTimestampMs,
|
|
132
|
-
targetTimestamp,
|
|
133
|
-
targetAuthor,
|
|
134
|
-
reactionEmoji,
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// Cleanup expired approvals
|
|
138
|
-
const keysListKey = 'approval:keys';
|
|
139
|
-
const existingKeys = (await store.get<string[]>(keysListKey, StoreScope.PROJECT)) || [];
|
|
140
|
-
const currentTimestamp = Math.floor(Date.now() / 1000);
|
|
141
|
-
const validKeys: string[] = [];
|
|
142
|
-
const keysToDelete: string[] = [];
|
|
143
|
-
|
|
144
|
-
console.log('[NewMessageReceived] DEBUG - Store info:', {
|
|
145
|
-
existingKeysCount: existingKeys.length,
|
|
146
|
-
existingKeys: existingKeys,
|
|
147
|
-
currentTimestamp,
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
for (const key of existingKeys) {
|
|
151
|
-
const mapping = await store.get<ApprovalMapping>(key, StoreScope.PROJECT);
|
|
152
|
-
if (mapping) {
|
|
153
|
-
// Check if expired
|
|
154
|
-
if (currentTimestamp - mapping.createdAt > mapping.timeoutSeconds) {
|
|
155
|
-
// Expired - delete it and flowRunId mapping
|
|
156
|
-
await store.delete(key, StoreScope.PROJECT);
|
|
157
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
158
|
-
await store.delete(flowRunMappingKey, StoreScope.PROJECT);
|
|
159
|
-
keysToDelete.push(key);
|
|
160
|
-
} else {
|
|
161
|
-
validKeys.push(key);
|
|
162
|
-
}
|
|
163
|
-
} else {
|
|
164
|
-
// Mapping not found - remove from list
|
|
165
|
-
keysToDelete.push(key);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Update keys list if any were deleted
|
|
170
|
-
if (keysToDelete.length > 0) {
|
|
171
|
-
await store.put(keysListKey, validKeys, StoreScope.PROJECT);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
console.log('[NewMessageReceived] DEBUG - Cleanup result:', {
|
|
175
|
-
keysDeleted: keysToDelete.length,
|
|
176
|
-
validKeysCount: validKeys.length,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Look up the specific approval mapping
|
|
180
|
-
const storeKey = `approval:${targetTimestamp}:${targetAuthor}`;
|
|
181
|
-
|
|
182
|
-
console.log('[NewMessageReceived] DEBUG - Store lookup:', {
|
|
183
|
-
storeKey,
|
|
184
|
-
existingKeysCount: existingKeys.length,
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
const mapping = await store.get<ApprovalMapping>(storeKey, StoreScope.PROJECT);
|
|
188
|
-
|
|
189
|
-
if (!mapping) {
|
|
190
|
-
// Not an approval message
|
|
191
|
-
console.log('[NewMessageReceived] DEBUG - No mapping found:', {
|
|
192
|
-
reason: 'not_an_approval_message',
|
|
193
|
-
searchedKey: storeKey,
|
|
194
|
-
});
|
|
195
|
-
return { resumed: false };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
console.log('[NewMessageReceived] DEBUG - Mapping found:', {
|
|
199
|
-
flowRunId: mapping.flowRunId,
|
|
200
|
-
requestId: mapping.requestId,
|
|
201
|
-
approveEmoji: mapping.approveEmoji,
|
|
202
|
-
disapproveEmoji: mapping.disapproveEmoji,
|
|
203
|
-
messageTimestamp: mapping.messageTimestamp,
|
|
204
|
-
createdAt: mapping.createdAt,
|
|
205
|
-
timeoutSeconds: mapping.timeoutSeconds,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
// Check if expired
|
|
209
|
-
const ageInSeconds = currentTimestamp - mapping.createdAt;
|
|
210
|
-
const isExpired = ageInSeconds > mapping.timeoutSeconds;
|
|
211
|
-
|
|
212
|
-
console.log('[NewMessageReceived] DEBUG - Expiration check:', {
|
|
213
|
-
currentTimestamp,
|
|
214
|
-
createdAt: mapping.createdAt,
|
|
215
|
-
ageInSeconds,
|
|
216
|
-
timeoutSeconds: mapping.timeoutSeconds,
|
|
217
|
-
isExpired,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
if (isExpired) {
|
|
221
|
-
// Expired - delete and return
|
|
222
|
-
await store.delete(storeKey, StoreScope.PROJECT);
|
|
223
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
224
|
-
await store.delete(flowRunMappingKey, StoreScope.PROJECT);
|
|
225
|
-
const updatedKeys = validKeys.filter(key => key !== storeKey);
|
|
226
|
-
await store.put(keysListKey, updatedKeys, StoreScope.PROJECT);
|
|
227
|
-
console.log('[NewMessageReceived] DEBUG - Approval expired');
|
|
228
|
-
return { resumed: false };
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Check emoji and determine action
|
|
232
|
-
let action: string;
|
|
233
|
-
|
|
234
|
-
console.log('[NewMessageReceived] DEBUG - Emoji check:', {
|
|
235
|
-
receivedEmoji: reactionEmoji,
|
|
236
|
-
expectedApproveEmoji: mapping.approveEmoji,
|
|
237
|
-
expectedDisapproveEmoji: mapping.disapproveEmoji,
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
if (reactionEmoji === mapping.approveEmoji) {
|
|
241
|
-
action = 'approve';
|
|
242
|
-
console.log('[NewMessageReceived] DEBUG - Emoji matched: approve');
|
|
243
|
-
} else if (reactionEmoji === mapping.disapproveEmoji) {
|
|
244
|
-
action = 'disapprove';
|
|
245
|
-
console.log('[NewMessageReceived] DEBUG - Emoji matched: disapprove');
|
|
246
|
-
} else {
|
|
247
|
-
// Invalid emoji - not an approval reaction
|
|
248
|
-
console.log('[NewMessageReceived] DEBUG - Invalid emoji:', {
|
|
249
|
-
reason: 'invalid_emoji',
|
|
250
|
-
receivedEmoji: reactionEmoji,
|
|
251
|
-
});
|
|
252
|
-
return { resumed: false };
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Make HTTP request to resume the flow
|
|
256
|
-
const resumeUrl = `${apiUrl}v1/flow-runs/${mapping.flowRunId}/requests/${mapping.requestId}?action=${action}`;
|
|
257
|
-
|
|
258
|
-
console.log('[NewMessageReceived] DEBUG - Attempting resume:', {
|
|
259
|
-
resumeUrl,
|
|
260
|
-
apiUrl,
|
|
261
|
-
flowRunId: mapping.flowRunId,
|
|
262
|
-
requestId: mapping.requestId,
|
|
263
|
-
action,
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
try {
|
|
267
|
-
const response = await httpClient.sendRequest({
|
|
268
|
-
method: HttpMethod.POST,
|
|
269
|
-
url: resumeUrl,
|
|
270
|
-
headers: {
|
|
271
|
-
'Content-Type': 'application/json',
|
|
272
|
-
},
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
console.log('[NewMessageReceived] DEBUG - Resume successful:', {
|
|
276
|
-
flowRunId: mapping.flowRunId,
|
|
277
|
-
action,
|
|
278
|
-
responseStatus: response.status,
|
|
279
|
-
responseBody: response.body,
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
// Delete mapping from Store (cleanup)
|
|
283
|
-
await store.delete(storeKey, StoreScope.PROJECT);
|
|
284
|
-
|
|
285
|
-
// Delete flowRunId mapping
|
|
286
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
287
|
-
await store.delete(flowRunMappingKey, StoreScope.PROJECT);
|
|
288
|
-
|
|
289
|
-
// Remove key from approval keys list
|
|
290
|
-
const finalKeys = validKeys.filter(key => key !== storeKey);
|
|
291
|
-
await store.put(keysListKey, finalKeys, StoreScope.PROJECT);
|
|
292
|
-
|
|
293
|
-
console.log('[NewMessageReceived] DEBUG - Cleanup completed');
|
|
294
|
-
|
|
295
|
-
return { resumed: true, action };
|
|
296
|
-
} catch (error) {
|
|
297
|
-
// If resume fails, log but don't throw - message will still be returned
|
|
298
|
-
console.error('[NewMessageReceived] DEBUG - Resume failed:', {
|
|
299
|
-
error: error instanceof Error ? error.message : String(error),
|
|
300
|
-
errorStack: error instanceof Error ? error.stack : undefined,
|
|
301
|
-
resumeUrl,
|
|
302
|
-
flowRunId: mapping.flowRunId,
|
|
303
|
-
reason: 'resume_failed',
|
|
304
|
-
});
|
|
305
|
-
return { resumed: false };
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const polling: Polling<
|
|
310
|
-
AppConnectionValueForAuthProperty<typeof signalCliRestApiAuth>,
|
|
311
|
-
{
|
|
312
|
-
number: string;
|
|
313
|
-
timeout?: number;
|
|
314
|
-
ignore_attachments?: boolean;
|
|
315
|
-
ignore_stories?: boolean;
|
|
316
|
-
max_messages?: number;
|
|
317
|
-
send_read_receipts?: boolean;
|
|
318
|
-
}
|
|
319
|
-
> = {
|
|
320
|
-
strategy: DedupeStrategy.TIMEBASED,
|
|
321
|
-
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
|
|
322
|
-
const { baseUrl, useBasicAuth, basicAuthUsername, basicAuthPassword, mode = 'normal' } = auth.props;
|
|
323
|
-
const { number, timeout = 1, ignore_attachments = false, ignore_stories = false, max_messages, send_read_receipts = false } = propsValue;
|
|
324
|
-
|
|
325
|
-
const formattedNumber = formatPhoneNumber(number);
|
|
326
|
-
|
|
327
|
-
// Build query parameters
|
|
328
|
-
const queryParams = new URLSearchParams();
|
|
329
|
-
queryParams.append('timeout', timeout.toString());
|
|
330
|
-
queryParams.append('ignore_attachments', ignore_attachments.toString());
|
|
331
|
-
queryParams.append('ignore_stories', ignore_stories.toString());
|
|
332
|
-
if (max_messages) {
|
|
333
|
-
queryParams.append('max_messages', max_messages.toString());
|
|
334
|
-
}
|
|
335
|
-
queryParams.append('send_read_receipts', send_read_receipts.toString());
|
|
336
|
-
|
|
337
|
-
const baseUrlClean = baseUrl.replace(/\/$/, '');
|
|
338
|
-
const httpUrl = `${baseUrlClean}/v1/receive/${encodeURIComponent(formattedNumber)}?${queryParams.toString()}`;
|
|
339
|
-
|
|
340
|
-
// Build headers
|
|
341
|
-
const headers: Record<string, string> = {};
|
|
342
|
-
|
|
343
|
-
// Add Basic Auth header if configured
|
|
344
|
-
if (useBasicAuth && basicAuthUsername && basicAuthPassword) {
|
|
345
|
-
const credentials = Buffer.from(
|
|
346
|
-
`${basicAuthUsername}:${basicAuthPassword}`
|
|
347
|
-
).toString('base64');
|
|
348
|
-
headers['Authorization'] = `Basic ${credentials}`;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Use the configured mode to determine which method to use
|
|
352
|
-
if (mode === 'json-rpc') {
|
|
353
|
-
// Use WebSocket for json-rpc mode
|
|
354
|
-
return tryWebSocketReceive(httpUrl, headers, timeout, max_messages);
|
|
355
|
-
} else {
|
|
356
|
-
// Use HTTP GET for normal/native mode
|
|
357
|
-
return tryHttpReceive(httpUrl, headers);
|
|
358
|
-
}
|
|
359
|
-
},
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
// WebSocket receive function (for json-rpc mode)
|
|
363
|
-
async function tryWebSocketReceive(
|
|
364
|
-
httpUrl: string,
|
|
365
|
-
headers: Record<string, string>,
|
|
366
|
-
timeout: number,
|
|
367
|
-
max_messages?: number
|
|
368
|
-
): Promise<Array<{ epochMilliSeconds: number; data: SignalMessage }>> {
|
|
369
|
-
const wsUrl = httpUrl.replace(/^http:/, 'ws:').replace(/^https:/, 'wss:');
|
|
370
|
-
const wsHeaders: Record<string, string> = {
|
|
371
|
-
...headers,
|
|
372
|
-
'Connection': 'Upgrade',
|
|
373
|
-
'Upgrade': 'websocket',
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
return new Promise((resolve, reject) => {
|
|
377
|
-
const messages: SignalMessage[] = [];
|
|
378
|
-
let messageCount = 0;
|
|
379
|
-
const maxMessagesToCollect = max_messages || Infinity;
|
|
380
|
-
const timeoutMs = timeout * 1000;
|
|
381
|
-
let resolved = false;
|
|
382
|
-
|
|
383
|
-
const resolveOnce = (result: Array<{ epochMilliSeconds: number; data: SignalMessage }>) => {
|
|
384
|
-
if (!resolved) {
|
|
385
|
-
resolved = true;
|
|
386
|
-
resolve(result);
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
const rejectOnce = (error: Error) => {
|
|
391
|
-
if (!resolved) {
|
|
392
|
-
resolved = true;
|
|
393
|
-
reject(error);
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
|
|
397
|
-
const processMessages = () => {
|
|
398
|
-
// Filter messages that have dataMessage (actual message content)
|
|
399
|
-
const dataMessages = messages.filter((msg) => msg.envelope?.dataMessage);
|
|
400
|
-
|
|
401
|
-
// Map to polling format with timestamp
|
|
402
|
-
return dataMessages.map((message) => {
|
|
403
|
-
const timestamp = message.envelope.dataMessage?.timestamp || message.envelope.timestamp || Date.now();
|
|
404
|
-
return {
|
|
405
|
-
epochMilliSeconds: timestamp * 1000, // Convert to milliseconds
|
|
406
|
-
data: message,
|
|
407
|
-
};
|
|
408
|
-
});
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
const ws = new WebSocket(wsUrl, {
|
|
412
|
-
headers: wsHeaders,
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
const timeoutId = setTimeout(() => {
|
|
416
|
-
if (!resolved) {
|
|
417
|
-
ws.close();
|
|
418
|
-
resolveOnce(processMessages());
|
|
419
|
-
}
|
|
420
|
-
}, timeoutMs);
|
|
421
|
-
|
|
422
|
-
ws.on('open', () => {
|
|
423
|
-
// WebSocket connection opened successfully
|
|
424
|
-
// The server will send messages as they arrive
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
ws.on('message', (data: WebSocket.Data) => {
|
|
428
|
-
try {
|
|
429
|
-
const messageText = data.toString();
|
|
430
|
-
|
|
431
|
-
// Check if it's an error message
|
|
432
|
-
if (messageText.includes('"error"') || messageText.includes('"Msg"')) {
|
|
433
|
-
try {
|
|
434
|
-
const errorObj = JSON.parse(messageText);
|
|
435
|
-
if (errorObj.error || errorObj.Msg) {
|
|
436
|
-
clearTimeout(timeoutId);
|
|
437
|
-
ws.close();
|
|
438
|
-
// If it's a "no messages" type error, return empty array
|
|
439
|
-
if (errorObj.Msg && errorObj.Msg.includes('No new messages')) {
|
|
440
|
-
resolveOnce([]);
|
|
441
|
-
} else {
|
|
442
|
-
rejectOnce(new Error(errorObj.error || errorObj.Msg));
|
|
443
|
-
}
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
} catch {
|
|
447
|
-
// Not a JSON error, continue processing
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Try to parse as JSON message
|
|
452
|
-
try {
|
|
453
|
-
const message: SignalMessage = JSON.parse(messageText);
|
|
454
|
-
messages.push(message);
|
|
455
|
-
messageCount++;
|
|
456
|
-
|
|
457
|
-
// If we've reached max_messages, close the connection
|
|
458
|
-
if (messageCount >= maxMessagesToCollect) {
|
|
459
|
-
clearTimeout(timeoutId);
|
|
460
|
-
ws.close();
|
|
461
|
-
resolveOnce(processMessages());
|
|
462
|
-
}
|
|
463
|
-
} catch (parseError) {
|
|
464
|
-
// If parsing fails, ignore this message
|
|
465
|
-
// The server might send non-JSON data
|
|
466
|
-
}
|
|
467
|
-
} catch (error) {
|
|
468
|
-
// Ignore individual message errors
|
|
469
|
-
}
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
ws.on('error', (error) => {
|
|
473
|
-
clearTimeout(timeoutId);
|
|
474
|
-
ws.close();
|
|
475
|
-
// Reject to trigger fallback to HTTP GET
|
|
476
|
-
rejectOnce(error);
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
ws.on('close', () => {
|
|
480
|
-
clearTimeout(timeoutId);
|
|
481
|
-
// If we haven't resolved yet, resolve with collected messages
|
|
482
|
-
if (!resolved) {
|
|
483
|
-
resolveOnce(processMessages());
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// HTTP GET receive function (for normal/native mode)
|
|
490
|
-
async function tryHttpReceive(
|
|
491
|
-
httpUrl: string,
|
|
492
|
-
headers: Record<string, string>
|
|
493
|
-
): Promise<Array<{ epochMilliSeconds: number; data: SignalMessage }>> {
|
|
494
|
-
try {
|
|
495
|
-
const response = await httpClient.sendRequest<SignalMessage[] | string>({
|
|
496
|
-
method: HttpMethod.GET,
|
|
497
|
-
url: httpUrl,
|
|
498
|
-
headers,
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
// The API returns either a JSON array of messages or a JSON string
|
|
502
|
-
let messages: SignalMessage[] = [];
|
|
503
|
-
if (typeof response.body === 'string') {
|
|
504
|
-
try {
|
|
505
|
-
messages = JSON.parse(response.body);
|
|
506
|
-
} catch {
|
|
507
|
-
// If parsing fails, try to parse as array
|
|
508
|
-
messages = [];
|
|
509
|
-
}
|
|
510
|
-
} else if (Array.isArray(response.body)) {
|
|
511
|
-
messages = response.body;
|
|
512
|
-
} else {
|
|
513
|
-
messages = [];
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Filter messages that have dataMessage (actual message content)
|
|
517
|
-
const dataMessages = messages.filter((msg) => msg.envelope?.dataMessage);
|
|
518
|
-
|
|
519
|
-
// Map to polling format with timestamp
|
|
520
|
-
return dataMessages.map((message) => {
|
|
521
|
-
const timestamp = message.envelope.dataMessage?.timestamp || message.envelope.timestamp || Date.now();
|
|
522
|
-
return {
|
|
523
|
-
epochMilliSeconds: timestamp * 1000, // Convert to milliseconds
|
|
524
|
-
data: message,
|
|
525
|
-
};
|
|
526
|
-
});
|
|
527
|
-
} catch (error) {
|
|
528
|
-
// If no messages are available, return empty array
|
|
529
|
-
if (error instanceof Error && error.message.includes('No new messages')) {
|
|
530
|
-
return [];
|
|
531
|
-
}
|
|
532
|
-
throw error;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
export const newMessageReceived = createTrigger({
|
|
537
|
-
auth: signalCliRestApiAuth,
|
|
538
|
-
name: 'newMessageReceived',
|
|
539
|
-
displayName: 'New Message Received',
|
|
540
|
-
description: 'Triggers when a new message is received via Signal. Automatically resumes approval flows if the message is a reaction to an approval request.',
|
|
541
|
-
type: TriggerStrategy.POLLING,
|
|
542
|
-
props: {
|
|
543
|
-
number: Property.ShortText({
|
|
544
|
-
displayName: 'Phone Number',
|
|
545
|
-
description: 'Registered phone number in international format (e.g., +43123456789)',
|
|
546
|
-
required: true,
|
|
547
|
-
}),
|
|
548
|
-
timeout: Property.Number({
|
|
549
|
-
displayName: 'Timeout (seconds)',
|
|
550
|
-
description: 'Receive timeout in seconds (default: 1)',
|
|
551
|
-
required: false,
|
|
552
|
-
defaultValue: 1,
|
|
553
|
-
}),
|
|
554
|
-
ignore_attachments: Property.Checkbox({
|
|
555
|
-
displayName: 'Ignore Attachments',
|
|
556
|
-
description: 'Ignore attachments when receiving messages',
|
|
557
|
-
required: false,
|
|
558
|
-
defaultValue: false,
|
|
559
|
-
}),
|
|
560
|
-
ignore_stories: Property.Checkbox({
|
|
561
|
-
displayName: 'Ignore Stories',
|
|
562
|
-
description: 'Ignore stories when receiving messages',
|
|
563
|
-
required: false,
|
|
564
|
-
defaultValue: false,
|
|
565
|
-
}),
|
|
566
|
-
max_messages: Property.Number({
|
|
567
|
-
displayName: 'Max Messages',
|
|
568
|
-
description: 'Maximum number of messages to receive (default: unlimited)',
|
|
569
|
-
required: false,
|
|
570
|
-
}),
|
|
571
|
-
send_read_receipts: Property.Checkbox({
|
|
572
|
-
displayName: 'Send Read Receipts',
|
|
573
|
-
description: 'Automatically send read receipts when receiving messages',
|
|
574
|
-
required: false,
|
|
575
|
-
defaultValue: false,
|
|
576
|
-
}),
|
|
577
|
-
},
|
|
578
|
-
sampleData: {
|
|
579
|
-
envelope: {
|
|
580
|
-
source: '+43123456789',
|
|
581
|
-
sourceNumber: '+43123456789',
|
|
582
|
-
sourceDevice: 1,
|
|
583
|
-
timestamp: 1234567890,
|
|
584
|
-
dataMessage: {
|
|
585
|
-
message: 'Hello, this is a test message',
|
|
586
|
-
timestamp: 1234567890,
|
|
587
|
-
},
|
|
588
|
-
},
|
|
589
|
-
account: '+43123456789',
|
|
590
|
-
},
|
|
591
|
-
async test(context) {
|
|
592
|
-
return await pollingHelper.test(polling, context);
|
|
593
|
-
},
|
|
594
|
-
async onEnable(context) {
|
|
595
|
-
await pollingHelper.onEnable(polling, context);
|
|
596
|
-
},
|
|
597
|
-
async onDisable(context) {
|
|
598
|
-
await pollingHelper.onDisable(polling, context);
|
|
599
|
-
},
|
|
600
|
-
async run(context) {
|
|
601
|
-
// Get messages from polling
|
|
602
|
-
const messages = await pollingHelper.poll(polling, context);
|
|
603
|
-
|
|
604
|
-
// Process each message: try to resume approval flows if applicable
|
|
605
|
-
// Messages are still returned regardless of whether they triggered a resume
|
|
606
|
-
// Debug information is output via console.log (visible in Docker logs)
|
|
607
|
-
const apiUrl = context.server?.apiUrl || '';
|
|
608
|
-
|
|
609
|
-
for (const message of messages) {
|
|
610
|
-
const signalMessage = message as SignalMessage;
|
|
611
|
-
// This will output debug info via console.log
|
|
612
|
-
await tryResumeApprovalFlow(signalMessage, context.store, apiUrl);
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
// Return messages without debug fields (normal output)
|
|
616
|
-
return messages;
|
|
617
|
-
},
|
|
618
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../../../tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"forceConsistentCasingInFileNames": true,
|
|
6
|
-
"strict": true,
|
|
7
|
-
"noImplicitOverride": true,
|
|
8
|
-
"noPropertyAccessFromIndexSignature": true,
|
|
9
|
-
"noImplicitReturns": true,
|
|
10
|
-
"noFallthroughCasesInSwitch": true
|
|
11
|
-
},
|
|
12
|
-
"files": [],
|
|
13
|
-
"include": [],
|
|
14
|
-
"references": [
|
|
15
|
-
{
|
|
16
|
-
"path": "./tsconfig.lib.json"
|
|
17
|
-
}
|
|
18
|
-
]
|
|
19
|
-
}
|
package/tsconfig.lib.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"outDir": "../../../../dist/out-tsc",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"types": ["node"]
|
|
8
|
-
},
|
|
9
|
-
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
|
|
10
|
-
"include": ["src/**/*.ts", "src/lib/actions/common/utils.ts"]
|
|
11
|
-
}
|