为什么会有这个页面?
官方文档虽然对 Milky 的协议内容进行了尽可能详尽的介绍,但仍然有一些地方描述不足,需要进行补充说明。以下内容是根据接到的用户反馈,对一些常见问题的解答。未尽之处,欢迎加入 QQ 群讨论相关细节,或新开 Issue 提出。
xxx 字段是用 null/undefined 还是用 0/空字符串表示“无值”?
省流:如果这个字段被标记了 optional,那么就大大方方用 null/undefined 表示“无值”;否则就用 0/空字符串表示“无值”。
至于为什么有的字段被标记为 optional,有的没有,这与 Milky 的可空性设计哲学有关,具体如下:
- 如果
null/undefined 和 0/空字符串在语义上是等价的,则不标记为 optional,使用 0/空字符串表示“无值”;
- 如果
null/undefined 和 0/空字符串在语义上不等价,或 0/空字符串是不合法的值(例如时间戳、QQ 号),则标记为 optional,使用 null/undefined 表示“无值”。
看不懂?没关系,按照上面省流部分说的就行了。
message_seq 是否相当于 OneBot 11 中的 message_id?
省流:message_scene + peer_id + message_seq = 完整版 message_id。
message_seq 不是“大号的 message_id”,而是一个自增的数字,表示消息在当前会话中的顺序,对于每个会话(好友或群聊)都是独立的。Milky 用 message_scene、peer_id 和 message_seq 组合来唯一标识一条消息。其中:
message_scene 是一个字符串,表示消息的场景(例如:好友、群聊等)
peer_id 是一个数字,表示会话的 ID。对于好友消息,peer_id 是好友的 QQ 号;对于群消息,peer_id 是群号。
OneBot 11 则使用 message_id 来唯一标识一条消息。
那我实在需要一个消息 ID 该怎么办?
可以通过拼接字符串的方式来实现,但这样的消息 ID 只适用于内部表示,在发送 Milky API 请求时仍然需要从消息 ID 中还原出真实信息。例如,一个来自好友 12345 的序列号为 42 的消息的 ID 可以是 friend|12345|42,在调用 get_message API 时通过 String.split 等方法还原出 message_scene、peer_id 和 message_seq。
如果一条消息被撤回了 / 没有任何合法消息段,协议端应该如何处理?
Milky 中需要用到消息的规范表示的位置主要是两个 API,以下是两个 API 在处理已被撤回 / 没有任何合法消息段的消息时的预期行为:
- 获取消息 API
get_message:直接 fail,返回的 retcode 为 -404;
- 获取历史消息 API
get_history_messages:返回结果中不包含对应 message_seq 的消息。例如,message_seq 为 29 的消息被撤回了,那么在拉取 message_seq 从 1 到 30 的历史消息时,返回的消息列表就应该只包含 29 条消息 (1, 2, ..., 28, 30)。一种极端情况是要拉取的 30 条消息全都被撤回 / 没有合法消息段,这时应该返回空数组。
此外,如果一条消息没有任何合法消息段,它也不应该出现在 message_receive 事件推送中。总而言之,Milky 中的消息至少保证有一个消息段。
感谢 #40 提出这一问题。感谢 @idranme 补充消息没有任何合法消息段的情况。
消息撤回(recall)和戳一戳(nudge)的事件推送中 display_ 开头的字段指的是什么?
假如一条消息撤回的提示如下:
那么其对应的 message_recall 事件中的 display_suffix 字段是 并假装无事发生。。
假如一条戳一戳的提示如下:
那么其对应的 message_nudge 事件中的 display_action 字段是 戳了戳,display_suffix 字段是 的……。不许戳啦!。
forward 消息段中的 title、preview 和 summary 分别指的是什么?
这些是用户在接收到合并转发消息但未展开查看时,看到的预览信息。例如这样一条合并转发消息的预览信息:
群聊的聊天记录 // title
Salt: [动画表情] // preview[0]
Milk: [图片] // preview[1]
Shama: [视频] // preview[2]
---
查看3条转发消息 // summary
file 消息段和 file_upload 事件是同一个东西吗?
是的,包含在消息中的 file 消息段和 friend_file_upload、group_file_upload 事件上报的内容是相同的,都是表示好友 / 群成员上传了文件,两者的字段和含义也完全一致。协议端在收到文件消息后,需要同时推送包含 file 消息段的 IncomingMessage 和 {friend,group}_file_upload 事件,应用端可以按需处理。
二者的主要不同在于用途:前者方便在拉取消息时获取文件信息,后者方便在 event 驱动的应用中处理用户上传的文件。
image、record 和 video 消息段分别支持哪些格式?
image:协议端至少需要支持 JPG、PNG、GIF、BMP、WEBP 格式的图片;
record:QQ 使用的语音格式是 SILK。在发送时,协议端至少需要支持 WAV 和 MP3 格式到 SILK 的转码;
video:协议端至少需要支持 MP4 格式的视频,并且在用户未提供 thumb_uri 时从视频中截取一帧作为缩略图。
face_id 都有哪些?
以下页面整理了可用的 QQ 表情 ID 列表,供参考:
如何获取用户或群的头像?
QQ 有一些公开的 API 可以用来获取头像:
- 用户头像:
https://q1.qlogo.cn/g?b=qq&nk=${user_id}&s=${quality}
user_id:用户 QQ 号;
quality:图片质量,可选值为 100(100x100)、640(640x640)等。
- 群头像:
https://p.qlogo.cn/gh/${group_id}/${group_id}/0/
感谢 #36 提出这一问题。
接收的合并转发中为什么提取不到真实 QQ 号?
因为确实提取不到,这是腾讯对被转发者信息的保护。
被转发的消息中,发送者的 QQ 号都会被统一覆盖成 1094950020(一个昵称为 QQ用户 的默认头像账号),而来源的群号都会被统一覆盖成 284840486。
同样,在 Milky 中,在没有具体发送者信息的情况下构造合并转发消息时,同样可以提供上述占位符 QQ 号。感谢 #63 补充这一情况。
Milky 会支持 QQ 频道/空间/农场/... 之类的业务相关 API 吗?
目前 Milky 的支持范围仅限于 QQ 本体的私聊及群聊业务,QQ 的其他相对独立的业务暂不考虑。
感谢 #109 提出这一问题。
喵喵?
咕噜咕噜。
感谢 @pk5ls20 提出这一问题(雾)。
为什么会有这个页面?
官方文档虽然对 Milky 的协议内容进行了尽可能详尽的介绍,但仍然有一些地方描述不足,需要进行补充说明。以下内容是根据接到的用户反馈,对一些常见问题的解答。未尽之处,欢迎加入 QQ 群讨论相关细节,或新开 Issue 提出。
xxx字段是用null/undefined还是用0/空字符串表示“无值”?省流:如果这个字段被标记了 optional,那么就大大方方用
null/undefined表示“无值”;否则就用0/空字符串表示“无值”。至于为什么有的字段被标记为 optional,有的没有,这与 Milky 的可空性设计哲学有关,具体如下:
null/undefined和0/空字符串在语义上是等价的,则不标记为 optional,使用0/空字符串表示“无值”;null/undefined和0/空字符串在语义上不等价,或0/空字符串是不合法的值(例如时间戳、QQ 号),则标记为 optional,使用null/undefined表示“无值”。看不懂?没关系,按照上面省流部分说的就行了。
message_seq是否相当于 OneBot 11 中的message_id?省流:
message_scene+peer_id+message_seq= 完整版message_id。message_seq不是“大号的message_id”,而是一个自增的数字,表示消息在当前会话中的顺序,对于每个会话(好友或群聊)都是独立的。Milky 用message_scene、peer_id和message_seq组合来唯一标识一条消息。其中:message_scene是一个字符串,表示消息的场景(例如:好友、群聊等)peer_id是一个数字,表示会话的 ID。对于好友消息,peer_id是好友的 QQ 号;对于群消息,peer_id是群号。OneBot 11 则使用
message_id来唯一标识一条消息。那我实在需要一个消息 ID 该怎么办?
可以通过拼接字符串的方式来实现,但这样的消息 ID 只适用于内部表示,在发送 Milky API 请求时仍然需要从消息 ID 中还原出真实信息。例如,一个来自好友
12345的序列号为42的消息的 ID 可以是friend|12345|42,在调用get_messageAPI 时通过String.split等方法还原出message_scene、peer_id和message_seq。如果一条消息被撤回了 / 没有任何合法消息段,协议端应该如何处理?
Milky 中需要用到消息的规范表示的位置主要是两个 API,以下是两个 API 在处理已被撤回 / 没有任何合法消息段的消息时的预期行为:
get_message:直接 fail,返回的retcode为-404;get_history_messages:返回结果中不包含对应message_seq的消息。例如,message_seq为 29 的消息被撤回了,那么在拉取message_seq从 1 到 30 的历史消息时,返回的消息列表就应该只包含 29 条消息 (1, 2, ..., 28, 30)。一种极端情况是要拉取的 30 条消息全都被撤回 / 没有合法消息段,这时应该返回空数组。此外,如果一条消息没有任何合法消息段,它也不应该出现在
message_receive事件推送中。总而言之,Milky 中的消息至少保证有一个消息段。感谢 #40 提出这一问题。感谢 @idranme 补充消息没有任何合法消息段的情况。
消息撤回(
recall)和戳一戳(nudge)的事件推送中display_开头的字段指的是什么?假如一条消息撤回的提示如下:
那么其对应的
message_recall事件中的display_suffix字段是并假装无事发生。。假如一条戳一戳的提示如下:
那么其对应的
message_nudge事件中的display_action字段是戳了戳,display_suffix字段是的……。不许戳啦!。forward消息段中的title、preview和summary分别指的是什么?这些是用户在接收到合并转发消息但未展开查看时,看到的预览信息。例如这样一条合并转发消息的预览信息:
file消息段和file_upload事件是同一个东西吗?是的,包含在消息中的
file消息段和friend_file_upload、group_file_upload事件上报的内容是相同的,都是表示好友 / 群成员上传了文件,两者的字段和含义也完全一致。协议端在收到文件消息后,需要同时推送包含file消息段的 IncomingMessage 和{friend,group}_file_upload事件,应用端可以按需处理。二者的主要不同在于用途:前者方便在拉取消息时获取文件信息,后者方便在
event驱动的应用中处理用户上传的文件。image、record和video消息段分别支持哪些格式?image:协议端至少需要支持JPG、PNG、GIF、BMP、WEBP格式的图片;record:QQ 使用的语音格式是 SILK。在发送时,协议端至少需要支持WAV和MP3格式到SILK的转码;video:协议端至少需要支持MP4格式的视频,并且在用户未提供thumb_uri时从视频中截取一帧作为缩略图。face_id都有哪些?以下页面整理了可用的 QQ 表情 ID 列表,供参考:
如何获取用户或群的头像?
QQ 有一些公开的 API 可以用来获取头像:
https://q1.qlogo.cn/g?b=qq&nk=${user_id}&s=${quality}user_id:用户 QQ 号;quality:图片质量,可选值为100(100x100)、640(640x640)等。https://p.qlogo.cn/gh/${group_id}/${group_id}/0/group_id:群号。感谢 #36 提出这一问题。
接收的合并转发中为什么提取不到真实 QQ 号?
因为确实提取不到,这是腾讯对被转发者信息的保护。
被转发的消息中,发送者的 QQ 号都会被统一覆盖成
1094950020(一个昵称为QQ用户的默认头像账号),而来源的群号都会被统一覆盖成284840486。同样,在 Milky 中,在没有具体发送者信息的情况下构造合并转发消息时,同样可以提供上述占位符 QQ 号。感谢 #63 补充这一情况。
Milky 会支持 QQ 频道/空间/农场/... 之类的业务相关 API 吗?
目前 Milky 的支持范围仅限于 QQ 本体的私聊及群聊业务,QQ 的其他相对独立的业务暂不考虑。
感谢 #109 提出这一问题。
喵喵?
咕噜咕噜。
感谢 @pk5ls20 提出这一问题(雾)。