圈组消息收发
更新时间: 2024/11/21 16:31:48
NIM SDK 的nim_qchat::Message
类提供圈组消息收发的方法,支持支持文本、图片、语音、视频、文件、地理位置等消息类型。定义圈组消息的结构体为QchatMessage
。
功能介绍
消息类型 |
API关键字 |
说明 |
---|---|---|
文本消息 | text |
消息内容为普通文本 |
图片消息 | image |
消息内容为图片 URL 地址、尺寸、图片大小等信息 |
语音消息 | audio |
消息内容为语音文件的 URL 地址、时长、大小、格式等信息 |
视频消息 | video |
消息内容为视频文件的 URL 地址、时长、大小、格式等信息 |
文件消息 | file |
消息内容为文件的 URL 地址、大小、格式等信息 |
位置消息 | location |
消息内容为地理位置标题、经度、纬度信息 |
提示消息 | tip |
又叫做 Tip 消息,没有推送和通知栏提醒,主要用于会话内的通知提醒,例如进入会话时出现的欢迎消息,或是会话过程中命中敏感词后的提示消息等场景 |
通知消息 | notification |
主要用于圈组的事件通知 |
自定义消息 | custom |
开发者自定义的消息类型,例如红包消息、石头剪子布等形式的消息 |
技术原理
下图展示了集成并初始化 NIM SDK 后,实现圈组消息收发的基本工作流。图中的 QChat 即为 NIM SDK 的圈组组件,云信服务端包含 IM 服务端和圈组服务端。
- 上图仅以静态 Token 登录为例展示消息收发流程。网易云信 IM 还支持动态 Token 登录鉴权和第三方回调登录鉴权,相关详情请参见登录鉴权。
- 圈组服务端与圈组服务器是两个不同概念,前者指云信服务器内提供圈组功能的服务端,后者为圈组的特殊概念,对应 Discord 的 Server, 为社群本身。
上图中的流程可归纳为如下 5 步:
- 账号集成与登录。
- 开发者将应用的用户账号传入云信 IM 服务端,注册云信 IM 账号。
- 云信 IM 服务端返回 Token 给应用服务器。
- 应用客户端登录应用服务器。
- 应用服务端将 Token 返回给应用客户端。
- 用户A 和用户B 带 Token 登录云信 IM 服务端。
- 用户A 创建圈组服务器,并在服务器内创建频道。
- 用户B 加入圈组服务器。
- 用户A 在频道发送一条消息到云信圈组服务器。
- 云信圈组服务器投递消息至频道,用户B 接收消息。
前提条件
- 已开通圈组功能。
- 已完成圈组初始化。
如果频道所属的服务器的成员人数超过 2000 人阈值,接收方还必须先订阅该频道,才能收到该频道的消息。如果未超过 2000 人阈值,无需订阅也能收到消息。订阅相关说明,请参见圈组订阅机制。
实现消息收发
API 调用时序
sequenceDiagram
note over QChat: 初始化
发送方 ->> QChat: 初始化
接收方 ->> QChat: 初始化
note over QChat: 注册回调函数并登录
发送方 ->> QChat: 登录圈组
接收方 ->> QChat: 注册接收消息回调
接收方 ->> QChat: 登录圈组
note over QChat: 双方都成为同一服务器的成员
note over QChat: 双方都能访问同一频道
note over QChat: 发送方拥有发送消息的权限
note over QChat: 消息收发
发送方 ->> QChat: 在频道发送消息
QChat ->> 接收方: 投递消息(QChatMessage)
接收方 ->> QChat: 将消息标记为已读
具体流程
本节仅对上图中标为部分的流程进行说明,其他流程请参考相关文档。例如:
-
接收方在登录圈组前,注册
RegRecvCb
消息接收回调函数。示例代码如下:
C++
nim_qchat::QChatRegRecvMsgCbParam reg_receive_message_cb_param; reg_receive_message_cb_param.cb = [this](const nim_qchat::QChatRecvMsgResp& resp) { // p }; nim_qchat::Message::RegRecvCb(reg_receive_message_cb_param);
-
发送方调用
Send
方法发送消息,调用时通过msg_type
的类型枚举NIMQChatMsgType
设置消息的类型。消息发送方需要拥有发送消息的权限
kPermissionSendMessage
。该方法的部分重要参数说明如下(全量请参见
QchatMessage
):参数类型说明 anti_spam_info
QChatMessageAntiSpamInfo
配置安全通(易盾反垃圾)相关的各项参数。如果您配置了这些参数,在发送消息时,会对发送的文本和附件进行内容审核(反垃圾检测)。根据您在控制台预设的拦截/过滤规则,如果检测到违规内容,消息可能发送失败或者敏感信息被过滤。 圈组的安全通功能属于增值功能,需要在开通圈组功能后再额外开通。如尚未开通,请通过云信官网首页提供的联系方式咨询商务经理开通 mention_all
bool 是否@所有人,false:否,true:是 用户需要拥有@所有人权限( kPermissionAtAll
)才能@所有人mention_accid
char ** @部分人,如果将该消息设置为@所有人(即 mention_all
设置为true)或者@身份组(即mention_role_ids
不为空,则本参数无效)用户需要拥有@某个人权限( kPermissionAtMember
)才能@部分人。mention_role_ids
uint64_t * @的身份组列表,最多@ 10 个身份组。如果将该消息设置为@所有人(即 mention_all
设置为true),则本参数无效用户需要拥有@身份组权限( kPermissionAtRole
)才能@身份组。resend_flag
bool 是否重发消息,false:否,true:是 msg_id
std::string 消息重发时需要指定此消息的 ID(消息发送成功后云信会生成消息 ID) 发送各类型消息的示例代码如下:
文本QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // content moderation param.message.anti_spam_info.use_custom_content = false; param.message.anti_spam_info.anti_spam_using_yidun = true; param.message.anti_spam_info.anti_spam_content = "anti spam content"; param.message.anti_spam_info.anti_spam_bussiness_id = "anti spam bussiness id"; param.message.anti_spam_info.yidun_callback_url = "yidun callback url"; param.message.anti_spam_info.yidun_anti_cheating = "yidun anti cheating"; param.message.anti_spam_info.yidun_anti_spam_ext = "yidun anti spam ext"; // text message param.message.msg_type = kNIMQChatMsgTypeText; auto attach = std::make_shared<QChatDefaultAttach>(); attach->msg_attach = "msg attach"; Message::Send(param);
图片QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // image message param.message.msg_type = kNIMQChatMsgTypeImage; auto attach = std::make_shared<QChatImageAttach>(); attach->file_path = "image path"; attach->width = 100; attach->height = 100; param.message.msg_attach = attach; Message::Send(param);
语音QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // audio message param.message.msg_type = kNIMQChatMsgTypeAudio; auto attach = std::make_shared<QChatAudioAttach>(); attach->file_path = "audio path"; attach->duration = 60; param.message.msg_attach = attach; Message::Send(param);
视频QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // video message param.message.msg_type = kNIMQChatMsgTypeVideo; auto attach = std::make_shared<QChatVideoAttach>(); attach->file_path = "video path"; attach->duration = 60; param.message.msg_attach = attach; Message::Send(param);
文件QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // file message param.message.msg_type = kNIMQChatMsgTypeFile; auto attach = std::make_shared<QChatFileAttach>(); attach->file_path = "file path"; param.message.msg_attach = attach; Message::Send(param);
位置QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // location message param.message.msg_type = kNIMQChatMsgTypeLocation; attach->latitude = 123.456; attach->longitude = 123.456; attach->title = "location title"; param.message.msg_attach = attach; Message::Send(param);
通知QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // notification message param.message.msg_type = kNIMQChatMsgTypeNotification; auto attach = std::make_shared<QChatNotificationAttach>(); attach->id = 1; attach->data = "notification data"; param.message.msg_attach = attach; Message::Send(param);
提示QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // tips message param.message.msg_type = kNIMQChatMsgTypeTips; auto attach = std::make_shared<QChatTipsAttach>(); attach->type = 1; attach->data = "tips data"; param.message.msg_attach = attach; Message::Send(param);
自定义QChatSendMessageParam param; param.message.server_id = 123456; param.message.channel_id = 123456; param.message.msg_body = "message body"; param.message.msg_ext = "message ext"; param.message.resend_flag = false; param.message.msg_id = ""; // only for resend. if not, leave it empty, we will generate it param.message.mention_all = false; param.message.mention_accids = {"accid1", "accid2"}; // if mention_all is true, this will be ignored param.message.history_enable = true; param.message.push_enable = false; param.message.push_payload = "push payload"; param.message.push_content = "push content"; param.message.need_badge = true; param.message.need_push_nick = true; param.message.route_enable = true; // custom message param.message.msg_type = kNIMQChatMsgTypeCustom; auto attach = std::make_shared<QChatDefaultAttach>(); attach->msg_attach = "msg attach"; Message::Send(param);
-
RegRecvCb
回调函数触发,消息投递至接收方。 -
接收方调用
MarkRead
方法将接收到的消息标记为已读。- 将消息标记为已读后,该消息之前接收到的消息全部变为已读状态。
- 如果传入的
timestamp
参数为 0,则频道内所有消息将被标记为未读。 - 该方法调用存在频控,200ms 内最多可调用一次。
示例代码如下:
QChatMarkMessageReadParam param; param.id_info.server_id = 123456; param.id_info.channel_id = 123456; param.timestamp = 123456; param.cb = [this, param](const QChatMarkMessageReadResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Message::MarkRead(param);
相关参考
消息未读数限制
- 所有未读消息(包括@消息)的消息阈值默认为 99 条。
- @消息的未读数的有效期,默认为 7 天,即默认存储 7 天。
若需要扩展上限,可在控制台配置圈组子功能项(未读的@消息数-周期 和 所有未读消息(包括@)的消息计数-阈值),具体请参考开通和配置圈组功能。
此文档是否对你有帮助?