fix(telegram): include forward_from_chat metadata in forwarded message context (#8133)
Extract missing metadata from forwarded Telegram messages: - Add fromChatType to TelegramForwardedContext, capturing the original chat type (channel/supergroup/group) from forward_from_chat.type and forward_origin.chat/sender_chat.type - Add fromMessageId to capture the original message ID from channel forwards - Read author_signature from forward_origin objects (modern API), preferring it over the deprecated forward_signature field - Pass ForwardedFromChatType and ForwardedFromMessageId through to the inbound context payload - Add test coverage for forward_origin channel/chat types, including author_signature extraction and fromChatType propagationmain
parent
da6de49815
commit
57566c5e4d
|
|
@ -56,6 +56,8 @@ export type MsgContext = {
|
||||||
ForwardedFromUsername?: string;
|
ForwardedFromUsername?: string;
|
||||||
ForwardedFromTitle?: string;
|
ForwardedFromTitle?: string;
|
||||||
ForwardedFromSignature?: string;
|
ForwardedFromSignature?: string;
|
||||||
|
ForwardedFromChatType?: string;
|
||||||
|
ForwardedFromMessageId?: number;
|
||||||
ForwardedDate?: number;
|
ForwardedDate?: number;
|
||||||
ThreadStarterBody?: string;
|
ThreadStarterBody?: string;
|
||||||
ThreadLabel?: string;
|
ThreadLabel?: string;
|
||||||
|
|
|
||||||
|
|
@ -598,6 +598,8 @@ export const buildTelegramMessageContext = async ({
|
||||||
ForwardedFromUsername: forwardOrigin?.fromUsername,
|
ForwardedFromUsername: forwardOrigin?.fromUsername,
|
||||||
ForwardedFromTitle: forwardOrigin?.fromTitle,
|
ForwardedFromTitle: forwardOrigin?.fromTitle,
|
||||||
ForwardedFromSignature: forwardOrigin?.fromSignature,
|
ForwardedFromSignature: forwardOrigin?.fromSignature,
|
||||||
|
ForwardedFromChatType: forwardOrigin?.fromChatType,
|
||||||
|
ForwardedFromMessageId: forwardOrigin?.fromMessageId,
|
||||||
ForwardedDate: forwardOrigin?.date ? forwardOrigin.date * 1000 : undefined,
|
ForwardedDate: forwardOrigin?.date ? forwardOrigin.date * 1000 : undefined,
|
||||||
Timestamp: msg.date ? msg.date * 1000 : undefined,
|
Timestamp: msg.date ? msg.date * 1000 : undefined,
|
||||||
WasMentioned: isGroup ? effectiveWasMentioned : undefined,
|
WasMentioned: isGroup ? effectiveWasMentioned : undefined,
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,90 @@ describe("normalizeForwardedContext", () => {
|
||||||
expect(ctx?.fromTitle).toBe("Hidden Name");
|
expect(ctx?.fromTitle).toBe("Hidden Name");
|
||||||
expect(ctx?.date).toBe(456);
|
expect(ctx?.date).toBe(456);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("handles forward_origin channel with author_signature and message_id", () => {
|
||||||
|
const ctx = normalizeForwardedContext({
|
||||||
|
forward_origin: {
|
||||||
|
type: "channel",
|
||||||
|
chat: {
|
||||||
|
title: "Tech News",
|
||||||
|
username: "technews",
|
||||||
|
id: -1001234,
|
||||||
|
type: "channel",
|
||||||
|
},
|
||||||
|
date: 500,
|
||||||
|
author_signature: "Editor",
|
||||||
|
message_id: 42,
|
||||||
|
},
|
||||||
|
// oxlint-disable-next-line typescript/no-explicit-any
|
||||||
|
} as any);
|
||||||
|
expect(ctx).not.toBeNull();
|
||||||
|
expect(ctx?.from).toBe("Tech News (Editor)");
|
||||||
|
expect(ctx?.fromType).toBe("channel");
|
||||||
|
expect(ctx?.fromId).toBe("-1001234");
|
||||||
|
expect(ctx?.fromUsername).toBe("technews");
|
||||||
|
expect(ctx?.fromTitle).toBe("Tech News");
|
||||||
|
expect(ctx?.fromSignature).toBe("Editor");
|
||||||
|
expect(ctx?.fromChatType).toBe("channel");
|
||||||
|
expect(ctx?.fromMessageId).toBe(42);
|
||||||
|
expect(ctx?.date).toBe(500);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles forward_origin chat with sender_chat and author_signature", () => {
|
||||||
|
const ctx = normalizeForwardedContext({
|
||||||
|
forward_origin: {
|
||||||
|
type: "chat",
|
||||||
|
sender_chat: {
|
||||||
|
title: "Discussion Group",
|
||||||
|
id: -1005678,
|
||||||
|
type: "supergroup",
|
||||||
|
},
|
||||||
|
date: 600,
|
||||||
|
author_signature: "Admin",
|
||||||
|
},
|
||||||
|
// oxlint-disable-next-line typescript/no-explicit-any
|
||||||
|
} as any);
|
||||||
|
expect(ctx).not.toBeNull();
|
||||||
|
expect(ctx?.from).toBe("Discussion Group (Admin)");
|
||||||
|
expect(ctx?.fromType).toBe("chat");
|
||||||
|
expect(ctx?.fromId).toBe("-1005678");
|
||||||
|
expect(ctx?.fromTitle).toBe("Discussion Group");
|
||||||
|
expect(ctx?.fromSignature).toBe("Admin");
|
||||||
|
expect(ctx?.fromChatType).toBe("supergroup");
|
||||||
|
expect(ctx?.date).toBe(600);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses author_signature from forward_origin", () => {
|
||||||
|
const ctx = normalizeForwardedContext({
|
||||||
|
forward_origin: {
|
||||||
|
type: "channel",
|
||||||
|
chat: { title: "My Channel", id: -100999, type: "channel" },
|
||||||
|
date: 700,
|
||||||
|
author_signature: "New Sig",
|
||||||
|
message_id: 1,
|
||||||
|
},
|
||||||
|
// oxlint-disable-next-line typescript/no-explicit-any
|
||||||
|
} as any);
|
||||||
|
expect(ctx).not.toBeNull();
|
||||||
|
expect(ctx?.fromSignature).toBe("New Sig");
|
||||||
|
expect(ctx?.from).toBe("My Channel (New Sig)");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles forward_origin channel without author_signature", () => {
|
||||||
|
const ctx = normalizeForwardedContext({
|
||||||
|
forward_origin: {
|
||||||
|
type: "channel",
|
||||||
|
chat: { title: "News", id: -100111, type: "channel" },
|
||||||
|
date: 900,
|
||||||
|
message_id: 1,
|
||||||
|
},
|
||||||
|
// oxlint-disable-next-line typescript/no-explicit-any
|
||||||
|
} as any);
|
||||||
|
expect(ctx).not.toBeNull();
|
||||||
|
expect(ctx?.from).toBe("News");
|
||||||
|
expect(ctx?.fromSignature).toBeUndefined();
|
||||||
|
expect(ctx?.fromChatType).toBe("channel");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("expandTextLinks", () => {
|
describe("expandTextLinks", () => {
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,10 @@ export type TelegramForwardedContext = {
|
||||||
fromUsername?: string;
|
fromUsername?: string;
|
||||||
fromTitle?: string;
|
fromTitle?: string;
|
||||||
fromSignature?: string;
|
fromSignature?: string;
|
||||||
|
/** Original chat type from forward_from_chat (e.g. "channel", "supergroup", "group"). */
|
||||||
|
fromChatType?: string;
|
||||||
|
/** Original message ID in the source chat (channel forwards). */
|
||||||
|
fromMessageId?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
function normalizeForwardedUserLabel(user: User) {
|
function normalizeForwardedUserLabel(user: User) {
|
||||||
|
|
@ -323,6 +327,7 @@ function buildForwardedContextFromChat(params: {
|
||||||
date?: number;
|
date?: number;
|
||||||
type: string;
|
type: string;
|
||||||
signature?: string;
|
signature?: string;
|
||||||
|
messageId?: number;
|
||||||
}): TelegramForwardedContext | null {
|
}): TelegramForwardedContext | null {
|
||||||
const fallbackKind = params.type === "channel" ? "channel" : "chat";
|
const fallbackKind = params.type === "channel" ? "channel" : "chat";
|
||||||
const { display, title, username, id } = normalizeForwardedChatLabel(params.chat, fallbackKind);
|
const { display, title, username, id } = normalizeForwardedChatLabel(params.chat, fallbackKind);
|
||||||
|
|
@ -331,6 +336,7 @@ function buildForwardedContextFromChat(params: {
|
||||||
}
|
}
|
||||||
const signature = params.signature?.trim() || undefined;
|
const signature = params.signature?.trim() || undefined;
|
||||||
const from = signature ? `${display} (${signature})` : display;
|
const from = signature ? `${display} (${signature})` : display;
|
||||||
|
const chatType = params.chat.type?.trim() || undefined;
|
||||||
return {
|
return {
|
||||||
from,
|
from,
|
||||||
date: params.date,
|
date: params.date,
|
||||||
|
|
@ -339,6 +345,8 @@ function buildForwardedContextFromChat(params: {
|
||||||
fromUsername: username,
|
fromUsername: username,
|
||||||
fromTitle: title,
|
fromTitle: title,
|
||||||
fromSignature: signature,
|
fromSignature: signature,
|
||||||
|
fromChatType: chatType,
|
||||||
|
fromMessageId: params.messageId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,6 +377,7 @@ function resolveForwardOrigin(origin: MessageOrigin): TelegramForwardedContext |
|
||||||
date: origin.date,
|
date: origin.date,
|
||||||
type: "channel",
|
type: "channel",
|
||||||
signature: origin.author_signature,
|
signature: origin.author_signature,
|
||||||
|
messageId: origin.message_id,
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
// Exhaustiveness guard: if Grammy adds a new MessageOrigin variant,
|
// Exhaustiveness guard: if Grammy adds a new MessageOrigin variant,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue