@theowlops/channelhub 1.0.0 → 1.1.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/channels/discord/adapter.d.ts +2 -0
- package/dist/channels/discord/index.js +13 -0
- package/dist/channels/slack/adapter.d.ts +2 -0
- package/dist/channels/slack/index.js +13 -0
- package/dist/channels/telegram/adapter.d.ts +2 -0
- package/dist/channels/telegram/index.js +18 -0
- package/dist/channels/zalo/adapter.d.ts +13 -1
- package/dist/channels/zalo/index.js +168 -31
- package/dist/core/context.d.ts +3 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +132 -0
- package/dist/core/stream.d.ts +16 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/index.cjs +345 -33
- package/dist/index.js +345 -33
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20548,9 +20548,9 @@ var require_websocket_server = __commonJS(function(exports2, module2) {
|
|
|
20548
20548
|
});
|
|
20549
20549
|
|
|
20550
20550
|
// node_modules/ws/wrapper.mjs
|
|
20551
|
-
var
|
|
20551
|
+
var import_stream2, import_extension, import_permessage_deflate, import_receiver, import_sender, import_subprotocol, import_websocket, import_websocket_server, wrapper_default;
|
|
20552
20552
|
var init_wrapper = __esm(() => {
|
|
20553
|
-
|
|
20553
|
+
import_stream2 = __toESM(require_stream(), 1);
|
|
20554
20554
|
import_extension = __toESM(require_extension(), 1);
|
|
20555
20555
|
import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
20556
20556
|
import_receiver = __toESM(require_receiver(), 1);
|
|
@@ -37520,6 +37520,7 @@ __export(exports_src, {
|
|
|
37520
37520
|
CommandRouter: () => CommandRouter,
|
|
37521
37521
|
DiscordChannelAdapter: () => DiscordChannelAdapter,
|
|
37522
37522
|
SlackChannelAdapter: () => SlackChannelAdapter,
|
|
37523
|
+
SmartStreamer: () => SmartStreamer,
|
|
37523
37524
|
TelegramChannelAdapter: () => TelegramChannelAdapter,
|
|
37524
37525
|
WebhookBridge: () => WebhookBridge,
|
|
37525
37526
|
Zalo: () => Zalo,
|
|
@@ -37563,6 +37564,126 @@ class ChannelEventBus extends import_node_events2.EventEmitter {
|
|
|
37563
37564
|
return this.emit("status", status);
|
|
37564
37565
|
}
|
|
37565
37566
|
}
|
|
37567
|
+
// src/core/stream.ts
|
|
37568
|
+
class SmartStreamer {
|
|
37569
|
+
adapter;
|
|
37570
|
+
options;
|
|
37571
|
+
constructor(adapter, options = {}) {
|
|
37572
|
+
this.adapter = adapter;
|
|
37573
|
+
this.options = {
|
|
37574
|
+
editDebounceMs: 1000,
|
|
37575
|
+
typingIntervalMs: 4000,
|
|
37576
|
+
chunkMode: "sentence",
|
|
37577
|
+
minSentenceLength: 60,
|
|
37578
|
+
initialPlaceholder: "...",
|
|
37579
|
+
...options
|
|
37580
|
+
};
|
|
37581
|
+
}
|
|
37582
|
+
async stream(chatId, tokenStream, sendOptions) {
|
|
37583
|
+
let typingActive = true;
|
|
37584
|
+
const triggerTyping = async () => {
|
|
37585
|
+
if (this.adapter.sendTyping) {
|
|
37586
|
+
try {
|
|
37587
|
+
await this.adapter.sendTyping(chatId);
|
|
37588
|
+
} catch {}
|
|
37589
|
+
}
|
|
37590
|
+
};
|
|
37591
|
+
await triggerTyping();
|
|
37592
|
+
const typingTimer = setInterval(() => {
|
|
37593
|
+
if (typingActive)
|
|
37594
|
+
triggerTyping();
|
|
37595
|
+
}, this.options.typingIntervalMs);
|
|
37596
|
+
try {
|
|
37597
|
+
if (typeof this.adapter.editText === "function") {
|
|
37598
|
+
return await this.streamWithEdit(chatId, tokenStream, sendOptions);
|
|
37599
|
+
} else {
|
|
37600
|
+
return await this.streamWithoutEdit(chatId, tokenStream, sendOptions);
|
|
37601
|
+
}
|
|
37602
|
+
} finally {
|
|
37603
|
+
typingActive = false;
|
|
37604
|
+
clearInterval(typingTimer);
|
|
37605
|
+
}
|
|
37606
|
+
}
|
|
37607
|
+
async streamWithEdit(chatId, tokenStream, sendOptions) {
|
|
37608
|
+
let accumulated = "";
|
|
37609
|
+
let sentMsg = null;
|
|
37610
|
+
let lastEditTime = 0;
|
|
37611
|
+
let pendingEditTimeout = null;
|
|
37612
|
+
const performEdit = async (text) => {
|
|
37613
|
+
if (sentMsg && this.adapter.editText) {
|
|
37614
|
+
await this.adapter.editText(chatId, sentMsg.messageId, text);
|
|
37615
|
+
lastEditTime = Date.now();
|
|
37616
|
+
}
|
|
37617
|
+
};
|
|
37618
|
+
for await (const chunk of tokenStream) {
|
|
37619
|
+
accumulated += chunk;
|
|
37620
|
+
if (!sentMsg) {
|
|
37621
|
+
sentMsg = await this.adapter.sendText(chatId, accumulated.trim() || this.options.initialPlaceholder, sendOptions);
|
|
37622
|
+
lastEditTime = Date.now();
|
|
37623
|
+
continue;
|
|
37624
|
+
}
|
|
37625
|
+
const now = Date.now();
|
|
37626
|
+
const elapsed = now - lastEditTime;
|
|
37627
|
+
if (elapsed >= this.options.editDebounceMs) {
|
|
37628
|
+
if (pendingEditTimeout) {
|
|
37629
|
+
clearTimeout(pendingEditTimeout);
|
|
37630
|
+
pendingEditTimeout = null;
|
|
37631
|
+
}
|
|
37632
|
+
await performEdit(accumulated);
|
|
37633
|
+
} else if (!pendingEditTimeout) {
|
|
37634
|
+
pendingEditTimeout = setTimeout(async () => {
|
|
37635
|
+
pendingEditTimeout = null;
|
|
37636
|
+
await performEdit(accumulated);
|
|
37637
|
+
}, this.options.editDebounceMs - elapsed);
|
|
37638
|
+
}
|
|
37639
|
+
}
|
|
37640
|
+
if (pendingEditTimeout) {
|
|
37641
|
+
clearTimeout(pendingEditTimeout);
|
|
37642
|
+
pendingEditTimeout = null;
|
|
37643
|
+
}
|
|
37644
|
+
if (sentMsg && accumulated) {
|
|
37645
|
+
await performEdit(accumulated);
|
|
37646
|
+
return [sentMsg];
|
|
37647
|
+
} else if (!sentMsg && accumulated) {
|
|
37648
|
+
const res = await this.adapter.sendText(chatId, accumulated, sendOptions);
|
|
37649
|
+
return [res];
|
|
37650
|
+
}
|
|
37651
|
+
return sentMsg ? [sentMsg] : [];
|
|
37652
|
+
}
|
|
37653
|
+
async streamWithoutEdit(chatId, tokenStream, sendOptions) {
|
|
37654
|
+
const results = [];
|
|
37655
|
+
if (this.options.chunkMode === "accumulate") {
|
|
37656
|
+
let accumulated = "";
|
|
37657
|
+
for await (const chunk of tokenStream) {
|
|
37658
|
+
accumulated += chunk;
|
|
37659
|
+
}
|
|
37660
|
+
if (accumulated.trim()) {
|
|
37661
|
+
const res = await this.adapter.sendText(chatId, accumulated, sendOptions);
|
|
37662
|
+
results.push(res);
|
|
37663
|
+
}
|
|
37664
|
+
return results;
|
|
37665
|
+
}
|
|
37666
|
+
let buffer = "";
|
|
37667
|
+
const sentenceEndRegex = /[.?!;\n]\s*$/;
|
|
37668
|
+
for await (const chunk of tokenStream) {
|
|
37669
|
+
buffer += chunk;
|
|
37670
|
+
if (buffer.length >= this.options.minSentenceLength && sentenceEndRegex.test(buffer.trimEnd())) {
|
|
37671
|
+
const textToSend = buffer.trim();
|
|
37672
|
+
if (textToSend) {
|
|
37673
|
+
const res = await this.adapter.sendText(chatId, textToSend, sendOptions);
|
|
37674
|
+
results.push(res);
|
|
37675
|
+
buffer = "";
|
|
37676
|
+
}
|
|
37677
|
+
}
|
|
37678
|
+
}
|
|
37679
|
+
if (buffer.trim()) {
|
|
37680
|
+
const res = await this.adapter.sendText(chatId, buffer.trim(), sendOptions);
|
|
37681
|
+
results.push(res);
|
|
37682
|
+
}
|
|
37683
|
+
return results;
|
|
37684
|
+
}
|
|
37685
|
+
}
|
|
37686
|
+
|
|
37566
37687
|
// src/core/context.ts
|
|
37567
37688
|
function createMessageContext(message, channel) {
|
|
37568
37689
|
return {
|
|
@@ -37580,6 +37701,17 @@ function createMessageContext(message, channel) {
|
|
|
37580
37701
|
if (channel.addReaction) {
|
|
37581
37702
|
await channel.addReaction(message.chat.id, message.id, emoji);
|
|
37582
37703
|
}
|
|
37704
|
+
},
|
|
37705
|
+
sendTyping: async () => {
|
|
37706
|
+
if (channel.sendTyping) {
|
|
37707
|
+
await channel.sendTyping(message.chat.id);
|
|
37708
|
+
}
|
|
37709
|
+
},
|
|
37710
|
+
stream: async (tokenStream, options) => {
|
|
37711
|
+
const streamer = new SmartStreamer(channel, options);
|
|
37712
|
+
return await streamer.stream(message.chat.id, tokenStream, {
|
|
37713
|
+
replyToId: message.id
|
|
37714
|
+
});
|
|
37583
37715
|
}
|
|
37584
37716
|
};
|
|
37585
37717
|
}
|
|
@@ -37627,14 +37759,47 @@ class ChannelHub {
|
|
|
37627
37759
|
}
|
|
37628
37760
|
}
|
|
37629
37761
|
// src/channels/zalo/adapter.ts
|
|
37762
|
+
var EMOJI_TO_ZALO = {
|
|
37763
|
+
"❤️": "HEART",
|
|
37764
|
+
"\uD83D\uDC96": "HEART",
|
|
37765
|
+
"\uD83D\uDC4D": "LIKE",
|
|
37766
|
+
"\uD83D\uDE06": "HAHA",
|
|
37767
|
+
"\uD83D\uDE02": "TEARS_OF_JOY",
|
|
37768
|
+
"\uD83D\uDE2E": "WOW",
|
|
37769
|
+
"\uD83D\uDE2D": "CRY",
|
|
37770
|
+
"\uD83D\uDE21": "ANGRY",
|
|
37771
|
+
"\uD83D\uDE18": "KISS",
|
|
37772
|
+
"\uD83D\uDCA9": "SHIT",
|
|
37773
|
+
"\uD83C\uDF39": "ROSE",
|
|
37774
|
+
"\uD83D\uDC94": "BROKEN_HEART",
|
|
37775
|
+
"\uD83D\uDC4E": "DISLIKE",
|
|
37776
|
+
"\uD83D\uDE0D": "LOVE",
|
|
37777
|
+
"\uD83E\uDD14": "CONFUSED",
|
|
37778
|
+
"\uD83D\uDE09": "WINK",
|
|
37779
|
+
heart: "HEART",
|
|
37780
|
+
like: "LIKE",
|
|
37781
|
+
haha: "HAHA",
|
|
37782
|
+
wow: "WOW",
|
|
37783
|
+
cry: "CRY",
|
|
37784
|
+
angry: "ANGRY"
|
|
37785
|
+
};
|
|
37786
|
+
|
|
37630
37787
|
class ZaloChannelAdapter extends BaseChannel {
|
|
37631
37788
|
name = "zalo";
|
|
37632
37789
|
api;
|
|
37633
37790
|
ownId;
|
|
37634
37791
|
config;
|
|
37792
|
+
threadTypeCache = new Map;
|
|
37793
|
+
messageCache = new Map;
|
|
37794
|
+
sendQueue = Promise.resolve();
|
|
37635
37795
|
constructor(config = {}) {
|
|
37636
37796
|
super();
|
|
37637
|
-
this.config =
|
|
37797
|
+
this.config = {
|
|
37798
|
+
minDelayMs: 300,
|
|
37799
|
+
maxDelayMs: 800,
|
|
37800
|
+
cacheLimit: 1000,
|
|
37801
|
+
...config
|
|
37802
|
+
};
|
|
37638
37803
|
if (config.api) {
|
|
37639
37804
|
this.api = config.api;
|
|
37640
37805
|
}
|
|
@@ -37669,17 +37834,101 @@ class ZaloChannelAdapter extends BaseChannel {
|
|
|
37669
37834
|
if (!this.api?.listener?.on)
|
|
37670
37835
|
return;
|
|
37671
37836
|
this.api.listener.on("message", (raw) => {
|
|
37837
|
+
this.recordInbound(raw);
|
|
37672
37838
|
const unified = this.normalizeMessage(raw);
|
|
37673
37839
|
if (unified) {
|
|
37674
37840
|
this.emit("message", unified);
|
|
37675
37841
|
}
|
|
37676
37842
|
});
|
|
37843
|
+
const onSessionDrop = (err) => {
|
|
37844
|
+
this.emit("session:expired", {
|
|
37845
|
+
reason: "SESSION_EXPIRED_OR_DROPPED",
|
|
37846
|
+
raw: err,
|
|
37847
|
+
requiresQrScan: true
|
|
37848
|
+
});
|
|
37849
|
+
this.setConnected(false);
|
|
37850
|
+
};
|
|
37851
|
+
this.api.listener.on("closed", onSessionDrop);
|
|
37852
|
+
this.api.listener.on("error", (err) => {
|
|
37853
|
+
const msg = String(err?.message || err);
|
|
37854
|
+
if (msg.includes("1002") || msg.includes("session") || msg.includes("auth")) {
|
|
37855
|
+
onSessionDrop(err);
|
|
37856
|
+
}
|
|
37857
|
+
});
|
|
37677
37858
|
if (this.api.listener.start) {
|
|
37678
37859
|
try {
|
|
37679
37860
|
this.api.listener.start();
|
|
37680
37861
|
} catch {}
|
|
37681
37862
|
}
|
|
37682
37863
|
}
|
|
37864
|
+
recordInbound(raw) {
|
|
37865
|
+
if (!raw)
|
|
37866
|
+
return;
|
|
37867
|
+
const data = raw.data || raw;
|
|
37868
|
+
const isGroup = raw.type === 1 || raw.type === "group" || Boolean(raw.isGroup);
|
|
37869
|
+
const chatId = String(raw.threadId || data.idTo || data.threadId || "");
|
|
37870
|
+
const msgId = String(data.msgId || raw.msgId || "");
|
|
37871
|
+
const cliMsgId = data.cliMsgId ? String(data.cliMsgId) : undefined;
|
|
37872
|
+
const uidFrom = String(data.uidFrom || raw.senderId || "");
|
|
37873
|
+
const content = typeof data.content === "string" ? data.content : data.msg || "";
|
|
37874
|
+
if (chatId) {
|
|
37875
|
+
this.threadTypeCache.set(chatId, isGroup ? 1 : 0);
|
|
37876
|
+
}
|
|
37877
|
+
const cached = {
|
|
37878
|
+
msgId,
|
|
37879
|
+
cliMsgId,
|
|
37880
|
+
uidFrom,
|
|
37881
|
+
content,
|
|
37882
|
+
threadId: chatId,
|
|
37883
|
+
isGroup
|
|
37884
|
+
};
|
|
37885
|
+
const limit = this.config.cacheLimit || 1000;
|
|
37886
|
+
if (this.messageCache.size >= limit) {
|
|
37887
|
+
const firstKey = this.messageCache.keys().next().value;
|
|
37888
|
+
if (firstKey)
|
|
37889
|
+
this.messageCache.delete(firstKey);
|
|
37890
|
+
}
|
|
37891
|
+
if (msgId)
|
|
37892
|
+
this.messageCache.set(msgId, cached);
|
|
37893
|
+
if (cliMsgId)
|
|
37894
|
+
this.messageCache.set(cliMsgId, cached);
|
|
37895
|
+
}
|
|
37896
|
+
resolveThreadType(chatId) {
|
|
37897
|
+
if (this.threadTypeCache.has(chatId)) {
|
|
37898
|
+
return this.threadTypeCache.get(chatId);
|
|
37899
|
+
}
|
|
37900
|
+
return this.config.defaultIsGroup ?? true ? 1 : 0;
|
|
37901
|
+
}
|
|
37902
|
+
resolveQuote(replyToId) {
|
|
37903
|
+
if (!replyToId)
|
|
37904
|
+
return;
|
|
37905
|
+
const cached = this.messageCache.get(replyToId);
|
|
37906
|
+
if (cached) {
|
|
37907
|
+
return {
|
|
37908
|
+
msgId: cached.msgId,
|
|
37909
|
+
cliMsgId: cached.cliMsgId,
|
|
37910
|
+
uidFrom: cached.uidFrom,
|
|
37911
|
+
content: cached.content
|
|
37912
|
+
};
|
|
37913
|
+
}
|
|
37914
|
+
return replyToId;
|
|
37915
|
+
}
|
|
37916
|
+
async enqueueSend(operation) {
|
|
37917
|
+
const minDelay = this.config.minDelayMs ?? 300;
|
|
37918
|
+
const maxDelay = this.config.maxDelayMs ?? 800;
|
|
37919
|
+
const execute = async () => {
|
|
37920
|
+
if (maxDelay > 0) {
|
|
37921
|
+
const jitter = Math.floor(minDelay + Math.random() * Math.max(0, maxDelay - minDelay));
|
|
37922
|
+
if (jitter > 0) {
|
|
37923
|
+
await new Promise((r) => setTimeout(r, jitter));
|
|
37924
|
+
}
|
|
37925
|
+
}
|
|
37926
|
+
return await operation();
|
|
37927
|
+
};
|
|
37928
|
+
const next = this.sendQueue.then(execute, execute);
|
|
37929
|
+
this.sendQueue = next.catch(() => {});
|
|
37930
|
+
return next;
|
|
37931
|
+
}
|
|
37683
37932
|
normalizeMessage(raw) {
|
|
37684
37933
|
if (!raw)
|
|
37685
37934
|
return null;
|
|
@@ -37713,41 +37962,60 @@ class ZaloChannelAdapter extends BaseChannel {
|
|
|
37713
37962
|
async sendText(chatId, text, options) {
|
|
37714
37963
|
if (!this.api)
|
|
37715
37964
|
throw new Error("Zalo adapter is not connected.");
|
|
37716
|
-
const
|
|
37717
|
-
const
|
|
37718
|
-
const payload = { msg: text, quote
|
|
37719
|
-
|
|
37720
|
-
|
|
37721
|
-
|
|
37722
|
-
|
|
37723
|
-
|
|
37724
|
-
|
|
37725
|
-
|
|
37965
|
+
const threadType = this.resolveThreadType(chatId);
|
|
37966
|
+
const quote = this.resolveQuote(options?.replyToId);
|
|
37967
|
+
const payload = { msg: text, quote };
|
|
37968
|
+
return await this.enqueueSend(async () => {
|
|
37969
|
+
const res = await this.api.sendMessage(payload, chatId, threadType);
|
|
37970
|
+
const resMsgId = res?.message?.msgId || res?.msgId || `z-${Date.now()}`;
|
|
37971
|
+
return {
|
|
37972
|
+
messageId: String(resMsgId),
|
|
37973
|
+
chatId,
|
|
37974
|
+
timestamp: Date.now()
|
|
37975
|
+
};
|
|
37976
|
+
});
|
|
37726
37977
|
}
|
|
37727
|
-
async sendMedia(chatId, media,
|
|
37978
|
+
async sendMedia(chatId, media, options) {
|
|
37728
37979
|
if (!this.api)
|
|
37729
37980
|
throw new Error("Zalo adapter is not connected.");
|
|
37730
|
-
const
|
|
37731
|
-
const
|
|
37732
|
-
|
|
37733
|
-
|
|
37734
|
-
|
|
37735
|
-
|
|
37736
|
-
|
|
37737
|
-
|
|
37738
|
-
|
|
37739
|
-
|
|
37740
|
-
|
|
37741
|
-
|
|
37742
|
-
|
|
37743
|
-
|
|
37744
|
-
|
|
37745
|
-
|
|
37981
|
+
const threadType = this.resolveThreadType(chatId);
|
|
37982
|
+
const quote = this.resolveQuote(options?.replyToId);
|
|
37983
|
+
return await this.enqueueSend(async () => {
|
|
37984
|
+
let res;
|
|
37985
|
+
if (media.type === "image") {
|
|
37986
|
+
res = await this.api.sendMessage({ msg: media.caption || "", attachments: [media.source], quote }, chatId, threadType);
|
|
37987
|
+
} else if (media.type === "video" && this.api.sendVideo) {
|
|
37988
|
+
res = await this.api.sendVideo({ video: media.source, msg: media.caption || "", quote }, chatId, threadType);
|
|
37989
|
+
} else {
|
|
37990
|
+
res = await this.api.sendMessage({ msg: media.caption || "", attachments: [media.source], quote }, chatId, threadType);
|
|
37991
|
+
}
|
|
37992
|
+
const resMsgId = res?.message?.msgId || res?.msgId || `z-${Date.now()}`;
|
|
37993
|
+
return {
|
|
37994
|
+
messageId: String(resMsgId),
|
|
37995
|
+
chatId,
|
|
37996
|
+
timestamp: Date.now()
|
|
37997
|
+
};
|
|
37998
|
+
});
|
|
37746
37999
|
}
|
|
37747
38000
|
async addReaction(chatId, messageId, emoji) {
|
|
37748
|
-
if (this.api?.addReaction)
|
|
37749
|
-
|
|
37750
|
-
|
|
38001
|
+
if (!this.api?.addReaction)
|
|
38002
|
+
return;
|
|
38003
|
+
const threadType = this.resolveThreadType(chatId);
|
|
38004
|
+
const isGroup = threadType === 1;
|
|
38005
|
+
const reactionCode = EMOJI_TO_ZALO[emoji] || emoji;
|
|
38006
|
+
const cached = this.messageCache.get(messageId);
|
|
38007
|
+
const cliMsgId = cached?.cliMsgId || messageId;
|
|
38008
|
+
await this.enqueueSend(async () => {
|
|
38009
|
+
await this.api.addReaction(chatId, messageId, cliMsgId, reactionCode, threadType);
|
|
38010
|
+
});
|
|
38011
|
+
}
|
|
38012
|
+
async sendTyping(chatId) {
|
|
38013
|
+
if (!this.api?.sendTypingEvent)
|
|
38014
|
+
return;
|
|
38015
|
+
const threadType = this.resolveThreadType(chatId);
|
|
38016
|
+
try {
|
|
38017
|
+
await this.api.sendTypingEvent(chatId, true, threadType);
|
|
38018
|
+
} catch {}
|
|
37751
38019
|
}
|
|
37752
38020
|
}
|
|
37753
38021
|
// src/personal/client.ts
|
|
@@ -38625,6 +38893,24 @@ class TelegramChannelAdapter extends BaseChannel {
|
|
|
38625
38893
|
reaction: [{ type: "emoji", emoji }]
|
|
38626
38894
|
});
|
|
38627
38895
|
}
|
|
38896
|
+
async sendTyping(chatId) {
|
|
38897
|
+
await this.callApi("sendChatAction", {
|
|
38898
|
+
chat_id: chatId,
|
|
38899
|
+
action: "typing"
|
|
38900
|
+
});
|
|
38901
|
+
}
|
|
38902
|
+
async editText(chatId, messageId, text) {
|
|
38903
|
+
const res = await this.callApi("editMessageText", {
|
|
38904
|
+
chat_id: chatId,
|
|
38905
|
+
message_id: Number(messageId),
|
|
38906
|
+
text
|
|
38907
|
+
});
|
|
38908
|
+
return {
|
|
38909
|
+
messageId: String(res.message_id || messageId),
|
|
38910
|
+
chatId,
|
|
38911
|
+
timestamp: Date.now()
|
|
38912
|
+
};
|
|
38913
|
+
}
|
|
38628
38914
|
}
|
|
38629
38915
|
// src/channels/discord/adapter.ts
|
|
38630
38916
|
class DiscordChannelAdapter extends BaseChannel {
|
|
@@ -38735,6 +39021,19 @@ class DiscordChannelAdapter extends BaseChannel {
|
|
|
38735
39021
|
const encoded = encodeURIComponent(emoji);
|
|
38736
39022
|
await this.callApi("PUT", `/channels/${chatId}/messages/${messageId}/reactions/${encoded}/@me`);
|
|
38737
39023
|
}
|
|
39024
|
+
async sendTyping(chatId) {
|
|
39025
|
+
await this.callApi("POST", `/channels/${chatId}/typing`, {});
|
|
39026
|
+
}
|
|
39027
|
+
async editText(chatId, messageId, text) {
|
|
39028
|
+
const res = await this.callApi("PATCH", `/channels/${chatId}/messages/${messageId}`, {
|
|
39029
|
+
content: text
|
|
39030
|
+
});
|
|
39031
|
+
return {
|
|
39032
|
+
messageId: String(res.id || messageId),
|
|
39033
|
+
chatId,
|
|
39034
|
+
timestamp: Date.now()
|
|
39035
|
+
};
|
|
39036
|
+
}
|
|
38738
39037
|
}
|
|
38739
39038
|
// src/channels/slack/adapter.ts
|
|
38740
39039
|
class SlackChannelAdapter extends BaseChannel {
|
|
@@ -38837,6 +39136,19 @@ class SlackChannelAdapter extends BaseChannel {
|
|
|
38837
39136
|
name: cleanName
|
|
38838
39137
|
});
|
|
38839
39138
|
}
|
|
39139
|
+
async sendTyping(chatId) {}
|
|
39140
|
+
async editText(chatId, messageId, text) {
|
|
39141
|
+
const res = await this.callApi("chat.update", {
|
|
39142
|
+
channel: chatId,
|
|
39143
|
+
ts: messageId,
|
|
39144
|
+
text
|
|
39145
|
+
});
|
|
39146
|
+
return {
|
|
39147
|
+
messageId: String(res.ts || messageId),
|
|
39148
|
+
chatId,
|
|
39149
|
+
timestamp: Date.now()
|
|
39150
|
+
};
|
|
39151
|
+
}
|
|
38840
39152
|
}
|
|
38841
39153
|
// src/bridges/mcp/index.ts
|
|
38842
39154
|
function getChannelHubMcpTools() {
|