# 新命令开发 **本文档引用的文件** - [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) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排除指南](#故障排除指南) 9. [结论](#结论) 10. [附录:新命令开发完整流程](#附录新命令开发完整流程) ## 简介 本指南面向希望为现有命令系统添加新命令的开发者,涵盖命令注册流程、参数解析方法、业务逻辑实现步骤、命令路由机制(command() 与 hears() 的使用场景与区别)、错误处理策略以及用户交互最佳实践。文档以项目现有实现为蓝本,提供可直接参考的扩展示例,帮助快速完成新命令的开发与集成。 ## 项目结构 该项目基于 grammY 框架与 Cloudflare Workers 运行时,采用模块化组织方式: - 入口文件负责初始化 Bot 并设置命令菜单 - 命令注册集中于命令模块,统一管理所有命令与回调 - 命令处理器按功能拆分至 handlers 目录 - 客户端封装对第三方 API 的调用 ```mermaid graph TB A["入口: src/index.ts"] --> B["命令注册: src/command/index.ts"] B --> C["命令处理器: src/command/handlers/*.ts"] C --> D["客户端: src/client/cosmoe.ts"] A --> E["Cloudflare 环境变量"] ``` 图表来源 - [src/index.ts](file://src/index.ts#L1-L47) - [src/command/index.ts](file://src/command/index.ts#L1-L110) 章节来源 - [src/index.ts](file://src/index.ts#L1-L47) - [src/command/index.ts](file://src/command/index.ts#L1-L110) ## 核心组件 - Bot 初始化与 Webhook 回调:入口文件创建 Bot 实例,配置命令菜单,并通过 Cloudflare Worker 的 webhookCallback 接收外部请求。 - 命令注册中心:命令模块集中导入各处理器,使用 bot.command() 与 bot.hears() 注册命令与模式匹配事件,并安装对话插件支持多步交互。 - 命令处理器:每个处理器负责单一职责,处理参数、调用客户端 API、构建响应消息并进行错误处理。 - 客户端封装:CosmoeClient 提供认证、活动查询、预约、取消等 API 调用,统一返回格式与错误处理。 章节来源 - [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) ## 架构总览 下图展示了从用户触发命令到业务处理与响应的完整流程,以及命令路由机制的差异。 ```mermaid sequenceDiagram participant U as "用户" participant W as "Cloudflare Webhook" participant B as "Bot 实例" participant R as "命令路由" participant H as "命令处理器" participant C as "CosmoeClient" participant API as "第三方 API" U->>W : "发送消息/命令" W->>B : "webhookCallback 分发" B->>R : "根据路由规则匹配" alt "命令路由 : bot.command()" R->>H : "调用对应处理器" else "模式路由 : bot.hears()" R->>H : "正则匹配后调用处理器" else "回调路由 : bot.callbackQuery()" R->>H : "回调数据解析后调用处理器" end H->>C : "调用客户端 API" C->>API : "HTTP 请求" API-->>C : "返回结果" C-->>H : "标准化结果" H-->>U : "发送响应消息" ``` 图表来源 - [src/index.ts](file://src/index.ts#L14-L35) - [src/command/index.ts](file://src/command/index.ts#L59-L110) - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) ## 详细组件分析 ### 命令注册与路由机制 - bot.command("命令名", 处理器):用于标准命令触发,例如 /start、/login、/events、/history、/logout。 - bot.hears(正则表达式, 处理器):用于模式匹配的消息触发,例如 /event_{id}、/book_{event_id}_{slot_id}、/cancel_{booking_id}。 - bot.callbackQuery(正则表达式, 处理器):用于内联键盘回调,例如确认取消、选择优惠券等。 ```mermaid flowchart TD Start(["收到消息"]) --> Type{"消息类型"} Type --> |命令| Cmd["bot.command() 匹配"] Type --> |文本/正则| Hears["bot.hears() 匹配"] Type --> |回调| CB["bot.callbackQuery() 匹配"] Cmd --> Handler["调用对应处理器"] Hears --> Handler CB --> Handler Handler --> End(["发送响应"]) ``` 图表来源 - [src/command/index.ts](file://src/command/index.ts#L59-L110) 章节来源 - [src/command/index.ts](file://src/command/index.ts#L59-L110) ### 参数解析与业务逻辑实现步骤 - 解析上下文参数:从 ctx.from、ctx.message、ctx.match、ctx.callbackQuery.data 等提取必要信息。 - 数据校验:检查用户身份、登录状态、参数有效性、业务约束(如时间范围、库存)。 - 调用客户端 API:通过 CosmoeClient 执行业务操作,统一处理返回码与错误信息。 - 构建响应消息:使用 Markdown 或纯文本格式,注意长度限制与 Telegram API 限制。 - 错误处理:捕获异常、记录日志、向用户反馈错误信息。 章节来源 - [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/login.ts](file://src/command/handlers/login.ts#L13-L75) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L10-L34) ### 命令处理器示例分析 #### 启动命令处理器 - 功能:向用户展示可用命令列表。 - 关键点:使用 ctx.reply 发送文本;适合简单无状态命令。 章节来源 - [src/command/handlers/start.ts](file://src/command/handlers/start.ts#L4-L6) #### 事件列表命令处理器 - 功能:拉取最新活动并生成列表链接。 - 关键点:调用 CosmoeClient.getEvents;限制数量;Markdown 格式化;错误兜底。 章节来源 - [src/command/handlers/events.ts](file://src/command/handlers/events.ts#L4-L27) #### 事件详情与预约命令处理器 - 功能:解析 /event_{id} 与 /book_{event_id}_{slot_id},展示时间槽并支持优惠券选择。 - 关键点:正则匹配参数;KV 存储用户凭证;调用 getEventDetail 与 getAvailableCoupons;内联键盘与回调处理;Markdown 格式化;库存与时间判断。 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant ED as "事件详情处理器" participant BE as "预约处理器" participant C as "CosmoeClient" participant API as "第三方 API" U->>B : "/event_123" B->>ED : "匹配 /event_{id}" ED->>C : "getEventDetail(id)" C->>API : "请求" API-->>C : "返回活动详情" C-->>ED : "返回数据" ED-->>U : "发送活动详情与可预约链接" U->>B : "/book_123_0" B->>BE : "匹配 /book_{event_id}_{slot_id}" BE->>C : "getEventDetail(eventId)" C-->>BE : "返回数据" BE->>BE : "检查库存与优惠券" alt "多个优惠券" BE-->>U : "显示优惠券选择键盘" U->>B : "回调 : select_coupon_123_0_xxx" B->>BE : "解析回调" BE->>C : "bookEvent(couponCode)" else "单个/无优惠券" BE->>C : "bookEvent()" end C-->>BE : "返回结果" BE-->>U : "发送预约结果" ``` 图表来源 - [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/client/cosmoe.ts](file://src/client/cosmoe.ts#L191-L270) 章节来源 - [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) #### 预约历史与取消命令处理器 - 功能:读取用户凭证,查询预约历史,生成 Markdown 列表,并提供取消链接与确认回调。 - 关键点:KV 读写凭证;认证校验;排序与截断;贝时拼接与比较;内联键盘确认;回调解析与状态更新。 ```mermaid sequenceDiagram participant U as "用户" participant B as "Bot" participant HC as "历史处理器" participant CC as "取消处理器" participant C as "CosmoeClient" participant API as "第三方 API" U->>B : "/history" B->>HC : "调用历史处理器" HC->>HC : "KV 读取凭证" HC->>C : "getMyBookings()" C-->>HC : "返回历史数据" HC-->>U : "发送历史列表(含取消链接)" U->>B : "/cancel_456" B->>CC : "匹配 /cancel_{booking_id}" CC->>C : "getMyBookings() 确认" CC-->>U : "发送确认键盘" U->>B : "回调 : confirm_cancel_456" B->>CC : "解析回调" CC->>C : "cancelBooking(456)" C-->>CC : "返回结果" CC-->>U : "编辑消息为取消结果" ``` 图表来源 - [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-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) #### 登录与登出命令处理器 - 功能:登录采用对话式多步交互,登出清理 KV 中的凭证。 - 关键点:对话插件与 KV 适配器;凭证持久化;错误处理与提示。 章节来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L13-L75) - [src/command/handlers/logout.ts](file://src/command/handlers/logout.ts#L10-L34) ### 客户端 API 封装 CosmoeClient 统一封装了认证、活动、预约、取消、转账、改密等 API,提供一致的返回格式与错误处理,便于命令处理器复用。 章节来源 - [src/client/cosmoe.ts](file://src/client/cosmoe.ts#L113-L503) ## 依赖分析 - grammY:核心框架,提供 Bot、Context、InlineKeyboard、callbackQuery 等能力。 - @grammyjs/conversations:对话插件,支持多步交互与状态存储。 - @grammyjs/storage-cloudflare:KV 存储适配器,用于会话状态持久化。 - Cloudflare Workers:运行时环境,提供 KVNamespace、Webhook 回调等。 ```mermaid graph TB Pkg["package.json 依赖"] --> G["grammy"] Pkg --> Conv["@grammyjs/conversations"] Pkg --> KV["@grammyjs/storage-cloudflare"] G --> Bot["Bot/Context"] Conv --> Conversations["对话插件"] KV --> Storage["KV 适配器"] ``` 图表来源 - [package.json](file://package.json#L18-L22) 章节来源 - [package.json](file://package.json#L1-L24) ## 性能考虑 - 消息长度控制:历史与详情消息可能较长,需限制长度避免 Telegram API 限制。 - KV 访问优化:尽量减少 KV 读写次数,合并请求或缓存必要数据。 - 异步并发:合理使用异步调用,避免阻塞主线程。 - 错误快速失败:在参数无效或状态不满足时尽早返回,减少无效请求。 ## 故障排除指南 - 命令未生效:检查命令是否在入口文件中设置命令菜单,以及命令注册是否正确导入。 - 参数解析失败:确认正则表达式与 ctx.match 是否匹配预期格式。 - 凭证问题:检查 KV 中是否存在用户凭证,登录状态是否有效。 - API 返回异常:查看客户端封装的错误处理与返回码,确保统一处理。 - 回调无响应:确认回调查询与回调处理器的正则匹配一致,并正确调用 answerCallbackQuery。 章节来源 - [src/index.ts](file://src/index.ts#L24-L32) - [src/command/index.ts](file://src/command/index.ts#L92-L105) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L13-L29) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L16-L117) ## 结论 通过统一的命令注册中心与清晰的处理器职责划分,项目实现了可扩展的命令系统。新增命令应遵循现有模式:在命令模块中注册路由,在 handlers 目录中实现处理器,利用 CosmoeClient 封装 API,严格进行参数校验与错误处理,并通过 Markdown 等格式提升用户体验。 ## 附录:新命令开发完整流程 ### 第一步:设计命令与参数 - 明确命令名称与用途(如 /admin_stats)。 - 设计参数格式与可选参数,决定使用 bot.command() 还是 bot.hears()。 - 规划用户交互流程(是否需要内联键盘或对话)。 ### 第二步:创建处理器文件 - 在 src/command/handlers 下新建处理器文件,导出异步处理函数。 - 处理函数签名建议:handleXxxCommand(ctx, env?),其中 env 可选用于访问 KV 等资源。 章节来源 - [src/command/handlers/start.ts](file://src/command/handlers/start.ts#L4-L6) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L4-L107) ### 第三步:实现业务逻辑 - 解析参数:从 ctx.from、ctx.message、ctx.match、ctx.callbackQuery.data 获取必要信息。 - 校验输入:检查用户身份、登录状态、参数合法性。 - 调用客户端:通过 CosmoeClient 执行业务操作。 - 构建响应:使用 Markdown 或纯文本,注意长度限制与格式规范。 章节来源 - [src/command/handlers/eventDetails.ts](file://src/command/handlers/eventDetails.ts#L4-L61) - [src/command/handlers/bookEvent.ts](file://src/command/handlers/bookEvent.ts#L120-L157) ### 第四步:注册命令路由 - 在命令模块中导入新处理器。 - 使用 bot.command() 或 bot.hears() 注册路由,必要时使用 bot.callbackQuery() 注册回调。 - 如需对话交互,使用 conversations 插件与 createConversation 包裹处理器。 章节来源 - [src/command/index.ts](file://src/command/index.ts#L55-L57) - [src/command/index.ts](file://src/command/index.ts#L64-L66) - [src/command/index.ts](file://src/command/index.ts#L72-L80) - [src/command/index.ts](file://src/command/index.ts#L92-L105) ### 第五步:设置命令菜单 - 在入口文件中调用 bot.api.setMyCommands 设置命令菜单,确保用户可见。 章节来源 - [src/index.ts](file://src/index.ts#L24-L32) ### 第六步:错误处理与测试 - 添加 try-catch 捕获异常,记录日志并友好提示用户。 - 编写单元测试覆盖正常与异常路径。 - 在本地与生产环境中验证命令行为。 章节来源 - [src/command/handlers/login.ts](file://src/command/handlers/login.ts#L70-L74) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L103-L107) ### 示例:添加一个“管理员统计”命令 - 命令设计:/admin_stats,仅管理员可用,返回预约统计与用户活跃度。 - 参数:可选日期范围(YYYY-MM-DD),默认最近7天。 - 路由:使用 bot.command() 注册。 - 处理器:解析参数、校验管理员权限、调用客户端统计接口、构建 Markdown 表格并发送。 - 回调:如需分页或筛选,使用内联键盘与回调处理。 章节来源 - [src/command/index.ts](file://src/command/index.ts#L59-L70) - [src/command/handlers/history.ts](file://src/command/handlers/history.ts#L47-L92)