spectrum-ts 0.5.0 → 0.6.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/dist/chunk-XZTTLPHE.js +341 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +28 -66
- package/dist/providers/imessage/index.d.ts +1 -1
- package/dist/providers/imessage/index.js +117 -61
- package/dist/providers/terminal/index.d.ts +1 -1
- package/dist/providers/terminal/index.js +7 -3
- package/dist/providers/whatsapp-business/index.d.ts +1 -1
- package/dist/providers/whatsapp-business/index.js +57 -46
- package/dist/{types-CfiD_00g.d.ts → types-DZMHfgYQ.d.ts} +33 -8
- package/package.json +2 -2
- package/dist/chunk-XEEDIGVK.js +0 -199
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
asText,
|
|
15
15
|
definePlatform
|
|
16
|
-
} from "../../chunk-
|
|
16
|
+
} from "../../chunk-XZTTLPHE.js";
|
|
17
17
|
|
|
18
18
|
// src/providers/imessage/index.ts
|
|
19
19
|
import { createClient as createClient2, directChat } from "@photon-ai/advanced-imessage";
|
|
@@ -107,13 +107,14 @@ async function disposeCloudAuth(clients) {
|
|
|
107
107
|
|
|
108
108
|
// src/providers/imessage/local.ts
|
|
109
109
|
import { createReadStream } from "fs";
|
|
110
|
-
import { mkdtemp, rm, writeFile } from "fs/promises";
|
|
110
|
+
import { mkdtemp, readFile, rm, writeFile } from "fs/promises";
|
|
111
111
|
import { tmpdir } from "os";
|
|
112
112
|
import { basename, join } from "path";
|
|
113
113
|
import { Readable } from "stream";
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
var synthSendResult = () => ({
|
|
115
|
+
id: crypto.randomUUID(),
|
|
116
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
117
|
+
});
|
|
117
118
|
var DEFAULT_ATTACHMENT_NAME = "attachment";
|
|
118
119
|
var VCARD_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
119
120
|
"text/vcard",
|
|
@@ -129,17 +130,21 @@ var isVCardAttachment = (mimeType, fileName) => {
|
|
|
129
130
|
}
|
|
130
131
|
return Boolean(fileName?.toLowerCase().endsWith(".vcf"));
|
|
131
132
|
};
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
133
|
+
var readLocalAttachment = async (att) => {
|
|
134
|
+
if (!att.localPath) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`iMessage attachment ${att.id} has no local file available on disk`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
return readFile(att.localPath);
|
|
140
|
+
};
|
|
136
141
|
var toAttachmentContent = (att) => {
|
|
137
142
|
const { localPath } = att;
|
|
138
143
|
return asAttachment({
|
|
139
144
|
name: att.fileName ?? DEFAULT_ATTACHMENT_NAME,
|
|
140
145
|
mimeType: att.mimeType,
|
|
141
146
|
size: att.sizeBytes,
|
|
142
|
-
read: () =>
|
|
147
|
+
read: () => readLocalAttachment(att),
|
|
143
148
|
stream: localPath ? async () => Readable.toWeb(
|
|
144
149
|
createReadStream(localPath)
|
|
145
150
|
) : void 0
|
|
@@ -147,16 +152,23 @@ var toAttachmentContent = (att) => {
|
|
|
147
152
|
};
|
|
148
153
|
var toVCardContent = async (att) => {
|
|
149
154
|
try {
|
|
150
|
-
const buf = await
|
|
155
|
+
const buf = await readLocalAttachment(att);
|
|
151
156
|
return asContact(fromVCard(buf.toString("utf8")));
|
|
152
157
|
} catch {
|
|
153
158
|
return toAttachmentContent(att);
|
|
154
159
|
}
|
|
155
160
|
};
|
|
156
161
|
var toMessages = async (message) => {
|
|
162
|
+
const { chatId, chatKind } = message;
|
|
163
|
+
if (!chatId || chatKind === "unknown") {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
if (message.reaction !== null || message.kind !== "text" || message.retractedAt !== null) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
157
169
|
const base = {
|
|
158
170
|
sender: { id: message.participant ?? "" },
|
|
159
|
-
space:
|
|
171
|
+
space: { id: chatId, type: chatKind === "group" ? "group" : "dm" },
|
|
160
172
|
timestamp: message.createdAt
|
|
161
173
|
};
|
|
162
174
|
if (message.attachments.length > 0) {
|
|
@@ -178,16 +190,23 @@ var toMessages = async (message) => {
|
|
|
178
190
|
};
|
|
179
191
|
var messages = (client) => stream((emit, end) => {
|
|
180
192
|
let lastPromise = Promise.resolve();
|
|
181
|
-
client.startWatching({
|
|
182
|
-
|
|
193
|
+
const startPromise = client.startWatching({
|
|
194
|
+
onIncomingMessage: (message) => {
|
|
183
195
|
lastPromise = lastPromise.then(() => toMessages(message)).then((ms) => {
|
|
184
196
|
for (const m of ms) {
|
|
185
197
|
emit(m);
|
|
186
198
|
}
|
|
187
|
-
}).catch(
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
199
|
+
}).catch(end);
|
|
200
|
+
},
|
|
201
|
+
onError: end
|
|
202
|
+
}).catch(end);
|
|
203
|
+
return async () => {
|
|
204
|
+
await startPromise.catch(() => {
|
|
205
|
+
});
|
|
206
|
+
await client.stopWatching();
|
|
207
|
+
await lastPromise.catch(() => {
|
|
208
|
+
});
|
|
209
|
+
};
|
|
191
210
|
});
|
|
192
211
|
var vcardFileName = (content) => {
|
|
193
212
|
const base = content.name?.formatted ?? content.user?.id ?? "contact";
|
|
@@ -199,7 +218,7 @@ var sendTempFile = async (client, spaceId, name, data) => {
|
|
|
199
218
|
const tmp = join(dir, safeName);
|
|
200
219
|
await writeFile(tmp, data);
|
|
201
220
|
try {
|
|
202
|
-
await client.send(spaceId,
|
|
221
|
+
await client.send({ to: spaceId, attachments: [tmp] });
|
|
203
222
|
} finally {
|
|
204
223
|
await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
205
224
|
});
|
|
@@ -208,11 +227,11 @@ var sendTempFile = async (client, spaceId, name, data) => {
|
|
|
208
227
|
var send = async (client, spaceId, content) => {
|
|
209
228
|
switch (content.type) {
|
|
210
229
|
case "text":
|
|
211
|
-
await client.send(spaceId, content.text);
|
|
212
|
-
|
|
230
|
+
await client.send({ to: spaceId, text: content.text });
|
|
231
|
+
return synthSendResult();
|
|
213
232
|
case "attachment":
|
|
214
233
|
await sendTempFile(client, spaceId, content.name, await content.read());
|
|
215
|
-
|
|
234
|
+
return synthSendResult();
|
|
216
235
|
case "contact": {
|
|
217
236
|
const vcf = await toVCard(content);
|
|
218
237
|
await sendTempFile(
|
|
@@ -221,10 +240,12 @@ var send = async (client, spaceId, content) => {
|
|
|
221
240
|
vcardFileName(content),
|
|
222
241
|
Buffer.from(vcf, "utf8")
|
|
223
242
|
);
|
|
224
|
-
|
|
243
|
+
return synthSendResult();
|
|
225
244
|
}
|
|
226
245
|
default:
|
|
227
|
-
|
|
246
|
+
throw new Error(
|
|
247
|
+
`Unsupported iMessage local content type: ${content.type}`
|
|
248
|
+
);
|
|
228
249
|
}
|
|
229
250
|
};
|
|
230
251
|
|
|
@@ -237,7 +258,7 @@ import {
|
|
|
237
258
|
|
|
238
259
|
// src/utils/audio.ts
|
|
239
260
|
import { spawn } from "child_process";
|
|
240
|
-
import { mkdtemp as mkdtemp2, readFile, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
261
|
+
import { mkdtemp as mkdtemp2, readFile as readFile2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
241
262
|
import { tmpdir as tmpdir2 } from "os";
|
|
242
263
|
import { join as join2 } from "path";
|
|
243
264
|
var M4A_BRANDS = /* @__PURE__ */ new Set([
|
|
@@ -344,7 +365,7 @@ var transcodeToM4a = async (buffer) => {
|
|
|
344
365
|
if (code !== 0) {
|
|
345
366
|
throw new Error(`ffmpeg conversion failed (exit ${code}): ${stderr}`);
|
|
346
367
|
}
|
|
347
|
-
const out = await
|
|
368
|
+
const out = await readFile2(outPath);
|
|
348
369
|
return { buffer: out, duration: parseDuration(stderr) };
|
|
349
370
|
} finally {
|
|
350
371
|
await rm2(dir, { recursive: true, force: true }).catch(() => {
|
|
@@ -359,6 +380,10 @@ var ensureM4a = async (buffer, mimeType) => {
|
|
|
359
380
|
};
|
|
360
381
|
|
|
361
382
|
// src/providers/imessage/remote.ts
|
|
383
|
+
var toSendResult = (receipt) => ({
|
|
384
|
+
id: receipt.guid,
|
|
385
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
386
|
+
});
|
|
362
387
|
var VCARD_MIME_TYPES2 = /* @__PURE__ */ new Set([
|
|
363
388
|
"text/vcard",
|
|
364
389
|
"text/x-vcard",
|
|
@@ -425,6 +450,9 @@ var clientStream = (client) => {
|
|
|
425
450
|
(async () => {
|
|
426
451
|
try {
|
|
427
452
|
for await (const event of sub) {
|
|
453
|
+
if (event.message.isFromMe) {
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
428
456
|
for (const message of await toMessages2(client, event)) {
|
|
429
457
|
emit(message);
|
|
430
458
|
}
|
|
@@ -469,27 +497,27 @@ var stopTyping = async (clients, spaceId) => {
|
|
|
469
497
|
var send2 = async (clients, spaceId, content) => {
|
|
470
498
|
const remote = clients[0];
|
|
471
499
|
if (!remote) {
|
|
472
|
-
|
|
500
|
+
throw new Error("No remote iMessage client available");
|
|
473
501
|
}
|
|
502
|
+
const chat = chatGuid(spaceId);
|
|
474
503
|
switch (content.type) {
|
|
475
504
|
case "text":
|
|
476
|
-
await remote.messages.send(
|
|
477
|
-
break;
|
|
505
|
+
return toSendResult(await remote.messages.send(chat, content.text));
|
|
478
506
|
case "attachment": {
|
|
479
507
|
const attachment = await remote.attachments.upload({
|
|
480
508
|
data: await content.read(),
|
|
481
509
|
fileName: content.name,
|
|
482
510
|
mimeType: content.mimeType
|
|
483
511
|
});
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
512
|
+
return toSendResult(
|
|
513
|
+
await remote.messages.send(chat, "", {
|
|
514
|
+
attachment: attachment.guid
|
|
515
|
+
})
|
|
516
|
+
);
|
|
488
517
|
}
|
|
489
518
|
case "contact": {
|
|
490
519
|
const attachment = await sendContactAttachment(remote, content);
|
|
491
|
-
await remote.messages.send(
|
|
492
|
-
break;
|
|
520
|
+
return toSendResult(await remote.messages.send(chat, "", { attachment }));
|
|
493
521
|
}
|
|
494
522
|
case "voice": {
|
|
495
523
|
const { buffer } = await ensureM4a(
|
|
@@ -501,11 +529,12 @@ var send2 = async (clients, spaceId, content) => {
|
|
|
501
529
|
fileName: content.name ?? "voice.m4a",
|
|
502
530
|
mimeType: "audio/x-m4a"
|
|
503
531
|
});
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
532
|
+
return toSendResult(
|
|
533
|
+
await remote.messages.send(chat, "", {
|
|
534
|
+
attachment: attachment.guid,
|
|
535
|
+
audioMessage: true
|
|
536
|
+
})
|
|
537
|
+
);
|
|
509
538
|
}
|
|
510
539
|
default:
|
|
511
540
|
throw new Error(`Unsupported iMessage content type: ${content.type}`);
|
|
@@ -514,30 +543,33 @@ var send2 = async (clients, spaceId, content) => {
|
|
|
514
543
|
var replyToMessage = async (clients, spaceId, msgId, content) => {
|
|
515
544
|
const remote = clients[0];
|
|
516
545
|
if (!remote) {
|
|
517
|
-
|
|
546
|
+
throw new Error("No remote iMessage client available");
|
|
518
547
|
}
|
|
519
548
|
const chat = chatGuid(spaceId);
|
|
520
549
|
const replyTo = messageGuid(msgId);
|
|
521
550
|
switch (content.type) {
|
|
522
551
|
case "text":
|
|
523
|
-
|
|
524
|
-
|
|
552
|
+
return toSendResult(
|
|
553
|
+
await remote.messages.send(chat, content.text, { replyTo })
|
|
554
|
+
);
|
|
525
555
|
case "attachment": {
|
|
526
556
|
const attachment = await remote.attachments.upload({
|
|
527
557
|
data: await content.read(),
|
|
528
558
|
fileName: content.name,
|
|
529
559
|
mimeType: content.mimeType
|
|
530
560
|
});
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
561
|
+
return toSendResult(
|
|
562
|
+
await remote.messages.send(chat, "", {
|
|
563
|
+
attachment: attachment.guid,
|
|
564
|
+
replyTo
|
|
565
|
+
})
|
|
566
|
+
);
|
|
536
567
|
}
|
|
537
568
|
case "contact": {
|
|
538
569
|
const attachment = await sendContactAttachment(remote, content);
|
|
539
|
-
|
|
540
|
-
|
|
570
|
+
return toSendResult(
|
|
571
|
+
await remote.messages.send(chat, "", { attachment, replyTo })
|
|
572
|
+
);
|
|
541
573
|
}
|
|
542
574
|
case "voice": {
|
|
543
575
|
const { buffer } = await ensureM4a(
|
|
@@ -549,17 +581,32 @@ var replyToMessage = async (clients, spaceId, msgId, content) => {
|
|
|
549
581
|
fileName: content.name ?? "voice.m4a",
|
|
550
582
|
mimeType: "audio/x-m4a"
|
|
551
583
|
});
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
584
|
+
return toSendResult(
|
|
585
|
+
await remote.messages.send(chat, "", {
|
|
586
|
+
attachment: attachment.guid,
|
|
587
|
+
audioMessage: true,
|
|
588
|
+
replyTo
|
|
589
|
+
})
|
|
590
|
+
);
|
|
558
591
|
}
|
|
559
592
|
default:
|
|
560
593
|
throw new Error(`Unsupported iMessage content type: ${content.type}`);
|
|
561
594
|
}
|
|
562
595
|
};
|
|
596
|
+
var editMessage = async (clients, spaceId, msgId, content) => {
|
|
597
|
+
if (content.type !== "text") {
|
|
598
|
+
throw new Error("iMessage only supports editing text content");
|
|
599
|
+
}
|
|
600
|
+
const remote = clients[0];
|
|
601
|
+
if (!remote) {
|
|
602
|
+
throw new Error("No remote iMessage client available");
|
|
603
|
+
}
|
|
604
|
+
await remote.messages.edit(
|
|
605
|
+
chatGuid(spaceId),
|
|
606
|
+
messageGuid(msgId),
|
|
607
|
+
content.text
|
|
608
|
+
);
|
|
609
|
+
};
|
|
563
610
|
var reactToMessage = async (clients, spaceId, msgId, reaction) => {
|
|
564
611
|
const remote = clients[0];
|
|
565
612
|
if (!remote) {
|
|
@@ -671,10 +718,9 @@ var imessage = definePlatform("iMessage", {
|
|
|
671
718
|
actions: {
|
|
672
719
|
send: async ({ space, content, client }) => {
|
|
673
720
|
if (isLocal(client)) {
|
|
674
|
-
await send(client, space.id, content);
|
|
675
|
-
} else {
|
|
676
|
-
await send2(client, space.id, content);
|
|
721
|
+
return await send(client, space.id, content);
|
|
677
722
|
}
|
|
723
|
+
return await send2(client, space.id, content);
|
|
678
724
|
},
|
|
679
725
|
startTyping: async ({ space, client }) => {
|
|
680
726
|
if (isLocal(client)) {
|
|
@@ -696,9 +742,19 @@ var imessage = definePlatform("iMessage", {
|
|
|
696
742
|
},
|
|
697
743
|
replyToMessage: async ({ space, messageId, content, client }) => {
|
|
698
744
|
if (isLocal(client)) {
|
|
699
|
-
|
|
745
|
+
throw new Error(
|
|
746
|
+
"iMessage local mode does not support replying to messages"
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
return await replyToMessage(client, space.id, messageId, content);
|
|
750
|
+
},
|
|
751
|
+
editMessage: async ({ space, messageId, content, client }) => {
|
|
752
|
+
if (isLocal(client)) {
|
|
753
|
+
throw new Error(
|
|
754
|
+
"iMessage local mode does not support editing messages"
|
|
755
|
+
);
|
|
700
756
|
}
|
|
701
|
-
await
|
|
757
|
+
await editMessage(client, space.id, messageId, content);
|
|
702
758
|
}
|
|
703
759
|
}
|
|
704
760
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-
|
|
1
|
+
import { d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-DZMHfgYQ.js';
|
|
2
2
|
import * as node_readline from 'node:readline';
|
|
3
3
|
import z__default from 'zod';
|
|
4
4
|
import 'hotscript';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
definePlatform
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-XZTTLPHE.js";
|
|
4
4
|
|
|
5
5
|
// src/providers/terminal/index.ts
|
|
6
6
|
import { createInterface } from "readline";
|
|
@@ -49,9 +49,13 @@ var terminal = definePlatform("terminal", {
|
|
|
49
49
|
},
|
|
50
50
|
actions: {
|
|
51
51
|
send: async ({ content }) => {
|
|
52
|
-
if (content.type
|
|
53
|
-
|
|
52
|
+
if (content.type !== "text") {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Terminal provider only supports text content, got "${content.type}"`
|
|
55
|
+
);
|
|
54
56
|
}
|
|
57
|
+
console.log(content.text);
|
|
58
|
+
return { id: crypto.randomUUID(), timestamp: /* @__PURE__ */ new Date() };
|
|
55
59
|
}
|
|
56
60
|
}
|
|
57
61
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { M as ManagedStream } from '../../stream-DGy4geUK.js';
|
|
2
2
|
import * as z from 'zod';
|
|
3
3
|
import z__default from 'zod';
|
|
4
|
-
import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-
|
|
4
|
+
import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-DZMHfgYQ.js';
|
|
5
5
|
import * as zod_v4_core from 'zod/v4/core';
|
|
6
6
|
import { WhatsAppClient } from '@photon-ai/whatsapp-business';
|
|
7
7
|
import 'hotscript';
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
asText,
|
|
9
9
|
definePlatform
|
|
10
|
-
} from "../../chunk-
|
|
10
|
+
} from "../../chunk-XZTTLPHE.js";
|
|
11
11
|
|
|
12
12
|
// src/providers/whatsapp-business/index.ts
|
|
13
13
|
import {
|
|
@@ -16,6 +16,9 @@ import {
|
|
|
16
16
|
|
|
17
17
|
// src/providers/whatsapp-business/messages.ts
|
|
18
18
|
import { extension as mimeExtension } from "mime-types";
|
|
19
|
+
var toSendResult = (result) => ({
|
|
20
|
+
id: result.messageId
|
|
21
|
+
});
|
|
19
22
|
var mapWaPhoneType = (type) => {
|
|
20
23
|
if (!type) {
|
|
21
24
|
return void 0;
|
|
@@ -311,8 +314,9 @@ var messages = (client) => {
|
|
|
311
314
|
var send = async (client, spaceId, content) => {
|
|
312
315
|
switch (content.type) {
|
|
313
316
|
case "text":
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
return toSendResult(
|
|
318
|
+
await client.messages.send({ to: spaceId, text: content.text })
|
|
319
|
+
);
|
|
316
320
|
case "attachment": {
|
|
317
321
|
const { mediaId } = await client.media.upload({
|
|
318
322
|
file: await content.read(),
|
|
@@ -321,32 +325,35 @@ var send = async (client, spaceId, content) => {
|
|
|
321
325
|
});
|
|
322
326
|
const mediaType = mimeToMediaType(content.mimeType);
|
|
323
327
|
const mediaPayload = mediaType === "document" ? { id: mediaId, filename: content.name } : { id: mediaId };
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
return toSendResult(
|
|
329
|
+
await client.messages.send({
|
|
330
|
+
to: spaceId,
|
|
331
|
+
[mediaType]: mediaPayload
|
|
332
|
+
})
|
|
333
|
+
);
|
|
329
334
|
}
|
|
330
335
|
case "contact":
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
+
return toSendResult(
|
|
337
|
+
await client.messages.send({
|
|
338
|
+
to: spaceId,
|
|
339
|
+
contacts: [contactToWa(content)]
|
|
340
|
+
})
|
|
341
|
+
);
|
|
336
342
|
case "voice": {
|
|
337
343
|
const { mediaId } = await client.media.upload({
|
|
338
344
|
file: await content.read(),
|
|
339
345
|
mimeType: content.mimeType,
|
|
340
346
|
filename: voiceFilename(content)
|
|
341
347
|
});
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
348
|
+
return toSendResult(
|
|
349
|
+
await client.messages.send({
|
|
350
|
+
to: spaceId,
|
|
351
|
+
audio: { id: mediaId }
|
|
352
|
+
})
|
|
353
|
+
);
|
|
347
354
|
}
|
|
348
355
|
default:
|
|
349
|
-
|
|
356
|
+
throw new Error(`Unsupported WhatsApp content type: ${content.type}`);
|
|
350
357
|
}
|
|
351
358
|
};
|
|
352
359
|
var reactToMessage = async (client, spaceId, messageId, reaction) => {
|
|
@@ -358,12 +365,13 @@ var reactToMessage = async (client, spaceId, messageId, reaction) => {
|
|
|
358
365
|
var replyToMessage = async (client, spaceId, messageId, content) => {
|
|
359
366
|
switch (content.type) {
|
|
360
367
|
case "text":
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
368
|
+
return toSendResult(
|
|
369
|
+
await client.messages.send({
|
|
370
|
+
to: spaceId,
|
|
371
|
+
replyTo: messageId,
|
|
372
|
+
text: content.text
|
|
373
|
+
})
|
|
374
|
+
);
|
|
367
375
|
case "attachment": {
|
|
368
376
|
const { mediaId } = await client.media.upload({
|
|
369
377
|
file: await content.read(),
|
|
@@ -372,35 +380,38 @@ var replyToMessage = async (client, spaceId, messageId, content) => {
|
|
|
372
380
|
});
|
|
373
381
|
const mediaType = mimeToMediaType(content.mimeType);
|
|
374
382
|
const mediaPayload = mediaType === "document" ? { id: mediaId, filename: content.name } : { id: mediaId };
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
383
|
+
return toSendResult(
|
|
384
|
+
await client.messages.send({
|
|
385
|
+
to: spaceId,
|
|
386
|
+
replyTo: messageId,
|
|
387
|
+
[mediaType]: mediaPayload
|
|
388
|
+
})
|
|
389
|
+
);
|
|
381
390
|
}
|
|
382
391
|
case "contact":
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
392
|
+
return toSendResult(
|
|
393
|
+
await client.messages.send({
|
|
394
|
+
to: spaceId,
|
|
395
|
+
replyTo: messageId,
|
|
396
|
+
contacts: [contactToWa(content)]
|
|
397
|
+
})
|
|
398
|
+
);
|
|
389
399
|
case "voice": {
|
|
390
400
|
const { mediaId } = await client.media.upload({
|
|
391
401
|
file: await content.read(),
|
|
392
402
|
mimeType: content.mimeType,
|
|
393
403
|
filename: voiceFilename(content)
|
|
394
404
|
});
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
405
|
+
return toSendResult(
|
|
406
|
+
await client.messages.send({
|
|
407
|
+
to: spaceId,
|
|
408
|
+
replyTo: messageId,
|
|
409
|
+
audio: { id: mediaId }
|
|
410
|
+
})
|
|
411
|
+
);
|
|
401
412
|
}
|
|
402
413
|
default:
|
|
403
|
-
|
|
414
|
+
throw new Error(`Unsupported WhatsApp content type: ${content.type}`);
|
|
404
415
|
}
|
|
405
416
|
};
|
|
406
417
|
|
|
@@ -457,7 +468,7 @@ var whatsappBusiness = definePlatform("WhatsApp Business", {
|
|
|
457
468
|
},
|
|
458
469
|
actions: {
|
|
459
470
|
send: async ({ space, content, client }) => {
|
|
460
|
-
await send(client, space.id, content);
|
|
471
|
+
return await send(client, space.id, content);
|
|
461
472
|
},
|
|
462
473
|
reactToMessage: async ({ space, messageId, reaction, client }) => {
|
|
463
474
|
await reactToMessage(
|
|
@@ -468,7 +479,7 @@ var whatsappBusiness = definePlatform("WhatsApp Business", {
|
|
|
468
479
|
);
|
|
469
480
|
},
|
|
470
481
|
replyToMessage: async ({ space, messageId, content, client }) => {
|
|
471
|
-
await replyToMessage(
|
|
482
|
+
return await replyToMessage(
|
|
472
483
|
client,
|
|
473
484
|
space.id,
|
|
474
485
|
messageId,
|
|
@@ -92,23 +92,35 @@ interface User {
|
|
|
92
92
|
|
|
93
93
|
interface Space<_Def = unknown> {
|
|
94
94
|
readonly __platform: string;
|
|
95
|
+
edit(message: OutboundMessage, newContent: ContentInput): Promise<void>;
|
|
95
96
|
readonly id: string;
|
|
96
97
|
responding<T>(fn: () => T | Promise<T>): Promise<T>;
|
|
97
|
-
send(
|
|
98
|
+
send(content: ContentInput): Promise<OutboundMessage>;
|
|
99
|
+
send(...content: [ContentInput, ContentInput, ...ContentInput[]]): Promise<OutboundMessage[]>;
|
|
98
100
|
startTyping(): Promise<void>;
|
|
99
101
|
stopTyping(): Promise<void>;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
interface
|
|
104
|
+
interface BaseMessage<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> {
|
|
103
105
|
content: Content;
|
|
104
106
|
readonly id: string;
|
|
105
107
|
platform: TPlatform;
|
|
106
108
|
react(reaction: string): Promise<void>;
|
|
107
|
-
reply(
|
|
108
|
-
|
|
109
|
+
reply(content: ContentInput): Promise<OutboundMessage<TPlatform, TSender, TSpace>>;
|
|
110
|
+
reply(...content: [ContentInput, ContentInput, ...ContentInput[]]): Promise<OutboundMessage<TPlatform, TSender, TSpace>[]>;
|
|
109
111
|
space: TSpace;
|
|
110
112
|
timestamp: Date;
|
|
111
113
|
}
|
|
114
|
+
interface InboundMessage<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> extends BaseMessage<TPlatform, TSender, TSpace> {
|
|
115
|
+
direction: "inbound";
|
|
116
|
+
sender: TSender;
|
|
117
|
+
}
|
|
118
|
+
interface OutboundMessage<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> extends BaseMessage<TPlatform, TSender, TSpace> {
|
|
119
|
+
direction: "outbound";
|
|
120
|
+
edit(newContent: ContentInput): Promise<void>;
|
|
121
|
+
sender: TSender | undefined;
|
|
122
|
+
}
|
|
123
|
+
type Message<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> = InboundMessage<TPlatform, TSender, TSpace> | OutboundMessage<TPlatform, TSender, TSpace>;
|
|
112
124
|
|
|
113
125
|
type ResolvedSpace = Pick<Space, "id">;
|
|
114
126
|
type SpaceRef = Pick<Space, "id" | "__platform">;
|
|
@@ -131,6 +143,11 @@ type ProviderMessage<TSender extends ResolvedUser = ResolvedUser, TSpace extends
|
|
|
131
143
|
space: TSpace;
|
|
132
144
|
timestamp?: Date;
|
|
133
145
|
} & TExtra;
|
|
146
|
+
interface SendResult<TSender extends ResolvedUser = ResolvedUser> {
|
|
147
|
+
id: string;
|
|
148
|
+
sender?: TSender;
|
|
149
|
+
timestamp?: Date;
|
|
150
|
+
}
|
|
134
151
|
type MergeSchema<TSchema extends z__default.ZodType | undefined, TBase extends object> = TSchema extends z__default.ZodType ? string extends keyof z__default.infer<TSchema> ? TBase : Omit<z__default.infer<TSchema>, keyof TBase> & TBase : TBase;
|
|
135
152
|
type SchemaMessage<TUserSchema extends z__default.ZodType | undefined = undefined, TSpaceSchema extends z__default.ZodType | undefined = undefined> = ProviderMessage<MergeSchema<TUserSchema, ResolvedUser>, MergeSchema<TSpaceSchema, ResolvedSpace>>;
|
|
136
153
|
type InferEventPayload<T> = T extends (ctx: never) => AsyncIterable<infer P> ? P : never;
|
|
@@ -146,7 +163,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
|
|
|
146
163
|
content: Content;
|
|
147
164
|
client: _Client;
|
|
148
165
|
config: z__default.infer<_ConfigSchema>;
|
|
149
|
-
}) => Promise<
|
|
166
|
+
}) => Promise<SendResult<_ResolvedUser>>;
|
|
150
167
|
startTyping?: (_: {
|
|
151
168
|
space: _ResolvedSpace & SpaceRef;
|
|
152
169
|
client: _Client;
|
|
@@ -170,6 +187,13 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
|
|
|
170
187
|
content: Content;
|
|
171
188
|
client: _Client;
|
|
172
189
|
config: z__default.infer<_ConfigSchema>;
|
|
190
|
+
}) => Promise<SendResult<_ResolvedUser>>;
|
|
191
|
+
editMessage?: (_: {
|
|
192
|
+
space: _ResolvedSpace & SpaceRef;
|
|
193
|
+
messageId: string;
|
|
194
|
+
content: Content;
|
|
195
|
+
client: _Client;
|
|
196
|
+
config: z__default.infer<_ConfigSchema>;
|
|
173
197
|
}) => Promise<void>;
|
|
174
198
|
};
|
|
175
199
|
config: _ConfigSchema;
|
|
@@ -215,11 +239,12 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
|
|
|
215
239
|
}
|
|
216
240
|
interface AnyPlatformDef {
|
|
217
241
|
actions: {
|
|
218
|
-
send: (_: any) => Promise<
|
|
242
|
+
send: (_: any) => Promise<SendResult>;
|
|
219
243
|
startTyping?: (_: any) => Promise<void>;
|
|
220
244
|
stopTyping?: (_: any) => Promise<void>;
|
|
221
245
|
reactToMessage?: (_: any) => Promise<void>;
|
|
222
|
-
replyToMessage?: (_: any) => Promise<
|
|
246
|
+
replyToMessage?: (_: any) => Promise<SendResult>;
|
|
247
|
+
editMessage?: (_: any) => Promise<void>;
|
|
223
248
|
};
|
|
224
249
|
config: z__default.ZodType<object>;
|
|
225
250
|
events: {
|
|
@@ -318,4 +343,4 @@ interface Platform<Def extends AnyPlatformDef> {
|
|
|
318
343
|
(message: Message): PlatformMessage<Def>;
|
|
319
344
|
}
|
|
320
345
|
|
|
321
|
-
export type { AnyPlatformDef as A, ContentBuilder as C, EventProducer as E, Message as M, ProviderMessage as P, SpectrumLike as S, User as U, ContentInput as a, Content as b, PlatformDef as c, Platform as d, PlatformProviderConfig as e, CustomEventStreams as f, Space as g, PlatformInstance as h, PlatformMessage as i, PlatformSpace as j, PlatformUser as k, SchemaMessage as l };
|
|
346
|
+
export type { AnyPlatformDef as A, ContentBuilder as C, EventProducer as E, InboundMessage as I, Message as M, OutboundMessage as O, ProviderMessage as P, SpectrumLike as S, User as U, ContentInput as a, Content as b, PlatformDef as c, Platform as d, PlatformProviderConfig as e, CustomEventStreams as f, Space as g, PlatformInstance as h, PlatformMessage as i, PlatformSpace as j, PlatformUser as k, SchemaMessage as l };
|