圈组消息收发
更新时间: 2024/03/15 16:12:32
QChat SDK 的QChatMsgServiceInterface
接口提供圈组消息收发的方法,支持支持文本、图片、语音、视频、文件、地理位置等消息类型。定义圈组消息的结构为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 调用时序
具体流程
本节仅对上图中标为橙色的流程进行说明,其他流程请参考相关文档。例如:
-
接收方在登录圈组前,注册
message
事件回调函数,监听消息接收事件。示例代码如下:
const qchat = new QChat({ // 初始化参数 }) qchat.on('message',(message)=>{})
-
发送方调用
sendMessage
方法发送消息,调用时通过类型枚举type
设置消息的类型。如果您希望在发送消息前提前得到
QChatMessage
以便于插入界面中,请使用SendMessageOptions
里的onSendBefore
回调方法。消息发送方需要拥有发送消息的权限(
sendMsg
)。
该方法的部分重要参数说明如下(全量请参见
SendMessageOptions
和IUploadFileOptions
):参数类型说明 antiSpamInfo
QChatMessageAntiSpamInfo
配置安全通(易盾反垃圾)相关的各项参数。如果您配置了这些参数,在发送消息时,会对发送的文本和附件进行内容审核(反垃圾检测)。根据您在云信控制台预设的拦截/过滤规则,如果检测到违规内容,消息可能发送失败或者敏感信息被过滤。安全通相关机制请参见安全通。 圈组的安全通功能属于增值功能,需要在开通圈组功能后再额外开通,具体请参考开通 IM 安全通。 mentionAll
boolean 是否@所有人,false:否,true:是 用户需要拥有@所有人权限( remindAll
)才能@所有人。mentionAccids
string @部分人,如果将该消息设置为@所有人(即 mention_all
设置为true)或者@身份组(即mention_role_ids
不为空),则本参数无效)用户需要拥有@他人权限( remindOther
)才能@部分人。mentionRoleIds
string @的身份组列表,最多@ 10 个身份组。如果将该消息设置为@所有人(即 mention_all
设置为true),则本参数无效用户需要拥有@身份组权限( mentionedRole
)才能@身份组。onSendBefore
function 发送前的回调函数,用于发送消息前获取消息对象( QChatMessage
)。通过该回调函数获取的消息对象还没有服务端消息 ID(idServer
) 和准确的消息发送成功时间戳(time
),并且status
也只是在发送中(sending
)。如果您希望在发送消息前提前获取到消息对象以便于插入界面中,请使用该回调方法
发送各类型消息的示例代码如下:
文本// text and @everyone message const msg = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "text", "body": "This is a test message", "mentionAll": true }) console.log(msg.msgIdServer) // text and @somebody message const msg1 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "text", "body": "This is a test message", "mentionAccids": ["accountId1", "accountId2"] })
图片// image message const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "image", // Get First File from DOM "file": document.getElementById('fileInput').files[0], "onUploadStart": function(task) { console.log('onUploadStart', task) }, "onUploadProgress": function(progress) { console.log('onUploadProgress', progress) }, "onUploadDone": function(file) { console.log('onUploadDone', file) }, "onSendBefore": function(msg) { console.log('onSendBefore', msg) } }) // trigger order: // onUploadStart -> onUploadProgress -> onUploadDone -> onSendBefore
语音const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "audio", // Get First File from DOM "file": document.getElementById('fileInput').files[0], "onUploadStart": function(task) { console.log('onUploadStart', task) }, "onUploadProgress": function(progress) { console.log('onUploadProgress', progress) }, "onUploadDone": function(file) { console.log('onUploadDone', file) }, "onSendBefore": function(msg) { console.log('onSendBefore', msg) } }) // trigger order: // onUploadStart -> onUploadProgress -> onUploadDone -> onSendBefore
视频const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "video", // Get First File from DOM "file": document.getElementById('fileInput').files[0], "onUploadStart": function(task) { console.log('onUploadStart', task) }, "onUploadProgress": function(progress) { console.log('onUploadProgress', progress) }, "onUploadDone": function(file) { console.log('onUploadDone', file) }, "onSendBefore": function(msg) { console.log('onSendBefore', msg) } }) // trigger order: // onUploadStart -> onUploadProgress -> onUploadDone -> onSendBefore
文件const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "file", // Get First File from DOM "file": document.getElementById('fileInput').files[0], "onUploadStart": function(task) { console.log('onUploadStart', task) }, "onUploadProgress": function(progress) { console.log('onUploadProgress', progress) }, "onUploadDone": function(file) { console.log('onUploadDone', file) }, "onSendBefore": function(msg) { console.log('onSendBefore', msg) } }) // trigger order: // onUploadStart -> onUploadProgress -> onUploadDone -> onSendBefore
位置// GEO message const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "geo", "attach": { "lat": 30.2083999 "lng": 120.21201 "title": 'Hang zhou' } })
通知const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "notification", ... })
提示const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "tip", ... })
自定义const msg2 = await qchat.qchatMsg.sendMessage({ "serverId": "{{YOUR_SERVERID}}", "channelId": "{{YOUR_CHANNELID}}", "type": "custom", ... })
-
message
事件回调触发,消息投递至接收方。 -
接收方调用
markMessageRead
方法将接收到的消息标记为已读。其参数结构MarkMesaageReadOptions
需要传入serverId
、ChannelId
和标记已读时间戳。- 标记已读成功后,当前消息和标记已读时间戳之前的所有消息都会被认为是已读。如果标记已读时间戳为 0,则 Channel 中的所有消息都将重新被视为未读消息。更多消息未读相关说明,请参见频道未读数管理。
- 该方法调用存在频控,200ms 内最多可调用一次。
示例代码如下:
await qchat.qchatMsg.markMessageRead({ "serverId": "132305", "channelId": "67291", "time": new Date().getTime() })
实现消息重发
如果因为网络等原因发送消息失败(deliveryStatus
为 failed
),可调用resendMessage
方法(调用时传入发送失败的完整的消息体),实现消息重发。
- 只有当
QChatMessage
的deliveryStatus
字段为failed
时才可以重发消息。 - 如果重发消息时配置了安全通(易盾反垃圾)相关参数,系统会对发送的文本和附件进行内容审核(反垃圾检测)。根据您在云信控制台预设的拦截/过滤规则,如果检测到违规内容,消息可能发送失败或者敏感信息被过滤。安全通相关机制请参见安全通。圈组的安全通功能属于增值功能,需要在开通圈组功能后再额外开通。如尚未开通,请通过云信官网首页提供的联系方式咨询商务经理开通。
示例代码如下:
jsawait qchat.qchatMsg.resendMessage({
"serverId": "{{YOUR_SERVERID}}",
"channelId": "{{YOUR_CHANNELID}}",
"type": "text",
"body": "121266",
"mentionAll": true,
"msgIdClient": "acb03e935be4b338dd5a3b1998e8170b",
"fromAccount": "11011",
"fromClientType": "Web",
"fromDeviceId": "dcb71ec37ba8ef59a97abadb7189b100",
"fromNick": "ssss",
"time": 1644568398632,
"updateTime": 1644568398632,
"msgIdServer": "853754",
"status": 0,
"historyEnable": true,
"deliveryStatus": "failed"
})
实现消息抄送
消息抄送服务可以将圈组消息或事件等数据,实时同步至您预设的服务器。
-
在云信控制台开通消息抄送。
-
调用
sendMessage
方法发送消息时,传入env
,callbackExt
,routeEnable
等参数,可实现发送消息的同时将该消息实时同步至指定的环境(即您预设的服务器地址)。相关参数具体定义请参见QChatMsgServiceInterface-SendMessageOptions
。
假设您在云信控制台配置的抄送环境为 prod,抄送地址为 callbackext123,则发送消息抄送的示例代码如下:
js
const msg = await qchat.qchatMsg.sendMessage({ serverId: '{{YOUR_SERVERID}}', channelId: '{{YOUR_CHANNELID}}', type: 'text', body: 'This is a test message', env: 'prod', routeEnable: true }) console.log(msg.env, msg.routeEnable, msg.callbackExt) // "prod" true "callbackext123"
您也可通过云信 IM 服务端实现圈组消息抄送,具体介绍请参见圈组消息抄送。
相关参考
消息未读数限制
- 所有未读消息(包括@消息)的消息阈值默认为 99 条。
- @消息的未读数的有效期,默认为 7 天,即默认存储 7 天。
若需要扩展上限,可在控制台配置圈组子功能项(未读的@消息数-周期 和 所有未读消息(包括@)的消息计数-阈值),具体请参考开通和配置圈组功能。
API 参考
API |
说明 |
---|---|
message |
消息接收回事件调函数 |
messageUpdate |
消息更新事件回调函数 |
sendMessage |
发送消息 |
markMessageRead |
将消息标记为已读 |
resendMessage |
重发消息 |