Skip to content

本版新增功能

本文记录本 Fork 相对上游 Gensokyo 的主要代码行为。

范围说明:

标记含义
-通用能力,具体可用性取决于调用的 Action 和 QQ API 限制
私聊 (C2C)QQ C2C 单聊
q群 (Group Chat)QQ 群
q頻 (QQ Guild)QQ 频道/子频道

事件

Handler范围行为
GroupMessageEventHandlerq群 (Group Chat)接收 GROUP_MESSAGE_CREATE 非 @ 群消息。
MemberEventHandlerq頻 (QQ Guild)GUILD_MEMBER_ADD / GUILD_MEMBER_REMOVE 转 OneBot notice。
GroupMemberAddEventHandlerq群 (Group Chat)GROUP_MEMBER_ADDnotice.group_increase
GroupMemberRemoveEventHandlerq群 (Group Chat)GROUP_MEMBER_REMOVEnotice.group_decrease
C2CMsgRejectHandler私聊 (C2C)用户关闭 C2C 主动消息推送。
C2CMsgReceiveHandler私聊 (C2C)用户开启 C2C 主动消息推送。
FriendAddEventHandler / FriendDelEventHandler私聊 (C2C)好友关系事件。

text_intent 只注册写入的 handler。遇到 4014: disallowed intents 时可开启:

yaml
suppress_disallowed_intents: true

该开关只在 Identify 阶段屏蔽容易被拒绝的私有/未授权 intent,不会自动启用对应 handler。

API

Action范围行为
get_avatar-获取 QQ 头像直链。
get_robot_share_link-获取机器人分享链接。
send_private_msg_wakeup私聊 (C2C)发送带 is_wakeup=true 的 C2C 召回消息。
put_interaction-回复按钮交互结果。
set_group_card-OneBot 11 兼容 mock;返回 ok,不调用 QQ API。
set_group_add_request-OneBot 11 兼容 mock;返回 ok,不调用 QQ API。
/metrics-Prometheus 文本指标。

消息与 CQ 行为

q群 to_me

范围:q群 (Group Chat)

q群消息事件新增 to_me 字段:

  • GROUP_AT_MESSAGE_CREATE 固定为 true
  • GROUP_MESSAGE_CREATE 根据 Mentions[].IsYou 判断。

非自身 @

范围:q群 (Group Chat)

GROUP_MESSAGE_CREATE 中:

  • @bot 从文本中剥离,并设置 to_me=true
  • @其他人 转成 [CQ:at,qq=<虚拟ID>],同时建立 idmap 映射。

出站 @

范围:q群 (Group Chat) / q頻 (QQ Guild)

出站 [CQ:at,qq=<虚拟ID>] 会反查 OpenID,并转换为 <qqbot-at-user id="OpenID" />(仅 Markdown 消息,普通文本不转换)。

text
<qqbot-at-user id="OpenID" />

Markdown 内容里的 [CQ:at] 也会在发送前转换。详见 Markdown 中的 CQ at

Markdown 图片

范围:q群 (Group Chat) / q頻 (QQ Guild)

Markdown 内容中的 ![](path)

  • HTTP(S) URL 保留。
  • 本地路径或 file:// 路径会上传到 QQ CDN 后替换为直链。

[CQ:reply]

范围:q群 (Group Chat)

send_group_msg 会从文本中提取 [CQ:reply,id=<虚拟消息ID>],尝试通过 idmap 缓存反查真实 QQ message_id,再写入 message_reference。QQ q群 API 可能接受但不显示引用样式;send_guild_channel_msg 当前没有同等处理。

[CQ:member]

范围:q群 (Group Chat)

GROUP_MEMBER_ADD / GROUP_MEMBER_REMOVE 转 OneBot notice,message 字段附带 [CQ:member]。后端用普通 send_group_msg 回复时带回该 CQ 码,Gensokyo 会重新路由到真实 q群。详见 CQ member

delete_group_msg

范围:q群 (Group Chat)

独立 action,用于撤回指定用户在群内的消息;省略 message_id 时查找该用户最后一条消息。user_id 缺失、为 0 或负数时按 Bot 自身消息处理。详见 delete_group_msg

[CQ:active]

范围:-

当前文本解析只处理 [CQ:active,type=...,sub_type=...],解析后移除并记录字段;代码没有消费这些字段。需要 C2C 召回消息时使用 send_private_msg_wakeup

[CQ:remove]

范围:q群 (Group Chat)

出站 CQ 码 [CQ:remove,user_id=虚拟用户ID,msg_id=虚拟消息ID],后端通过 send_group_msg 携带此 CQ 码即可撤回指定的群消息。user_idmsg_id 均为虚拟 ID,Gensokyo 内部自动转换为 QQ OpenID / 真实 message_id。纯 CQ 码的消息不会发送到 QQ 频道。详见 CQ remove

按钮权限 ID

范围:-

发送 keyboard 时,会遍历按钮 permission.specify_user_ids,把虚拟数字 ID 转成 QQ OpenID。C2C 场景中,如果 permission.type=0 且指定了用户,会改为 type=2,避免 QQ API 拒绝。

零值字段

范围:-

action.type=0permission.type=0render_data.style=0 会被保留,不再因为 JSON omitempty 丢失。

语音

范围:-

[CQ:record] 支持自动转 SILK v3。WAV/MP3 可走 Go 内部处理;其他格式仍可能需要 ffmpeg。目标音频为 16-bit、单声道、采样率由 record_sampleRate 控制,默认 24000。

idmap

旧版单库 idmap.db 拆为:

文件用途
openid-map.dbOpenID/rUIN/raw 与内部 vUIN 的身份关系。
msgid-map.dbQQ message_id 与虚拟 message_id 的临时映射。
idmap.db旧库,仅作为一次性迁移源。

规则:

  • 下游默认继续使用内部 vUIN。
  • QQ OpenID 身份键为 openid:QQ:<appid>:<openid>
  • q群、私聊 (C2C)、好友事件、群成员事件共用同一 QQ OpenID 身份键。
  • q頻 (QQ Guild) 相关 ID 继续沿用现有逻辑。
  • message_id 默认保留 1 小时,由 msgid_ttl_seconds 控制。

相关配置:

yaml
op_userid_type: vuin
msgid_ttl_seconds: 3600

事件字段

sender.nickname

event.sender.nickname 优先级:

  1. card_nick 配置。
  2. QQ API 的 Author.Username
  3. 空字符串。

q群 sender.role

范围:q群 (Group Chat)

q群消息优先使用 QQ API 的 member_role

member_rolesender.role
ownerowner
adminadmin
membermember

没有 member_role 时,再回退到 master_id 判断。

event_id

已存储 event_id 的入口:

事件处理入口
INTERACTION_CREATEProcessInlineSearch
C2C_MSG_RECEIVEprocess_c2c_switch
FRIEND_ADDprocess_friend
GROUP_ADD_ROBOTProcessGroupAddBot
GROUP_MSG_RECEIVEProcessGroupMsgReceive
GROUP_MEMBER_ADDProcessGroupMember

日志与监控

mylog

当前内置日志支持:

  • 控制台按级别着色:log_color_enabled
  • 控制台日志格式:2006/JAN/02 PM 03:04:05 [INFO ] [module] message
  • 本地文件日志默认关闭,save_logs: true 或启动参数 run --local-logger=enable 均可启用。
  • 文件日志写入 log/ 下的纯文本文件,文件名使用 UTC 时间。
  • log_suffix_per_mins 控制时间切分,log_max_size_mb 控制单文件大小轮转。
  • log_max_age_days 控制最大保留天数,log_keep_files 控制本地旧日志文件最大保留个数。

慢事件与 /metrics

runWithTimer 会按 log_slow_event_threshold_ms 判定慢事件。/metrics 输出:

  • gensokyo_uptime_seconds
  • gensokyo_messages_received_total
  • gensokyo_messages_sent_total
  • gensokyo_errors_total
  • gensokyo_slow_events_total
  • gensokyo_memory_allocated_bytes

Master 指令

范围:进入 HandleFrameworkCommand 的消息事件。

权限:

  • master_id 为空数组时不限制。
  • 否则要求真实用户 ID 或虚拟用户 ID 命中 master_id

指令:

配置项默认值行为
status_prefix/gskstatus返回版本、收发计数、慢事件/错误计数、内存、协程数、运行时间。
broadcast_prefix/gskbroadcast向已发现的 q頻文本子频道和 idmap 中的 q群提交广播。

指令前缀设为 ""/disabled/disabled... 时视为禁用。

构建

CI 使用静态编译配置 CGO_ENABLED=0,降低 GLIBC 版本依赖。

构建版本由 -ldflags 注入 buildinfo.BuildTypebuildinfo.BuildSpec,显示为 <buildtype>-<build_spec>,例如 git-2d643f4。未注入时回退为 dev-<UTC 时间戳>。启动命令 version、OneBot get_version_info/gskstatus 使用同一版本值。

build.ps1 同时支持单平台构建和 -All / -LinuxOnly 多平台构建;build_all.ps1 仅保留为兼容入口。

修复

  • GetRemoveBotAtGroup 误删用户主动发送的 @。
  • 入站 @bot 剥离逻辑改用 Mentions[i].OpenID
  • ParseAndHandle 增加错误日志和 panic 恢复。
  • 按钮零值字段序列化丢失。
  • C2C 按钮指定用户权限导致发送失败。

基于 MIT 协议开源发行