# 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)