@auxiora/channels 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +191 -0
  2. package/dist/adapters/bluebubbles.d.ts +63 -0
  3. package/dist/adapters/bluebubbles.d.ts.map +1 -0
  4. package/dist/adapters/bluebubbles.js +197 -0
  5. package/dist/adapters/bluebubbles.js.map +1 -0
  6. package/dist/adapters/discord.d.ts +27 -0
  7. package/dist/adapters/discord.d.ts.map +1 -0
  8. package/dist/adapters/discord.js +202 -0
  9. package/dist/adapters/discord.js.map +1 -0
  10. package/dist/adapters/email.d.ts +39 -0
  11. package/dist/adapters/email.d.ts.map +1 -0
  12. package/dist/adapters/email.js +359 -0
  13. package/dist/adapters/email.js.map +1 -0
  14. package/dist/adapters/googlechat.d.ts +77 -0
  15. package/dist/adapters/googlechat.d.ts.map +1 -0
  16. package/dist/adapters/googlechat.js +232 -0
  17. package/dist/adapters/googlechat.js.map +1 -0
  18. package/dist/adapters/matrix.d.ts +37 -0
  19. package/dist/adapters/matrix.d.ts.map +1 -0
  20. package/dist/adapters/matrix.js +262 -0
  21. package/dist/adapters/matrix.js.map +1 -0
  22. package/dist/adapters/signal.d.ts +32 -0
  23. package/dist/adapters/signal.d.ts.map +1 -0
  24. package/dist/adapters/signal.js +216 -0
  25. package/dist/adapters/signal.js.map +1 -0
  26. package/dist/adapters/slack.d.ts +29 -0
  27. package/dist/adapters/slack.d.ts.map +1 -0
  28. package/dist/adapters/slack.js +202 -0
  29. package/dist/adapters/slack.js.map +1 -0
  30. package/dist/adapters/teams.d.ts +66 -0
  31. package/dist/adapters/teams.d.ts.map +1 -0
  32. package/dist/adapters/teams.js +227 -0
  33. package/dist/adapters/teams.js.map +1 -0
  34. package/dist/adapters/telegram.d.ts +28 -0
  35. package/dist/adapters/telegram.d.ts.map +1 -0
  36. package/dist/adapters/telegram.js +170 -0
  37. package/dist/adapters/telegram.js.map +1 -0
  38. package/dist/adapters/twilio.d.ts +63 -0
  39. package/dist/adapters/twilio.d.ts.map +1 -0
  40. package/dist/adapters/twilio.js +193 -0
  41. package/dist/adapters/twilio.js.map +1 -0
  42. package/dist/adapters/whatsapp.d.ts +99 -0
  43. package/dist/adapters/whatsapp.d.ts.map +1 -0
  44. package/dist/adapters/whatsapp.js +218 -0
  45. package/dist/adapters/whatsapp.js.map +1 -0
  46. package/dist/adapters/zalo.d.ts +64 -0
  47. package/dist/adapters/zalo.d.ts.map +1 -0
  48. package/dist/adapters/zalo.js +216 -0
  49. package/dist/adapters/zalo.js.map +1 -0
  50. package/dist/index.d.ts +15 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +16 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/manager.d.ts +35 -0
  55. package/dist/manager.d.ts.map +1 -0
  56. package/dist/manager.js +127 -0
  57. package/dist/manager.js.map +1 -0
  58. package/dist/types.d.ts +71 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +32 -0
  63. package/src/adapters/bluebubbles.ts +294 -0
  64. package/src/adapters/discord.ts +253 -0
  65. package/src/adapters/email.ts +457 -0
  66. package/src/adapters/googlechat.ts +364 -0
  67. package/src/adapters/matrix.ts +376 -0
  68. package/src/adapters/signal.ts +313 -0
  69. package/src/adapters/slack.ts +252 -0
  70. package/src/adapters/teams.ts +320 -0
  71. package/src/adapters/telegram.ts +208 -0
  72. package/src/adapters/twilio.ts +256 -0
  73. package/src/adapters/whatsapp.ts +342 -0
  74. package/src/adapters/zalo.ts +319 -0
  75. package/src/index.ts +78 -0
  76. package/src/manager.ts +180 -0
  77. package/src/types.ts +84 -0
  78. package/tests/bluebubbles.test.ts +438 -0
  79. package/tests/email.test.ts +136 -0
  80. package/tests/googlechat.test.ts +439 -0
  81. package/tests/matrix.test.ts +564 -0
  82. package/tests/signal.test.ts +404 -0
  83. package/tests/slack.test.ts +343 -0
  84. package/tests/teams.test.ts +429 -0
  85. package/tests/twilio.test.ts +269 -0
  86. package/tests/whatsapp.test.ts +530 -0
  87. package/tests/zalo.test.ts +499 -0
  88. package/tsconfig.json +8 -0
  89. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,227 @@
1
+ import { audit } from '@auxiora/audit';
2
+ const MAX_MESSAGE_LENGTH = 28000;
3
+ const TOKEN_URL = 'https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token';
4
+ export class TeamsAdapter {
5
+ type = 'teams';
6
+ name = 'Microsoft Teams';
7
+ config;
8
+ messageHandler;
9
+ errorHandler;
10
+ connected = false;
11
+ accessToken;
12
+ tokenExpiry = 0;
13
+ constructor(config) {
14
+ this.config = config;
15
+ }
16
+ async connect() {
17
+ // Verify credentials by obtaining a token
18
+ await this.getAccessToken();
19
+ this.connected = true;
20
+ audit('channel.connected', {
21
+ channelType: 'teams',
22
+ appId: this.config.microsoftAppId,
23
+ });
24
+ }
25
+ async disconnect() {
26
+ this.connected = false;
27
+ this.accessToken = undefined;
28
+ this.tokenExpiry = 0;
29
+ audit('channel.disconnected', { channelType: 'teams' });
30
+ }
31
+ isConnected() {
32
+ return this.connected;
33
+ }
34
+ async getAccessToken() {
35
+ if (this.accessToken && Date.now() < this.tokenExpiry) {
36
+ return this.accessToken;
37
+ }
38
+ const params = new URLSearchParams({
39
+ grant_type: 'client_credentials',
40
+ client_id: this.config.microsoftAppId,
41
+ client_secret: this.config.microsoftAppPassword,
42
+ scope: 'https://api.botframework.com/.default',
43
+ });
44
+ const response = await fetch(TOKEN_URL, {
45
+ method: 'POST',
46
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
47
+ body: params.toString(),
48
+ });
49
+ if (!response.ok) {
50
+ throw new Error(`Failed to obtain Teams token: ${response.status} ${response.statusText}`);
51
+ }
52
+ const data = await response.json();
53
+ this.accessToken = data.access_token;
54
+ // Expire 5 minutes early to avoid edge cases
55
+ this.tokenExpiry = Date.now() + (data.expires_in - 300) * 1000;
56
+ return this.accessToken;
57
+ }
58
+ /**
59
+ * Handle incoming webhook from Microsoft Bot Framework.
60
+ * Call this from your HTTP server when receiving POST to /api/messages.
61
+ */
62
+ async handleWebhook(activity) {
63
+ if (activity.type !== 'message')
64
+ return;
65
+ if (!activity.text)
66
+ return;
67
+ // Check allowed tenants
68
+ const tenantId = activity.conversation.tenantId;
69
+ if (tenantId && this.config.allowedTenants?.length && !this.config.allowedTenants.includes(tenantId)) {
70
+ audit('message.filtered', { channelType: 'teams', senderId: activity.from.id, tenantId, reason: 'tenant_not_allowed' });
71
+ return;
72
+ }
73
+ // Check allowed users
74
+ if (this.config.allowedUsers?.length && !this.config.allowedUsers.includes(activity.from.id)) {
75
+ audit('message.filtered', { channelType: 'teams', senderId: activity.from.id, reason: 'user_not_allowed' });
76
+ return;
77
+ }
78
+ const inbound = this.toInboundMessage(activity);
79
+ audit('message.received', {
80
+ channelType: 'teams',
81
+ senderId: inbound.senderId,
82
+ channelId: inbound.channelId,
83
+ });
84
+ if (this.messageHandler) {
85
+ try {
86
+ await this.messageHandler(inbound);
87
+ }
88
+ catch (error) {
89
+ this.errorHandler?.(error instanceof Error ? error : new Error(String(error)));
90
+ }
91
+ }
92
+ }
93
+ toInboundMessage(activity) {
94
+ // Strip bot mention from content
95
+ let content = activity.text || '';
96
+ if (activity.recipient?.name) {
97
+ content = content.replace(new RegExp(`<at>${activity.recipient.name}</at>`, 'gi'), '').trim();
98
+ }
99
+ return {
100
+ id: activity.id,
101
+ channelType: 'teams',
102
+ channelId: activity.conversation.id,
103
+ senderId: activity.from.id,
104
+ senderName: activity.from.name,
105
+ content,
106
+ timestamp: new Date(activity.timestamp).getTime(),
107
+ replyToId: activity.replyToId,
108
+ attachments: activity.attachments?.map((a) => ({
109
+ type: a.contentType.startsWith('image/')
110
+ ? 'image'
111
+ : 'file',
112
+ url: a.contentUrl,
113
+ mimeType: a.contentType,
114
+ filename: a.name,
115
+ })),
116
+ raw: activity,
117
+ };
118
+ }
119
+ async send(channelId, message) {
120
+ try {
121
+ const token = await this.getAccessToken();
122
+ const chunks = this.chunkMessage(message.content);
123
+ let lastMessageId;
124
+ // We need the serviceUrl from the incoming activity
125
+ // For now, use the default Bot Framework service URL
126
+ const serviceUrl = 'https://smba.trafficmanager.net/teams/';
127
+ for (const chunk of chunks) {
128
+ const activity = {
129
+ type: 'message',
130
+ text: chunk,
131
+ ...(message.replyToId ? { replyToId: message.replyToId } : {}),
132
+ };
133
+ const url = `${serviceUrl}v3/conversations/${encodeURIComponent(channelId)}/activities`;
134
+ const response = await fetch(url, {
135
+ method: 'POST',
136
+ headers: {
137
+ 'Authorization': `Bearer ${token}`,
138
+ 'Content-Type': 'application/json',
139
+ },
140
+ body: JSON.stringify(activity),
141
+ });
142
+ if (!response.ok) {
143
+ const errorText = await response.text().catch(() => response.statusText);
144
+ throw new Error(`Teams API error ${response.status}: ${errorText}`);
145
+ }
146
+ const result = await response.json();
147
+ lastMessageId = result.id;
148
+ }
149
+ audit('message.sent', {
150
+ channelType: 'teams',
151
+ channelId,
152
+ messageId: lastMessageId,
153
+ });
154
+ return { success: true, messageId: lastMessageId };
155
+ }
156
+ catch (error) {
157
+ const errorMessage = error instanceof Error ? error.message : String(error);
158
+ audit('channel.error', {
159
+ channelType: 'teams',
160
+ action: 'send',
161
+ error: errorMessage,
162
+ });
163
+ return { success: false, error: errorMessage };
164
+ }
165
+ }
166
+ chunkMessage(content) {
167
+ if (content.length <= MAX_MESSAGE_LENGTH) {
168
+ return [content];
169
+ }
170
+ const chunks = [];
171
+ let remaining = content;
172
+ while (remaining.length > 0) {
173
+ if (remaining.length <= MAX_MESSAGE_LENGTH) {
174
+ chunks.push(remaining);
175
+ break;
176
+ }
177
+ let breakPoint = remaining.lastIndexOf('\n', MAX_MESSAGE_LENGTH);
178
+ if (breakPoint === -1 || breakPoint < MAX_MESSAGE_LENGTH / 2) {
179
+ breakPoint = remaining.lastIndexOf(' ', MAX_MESSAGE_LENGTH);
180
+ }
181
+ if (breakPoint === -1 || breakPoint < MAX_MESSAGE_LENGTH / 2) {
182
+ breakPoint = MAX_MESSAGE_LENGTH;
183
+ }
184
+ chunks.push(remaining.slice(0, breakPoint));
185
+ remaining = remaining.slice(breakPoint).trimStart();
186
+ }
187
+ return chunks;
188
+ }
189
+ async startTyping(channelId) {
190
+ let token;
191
+ try {
192
+ token = await this.getAccessToken();
193
+ }
194
+ catch {
195
+ return () => { };
196
+ }
197
+ const serviceUrl = 'https://smba.trafficmanager.net/teams/';
198
+ const url = `${serviceUrl}v3/conversations/${encodeURIComponent(channelId)}/activities`;
199
+ // Send typing activity immediately, repeat every 3s
200
+ let stopped = false;
201
+ const sendTyping = () => fetch(url, {
202
+ method: 'POST',
203
+ headers: {
204
+ 'Authorization': `Bearer ${token}`,
205
+ 'Content-Type': 'application/json',
206
+ },
207
+ body: JSON.stringify({ type: 'typing' }),
208
+ }).catch(() => { });
209
+ sendTyping();
210
+ const interval = setInterval(() => {
211
+ if (stopped)
212
+ return;
213
+ sendTyping();
214
+ }, 3000);
215
+ return () => {
216
+ stopped = true;
217
+ clearInterval(interval);
218
+ };
219
+ }
220
+ onMessage(handler) {
221
+ this.messageHandler = handler;
222
+ }
223
+ onError(handler) {
224
+ this.errorHandler = handler;
225
+ }
226
+ }
227
+ //# sourceMappingURL=teams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams.js","sourceRoot":"","sources":["../../src/adapters/teams.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { ChannelAdapter, InboundMessage, OutboundMessage, SendResult } from '../types.js';
2
+ export interface TelegramAdapterConfig {
3
+ token: string;
4
+ webhookUrl?: string;
5
+ allowedChats?: string[];
6
+ }
7
+ export declare class TelegramAdapter implements ChannelAdapter {
8
+ readonly type: "telegram";
9
+ readonly name = "Telegram";
10
+ private bot;
11
+ private config;
12
+ private messageHandler?;
13
+ private errorHandler?;
14
+ private connected;
15
+ constructor(config: TelegramAdapterConfig);
16
+ private setupEventHandlers;
17
+ private toInboundMessage;
18
+ connect(): Promise<void>;
19
+ disconnect(): Promise<void>;
20
+ isConnected(): boolean;
21
+ send(channelId: string, message: OutboundMessage): Promise<SendResult>;
22
+ private chunkMessage;
23
+ startTyping(channelId: string): Promise<() => void>;
24
+ handleWebhook(body: unknown): Promise<void>;
25
+ onMessage(handler: (message: InboundMessage) => Promise<void>): void;
26
+ onError(handler: (error: Error) => void): void;
27
+ }
28
+ //# sourceMappingURL=telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAID,qBAAa,eAAgB,YAAW,cAAc;IACpD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,cAAc,CAAC,CAA6C;IACpE,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,qBAAqB;IAMzC,OAAO,CAAC,kBAAkB;IAoC1B,OAAO,CAAC,gBAAgB;IAmBlB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAexB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,IAAI,OAAO;IAIhB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAoC5E,OAAO,CAAC,YAAY;IA6Bd,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAkBnD,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIpE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;CAG/C"}
@@ -0,0 +1,170 @@
1
+ import { Bot } from 'grammy';
2
+ import { audit } from '@auxiora/audit';
3
+ const MAX_MESSAGE_LENGTH = 4096;
4
+ export class TelegramAdapter {
5
+ type = 'telegram';
6
+ name = 'Telegram';
7
+ bot;
8
+ config;
9
+ messageHandler;
10
+ errorHandler;
11
+ connected = false;
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.bot = new Bot(config.token);
15
+ this.setupEventHandlers();
16
+ }
17
+ setupEventHandlers() {
18
+ this.bot.on('message:text', async (ctx) => {
19
+ const message = ctx.message;
20
+ if (!message || !message.text)
21
+ return;
22
+ // Check chat allowlist
23
+ if (this.config.allowedChats?.length &&
24
+ !this.config.allowedChats.includes(String(message.chat.id))) {
25
+ return;
26
+ }
27
+ const inbound = this.toInboundMessage(ctx);
28
+ audit('message.received', {
29
+ channelType: 'telegram',
30
+ senderId: inbound.senderId,
31
+ channelId: inbound.channelId,
32
+ });
33
+ if (this.messageHandler) {
34
+ try {
35
+ await this.messageHandler(inbound);
36
+ }
37
+ catch (error) {
38
+ this.errorHandler?.(error instanceof Error ? error : new Error(String(error)));
39
+ }
40
+ }
41
+ });
42
+ this.bot.catch((error) => {
43
+ audit('channel.error', { channelType: 'telegram', error: error.message });
44
+ this.errorHandler?.(error);
45
+ });
46
+ }
47
+ toInboundMessage(ctx) {
48
+ const message = ctx.message;
49
+ const from = message.from;
50
+ return {
51
+ id: String(message.message_id),
52
+ channelType: 'telegram',
53
+ channelId: String(message.chat.id),
54
+ senderId: String(from.id),
55
+ senderName: from.first_name + (from.last_name ? ` ${from.last_name}` : ''),
56
+ content: message.text || '',
57
+ timestamp: message.date * 1000,
58
+ replyToId: message.reply_to_message
59
+ ? String(message.reply_to_message.message_id)
60
+ : undefined,
61
+ raw: message,
62
+ };
63
+ }
64
+ async connect() {
65
+ if (this.config.webhookUrl) {
66
+ await this.bot.api.setWebhook(this.config.webhookUrl);
67
+ }
68
+ else {
69
+ // Start polling
70
+ this.bot.start({
71
+ onStart: () => {
72
+ audit('channel.connected', { channelType: 'telegram' });
73
+ this.connected = true;
74
+ },
75
+ });
76
+ }
77
+ this.connected = true;
78
+ }
79
+ async disconnect() {
80
+ await this.bot.stop();
81
+ this.connected = false;
82
+ audit('channel.disconnected', { channelType: 'telegram' });
83
+ }
84
+ isConnected() {
85
+ return this.connected;
86
+ }
87
+ async send(channelId, message) {
88
+ try {
89
+ const chatId = parseInt(channelId, 10);
90
+ // Chunk long messages
91
+ const chunks = this.chunkMessage(message.content);
92
+ let lastMessageId;
93
+ for (const chunk of chunks) {
94
+ const sent = await this.bot.api.sendMessage(chatId, chunk, {
95
+ parse_mode: message.formatting?.markdown ? 'MarkdownV2' : undefined,
96
+ reply_parameters: message.replyToId
97
+ ? { message_id: parseInt(message.replyToId, 10) }
98
+ : undefined,
99
+ });
100
+ lastMessageId = sent.message_id;
101
+ }
102
+ audit('message.sent', {
103
+ channelType: 'telegram',
104
+ channelId,
105
+ messageId: lastMessageId,
106
+ });
107
+ return { success: true, messageId: String(lastMessageId) };
108
+ }
109
+ catch (error) {
110
+ const errorMessage = error instanceof Error ? error.message : String(error);
111
+ audit('channel.error', {
112
+ channelType: 'telegram',
113
+ action: 'send',
114
+ error: errorMessage,
115
+ });
116
+ return { success: false, error: errorMessage };
117
+ }
118
+ }
119
+ chunkMessage(content) {
120
+ if (content.length <= MAX_MESSAGE_LENGTH) {
121
+ return [content];
122
+ }
123
+ const chunks = [];
124
+ let remaining = content;
125
+ while (remaining.length > 0) {
126
+ if (remaining.length <= MAX_MESSAGE_LENGTH) {
127
+ chunks.push(remaining);
128
+ break;
129
+ }
130
+ let breakPoint = remaining.lastIndexOf('\n', MAX_MESSAGE_LENGTH);
131
+ if (breakPoint === -1 || breakPoint < MAX_MESSAGE_LENGTH / 2) {
132
+ breakPoint = remaining.lastIndexOf(' ', MAX_MESSAGE_LENGTH);
133
+ }
134
+ if (breakPoint === -1 || breakPoint < MAX_MESSAGE_LENGTH / 2) {
135
+ breakPoint = MAX_MESSAGE_LENGTH;
136
+ }
137
+ chunks.push(remaining.slice(0, breakPoint));
138
+ remaining = remaining.slice(breakPoint).trimStart();
139
+ }
140
+ return chunks;
141
+ }
142
+ async startTyping(channelId) {
143
+ const chatId = parseInt(channelId, 10);
144
+ // Send immediately, then repeat every 4s (Telegram typing expires after ~5s)
145
+ let stopped = false;
146
+ this.bot.api.sendChatAction(chatId, 'typing').catch((e) => {
147
+ audit('channel.error', { channelType: 'telegram', action: 'typing', error: e.message });
148
+ });
149
+ const interval = setInterval(() => {
150
+ if (stopped)
151
+ return;
152
+ this.bot.api.sendChatAction(chatId, 'typing').catch(() => { });
153
+ }, 4000);
154
+ return () => {
155
+ stopped = true;
156
+ clearInterval(interval);
157
+ };
158
+ }
159
+ // Webhook handler for serverless deployments
160
+ async handleWebhook(body) {
161
+ await this.bot.handleUpdate(body);
162
+ }
163
+ onMessage(handler) {
164
+ this.messageHandler = handler;
165
+ }
166
+ onError(handler) {
167
+ this.errorHandler = handler;
168
+ }
169
+ }
170
+ //# sourceMappingURL=telegram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAW,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAcvC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAmB,CAAC;IAC3B,IAAI,GAAG,UAAU,CAAC;IAEnB,GAAG,CAAM;IACT,MAAM,CAAwB;IAC9B,cAAc,CAA8C;IAC5D,YAAY,CAA0B;IACtC,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAY,MAA6B;QACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE;YACjD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;YAC5B,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI;gBAAE,OAAO;YAEtC,uBAAuB;YACvB,IACE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM;gBAChC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAC3D,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAE3C,KAAK,CAAC,kBAAkB,EAAE;gBACxB,WAAW,EAAE,UAAU;gBACvB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAC;YAEH,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,YAAY,EAAE,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACjF,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACvB,KAAK,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1E,IAAI,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,gBAAgB,CAAC,GAAY;QACnC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAQ,CAAC;QAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAK,CAAC;QAE3B,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAC9B,WAAW,EAAE,UAAU;YACvB,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1E,OAAO,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;YAC3B,SAAS,EAAE,OAAO,CAAC,IAAI,GAAG,IAAI;YAC9B,SAAS,EAAE,OAAO,CAAC,gBAAgB;gBACjC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC;gBAC7C,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,OAAO;SACb,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACN,gBAAgB;YAChB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;gBACb,OAAO,EAAE,GAAG,EAAE;oBACZ,KAAK,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;oBACxD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACxB,CAAC;aACF,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,KAAK,CAAC,sBAAsB,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,OAAwB;QACpD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAEvC,sBAAsB;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAClD,IAAI,aAAiC,CAAC;YAEtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE;oBACzD,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;oBACnE,gBAAgB,EAAE,OAAO,CAAC,SAAS;wBACjC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE;wBACjD,CAAC,CAAC,SAAS;iBACd,CAAC,CAAC;gBACH,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC;YAClC,CAAC;YAED,KAAK,CAAC,cAAc,EAAE;gBACpB,WAAW,EAAE,UAAU;gBACvB,SAAS;gBACT,SAAS,EAAE,aAAa;aACzB,CAAC,CAAC;YAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,KAAK,CAAC,eAAe,EAAE;gBACrB,WAAW,EAAE,UAAU;gBACvB,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,YAAY;aACpB,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,OAAe;QAClC,IAAI,OAAO,CAAC,MAAM,IAAI,kBAAkB,EAAE,CAAC;YACzC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,SAAS,GAAG,OAAO,CAAC;QAExB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,SAAS,CAAC,MAAM,IAAI,kBAAkB,EAAE,CAAC;gBAC3C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACvB,MAAM;YACR,CAAC;YAED,IAAI,UAAU,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;YACjE,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,UAAU,GAAG,kBAAkB,GAAG,CAAC,EAAE,CAAC;gBAC7D,UAAU,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;YAC9D,CAAC;YACD,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,UAAU,GAAG,kBAAkB,GAAG,CAAC,EAAE,CAAC;gBAC7D,UAAU,GAAG,kBAAkB,CAAC;YAClC,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;YAC5C,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE,CAAC;QACtD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,SAAiB;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACvC,6EAA6E;QAC7E,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE;YAC/D,KAAK,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;YAChC,IAAI,OAAO;gBAAE,OAAO;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAChE,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,IAAI,CAAC;YACf,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC,CAAC;IACJ,CAAC;IAED,6CAA6C;IAC7C,KAAK,CAAC,aAAa,CAAC,IAAa;QAC/B,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAmD,CAAC,CAAC;IACnF,CAAC;IAED,SAAS,CAAC,OAAmD;QAC3D,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,OAA+B;QACrC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,63 @@
1
+ import type { ChannelAdapter, InboundMessage, OutboundMessage, SendResult } from '../types.js';
2
+ export interface TwilioAdapterConfig {
3
+ accountSid: string;
4
+ authToken: string;
5
+ phoneNumber: string;
6
+ whatsappNumber?: string;
7
+ webhookUrl?: string;
8
+ allowedNumbers?: string[];
9
+ }
10
+ export interface TwilioWebhookBody {
11
+ MessageSid: string;
12
+ AccountSid: string;
13
+ From: string;
14
+ To: string;
15
+ Body: string;
16
+ NumMedia?: string;
17
+ MediaUrl0?: string;
18
+ MediaContentType0?: string;
19
+ }
20
+ export declare class TwilioAdapter implements ChannelAdapter {
21
+ readonly type: "twilio";
22
+ readonly name = "Twilio";
23
+ private client;
24
+ private config;
25
+ private messageHandler?;
26
+ private errorHandler?;
27
+ private connected;
28
+ constructor(config: TwilioAdapterConfig);
29
+ connect(): Promise<void>;
30
+ disconnect(): Promise<void>;
31
+ isConnected(): boolean;
32
+ /**
33
+ * Handle incoming webhook from Twilio
34
+ * Call this from your HTTP server when receiving POST to your webhook URL
35
+ */
36
+ handleWebhook(body: TwilioWebhookBody): Promise<string | null>;
37
+ /**
38
+ * Send message to a phone number
39
+ * @param channelId Phone number in E.164 format (+1234567890) or whatsapp:+1234567890
40
+ */
41
+ send(channelId: string, message: OutboundMessage): Promise<SendResult>;
42
+ /**
43
+ * Send SMS to a phone number
44
+ */
45
+ sendSMS(to: string, message: string): Promise<SendResult>;
46
+ /**
47
+ * Send WhatsApp message
48
+ */
49
+ sendWhatsApp(to: string, message: string): Promise<SendResult>;
50
+ private chunkMessage;
51
+ /**
52
+ * Validate Twilio webhook signature
53
+ */
54
+ validateWebhookSignature(signature: string, url: string, params: Record<string, string>): boolean;
55
+ /**
56
+ * Generate TwiML response for immediate reply
57
+ */
58
+ static generateTwiML(message: string): string;
59
+ private static escapeXml;
60
+ onMessage(handler: (message: InboundMessage) => Promise<void>): void;
61
+ onError(handler: (error: Error) => void): void;
62
+ }
63
+ //# sourceMappingURL=twilio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio.d.ts","sourceRoot":"","sources":["../../src/adapters/twilio.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAKD,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,cAAc,CAAC,CAA6C;IACpE,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,mBAAmB;IAKjC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAWxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,WAAW,IAAI,OAAO;IAItB;;;OAGG;IACG,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA+CpE;;;OAGG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IA2C5E;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAM/D;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAOpE,OAAO,CAAC,YAAY;IA6BpB;;OAEG;IACH,wBAAwB,CACtB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,OAAO;IASV;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAO7C,OAAO,CAAC,MAAM,CAAC,SAAS;IASxB,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIpE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;CAG/C"}