Files
dsh-telegram-channel/lib/client.d.ts
T
RRRosmontis f3f6a3ebaf feat: admit photos and image documents into the bound session
Telegram 图片消息此前一律回复「暂只支持文本消息」。本改动:

- photo 取最大尺寸(TG 压成 jpeg),document 仅接受 image/png|jpeg|webp|gif
- caption 作为伴随文本块进入同一条消息(不解析为命令)
- 相册(同一 media_group_id)去抖 1.2s 合并为一条多图消息,避免 N 连回合
- 派发走宿主 sessions.prompt RPC(Web 端同通道):模型图像能力校验 +
  附件服务持久化 + mode queue 排队,与纯文本路径的 agent.followup 语义一致
- 错误映射:MODEL_DOES_NOT_SUPPORT_IMAGES → 提示换多模态模型;其余回退
  图片发送失败 + [code] 详情;下载失败即时提示
- 客户端新增 getFile/downloadFile(GET file 端点,复用代理感知 fetch)

tests +7(58/58):photo+caption、png document、pdf 拒绝、相册合并、
模型不支持、下载失败、未绑定。无 emoji 文案。
2026-09-05 17:51:21 +08:00

108 lines
3.5 KiB
TypeScript

export interface TelegramUser {
id: number;
is_bot?: boolean;
first_name?: string;
username?: string;
}
export interface TelegramChat {
id: number;
type: string;
title?: string;
username?: string;
}
export interface TelegramPhotoSize {
file_id: string;
file_unique_id: string;
width: number;
height: number;
file_size?: number;
}
export interface TelegramDocument {
file_id: string;
file_unique_id: string;
file_name?: string;
mime_type?: string;
file_size?: number;
}
export interface TelegramMessage {
message_id: number;
date: number;
chat: TelegramChat;
from?: TelegramUser;
text?: string;
/** Media caption (photos/documents); TG puts it here, not in `text`. */
caption?: string;
photo?: TelegramPhotoSize[];
document?: TelegramDocument;
/** Album grouping id: several photo updates share one media_group_id. */
media_group_id?: string;
}
export interface TelegramFile {
file_id: string;
file_unique_id: string;
file_size?: number;
file_path?: string;
}
export interface TelegramCallbackQuery {
id: string;
from: TelegramUser;
message?: TelegramMessage;
data?: string;
}
export interface TelegramUpdate {
update_id: number;
message?: TelegramMessage;
callback_query?: TelegramCallbackQuery;
}
export interface InlineKeyboardButton {
text: string;
callback_data: string;
}
export interface InlineKeyboardMarkup {
inline_keyboard: InlineKeyboardButton[][];
}
export interface TelegramBotCommand {
command: string;
description: string;
}
export interface TelegramInputRichMessage {
markdown: string;
skip_entity_detection?: boolean;
}
export interface TelegramClientOptions {
fetch?: typeof fetch;
baseUrl?: string;
pollingTimeoutSec?: number;
}
export interface TelegramClientLike {
getMe(): Promise<TelegramUser>;
getUpdates(offset?: number): Promise<TelegramUpdate[]>;
sendMessage(chatId: number, text: string, parseMode?: string, replyMarkup?: InlineKeyboardMarkup): Promise<TelegramMessage>;
sendRichMessage(chatId: number, markdown: string): Promise<TelegramMessage>;
sendChatAction(chatId: number, action: string): Promise<boolean>;
answerCallbackQuery(callbackQueryId: string, text?: string): Promise<boolean>;
setMyCommands(commands: TelegramBotCommand[]): Promise<boolean>;
/** Resolve a file_id to a file_path (downloadable URL suffix). */
getFile(fileId: string): Promise<TelegramFile>;
/** Download file bytes from the Bot API file endpoint (GET, proxy-aware). */
downloadFile(filePath: string): Promise<Uint8Array>;
}
export declare class TelegramClient implements TelegramClientLike {
private readonly token;
private readonly fetchImpl;
private readonly baseUrl;
private readonly pollingTimeoutSec;
constructor(token: string, options?: TelegramClientOptions);
private redact;
private call;
getMe(): Promise<TelegramUser>;
getUpdates(offset?: number): Promise<TelegramUpdate[]>;
sendMessage(chatId: number, text: string, parseMode?: string, replyMarkup?: InlineKeyboardMarkup): Promise<TelegramMessage>;
sendRichMessage(chatId: number, markdown: string): Promise<TelegramMessage>;
sendChatAction(chatId: number, action: string): Promise<boolean>;
answerCallbackQuery(callbackQueryId: string, text?: string): Promise<boolean>;
setMyCommands(commands: TelegramBotCommand[]): Promise<boolean>;
getFile(fileId: string): Promise<TelegramFile>;
downloadFile(filePath: string): Promise<Uint8Array>;
}