交互式命令.md 18 KB

交互式命令

本文引用的文件

  • src/command/index.ts
  • src/command/handlers/events.ts
  • src/command/handlers/eventDetails.ts
  • src/command/handlers/history.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/login.ts
  • src/command/handlers/cancel.ts
  • src/command/handlers/logout.ts
  • src/command/handlers/start.ts
  • src/client/cosmoe.ts
  • package.json

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件聚焦于交互式命令的实现与设计,围绕以下命令展开:

  • /events:列出最近的摄影活动,并以“/event_{id}”链接引导查看详情
  • /event_{id}:展示活动详情、时间槽与预约入口
  • /history:展示用户的预约历史,并提供“/cancel_{booking_id}”取消入口
  • /book_{eventid}{slot_index}:基于回调的优惠券选择与最终预约
  • /login、/logout:认证与凭证管理
  • /cancel_{booking_id} 及确认回调:取消流程的二次确认

文档将深入解释动态参数(正则表达式匹配与参数解析)、命令与用户交互的设计模式(分页/菜单/状态保持),并提供开发模板与用户体验优化建议。

项目结构

该项目采用按功能模块划分的目录结构,命令注册集中在入口文件,各命令处理器位于独立文件中,底层通过客户端封装调用第三方 API。

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
  • src/command/handlers/events.ts
  • src/command/handlers/eventDetails.ts
  • src/command/handlers/history.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/login.ts
  • src/command/handlers/cancel.ts
  • src/command/handlers/logout.ts
  • src/command/handlers/start.ts
  • src/client/cosmoe.ts

章节来源

  • src/command/index.ts
  • package.json

核心组件

  • 命令注册与路由
    • 在入口文件中安装对话插件与 KV 存储,注册命令与正则监听器,绑定回调处理器
  • 事件列表与详情
    • 列表命令返回最近若干活动,详情命令解析动态路径并渲染时间槽与预约入口
  • 预约与优惠券
    • 通过回调键盘展示多张可用优惠券,支持“无优惠券”选项
  • 历史与取消
    • 历史命令读取用户凭证并拉取历史,提供取消入口;取消流程二次确认
  • 认证与登出
    • 对话式登录,KV 存储凭证;登出删除凭证

章节来源

  • src/command/index.ts
  • src/command/handlers/events.ts
  • src/command/handlers/eventDetails.ts
  • src/command/handlers/history.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/login.ts
  • src/command/handlers/cancel.ts
  • src/command/handlers/logout.ts

架构总览

整体采用“命令入口 + 处理器 + 客户端 + KV 存储”的分层架构。命令入口负责路由与上下文管理,处理器负责业务逻辑与用户交互,客户端封装 API 调用,KV 存储用于会话与凭证持久化。

graph TB
U["用户"]
B["Telegram Bot"]
C["命令入口<br/>src/command/index.ts"]
E["事件列表处理器<br/>events.ts"]
D["事件详情处理器<br/>eventDetails.ts"]
Y["历史处理器<br/>history.ts"]
BK["预约处理器<br/>bookEvent.ts"]
L["登录处理器<br/>login.ts"]
X["取消处理器<br/>cancel.ts"]
LOG["登出处理器<br/>logout.ts"]
CL["Cosmoe 客户端<br/>src/client/cosmoe.ts"]
KV["KV 存储<br/>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
  • src/client/cosmoe.ts

详细组件分析

/events:最近活动列表

  • 功能要点
    • 调用客户端获取活动列表,取最新若干条
    • 将每条活动拼接为“/event_{id}”的可点击链接,便于跳转详情
  • 参数与路由
    • 命令形式:/events
    • 输出包含动态链接,用户点击后进入 /event_{id}
  • 错误处理
    • 空数据时提示无活动;异常时提示网络错误
  • 用户体验

    • 限制输出数量,避免过长消息
    • 使用 Markdown 格式增强可读性

      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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/events.ts

/event_{id}:活动详情与预约入口

  • 动态参数解析
    • 使用正则 /^\/event_(.+)$/ 提取 id
  • 业务逻辑
    • 拉取活动详情,排序时间槽,判断是否可预约(剩余位数>0且活动未过期)
    • 对每个可预约时间槽生成“/book_{eventid}{slot_index}”的预约入口
  • 时间与状态
    • 使用北京时间(UTC+8)比较活动日期与当前时间,决定是否激活预约入口
  • 错误处理

    • 详情接口失败时提示错误;异常时统一兜底

      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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/eventDetails.ts

/history:预约历史与取消入口

  • 动态参数解析
    • 无需动态参数,直接读取上下文中的用户标识
  • 凭证与鉴权
    • 从 KV 中读取用户凭证,设置到客户端;若未登录则提示先登录
  • 数据处理
    • 拉取历史,按时间倒序取前若干条,格式化输出
    • 对可取消的历史项生成“/cancel_{booking_id}”入口
  • 时间与状态
    • 使用北京时间比较活动日期与当前时间,仅对未完成且未来日期的记录开放取消
  • 错误处理

    • 无历史、鉴权失败、接口异常均给出明确提示

      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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/history.ts

/book_{eventid}{slot_index}:预约与优惠券选择

  • 动态参数解析
    • 使用正则 /^\/book(\d+)(\d+)$/ 提取 event_id 与 slot_index
  • 凭证校验
    • 从 KV 读取用户凭证,设置到客户端;未登录则提示先登录
  • 时间槽校验
    • 重新拉取活动详情,排序时间槽,校验索引有效性与剩余位数
  • 优惠券策略
    • 若存在多张可用优惠券,弹出内联键盘供用户选择;支持“不使用优惠券”
    • 若仅一张或无优惠券,则自动使用或不使用
  • 最终预约

    • 调用客户端执行预约,返回最终价格、预约编号等信息

      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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/bookEvent.ts

/login:对话式登录与凭证存储

  • 交互模式
    • 使用对话插件,分步询问用户名与密码,等待用户输入
  • 凭证管理
    • 成功获取 token 后,将 user_id、token、时间戳写入 KV,键为 Telegram 用户 id
  • 错误处理

    • 输入缺失、认证失败、KV 写入异常均有相应提示

      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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/login.ts

/cancel_{booking_id} 与确认回调:取消流程

  • 动态参数解析
    • 使用正则 /^\/cancel_(\d+)$/ 提取 booking_id
  • 取消入口生成
    • 在历史命令中对可取消的记录生成“/cancel_{booking_id}”入口
  • 二次确认
    • 弹出“确认/取消”内联键盘;用户点击“确认”触发回调
  • 回调处理

    • 解析回调动作,读取凭证,调用取消接口,更新消息文本反馈结果

      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
  • src/client/cosmoe.ts

章节来源

  • src/command/handlers/cancel.ts

/logout:登出与凭证清理

  • 行为
    • 读取 KV 中的用户凭证,存在则删除,不存在则提示先登录
  • 错误处理
    • KV 读取/删除异常时统一提示

章节来源

  • src/command/handlers/logout.ts

/start:欢迎与命令指引

  • 行为
    • 返回欢迎语与可用命令列表,便于新用户快速上手

章节来源

  • src/command/handlers/start.ts

依赖关系分析

  • 插件与存储
    • 使用 @grammyjs/conversations 提供对话能力,@grammyjs/storage-cloudflare 提供 KV 存储适配
    • 命令入口中自定义 KV 读写包装,确保 JSON 序列化/反序列化一致性
  • 客户端依赖
    • 所有处理器依赖 CosmoeClient,后者封装 API 调用、鉴权与数据模型
  • 命令与回调

    • 命令通过正则监听器接收动态参数;回调通过内联键盘触发,解析动作字符串

      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
  • package.json

章节来源

  • src/command/index.ts
  • package.json

性能考量

  • 消息长度控制
    • 历史命令在发送前截断超长内容,避免 Telegram API 限制
  • 数据量限制
    • 列表与历史默认只取最近若干条,降低渲染与传输成本
  • KV 访问
    • 登录/取消/预约等关键流程均需 KV 读写,应关注并发与延迟;可考虑缓存短期会话状态
  • 网络请求
    • 客户端封装统一的 fetch 调用,建议在高频场景下增加本地缓存与去抖策略

章节来源

  • src/command/handlers/history.ts
  • src/command/handlers/events.ts

故障排查指南

  • 常见问题定位
    • 动态参数解析失败:检查正则是否与用户输入一致(如 /event_123、/book_1_0)
    • 未登录:KV 中无凭证或凭证失效,需先执行 /login
    • 接口异常:客户端返回非 200 或数据结构变化,需查看具体错误消息
    • KV 读写异常:检查命名空间权限与键名一致性
  • 日志与回退
    • 处理器中对异常进行捕获并回复友好提示,便于用户自助排查
  • 建议
    • 为关键流程添加重试与降级策略(如网络波动时的缓存读取)

章节来源

  • src/command/handlers/eventDetails.ts
  • src/command/handlers/history.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/cancel.ts

结论

该交互式命令体系通过清晰的命令路由、正则参数解析与回调交互,实现了从活动浏览、详情查看、预约下单到历史管理与取消的完整闭环。结合 KV 存储与对话插件,既保证了状态保持,也提升了用户体验。后续可在消息分页、批量操作、错误重试等方面进一步优化。

附录

交互式命令开发模板

  • 命令注册
    • 在命令入口中注册命令/正则监听器与回调
    • 绑定环境变量(KV、Bot 信息等)
  • 处理器骨架
    • 解析动态参数(正则/上下文)
    • 校验登录状态与凭证有效性
    • 调用客户端获取/提交数据
    • 构造消息与内联键盘(必要时)
    • 错误处理与用户提示
  • 回调处理
    • 解析回调动作字符串
    • 读取上下文与 KV
    • 更新消息文本或编辑消息
  • 模板参考
    • 参考现有处理器的结构与错误处理模式

章节来源

  • src/command/index.ts
  • src/command/handlers/login.ts
  • src/command/handlers/bookEvent.ts
  • src/command/handlers/cancel.ts

用户体验优化建议

  • 分页与滚动
    • 当列表较长时,采用分页或“加载更多”按钮,减少单次消息长度
  • 状态保持
    • 使用对话插件与 KV 存储保持上下文,避免重复输入
  • 反馈与通知
    • 关键操作(登录、预约、取消)提供即时反馈与可追踪的 ID
  • 可访问性
    • 文案简洁明确,提供“取消/返回”等兜底选项
  • 错误恢复
    • 对网络异常与参数错误提供重试与引导,避免用户卡死