diff --git a/src/telegram/bot-handlers.ts b/src/telegram/bot-handlers.ts index d0817c1f9da..e4d42cd889e 100644 --- a/src/telegram/bot-handlers.ts +++ b/src/telegram/bot-handlers.ts @@ -72,6 +72,14 @@ function isRecoverableMediaGroupError(err: unknown): boolean { return err instanceof MediaFetchError || isMediaSizeLimitError(err); } +function hasInboundMedia(msg: Message): boolean { + return ( + Boolean(msg.media_group_id) || + (Array.isArray(msg.photo) && msg.photo.length > 0) || + Boolean(msg.video ?? msg.video_note ?? msg.document ?? msg.audio ?? msg.voice ?? msg.sticker) + ); +} + export const registerTelegramHandlers = ({ cfg, accountId, @@ -1143,11 +1151,12 @@ export const registerTelegramHandlers = ({ if (shouldSkipUpdate(event.ctxForDedupe)) { return; } + const dmPolicy = telegramCfg.dmPolicy ?? "pairing"; const groupAllowContext = await resolveTelegramGroupAllowFromContext({ chatId: event.chatId, accountId, - dmPolicy: telegramCfg.dmPolicy ?? "pairing", + dmPolicy, isForum: event.isForum, messageThreadId: event.messageThreadId, groupAllowFrom, @@ -1161,6 +1170,11 @@ export const registerTelegramHandlers = ({ effectiveGroupAllow, hasGroupAllowOverride, } = groupAllowContext; + const effectiveDmAllow = normalizeAllowFromWithStore({ + allowFrom, + storeAllowFrom, + dmPolicy, + }); if (event.requireConfiguredGroup && (!groupConfig || groupConfig.enabled === false)) { logVerbose(`Blocked telegram channel ${event.chatId} (channel disabled)`); @@ -1184,26 +1198,10 @@ export const registerTelegramHandlers = ({ return; } - const hasInboundMedia = - Boolean(event.msg.media_group_id) || - (Array.isArray(event.msg.photo) && event.msg.photo.length > 0) || - Boolean( - event.msg.video ?? - event.msg.video_note ?? - event.msg.document ?? - event.msg.audio ?? - event.msg.voice ?? - event.msg.sticker, - ); - if (!event.isGroup && hasInboundMedia) { - const effectiveDmAllow = normalizeAllowFromWithStore({ - allowFrom, - storeAllowFrom, - dmPolicy: telegramCfg.dmPolicy ?? "pairing", - }); + if (!event.isGroup && hasInboundMedia(event.msg)) { const dmAuthorized = await enforceTelegramDmAccess({ isGroup: event.isGroup, - dmPolicy: telegramCfg.dmPolicy ?? "pairing", + dmPolicy, msg: event.msg, chatId: event.chatId, effectiveDmAllow, diff --git a/src/telegram/dm-access.ts b/src/telegram/dm-access.ts index 9d7e1d463e7..1c68dd43d69 100644 --- a/src/telegram/dm-access.ts +++ b/src/telegram/dm-access.ts @@ -11,6 +11,26 @@ type TelegramDmAccessLogger = { info: (obj: Record, msg: string) => void; }; +type TelegramSenderIdentity = { + username: string; + userId: string | null; + candidateId: string; + firstName?: string; + lastName?: string; +}; + +function resolveTelegramSenderIdentity(msg: Message, chatId: number): TelegramSenderIdentity { + const from = msg.from; + const userId = from?.id != null ? String(from.id) : null; + return { + username: from?.username ?? "", + userId, + candidateId: userId ?? String(chatId), + firstName: from?.first_name, + lastName: from?.last_name, + }; +} + export async function enforceTelegramDmAccess(params: { isGroup: boolean; dmPolicy: DmPolicy; @@ -32,13 +52,11 @@ export async function enforceTelegramDmAccess(params: { return true; } - const senderUsername = msg.from?.username ?? ""; - const senderUserId = msg.from?.id != null ? String(msg.from.id) : null; - const candidate = senderUserId ?? String(chatId); + const sender = resolveTelegramSenderIdentity(msg, chatId); const allowMatch = resolveSenderAllowMatch({ allow: effectiveDmAllow, - senderId: candidate, - senderUsername, + senderId: sender.candidateId, + senderUsername: sender.username, }); const allowMatchMeta = `matchKey=${allowMatch.matchKey ?? "none"} matchSource=${ allowMatch.matchSource ?? "none" @@ -51,33 +69,25 @@ export async function enforceTelegramDmAccess(params: { if (dmPolicy === "pairing") { try { - const from = msg.from as - | { - first_name?: string; - last_name?: string; - username?: string; - id?: number; - } - | undefined; - const telegramUserId = from?.id ? String(from.id) : candidate; + const telegramUserId = sender.userId ?? sender.candidateId; const { code, created } = await upsertChannelPairingRequest({ channel: "telegram", id: telegramUserId, accountId, meta: { - username: from?.username, - firstName: from?.first_name, - lastName: from?.last_name, + username: sender.username || undefined, + firstName: sender.firstName, + lastName: sender.lastName, }, }); if (created) { logger.info( { chatId: String(chatId), - senderUserId: senderUserId ?? undefined, - username: from?.username, - firstName: from?.first_name, - lastName: from?.last_name, + senderUserId: sender.userId ?? undefined, + username: sender.username || undefined, + firstName: sender.firstName, + lastName: sender.lastName, matchKey: allowMatch.matchKey ?? "none", matchSource: allowMatch.matchSource ?? "none", }, @@ -103,7 +113,7 @@ export async function enforceTelegramDmAccess(params: { } logVerbose( - `Blocked unauthorized telegram sender ${candidate} (dmPolicy=${dmPolicy}, ${allowMatchMeta})`, + `Blocked unauthorized telegram sender ${sender.candidateId} (dmPolicy=${dmPolicy}, ${allowMatchMeta})`, ); return false; }