Skip to content

常见问题 Q&A #46

@Wesley-Young

Description

@Wesley-Young

为什么会有这个页面?

官方文档虽然对 Milky 的协议内容进行了尽可能详尽的介绍,但仍然有一些地方描述不足,需要进行补充说明。以下内容是根据接到的用户反馈,对一些常见问题的解答。未尽之处,欢迎加入 QQ 群讨论相关细节,或新开 Issue 提出。

xxx 字段是用 null/undefined 还是用 0/空字符串表示“无值”?

省流:如果这个字段被标记了 optional,那么就大大方方用 null/undefined 表示“无值”;否则就用 0/空字符串表示“无值”。

至于为什么有的字段被标记为 optional,有的没有,这与 Milky 的可空性设计哲学有关,具体如下:

  • 如果 null/undefined0/空字符串在语义上是等价的,则不标记为 optional,使用 0/空字符串表示“无值”;
  • 如果 null/undefined0/空字符串在语义上不等价,或 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_scenepeer_idmessage_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_scenepeer_idmessage_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_ 开头的字段指的是什么?

假如一条消息撤回的提示如下:

Salt 撤回了一条消息,并假装无事发生。

那么其对应的 message_recall 事件中的 display_suffix 字段是 并假装无事发生。

假如一条戳一戳的提示如下:

Milk 戳了戳 Shama 的……。不许戳啦!

那么其对应的 message_nudge 事件中的 display_action 字段是 戳了戳display_suffix 字段是 的……。不许戳啦!

forward 消息段中的 titlepreviewsummary 分别指的是什么?

这些是用户在接收到合并转发消息但未展开查看时,看到的预览信息。例如这样一条合并转发消息的预览信息:

群聊的聊天记录      // title
Salt: [动画表情]   // preview[0]
Milk: [图片]      // preview[1]
Shama: [视频]     // preview[2]
---
查看3条转发消息     // summary

file 消息段和 file_upload 事件是同一个东西吗?

是的,包含在消息中的 file 消息段friend_file_uploadgroup_file_upload 事件上报的内容是相同的,都是表示好友 / 群成员上传了文件,两者的字段和含义也完全一致。协议端在收到文件消息后,需要同时推送包含 file 消息段的 IncomingMessage{friend,group}_file_upload 事件,应用端可以按需处理。

二者的主要不同在于用途:前者方便在拉取消息时获取文件信息,后者方便在 event 驱动的应用中处理用户上传的文件。

imagerecordvideo 消息段分别支持哪些格式?

  • image:协议端至少需要支持 JPGPNGGIFBMPWEBP 格式的图片;
  • record:QQ 使用的语音格式是 SILK。在发送时,协议端至少需要支持 WAVMP3 格式到 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 补充这一情况。

喵喵?

咕噜咕噜。

感谢 @pk5ls20 提出这一问题(雾)。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions