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.
Files changed (179) hide show
  1. package/package.json +26 -4
  2. package/src/index.d.ts +8 -0
  3. package/src/index.js +90 -0
  4. package/src/index.js.map +1 -0
  5. package/src/lib/actions/add-admins-to-group.d.ts +12 -0
  6. package/src/lib/actions/add-admins-to-group.js +45 -0
  7. package/src/lib/actions/add-admins-to-group.js.map +1 -0
  8. package/src/lib/actions/add-device.d.ts +11 -0
  9. package/src/lib/actions/add-device.js +40 -0
  10. package/src/lib/actions/add-device.js.map +1 -0
  11. package/src/lib/actions/add-members-to-group.d.ts +12 -0
  12. package/src/lib/actions/add-members-to-group.js +45 -0
  13. package/src/lib/actions/add-members-to-group.js.map +1 -0
  14. package/src/lib/actions/block-group.d.ts +11 -0
  15. package/src/lib/actions/block-group.js +37 -0
  16. package/src/lib/actions/block-group.js.map +1 -0
  17. package/src/lib/actions/create-group.d.ts +18 -0
  18. package/src/lib/actions/create-group.js +117 -0
  19. package/src/lib/actions/create-group.js.map +1 -0
  20. package/src/lib/actions/delete-group.d.ts +11 -0
  21. package/src/lib/actions/delete-group.js +37 -0
  22. package/src/lib/actions/delete-group.js.map +1 -0
  23. package/src/lib/actions/get-contact.d.ts +11 -0
  24. package/src/lib/actions/get-contact.js +37 -0
  25. package/src/lib/actions/get-contact.js.map +1 -0
  26. package/src/lib/actions/get-group.d.ts +11 -0
  27. package/src/lib/actions/get-group.js +37 -0
  28. package/src/lib/actions/get-group.js.map +1 -0
  29. package/src/lib/actions/get-qr-code-link.d.ts +11 -0
  30. package/src/lib/actions/get-qr-code-link.js +60 -0
  31. package/src/lib/actions/get-qr-code-link.js.map +1 -0
  32. package/src/lib/actions/join-group.d.ts +11 -0
  33. package/src/lib/actions/join-group.js +37 -0
  34. package/src/lib/actions/join-group.js.map +1 -0
  35. package/src/lib/actions/list-accounts.d.ts +8 -0
  36. package/src/lib/actions/list-accounts.js +23 -0
  37. package/src/lib/actions/list-accounts.js.map +1 -0
  38. package/src/lib/actions/list-attachments.d.ts +8 -0
  39. package/src/lib/actions/list-attachments.js +23 -0
  40. package/src/lib/actions/list-attachments.js.map +1 -0
  41. package/src/lib/actions/list-contacts.d.ts +10 -0
  42. package/src/lib/actions/list-contacts.js +32 -0
  43. package/src/lib/actions/list-contacts.js.map +1 -0
  44. package/src/lib/actions/list-devices.d.ts +10 -0
  45. package/src/lib/actions/list-devices.js +32 -0
  46. package/src/lib/actions/list-devices.js.map +1 -0
  47. package/src/lib/actions/list-groups.d.ts +10 -0
  48. package/src/lib/actions/list-groups.js +32 -0
  49. package/src/lib/actions/list-groups.js.map +1 -0
  50. package/src/lib/actions/list-identities.d.ts +10 -0
  51. package/src/lib/actions/list-identities.js +32 -0
  52. package/src/lib/actions/list-identities.js.map +1 -0
  53. package/src/lib/actions/quit-group.d.ts +11 -0
  54. package/src/lib/actions/quit-group.js +37 -0
  55. package/src/lib/actions/quit-group.js.map +1 -0
  56. package/src/lib/actions/receive-messages.d.ts +15 -0
  57. package/src/lib/actions/receive-messages.js +100 -0
  58. package/src/lib/actions/receive-messages.js.map +1 -0
  59. package/src/lib/actions/remote-delete-message.d.ts +12 -0
  60. package/src/lib/actions/remote-delete-message.js +46 -0
  61. package/src/lib/actions/remote-delete-message.js.map +1 -0
  62. package/src/lib/actions/remove-admins-from-group.d.ts +12 -0
  63. package/src/lib/actions/remove-admins-from-group.js +45 -0
  64. package/src/lib/actions/remove-admins-from-group.js.map +1 -0
  65. package/src/lib/actions/remove-device.d.ts +11 -0
  66. package/src/lib/actions/remove-device.js +37 -0
  67. package/src/lib/actions/remove-device.js.map +1 -0
  68. package/src/lib/actions/remove-members-from-group.d.ts +12 -0
  69. package/src/lib/actions/remove-members-from-group.js +45 -0
  70. package/src/lib/actions/remove-members-from-group.js.map +1 -0
  71. package/src/lib/actions/remove-reaction.d.ts +13 -0
  72. package/src/lib/actions/remove-reaction.js +52 -0
  73. package/src/lib/actions/remove-reaction.js.map +1 -0
  74. package/src/lib/actions/request-approval-message.d.ts +15 -0
  75. package/src/lib/actions/request-approval-message.js +184 -0
  76. package/src/lib/actions/request-approval-message.js.map +1 -0
  77. package/src/lib/actions/resume-approval-flow.d.ts +11 -0
  78. package/src/lib/actions/resume-approval-flow.js +181 -0
  79. package/src/lib/actions/resume-approval-flow.js.map +1 -0
  80. package/src/lib/actions/search-numbers.d.ts +11 -0
  81. package/src/lib/actions/search-numbers.js +42 -0
  82. package/src/lib/actions/search-numbers.js.map +1 -0
  83. package/src/lib/actions/send-message.d.ts +27 -0
  84. package/src/lib/actions/send-message.js +176 -0
  85. package/src/lib/actions/send-message.js.map +1 -0
  86. package/src/lib/actions/send-reaction.d.ts +14 -0
  87. package/src/lib/actions/send-reaction.js +58 -0
  88. package/src/lib/actions/send-reaction.js.map +1 -0
  89. package/src/lib/actions/send-receipt.d.ts +13 -0
  90. package/src/lib/actions/send-receipt.js +58 -0
  91. package/src/lib/actions/send-receipt.js.map +1 -0
  92. package/src/lib/actions/start-typing.d.ts +11 -0
  93. package/src/lib/actions/start-typing.js +40 -0
  94. package/src/lib/actions/start-typing.js.map +1 -0
  95. package/src/lib/actions/stop-typing.d.ts +11 -0
  96. package/src/lib/actions/stop-typing.js +40 -0
  97. package/src/lib/actions/stop-typing.js.map +1 -0
  98. package/src/lib/actions/sync-contacts.d.ts +10 -0
  99. package/src/lib/actions/sync-contacts.js +32 -0
  100. package/src/lib/actions/sync-contacts.js.map +1 -0
  101. package/src/lib/actions/update-account-settings.d.ts +12 -0
  102. package/src/lib/actions/update-account-settings.js +49 -0
  103. package/src/lib/actions/update-account-settings.js.map +1 -0
  104. package/src/lib/actions/update-contact.d.ts +13 -0
  105. package/src/lib/actions/update-contact.js +56 -0
  106. package/src/lib/actions/update-contact.js.map +1 -0
  107. package/src/lib/actions/update-group.d.ts +19 -0
  108. package/src/lib/actions/update-group.js +125 -0
  109. package/src/lib/actions/update-group.js.map +1 -0
  110. package/src/lib/actions/update-profile.d.ts +13 -0
  111. package/src/lib/actions/update-profile.js +56 -0
  112. package/src/lib/actions/update-profile.js.map +1 -0
  113. package/src/lib/common/api-client.d.ts +24 -0
  114. package/src/lib/common/api-client.js +103 -0
  115. package/src/lib/common/api-client.js.map +1 -0
  116. package/src/lib/common/auth.d.ts +8 -0
  117. package/src/lib/common/auth.js +68 -0
  118. package/src/lib/common/auth.js.map +1 -0
  119. package/src/lib/common/message-utils.d.ts +81 -0
  120. package/src/lib/common/message-utils.js +327 -0
  121. package/src/lib/common/message-utils.js.map +1 -0
  122. package/src/lib/common/types.d.ts +65 -0
  123. package/src/lib/common/types.js +3 -0
  124. package/src/lib/common/types.js.map +1 -0
  125. package/src/lib/common/utils.d.ts +23 -0
  126. package/src/lib/common/utils.js +105 -0
  127. package/src/lib/common/utils.js.map +1 -0
  128. package/src/lib/triggers/new-group-member.d.ts +50 -0
  129. package/src/lib/triggers/new-group-member.js +155 -0
  130. package/src/lib/triggers/new-group-member.js.map +1 -0
  131. package/src/lib/triggers/new-message-received.d.ts +58 -0
  132. package/src/lib/triggers/new-message-received.js +469 -0
  133. package/src/lib/triggers/new-message-received.js.map +1 -0
  134. package/project.json +0 -58
  135. package/src/index.ts +0 -87
  136. package/src/lib/actions/add-admins-to-group.ts +0 -50
  137. package/src/lib/actions/add-device.ts +0 -45
  138. package/src/lib/actions/add-members-to-group.ts +0 -50
  139. package/src/lib/actions/block-group.ts +0 -36
  140. package/src/lib/actions/create-group.ts +0 -139
  141. package/src/lib/actions/delete-group.ts +0 -36
  142. package/src/lib/actions/get-contact.ts +0 -42
  143. package/src/lib/actions/get-group.ts +0 -37
  144. package/src/lib/actions/get-qr-code-link.ts +0 -62
  145. package/src/lib/actions/join-group.ts +0 -36
  146. package/src/lib/actions/list-accounts.ts +0 -20
  147. package/src/lib/actions/list-attachments.ts +0 -20
  148. package/src/lib/actions/list-contacts.ts +0 -37
  149. package/src/lib/actions/list-devices.ts +0 -38
  150. package/src/lib/actions/list-groups.ts +0 -32
  151. package/src/lib/actions/list-identities.ts +0 -32
  152. package/src/lib/actions/quit-group.ts +0 -36
  153. package/src/lib/actions/receive-messages.ts +0 -108
  154. package/src/lib/actions/remote-delete-message.ts +0 -56
  155. package/src/lib/actions/remove-admins-from-group.ts +0 -50
  156. package/src/lib/actions/remove-device.ts +0 -36
  157. package/src/lib/actions/remove-members-from-group.ts +0 -50
  158. package/src/lib/actions/remove-reaction.ts +0 -59
  159. package/src/lib/actions/request-approval-message.ts +0 -215
  160. package/src/lib/actions/search-numbers.ts +0 -47
  161. package/src/lib/actions/send-message.ts +0 -189
  162. package/src/lib/actions/send-reaction.ts +0 -66
  163. package/src/lib/actions/send-receipt.ts +0 -65
  164. package/src/lib/actions/start-typing.ts +0 -45
  165. package/src/lib/actions/stop-typing.ts +0 -45
  166. package/src/lib/actions/sync-contacts.ts +0 -31
  167. package/src/lib/actions/update-account-settings.ts +0 -57
  168. package/src/lib/actions/update-contact.ts +0 -65
  169. package/src/lib/actions/update-group.ts +0 -145
  170. package/src/lib/actions/update-profile.ts +0 -65
  171. package/src/lib/common/api-client.ts +0 -150
  172. package/src/lib/common/auth.ts +0 -66
  173. package/src/lib/common/message-utils.ts +0 -449
  174. package/src/lib/common/types.ts +0 -73
  175. package/src/lib/common/utils.ts +0 -106
  176. package/src/lib/triggers/new-group-member.ts +0 -176
  177. package/src/lib/triggers/new-message-received.ts +0 -618
  178. package/tsconfig.json +0 -19
  179. package/tsconfig.lib.json +0 -11
@@ -1,32 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { GroupEntry } from '../common/types';
5
- import { formatPhoneNumber } from '../common/utils';
6
-
7
- export const listGroups = createAction({
8
- auth: signalCliRestApiAuth,
9
- name: 'listGroups',
10
- displayName: 'List Groups',
11
- description: 'List all Signal groups for a registered number',
12
- props: {
13
- number: Property.ShortText({
14
- displayName: 'Phone Number',
15
- description: 'Registered phone number in international format',
16
- required: true,
17
- }),
18
- },
19
- async run(context) {
20
- const { number } = context.propsValue;
21
- // Auth props are passed directly to API client
22
-
23
- const apiClient = new SignalCliApiClient(context.auth.props);
24
- const formattedNumber = formatPhoneNumber(number);
25
-
26
- const response = await apiClient.get<GroupEntry[]>(
27
- `/v1/groups/${encodeURIComponent(formattedNumber)}`
28
- );
29
-
30
- return response;
31
- },
32
- });
@@ -1,32 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { IdentityEntry } from '../common/types';
5
- import { formatPhoneNumber } from '../common/utils';
6
-
7
- export const listIdentities = createAction({
8
- auth: signalCliRestApiAuth,
9
- name: 'listIdentities',
10
- displayName: 'List Identities',
11
- description: 'List all identities for a registered number',
12
- props: {
13
- number: Property.ShortText({
14
- displayName: 'Phone Number',
15
- description: 'Registered phone number in international format',
16
- required: true,
17
- }),
18
- },
19
- async run(context) {
20
- const { number } = context.propsValue;
21
- // Auth props are passed directly to API client
22
-
23
- const apiClient = new SignalCliApiClient(context.auth.props);
24
- const formattedNumber = formatPhoneNumber(number);
25
-
26
- const response = await apiClient.get<IdentityEntry[]>(
27
- `/v1/identities/${encodeURIComponent(formattedNumber)}`
28
- );
29
-
30
- return response;
31
- },
32
- });
@@ -1,36 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { formatPhoneNumber } from '../common/utils';
5
-
6
- export const quitGroup = createAction({
7
- auth: signalCliRestApiAuth,
8
- name: 'quitGroup',
9
- displayName: 'Quit Group',
10
- description: 'Quit a Signal group',
11
- props: {
12
- number: Property.ShortText({
13
- displayName: 'Phone Number',
14
- description: 'Registered phone number in international format',
15
- required: true,
16
- }),
17
- groupid: Property.ShortText({
18
- displayName: 'Group ID',
19
- description: 'Group ID (base64 encoded)',
20
- required: true,
21
- }),
22
- },
23
- async run(context) {
24
- const { number, groupid } = context.propsValue;
25
- // Auth props are passed directly to API client
26
-
27
- const apiClient = new SignalCliApiClient(context.auth.props);
28
- const formattedNumber = formatPhoneNumber(number);
29
-
30
- await apiClient.post(
31
- `/v1/groups/${encodeURIComponent(formattedNumber)}/${encodeURIComponent(groupid)}/quit`
32
- );
33
-
34
- return { success: true };
35
- },
36
- });
@@ -1,108 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { formatPhoneNumber } from '../common/utils';
4
- import {
5
- tryWebSocketReceive,
6
- tryHttpReceive,
7
- tryResumeApprovalFlow,
8
- SignalMessage,
9
- } from '../common/message-utils';
10
-
11
- export const receiveMessages = createAction({
12
- auth: signalCliRestApiAuth,
13
- name: 'receiveMessages',
14
- displayName: 'Receive Messages',
15
- description: 'Receive new messages from Signal. Automatically resumes approval flows if a message is a reaction to an approval request. Can be called manually, e.g., from a webhook or scheduler.',
16
- props: {
17
- number: Property.ShortText({
18
- displayName: 'Phone Number',
19
- description: 'Registered phone number in international format (e.g., +43123456789)',
20
- required: true,
21
- }),
22
- timeout: Property.Number({
23
- displayName: 'Timeout (seconds)',
24
- description: 'Receive timeout in seconds (default: 1)',
25
- required: false,
26
- defaultValue: 1,
27
- }),
28
- ignore_attachments: Property.Checkbox({
29
- displayName: 'Ignore Attachments',
30
- description: 'Ignore attachments when receiving messages',
31
- required: false,
32
- defaultValue: false,
33
- }),
34
- ignore_stories: Property.Checkbox({
35
- displayName: 'Ignore Stories',
36
- description: 'Ignore stories when receiving messages',
37
- required: false,
38
- defaultValue: false,
39
- }),
40
- max_messages: Property.Number({
41
- displayName: 'Max Messages',
42
- description: 'Maximum number of messages to receive (default: unlimited)',
43
- required: false,
44
- }),
45
- send_read_receipts: Property.Checkbox({
46
- displayName: 'Send Read Receipts',
47
- description: 'Automatically send read receipts when receiving messages',
48
- required: false,
49
- defaultValue: false,
50
- }),
51
- },
52
- async run(context) {
53
- const { baseUrl, useBasicAuth, basicAuthUsername, basicAuthPassword, mode = 'normal' } = context.auth.props;
54
- const { number, timeout = 1, ignore_attachments = false, ignore_stories = false, max_messages, send_read_receipts = false } = context.propsValue;
55
-
56
- const formattedNumber = formatPhoneNumber(number);
57
-
58
- // Build query parameters
59
- const queryParams = new URLSearchParams();
60
- queryParams.append('timeout', timeout.toString());
61
- queryParams.append('ignore_attachments', ignore_attachments.toString());
62
- queryParams.append('ignore_stories', ignore_stories.toString());
63
- if (max_messages) {
64
- queryParams.append('max_messages', max_messages.toString());
65
- }
66
- queryParams.append('send_read_receipts', send_read_receipts.toString());
67
-
68
- const baseUrlClean = baseUrl.replace(/\/$/, '');
69
- const httpUrl = `${baseUrlClean}/v1/receive/${encodeURIComponent(formattedNumber)}?${queryParams.toString()}`;
70
-
71
- // Build headers
72
- const headers: Record<string, string> = {};
73
-
74
- // Add Basic Auth header if configured
75
- if (useBasicAuth && basicAuthUsername && basicAuthPassword) {
76
- const credentials = Buffer.from(
77
- `${basicAuthUsername}:${basicAuthPassword}`
78
- ).toString('base64');
79
- headers['Authorization'] = `Basic ${credentials}`;
80
- }
81
-
82
- // Use the configured mode to determine which method to use
83
- let messages: SignalMessage[];
84
- if (mode === 'json-rpc') {
85
- // Use WebSocket for json-rpc mode
86
- messages = await tryWebSocketReceive(httpUrl, headers, timeout, max_messages);
87
- } else {
88
- // Use HTTP GET for normal/native mode
89
- messages = await tryHttpReceive(httpUrl, headers);
90
- }
91
-
92
- // Process each message: try to resume approval flows if applicable
93
- // Messages are still returned regardless of whether they triggered a resume
94
- // Debug information is output via console.log (visible in Docker logs)
95
- const apiUrl = context.server?.apiUrl || '';
96
-
97
- for (const message of messages) {
98
- // This will output debug info via console.log
99
- await tryResumeApprovalFlow(message, context.store, apiUrl);
100
- }
101
-
102
- // Return messages
103
- return {
104
- messages,
105
- count: messages.length,
106
- };
107
- },
108
- });
@@ -1,56 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { formatPhoneNumber } from '../common/utils';
5
-
6
- interface RemoteDeleteRequest {
7
- recipient: string;
8
- timestamp: number;
9
- }
10
-
11
- interface RemoteDeleteResponse {
12
- timestamp: string;
13
- }
14
-
15
- export const remoteDeleteMessage = createAction({
16
- auth: signalCliRestApiAuth,
17
- name: 'remoteDeleteMessage',
18
- displayName: 'Remote Delete Message',
19
- description: 'Delete a message remotely',
20
- props: {
21
- number: Property.ShortText({
22
- displayName: 'Phone Number',
23
- description: 'Registered phone number in international format',
24
- required: true,
25
- }),
26
- recipient: Property.ShortText({
27
- displayName: 'Recipient',
28
- description: 'Phone number or group ID of the recipient',
29
- required: true,
30
- }),
31
- timestamp: Property.Number({
32
- displayName: 'Timestamp',
33
- description: 'Timestamp of the message to delete',
34
- required: true,
35
- }),
36
- },
37
- async run(context) {
38
- const { number, recipient, timestamp } = context.propsValue;
39
- // Auth props are passed directly to API client
40
-
41
- const apiClient = new SignalCliApiClient(context.auth.props);
42
- const formattedNumber = formatPhoneNumber(number);
43
-
44
- const requestBody: RemoteDeleteRequest = {
45
- recipient,
46
- timestamp,
47
- };
48
-
49
- const response = await apiClient.delete<RemoteDeleteResponse>(
50
- `/v1/remote-delete/${encodeURIComponent(formattedNumber)}`,
51
- requestBody
52
- );
53
-
54
- return response;
55
- },
56
- });
@@ -1,50 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { formatPhoneNumber } from '../common/utils';
5
-
6
- interface ChangeGroupAdminsRequest {
7
- admins: string[];
8
- }
9
-
10
- export const removeAdminsFromGroup = createAction({
11
- auth: signalCliRestApiAuth,
12
- name: 'removeAdminsFromGroup',
13
- displayName: 'Remove Admins from Group',
14
- description: 'Remove one or more admins from a Signal group',
15
- props: {
16
- number: Property.ShortText({
17
- displayName: 'Phone Number',
18
- description: 'Registered phone number in international format',
19
- required: true,
20
- }),
21
- groupid: Property.ShortText({
22
- displayName: 'Group ID',
23
- description: 'Group ID (base64 encoded)',
24
- required: true,
25
- }),
26
- admins: Property.Array({
27
- displayName: 'Admins',
28
- description: 'Array of phone numbers to remove as admins',
29
- required: true,
30
- }),
31
- },
32
- async run(context) {
33
- const { number, groupid, admins } = context.propsValue;
34
- // Auth props are passed directly to API client
35
-
36
- const apiClient = new SignalCliApiClient(context.auth.props);
37
- const formattedNumber = formatPhoneNumber(number);
38
-
39
- const requestBody: ChangeGroupAdminsRequest = {
40
- admins: admins as string[],
41
- };
42
-
43
- await apiClient.delete(
44
- `/v1/groups/${encodeURIComponent(formattedNumber)}/${encodeURIComponent(groupid)}/admins`,
45
- requestBody
46
- );
47
-
48
- return { success: true };
49
- },
50
- });
@@ -1,36 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { formatPhoneNumber } from '../common/utils';
5
-
6
- export const removeDevice = createAction({
7
- auth: signalCliRestApiAuth,
8
- name: 'removeDevice',
9
- displayName: 'Remove Device',
10
- description: 'Remove a linked device from the primary account',
11
- props: {
12
- number: Property.ShortText({
13
- displayName: 'Phone Number',
14
- description: 'Registered phone number in international format',
15
- required: true,
16
- }),
17
- deviceId: Property.Number({
18
- displayName: 'Device ID',
19
- description: 'Device ID from listDevices',
20
- required: true,
21
- }),
22
- },
23
- async run(context) {
24
- const { number, deviceId } = context.propsValue;
25
- // Auth props are passed directly to API client
26
-
27
- const apiClient = new SignalCliApiClient(context.auth.props);
28
- const formattedNumber = formatPhoneNumber(number);
29
-
30
- await apiClient.delete(
31
- `/v1/devices/${encodeURIComponent(formattedNumber)}/${deviceId}`
32
- );
33
-
34
- return { success: true };
35
- },
36
- });
@@ -1,50 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { formatPhoneNumber } from '../common/utils';
5
-
6
- interface ChangeGroupMembersRequest {
7
- members: string[];
8
- }
9
-
10
- export const removeMembersFromGroup = createAction({
11
- auth: signalCliRestApiAuth,
12
- name: 'removeMembersFromGroup',
13
- displayName: 'Remove Members from Group',
14
- description: 'Remove one or more members from a Signal group',
15
- props: {
16
- number: Property.ShortText({
17
- displayName: 'Phone Number',
18
- description: 'Registered phone number in international format',
19
- required: true,
20
- }),
21
- groupid: Property.ShortText({
22
- displayName: 'Group ID',
23
- description: 'Group ID (base64 encoded)',
24
- required: true,
25
- }),
26
- members: Property.Array({
27
- displayName: 'Members',
28
- description: 'Array of phone numbers to remove',
29
- required: true,
30
- }),
31
- },
32
- async run(context) {
33
- const { number, groupid, members } = context.propsValue;
34
- // Auth props are passed directly to API client
35
-
36
- const apiClient = new SignalCliApiClient(context.auth.props);
37
- const formattedNumber = formatPhoneNumber(number);
38
-
39
- const requestBody: ChangeGroupMembersRequest = {
40
- members: members as string[],
41
- };
42
-
43
- await apiClient.delete(
44
- `/v1/groups/${encodeURIComponent(formattedNumber)}/${encodeURIComponent(groupid)}/members`,
45
- requestBody
46
- );
47
-
48
- return { success: true };
49
- },
50
- });
@@ -1,59 +0,0 @@
1
- import { createAction, Property } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { formatPhoneNumber } from '../common/utils';
5
-
6
- interface ReactionRequest {
7
- recipient: string;
8
- target_author: string;
9
- timestamp: number;
10
- }
11
-
12
- export const removeReaction = createAction({
13
- auth: signalCliRestApiAuth,
14
- name: 'removeReaction',
15
- displayName: 'Remove Reaction',
16
- description: 'Remove a reaction from a message',
17
- props: {
18
- number: Property.ShortText({
19
- displayName: 'Phone Number',
20
- description: 'Registered phone number in international format',
21
- required: true,
22
- }),
23
- recipient: Property.ShortText({
24
- displayName: 'Recipient',
25
- description: 'Phone number or group ID of the recipient',
26
- required: true,
27
- }),
28
- target_author: Property.ShortText({
29
- displayName: 'Target Author',
30
- description: 'Phone number of the message author',
31
- required: true,
32
- }),
33
- timestamp: Property.Number({
34
- displayName: 'Timestamp',
35
- description: 'Timestamp of the message',
36
- required: true,
37
- }),
38
- },
39
- async run(context) {
40
- const { number, recipient, target_author, timestamp } = context.propsValue;
41
- // Auth props are passed directly to API client
42
-
43
- const apiClient = new SignalCliApiClient(context.auth.props);
44
- const formattedNumber = formatPhoneNumber(number);
45
-
46
- const requestBody: ReactionRequest = {
47
- recipient,
48
- target_author,
49
- timestamp,
50
- };
51
-
52
- await apiClient.delete(
53
- `/v1/reactions/${encodeURIComponent(formattedNumber)}`,
54
- requestBody
55
- );
56
-
57
- return { success: true };
58
- },
59
- });
@@ -1,215 +0,0 @@
1
- import { createAction, Property, StoreScope } from '@activepieces/pieces-framework';
2
- import { signalCliRestApiAuth } from '../common/auth';
3
- import { SignalCliApiClient } from '../common/api-client';
4
- import { SendMessageV2Request, SendMessageResponse } from '../common/types';
5
- import { formatPhoneNumber, commonProps } from '../common/utils';
6
- import { ExecutionType, PauseType } from '@activepieces/shared';
7
- import { assertNotNullOrUndefined } from '@activepieces/shared';
8
-
9
- interface ApprovalMapping {
10
- flowRunId: string;
11
- requestId: string;
12
- approveEmoji: string;
13
- disapproveEmoji: string;
14
- targetAuthor: string;
15
- messageTimestamp: number;
16
- timeoutSeconds: number;
17
- createdAt: number;
18
- }
19
-
20
- export const requestApprovalMessage = createAction({
21
- auth: signalCliRestApiAuth,
22
- name: 'request_approval_message',
23
- displayName: 'Request Approval (Signal)',
24
- description: 'Send an approval message via Signal and wait for a reaction response. This action sends a message and pauses the flow until the recipient reacts with an approve or disapprove emoji.',
25
- props: {
26
- number: Property.ShortText({
27
- displayName: 'Phone Number',
28
- description: 'Registered phone number in international format (e.g., +43123456789). If not provided, uses the default number from the connection.',
29
- required: false,
30
- }),
31
- recipients: commonProps.recipients,
32
- message: commonProps.message,
33
- approve_emoji: Property.ShortText({
34
- displayName: 'Approve Emoji',
35
- description: 'Emoji for approval (e.g., 👍)',
36
- required: false,
37
- defaultValue: '👍',
38
- }),
39
- disapprove_emoji: Property.ShortText({
40
- displayName: 'Disapprove Emoji',
41
- description: 'Emoji for disapproval (e.g., 👎)',
42
- required: false,
43
- defaultValue: '👎',
44
- }),
45
- timeout_seconds: Property.Number({
46
- displayName: 'Timeout (seconds)',
47
- description: 'Timeout in seconds after which the approval expires (default: 86400 = 24 hours)',
48
- required: false,
49
- defaultValue: 86400,
50
- }),
51
- },
52
- async run(context) {
53
- if (context.executionType === ExecutionType.BEGIN) {
54
- const { number, recipients, message, approve_emoji = '👍', disapprove_emoji = '👎', timeout_seconds = 86400 } = context.propsValue;
55
-
56
- assertNotNullOrUndefined(message, 'message');
57
- assertNotNullOrUndefined(recipients, 'recipients');
58
-
59
- const apiClient = new SignalCliApiClient(context.auth.props);
60
-
61
- // Use number from props or fallback to default from connection
62
- const phoneNumber = number || context.auth.props.defaultNumber;
63
- if (!phoneNumber) {
64
- throw new Error('Phone number is required. Please provide it in the action or set a default in the connection settings.');
65
- }
66
-
67
- const formattedNumber = formatPhoneNumber(phoneNumber);
68
-
69
- // Generate resume URL to extract requestId
70
- const resumeUrl = context.generateResumeUrl({
71
- queryParams: { action: 'approve' },
72
- });
73
-
74
- // Extract requestId from URL: /v1/flow-runs/{flowRunId}/requests/{requestId}
75
- const urlMatch = resumeUrl.match(/\/flow-runs\/[^/]+\/requests\/([^/?]+)/);
76
- if (!urlMatch || !urlMatch[1]) {
77
- throw new Error('Failed to extract requestId from resume URL');
78
- }
79
- const requestId = urlMatch[1];
80
-
81
- // Prepare request body - send message exactly as user entered it
82
- const requestBody: SendMessageV2Request = {
83
- number: formattedNumber,
84
- recipients: recipients as string[],
85
- message: message || '',
86
- };
87
-
88
- // Send the message
89
- const response = await apiClient.post<SendMessageResponse>('/v2/send', requestBody);
90
-
91
- // Extract messageTimestamp from response
92
- // Signal API returns timestamp in milliseconds as a string, convert to seconds (Unix timestamp)
93
- const timestampMs = typeof response.timestamp === 'string'
94
- ? parseInt(response.timestamp, 10)
95
- : Math.floor(response.timestamp);
96
- const messageTimestamp = Math.floor(timestampMs / 1000); // Convert milliseconds to seconds
97
-
98
- // targetAuthor is the phone number of the sender
99
- const targetAuthor = formattedNumber;
100
- const createdAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
101
-
102
- // Create store key
103
- const storeKey = `approval:${messageTimestamp}:${targetAuthor}`;
104
-
105
- // DEBUG: Log storing approval mapping
106
- console.log('[RequestApprovalMessage] DEBUG - Storing approval mapping:', {
107
- storeKey,
108
- timestampMs,
109
- messageTimestamp,
110
- targetAuthor,
111
- formattedNumber,
112
- flowRunId: context.run.id,
113
- requestId,
114
- responseTimestamp: response.timestamp,
115
- responseTimestampType: typeof response.timestamp
116
- });
117
-
118
- // Create mapping value
119
- const mapping: ApprovalMapping = {
120
- flowRunId: context.run.id,
121
- requestId: requestId,
122
- approveEmoji: approve_emoji,
123
- disapproveEmoji: disapprove_emoji,
124
- targetAuthor: targetAuthor,
125
- messageTimestamp: messageTimestamp,
126
- timeoutSeconds: timeout_seconds,
127
- createdAt: createdAt,
128
- };
129
-
130
- // DEBUG: Log full mapping
131
- console.log('[RequestApprovalMessage] DEBUG - Full mapping object:', mapping);
132
-
133
- // Save mapping in Store (PROJECT-scoped)
134
- await context.store.put(storeKey, mapping, StoreScope.PROJECT);
135
-
136
- // DEBUG: Verify it was stored
137
- const verifyMapping = await context.store.get<ApprovalMapping>(storeKey, StoreScope.PROJECT);
138
- console.log('[RequestApprovalMessage] DEBUG - Verified stored mapping:', verifyMapping);
139
-
140
- // Add key to approval keys list
141
- const keysListKey = 'approval:keys';
142
- const existingKeys = (await context.store.get<string[]>(keysListKey, StoreScope.PROJECT)) || [];
143
- if (!existingKeys.includes(storeKey)) {
144
- existingKeys.push(storeKey);
145
- await context.store.put(keysListKey, existingKeys, StoreScope.PROJECT);
146
- }
147
-
148
- // Also save mapping from flowRunId to storeKey for easy lookup in RESUME phase
149
- const flowRunMappingKey = `approval:flowRun:${context.run.id}`;
150
- await context.store.put(flowRunMappingKey, storeKey, StoreScope.PROJECT);
151
-
152
- const output = {
153
- messageTimestamp,
154
- targetAuthor,
155
- flowRunId: context.run.id,
156
- requestId,
157
- debug: {
158
- timestampMs,
159
- messageTimestamp,
160
- storeKey,
161
- formattedNumber,
162
- responseTimestamp: response.timestamp,
163
- responseTimestampType: typeof response.timestamp,
164
- approveEmoji: approve_emoji,
165
- disapproveEmoji: disapprove_emoji,
166
- timeoutSeconds: timeout_seconds,
167
- createdAt,
168
- mapping: mapping,
169
- verifiedMapping: verifyMapping,
170
- },
171
- };
172
-
173
- // Pause the flow and wait for approval
174
- context.run.pause({
175
- pauseMetadata: {
176
- type: PauseType.WEBHOOK,
177
- response: {},
178
- },
179
- });
180
-
181
- return output;
182
- } else {
183
- // RESUME-Phase: Flow was resumed by Resume-Action
184
- const action = context.resumePayload.queryParams['action'];
185
- const approved = action === 'approve';
186
-
187
- // Find the storeKey for this flowRunId
188
- const flowRunMappingKey = `approval:flowRun:${context.run.id}`;
189
- const storeKey = await context.store.get<string>(flowRunMappingKey, StoreScope.PROJECT);
190
-
191
- if (storeKey) {
192
- // Delete mapping from Store
193
- await context.store.delete(storeKey, StoreScope.PROJECT);
194
-
195
- // Delete flowRunId mapping
196
- await context.store.delete(flowRunMappingKey, StoreScope.PROJECT);
197
-
198
- // Remove key from approval keys list
199
- const keysListKey = 'approval:keys';
200
- const existingKeys = (await context.store.get<string[]>(keysListKey, StoreScope.PROJECT)) || [];
201
- const updatedKeys = existingKeys.filter(key => key !== storeKey);
202
- await context.store.put(keysListKey, updatedKeys, StoreScope.PROJECT);
203
- }
204
-
205
- return {
206
- approved,
207
- debug: {
208
- action,
209
- storeKey: storeKey || null,
210
- flowRunId: context.run.id,
211
- },
212
- };
213
- }
214
- },
215
- });