圈组消息管理

更新时间: 2023/07/21 06:56:54

SDK 提供一套完善的圈组消息传输管理服务,包括收发消息、存储消息、上传下载附件、@他人等。支持发送文本、语音、图片、视频、文件、地理位置等类型消息,同时支持用户发送自定义类型的消息。

SDK 中用于表示消息的结构为 QChatMessage,完整定义见 QChatMsgServiceInterface-QChatMessage

QChatMessage 部分重要参数说明见下表:

类型 参数名 说明
string channelId 频道 id
string serverId 服务器 id
string type 消息类型
object attach 附件,type 为 custom,image,video,audio,file,geo 等类型会有
string body 消息内容,type 为 text,tip 时有此值
number time 消息的发送时间
string msgIdClient 客户端消息 id,消息唯一凭证,主键
string msgIdServer 服务端生成的消息 id,如果消息发送成功,服务器将会赋予这个值.
number status 消息的状态 0: 一般状态,默认。 1: 被撤回。 2: 被删除。 大于 10000,用户可自定义。
string deliveryStatus 消息的发送状态,区分发送中 sending,发送失败 failed,发送成功 success
boolean mentionAll 是否 “艾特” 了所有人
string[] mentionAccids 被 “艾特” 的人的 account id 列表
object antiSpamInfo 反垃圾相关字段

其中请注意

  1. type 消息类型是一个字符串,可用的类型有 audio 音视频、custom 自定义、file 文件、geo 地理位置、image 图片、text、tip 提示、video 视频。
  2. body 和 attach 都不一定存在,视 type 类型而定。
  3. 注意 attach,其中 image,video,audio,file 作为文件类型,返回值是 UploadFileResult。而 geo 的返回是 QChatMessageForGEOAttach。而 custom 的返回一个可以随意 key-value 的对象。参见上文 ts 定义
  4. msgIdClient 作为端测唯一凭证的主键用,开发者可以在上层拿它作为 dom diff 的 key。

发送消息

接口说明

可以通过以下接口 sendMessage 发送圈组消息,参见完整 TS 定义 QChatMsgServiceInterface-sendMessage

js/**
 * 发送消息
 */
sendMessage(options: SendMessageOptions & IUploadFileOptions): Promise<QChatMessage>

其中 SendMessageOptions 是消息入参,必须传入 serverId、channelId 和 消息类型 type。

如果您希望在发送消息前提前得到 QChatMessage 以便于插入界面中,请使用 SendMessageOptions 里的 onSendBefore 回调方法。

接口完整入参可以参见 TS 定义 QChatMsgServiceInterface-sendMessage,这里列几个重要的

类型 参数名 说明
string channelId 频道 id
string serverId 服务器 id
string type 消息类型
object attach 附件,type 为 custom,image,video,audio,file,geo 等类型会有
string body 消息内容,type 为 text,tip 时有此值
boolean mentionAll 是否 “艾特” 了所有人
string[] mentionAccids 被 “艾特” 的人的 account id 列表
function onSendBefore 发送前的回调函数,用于发送前拿到这个消息对象

此外,如果发送的是文件类型,可以附加一些 TS 定义里的 IUploadFileOptions 的参数,推荐传入 File 对象,这里也例举几个重要的

类型 参数名 说明
File file JS 的 File 对象,浏览器专用
function onUploadProgress 上传进度钩子函数
function onUploadStart 上传前钩子函数
function onUploadDone 上传完成的钩子

示例代码

js// 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

// 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'
  }
})

如果您配置了QChatMessageAntiSpamInfo 结构下的安全通反垃圾相关参数,在发送消息时,会对发送的文本和附件进行反垃圾检测,根据您在控制台预设的拦截/过滤规则,如果消息触发反垃圾则可能发送消息失败或者消息敏感信息被过滤。安全通相关机制请参见 安全通

重发消息

如果因为网络等原因消息发送失败,deliveryStatus 为 failed,则传入失败的完整的消息体,可以用以下接口重发消息,:

/**
 * 重发某条消息
 *
 * 注意:只有当 QChatMessage 的 deliveryStatus 字段为 failed 时才可以进行重发消息。
 */
resendMessage(options: QChatMessage): Promise<QChatMessage>

完整 TS 定义参见 QChatMsgServiceInterface-resendMessage

示例代码:

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"
})

如果您配置了QChatMessageAntiSpamInfo 结构下的安全通反垃圾相关参数,在重发消息时,会对发送的文本和附件进行反垃圾检测,根据您在控制台预设的拦截/过滤规则,如果消息触发反垃圾则可能发送消息失败或者消息敏感信息被过滤。安全通相关机制请参见 安全通

消息接收监听

参见 TS 定义 QChatInterface-QChatEventInterface-message

在初始化实例时设置好事件,以下为示例代码

jsconst qchat = new QChatSDK({
  ... 
})
qchat.on('message', function (msg) {
  console.log('receive a message', msg)
})

await qchat.login()

请确保消息的发送者和接收者在同一个服务器中。频道人数小于默认阈值(2,000 人)时,接收者不需要订阅频道即可接收消息。频道人数大于默认阈值时,接收者需要订阅频道才能接收消息。订阅相关详情,请参见圈组订阅机制

查询历史消息

SDK 提供了查询消息历史的接口,查询 beginTime 到 endTime 之间的最多 limit 条消息。这里 limit 指上限。相关的 TS 定义参见 QChatMsgServiceInterface-getHistoryMessage

/**
 * 获取历史消息
 */
getHistoryMessage(options: GetHistoryMessageOptions): Promise<QChatMessage[]>

其中 QChatGetMessageHistoryParam 必须传入需要查询消息所属的 serverId 和 channelId,查询范围由 beginTime、endTime 和 limit 共同决定,以先到为准。

同时可以设置排除查询的消息id,用于排除查询时起始时间锚点的消息。

  • 如果 beginTime 上有多条消息,可以指定 excludeMsgId 所代表的消息的时间作为实际的起始时间
  • 如果 beginTime 到 endTime 之间消息大于 limit 条,返回 limit 条记录;如果小于 limit 条,返回实际条数;当已经查询到头时,返回的结果列表的 size 可能会比 limit 小。

endTime 如果设置为 0 则代表服务器当前时间,也就是说,不限制。

默认 reverse 为 false,返回按发送时间降序排列的消息列表,可以设置 reverse 为 true 得到升序列表

当进行首次查询时,推荐 beginTime=0, endTime=0 得到列表,然后再次查询时,填上对应的 beginTime, endTime, excludeMsgId。下面给一段示例代码:

js// page 1
const page1Msgs = await qchat.qchatMsg.getHistoryMessage({
  serverId: "{{YOUR_SERVERID}}",
  channelId: "{{YOUR_CHANNELID}}",
  beginTime: 0,
  endTime: 0,
})

const length = page1Msgs.length
console.log(length) // 100

// page 2
const page2Msgs = await qchat.qchatMsg.getHistoryMessage({
  serverId: "{{YOUR_SERVERID}}",
  channelId: "{{YOUR_CHANNELID}}",
  beginTime: 0,
  endTime: page2Msgs[length - 1].time,
  excludeMsgId: page2Msgs[length - 1].msgIdServer,
})

更新消息

对于已发送的消息,可以修改消息中部分信息,如 body,ext,status。

相关的 TS 定义参见 QChatMsgServiceInterface-updateMessage

js/**
 * 更新某条消息
 *
 * 注意:
 *
 * 1. 只有消息的发送者才可以更新这个消息。更新的字段
 * 2. 返回的内容只是部分的消息体字段
 */
updateMessage(options: UpdateMessageOptions): Promise<Partial<QChatMessage>>

API 中的 message 作为消息体的一部分,必须传入更新操作通用参数、 消息所属的 serverId、消息所属的 channelId、消息发送时间 time 以及 msgIdServer,以作为服务器找到此要修改的消息。

可以修改消息中的内容 body、自定义扩展 ext 和消息服务端状态 status,其中消息服务端状态值必须大于等于 10000,否则会返回 414 错误码。

下面给出一段示例代码,直接传入完整的 QChatMessage 即可:

jsawait qchat.qchatMsg.updateMessage({
  "message": {
    "serverId": "{{YOUR_SERVERID}}",
    "channelId": "{{YOUR_CHANNELID}}",
    "type": "text",
    "body": "keqing",
    "ext": "sdsdsd",
    "msgIdClient": "51d63bbe042f15b6117cc44c971e47e7",
    "fromAccount": "ctt1",
    "fromClientType": "Web",
    "fromDeviceId": "78a42adb0249809d864542827fa42e41",
    "fromNick": "123",
    "time": 1643364678578,
    "updateTime": 1643364678578,
    "msgIdServer": "657293",
    "status": 0,
    "historyEnable": true,
    "deliveryStatus": "success"
  },
  "ps": "ps111",
  "ext": "ext111"
})

消息更新状态监听,参见 TS 定义 QChatInterface-QChatEventInterface-messageUpdate,示例:

jsconst qchat = new QChatSDK({
  ... 
})
qchat.on('messageUpdate', function (msg) {
  console.log('receive a messageUpdate', msg)
})

await qchat.login()

如果您配置了QChatMessageAntiSpamInfo 结构下的安全通反垃圾相关参数,在更新消息时,会对发送的文本和附件进行反垃圾检测,根据您在控制台预设的拦截/过滤规则,如果消息触发反垃圾则可能发送消息失败或者消息敏感信息被过滤。安全通相关机制请参见 安全通

撤回消息

相关的 TS 定义参见 QChatMsgServiceInterface-revokeMessage

撤回圈组消息,目前没有时间限制。

js/**
 * 撤回某条消息
 *
 * 注意:
 *
 * 1. 只有消息的发送者才可以更新这个消息。更新的字段
 * 2. 返回的内容只是部分的消息体字段
 */
revokeMessage(options: RovokeMessageOptions): Promise<Partial<QChatMessage>>

其中 RovokeMessageOptions 中的 message 推荐直接传入整个消息体,也可以只传入 serverIdchannelIdmsgIdServertime,示例代码如下

jsawait qchat.qchatMsg.revokeMessage({
  "message": {
    "serverId": "{{YOUR_SERVERID}}",
    "channelId": "{{YOUR_CHANNELID}}",
    "type": "text",
    "body": "keqing",
    "ext": "sdsdsd",
    "msgIdClient": "51d63bbe042f15b6117cc44c971e47e7",
    "fromAccount": "ctt1",
    "fromClientType": "Web",
    "fromDeviceId": "78a42adb0249809d864542827fa42e41",
    "fromNick": "123",
    "time": 1643364678578,
    "updateTime": 1643364678578,
    "msgIdServer": "657293",
    "status": 0,
    "historyEnable": true,
    "deliveryStatus": "success"
  },
  "ps": "ps111",
  "ext": "ext111"
})

// or

await qchat.qchatMsg.revokeMessage({
  "message": {
    "serverId": "{{YOUR_SERVERID}}",
    "channelId": "{{YOUR_CHANNELID}}",
    "time": 1643364678578,
    "msgIdServer": "657293",
  },
  "ps": "ps111",
  "ext": "ext111"
})

消息撤回状态监听,同样是通过 messageUpdate 的事件,参见 TS 定义 QChatInterface-QChatEventInterface-messageUpdate,示例:

jsconst qchat = new QChatSDK({
  ... 
})
qchat.on('messageUpdate', function (msg) {
  console.log('receive a messageUpdate', msg)
  if (msg.status === 1) {
    console.log('receive a message revoke', msg)
  }
})

await qchat.login()

删除消息

相关的 TS 定义参见 QChatMsgServiceInterface-deleteMessage

js/**
 * 撤回某条消息
 *
 * 注意:
 *
 * 1. 只有消息的发送者才可以更新这个消息。更新的字段
 * 2. 返回的内容只是部分的消息体字段
 */
deleteMessage(options: RovokeMessageOptions): Promise<Partial<QChatMessage>>

其中 RovokeMessageOptions 中的 message 推荐直接传入整个消息体,也可以只传入 serverIdchannelIdmsgIdServertime,示例代码如下

jsawait qchat.qchatMsg.deleteMessage({
  "message": {
    "serverId": "{{YOUR_SERVERID}}",
    "channelId": "{{YOUR_CHANNELID}}",
    "type": "text",
    "body": "keqing",
    "ext": "sdsdsd",
    "msgIdClient": "51d63bbe042f15b6117cc44c971e47e7",
    "fromAccount": "ctt1",
    "fromClientType": "Web",
    "fromDeviceId": "78a42adb0249809d864542827fa42e41",
    "fromNick": "123",
    "time": 1643364678578,
    "updateTime": 1643364678578,
    "msgIdServer": "657293",
    "status": 0,
    "historyEnable": true,
    "deliveryStatus": "success"
  },
  "ps": "ps111",
  "ext": "ext111"
})

// or

await qchat.qchatMsg.deleteMessage({
  "message": {
    "serverId": "{{YOUR_SERVERID}}",
    "channelId": "{{YOUR_CHANNELID}}",
    "time": 1643364678578,
    "msgIdServer": "657293",
  },
  "ps": "ps111",
  "ext": "ext111"
})

消息撤回状态监听,同样是通过 messageUpdate 的事件,参见 TS 定义 QChatInterface-QChatEventInterface-messageUpdate,示例:

jsconst qchat = new QChatSDK({
  ... 
})
qchat.on('messageUpdate', function (msg) {
  console.log('receive a messageUpdate', msg)
  if (msg.status === 2) {
    console.log('receive a message deleted', msg)
  }
})

await qchat.login()

消息标记已读

收到消息后,可以对消息标记已读。标记后,消息发送方会收到未读信息变化通知。API 参见 QChatMsgServiceInterface-markMessageRead

js/**
 * 标记消息已读
 */
markMessageRead(options: MarkMesaageReadOptions): Promise<void>

注意:

  • 该接口做了频控,开发者频繁触发时,200ms 内最多可调用一次。
  • 其中 MarkMesaageReadOptions 需要传入 serverId、ChannelId 和标记已读时间戳。需要注意的是,标记已读成功后,标记已读时间戳之前的所有消息都会被认为是已读。如果标记已读时间戳为 0,则 Channel 中的所有消息都将重新被视为未读消息。

下面给一段示例代码

js// mark all message unread
await qchat.qchatMsg.markMessageRead({
  "serverId": "132305",
  "channelId": "67291",
  "time": 0
})

// mark all message read
await qchat.qchatMsg.markMessageRead({
  "serverId": "132305",
  "channelId": "67291",
  "time": new Date().getTime()
})

关于未读信息变化监听参见事件 QChatInterface-QChatEventInterface-unreadInfo

下面提供一段示例

jsconst qchat = new QChatSDK({
  ... 
})
qchat.on('unreadInfo', function (unreadInfo) {
  console.log('receive a unreadInfo', unreadInfo)
})

await qchat.login()

有关于 unreadInfo 的完整字段参见 QChatInterface-QChatUnreadInfo

类型 参数名 说明
string channelId 频道 id
string serverId 服务器 id
number unreadCount 未读数总数
number mentionedCount 被 @ 的未读数
number maxCount 未读数接收的最大上限,超过上限后,服务器不会下发这个事件
number lastMsgTime 最后一条消息的时间戳
number ackTimestamp 已读的时间戳

要注意的是,如果 maxCount 为 99,unreadCount 此时也是 99,那么服务器已经不会再次下发这个未读事件,开发者应该让界面上的未读数就此显示为 99+。直到调用 markMessageRead 标记了未读数,让 unreadCount 小于 99

抄送相关

消息收发时传入 env, callbackExt, routeEnable 等参数,可配置相应的消息抄送功能, API 定义见 QChatMsgServiceInterface-SendMessageOptions

假设您已在云信控制台配置过抄送,且抄送环境为 prod,抄送地址为 callbackext123,则发送消息抄送的示例代码如下:

jsconst 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"

圈组消息抄送的具体介绍请参见 消息与系统通知相关

搜索消息

调用searchMsgByPage 方法,可按照关键字和消息发送者等搜索当前用户所在服务器下的全部频道或单频道的消息,包括文本消息、图片消息、语音消息、视频消息和文件消息(其他类型消息均不支持搜索)。

已被撤回或删除的消息不可搜索。

示例代码如下:

js// 初始化SDK
const qchat = new QChatSDK({
  ... 
})
// 等待登录完成
await qchat.login()
// 消息搜索
qchat.qchatMsg.searchMsgByPage({

})
此文档是否对你有帮助?
有帮助
去反馈
  • 发送消息
  • 接口说明
  • 示例代码
  • 重发消息
  • 消息接收监听
  • 查询历史消息
  • 更新消息
  • 撤回消息
  • 删除消息
  • 消息标记已读
  • 抄送相关
  • 搜索消息