@onebots/adapter-zulip
v3.0.12
Published
onebots Zulip 适配器
Readme
@onebots/adapter-zulip
面向 Zulip 当前 REST API 与 Event Queue 的 OneBots 适配器。它使用官方 POST /register + GET /events 长轮询,不会创建不存在的 WebSocket 连接。
能力
- 频道、话题与单人/多人私聊消息
- 消息查询、历史、编辑、删除、narrow 匹配、批量标记与举报
- 定时消息、草稿、提醒与保存片段管理
- 用户组创建、权限更新、停用/恢复、成员与子组管理及成员关系查询
- Zulip-flavored Markdown、用户提及、Emoji、图片和文件上传
- 附件清单、删除、临时访问 URL、缩略图状态与实时生命周期事件
- 真实频道订阅者查询、邀请、移除、退订与频道改名
- 频道 ID、详情、话题、成员订阅状态、邮件入口与归档管理
- 消息反应、成员变更、心跳及未知原始事件投影
- 队列过期自动重建、无限指数退避、生命周期取消与成功后游标确认
- 独立可嵌入的
ZulipClient、底层call()与ingest(rawEvent) - HTTP/SOCKS 代理、结构化
ZulipError和完整 TypeScript 类型
配置
zulip.team-bot:
server_url: https://example.zulipchat.com
email: [email protected]
api_key: your-api-key
default_topic: general
receive_mode: event_queue
event_queue:
all_public_streams: false
retry_initial_delay_ms: 1000
retry_max_delay_ms: 30000
onebot.v11:
access_token: your-tokenserver_url 是组织根地址,不应包含 /api/v1。生产地址必须使用 HTTPS,仅本机回环地址允许 HTTP。api_key 在 Web 表单中按敏感字段处理。旧的 serverUrl、apiKey、websocket 和 event_queue.enabled 已移除;是否建立 Event Queue 统一由顶层 receive_mode 决定。
事件类型可在 Web 表单中直接增减;省略 event_queue.event_types 时订阅消息、编辑、删除、反应、频道、订阅、成员、用户组、在线状态和输入状态。队列始终无限恢复,不提供“重试若干次后永久离线”的选项。事件只有在全部 canonical 监听器成功返回后才推进队列游标并写入本地去重窗口;监听器抛错会保留原游标,让 Event Queue 重投,不会静默丢失业务事件。
停止会等待轮询退出并尝试删除服务端事件队列;任一步骤失败都会在本地代次清理完成后以结构化错误传播。
已有 Event Queue、消息代理或测试连接可配置 receive_mode: manual。客户端仍会调用 users/me 验证 API 凭据并缓存 Bot 身份,但不会注册或轮询服务器队列;外部系统通过 await account.client.ingest(rawEvent) 进入相同的可靠类型化事件管线。
场景 ID
- 频道:
stream_id/topic,例如42/releases。只有stream_id时使用default_topic。 - 私聊:用户 ID,例如
17;多人私聊使用17,23。
入站频道消息会把频道 ID 与原话题同时写入 group.id,因此直接回复不会丢失话题。频道名称可能变化,不作为稳定 ID。
独立 Client
import { ZulipClient } from "@onebots/adapter-zulip";
const client = new ZulipClient({
account_id: "team-bot",
server_url: "https://example.zulipchat.com",
email: "[email protected]",
api_key: process.env.ZULIP_API_KEY!,
receive_mode: "event_queue",
});
client.on("message", event => {
console.log(event.message);
});
client.on("client_error", error => {
console.error(error.code, error.message);
});
await client.start();已有 Event Queue 或代理连接可调用 await client.ingest(rawEvent),与内置长轮询共用同一事件管线。返回值表示本次调用是否完成首次投递;raw、精确类型和 canonical 监听器全部完成后才提交去重状态。client.call(path, method, params) 只允许当前组织 /api/v1 下的安全相对路径。
平台扩展动作
数据导出领域提供 list_data_exports、create_data_export、delete_data_export 与 get_data_export_consents,使用 Zulip 12 的字符串导出类型并保留跨服务器导出状态;默认订阅导出进度和成员授权变化,相关动作需要组织管理员权限。
Code Playground 领域提供 add_code_playground 与 remove_code_playground,只接受现代 RFC 6570 url_template,并默认订阅 realm_playgrounds 完整快照;Zulip 没有提供单独的列表或更新 REST API,因此不会暴露伪造动作。
允许域名领域提供 list_allowed_domains、add_allowed_domain、update_allowed_domain 与 remove_allowed_domain,并默认订阅增改删事件;写操作仅组织 Owner 可用。
Channel Folder 领域提供 list_channel_folders、create_channel_folder、reorder_channel_folders 与 update_channel_folder,完整覆盖创建、排序、资料更新、归档和恢复;写操作需要组织管理员权限。Client 默认订阅精确 channel_folder 事件,并投影为统一文件夹资源的创建、更新和排序通知。
Navigation View 领域提供 list_navigation_views、add_navigation_view、update_navigation_view 与 remove_navigation_view,安全编码 URL fragment,并闭合当前用户侧栏视图的精确创建、更新、删除事件。组织资源投影与共享事件基元已从主消息投影模块拆分,避免资源域继续膨胀单文件。
附件领域提供 get_attachments、remove_attachment、get_attachment_temporary_url 与 check_attachment_thumbnail;临时 URL 与缩略图动作按官方 path_id 拆分 realm_id_str 和 filename,每个路径段独立编码并拒绝路径穿越。Client 默认订阅 attachment 增改删事件,投影为统一附件资源通知,同时保留 path_id、空间使用量与原始事件。事件协议类型已独立到专用模块,REST 数据与队列报文不再共同推高单文件维护成本。
消息扩展领域提供 update_message_flags、update_message_flags_for_narrow、check_messages_match_narrow 与 report_message,并将原有反应、星标、历史、已读回执和 Markdown 渲染动作统一到独立消息模块。只允许客户端可修改的 read、starred、collapsed 标记;narrow 使用现代结构化条件,不暴露已弃用的全局已读端点。举报类型保留 Zulip 12 服务端动态 key,other 必须提供 1–1000 个 Unicode 字符的描述。Client 默认订阅精确 update_message_flags 事件,并投影为批量消息标记通知。
定时消息领域提供查询、创建、编辑和删除动作,只接受现代 direct / channel 请求场景,并按场景校验收件人、频道、话题、正文和发送时间;不会继续鼓励 private / stream 请求别名,也不会静默接受 direct 消息的无效话题。Client 默认订阅 scheduled_messages,完整声明 add/update/remove 判别联合,并将批量新增拆成稳定的逐资源 canonical 通知。
消息提醒领域提供 get_reminders、create_reminder 与 delete_reminder,创建时严格要求原消息 ID 和发送时间,并支持 Zulip 11 的可选备注。Client 默认订阅 add/remove 精确事件,将批量新增拆成逐提醒资源通知,并保留 reminder_target_message_id 以关联原消息。定时消息与提醒共享个人资源事件模块,后续同类能力无需复制投影骨架。
保存片段领域提供查询、创建、编辑与删除动作,标题和 Markdown 正文必须为非空字符串,局部编辑至少包含一个真实变更字段。Client 默认订阅 saved_snippets 的 add/update/remove 判别事件,并复用个人资源投影骨架生成统一生命周期通知。
草稿领域提供查询、批量创建、完整替换和删除动作,严格区分未寻址、频道与私聊目标,并拒绝只提交局部字段伪装完整草稿。Client 默认订阅 drafts,将批量新增与更新、删除投影为统一个人资源通知。
活动状态领域提供现代增量 Presence、单用户状态查询、个人话题可见性、消息撰写输入状态与消息编辑输入状态。Presence 不接受已废弃的 slim_presence;输入状态只接受 direct / channel 并按场景校验接收者或频道话题。Client 会展开批量 Presence,投影话题关注/静音变化与输入开始/停止通知,并默认订阅 user_topic。
个人设置领域提供 update_user_settings 与管理员专用的 update_user_settings_for_users,覆盖 Zulip 12 统一 /settings 端点的显示、通知、隐私、输入和话题策略。字段由共享元数据表严格校验,已移除的 dense_mode 不再透传;批量动作要求明确用户或用户组,且不能借此修改姓名、邮箱或密码。Client 精确声明 user_settings 增量事件,并投影为机器人本人的 user_updated/settings 通知。
组织新用户默认设置复用同一字段模型,通过管理员动作 update_default_user_settings 仅开放官方支持的设置子集;不会把姓名、凭据、语言、时区或仅属个人的邮件选项误发给组织端点。realm_user_settings_defaults 增量事件投影为独立 default_user_settings_updated 策略通知。
频道发现领域提供 get_channel_id、get_channel_topics、get_channel_subscriptions、get_channel_subscription_status、get_user_channels、list_zulip_channels、get_zulip_channel、get_channel_email_address 与 delete_channel_topic,并将原有订阅、订阅者、创建、更新和归档动作收敛到独立频道模块。频道列表仅暴露现代 include_all 等参数,不接受已弃用的 include_all_active;归档使用官方 DELETE /streams/{stream_id},不再伪装成 PATCH 属性更新。话题删除保留 Zulip 10+ 的空话题名语义。
频道个人设置提供 update_channel_subscription_settings 和 update_channel_subscription_property,支持批量或单频道更新颜色、静音、置顶和通知开关。颜色严格校验为 6 位十六进制值,其余属性必须为布尔值;不接受仅为旧客户端保留的 in_home_view。
频道成员关系提供 subscribe_channels、update_channel_subscriptions 与 unsubscribe_channels,按官方结构校验频道描述、用户 principals、初始策略和权限组;create_zulip_channel 严格对应 Zulip 11+ 的独立创建端点,要求频道名与初始订阅者列表,并只接受创建态权限组值。频道资料更新支持 Zulip 10+ 的现代权限组变更对象。已移除的 stream_post_policy、is_announcement_only 不会继续透传。stream 创建、更新、删除以及 subscription 自身/其他成员变化均有精确 Client 类型,并投影为稳定的频道资源与订阅关系通知;批量事件会拆成逐频道、逐用户事件,原始报文仍完整保留。
组织默认频道提供管理员动作 add_default_channel 与 remove_default_channel。Client 精确声明 default_streams 完整快照事件,并将其投影为单一 default_channels_updated 策略通知,避免把组织级替换误报成某一个频道的资料更新。
消息检索 get_messages 明确区分范围分页与 message_ids 两种互斥模式,支持 Zulip 12 的日期锚点、现代响应选项以及对象/二元组两种官方 narrow 结构;已废弃的 use_first_unread_anchor 不再进入命名动作,旧客户端应直接使用 anchor: "first_unread"。
视频会议领域提供 BigBlueButton、Nextcloud Talk、Webex 与 Constructor Groups 四种服务端集成的建会动作;命名动作只接受各官方端点声明的参数,具体集成须先由 Zulip 管理员在服务端启用。
账号生命周期提供 deactivate_own_account,组织 Owner 另可调用 deactivate_organization 并选择保留数据、延迟删除或立即永久删除。两者在能力清单中明确标为破坏性操作,参数严格对应官方端点;调用成功后当前凭据或整个组织将立即失效。
当前账号凭据可通过 regenerate_own_api_key 轮换。该动作与管理其他 Bot 凭据的接口分离,并标记为敏感操作;成功后调用方必须立即持久化返回的新 Key 并重建 Client,旧连接不能继续假装在线。
当前账号资料领域提供 get_own_user、update_own_profile_data、remove_own_profile_data、upload_own_avatar 与 delete_own_avatar;资料值严格遵循 Zulip 自定义字段类型,头像上传复用统一媒体来源并使用官方 file multipart 字段。资料和头像变更可能受组织权限策略限制。
通过统一 callAction 可调用反应、星标、消息搜索与编辑历史、频道订阅/管理、话题可见性、Presence、用户状态、输入状态、定时消息、草稿、提醒、保存片段、附件和服务器信息等动作。自定义表情领域提供 get_custom_emoji、upload_custom_emoji 与 deactivate_custom_emoji;上传接受 file(HTTP(S)、data URL、base64:// 或本地路径)及可选的 filename、content_type,并声明 Zulip 12 增量 Emoji 事件能力。自定义资料字段领域提供 list_profile_fields、create_profile_field、update_profile_field、delete_profile_field 与 reorder_profile_fields,闭合 8 种官方字段类型及 Zulip 12 的资料摘要、必填、用户可编辑和用户匹配约束,并默认订阅字段快照事件。个人偏好领域提供用户静音、Alert Words、状态读取与严格状态更新,并默认订阅对应集合变化;update_status_for_user 需要组织管理员权限。组织成员领域提供 create_user、update_user、deactivate_user 与 reactivate_user,严格校验官方角色、自定义资料和 Zulip 12 停用策略;这些动作需要组织管理员或服务器授予 Bot 相应特殊权限。邀请领域提供 list_invitations、send_invitations、create_invitation_link、resend_email_invitation、revoke_email_invitation 与 revoke_invitation_link,并默认订阅 invites_changed 以刷新邀请状态。Bot 领域提供 API Key 读取/再生成,以及 Zulip 12 Bot 专属的字符串存储读写删除;凭证动作需要 Bot 所有者或组织管理员权限。Linkifier 领域提供查询、创建、完整更新、删除和排序,并声明现代 URL Template 能力以接收 realm_linkifiers 事件;写操作需要组织管理员权限。用户组领域提供 list_user_groups、create_user_group、update_user_group、deactivate_user_group、update_user_group_members、update_user_group_subgroups、get_user_group_members、get_user_group_subgroups 与 get_user_group_membership。所有命名动作都会拒绝未知字段;call_zulip_api 仅用于尚未封装的官方端点,支持 GET、POST、PUT、PATCH、DELETE,且不会接受绝对 URL。
用户组创建、更新、停用/恢复会投影为标准 user_group 资源生命周期通知;成员和子组批量变化会拆成具有稳定 ID 的逐对象通知。自定义表情的增量创建和属性变化投影为标准 emoji 资源通知,停用保持 emoji_updated/deactivated 语义,因为 Zulip 仍会在历史消息中保留该资源。custom_profile_fields 是整表快照事件,Client 会提供精确类型监听,但不会将其猜测成某一个字段的生命周期。Zulip 未提供时间的 Event Queue 事件使用明确的时间戳 0,不会伪造本机接收时间。平台新增字段不会被丢弃:每个投影事件都保留 raw_event,未建立通用语义的事件会以 notice_type: "custom" 分发。
