ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Rocket.Chat Bot Helpers 完全指南:用 Hubot 通过 `botRequest` 查询用户状态与操作房间

Rocket.Chat Bot Helpers 完全指南:用 Hubot 通过 `botRequest` 查询用户状态与操作房间 Rocket.Chat Bot Helpers 完全指南用 Hubot 通过botRequest查询用户状态与操作房间【免费下载链接】Rocket.ChatThe Secure CommsOS™ for mission-critical operations项目地址: https://gitcode.com/GitHub_Trending/ro/Rocket.Chat本篇指南围绕 Rocket.Chat 仓库内 apps/meteor/server/lib/bot-helpers/README.md 所定义的Bot Helpers功能展开介绍它如何在 Rocket.Chat 服务端为 Hubot 脚本提供一组快捷 Meteor 方法用于查询在线用户、用户名、ID 列表以及将用户加入/移出房间与角色等扩展操作。读完你将掌握该机制的架构设计、BotHelpers_userFields白名单配置、八个只读 getter 方法的行为差异、从 Hubot 脚本侧发起调用的完整示例以及服务端鉴权与响应式查询的实现原理。背景为何需要 Bot HelpersRocket.Chat 的官方机器人生态基于 Hubot服务端通过 hubot-rocketchat adapter 把 Hubot 接入聊天室脚本作者通常需要反复实现查一下当前有哪些人在线把某人拉进某个频道之类的通用逻辑。Bot Helpers 的诞生源于一次如何扩展 Hubot 与 Rocket.Chat 集成的实验README 原文明确说明 This was an experiment in how to extend Hubot and Rocket.chat integration。其设计立场是尽量把控制器controller逻辑保留在 Rocket.Chat 服务端而不是塞进一个个 Hubot 脚本里。作者也坦承这不一定是最佳方案keeping controller logic out of Hubot scripts made sense to me, but its not necessarily the best approach——这句话说明了它的定位一个提供便利、面向简单 getter 场景的轻量辅助层而不是完整机器人框架。从源码看该功能由 apps/meteor/server/lib/bot-helpers/index.ts 一个文件实现并通过 apps/meteor/server/importPackages.ts#L11 的import ./lib/bot-helpers在服务端启动时被加载注册。整体工作方式双向依赖与调用链要让 Hubot 脚本使用这些方法需要满足两侧条件Rocket.Chat 服务端已包含并加载 bot-helpers 包当前仓库中即 apps/meteor/server/lib/bot-helpers/index.tsHubot 端使用官方 hubot-rocketchat adapterREADME 明确要求。调用链如下Hubot 脚本 └─ robot.adapter.callMethod(botRequest, onlineNames, ...) └─ (经 hubot-rocketchat adapter 转发) Meteor.call(botRequest, onlineNames) └─ 服务端 Meteor.methodsServerMethods 中的 botRequest 处理器 ├─ 鉴权当前用户需拥有 bot 角色 └─ 分发botHelpers.request(onlineNames) → 返回 getter 结果一个方法两类功能README 指出当前只有一个 helper 类型botRequest专为简单 getter设计未来可能扩展更多工具方法。但实际源码实现远不止 getter——在 index.ts 中BotHelpers类同时暴露了8 个查询型 getter用户/在线用户列表对应 README 中的核心用法4 个操作型方法addUserToRole、removeUserFromRole、addUserToRoom、removeUserFromRoomREADME 未列出但从源码可确认它们同样能被botRequest路由调用。核心用法从 Hubot 脚本调用调用约定在 Hubot 脚本中通过robot.adapter.callMethod发起Meteor.call第一个参数是 helper 类型botRequest第二个参数是方法名getter 或方法名后续参数为该方法所需入参。方法名若仅包含某个字段如allUsernames返回该属性组成的一维数组allUsers/onlineUsers则返回二维数组包含白名单中的全部属性。README 原始示例谁在线以下 CoffeeScript 示例监听who is online并用onlineNames方法获得在线用户不含机器人姓名数组再组合成自然语言回复# Use Bot Helpers class to check whos online robot.hear /who is online/i, (res) - promise robot.adapter.callMethod(botRequest, onlineNames) promise.then (result) - if result.length 0 names result.join(, ).replace(/,(?[^,]*$)/, and ) # convert last comma to and res.send #{ names } #{ if result.length 1 then is else are } currently online else res.send Nobody is currently online... \*cricket sound\* return , (error) - res.send Uh, sorry I dont know, somethings not working return当result.length 1时使用单数is例如Billie is currently online否则使用are正则/,(?[^,]*$)/把最后一个逗号替换为and从而拼出Robert, Desmond and Billie are currently online这样的句子。等价的 JavaScript/ES 版本若 Hubot 脚本用 JavaScript 编写同一逻辑为robot.hear(/who is online/i, (res) { robot.adapter .callMethod(botRequest, onlineNames) .then((result) { if (result.length 0) { const names result.join(, ).replace(/,(?[^,]*$)/, and ); const verb result.length 1 ? is : are; res.send(${names} ${verb} currently online); } else { res.send(Nobody is currently online... *cricket sound*); } }) .catch((error) { res.send(Uh, sorry I dont know, somethings not working); }); });注意 promise 会被 adapter 解析成可用数据失败时走 error 分支——例如当onlineNames所需的name字段未进入白名单时服务端会抛错脚本应像上例一样做好错误兜底。方法清单与返回结构README 列出了 8 个方法源码 index.ts 中的 getter 实现与之一一对应方法返回内容依赖白名单字段allUsers全部非 bot 用户对象数组含白名单中的属性任意字段白名单非空即可onlineUsers在线非 bot 用户对象数组任意字段白名单非空即可allUsernames全部非 bot 用户的username一维数组usernameonlineUsernames在线非 bot 用户的username一维数组usernameallNames全部非 bot 用户的name一维数组nameonlineNames在线非 bot 用户的name一维数组nameallIDs全部非 bot 用户的[{ id, name: username }]数组_id与usernameonlineIDs在线非 bot 用户的[{ id, name: username }]数组_id与username各 getter 的具体实现均可在 index.ts#L112-L188 中逐一验证。README 中提到前两个方法返回 2D array属性定义在 defaults 对象中当前为 id, name, username, status, emails——但对照当前仓库源码这一描述已与实际情况存在出入详见下文字段白名单配置一节的辨析。你还可以做的操作型方法源码级扩展从源码可以确认除 README 列出的查询 getter 外botRequest实际还能路由到以下方法它们封装了既有的 Rocket.Chat 服务端方法addUserToRole(userName, roleId, userId)内部委托 addUserToRole见 index.ts#L66-L68removeUserFromRole(userName, roleId, userId)内部委托 removeUserFromRole见 index.ts#L70-L72addUserToRoom(userName, room)先以房间 id 或名称查询Rooms.findOneByIdOrName找不到时抛Meteor.Error(invalid-channel)随后复用 addUsersToRoom 方法 实现批量加入见 index.ts#L74-L89removeUserFromRoom(userName, room)类似流程委托底层房间移除方法见 index.ts#L91-L102。需要注意的是这些写操作仍受底层方法自身的权限模型约束。以addUserToRoom为例addUsersToRoom.ts#L56-L77 会拒绝向私聊d房间拉人并要求调用者满足add-user-to-joined-room已在房间内或对应频道/私群add-user-to-any-c-room/add-user-to-any-p-room等权限之一否则抛出error-not-allowed。相关权限常量定义见 authorization/constant/permissions.ts。因此实践中建议给 bot 账号预分配相应角色与权限。服务端实现原理BotHelpers类index.ts#L20-L189的核心设计是私有属性用 Mongo 游标保持响应式公开 getter 按需把游标取成数组class BotHelpers { private queries: { online: FilterIUser; users: FilterIUser }; private userFields: Recordstring, 1; private _allUsers: FindCursorIUser; private _onlineUsers: FindCursorIUser; constructor() { this.queries { online: { status: { $ne: UserStatus.OFFLINE } }, // 在线 status ! offline users: { roles: { $not: { $all: [bot] } } }, // 排除带 bot 角色的账号 }; } ... }两个关键的 Mongo 过滤条件index.ts#L32-L37online判定status ! offline利用UserStatus.OFFLINE常量因此离开忙碌等状态也计入在线users排除roles数组中包含bot的账号从而保证机器人不会出现在查询结果中——这也解释了 README 示例注释里 not including bots 的含义。响应式游标与字段白名单setupCursors(fieldsSetting)index.ts#L40-L50负责初始化两个查询游标setupCursors(fieldsSetting: string | string[]) { this.userFields {}; if (typeof fieldsSetting string) { fieldsSetting fieldsSetting.split(,); } fieldsSetting.forEach((n) { this.userFields[n.trim()] 1; }); this._allUsers Users.find(this.queries.users, { projection: this.userFields }); this._onlineUsers Users.find({ $and: [this.queries.users, this.queries.online] }, { projection: this.userFields }); }值得留意userFields同时充当投影projection与字段是否被允许访问的双重开关。由于保存的是 Mongo 游标而非一次性数组结果天然保持响应式。字段白名单字符串会被split(,)后trim()每个字段名所以配置时字段间用英文逗号分隔即可、空格会被自动清理。该设置由以下代码在配置变更时动态重建游标index.ts#L195-L197settings.watchstring(BotHelpers_userFields, (value) { botHelpers.setupCursors(value); });这意味着管理员修改BotHelpers_userFields后无需重启服务新投影与访问控制会即时生效。通用分发器与安全兜底request(prop, ...params)index.ts#L53-L64是botRequest的通用分发器若this[prop]不存在返回null若是函数则以...params调用它操作型方法走此分支否则直接返回属性值getter 走此分支此时返回的是 Promise。requestError()index.ts#L105-L110则对请求了未授权字段的情况抛出标准错误throw new Meteor.Error(error-not-allowed, Bot request not allowed, { method: botRequest, action: bot_request, });各 getter 都会先校验依赖字段是否在白名单内再取数例如onlineNames要求userFields含nameallIDs/onlineIDs要求同时含_id与username不满足即调用requestError()抛错杜绝越权读取。服务端方法注册与角色鉴权文件末尾index.ts#L199-L214完成了类型声明与 Meteor 方法注册Meteor.methodsServerMethods({ async botRequest(...args) { const userID Meteor.userId(); if (userID (await hasRoleAsync(userID, bot))) { return botHelpers.request(...args, userID); } throw new Meteor.Error(error-invalid-user, Invalid user, { method: botRequest }); }, });调用方必须已登录且拥有bot角色否则直接抛error-invalid-user。角色校验走 apps/meteor/server/lib/authorization/hasRole.ts#L23-L29 的hasRoleAsync最终落到Roles.isUserInRoles(userId, [roleId], scope)。因此在真实部署中需先通过管理后台给 Hubot 机器人账号分配bot角色。配置BotHelpers_userFields字段白名单设置入口与默认值该白名单在服务端设置组中定义见 apps/meteor/server/settings/bots.ts#L3-L11settingsRegistry.addGroup(Bots, async function () { await this.add(BotHelpers_userFields, _id, name, username, emails, language, utcOffset, { type: string, section: Helpers, i18nLabel: BotHelpers_userFields, i18nDescription: BotHelpers_userFields_Description, }); });即管理后台 → Bots 设置组 → Helpers 分区下的BotHelpers_userFieldsUser Fields类型为字符串默认值为 CSV_id, name, username, emails, language, utcOffset对应 i18n 文案如 packages/i18n/src/locales/en.i18n.json#L1128-L1129将其描述为CSV of user fields that can be accessed by bots helper methods可被 bot helper 方法访问的用户字段 CSV。该设置组通过 apps/meteor/server/settings/definitions.ts#L46 的createBotsSettings()在启动时注册。实践建议与文档勘误把白名单当作最小暴露面来管理返回字段严格受限于 CSV 列表未列入的字段既不会被投影也会触发requestError。默认值已包含language、utcOffset等便于机器人做本地化与时间换算的字段。README 与当前实现存在一处出入README 称 defaults 为 id, name, username, status, emails但当前默认值为_id, name, username, emails, language, utcOffset——并没有status。且status实际上只出现在在线过滤条件里从未需要投影返回。若你的脚本希望拿到用户状态字段需主动把它加入 CSV 白名单。常见自定义形态只想开放用户名 在线情况时可精简为username此时onlineUsernames、allUsernames可用而onlineNames/allIDs会因缺少name/_id抛error-not-allowed。需要从脚本做频道治理时建议保留_id、username。测试与可扩展性现状README 的 Tests 一节直言None yet, PR adding tests would be much appreciated.暂无测试欢迎提交 PR 补充。从当前仓库检索来看apps/meteor/server/lib/bot-helpers 目录下仅有README.md与index.ts确实没有配套单元测试文件——这与 README 的陈述一致也说明该模块当前处于实验性、少维护状态。对于后续演进源码结构提供了两条清晰的方向新增 getter仿照 index.ts#L130-L188 的模式在类上定义 getter、校验依赖字段、基于this._allUsers/this._onlineUsers游标取数即可无需改动方法注册层新增工具方法仿照addUserToRoom等模式将新的服务端逻辑封装为类方法并在request()的路由下分发。由于request()采用通用分发新增能力时只需扩充类成员类型声明处index.ts#L199-L204同步更新keyof BotHelpers即可被 TypeScript 完整约束。小结Bot Helpers 是 Rocket.Chat 为 Hubot 集成提供的一层轻量服务端辅助架构上把通用用户/在线查询逻辑收敛进botRequest这一个 Meteor 方法通过BotHelpers类 Mongo 游标 配置驱动的字段白名单实现响应式与受控的数据暴露使用上Hubot 脚本只需robot.adapter.callMethod(botRequest, methodName)配合服务端Bots设置组的BotHelpers_userFields白名单与bot角色授权即可工作边界上README 仅记录了 8 个查询 getter实际源码还支持角色与房间管理类操作但这些写操作受底层权限体系约束且该模块尚无自动化测试属于实验性质的便利层生产使用前应结合自身权限模型审慎评估。如果想直接阅读或进一步扩展核心参考文件为模块 README、核心实现、设置定义、权限校验 与底层 addUsersToRoom 方法。【免费下载链接】Rocket.ChatThe Secure CommsOS™ for mission-critical operations项目地址: https://gitcode.com/GitHub_Trending/ro/Rocket.Chat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表