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,449 +0,0 @@
|
|
|
1
|
-
import { StoreScope } from '@activepieces/pieces-framework';
|
|
2
|
-
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
|
|
3
|
-
import WebSocket from 'ws';
|
|
4
|
-
|
|
5
|
-
export interface SignalMessage {
|
|
6
|
-
envelope: {
|
|
7
|
-
source: string;
|
|
8
|
-
sourceNumber?: string;
|
|
9
|
-
sourceUuid?: string;
|
|
10
|
-
sourceName?: string;
|
|
11
|
-
sourceDevice: number;
|
|
12
|
-
timestamp: number;
|
|
13
|
-
timestampISO?: string;
|
|
14
|
-
dataMessage?: {
|
|
15
|
-
message?: string;
|
|
16
|
-
timestamp: number;
|
|
17
|
-
expiresInSeconds?: number;
|
|
18
|
-
attachments?: Array<{
|
|
19
|
-
id: string;
|
|
20
|
-
contentType: string;
|
|
21
|
-
size: number;
|
|
22
|
-
fileName?: string;
|
|
23
|
-
width?: number;
|
|
24
|
-
height?: number;
|
|
25
|
-
voiceNote?: boolean;
|
|
26
|
-
caption?: string;
|
|
27
|
-
}>;
|
|
28
|
-
mentions?: Array<{
|
|
29
|
-
start: number;
|
|
30
|
-
length: number;
|
|
31
|
-
recipient: string;
|
|
32
|
-
}>;
|
|
33
|
-
groupInfo?: {
|
|
34
|
-
groupId: string;
|
|
35
|
-
type: string;
|
|
36
|
-
members?: string[];
|
|
37
|
-
name?: string;
|
|
38
|
-
avatarId?: number;
|
|
39
|
-
};
|
|
40
|
-
quote?: {
|
|
41
|
-
id: number;
|
|
42
|
-
author: string;
|
|
43
|
-
text?: string;
|
|
44
|
-
};
|
|
45
|
-
preview?: Array<{
|
|
46
|
-
url: string;
|
|
47
|
-
title: string;
|
|
48
|
-
description?: string;
|
|
49
|
-
}>;
|
|
50
|
-
sticker?: {
|
|
51
|
-
packId: string;
|
|
52
|
-
stickerId: number;
|
|
53
|
-
};
|
|
54
|
-
reaction?: {
|
|
55
|
-
emoji: string;
|
|
56
|
-
targetAuthor: string;
|
|
57
|
-
targetTimestamp: number;
|
|
58
|
-
};
|
|
59
|
-
viewOnce?: boolean;
|
|
60
|
-
};
|
|
61
|
-
syncMessage?: {
|
|
62
|
-
sentMessage?: {
|
|
63
|
-
destination: string;
|
|
64
|
-
timestamp: number;
|
|
65
|
-
message?: string;
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
receipt?: {
|
|
69
|
-
type: number;
|
|
70
|
-
timestamp: number;
|
|
71
|
-
timestamps: number[];
|
|
72
|
-
};
|
|
73
|
-
typing?: {
|
|
74
|
-
action: number;
|
|
75
|
-
timestamp: number;
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
account: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
interface ApprovalMapping {
|
|
82
|
-
flowRunId: string;
|
|
83
|
-
requestId: string;
|
|
84
|
-
approveEmoji: string;
|
|
85
|
-
disapproveEmoji: string;
|
|
86
|
-
targetAuthor: string;
|
|
87
|
-
messageTimestamp: number;
|
|
88
|
-
timeoutSeconds: number;
|
|
89
|
-
createdAt: number;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Function to automatically resume approval flows
|
|
93
|
-
export async function tryResumeApprovalFlow(
|
|
94
|
-
message: SignalMessage,
|
|
95
|
-
store: any,
|
|
96
|
-
apiUrl: string
|
|
97
|
-
): Promise<{ resumed: boolean; action?: string }> {
|
|
98
|
-
console.log('[ReceiveMessages] DEBUG - Processing message:', {
|
|
99
|
-
hasReaction: !!message.envelope?.dataMessage?.reaction,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Check if it's a reaction
|
|
103
|
-
if (!message.envelope?.dataMessage?.reaction) {
|
|
104
|
-
return { resumed: false };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
console.log('[ReceiveMessages] DEBUG - Reaction detected');
|
|
108
|
-
const reaction = message.envelope.dataMessage.reaction;
|
|
109
|
-
// Convert targetTimestamp from milliseconds to seconds (Unix timestamp)
|
|
110
|
-
// Note: targetTimestamp in SignalMessage interface might be targetSentTimestamp in actual data
|
|
111
|
-
const targetTimestampMs = (reaction as any).targetSentTimestamp || reaction.targetTimestamp;
|
|
112
|
-
const targetTimestamp = Math.floor(targetTimestampMs / 1000);
|
|
113
|
-
const targetAuthor = reaction.targetAuthor;
|
|
114
|
-
const reactionEmoji = reaction.emoji;
|
|
115
|
-
|
|
116
|
-
console.log('[ReceiveMessages] DEBUG - Reaction data:', {
|
|
117
|
-
targetSentTimestampOriginal: targetTimestampMs,
|
|
118
|
-
targetTimestamp,
|
|
119
|
-
targetAuthor,
|
|
120
|
-
reactionEmoji,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// Cleanup expired approvals
|
|
124
|
-
const keysListKey = 'approval:keys';
|
|
125
|
-
const existingKeys = (await store.get<string[]>(keysListKey, StoreScope.PROJECT)) || [];
|
|
126
|
-
const currentTimestamp = Math.floor(Date.now() / 1000);
|
|
127
|
-
const validKeys: string[] = [];
|
|
128
|
-
const keysToDelete: string[] = [];
|
|
129
|
-
|
|
130
|
-
console.log('[ReceiveMessages] DEBUG - Store info:', {
|
|
131
|
-
existingKeysCount: existingKeys.length,
|
|
132
|
-
existingKeys: existingKeys,
|
|
133
|
-
currentTimestamp,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
for (const key of existingKeys) {
|
|
137
|
-
const mapping = await store.get<ApprovalMapping>(key, StoreScope.PROJECT);
|
|
138
|
-
if (mapping) {
|
|
139
|
-
// Check if expired
|
|
140
|
-
if (currentTimestamp - mapping.createdAt > mapping.timeoutSeconds) {
|
|
141
|
-
// Expired - delete it and flowRunId mapping
|
|
142
|
-
await store.delete(key, StoreScope.PROJECT);
|
|
143
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
144
|
-
await store.delete(flowRunMappingKey, StoreScope.PROJECT);
|
|
145
|
-
keysToDelete.push(key);
|
|
146
|
-
} else {
|
|
147
|
-
validKeys.push(key);
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
// Mapping not found - remove from list
|
|
151
|
-
keysToDelete.push(key);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Update keys list if any were deleted
|
|
156
|
-
if (keysToDelete.length > 0) {
|
|
157
|
-
await store.put(keysListKey, validKeys, StoreScope.PROJECT);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
console.log('[ReceiveMessages] DEBUG - Cleanup result:', {
|
|
161
|
-
keysDeleted: keysToDelete.length,
|
|
162
|
-
validKeysCount: validKeys.length,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// Look up the specific approval mapping
|
|
166
|
-
const storeKey = `approval:${targetTimestamp}:${targetAuthor}`;
|
|
167
|
-
|
|
168
|
-
console.log('[ReceiveMessages] DEBUG - Store lookup:', {
|
|
169
|
-
storeKey,
|
|
170
|
-
existingKeysCount: existingKeys.length,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const mapping = await store.get<ApprovalMapping>(storeKey, StoreScope.PROJECT);
|
|
174
|
-
|
|
175
|
-
if (!mapping) {
|
|
176
|
-
// Not an approval message
|
|
177
|
-
console.log('[ReceiveMessages] DEBUG - No mapping found:', {
|
|
178
|
-
reason: 'not_an_approval_message',
|
|
179
|
-
searchedKey: storeKey,
|
|
180
|
-
});
|
|
181
|
-
return { resumed: false };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
console.log('[ReceiveMessages] DEBUG - Mapping found:', {
|
|
185
|
-
flowRunId: mapping.flowRunId,
|
|
186
|
-
requestId: mapping.requestId,
|
|
187
|
-
approveEmoji: mapping.approveEmoji,
|
|
188
|
-
disapproveEmoji: mapping.disapproveEmoji,
|
|
189
|
-
messageTimestamp: mapping.messageTimestamp,
|
|
190
|
-
createdAt: mapping.createdAt,
|
|
191
|
-
timeoutSeconds: mapping.timeoutSeconds,
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// Check if expired
|
|
195
|
-
const ageInSeconds = currentTimestamp - mapping.createdAt;
|
|
196
|
-
const isExpired = ageInSeconds > mapping.timeoutSeconds;
|
|
197
|
-
|
|
198
|
-
console.log('[ReceiveMessages] DEBUG - Expiration check:', {
|
|
199
|
-
currentTimestamp,
|
|
200
|
-
createdAt: mapping.createdAt,
|
|
201
|
-
ageInSeconds,
|
|
202
|
-
timeoutSeconds: mapping.timeoutSeconds,
|
|
203
|
-
isExpired,
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
if (isExpired) {
|
|
207
|
-
// Expired - delete and return
|
|
208
|
-
await store.delete(storeKey, StoreScope.PROJECT);
|
|
209
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
210
|
-
await store.delete(flowRunMappingKey, StoreScope.PROJECT);
|
|
211
|
-
const updatedKeys = validKeys.filter(key => key !== storeKey);
|
|
212
|
-
await store.put(keysListKey, updatedKeys, StoreScope.PROJECT);
|
|
213
|
-
console.log('[ReceiveMessages] DEBUG - Approval expired');
|
|
214
|
-
return { resumed: false };
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Check emoji and determine action
|
|
218
|
-
let action: string;
|
|
219
|
-
|
|
220
|
-
console.log('[ReceiveMessages] DEBUG - Emoji check:', {
|
|
221
|
-
receivedEmoji: reactionEmoji,
|
|
222
|
-
expectedApproveEmoji: mapping.approveEmoji,
|
|
223
|
-
expectedDisapproveEmoji: mapping.disapproveEmoji,
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
if (reactionEmoji === mapping.approveEmoji) {
|
|
227
|
-
action = 'approve';
|
|
228
|
-
console.log('[ReceiveMessages] DEBUG - Emoji matched: approve');
|
|
229
|
-
} else if (reactionEmoji === mapping.disapproveEmoji) {
|
|
230
|
-
action = 'disapprove';
|
|
231
|
-
console.log('[ReceiveMessages] DEBUG - Emoji matched: disapprove');
|
|
232
|
-
} else {
|
|
233
|
-
// Invalid emoji - not an approval reaction
|
|
234
|
-
console.log('[ReceiveMessages] DEBUG - Invalid emoji:', {
|
|
235
|
-
reason: 'invalid_emoji',
|
|
236
|
-
receivedEmoji: reactionEmoji,
|
|
237
|
-
});
|
|
238
|
-
return { resumed: false };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Make HTTP request to resume the flow
|
|
242
|
-
const resumeUrl = `${apiUrl}v1/flow-runs/${mapping.flowRunId}/requests/${mapping.requestId}?action=${action}`;
|
|
243
|
-
|
|
244
|
-
console.log('[ReceiveMessages] DEBUG - Attempting resume:', {
|
|
245
|
-
resumeUrl,
|
|
246
|
-
apiUrl,
|
|
247
|
-
flowRunId: mapping.flowRunId,
|
|
248
|
-
requestId: mapping.requestId,
|
|
249
|
-
action,
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
const response = await httpClient.sendRequest({
|
|
254
|
-
method: HttpMethod.POST,
|
|
255
|
-
url: resumeUrl,
|
|
256
|
-
headers: {
|
|
257
|
-
'Content-Type': 'application/json',
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
console.log('[ReceiveMessages] DEBUG - Resume successful:', {
|
|
262
|
-
flowRunId: mapping.flowRunId,
|
|
263
|
-
action,
|
|
264
|
-
responseStatus: response.status,
|
|
265
|
-
responseBody: response.body,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Delete mapping from Store (cleanup)
|
|
269
|
-
await store.delete(storeKey, StoreScope.PROJECT);
|
|
270
|
-
|
|
271
|
-
// Delete flowRunId mapping
|
|
272
|
-
const flowRunMappingKey = `approval:flowRun:${mapping.flowRunId}`;
|
|
273
|
-
await store.delete(flowRunMappingKey, StoreScope.PROJECT);
|
|
274
|
-
|
|
275
|
-
// Remove key from approval keys list
|
|
276
|
-
const finalKeys = validKeys.filter(key => key !== storeKey);
|
|
277
|
-
await store.put(keysListKey, finalKeys, StoreScope.PROJECT);
|
|
278
|
-
|
|
279
|
-
console.log('[ReceiveMessages] DEBUG - Cleanup completed');
|
|
280
|
-
|
|
281
|
-
return { resumed: true, action };
|
|
282
|
-
} catch (error) {
|
|
283
|
-
// If resume fails, log but don't throw - message will still be returned
|
|
284
|
-
console.error('[ReceiveMessages] DEBUG - Resume failed:', {
|
|
285
|
-
error: error instanceof Error ? error.message : String(error),
|
|
286
|
-
errorStack: error instanceof Error ? error.stack : undefined,
|
|
287
|
-
resumeUrl,
|
|
288
|
-
flowRunId: mapping.flowRunId,
|
|
289
|
-
reason: 'resume_failed',
|
|
290
|
-
});
|
|
291
|
-
return { resumed: false };
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// WebSocket receive function (for json-rpc mode)
|
|
296
|
-
export async function tryWebSocketReceive(
|
|
297
|
-
httpUrl: string,
|
|
298
|
-
headers: Record<string, string>,
|
|
299
|
-
timeout: number,
|
|
300
|
-
max_messages?: number
|
|
301
|
-
): Promise<SignalMessage[]> {
|
|
302
|
-
const wsUrl = httpUrl.replace(/^http:/, 'ws:').replace(/^https:/, 'wss:');
|
|
303
|
-
const wsHeaders: Record<string, string> = {
|
|
304
|
-
...headers,
|
|
305
|
-
'Connection': 'Upgrade',
|
|
306
|
-
'Upgrade': 'websocket',
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
return new Promise((resolve, reject) => {
|
|
310
|
-
const messages: SignalMessage[] = [];
|
|
311
|
-
let messageCount = 0;
|
|
312
|
-
const maxMessagesToCollect = max_messages || Infinity;
|
|
313
|
-
const timeoutMs = timeout * 1000;
|
|
314
|
-
let resolved = false;
|
|
315
|
-
|
|
316
|
-
const resolveOnce = (result: SignalMessage[]) => {
|
|
317
|
-
if (!resolved) {
|
|
318
|
-
resolved = true;
|
|
319
|
-
resolve(result);
|
|
320
|
-
}
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const rejectOnce = (error: Error) => {
|
|
324
|
-
if (!resolved) {
|
|
325
|
-
resolved = true;
|
|
326
|
-
reject(error);
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
const processMessages = () => {
|
|
331
|
-
// Filter messages that have dataMessage (actual message content)
|
|
332
|
-
return messages.filter((msg) => msg.envelope?.dataMessage);
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
const ws = new WebSocket(wsUrl, {
|
|
336
|
-
headers: wsHeaders,
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
const timeoutId = setTimeout(() => {
|
|
340
|
-
if (!resolved) {
|
|
341
|
-
ws.close();
|
|
342
|
-
resolveOnce(processMessages());
|
|
343
|
-
}
|
|
344
|
-
}, timeoutMs);
|
|
345
|
-
|
|
346
|
-
ws.on('open', () => {
|
|
347
|
-
// WebSocket connection opened successfully
|
|
348
|
-
// The server will send messages as they arrive
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
ws.on('message', (data: WebSocket.Data) => {
|
|
352
|
-
try {
|
|
353
|
-
const messageText = data.toString();
|
|
354
|
-
|
|
355
|
-
// Check if it's an error message
|
|
356
|
-
if (messageText.includes('"error"') || messageText.includes('"Msg"')) {
|
|
357
|
-
try {
|
|
358
|
-
const errorObj = JSON.parse(messageText);
|
|
359
|
-
if (errorObj.error || errorObj.Msg) {
|
|
360
|
-
clearTimeout(timeoutId);
|
|
361
|
-
ws.close();
|
|
362
|
-
// If it's a "no messages" type error, return empty array
|
|
363
|
-
if (errorObj.Msg && errorObj.Msg.includes('No new messages')) {
|
|
364
|
-
resolveOnce([]);
|
|
365
|
-
} else {
|
|
366
|
-
rejectOnce(new Error(errorObj.error || errorObj.Msg));
|
|
367
|
-
}
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
} catch {
|
|
371
|
-
// Not a JSON error, continue processing
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// Try to parse as JSON message
|
|
376
|
-
try {
|
|
377
|
-
const message: SignalMessage = JSON.parse(messageText);
|
|
378
|
-
messages.push(message);
|
|
379
|
-
messageCount++;
|
|
380
|
-
|
|
381
|
-
// If we've reached max_messages, close the connection
|
|
382
|
-
if (messageCount >= maxMessagesToCollect) {
|
|
383
|
-
clearTimeout(timeoutId);
|
|
384
|
-
ws.close();
|
|
385
|
-
resolveOnce(processMessages());
|
|
386
|
-
}
|
|
387
|
-
} catch (parseError) {
|
|
388
|
-
// If parsing fails, ignore this message
|
|
389
|
-
// The server might send non-JSON data
|
|
390
|
-
}
|
|
391
|
-
} catch (error) {
|
|
392
|
-
// Ignore individual message errors
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
ws.on('error', (error) => {
|
|
397
|
-
clearTimeout(timeoutId);
|
|
398
|
-
ws.close();
|
|
399
|
-
// Reject to trigger fallback to HTTP GET
|
|
400
|
-
rejectOnce(error);
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
ws.on('close', () => {
|
|
404
|
-
clearTimeout(timeoutId);
|
|
405
|
-
// If we haven't resolved yet, resolve with collected messages
|
|
406
|
-
if (!resolved) {
|
|
407
|
-
resolveOnce(processMessages());
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// HTTP GET receive function (for normal/native mode)
|
|
414
|
-
export async function tryHttpReceive(
|
|
415
|
-
httpUrl: string,
|
|
416
|
-
headers: Record<string, string>
|
|
417
|
-
): Promise<SignalMessage[]> {
|
|
418
|
-
try {
|
|
419
|
-
const response = await httpClient.sendRequest<SignalMessage[] | string>({
|
|
420
|
-
method: HttpMethod.GET,
|
|
421
|
-
url: httpUrl,
|
|
422
|
-
headers,
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
// The API returns either a JSON array of messages or a JSON string
|
|
426
|
-
let messages: SignalMessage[] = [];
|
|
427
|
-
if (typeof response.body === 'string') {
|
|
428
|
-
try {
|
|
429
|
-
messages = JSON.parse(response.body);
|
|
430
|
-
} catch {
|
|
431
|
-
// If parsing fails, try to parse as array
|
|
432
|
-
messages = [];
|
|
433
|
-
}
|
|
434
|
-
} else if (Array.isArray(response.body)) {
|
|
435
|
-
messages = response.body;
|
|
436
|
-
} else {
|
|
437
|
-
messages = [];
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Filter messages that have dataMessage (actual message content)
|
|
441
|
-
return messages.filter((msg) => msg.envelope?.dataMessage);
|
|
442
|
-
} catch (error) {
|
|
443
|
-
// If no messages are available, return empty array
|
|
444
|
-
if (error instanceof Error && error.message.includes('No new messages')) {
|
|
445
|
-
return [];
|
|
446
|
-
}
|
|
447
|
-
throw error;
|
|
448
|
-
}
|
|
449
|
-
}
|
package/src/lib/common/types.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
export interface SendMessageV2Request {
|
|
2
|
-
number: string;
|
|
3
|
-
recipients: string[];
|
|
4
|
-
message: string;
|
|
5
|
-
base64_attachments?: string[];
|
|
6
|
-
sticker?: string;
|
|
7
|
-
mentions?: MessageMention[];
|
|
8
|
-
quote_timestamp?: number;
|
|
9
|
-
quote_author?: string;
|
|
10
|
-
quote_message?: string;
|
|
11
|
-
quote_mentions?: MessageMention[];
|
|
12
|
-
text_mode?: 'normal' | 'styled';
|
|
13
|
-
edit_timestamp?: number;
|
|
14
|
-
notify_self?: boolean;
|
|
15
|
-
link_preview?: LinkPreviewType;
|
|
16
|
-
view_once?: boolean;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface MessageMention {
|
|
20
|
-
start: number;
|
|
21
|
-
length: number;
|
|
22
|
-
recipient: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface LinkPreviewType {
|
|
26
|
-
url: string;
|
|
27
|
-
title: string;
|
|
28
|
-
description?: string;
|
|
29
|
-
base64_thumbnail?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface GroupEntry {
|
|
33
|
-
id: string;
|
|
34
|
-
name: string;
|
|
35
|
-
description?: string;
|
|
36
|
-
members: string[];
|
|
37
|
-
admins: string[];
|
|
38
|
-
blocked: boolean;
|
|
39
|
-
permissions?: GroupPermissions;
|
|
40
|
-
group_link?: string;
|
|
41
|
-
expiration_time?: number;
|
|
42
|
-
pending_requests?: string[];
|
|
43
|
-
pending_invites?: string[];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface GroupPermissions {
|
|
47
|
-
add_members: 'every-member' | 'only-admins';
|
|
48
|
-
edit_group: 'every-member' | 'only-admins';
|
|
49
|
-
send_messages: 'every-member' | 'only-admins';
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface ContactEntry {
|
|
53
|
-
number: string;
|
|
54
|
-
name?: string;
|
|
55
|
-
expiration_in_seconds?: number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface IdentityEntry {
|
|
59
|
-
number: string;
|
|
60
|
-
trust_level: string;
|
|
61
|
-
added: string;
|
|
62
|
-
safety_number: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface SendMessageResponse {
|
|
66
|
-
timestamp: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface ErrorResponse {
|
|
70
|
-
error: string;
|
|
71
|
-
challenge_tokens?: string[];
|
|
72
|
-
account?: string;
|
|
73
|
-
}
|
package/src/lib/common/utils.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { Property, ApFile } from '@activepieces/pieces-framework';
|
|
2
|
-
import mime from 'mime-types';
|
|
3
|
-
|
|
4
|
-
export const commonProps = {
|
|
5
|
-
number: Property.ShortText({
|
|
6
|
-
displayName: 'Phone Number',
|
|
7
|
-
description: 'Registered phone number in international format (e.g., +43123456789). If not provided, uses the default number from the connection.',
|
|
8
|
-
required: false,
|
|
9
|
-
}),
|
|
10
|
-
recipients: Property.Array({
|
|
11
|
-
displayName: 'Recipients',
|
|
12
|
-
description: 'Array of phone numbers or group IDs',
|
|
13
|
-
required: true,
|
|
14
|
-
}),
|
|
15
|
-
message: Property.LongText({
|
|
16
|
-
displayName: 'Message',
|
|
17
|
-
description: 'Message text to send',
|
|
18
|
-
required: true,
|
|
19
|
-
}),
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Gets the phone number from props or connection default
|
|
24
|
-
*/
|
|
25
|
-
export function getPhoneNumber(
|
|
26
|
-
numberFromProps: string | undefined,
|
|
27
|
-
defaultNumberFromConnection: string | undefined
|
|
28
|
-
): string {
|
|
29
|
-
const phoneNumber = numberFromProps || defaultNumberFromConnection;
|
|
30
|
-
if (!phoneNumber) {
|
|
31
|
-
throw new Error('Phone number is required. Please provide it in the action or set a default in the connection settings.');
|
|
32
|
-
}
|
|
33
|
-
return formatPhoneNumber(phoneNumber);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function validatePhoneNumber(number: string): boolean {
|
|
37
|
-
// Basic validation for international phone number format
|
|
38
|
-
// Should start with + and contain only digits after that
|
|
39
|
-
return /^\+[1-9]\d{1,14}$/.test(number);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function formatPhoneNumber(number: string): string {
|
|
43
|
-
// Remove any spaces, dashes, or parentheses
|
|
44
|
-
const cleaned = number.replace(/[\s\-\(\)]/g, '');
|
|
45
|
-
// Ensure it starts with +
|
|
46
|
-
if (!cleaned.startsWith('+')) {
|
|
47
|
-
return '+' + cleaned;
|
|
48
|
-
}
|
|
49
|
-
return cleaned;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Converts a file data URL or base64 string to a format suitable for the API
|
|
54
|
-
* Supports:
|
|
55
|
-
* - Base64 strings (with or without data URL prefix)
|
|
56
|
-
* - Data URLs (data:mime/type;base64,base64data)
|
|
57
|
-
* - File data URLs with filename (data:mime/type;filename=name;base64,base64data)
|
|
58
|
-
*/
|
|
59
|
-
export function normalizeBase64Attachment(
|
|
60
|
-
attachment: string
|
|
61
|
-
): string {
|
|
62
|
-
// If it's already a plain base64 string, return as is
|
|
63
|
-
if (!attachment.includes(',')) {
|
|
64
|
-
return attachment;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// If it's a data URL, extract the base64 part
|
|
68
|
-
if (attachment.startsWith('data:')) {
|
|
69
|
-
const parts = attachment.split(',');
|
|
70
|
-
if (parts.length === 2) {
|
|
71
|
-
// Extract mime type and other metadata from the first part
|
|
72
|
-
const header = parts[0];
|
|
73
|
-
const base64Data = parts[1];
|
|
74
|
-
|
|
75
|
-
// Check if it has filename
|
|
76
|
-
if (header.includes('filename=')) {
|
|
77
|
-
// Format: data:mime/type;filename=name;base64,data
|
|
78
|
-
return attachment;
|
|
79
|
-
} else if (header.includes('base64')) {
|
|
80
|
-
// Format: data:mime/type;base64,data
|
|
81
|
-
return attachment;
|
|
82
|
-
} else {
|
|
83
|
-
// Just base64 data, add data URL prefix
|
|
84
|
-
const mimeType = header.replace('data:', '').split(';')[0] || 'application/octet-stream';
|
|
85
|
-
return `data:${mimeType};base64,${base64Data}`;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return attachment;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Converts file data to base64 string
|
|
95
|
-
*/
|
|
96
|
-
export async function fileToBase64(file: File | Blob): Promise<string> {
|
|
97
|
-
return new Promise((resolve, reject) => {
|
|
98
|
-
const reader = new FileReader();
|
|
99
|
-
reader.onload = () => {
|
|
100
|
-
const result = reader.result as string;
|
|
101
|
-
resolve(result);
|
|
102
|
-
};
|
|
103
|
-
reader.onerror = reject;
|
|
104
|
-
reader.readAsDataURL(file);
|
|
105
|
-
});
|
|
106
|
-
}
|