@spectrum-ts/whatsapp-business 11.0.0 → 11.2.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.
- package/dist/index.js +80 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TypedEventStream, button, buttons, createClient, list } from "@photon-ai/whatsapp-business";
|
|
2
2
|
import { UnsupportedError, cloud, definePlatform, mergeStreams, stream } from "@spectrum-ts/core";
|
|
3
|
-
import { asAttachment, asContact, asCustom, asGroup, asPollOption, asReaction, asText, createLogger, errorAttrs, tracedFetch } from "@spectrum-ts/core/authoring";
|
|
3
|
+
import { asAttachment, asContact, asCustom, asGroup, asPollOption, asReaction, asText, asUnsend, createLogger, errorAttrs, tracedFetch } from "@spectrum-ts/core/authoring";
|
|
4
4
|
import { extension } from "mime-types";
|
|
5
5
|
import z from "zod";
|
|
6
6
|
//#region src/auth.ts
|
|
@@ -296,6 +296,31 @@ const cachePoll = (client, messageId, poll) => {
|
|
|
296
296
|
if (first !== void 0) cache.delete(first);
|
|
297
297
|
}
|
|
298
298
|
};
|
|
299
|
+
const MAX_REACTION_CACHE_SIZE = 1e3;
|
|
300
|
+
const reactionCaches = /* @__PURE__ */ new WeakMap();
|
|
301
|
+
const reactionCacheKey = (reactedId, from) => `${reactedId}:${from}`;
|
|
302
|
+
const cacheReaction = (client, reactedId, from, entry) => {
|
|
303
|
+
let cache = reactionCaches.get(client);
|
|
304
|
+
if (!cache) {
|
|
305
|
+
cache = /* @__PURE__ */ new Map();
|
|
306
|
+
reactionCaches.set(client, cache);
|
|
307
|
+
}
|
|
308
|
+
const key = reactionCacheKey(reactedId, from);
|
|
309
|
+
cache.delete(key);
|
|
310
|
+
cache.set(key, entry);
|
|
311
|
+
if (cache.size > MAX_REACTION_CACHE_SIZE) {
|
|
312
|
+
const first = cache.keys().next().value;
|
|
313
|
+
if (first !== void 0) cache.delete(first);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
const getCachedReaction = (client, reactedId, from) => reactionCaches.get(client)?.get(reactionCacheKey(reactedId, from));
|
|
317
|
+
const reactionTargetStub = (reactedId) => ({
|
|
318
|
+
id: reactedId,
|
|
319
|
+
content: asCustom({
|
|
320
|
+
whatsapp_type: "reaction-target",
|
|
321
|
+
stub: true
|
|
322
|
+
})
|
|
323
|
+
});
|
|
299
324
|
const optionIndexFromId = (id) => {
|
|
300
325
|
if (!id.startsWith(OPTION_ID_PREFIX)) return;
|
|
301
326
|
const index = Number(id.slice(4));
|
|
@@ -395,6 +420,34 @@ const toMessages = (client, msg) => {
|
|
|
395
420
|
content: mapContent(client, msg)
|
|
396
421
|
}];
|
|
397
422
|
};
|
|
423
|
+
const mapReactionContent = (client, msg, reaction) => {
|
|
424
|
+
const reactedId = reaction.messageId;
|
|
425
|
+
if (!reaction.emoji) {
|
|
426
|
+
const cached = getCachedReaction(client, reactedId, msg.from);
|
|
427
|
+
return asUnsend({ target: cached ? {
|
|
428
|
+
id: cached.id,
|
|
429
|
+
content: asReaction({
|
|
430
|
+
emoji: cached.emoji,
|
|
431
|
+
target: reactionTargetStub(reactedId)
|
|
432
|
+
})
|
|
433
|
+
} : {
|
|
434
|
+
id: `${reactedId}:reaction:${msg.from}`,
|
|
435
|
+
content: asCustom({
|
|
436
|
+
whatsapp_type: "reaction-removed",
|
|
437
|
+
messageId: reactedId,
|
|
438
|
+
stub: true
|
|
439
|
+
})
|
|
440
|
+
} });
|
|
441
|
+
}
|
|
442
|
+
cacheReaction(client, reactedId, msg.from, {
|
|
443
|
+
id: msg.id,
|
|
444
|
+
emoji: reaction.emoji
|
|
445
|
+
});
|
|
446
|
+
return asReaction({
|
|
447
|
+
emoji: reaction.emoji,
|
|
448
|
+
target: reactionTargetStub(reactedId)
|
|
449
|
+
});
|
|
450
|
+
};
|
|
398
451
|
const mapContent = (client, msg) => {
|
|
399
452
|
const { content } = msg;
|
|
400
453
|
switch (content.type) {
|
|
@@ -416,19 +469,7 @@ const mapContent = (client, msg) => {
|
|
|
416
469
|
whatsapp_type: "location",
|
|
417
470
|
...content.location
|
|
418
471
|
});
|
|
419
|
-
case "reaction":
|
|
420
|
-
const stubTarget = {
|
|
421
|
-
id: content.reaction.messageId,
|
|
422
|
-
content: asCustom({
|
|
423
|
-
whatsapp_type: "reaction-target",
|
|
424
|
-
stub: true
|
|
425
|
-
})
|
|
426
|
-
};
|
|
427
|
-
return asReaction({
|
|
428
|
-
emoji: content.reaction.emoji,
|
|
429
|
-
target: stubTarget
|
|
430
|
-
});
|
|
431
|
-
}
|
|
472
|
+
case "reaction": return mapReactionContent(client, msg, content.reaction);
|
|
432
473
|
case "interactive": {
|
|
433
474
|
const inter = content.interactive;
|
|
434
475
|
if (inter.type === "button_reply" || inter.type === "list_reply") {
|
|
@@ -560,7 +601,19 @@ const clientStream = (client) => {
|
|
|
560
601
|
return stream((emit, end) => {
|
|
561
602
|
const pump = (async () => {
|
|
562
603
|
try {
|
|
563
|
-
for await (const event of eventStream)
|
|
604
|
+
for await (const event of eventStream) {
|
|
605
|
+
let mapped;
|
|
606
|
+
try {
|
|
607
|
+
mapped = toMessages(client, event.message);
|
|
608
|
+
} catch (error) {
|
|
609
|
+
streamLog.warn("skipping unmappable whatsapp message event", {
|
|
610
|
+
"spectrum.whatsapp.message_id": event.message.id,
|
|
611
|
+
...errorAttrs(error)
|
|
612
|
+
}, error instanceof Error ? error : void 0);
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
for (const m of mapped) await emit(m);
|
|
616
|
+
}
|
|
564
617
|
end();
|
|
565
618
|
} catch (e) {
|
|
566
619
|
end(e);
|
|
@@ -581,6 +634,18 @@ const send = async (clients, spaceId, content) => {
|
|
|
581
634
|
await primary(clients).messages.markRead(parentWamid(content.target.id));
|
|
582
635
|
return;
|
|
583
636
|
}
|
|
637
|
+
if (content.type === "unsend") {
|
|
638
|
+
const unsent = content.target.content;
|
|
639
|
+
if (unsent.type !== "reaction") throw UnsupportedError.content(content.type);
|
|
640
|
+
await primary(clients).messages.send({
|
|
641
|
+
to: spaceId,
|
|
642
|
+
reaction: {
|
|
643
|
+
messageId: parentWamid(unsent.target.id),
|
|
644
|
+
emoji: ""
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
584
649
|
const client = primary(clients);
|
|
585
650
|
switch (content.type) {
|
|
586
651
|
case "text": return toRecord(await client.messages.send({
|