mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-11 13:10:49 +08:00
Add Telegram and Discord IM channels
This commit is contained in:
parent
7123fce47a
commit
cb74e1c4c7
66 changed files with 8579 additions and 1910 deletions
81
src/channels/shared/editable-message-stream.mjs
Normal file
81
src/channels/shared/editable-message-stream.mjs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
export function splitMessageText(value, limit) {
|
||||
const text = typeof value === 'string' ? value.trim() : '';
|
||||
if (!text) return [];
|
||||
const chunks = [];
|
||||
let remaining = text;
|
||||
while (remaining.length > limit) {
|
||||
let cut = remaining.lastIndexOf('\n', limit);
|
||||
if (cut < Math.floor(limit * 0.55)) cut = remaining.lastIndexOf(' ', limit);
|
||||
if (cut < Math.floor(limit * 0.55)) cut = limit;
|
||||
chunks.push(remaining.slice(0, cut).trim());
|
||||
remaining = remaining.slice(cut).trimStart();
|
||||
}
|
||||
if (remaining) chunks.push(remaining);
|
||||
return chunks;
|
||||
}
|
||||
|
||||
export function createEditableMessageStream({
|
||||
initialText = '正在处理…',
|
||||
limit,
|
||||
updateIntervalMs = 800,
|
||||
create,
|
||||
edit,
|
||||
sendRemainder,
|
||||
logger = console,
|
||||
}) {
|
||||
let messageId;
|
||||
let pending = null;
|
||||
let timer = null;
|
||||
let inFlight = null;
|
||||
let closed = false;
|
||||
let lastSent = initialText;
|
||||
|
||||
const schedule = () => {
|
||||
if (closed || timer !== null || inFlight || !pending) return;
|
||||
timer = setTimeout(() => {
|
||||
timer = null;
|
||||
const text = pending;
|
||||
pending = null;
|
||||
const next = splitMessageText(text, limit)[0] ?? initialText;
|
||||
inFlight = Promise.resolve(next === lastSent ? undefined : edit(messageId, next))
|
||||
.then(() => { lastSent = next; })
|
||||
.catch((error) => logger.warn?.('[dsh-im] streamed message update failed:', error))
|
||||
.finally(() => {
|
||||
inFlight = null;
|
||||
schedule();
|
||||
});
|
||||
}, updateIntervalMs);
|
||||
timer?.unref?.();
|
||||
};
|
||||
|
||||
return {
|
||||
async start() {
|
||||
messageId = await create(initialText);
|
||||
return this;
|
||||
},
|
||||
update(text) {
|
||||
if (closed || typeof text !== 'string' || !text.trim()) return;
|
||||
pending = text;
|
||||
schedule();
|
||||
},
|
||||
async finish(text) {
|
||||
if (closed) throw new Error('Message stream is already closed');
|
||||
closed = true;
|
||||
if (timer !== null) clearTimeout(timer);
|
||||
timer = null;
|
||||
pending = null;
|
||||
await inFlight?.catch(() => undefined);
|
||||
const chunks = splitMessageText(text, limit);
|
||||
const first = chunks[0] ?? '处理完成。';
|
||||
if (first !== lastSent) await edit(messageId, first);
|
||||
lastSent = first;
|
||||
for (const chunk of chunks.slice(1)) await sendRemainder(chunk);
|
||||
},
|
||||
cancel() {
|
||||
closed = true;
|
||||
pending = null;
|
||||
if (timer !== null) clearTimeout(timer);
|
||||
timer = null;
|
||||
},
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue