# Telegram 集成 **本文引用的文件** - [src/index.ts](file://src/index.ts) - [src/command/index.ts](file://src/command/index.ts) - [src/command/handlers/start.ts](file://src/command/handlers/start.ts) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts) - [src/command/handlers/events.ts](file://src/command/handlers/events.ts) - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts) - [src/scheduler/index.ts](file://src/scheduler/index.ts) - [wrangler.jsonc](file://wrangler.jsonc) - [package.json](file://package.json) - [tsconfig.json](file://tsconfig.json) - [vitest.config.mts](file://vitest.config.mts) - [test/index.spec.ts](file://test/index.spec.ts) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本项目为基于 Cloudflare Workers 的 Telegram Bot,采用 grammY 框架与 @grammyjs/conversations 插件实现对话式交互,结合 Cloudflare KV 存储完成用户会话与凭证持久化。Bot 提供命令系统(/start、/login、/events、/history、/logout)以及事件浏览、预约、取消等完整业务流程;通过计划任务实现新活动推送通知。 ## 项目结构 - 入口与运行环境 - Worker 入口:src/index.ts,负责 Bot 初始化、命令菜单注册、Webhook 回调接入与定时任务调度。 - 配置:wrangler.jsonc 定义 Worker 名称、兼容日期、触发器、KV 绑定与变量。 - 命令系统 - src/command/index.ts:安装 conversations 插件、注册命令与回调查询处理器。 - 各命令处理器位于 src/command/handlers/ 下,按功能模块划分。 - 客户端 - src/client/cosmoe.ts:封装 Cosmoe API 客户端,统一认证、事件、预约、取消等接口。 - 调度器 - src/scheduler/index.ts:基于 Cron 触发,向已注册用户推送新活动通知。 - 测试与类型 - Vitest 配置与测试用例位于 test/ 与 vitest.config.mts。 - 类型声明位于 worker-configuration.d.ts(在 tsconfig 中引入)。 ```mermaid graph TB A["src/index.ts
Worker 入口"] --> B["src/command/index.ts
命令与对话注册"] B --> C["src/command/handlers/*.ts
命令处理器"] C --> D["src/client/cosmoe.ts
Cosmoe API 客户端"] A --> E["src/scheduler/index.ts
计划任务"] F["wrangler.jsonc
Worker 配置"] --> A G["package.json
依赖与脚本"] --> A H["tsconfig.json
TypeScript 配置"] --> A I["vitest.config.mts
测试配置"] --> J["test/index.spec.ts
单元/集成测试"] ``` 图表来源 - [src/index.ts](file://src/index.ts#L1-L47) - [src/command/index.ts](file://src/command/index.ts#L1-L110) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L1-L88) - [wrangler.jsonc](file://wrangler.jsonc#L1-L31) - [package.json](file://package.json#L1-L24) - [tsconfig.json](file://tsconfig.json#L1-L46) - [vitest.config.mts](file://vitest.config.mts#L1-L12) - [test/index.spec.ts](file://test/index.spec.ts#L1-L25) 章节来源 - [src/index.ts](file://src/index.ts#L1-L47) - [wrangler.jsonc](file://wrangler.jsonc#L1-L31) - [package.json](file://package.json#L1-L24) - [tsconfig.json](file://tsconfig.json#L1-L46) - [vitest.config.mts](file://vitest.config.mts#L1-L12) - [test/index.spec.ts](file://test/index.spec.ts#L1-L25) ## 核心组件 - Bot 实例与 Webhook - 在入口中创建带对话风味的 Bot 实例,解析 botInfo 并注册命令菜单,最后通过 webhookCallback 将请求交由 grammY 处理。 - 对话管理器(Conversations) - 使用 @grammyjs/conversations 与 @grammyjs/storage-cloudflare 的 KV 适配器,将对话状态持久化到 COSMOE_STORAGE。 - 在命令注册处安装 conversations 插件,并定义交互式登录对话“login”。 - 命令系统 - 注册 /start、/login、/events、/history、/logout 等命令;对特定格式的消息(如 /event_{id}、/book_{event_id}_{slot_id}、/cancel_{booking_id})使用 hears 与 callbackQuery 进行路由。 - API 客户端 - CosmoeClient 封装认证、事件列表、活动详情、预约、取消、历史等接口,支持设置/读取凭证与自动校验登录状态。 - 计划任务 - 通过 Cron 每分钟触发一次,对比最新事件 ID,向已注册用户发送新活动通知。 章节来源 - [src/index.ts](file://src/index.ts#L13-L46) - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88) ## 架构总览 下图展示从 Telegram 请求到业务处理与外部 API 调用的整体流程。 ```mermaid sequenceDiagram participant U as "用户" participant T as "Telegram" participant W as "Cloudflare Worker
src/index.ts" participant C as "命令系统
src/command/index.ts" participant H as "命令处理器
handlers/*.ts" participant K as "KV 存储
COSMOE_CREDENTIALS/COSMOE_STORAGE" participant API as "Cosmoe API
src/client/cosmoe.ts" U->>T : 发送命令/消息/回调 T->>W : HTTP 请求Webhook W->>C : 转发至 grammY Bot C->>H : 匹配命令/正则/回调 H->>K : 读写用户凭证/会话状态 H->>API : 调用认证/事件/预约/取消等接口 API-->>H : 返回业务数据 H-->>U : 发送消息/内联键盘/编辑消息 ``` 图表来源 - [src/index.ts](file://src/index.ts#L13-L46) - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L75) - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L4-L27) - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L4-L61) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L226) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L4-L107) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L11-L132) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) ## 详细组件分析 ### Bot 初始化与 Webhook 接入 - 创建带对话风味的 Bot 实例,注入 botInfo 与 token。 - 注册命令菜单 setMyCommands,异常捕获避免部署失败。 - 使用 webhookCallback("cloudflare-mod") 将请求交由 grammY 处理。 章节来源 - [src/index.ts](file://src/index.ts#L13-L46) ### 对话管理器(Conversations)与 KV 存储 - 使用 @grammyjs/storage-cloudflare 的 KvAdapter 作为对话存储后端。 - 自定义 KV 读写删除适配器,JSON 序列化对话状态。 - 安装 conversations 插件并注册交互式登录对话“login”。 ```mermaid flowchart TD Start(["进入对话"]) --> ReadKV["从 COSMOE_STORAGE 读取对话状态"] ReadKV --> State{"是否存在状态?"} State --> |否| Init["初始化状态"] State --> |是| Resume["恢复状态"] Init --> Run["执行对话步骤"] Resume --> Run Run --> Persist["写回 COSMOE_STORAGE"] Persist --> End(["结束对话"]) ``` 图表来源 - [src/command/index.ts](file://src/command/index.ts#L20-L52) 章节来源 - [src/command/index.ts](file://src/command/index.ts#L20-L52) ### 命令系统与路由 - /start:欢迎语与可用命令提示。 - /login:进入交互式登录对话,获取用户名/密码并调用 Cosmoe API 获取 token,存入 COSMOE_CREDENTIALS。 - /events:获取最近活动列表,生成命令链接。 - /event_{id}:显示活动详情与可预约时间段,含预约链接。 - /book_{event_id}_{slot_id}:根据索引选择时间段,处理优惠券选择与最终预约。 - /history:获取用户预约历史,含取消链接。 - /cancel_{booking_id}:发起取消确认,回调 confirm_cancel_* 或 cancel_action。 - /logout:删除用户凭证。 章节来源 - [src/command/index.ts](file://src/command/index.ts#L59-L110) - [src/command/handlers/start.ts](file://src/command/handlers/start.ts#L4-L6) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L75) - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L4-L27) - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L4-L61) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L226) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L4-L107) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L11-L132) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L10-L34) ### 内联键盘与回调查询 - 事件详情页:当时间段有余量且活动处于活跃期,为每个时间段生成“预约”链接。 - 优惠券选择:多优惠券时以内联键盘列出,回调格式 select_coupon_{event_id}_{slot_index}_{coupon_code|none}。 - 取消确认:内联键盘“确认/取消”,回调格式 confirm_cancel_{booking_id} 或 cancel_action。 ```mermaid sequenceDiagram participant U as "用户" participant H as "事件详情处理器" participant KB as "内联键盘" participant CB as "回调处理器" U->>H : 发送 /event_{id} H-->>U : 返回活动详情与可预约时间段 U->>KB : 点击“预约” KB-->>CB : 回调 /book_{event_id}_{slot_index} CB-->>U : 显示优惠券选择或直接预约 ``` 图表来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L40-L45) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L76-L117) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L60-L78) 章节来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L40-L45) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L76-L117) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L60-L78) ### 文件上传/下载与媒体资源 - 当前代码未实现文件上传/下载逻辑。 - 活动详情包含封面图与图集 URL,可在消息中直接展示或引导用户查看。 章节来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L50-L51) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L19-L50) ### 错误处理与重试策略 - 命令处理器普遍使用 try/catch 捕获异常并回复友好提示。 - KV 读写与 API 调用均包含错误日志输出,便于定位问题。 - 建议在关键路径增加指数退避重试与超时控制(当前未实现)。 章节来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L70-L74) - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L23-L26) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L103-L106) ### 用户体验优化 - Markdown 格式化消息,突出关键信息(活动名、时间、价格、状态)。 - 控制消息长度(历史记录限制),避免超出 Telegram API 限制。 - 取消操作提供二次确认,降低误操作风险。 章节来源 - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L94-L102) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L60-L78) ### 计划任务与推送通知 - Cron 每分钟触发一次,比较最新事件 ID,向所有已注册用户发送新活动通知。 - 使用 bot.api.sendMessage 推送 Markdown 格式消息。 ```mermaid flowchart TD S["Cron 触发"] --> L["读取最新事件ID"] L --> Q["拉取全部活动"] Q --> N{"存在新活动?"} N --> |否| E["结束"] N --> |是| U["遍历已注册用户"] U --> M["发送通知消息"] M --> R["更新最新事件ID"] R --> E ``` 图表来源 - [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88) 章节来源 - [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88) ## 依赖关系分析 - grammY 与 @grammyjs/conversations:提供 Bot 核心能力与对话管理。 - @grammyjs/storage-cloudflare:KV 存储适配器,用于对话状态持久化。 - Cloudflare KV:COSMOE_CREDENTIALS 存放用户凭证,COSMOE_STORAGE 存放对话状态与最新事件 ID。 - Cosmoe API:通过 CosmoeClient 统一访问认证、事件、预约、取消、历史等接口。 ```mermaid graph LR P["package.json 依赖"] --> G["grammy"] P --> C["@grammyjs/conversations"] P --> S["@grammyjs/storage-cloudflare"] G --> B["Bot 核心"] C --> V["对话插件"] S --> K["KV 适配器"] B --> H["命令/回调处理"] H --> X["CosmoeClient"] X --> A["Cosmoe API"] ``` 图表来源 - [package.json](file://package.json#L18-L22) 章节来源 - [package.json](file://package.json#L18-L22) - [wrangler.jsonc](file://wrangler.jsonc#L21-L30) ## 性能考虑 - KV 读写:对话状态与用户凭证频繁读写,建议在高并发场景下评估 KV 延迟与吞吐。 - API 调用:事件列表与历史记录可能返回大量数据,注意分页与截断(当前已做截断)。 - 消息长度:Markdown 消息超过阈值会被截断,确保用户体验一致。 - 计划任务:每分钟触发一次,建议在大规模用户场景下优化遍历与发送逻辑。 ## 故障排查指南 - Webhook 未生效 - 检查 Worker 是否正确暴露 fetch/scheduled 生命周期。 - 确认 Wrangler 配置与部署状态。 - 命令无响应 - 查看 setMyCommands 是否成功执行(入口已捕获异常)。 - 检查命令路由是否匹配(/event_、/book_、/cancel_)。 - 登录失败 - 确认 Cosmoe API 返回 code=200 且包含 user_id/token。 - 检查 KV 写入是否成功(COSMOE_CREDENTIALS)。 - 预约/取消异常 - 检查回调数据格式与解析逻辑。 - 确认 CosmoeClient 已设置正确的凭证。 - 计划任务未推送 - 检查 Cron 配置与 scheduled 生命周期。 - 确认 KV 中已存在用户键并可被枚举。 章节来源 - [src/index.ts](file://src/index.ts#L24-L32) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L46-L74) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L160-L226) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L18-L88) ## 结论 本项目以 grammY 为核心,结合 @grammyjs/conversations 与 Cloudflare KV,构建了完整的 Telegram Bot 业务闭环:从命令交互、内联键盘、回调处理到外部 API 调用与计划任务推送。建议后续增强错误重试、超时控制与限流策略,以提升稳定性与用户体验。 ## 附录 - 部署与开发 - 使用 Wrangler 部署与本地开发,脚本已在 package.json 中定义。 - Vitest 配置指向 wrangler.jsonc,便于集成测试。 - 类型与配置 - tsconfig.json 启用严格模式与 isolatedModules,确保类型安全。 - worker-configuration.d.ts 由 tsconfig 引入,提供 Cloudflare Worker 类型支持。 章节来源 - [package.json](file://package.json#L5-L11) - [vitest.config.mts](file://vitest.config.mts#L1-L12) - [tsconfig.json](file://tsconfig.json#L34-L42) - [test/index.spec.ts](file://test/index.spec.ts#L1-L25)