import { telegramRequest } from './request.ts' import { boundedLimit, inputRecord, optionalInteger, secretNameFrom, } from './validation.ts' type TelegramChat = { id?: number type?: string title?: string username?: string first_name?: string [key: string]: unknown } type TelegramMessage = { message_id?: number date?: number text?: string caption?: string chat?: TelegramChat from?: { id?: number; username?: string; first_name?: string; is_bot?: boolean } [key: string]: unknown } type TelegramUpdate = { update_id?: number message?: TelegramMessage edited_message?: TelegramMessage channel_post?: TelegramMessage callback_query?: { id?: string data?: string from?: { id?: number; username?: string } message?: TelegramMessage } [key: string]: unknown } function summarizeChat(chat: TelegramChat | undefined) { if (!chat || typeof chat !== 'object') return null return { id: typeof chat.id === 'number' ? chat.id : null, type: typeof chat.type === 'string' ? chat.type : null, title: typeof chat.title === 'string' ? chat.title : null, username: typeof chat.username === 'string' ? chat.username : null, firstName: typeof chat.first_name === 'string' ? chat.first_name : null, } } function summarizeMessage(message: TelegramMessage | undefined) { if (!message || typeof message !== 'object') return null return { messageId: typeof message.message_id === 'number' ? message.message_id : null, date: typeof message.date === 'number' ? message.date : null, text: typeof message.text === 'string' ? message.text : null, caption: typeof message.caption === 'string' ? message.caption : null, chat: summarizeChat(message.chat), fromId: typeof message.from?.id === 'number' ? message.from.id : null, fromUsername: typeof message.from?.username === 'string' ? message.from.username : null, } } function summarizeUpdate(update: TelegramUpdate) { const kind = update.message ? 'message' : update.edited_message ? 'edited_message' : update.channel_post ? 'channel_post' : update.callback_query ? 'callback_query' : 'other' return { updateId: typeof update.update_id === 'number' ? update.update_id : null, kind, message: summarizeMessage( update.message ?? update.edited_message ?? update.channel_post, ), callbackQueryId: typeof update.callback_query?.id === 'string' ? update.callback_query.id : null, callbackData: typeof update.callback_query?.data === 'string' ? update.callback_query.data : null, } } /** * Read pending Bot API updates (polling). Bots cannot fetch arbitrary chat * history; they only see messages delivered via getUpdates or a webhook. * Passing offset acknowledges earlier updates. */ export default async function getUpdates(params: Record = {}) { const input = inputRecord(params) const secretName = secretNameFrom(input) const allowedUpdates = input.allowedUpdates if ( allowedUpdates !== undefined && (!Array.isArray(allowedUpdates) || allowedUpdates.some((item) => typeof item !== 'string')) ) { throw new Error('allowedUpdates must be an array of strings when provided.') } const result = await telegramRequest({ method: 'getUpdates', secretName, params: { offset: optionalInteger(input, 'offset'), limit: boundedLimit(input.limit, 20, 100), timeout: optionalInteger(input, 'timeout') ?? 0, allowed_updates: allowedUpdates, }, }) const updates = Array.isArray(result) ? result.map(summarizeUpdate) : [] const lastUpdateId = updates.reduce((max, update) => { if (typeof update.updateId === 'number' && update.updateId > max) { return update.updateId } return max }, 0) return { ok: true, count: updates.length, nextOffset: lastUpdateId > 0 ? lastUpdateId + 1 : null, updates, } }