mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-09-21 05:21:43 +00:00
feat(worker): native TDLib forward from source to destination channel
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { forwardArchiveToChannel } from "./forward.js";
|
||||
|
||||
function fakeClient(response: unknown) {
|
||||
return { invoke: vi.fn(async () => response) } as never;
|
||||
}
|
||||
|
||||
describe("forwardArchiveToChannel", () => {
|
||||
it("sorts message ids ascending and sends them via forwardMessages", async () => {
|
||||
const invoke = vi.fn(async (req: { message_ids: number[] }) => ({
|
||||
messages: req.message_ids.map((id) => ({ id: id + 1000 })),
|
||||
}));
|
||||
const client = { invoke } as never;
|
||||
|
||||
const result = await forwardArchiveToChannel(client, 111n, 222n, [30n, 10n, 20n]);
|
||||
|
||||
expect(invoke).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
_: "forwardMessages",
|
||||
chat_id: 222,
|
||||
from_chat_id: 111,
|
||||
message_ids: [10, 20, 30],
|
||||
send_copy: false,
|
||||
}),
|
||||
);
|
||||
expect(result.messageId).toBe(1010n);
|
||||
expect(result.messageIds).toEqual([1010n, 1020n, 1030n]);
|
||||
});
|
||||
|
||||
it("throws when Telegram returns null for a message (can't be forwarded)", async () => {
|
||||
const client = fakeClient({ messages: [{ id: 1001 }, null] });
|
||||
await expect(forwardArchiveToChannel(client, 111n, 222n, [10n, 20n])).rejects.toThrow(/could not forward/);
|
||||
});
|
||||
|
||||
it("throws when the response has the wrong number of messages", async () => {
|
||||
const client = fakeClient({ messages: [{ id: 1001 }] });
|
||||
await expect(forwardArchiveToChannel(client, 111n, 222n, [10n, 20n])).rejects.toThrow(/expected 2/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { Client } from "tdl";
|
||||
import { childLogger } from "../util/logger.js";
|
||||
import { withFloodWait } from "../util/retry.js";
|
||||
|
||||
const log = childLogger("forward");
|
||||
|
||||
export interface ForwardResult {
|
||||
messageId: bigint;
|
||||
messageIds: bigint[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward all parts of an archive set from the source chat directly to the
|
||||
* destination chat via TDLib's forwardMessages — no download, no re-upload.
|
||||
* Only usable when the source channel allows forwarding
|
||||
* (TelegramChannel.allowsForwarding); the caller is responsible for that
|
||||
* check. message_ids must be in strictly increasing order per the TDLib API,
|
||||
* so this always sorts them regardless of the order they're passed in.
|
||||
*/
|
||||
export async function forwardArchiveToChannel(
|
||||
client: Client,
|
||||
fromChatId: bigint,
|
||||
toChatId: bigint,
|
||||
sourceMessageIds: bigint[],
|
||||
): Promise<ForwardResult> {
|
||||
const sortedIds = [...sourceMessageIds].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
||||
const numericIds = sortedIds.map((id) => Number(id));
|
||||
|
||||
log.info(
|
||||
{ fromChatId: Number(fromChatId), toChatId: Number(toChatId), count: numericIds.length },
|
||||
"Forwarding archive to destination channel"
|
||||
);
|
||||
|
||||
const result = (await withFloodWait(
|
||||
() =>
|
||||
client.invoke({
|
||||
_: "forwardMessages",
|
||||
chat_id: Number(toChatId),
|
||||
topic_id: null,
|
||||
from_chat_id: Number(fromChatId),
|
||||
message_ids: numericIds,
|
||||
options: null,
|
||||
send_copy: false,
|
||||
remove_caption: false,
|
||||
} as never),
|
||||
"forwardMessages"
|
||||
)) as { messages: ({ id: number } | null)[] };
|
||||
|
||||
const forwarded = result.messages;
|
||||
if (!forwarded || forwarded.length !== numericIds.length) {
|
||||
throw new Error(
|
||||
`forwardMessages returned ${forwarded?.length ?? 0} messages, expected ${numericIds.length}`
|
||||
);
|
||||
}
|
||||
|
||||
const messageIds: bigint[] = [];
|
||||
for (let i = 0; i < forwarded.length; i++) {
|
||||
const msg = forwarded[i];
|
||||
if (!msg) {
|
||||
throw new Error(
|
||||
`forwardMessages could not forward source message ${sortedIds[i]} (Telegram returned null — message may not be forwardable)`
|
||||
);
|
||||
}
|
||||
messageIds.push(BigInt(msg.id));
|
||||
}
|
||||
|
||||
log.info(
|
||||
{ fromChatId: Number(fromChatId), toChatId: Number(toChatId), messageIds: messageIds.map(Number) },
|
||||
"Forward confirmed by Telegram"
|
||||
);
|
||||
|
||||
return { messageId: messageIds[0], messageIds };
|
||||
}
|
||||
Reference in New Issue
Block a user