# 交互式命令 **本文引用的文件** - [src/command/index.ts](file://src/command/index.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/history.ts](file://src/command/handlers/history.ts) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts) - [src/command/handlers/start.ts](file://src/command/handlers/start.ts) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts) - [package.json](file://package.json) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件聚焦于交互式命令的实现与设计,围绕以下命令展开: - /events:列出最近的摄影活动,并以“/event_{id}”链接引导查看详情 - /event_{id}:展示活动详情、时间槽与预约入口 - /history:展示用户的预约历史,并提供“/cancel_{booking_id}”取消入口 - /book_{event_id}_{slot_index}:基于回调的优惠券选择与最终预约 - /login、/logout:认证与凭证管理 - /cancel_{booking_id} 及确认回调:取消流程的二次确认 文档将深入解释动态参数(正则表达式匹配与参数解析)、命令与用户交互的设计模式(分页/菜单/状态保持),并提供开发模板与用户体验优化建议。 ## 项目结构 该项目采用按功能模块划分的目录结构,命令注册集中在入口文件,各命令处理器位于独立文件中,底层通过客户端封装调用第三方 API。 ```mermaid graph TB subgraph "命令层" IDX["src/command/index.ts"] H1["handlers/events.ts"] H2["handlers/eventDetails.ts"] H3["handlers/history.ts"] H4["handlers/bookEvent.ts"] H5["handlers/login.ts"] H6["handlers/cancel.ts"] H7["handlers/logout.ts"] H8["handlers/start.ts"] end subgraph "客户端" C1["src/client/cosmoe.ts"] end IDX --> H1 IDX --> H2 IDX --> H3 IDX --> H4 IDX --> H5 IDX --> H6 IDX --> H7 IDX --> H8 H1 --> C1 H2 --> C1 H3 --> C1 H4 --> C1 H5 --> C1 H6 --> C1 H7 --> C1 ``` 图表来源 - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [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/command/handlers/history.ts](file://src/command/handlers/history.ts#L1-L107) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L1-L226) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L1-L75) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L1-L132) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L1-L34) - [src/command/handlers/start.ts](file://src/command/handlers/start.ts#L1-L6) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) 章节来源 - [src/command/index.ts](file://src/command/index.ts#L1-L110) - [package.json](file://package.json#L1-L24) ## 核心组件 - 命令注册与路由 - 在入口文件中安装对话插件与 KV 存储,注册命令与正则监听器,绑定回调处理器 - 事件列表与详情 - 列表命令返回最近若干活动,详情命令解析动态路径并渲染时间槽与预约入口 - 预约与优惠券 - 通过回调键盘展示多张可用优惠券,支持“无优惠券”选项 - 历史与取消 - 历史命令读取用户凭证并拉取历史,提供取消入口;取消流程二次确认 - 认证与登出 - 对话式登录,KV 存储凭证;登出删除凭证 章节来源 - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [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/command/handlers/history.ts](file://src/command/handlers/history.ts#L1-L107) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L1-L226) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L1-L75) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L1-L132) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L1-L34) ## 架构总览 整体采用“命令入口 + 处理器 + 客户端 + KV 存储”的分层架构。命令入口负责路由与上下文管理,处理器负责业务逻辑与用户交互,客户端封装 API 调用,KV 存储用于会话与凭证持久化。 ```mermaid graph TB U["用户"] B["Telegram Bot"] C["命令入口
src/command/index.ts"] E["事件列表处理器
events.ts"] D["事件详情处理器
eventDetails.ts"] Y["历史处理器
history.ts"] BK["预约处理器
bookEvent.ts"] L["登录处理器
login.ts"] X["取消处理器
cancel.ts"] LOG["登出处理器
logout.ts"] CL["Cosmoe 客户端
src/client/cosmoe.ts"] KV["KV 存储
COSMOE_STORAGE/COSMOE_CREDENTIALS"] U --> B B --> C C --> E C --> D C --> Y C --> BK C --> L C --> X C --> LOG E --> CL D --> CL Y --> CL BK --> CL L --> CL X --> CL LOG --> CL C --> KV L --> KV Y --> KV BK --> KV X --> KV LOG --> KV ``` 图表来源 - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) ## 详细组件分析 ### /events:最近活动列表 - 功能要点 - 调用客户端获取活动列表,取最新若干条 - 将每条活动拼接为“/event_{id}”的可点击链接,便于跳转详情 - 参数与路由 - 命令形式:/events - 输出包含动态链接,用户点击后进入 /event_{id} - 错误处理 - 空数据时提示无活动;异常时提示网络错误 - 用户体验 - 限制输出数量,避免过长消息 - 使用 Markdown 格式增强可读性 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant H as "handleEventsCommand" participant CL as "CosmoeClient" U->>B : "/events" B->>H : 调用处理器 H->>CL : 获取活动列表 CL-->>H : 返回结果 H->>U : 发送最近活动列表含 /event_{id} 链接 ``` 图表来源 - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L1-L27) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L177-L184) 章节来源 - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L1-L27) ### /event_{id}:活动详情与预约入口 - 动态参数解析 - 使用正则 /^\/event_(.+)$/ 提取 id - 业务逻辑 - 拉取活动详情,排序时间槽,判断是否可预约(剩余位数>0且活动未过期) - 对每个可预约时间槽生成“/book_{event_id}_{slot_index}”的预约入口 - 时间与状态 - 使用北京时间(UTC+8)比较活动日期与当前时间,决定是否激活预约入口 - 错误处理 - 详情接口失败时提示错误;异常时统一兜底 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant H as "handleEventDetails" participant CL as "CosmoeClient" U->>B : "/event_{id}" B->>H : 解析 id 并调用处理器 H->>CL : 获取活动详情 CL-->>H : 返回详情含时间槽 H->>U : 发送活动详情与可预约入口 ``` 图表来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L1-L61) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L191-L199) 章节来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L1-L61) ### /history:预约历史与取消入口 - 动态参数解析 - 无需动态参数,直接读取上下文中的用户标识 - 凭证与鉴权 - 从 KV 中读取用户凭证,设置到客户端;若未登录则提示先登录 - 数据处理 - 拉取历史,按时间倒序取前若干条,格式化输出 - 对可取消的历史项生成“/cancel_{booking_id}”入口 - 时间与状态 - 使用北京时间比较活动日期与当前时间,仅对未完成且未来日期的记录开放取消 - 错误处理 - 无历史、鉴权失败、接口异常均给出明确提示 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant H as "handleHistoryCommand" participant KV as "KV 存储" participant CL as "CosmoeClient" U->>B : "/history" B->>H : 调用处理器 H->>KV : 读取用户凭证 KV-->>H : 返回凭证 H->>CL : 设置凭证并获取历史 CL-->>H : 返回历史 H->>U : 发送历史列表含可取消入口 ``` 图表来源 - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L1-L107) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L226-L239) 章节来源 - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L1-L107) ### /book_{event_id}_{slot_index}:预约与优惠券选择 - 动态参数解析 - 使用正则 /^\/book_(\d+)_(\d+)$/ 提取 event_id 与 slot_index - 凭证校验 - 从 KV 读取用户凭证,设置到客户端;未登录则提示先登录 - 时间槽校验 - 重新拉取活动详情,排序时间槽,校验索引有效性与剩余位数 - 优惠券策略 - 若存在多张可用优惠券,弹出内联键盘供用户选择;支持“不使用优惠券” - 若仅一张或无优惠券,则自动使用或不使用 - 最终预约 - 调用客户端执行预约,返回最终价格、预约编号等信息 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant H as "handleBookEvent" participant KV as "KV 存储" participant CL as "CosmoeClient" U->>B : "/book_{event_id}_{slot_index}" B->>H : 解析参数并调用处理器 H->>KV : 读取用户凭证 KV-->>H : 返回凭证 H->>CL : 设置凭证并获取活动详情 CL-->>H : 返回详情含时间槽 alt 多张优惠券 H->>U : 弹出优惠券选择键盘 U->>B : 回调选择优惠券 B->>H : 触发优惠券选择回调 else 单张/无优惠券 H->>CL : 执行预约 CL-->>H : 返回预约结果 end H->>U : 发送预约成功/失败信息 ``` 图表来源 - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L1-L226) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L247-L270) 章节来源 - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L1-L226) ### /login:对话式登录与凭证存储 - 交互模式 - 使用对话插件,分步询问用户名与密码,等待用户输入 - 凭证管理 - 成功获取 token 后,将 user_id、token、时间戳写入 KV,键为 Telegram 用户 id - 错误处理 - 输入缺失、认证失败、KV 写入异常均有相应提示 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant C as "对话插件" participant H as "handleInteractiveLogin" participant CL as "CosmoeClient" participant KV as "KV 存储" U->>B : "/login" B->>C : 进入 login 对话 C->>H : 触发对话处理器 H->>U : 请求用户名 U->>C : 输入用户名 H->>U : 请求密码 U->>C : 输入密码 H->>CL : 获取 token CL-->>H : 返回 token alt 成功 H->>KV : 写入凭证 KV-->>H : 成功 H->>U : 登录成功提示 else 失败 H->>U : 登录失败提示 end ``` 图表来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L1-L75) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L124-L140) 章节来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L1-L75) ### /cancel_{booking_id} 与确认回调:取消流程 - 动态参数解析 - 使用正则 /^\/cancel_(\d+)$/ 提取 booking_id - 取消入口生成 - 在历史命令中对可取消的记录生成“/cancel_{booking_id}”入口 - 二次确认 - 弹出“确认/取消”内联键盘;用户点击“确认”触发回调 - 回调处理 - 解析回调动作,读取凭证,调用取消接口,更新消息文本反馈结果 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant H1 as "handleCancelCommand" participant H2 as "handleCancelConfirmation" participant KV as "KV 存储" participant CL as "CosmoeClient" U->>B : "/cancel_{booking_id}" B->>H1 : 解析参数并调用处理器 H1->>KV : 读取用户凭证 KV-->>H1 : 返回凭证 H1->>CL : 设置凭证并获取历史 CL-->>H1 : 返回历史 H1->>U : 发送取消确认键盘 U->>B : 点击“确认” B->>H2 : 触发回调处理器 H2->>KV : 读取用户凭证 KV-->>H2 : 返回凭证 H2->>CL : 取消预约 CL-->>H2 : 返回结果 H2->>U : 更新消息为成功/失败 ``` 图表来源 - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L1-L132) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L405-L422) 章节来源 - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L1-L132) ### /logout:登出与凭证清理 - 行为 - 读取 KV 中的用户凭证,存在则删除,不存在则提示先登录 - 错误处理 - KV 读取/删除异常时统一提示 章节来源 - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L1-L34) ### /start:欢迎与命令指引 - 行为 - 返回欢迎语与可用命令列表,便于新用户快速上手 章节来源 - [src/command/handlers/start.ts](file://src/command/handlers/start.ts#L1-L6) ## 依赖关系分析 - 插件与存储 - 使用 @grammyjs/conversations 提供对话能力,@grammyjs/storage-cloudflare 提供 KV 存储适配 - 命令入口中自定义 KV 读写包装,确保 JSON 序列化/反序列化一致性 - 客户端依赖 - 所有处理器依赖 CosmoeClient,后者封装 API 调用、鉴权与数据模型 - 命令与回调 - 命令通过正则监听器接收动态参数;回调通过内联键盘触发,解析动作字符串 ```mermaid graph LR P["@grammyjs/conversations"] --> IDX["src/command/index.ts"] S["@grammyjs/storage-cloudflare"] --> IDX IDX --> H1["events.ts"] IDX --> H2["eventDetails.ts"] IDX --> H3["history.ts"] IDX --> H4["bookEvent.ts"] IDX --> H5["login.ts"] IDX --> H6["cancel.ts"] IDX --> H7["logout.ts"] H1 --> C["src/client/cosmoe.ts"] H2 --> C H3 --> C H4 --> C H5 --> C H6 --> C H7 --> C ``` 图表来源 - [src/command/index.ts](file://src/command/index.ts#L1-L11) - [package.json](file://package.json#L18-L22) 章节来源 - [src/command/index.ts](file://src/command/index.ts#L1-L11) - [package.json](file://package.json#L18-L22) ## 性能考量 - 消息长度控制 - 历史命令在发送前截断超长内容,避免 Telegram API 限制 - 数据量限制 - 列表与历史默认只取最近若干条,降低渲染与传输成本 - KV 访问 - 登录/取消/预约等关键流程均需 KV 读写,应关注并发与延迟;可考虑缓存短期会话状态 - 网络请求 - 客户端封装统一的 fetch 调用,建议在高频场景下增加本地缓存与去抖策略 章节来源 - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L94-L98) - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L9-L10) ## 故障排查指南 - 常见问题定位 - 动态参数解析失败:检查正则是否与用户输入一致(如 /event_123、/book_1_0) - 未登录:KV 中无凭证或凭证失效,需先执行 /login - 接口异常:客户端返回非 200 或数据结构变化,需查看具体错误消息 - KV 读写异常:检查命名空间权限与键名一致性 - 日志与回退 - 处理器中对异常进行捕获并回复友好提示,便于用户自助排查 - 建议 - 为关键流程添加重试与降级策略(如网络波动时的缓存读取) 章节来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.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/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L80-L83) ## 结论 该交互式命令体系通过清晰的命令路由、正则参数解析与回调交互,实现了从活动浏览、详情查看、预约下单到历史管理与取消的完整闭环。结合 KV 存储与对话插件,既保证了状态保持,也提升了用户体验。后续可在消息分页、批量操作、错误重试等方面进一步优化。 ## 附录 ### 交互式命令开发模板 - 命令注册 - 在命令入口中注册命令/正则监听器与回调 - 绑定环境变量(KV、Bot 信息等) - 处理器骨架 - 解析动态参数(正则/上下文) - 校验登录状态与凭证有效性 - 调用客户端获取/提交数据 - 构造消息与内联键盘(必要时) - 错误处理与用户提示 - 回调处理 - 解析回调动作字符串 - 读取上下文与 KV - 更新消息文本或编辑消息 - 模板参考 - 参考现有处理器的结构与错误处理模式 章节来源 - [src/command/index.ts](file://src/command/index.ts#L20-L110) - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L12-L75) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L11-L226) - [src/command/handlers/cancel.ts](file://src/command/handlers/cancel.ts#L11-L84) ### 用户体验优化建议 - 分页与滚动 - 当列表较长时,采用分页或“加载更多”按钮,减少单次消息长度 - 状态保持 - 使用对话插件与 KV 存储保持上下文,避免重复输入 - 反馈与通知 - 关键操作(登录、预约、取消)提供即时反馈与可追踪的 ID - 可访问性 - 文案简洁明确,提供“取消/返回”等兜底选项 - 错误恢复 - 对网络异常与参数错误提供重试与引导,避免用户卡死