# 数据流设计 **本文引用的文件** - [src/index.ts](file://src/index.ts) - [src/command/index.ts](file://src/command/index.ts) - [src/client/cosmoe.ts](file://src/client/cosmoe.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/scheduler/index.ts](file://src/scheduler/index.ts) - [wrangler.jsonc](file://wrangler.jsonc) - [package.json](file://package.json) - [tsconfig.json](file://tsconfig.json) - [worker-configuration.d.ts](file://worker-configuration.d.ts) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) ## 简介 本设计文档围绕 Cosmoe Bot 的数据流进行系统性梳理,覆盖从 Telegram 用户消息进入 Cloudflare Workers,经由 grammY 框架解析与路由,到各命令处理器执行业务逻辑、调用 Cosmoe API 客户端访问外部服务,并通过 KV 存储完成状态持久化的完整链路。文档同时给出数据流向图、关键数据节点结构定义、缓存策略与一致性保障、异步处理与错误恢复机制等。 ## 项目结构 该项目采用按功能模块组织的目录结构,核心入口在 Cloudflare Workers 中,使用 grammY 作为 Telegram Bot 框架,配合 @grammyjs/conversations 实现对话式交互,使用 @grammyjs/storage-cloudflare 将会话状态持久化至 KV。 ```mermaid graph TB subgraph "Cloudflare Workers" A["src/index.ts
入口与webhook回调"] B["src/command/index.ts
命令注册与会话存储"] C["src/scheduler/index.ts
定时任务"] end subgraph "命令处理器" H1["start.ts"] H2["login.ts"] H3["events.ts"] H4["eventDetails.ts"] H5["bookEvent.ts"] H6["history.ts"] H7["cancel.ts"] H8["logout.ts"] end subgraph "外部服务" E["Telegram API"] F["Cosmoe API"] end subgraph "KV 存储" K1["COSMOE_CREDENTIALS
用户凭证"] K2["COSMOE_STORAGE
通用状态"] end A --> B A --> C B --> H1 B --> H2 B --> H3 B --> H4 B --> H5 B --> H6 B --> H7 B --> H8 H2 --> K1 H6 --> K1 H8 --> K1 H5 --> F H6 --> F H7 --> F H3 --> F H4 --> F C --> F C --> K2 ``` 图表来源 - [src/index.ts](file://src/index.ts#L1-L47) - [src/command/index.ts](file://src/command/index.ts#L1-L110) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L1-L88) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L1-L75) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L1-L107) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L1-L34) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L1-L226) - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L1-L27) - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L1-L61) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L1-L503) 章节来源 - [src/index.ts](file://src/index.ts#L1-L47) - [src/command/index.ts](file://src/command/index.ts#L1-L110) - [wrangler.jsonc](file://wrangler.jsonc#L1-L31) ## 核心组件 - 入口与 Webhook 回调:初始化 grammY Bot,设置命令菜单,将请求交由 Cloudflare 的 webhookCallback 处理。 - 命令注册与会话存储:安装 conversations 插件,使用 KV 适配器实现会话状态持久化;注册各类命令与回调处理器。 - 命令处理器:按功能拆分,包括启动引导、登录(对话式)、活动列表、活动详情、预约、历史、取消、登出等。 - Cosmoe API 客户端:封装认证、事件查询、个人资料、预约、取消、修改等 API 调用。 - 定时任务:周期性扫描新活动并向已注册用户推送通知。 - KV 存储:COSMOE_CREDENTIALS 保存用户凭证;COSMOE_STORAGE 保存通用状态(如最新活动 ID)。 章节来源 - [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#L1-L503) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L1-L88) - [wrangler.jsonc](file://wrangler.jsonc#L21-L30) ## 架构总览 下图展示从 Telegram 到 Cloudflare Workers、grammY、命令处理器、Cosmoe API 客户端以及 KV 存储的整体数据流。 ```mermaid sequenceDiagram participant U as "用户" participant T as "Telegram API" participant W as "Cloudflare Workers
src/index.ts" participant G as "grammY 框架" participant CMD as "命令处理器
src/command/handlers/*" participant KV as "KV 存储
COSMOE_CREDENTIALS/COSMOE_STORAGE" participant API as "Cosmoe API" U->>T : "发送消息/命令" T-->>W : "HTTP 请求" W->>G : "webhookCallback 分发" G->>CMD : "匹配命令/回调并执行" CMD->>KV : "读取/写入用户凭证/状态" CMD->>API : "调用 Cosmoe API" API-->>CMD : "返回业务数据" CMD-->>G : "构造响应" G-->>W : "生成 Telegram 响应" W-->>T : "回传消息" T-->>U : "显示结果" ``` 图表来源 - [src/index.ts](file://src/index.ts#L13-L35) - [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/history.ts](file://src/command/handlers/history.ts#L4-L107) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L226) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) - [wrangler.jsonc](file://wrangler.jsonc#L21-L30) ## 详细组件分析 ### 命令注册与会话存储(KV) - 会话存储:通过 @grammyjs/storage-cloudflare 的 KvAdapter 将会话状态序列化为 JSON 并写入 COSMOE_STORAGE。 - 登录对话:使用 createConversation 定义交互式登录流程,完成后将用户凭证写入 COSMOE_CREDENTIALS。 - 命令路由:注册 /start、/login、/events、/event_{id}、/book_{event}_{slot}、/history、/cancel_{id}、回调等。 ```mermaid flowchart TD Start(["进入 setupCommands"]) --> KV["创建 KV 适配器
绑定 COSMOE_STORAGE"] KV --> Conv["安装 conversations 插件
指定 storage=KV"] Conv --> Login["注册 /login 对话
enter('login')"] Login --> ReadCreds["读取用户凭证
COSMOE_CREDENTIALS"] ReadCreds --> ExecCmd["执行命令处理器"] ExecCmd --> WriteKV["写入 KV 状态/凭证"] WriteKV --> End(["完成"]) ``` 图表来源 - [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/index.ts](file://src/command/index.ts#L20-L110) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L75) ### 登录流程(对话式) - 用户输入用户名/密码,调用 CosmoeClient.getToken 获取 token。 - 将 user_id、token、timestamp 写入 COSMOE_CREDENTIALS,键为 Telegram 用户 ID。 - 异常处理:输入缺失、认证失败、KV 写入异常均进行友好提示与日志记录。 ```mermaid sequenceDiagram participant U as "用户" participant CMD as "handleInteractiveLogin" participant KV as "COSMOE_CREDENTIALS" participant API as "CosmoeClient.getToken" U->>CMD : "/login 进入对话" CMD->>U : "提示输入用户名" U-->>CMD : "用户名" CMD->>U : "提示输入密码" U-->>CMD : "密码" CMD->>API : "getToken(username,password)" API-->>CMD : "返回 {user_id,token}" CMD->>KV : "put(telegramUserId, JSON)" CMD-->>U : "登录成功提示" ``` 图表来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L75) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L124-L140) 章节来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L75) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L124-L140) ### 活动列表与详情 - /events:调用 getEvents 获取最新活动列表,拼接 Markdown 链接供用户点击 /event_{id}。 - /event_{id}:调用 getEventDetail 获取活动详情,渲染时间段、价格、剩余容量,并对可预约时间段提供 /book_{event}_{slot} 链接。 ```mermaid flowchart TD A["/events"] --> B["CosmoeClient.getEvents"] B --> C["筛选最新N条"] C --> D["拼装 Markdown 列表"] D --> E["发送消息"] F["/event_{id}"] --> G["CosmoeClient.getEventDetail"] G --> H["排序时间槽"] H --> I{"是否可预约"} I --> |是| J["生成 /book_{event}_{slot} 链接"] I --> |否| K["仅展示信息"] ``` 图表来源 - [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/client/cosmoe.ts](file://src/client/cosmoe.ts#L177-L200) 章节来源 - [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/client/cosmoe.ts](file://src/client/cosmoe.ts#L177-L200) ### 预约流程(含优惠券选择) - 解析 /book_{event}_{slot},校验用户登录态,获取活动详情与时间槽。 - 若存在多个可用优惠券,弹出内联键盘让用户选择;单个则自动使用。 - 调用 bookEvent 提交预约,返回最终价格、预约编号等信息。 ```mermaid sequenceDiagram participant U as "用户" participant CMD as "handleBookEvent" participant KV as "COSMOE_CREDENTIALS" participant API as "CosmoeClient" participant CB as "handleCouponSelection" U->>CMD : "/book_{event}_{slot}" CMD->>KV : "读取凭证" CMD->>API : "getEventDetail(eventId)" CMD->>API : "getAvailableCoupons(eventId)" alt 多个优惠券 CMD-->>U : "显示内联键盘选择" U->>CB : "回调 : select_coupon_{...}" CB->>API : "bookEvent(带coupon)" else 单个/无优惠券 CMD->>API : "bookEvent(直接提交)" end API-->>CMD : "返回预约结果" CMD-->>U : "发送成功/失败消息" ``` 图表来源 - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L226) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L247-L270) 章节来源 - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L226) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L247-L270) ### 历史与取消 - /history:读取用户凭证,调用 getMyBookings 获取预约历史,格式化 Markdown 并附带可取消链接。 - /cancel_{id}:弹出确认内联键盘,确认后调用 cancelBooking 执行取消。 ```mermaid flowchart TD H1["/history"] --> H2["读取凭证"] H2 --> H3["CosmoeClient.getMyBookings"] H3 --> H4["格式化 Markdown"] H4 --> H5["发送消息"] C1["/cancel_{id}"] --> C2["读取凭证"] C2 --> C3["获取预约详情"] C3 --> C4["内联键盘确认"] C4 --> C5["cancelBooking"] C5 --> C6["编辑消息反馈结果"] ``` 图表来源 - [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#L226-L239) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L405-L422) 章节来源 - [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#L226-L239) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L405-L422) ### 定时任务与通知 - 触发频率:每分钟一次(*/1 * * * *)。 - 逻辑:读取 COSMOE_STORAGE 中的 latestEventId,拉取全部活动,过滤新增活动,遍历 COSMOE_CREDENTIALS 中的用户键,逐个发送通知,并更新 latestEventId。 ```mermaid flowchart TD S["scheduled 触发"] --> L["读取 latestEventId"] L --> E["CosmoeClient.getEvents"] E --> F["过滤新活动"] F --> K["遍历已注册用户键"] K --> N["bot.api.sendMessage"] N --> U["更新 latestEventId"] ``` 图表来源 - [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L177-L184) 章节来源 - [src/scheduler/index.ts](file://src/scheduler/index.ts#L12-L88) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L177-L184) ### 关键数据节点结构定义 - 通用响应结构 - 字段:code、msg、data - 用途:统一承载 API 返回状态与数据 - 认证响应 - 字段:user_id、token - 用途:登录成功后返回,后续请求需携带 - 事件与活动详情 - 字段:id、name、description、event_date、cover_image_url、slots、gallery 等 - 用途:活动列表与详情展示 - 时间槽 - 字段:range、price、capacity、remaining - 用途:展示时间段、价格与剩余容量 - 用户资料与统计 - 字段:user_info、statistics - 用途:个人中心与历史记录 - 预约 - 字段:id、status、booking_date、time_slot、final_price、notes_by_user、event_name 等 - 用途:历史记录与取消操作 章节来源 - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L9-L105) ### 缓存策略与一致性 - KV 会话存储:使用 @grammyjs/storage-cloudflare 的 KvAdapter 将会话状态持久化至 COSMOE_STORAGE,确保多实例间会话一致性。 - 用户凭证:COSMOE_CREDENTIALS 以 Telegram 用户 ID 为键,存储 user_id、token、timestamp,便于命令处理器快速读取与鉴权。 - 通用状态:COSMOE_STORAGE 用于保存 latestEventId 等全局状态,避免重复推送。 - 一致性保障:KV 写入在登录、历史查询、取消等关键路径均有错误捕获与日志输出,保证异常可追踪;会话读写封装在 KV 适配器中,避免直接 KV 操作分散。 章节来源 - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L49-L63) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L26-L78) ### 异步处理与错误恢复 - 异步模型:grammY 与 Cloudflare Workers 均基于事件循环与 Promise,命令处理器与 API 调用均为异步。 - 错误恢复: - 命令处理器内部 try/catch 包裹,出现异常时向用户发送“稍后重试”提示并记录日志。 - KV 读写封装在会话存储中,异常时打印错误并继续执行,避免中断对话流程。 - 定时任务对每个用户的发送单独 try/catch,失败不影响其他用户的通知。 - 超时与可观测性:Wrangler 启用 observability,便于监控与排障。 章节来源 - [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) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L114-L117) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L65-L67) - [wrangler.jsonc](file://wrangler.jsonc#L10-L12) ## 依赖关系分析 - grammY 生态:grammy、@grammyjs/conversations、@grammyjs/storage-cloudflare。 - 运行时类型:通过 wrangler types 生成的 worker-configuration.d.ts 提供环境变量与运行时类型声明。 - 构建与脚本:使用 TypeScript 与 Vitest,部署与开发通过 Wrangler CLI。 ```mermaid graph LR P["package.json 依赖"] --> G["grammy"] P --> C["conversations"] P --> S["storage-cloudflare"] W["wrangler.jsonc 配置"] --> T["worker-configuration.d.ts 类型"] ``` 图表来源 - [package.json](file://package.json#L18-L22) - [wrangler.jsonc](file://wrangler.jsonc#L1-L31) - [worker-configuration.d.ts](file://worker-configuration.d.ts#L1-L10849) 章节来源 - [package.json](file://package.json#L18-L22) - [wrangler.jsonc](file://wrangler.jsonc#L1-L31) - [worker-configuration.d.ts](file://worker-configuration.d.ts#L1-L10849) ## 性能考量 - 会话存储:KV 读写为网络 IO,建议减少不必要的频繁写入;对话结束后及时清理临时状态。 - API 调用:批量获取活动与用户历史时注意分页与限流,避免超时。 - Markdown 渲染:历史消息长度限制在 4000 字符以内,防止 Telegram API 报错。 - 定时任务:每分钟触发一次,注意控制通知数量与并发发送,避免触发速率限制。 ## 故障排查指南 - 登录失败:检查用户名/密码是否正确,确认 CosmoeClient.getToken 返回 code=200;查看 KV 写入是否成功。 - 无凭证或凭证失效:确认 /login 是否执行成功,COSMOE_CREDENTIALS 中是否存在对应键;必要时执行 /logout 清理后重新登录。 - 预约失败:核对时间槽剩余容量,确认优惠券有效性;查看 bookEvent 返回的 msg 信息。 - 历史为空:确认用户是否有历史记录,或是否超过筛选条数上限。 - 定时通知未送达:检查 COSMOE_STORAGE 中 latestEventId 是否更新,确认 COSMOE_CREDENTIALS 中用户键是否有效;查看定时任务日志。 章节来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L67-L73) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L34-L37) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L137-L156) - [src/scheduler/index.ts](file://src/scheduler/index.ts#L59-L64) ## 结论 该系统通过 grammY 与 Cloudflare Workers 实现高可用的 Telegram Bot 数据流:用户消息经由 webhook 进入 Worker,命令处理器负责业务编排,Cosmoe API 客户端承担外部数据交互,KV 存储贯穿凭证与会话状态管理。整体具备清晰的模块边界、完善的错误处理与可观测性配置,适合在生产环境中稳定运行与扩展。