fix: require thread specs for telegram sends

This commit is contained in:
Ayaan Zaidi
2026-02-02 09:05:36 +05:30
committed by Ayaan Zaidi
parent 19b8416a81
commit 1d7dd5f261
5 changed files with 22 additions and 20 deletions

View File

@@ -39,7 +39,7 @@ export async function deliverReplies(params: {
bot: Bot;
replyToMode: ReplyToMode;
textLimit: number;
thread?: TelegramThreadSpec | number | null;
thread?: TelegramThreadSpec | null;
tableMode?: MarkdownTableMode;
chunkMode?: ChunkMode;
/** Callback invoked before sending a voice message to switch typing indicator. */
@@ -451,7 +451,7 @@ async function sendTelegramVoiceFallbackText(opts: {
replyToId?: number;
replyToMode: ReplyToMode;
hasReplied: boolean;
thread?: TelegramThreadSpec | number | null;
thread?: TelegramThreadSpec | null;
linkPreview?: boolean;
replyMarkup?: ReturnType<typeof buildInlineKeyboard>;
replyQuoteText?: string;
@@ -479,7 +479,7 @@ async function sendTelegramVoiceFallbackText(opts: {
function buildTelegramSendParams(opts?: {
replyToMessageId?: number;
thread?: TelegramThreadSpec | number | null;
thread?: TelegramThreadSpec | null;
replyQuoteText?: string;
}): Record<string, unknown> {
const threadParams = buildTelegramThreadParams(opts?.thread);
@@ -509,7 +509,7 @@ async function sendTelegramText(
opts?: {
replyToMessageId?: number;
replyQuoteText?: string;
thread?: TelegramThreadSpec | number | null;
thread?: TelegramThreadSpec | null;
textMode?: "markdown" | "html";
plainText?: string;
linkPreview?: boolean;

View File

@@ -34,11 +34,13 @@ describe("resolveTelegramForumThreadId", () => {
describe("buildTelegramThreadParams", () => {
it("omits General topic thread id for message sends", () => {
expect(buildTelegramThreadParams(1)).toBeUndefined();
expect(buildTelegramThreadParams({ id: 1, scope: "forum" })).toBeUndefined();
});
it("includes non-General topic thread ids", () => {
expect(buildTelegramThreadParams(99)).toEqual({ message_thread_id: 99 });
expect(buildTelegramThreadParams({ id: 99, scope: "forum" })).toEqual({
message_thread_id: 99,
});
});
it("keeps thread id=1 for dm threads", () => {
@@ -48,7 +50,9 @@ describe("buildTelegramThreadParams", () => {
});
it("normalizes thread ids to integers", () => {
expect(buildTelegramThreadParams(42.9)).toEqual({ message_thread_id: 42 });
expect(buildTelegramThreadParams({ id: 42.9, scope: "forum" })).toEqual({
message_thread_id: 42,
});
});
});

View File

@@ -69,18 +69,12 @@ export function resolveTelegramThreadSpec(params: {
* General forum topic (id=1) must be treated like a regular supergroup send:
* Telegram rejects sendMessage/sendMedia with message_thread_id=1 ("thread not found").
*/
export function buildTelegramThreadParams(thread?: TelegramThreadSpec | number | null) {
let spec: TelegramThreadSpec | undefined;
if (typeof thread === "number") {
spec = { id: thread, scope: "forum" };
} else if (thread && typeof thread === "object") {
spec = thread;
}
if (!spec?.id) {
export function buildTelegramThreadParams(thread?: TelegramThreadSpec | null) {
if (!thread?.id) {
return undefined;
}
const normalized = Math.trunc(spec.id);
if (normalized === TELEGRAM_GENERAL_TOPIC_ID && spec.scope === "forum") {
const normalized = Math.trunc(thread.id);
if (normalized === TELEGRAM_GENERAL_TOPIC_ID && thread.scope === "forum") {
return undefined;
}
return { message_thread_id: normalized };

View File

@@ -15,7 +15,7 @@ export function createTelegramDraftStream(params: {
chatId: number;
draftId: number;
maxChars?: number;
thread?: TelegramThreadSpec | number | null;
thread?: TelegramThreadSpec | null;
throttleMs?: number;
log?: (message: string) => void;
warn?: (message: string) => void;

View File

@@ -221,7 +221,9 @@ export async function sendMessageTelegram(
// Only include these if actually provided to keep API calls clean.
const messageThreadId =
opts.messageThreadId != null ? opts.messageThreadId : target.messageThreadId;
const threadIdParams = buildTelegramThreadParams(messageThreadId);
const threadSpec =
messageThreadId != null ? { id: messageThreadId, scope: "forum" as const } : undefined;
const threadIdParams = buildTelegramThreadParams(threadSpec);
const threadParams: Record<string, unknown> = threadIdParams ? { ...threadIdParams } : {};
const quoteText = opts.quoteText?.trim();
if (opts.replyToMessageId != null) {
@@ -694,7 +696,9 @@ export async function sendStickerTelegram(
const messageThreadId =
opts.messageThreadId != null ? opts.messageThreadId : target.messageThreadId;
const threadIdParams = buildTelegramThreadParams(messageThreadId);
const threadSpec =
messageThreadId != null ? { id: messageThreadId, scope: "forum" as const } : undefined;
const threadIdParams = buildTelegramThreadParams(threadSpec);
const threadParams: Record<string, number> = threadIdParams ? { ...threadIdParams } : {};
if (opts.replyToMessageId != null) {
threadParams.reply_to_message_id = Math.trunc(opts.replyToMessageId);