聊天室
聊天室適合直播間、語聊房、活動互動區:沒有固定成員,使用者開啟頁面時進入、離開頁面時離開,一個聊天室可以有幾十萬人同時線上。訊息只推給此刻在聊天室裡的使用者,不進入會話列表,不計未讀數,也沒有離線推送;剛進入的使用者可以看到最近的幾十條訊息。
典型的用法是:你的服務端在直播開始時建立聊天室,把聊天室 ID 交給 App;直播間頁面呼叫 im.chatrooms.enter() 進入,得到一個 ChatroomHandle,用它讀取聊天室資訊、顯示訊息、傳送訊息;離開頁面時呼叫 leave()。
import 'package:deeprespond_im_flutter/deeprespond_im_flutter.dart';
final room = await im.chatrooms.enter('100310941534519296');
room.stream.listen((s) {
print('${s.info.name}(${s.info.memberCount} 人)共 ${s.messages.length} 条消息');
});
await room.send(const OutgoingContent.text('主播晚上好'));聊天室的完整規則(人數上限、身份、訊息的優先順序與限流、最近的訊息、屬性)見服務端文件聊天室管理,本頁只說明在 Flutter App 中怎麼用。聊天室的訊息和狀態只在記憶體中,不寫入本地資料庫。
| 要做什麼 | 看哪裡 |
|---|---|
| 顯示聊天室列表和線上人數 | 查詢聊天室 |
| 進入、切換、離開直播間 | 進入聊天室、切換直播間、離開聊天室 |
| 寫一個直播間頁面 | 在頁面中使用 |
| 切到後臺、斷線後的行為 | 切到後臺與斷線後的重新進入 |
| 被踢、被封禁時提示使用者 | 被移出聊天室 |
| 顯示和傳送訊息、禮物特效、點贊 | 接收訊息、傳送訊息、點贊 |
| 語聊房的麥位 | 聊天室屬性 |
| 房管禁言、踢人、全員禁言 | 管理聊天室 |
查詢聊天室
im.chatrooms.list() 列出應用中對客戶端公開的聊天室(服務端建立時 listed 為 true、狀態正常的),可以按名稱字首搜尋;不公開的聊天室只能按 ID 進入。im.chatrooms.get() 查詢一個聊天室的資訊,不需要先進入。
final page = await im.chatrooms.list(namePrefix: '周末', limit: 20);
for (final item in page.items) {
print('${item.roomId} ${item.name} ${item.memberCount}');
}
// 还有下一页时:im.chatrooms.list(namePrefix: '周末', cursor: page.nextCursor)在列表頁上同時顯示多個聊天室的線上人數,用 onlineCounts() 一次查詢,最多 100 個:
final counts = await im.chatrooms.onlineCounts(['100310941534519296', '100311027031212032']);
for (final c in counts) {
print('${c.roomId}:${c.memberCount} 人在线'); // 不存在和已解散的不在结果中
}線上人數按使用者計算(同一使用者多臺裝置只算一次),最多快取 5 秒,是近似值,適合“1.2 萬人線上”這樣的展示。
進入聊天室
enter() 在進入成功後兌現,返回這個聊天室的控制代碼。進入時可以帶一段最長 512 位元組的 ext(如“VIP3”),隨進入的通知發給其他成員。
try {
final room = await im.chatrooms.enter('100310941534519296', ext: 'VIP3');
print(room.snapshot.state); // in
} on DRException catch (e) {
if (e.reason == 'chatroom_banned') {
showToast('你已被禁止进入该直播间');
} else if (e.code == 'not_found') {
showToast('直播已结束');
} else {
rethrow;
}
}進入的條件:聊天室存在且正常;你沒有被這個聊天室封禁;聊天室沒有滿員(所有者和管理員不受人數上限的限制)。
- 多次進入同一個聊天室:對同一個聊天室多次呼叫
enter(),得到的是同一個控制代碼(ext、leaveOthers只在第一次生效),SDK 記下進入的次數,leave()呼叫同樣的次數後才真正離開。App 中的幾個頁面或元件可以各自進入和離開同一個聊天室,互不影響。 - 進入的數量:同一臺裝置同時進入的聊天室數有上限(預設 10 個),超出時
enter()以limit_exceeded(connection_room_limit)拒絕。 - 進入太頻繁:同一時刻大量使用者進入同一個聊天室時,服務端會讓一部分人稍後再進入,SDK 自動等待並重試,
enter()可能需要幾秒才兌現。 - 還沒連上長連線:進入必須經過長連線,長連線沒有就緒時
enter()等待,最長 15 秒,超時以not_connected拒絕。
切換直播間
在直播間之間切換(如上下滑動切換)時,進入新的聊天室時帶上 leaveOthers: true,會同時離開本 App 進入的其他聊天室,舊的控制代碼的 state 變為 left:
final next = await im.chatrooms.enter('100311027031212032', leaveOthers: true);離開聊天室
final room = await im.chatrooms.enter('100310941534519296');
// ……
await room.leave();leave()立即離開,其他成員會收到離開的通知(人數不多的聊天室)。沒有呼叫leave()而連線斷開的,斷開 15 秒後服務端判定你已離開。- 直播間頁面關閉(
State.dispose)時請呼叫leave(),見下面的在頁面中使用。 - 離開之後控制代碼就結束了:快照的
state為left,不再變化,再呼叫send()等方法以invalid_state拒絕。要再次進入,重新呼叫enter(),會得到新的控制代碼。 im.chatrooms.entered是本 App 當前進入的聊天室(聊天室 ID 到控制代碼)。- 退出登入時,全部控制代碼結束,
state為left。
在頁面中使用
控制代碼的 stream 在訂閱時先發出當前快照,之後每次變化發出新快照,可以直接交給 StreamBuilder。快照不可修改,沒有變化的訊息沿用原來的物件。下面是一個直播間頁面的骨架:進入、顯示、傳送、點贊,頁面關閉時離開。
import 'dart:async';
import 'package:deeprespond_im_flutter/deeprespond_im_flutter.dart';
import 'package:flutter/material.dart';
class LiveRoomPage extends StatefulWidget {
const LiveRoomPage({super.key, required this.im, required this.roomId});
final DRClient im;
final String roomId;
@override
State<LiveRoomPage> createState() => _LiveRoomPageState();
}
class _LiveRoomPageState extends State<LiveRoomPage> {
late final Future<ChatroomHandle> _room = widget.im.chatrooms.enter(widget.roomId);
@override
void dispose() {
// 进入失败的不需要离开
unawaited(_room.then((room) => room.leave(), onError: (Object _) {}));
super.dispose();
}
@override
Widget build(BuildContext context) => FutureBuilder<ChatroomHandle>(
future: _room,
builder: (context, entered) {
if (entered.hasError) return const Center(child: Text('进入失败'));
final room = entered.data;
if (room == null) return const Center(child: Text('正在进入…'));
return StreamBuilder<ChatroomSnapshot>(
stream: room.stream,
initialData: room.snapshot,
builder: (context, s) {
final snap = s.data!;
return Column(
children: [
Text('${snap.info.name}(${snap.info.memberCount} 人在线)'),
if (snap.state == 'reentering') const Text('正在重新连接…'),
Expanded(
child: ListView(
children: [
for (final m in snap.messages)
ListTile(
title: Text(m.senderNickname ?? m.sender ?? '系统'),
subtitle: Text(m.type == 'text' ? '${m.body?['text']}' : '[消息]'),
),
],
),
),
Row(
children: [
TextButton(onPressed: () => room.send(const OutgoingContent.text('666')), child: const Text('发送')),
IconButton(onPressed: room.like, icon: const Icon(Icons.favorite)),
],
),
],
);
},
);
},
);
}切到後臺與斷線後的重新進入
聊天室屬於長連線:進入的狀態儲存在服務端這條連線上。
- 網路斷開又恢復、或在 Wi-Fi 與行動網路之間切換:SDK 立即建立新的長連線,並自動重新進入斷開前所在的聊天室,控制代碼不變,你不需要做任何處理。重新進入期間快照的
state為reentering,可以顯示“正在重新連線”;成功後回到in,並重新獲取聊天室資訊、屬性和最近的訊息。在 15 秒內重新進入的,其他成員看不到你離開再進入。 - 切到後臺:長連線保持,你仍在聊天室中,照常收到訊息,
state保持in。 - 後臺被系統斷開連線:系統掛起 App 或斷開網路後連線關閉,SDK 在後臺不重連;15 秒後服務端判定你已離開,其他成員收到離開的通知,你設定的
autoDelete屬性(如麥位)被刪除。回到前臺後 SDK 重新連線並自動重新進入,state先為reentering再回到in,其他成員看到你重新進入。
斷開期間的訊息不會補發:聊天室訊息只推給此刻線上的連線。重新進入後獲取的最近訊息會與已有的訊息合併、去重。
斷開期間如果你被移出、被封禁,或聊天室已解散、已被封禁,重新進入不會成功,控制代碼按被移出處理。
直播類 App 如果不希望使用者在後臺時繼續佔著聊天室的名額(或麥位),可以在切到後臺時自己呼叫 leave(),回到前臺時重新 enter():
import 'package:flutter/widgets.dart';
class RoomLifecycle {
RoomLifecycle(this.roomId) {
_listener = AppLifecycleListener(onHide: _onHide, onShow: _onShow);
}
final String roomId;
late final AppLifecycleListener _listener;
ChatroomHandle? room;
Future<void> _onHide() async {
await room?.leave();
room = null;
}
Future<void> _onShow() async {
room ??= await im.chatrooms.enter(roomId);
}
void dispose() => _listener.dispose();
}被移出聊天室
你被所有者、管理員或你的服務端移出、封禁,或者聊天室被解散、被封禁時,控制代碼發出 ChatroomRemovedEvent 事件,快照的 state 變為 removed,removed 中是原因。SDK 不會自動重新進入。
final room = await im.chatrooms.enter('100310941534519296');
room.on<ChatroomRemovedEvent>().listen((e) {
final r = e.removed;
final until = r.expiresAt;
final text = switch (r.reason) {
'kicked' => '你已被移出直播间',
'banned' => until != null ? '你已被禁止进入,至 ${until.toLocal()}' : '你已被永久禁止进入',
'dismissed' => '直播已结束',
'disabled' => '该直播间已被关闭',
_ => '你已离开直播间',
};
showToast(text);
});reason | 說明 |
|---|---|
kicked | 被移出,operator 為操作人的使用者名稱(你的服務端操作時為 null)。可以再次進入 |
banned | 被封禁,expiresAt 為封禁的到期時間,永久封禁為 null。到期前不能再進入 |
dismissed | 聊天室已解散 |
disabled | 聊天室已被封禁 |
聊天室資訊與線上人數
快照的 info 是聊天室的資訊:名稱、簡介、封面、公告、所有者、管理員、線上人數、是否全員禁言等,見 ChatroomInfo。資料變化時(包括全員禁言、所有者和管理員的變化)SDK 自動更新快照:
final room = await im.chatrooms.enter('100310941534519296');
final sub = room.stream.listen((s) {
final info = s.info;
print('${info.name} ${info.avatarUrl} 在线 ${info.memberCount} 全员禁言 ${info.muteAll}');
});
// 不再需要时 await sub.cancel()info.self 是你在這個聊天室中的身份和狀態(ChatroomSelf):
| 欄位 | 說明 |
|---|---|
role | owner 所有者 / admin 管理員 / member 普通使用者 |
muted、mutedUntil | 你是否被禁言、禁言的到期時間(永久禁言為 null)。禁言到期時 SDK 自動恢復為 false |
allowlisted | 你是否在白名單中:全員禁言時白名單中的使用者仍然可以發言 |
線上人數 memberCount 在進入時取得;人數不多的聊天室(不超過執行策略 chatroom_member_notify_limit,預設 100 人)在有人進出時隨通知更新。人數更多的聊天室不推送進出通知,需要定時重新整理線上人數時,呼叫 refresh() 或 im.chatrooms.get():
final room = await im.chatrooms.enter('100310941534519296');
final timer = Timer.periodic(const Duration(seconds: 30), (_) {
unawaited(room.refresh().catchError((Object _) {}));
});
// 离开时 timer.cancel()接收訊息
快照的 messages 是進入後獲取的最近的訊息,加上之後收到和發出的訊息,按到達的順序排列,最多保留 500 條(更早的自動丟棄)。通常直接按 messages 構建訊息列表(見在頁面中使用)。
需要對每條新訊息做處理(如播放禮物特效)時,監聽 ChatroomMessageReceived 事件:
final room = await im.chatrooms.enter('100310941534519296');
room.on<ChatroomMessageReceived>().listen((e) {
final m = e.message;
if (m.type == 'custom' && m.body?['gift'] != null) {
print('${m.senderNickname} 送出了 ${m.body!['gift']}');
}
});- 管理員和官方訊息:
senderRole為傳送時的身份(owner、admin、member),可以據此顯示“房管”標識;local.trusted為true的訊息由你的服務端、控制檯或系統發出,不是使用者在客戶端傳送的,可以顯示為官方訊息。不要根據ext中的內容判斷,ext由傳送者自己填寫。 - 系統訊息:
senderType為system的訊息,sender、senderNickname、senderAvatarUrl、senderRole都為null。 - 訊息過多時:熱鬧的聊天室中,服務端每秒推給每個連線的訊息有上限,超出時先丟棄低優先順序的,再丟棄普通的(高優先順序的正常情況下不會丟棄)。有訊息被丟棄時控制代碼發出
ChatroomDropped事件,可以提示“訊息過多,已省略部分”:
room.on<ChatroomDropped>().listen((e) {
print('消息过多,已省略 ${e.count} 条');
});- 撤回:訊息被撤回時,SDK 把它從
messages中去掉,併發出ChatroomMessageRecalled事件; - 不保證送達和順序:網路異常時訊息可能丟失,不同使用者發出的訊息到達的先後可能略有不同。需要可靠送達的內容(如禮物結算)請以高優先順序傳送,並由你的業務另行保證。
room.events 是控制代碼全部事件的流(Stream<ChatroomEvent>,ChatroomEvent 是密封類),可以用 switch 一起處理;room.on<T>() 只取一種。
最近的訊息
進入聊天室後,SDK 自動獲取最近的訊息並放在 messages 的前面,你不需要另外呼叫。最近的訊息只有普通和高優先順序的,最多 chatroom_history_size 條(執行策略,預設 50 條),只保留 24 小時;執行策略設為 0 時不儲存,進入後 messages 從空開始。最近的訊息不能向前翻頁。
收到服務端的提示、可能漏收了內容時,SDK 會自動重新獲取聊天室資訊、屬性和最近的訊息,並與已有的訊息合併、去重。你也可以呼叫 refresh() 手動重新整理。
傳送訊息
send() 傳送一條訊息,支援文字、位置、自定義訊息,以及已上傳的圖片、語音、影片、檔案,內容的格式與單聊、群聊訊息相同,見訊息格式。
final room = await im.chatrooms.enter('100310941534519296');
final sent = await room.send(const OutgoingContent.text('唱得太好了!'));
print('${sent.messageId} ${sent.local.status}'); // sent傳送時,普通和高優先順序的訊息先以 sending 狀態出現在 messages 中,成功後變為 sent,失敗時變為 failed 並以錯誤拒絕。網路錯誤、超時時 SDK 自動重試,1 分鐘內結束;被限流(rate_limited)時不自動重試,請提示使用者“傳送太頻繁”。在進入完成之前呼叫的,等進入成功後再傳送;長連線沒有就緒時最多等待 15 秒。
優先順序
每條聊天室訊息有一個優先順序(ChatroomPriority),決定訊息過多時是否會被限流或丟棄:
priority | 用途 | 誰可以傳送 | 傳送時超出聊天室的額度 |
|---|---|---|---|
high | 系統通知、管理員公告、禮物結算等不能丟的訊息 | 所有者、管理員 | 以 rate_limited 拒絕 |
normal | 普通聊天,預設 | 所有人 | 以 rate_limited 拒絕 |
low | 點贊、彈幕特效、進場特效等丟了無妨的高頻訊息 | 所有人 | 靜默丟棄,返回的訊息 local.status 為 dropped,不必提示使用者 |
final room = await im.chatrooms.enter('100310941534519296');
// 进场特效:低优先级
await room.send(const OutgoingContent.custom({'effect': 'enter', 'level': 3}), priority: ChatroomPriority.low);
// 管理员公告:高优先级,普通用户发送以 permission_denied(priority_denied)拒绝
await room.send(const OutgoingContent.text('请文明发言'), priority: ChatroomPriority.high);低優先順序的訊息不先出現在 messages 中,也不自動重試;服務端推回來後才出現在 messages 中,被丟棄的不會出現。
每個聊天室每秒接受的普通和低優先順序訊息數由執行策略 chatroom_msg_per_second 決定(預設 40 條),見訊息的優先順序與下發。
大小上限與圖片
一條聊天室訊息(型別、內容和 ext 合計)不能超過執行策略 max_chatroom_message_bytes(預設 2 KB),超出時 SDK 在本地以 local_validation(too_large)拒絕。
傳送圖片等附件時,先上傳檔案,再用 OutgoingContent.uploaded 把地址寫進訊息。聊天室不支援直接傳入檔案,OutgoingContent.image(DRFile(...)) 這類內容以 unsupported(chatroom_attachment)拒絕:
Future<void> sendImage(ChatroomHandle room, String path) async {
final info = await im.files.upload(DRFile(path), purpose: UploadPurpose.attachment, kind: FileKind.image).result;
await room.send(OutgoingContent.uploaded('image', {
'url': info.url,
if (info.width != null) 'width': info.width,
if (info.height != null) 'height': info.height,
'size': info.size,
}));
}上傳和顯示附件見檔案與圖片。
禁言
你被禁言(info.self.muted 為 true),或聊天室開啟了全員禁言(info.muteAll 為 true)而你不是所有者、管理員、也不在白名單中時,不能傳送訊息和設定屬性,傳送以 chatroom_muted 拒絕,details['reason'] 為 member(你被禁言)或 all(全員禁言)。請據快照禁用輸入框:
bool canSpeak(ChatroomSnapshot s) {
final self = s.info.self;
final privileged = self?.role == 'owner' || self?.role == 'admin' || self?.allowlisted == true;
return self?.muted != true && (!s.info.muteAll || privileged);
}禁言、解除禁言、全員禁言的變化會實時更新快照;禁言到期時 SDK 在本地自動恢復。使用者被全域性禁言(聊天室場景)時,傳送以 user_muted 拒絕,見使用者、好友與線上狀態。
點贊
點贊這類高頻操作不要每點一次發一條訊息。like() 把一秒內的多次點贊合併成一條低優先順序的訊息傳送,不等待結果,也不丟擲錯誤:
// 用户每点一次
room.like();
// 其他人的点赞(同一个人一秒内的合并为一次)
room.on<ChatroomLike>().listen((e) {
print('${e.username} 点了 ${e.count} 个赞');
});點贊不會出現在 messages 中,只以 ChatroomLike 事件交給你。點贊是低優先順序的訊息,聊天室訊息過多時可能被丟棄。
撤回訊息
final room = await im.chatrooms.enter('100310941534519296');
final sent = await room.send(const OutgoingContent.text('发错了'));
final id = sent.messageId;
if (id != null) {
final changed = await room.recall(id);
}- 普通使用者可以在執行策略
recall_window_seconds(預設 120 秒)內撤回自己的訊息; - 管理員可以撤回傳送者現在是普通使用者的訊息,所有者可以撤回任何人的訊息;
- 只能撤回還在最近的訊息中的訊息,已經不在的以
not_found拒絕。
撤回後,所有人的 messages 中這條訊息被去掉,併發出 ChatroomMessageRecalled 事件:
room.on<ChatroomMessageRecalled>().listen((e) {
final by = e.recalledBy;
print(by != null ? '$by 撤回了一条消息' : '一条消息已被撤回');
});成員列表
members() 分頁返回此刻在聊天室裡的使用者,按進入時間從早到晚排列,每頁最多 100 個。翻頁時 SDK 已按使用者名稱去重(不帶 cursor 從第一頁開始時重新計)。
final room = await im.chatrooms.enter('100310941534519296');
var page = await room.members(limit: 50);
print(page.items.map((m) => '${m.nickname.isNotEmpty ? m.nickname : m.username}(${m.role})'));
final next = page.nextCursor;
if (next != null) {
page = await room.members(cursor: next, limit: 50);
}人數不多的聊天室(不超過執行策略 chatroom_member_notify_limit,預設 100 人),有人進入和離開時控制代碼發出 ChatroomMemberJoined、ChatroomMemberLeft 事件,同時更新快照中的線上人數。人數更多的聊天室不推送這兩個事件;需要顯示“某某進入直播間”時,請讓進入的使用者自己發一條低優先順序的自定義訊息。
room.on<ChatroomMemberJoined>().listen((e) {
final nickname = e.data['nickname'];
print('${nickname is String && nickname.isNotEmpty ? nickname : e.username} 进入了直播间,ext:${e.data['ext']}');
});
room.on<ChatroomMemberLeft>().listen((e) {
print('${e.username} 离开了直播间(${e.data['reason']})');
});兩個事件都有 username,data 是通知的原始內容:
| 事件 | data 的欄位 |
|---|---|
ChatroomMemberJoined | room_id、username、nickname、avatar_url、role、ext(進入時帶的 ext)、joined_at、member_count |
ChatroomMemberLeft | room_id、username、reason(left 主動離開 / disconnected 斷開 / kicked 被移出 / banned 被封禁)、member_count |
聊天室屬性
屬性是聊天室的自定義鍵值對,全體成員可見,常用於語聊房的麥位(如 seat_1 為 zhangsan)、直播間的玩法狀態。快照的 attributes 是當前的全部屬性(鍵到 ChatroomAttribute),變化時 SDK 自動更新快照。
final room = await im.chatrooms.enter('100310941534519296');
room.stream.listen((s) {
print('1 号麦:${s.attributes['seat_1']?.value ?? '空位'}');
});設定和刪除屬性
final room = await im.chatrooms.enter('100310941534519296');
// 上麦:离开聊天室(包括断线 15 秒后)时自动删除,麦位不会一直被占着
final result = await room.setAttributes({'seat_1': 'zhangsan'}, autoDelete: true);
if (result.failed.containsKey('seat_1')) {
showToast('这个麦位已经有人了');
}
// 下麦
await room.removeAttributes(['seat_1']);- 誰能修改:在聊天室裡的使用者可以設定和刪除沒人設定過的鍵和自己設定的鍵;別人設定的鍵在
failed中返回permission_denied(attribute_owned),其他鍵照常寫入。所有者和管理員帶上force: true可以覆蓋和刪除別人(包括你的服務端)設定的鍵,普通使用者帶force以permission_denied(role_required)拒絕。 - 禁言:被禁言的使用者,以及全員禁言時不在白名單中的普通使用者,不能設定屬性(以
chatroom_muted拒絕),可以刪除自己設定的屬性。 - 格式:每個聊天室最多 100 個鍵。鍵為 1 到 128 個字元,只能包含字母、數字和
_、-、.、:;值為字串,最長 4096 位元組。一次最多設定或刪除 20 個鍵,一次設定的鍵和值合計不超過 16 KB,超出時 SDK 在本地以local_validation拒絕。 - 頻率:每個聊天室每秒最多 20 次屬性寫入。每秒變化多次的狀態(如實時點贊數)不適合放在屬性中,請用低優先順序的自定義訊息。
- 設定後,屬性的值還會經過內容安全檢查,違規的屬性會被刪除。
公告
公告是快照中的 info.announcement,每次修改都會更新 announcementUpdatedAt。要提示“公告已更新”,記下使用者看過的公告時間(如儲存在 shared_preferences 中),與它比較:
DateTime? seenAnnouncementAt; // 从持久化存储中读取
void checkAnnouncement(ChatroomSnapshot s, void Function(String text) show) {
final info = s.info;
final updatedAt = info.announcementUpdatedAt;
if (info.announcement.isNotEmpty && updatedAt != null && updatedAt != seenAnnouncementAt) {
show(info.announcement);
seenAnnouncementAt = updatedAt; // 同时写回持久化存储
}
}所有者和管理員可以修改公告:
await room.manage.update(const ChatroomPatch(announcement: '今晚 8 点开播,请文明发言'));管理聊天室
所有者和管理員可以在客戶端管理聊天室,介面在控制代碼的 manage 下(需要先進入聊天室)。身份不滿足時以 permission_denied(role_required,details['required_role'] 為需要的身份)拒絕。普通使用者的介面中請隱藏這些入口,按 info.self?.role 判斷。
| 操作 | 方法 | 所有者 | 管理員 |
|---|---|---|---|
| 修改名稱、簡介、封面、公告 | manage.update() | 可以 | 可以 |
| 修改人數上限、是否出現在列表中 | manage.update() | 可以 | 不可以 |
| 開啟、關閉全員禁言 | manage.setMuteAll() | 可以 | 可以 |
| 禁言、解除禁言,檢視禁言名單 | manage.mute()、unmute()、mutes() | 可以 | 只能處置普通使用者 |
| 封禁、解除封禁,檢視封禁名單 | manage.ban()、unban()、bans() | 可以 | 只能處置普通使用者 |
| 移出 | manage.kick() | 可以 | 只能移出普通使用者 |
| 管理白名單 | manage.allowlist | 可以 | 可以 |
| 設定、取消管理員 | manage.setAdmin() | 可以 | 不可以 |
| 轉讓所有者 | manage.transferOwner() | 可以 | 不可以 |
| 解散聊天室 | manage.dismiss() | 可以 | 不可以 |
| 傳送高優先順序的訊息 | send() | 可以 | 可以 |
| 撤回別人的訊息 | recall() | 任何人的 | 普通使用者的 |
- 沒有人能禁言、移出或封禁所有者(
owner_protected);管理員不能處置其他管理員(admin_protected)。 - 解除禁言和封禁時,管理員只能解除管理員設定的,所有者和你的服務端設定的只有所有者能解除(
set_by_higher_role)。 - 聊天室被封禁期間,客戶端的管理操作都以
chatroom_disabled拒絕。 - 普通使用者可以進入、傳送普通和低優先順序的訊息、檢視成員和最近的訊息、設定屬性、撤回自己的訊息。
禁言、封禁與移出
禁言、封禁、移出和白名單都是批次操作,一次最多 100 人,逐個處理,某個使用者失敗不影響其他使用者,返回每個使用者的結果(ChatroomMemberResult):
final room = await im.chatrooms.enter('100310941534519296');
// 禁言 10 分钟;省略 durationSeconds 为永久禁言
final results = await room.manage.mute(['spammer01', 'spammer02'], durationSeconds: 600, reason: '刷屏');
for (final r in results) {
if (!r.ok) showToast('${r.username}:${r.code}'); // 如 permission_denied(owner_protected)
}
await room.manage.unmute(['spammer02']);
// 封禁:在聊天室里的会被立即移出,到期前不能再进入
await room.manage.ban(['troll01'], durationSeconds: 24 * 3600);
// 移出:之后可以再次进入
await room.manage.kick(['troll02']);- 禁言:不能傳送訊息和設定屬性,仍然可以留在聊天室裡、接收訊息。時長 1 秒到 10 年,或永久,到期自動解除。
- 封禁:在聊天室裡的被移出,封禁期間不能進入。封禁管理員時,他同時不再是管理員。
- 移出:只是讓他離開,他可以再次進入;要阻止再次進入請用封禁。
- 三個名單(禁言、封禁、白名單)與使用者是否在聊天室裡無關,可以對此刻不在聊天室裡的使用者操作。
檢視名單(只列出未到期的):
final mutes = await room.manage.mutes(limit: 20);
for (final entry in mutes.items) {
final name = entry.nickname.isNotEmpty ? entry.nickname : entry.username;
print('$name 禁言到 ${entry.mutedUntil?.toLocal() ?? '永久'}');
}全員禁言與白名單
final room = await im.chatrooms.enter('100310941534519296');
await room.manage.setMuteAll(true);
// 嘉宾在全员禁言时仍然可以发言
await room.manage.allowlist.add(['guest01']);
await room.manage.allowlist.remove(['guest01']);
await room.manage.setMuteAll(false);全員禁言時,所有者、管理員和白名單中的使用者仍然可以發言;被單獨禁言的使用者即使在白名單中也不能發言。白名單最多 500 人。
修改資料
manage.update() 只修改 ChatroomPatch 中給出的欄位,返回修改後的聊天室資訊。可以帶上讀取到的 info.infoVersion 作為 version,防止覆蓋別人同時做的修改,不一致時以 version_conflict 拒絕。
final room = await im.chatrooms.enter('100310941534519296');
final info = room.snapshot.info;
await room.manage.update(
const ChatroomPatch(name: '周末音乐会(返场)', description: '每周六晚八点'),
version: info.infoVersion,
);修改封面時,先以用途 chatroom_avatar 上傳圖片:
Future<void> changeCover(ChatroomHandle room, String path) async {
final uploaded = await im.files.upload(DRFile(path), purpose: UploadPurpose.chatroomAvatar).result;
await room.manage.update(ChatroomPatch(avatarUrl: uploaded.url));
}名稱、簡介和公告會經過內容安全檢查,不透過的以 content_rejected 拒絕(details['field'] 為不透過的欄位)。
管理員、所有者與解散
final room = await im.chatrooms.enter('100310941534519296');
await room.manage.setAdmin('lisi', true); // 设置管理员(最多 99 个)
await room.manage.setAdmin('lisi', false); // 取消管理员
await room.manage.transferOwner('wangwu'); // 转让后你成为普通用户所有者可以解散聊天室,解散後所有人(包括自己)被移出,ChatroomRemovedEvent 的原因為 dismissed,不能恢復:
await room.manage.dismiss();在客戶端建立聊天室
預設只能由你的服務端或在控制檯中建立聊天室。應用在執行策略中開啟 client_chatroom_create_enabled 後,使用者可以在客戶端建立,建立者成為所有者。沒有開啟時 create() 以 permission_denied(client_create_disabled)拒絕,請按執行配置決定是否顯示入口:
if (im.config?.clientChatroomCreateEnabled == true) {
final info = await im.chatrooms.create(name: '我的直播间', description: '欢迎来玩', listed: true);
final room = await im.chatrooms.enter(info.roomId);
}應用中的聊天室數有上限,達到時以 limit_exceeded(chatroom_limit)拒絕。
介面參考
im.chatrooms.list()
分頁列出對客戶端公開(listed 為 true)、狀態正常的聊天室,按建立時間從新到舊排列;按名稱字首搜尋時按名稱排列。引數都是命名引數。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
namePrefix | String? | 否 | 按名稱字首搜尋,1 到 128 個字元 |
limit | int? | 否 | 每頁條數,預設 20,最多 100 |
cursor | String? | 否 | 上一頁返回的 nextCursor |
返回值:Future<DRPage<ChatroomListItem>>,nextCursor 為下一頁的遊標,沒有下一頁時為 null。
可能的錯誤:invalid_argument(引數不合法)、not_signed_in。
im.chatrooms.get()
查詢一個聊天室的資訊,含當前線上人數和你在其中的身份 self,不需要先進入。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
roomId | String | 是 | 聊天室 ID |
返回值:Future<ChatroomInfo>。
可能的錯誤:not_found(聊天室不存在或已解散)、local_validation(roomId 為空)。
im.chatrooms.onlineCounts()
批次查詢線上人數。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
roomIds | List<String> | 是 | 聊天室 ID,1 到 100 個 |
返回值:Future<List<ChatroomOnlineCount>>,按請求的順序;不存在和已解散的聊天室不在結果中,已封禁的為 0。
可能的錯誤:local_validation(roomIds 為空或超過 100 個)。
im.chatrooms.create()
在客戶端建立聊天室,你成為所有者。需要應用開啟 client_chatroom_create_enabled。引數都是命名引數。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
name | String | 是 | 名稱,1 到 128 個字元 |
description | String? | 否 | 簡介,最長 512 個字元 |
avatarUrl | String? | 否 | 封面地址,以用途 chatroom_avatar 上傳後得到 |
announcement | String? | 否 | 公告,最長 2048 個字元 |
maxMembers | int? | 否 | 人數上限,1 到 500000;省略時跟隨執行策略 |
listed | bool? | 否 | 是否出現在聊天室列表中,預設 true |
返回值:Future<ChatroomInfo>。建立後需要呼叫 enter() 才進入。
可能的錯誤:permission_denied(client_create_disabled,應用沒有開啟客戶端建立,在本地判斷)、limit_exceeded(chatroom_limit)、content_rejected(名稱、簡介或公告沒有透過內容安全檢查)、invalid_argument(如封面地址不被允許 url_not_allowed)、app_unavailable(應用只讀)、local_validation(名稱為空)。
im.chatrooms.enter()
進入聊天室,成功後兌現。對同一個聊天室多次呼叫返回同一個控制代碼,進入次數加一。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
roomId | String | 是 | 聊天室 ID |
ext | String? | 否 | 命名引數。這次進入的附加資訊,最長 512 位元組,隨進入的通知發給其他成員。只在第一次進入時生效 |
leaveOthers | bool | 否 | 命名引數。為 true 時同時離開本 App 進入的其他聊天室,用於切換直播間;預設 false |
返回值:Future<ChatroomHandle>。
可能的錯誤:not_found(聊天室不存在或已解散)、chatroom_disabled(聊天室已被封禁)、permission_denied(chatroom_banned,你被封禁,details['expires_at'] 為到期時間,永久為 null)、limit_exceeded(chatroom_member_limit 聊天室已滿;connection_room_limit 同時進入的聊天室已達上限)、rate_limited(進入太頻繁,SDK 等待時間不超過 60 秒的會自動重試)、not_connected(長連線 15 秒內沒有就緒)、local_validation(roomId 為空或 ext 超長)、not_signed_in。
im.chatrooms.entered
只讀屬性,Map<String, ChatroomHandle>(不可修改):本 App 當前進入的聊天室,聊天室 ID 到控制代碼。
ChatroomHandle.snapshot
只讀屬性:控制代碼當前的快照(不可修改,變化時整體替換),見 ChatroomSnapshot。
ChatroomHandle.stream
Stream<ChatroomSnapshot>:訂閱時先發出當前快照,之後每次變化發出新快照。可以多處訂閱;不再需要時取消訂閱。
ChatroomHandle.events 與 on()
events 為控制代碼的全部事件(Stream<ChatroomEvent>);on<T extends ChatroomEvent>() 返回按型別過濾的 Stream<T>,如 room.on<ChatroomLike>()。
| 事件 | 欄位 | 說明 |
|---|---|---|
ChatroomMessageReceived | message(ChatroomMessageView) | 收到新訊息,或你傳送的訊息被服務端確認 |
ChatroomMessageRecalled | messageId、recalledBy(String?)、recalledAt(DateTime?) | 訊息被撤回,recalledBy 為操作人,你的服務端撤回時為 null |
ChatroomMemberJoined | username、data | 有人進入(只在人數不多的聊天室推送),data 的欄位見成員列表 |
ChatroomMemberLeft | username、data | 有人離開(只在人數不多的聊天室推送) |
ChatroomLike | username、count | 有人點贊 |
ChatroomDropped | count | 訊息過多,服務端丟棄了 count 條 |
ChatroomRemovedEvent | removed(ChatroomRemoved) | 你被移出,見被移出聊天室 |
ChatroomHandle.send()
傳送一條聊天室訊息。在進入完成之前呼叫的,等進入成功後再傳送。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
content | OutgoingContent | 是 | 訊息內容:text、location、custom,或 uploaded(已上傳的附件)。不支援直接傳入檔案 |
priority | ChatroomPriority | 否 | 命名引數。優先順序,預設 normal。high 只有所有者和管理員能用 |
ext | Map<String, Object?>? | 否 | 命名引數。擴充套件欄位 |
返回值:Future<ChatroomMessageView>,傳送成功的訊息;低優先順序被丟棄時 local.status 為 dropped、messageId 為 null。
可能的錯誤:chatroom_muted(被禁言或全員禁言,details['reason'] 為 member 或 all,details['muted_until'] 為到期時間)、user_muted(被全域性禁言)、permission_denied(priority_denied,普通使用者傳送高優先順序的訊息)、rate_limited(user_send_rate 你傳送太頻繁;room_send_rate 聊天室訊息太多)、message_rejected(被內容安全或你的傳送前回撥拒絕)、payload_too_large、local_validation(內容不合法,如 too_large 超過 max_chatroom_message_bytes)、unsupported(chatroom_attachment,直接傳入了檔案)、not_chatroom_member、chatroom_disabled、not_found、app_unavailable、not_connected、invalid_state(控制代碼已結束)。
ChatroomHandle.like()
點贊。一秒內的多次點贊合併成一條低優先順序的訊息傳送,不返回結果,也不丟擲錯誤。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
count | int | 否 | 可選的位置引數。這次點讚的次數,正整數,預設 1 |
返回值:void。
ChatroomHandle.setAttributes()
設定聊天室屬性。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
attributes | Map<String, String> | 是 | 鍵到值,1 到 20 個,鍵和值合計不超過 16 KB |
autoDelete | bool | 否 | 命名引數。為 true 時這些鍵在你離開聊天室時自動刪除,預設 false |
force | bool | 否 | 命名引數。覆蓋別人設定的鍵,只有所有者和管理員能用,預設 false |
返回值:Future<AttributeResult>。部分鍵失敗時不丟擲錯誤,失敗的鍵在 failed 中。
可能的錯誤:chatroom_muted、permission_denied(role_required,普通使用者帶 force)、rate_limited(attribute_rate、room_attribute_rate)、invalid_argument(invalid_attribute_key、invalid_attribute_value)、local_validation(鍵數或大小超出)、not_chatroom_member、chatroom_disabled、app_unavailable、not_connected、invalid_state。
ChatroomHandle.removeAttributes()
刪除聊天室屬性。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
keys | List<String> | 是 | 要刪除的鍵,1 到 20 個;不存在的鍵忽略 |
force | bool | 否 | 命名引數。刪除別人設定的鍵,只有所有者和管理員能用,預設 false |
返回值:Future<AttributeResult>。
可能的錯誤:同 setAttributes(),被禁言時也可以刪除自己設定的屬性。
ChatroomHandle.recall()
撤回一條聊天室訊息。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
messageId | String | 是 | 訊息 ID |
返回值:Future<bool>,是否有變化;已經撤回過的為 false。
可能的錯誤:permission_denied(recall_window_expired 超過可撤回的時間;recall_denied 無權撤回這條訊息)、not_found(訊息已不在最近的訊息中)、local_validation(messageId 為空)、invalid_state。
ChatroomHandle.members()
分頁返回此刻在聊天室裡的使用者,按進入時間從早到晚排列,已按使用者名稱去重。引數都是命名引數。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
limit | int? | 否 | 每頁條數,最多 100 |
cursor | String? | 否 | 上一頁返回的 nextCursor;不帶時從第一頁開始 |
返回值:Future<DRPage<ChatroomMember>>。
可能的錯誤:not_chatroom_member、invalid_state。
ChatroomHandle.refresh()
重新獲取聊天室資訊(含線上人數)、屬性和最近的訊息,更新快照。
返回值:Future<void>。
可能的錯誤:not_found、invalid_state。
ChatroomHandle.leave()
離開聊天室。進入次數減一,減到 0 時真正離開,之後控制代碼結束。進入還沒完成時呼叫的,等進入完成後再處理。控制代碼已結束時呼叫沒有作用。
返回值:Future<void>,不會失敗。
ChatroomHandle.manage.update()
修改聊天室資料,只修改給出的欄位。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
patch | ChatroomPatch | 是 | 要修改的欄位,見 ChatroomPatch |
version | int? | 否 | 命名引數。讀取到的 info.infoVersion,不一致時不修改 |
返回值:Future<ChatroomInfo>,修改後的資訊。
可能的錯誤:permission_denied(role_required)、version_conflict、content_rejected、invalid_argument、chatroom_disabled、app_unavailable、invalid_state。
ChatroomHandle.manage.setMuteAll()
開啟或關閉全員禁言(所有者、管理員)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
on | bool | 是 | true 開啟,false 關閉 |
返回值:Future<void>。
可能的錯誤:permission_denied(role_required)、chatroom_disabled、invalid_state。
ChatroomHandle.manage.setAdmin()
設定或取消管理員(所有者)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
username | String | 是 | 使用者名稱,不要求他在聊天室裡 |
admin | bool | 是 | true 設定,false 取消 |
返回值:Future<void>。
可能的錯誤:permission_denied(role_required;target_banned 對方在封禁中)、limit_exceeded(admin_limit,管理員已有 99 個)、not_found(使用者不存在)、chatroom_disabled、invalid_state。
ChatroomHandle.manage.transferOwner()
把所有者轉讓給另一個使用者(所有者),你成為普通使用者。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
username | String | 是 | 新所有者的使用者名稱,不要求他在聊天室裡 |
返回值:Future<void>。
可能的錯誤:permission_denied(role_required)、not_found、chatroom_disabled、invalid_state。
ChatroomHandle.manage.mute()
禁言使用者(所有者、管理員)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
durationSeconds | int? | 否 | 命名引數。時長,1 到 315360000 秒(10 年);省略表示永久 |
reason | String? | 否 | 命名引數。原因 |
返回值:Future<List<ChatroomMemberResult>>,每個使用者的結果:成功的 result 為 muted 或 unchanged,失敗的帶 code(如 permission_denied 的 owner_protected、admin_protected,not_found,limit_exceeded 的 mute_limit)。
可能的錯誤:permission_denied(role_required)、chatroom_disabled、invalid_argument、local_validation(usernames 為空)、invalid_state。
ChatroomHandle.manage.unmute()
解除禁言(所有者、管理員)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
返回值:Future<List<ChatroomMemberResult>>,成功為 unmuted 或 unchanged(原來沒有禁言),失敗如 permission_denied(set_by_higher_role)。
可能的錯誤:同 mute()。
ChatroomHandle.manage.ban()
封禁使用者(所有者、管理員),在聊天室裡的同時被移出。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
durationSeconds | int? | 否 | 命名引數。時長,1 到 315360000 秒;省略表示永久 |
reason | String? | 否 | 命名引數。原因 |
返回值:Future<List<ChatroomMemberResult>>,成功為 banned 或 unchanged,失敗如 owner_protected、admin_protected、ban_limit。
可能的錯誤:同 mute()。
ChatroomHandle.manage.unban()
解除封禁(所有者、管理員)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
返回值:Future<List<ChatroomMemberResult>>,成功為 unbanned 或 unchanged,失敗如 set_by_higher_role。
可能的錯誤:同 mute()。
ChatroomHandle.manage.kick()
把使用者移出聊天室(所有者、管理員),他之後可以再次進入。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
返回值:Future<List<ChatroomMemberResult>>,成功為 removed 或 not_in_room(他不在聊天室裡),失敗如 owner_protected、admin_protected。
可能的錯誤:同 mute()。
ChatroomHandle.manage.allowlist.list()
分頁查詢白名單(所有者、管理員)。引數都是命名引數。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
limit | int? | 否 | 每頁條數,預設 20,最多 100 |
cursor | String? | 否 | 上一頁返回的 nextCursor |
返回值:Future<DRPage<ChatroomAllowlistEntry>>。
可能的錯誤:permission_denied(role_required)、invalid_state。
ChatroomHandle.manage.allowlist.add()
把使用者加入白名單(所有者、管理員)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
返回值:Future<List<ChatroomMemberResult>>,成功為 added 或 unchanged,失敗如 limit_exceeded(allowlist_limit,白名單已有 500 人)。
可能的錯誤:同 mute(),另有 app_unavailable(應用只讀)。
ChatroomHandle.manage.allowlist.remove()
把使用者移出白名單(所有者、管理員)。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | List<String> | 是 | 使用者名稱,1 到 100 個 |
返回值:Future<List<ChatroomMemberResult>>,成功為 removed 或 unchanged。
可能的錯誤:同 mute()。
ChatroomHandle.manage.mutes()
分頁查詢未到期的禁言(所有者、管理員)。引數同 allowlist.list()。
返回值:Future<DRPage<ChatroomMuteEntry>>。
可能的錯誤:permission_denied(role_required)、invalid_state。
ChatroomHandle.manage.bans()
分頁查詢未到期的封禁(所有者、管理員)。引數同 allowlist.list()。
返回值:Future<DRPage<ChatroomBanEntry>>。
可能的錯誤:permission_denied(role_required)、invalid_state。
ChatroomHandle.manage.dismiss()
解散聊天室(所有者),不能恢復。全部成員被移出,ChatroomRemovedEvent 的原因為 dismissed。
返回值:Future<void>。
可能的錯誤:permission_denied(role_required)、chatroom_disabled(被平臺封禁的聊天室)、invalid_state。
資料結構
服務端物件(繼承 DRObject)的常用欄位以 getter 提供;時間為 UTC 的 DateTime。服務端返回的全部欄位都在 raw(Map<String, Object?>)中。
ChatroomSnapshot
控制代碼的快照,不可修改。
| 欄位 | 型別 | 說明 |
|---|---|---|
info | ChatroomInfo | 聊天室資訊,含 self |
attributes | Map<String, ChatroomAttribute> | 全部屬性,鍵到屬性 |
attributesVersion | int | 屬性的版本號,每次變化加一 |
messages | List<ChatroomMessageView> | 最近的訊息和之後收到、發出的訊息,按到達順序,最多 500 條 |
state | String | entering 正在進入 / in 在聊天室中 / reentering 斷線後正在重新進入 / removed 已被移出 / left 已離開 |
removed | ChatroomRemoved? | 只在 state 為 removed 時有,見下 |
ChatroomRemoved
| 欄位 | 型別 | 說明 |
|---|---|---|
reason | String | kicked、banned、dismissed、disabled 等,見被移出聊天室 |
operator | String? | 操作人,只有 kicked、banned 有 |
expiresAt | DateTime? | 封禁的到期時間,只有 banned 有;永久封禁為 null |
ChatroomInfo
| 欄位 | 型別 | 說明 |
|---|---|---|
roomId | String | 聊天室 ID |
name | String | 名稱 |
description | String | 簡介 |
avatarUrl | String | 封面地址,沒有時為空字串 |
announcement | String | 公告 |
announcementUpdatedAt | DateTime? | 公告的修改時間 |
announcementUpdatedBy | String? | 在客戶端修改公告的使用者;你的服務端修改時為 null |
owner | String? | 所有者的使用者名稱,沒有所有者時為 null |
admins | List<String> | 管理員的使用者名稱 |
maxMembers | int | 實際生效的人數上限 |
muteAll | bool | 是否開啟了全員禁言 |
listed | bool | 是否出現在聊天室列表中 |
status | String | active 正常 / disabled 已封禁 / dismissed 已解散 |
disabledBy | String? | 封禁方,未封禁時為 null |
memberCount | int | 線上人數,近似值 |
infoVersion | int | 資料的版本號,每次變化加一 |
attributesVersion | int | 屬性的版本號 |
createdAt | DateTime? | 建立時間 |
self | ChatroomSelf? | 你在這個聊天室中的狀態;列表、建立的結果中沒有 |
ChatroomSelf
| 欄位 | 型別 | 說明 |
|---|---|---|
role | String | owner / admin / member |
inRoom | bool | 是否在聊天室中 |
muted | bool | 是否在這個聊天室被禁言(不含全域性禁言) |
mutedUntil | DateTime? | 禁言的到期時間,永久禁言為 null |
allowlisted | bool | 是否在白名單中 |
ChatroomListItem
im.chatrooms.list() 的一項。
| 欄位 | 型別 | 說明 |
|---|---|---|
roomId | String | 聊天室 ID |
name | String | 名稱 |
description | String | 簡介 |
avatarUrl | String | 封面地址 |
owner | String? | 所有者 |
maxMembers | int | 人數上限 |
memberCount | int | 線上人數 |
ChatroomOnlineCount
| 欄位 | 型別 | 說明 |
|---|---|---|
roomId | String | 聊天室 ID |
memberCount | int | 線上人數 |
ChatroomMessageView
messages 中的一條訊息:服務端的聊天室訊息,加上本地的狀態 local。
| 欄位 | 型別 | 說明 |
|---|---|---|
roomId | String | 聊天室 ID |
messageId | String? | 訊息 ID;正在傳送、傳送失敗或被丟棄的為 null |
clientMsgId | String? | 傳送者生成的去重 ID |
sender | String? | 傳送者的使用者名稱,系統訊息為 null |
senderType | String | user 使用者 / system 系統 |
senderNickname | String? | 傳送時的暱稱 |
senderAvatarUrl | String? | 傳送時的頭像 |
senderRole | String? | 傳送時的身份:owner / admin / member |
type | String | 訊息型別:text、image、voice、video、file、location、custom |
body | Map<String, Object?>? | 訊息內容,見訊息格式 |
ext | Map<String, Object?>? | 擴充套件欄位 |
priority | String | high / normal / low |
via | String | 傳送途徑:client 客戶端 / openapi 你的服務端 / console 控制檯 / system 系統 |
createdAt | DateTime? | 傳送時間;正在傳送的為 null |
local | ChatroomMessageLocal | 本地的狀態,見下 |
收到的訊息(ChatroomMessageReceived 事件、最近的訊息)的 messageId 和 createdAt 總是有值。
ChatroomMessageLocal
| 欄位 | 型別 | 說明 |
|---|---|---|
status | String | sending 正在傳送 / sent 已傳送 / failed 傳送失敗 / dropped 低優先順序的訊息被丟棄 |
error | DRException? | 傳送失敗的原因,只在 failed 時有 |
trusted | bool | 為 true 表示由你的服務端、控制檯或系統發出 |
ChatroomMember
members() 的一項。
| 欄位 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱 |
nickname | String | 暱稱,沒有時為空字串 |
avatarUrl | String | 頭像地址,沒有時為空字串 |
role | String | owner / admin / member |
joinedAt | DateTime? | 這一次進入的時間 |
ChatroomAttribute
一個屬性。
| 欄位 | 型別 | 說明 |
|---|---|---|
value | String? | 值 |
owner | String? | 最近一次設定這個鍵的使用者;你的服務端設定的為 null |
autoDelete | bool | 是否在設定人離開聊天室時自動刪除 |
updatedAt | DateTime? | 最近一次設定的時間 |
AttributeResult
setAttributes()、removeAttributes() 的結果。
| 欄位 | 型別 | 說明 |
|---|---|---|
changed | bool | 是否有鍵被寫入或刪除 |
attributesVersion | int | 操作之後的屬性版本號 |
failed | Map<String, Map<String, Object?>> | 失敗的鍵到 code、reason:permission_denied(attribute_owned,鍵屬於別人)或 limit_exceeded(attribute_limit,個數或總大小超出)。沒有失敗時為空 |
ChatroomMemberResult
批次管理操作中一個使用者的結果:成功的有 result,失敗的有 code。
| 欄位 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱 |
ok | bool | 是否成功 |
result | String? | 成功時的結果:muted、unmuted、banned、unbanned、removed、not_in_room、added、unchanged |
code | String? | 失敗時的錯誤碼 |
message | String? | 失敗時的說明 |
details | Map<String, Object?>? | 失敗的詳細原因,如 reason 為 owner_protected |
ChatroomMuteEntry、ChatroomBanEntry、ChatroomAllowlistEntry
禁言名單、封禁名單和白名單的一項。
| 欄位 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱 |
nickname | String | 暱稱 |
avatarUrl | String | 頭像地址 |
mutedUntil | DateTime? | 只在禁言名單中:到期時間,永久為 null |
expiresAt | DateTime? | 只在封禁名單中:到期時間,永久為 null |
reason | String | 禁言、封禁的原因(白名單沒有) |
createdBy | String? | 操作人的使用者名稱 |
createdByRole | String | 禁言、封禁時操作人的身份:owner、admin 或 server(白名單沒有) |
createdAt | DateTime? | 加入名單的時間 |
ChatroomPatch
manage.update() 的引數,建構函式的引數都是可選的命名引數,省略的欄位不改。
| 欄位 | 型別 | 說明 |
|---|---|---|
name | String? | 名稱,不能清空(所有者、管理員) |
description | String? | 簡介,空字串表示清空(所有者、管理員) |
avatarUrl | String? | 封面地址,空字串表示清空(所有者、管理員) |
announcement | String? | 公告,空字串表示清空(所有者、管理員) |
maxMembers | int? | 人數上限(所有者) |
resetMaxMembers | bool | 為 true 時人數上限改為跟隨執行策略(所有者),預設 false |
listed | bool? | 是否出現在聊天室列表中(所有者) |
ChatroomPriority
列舉:high、normal、low,見優先順序。
