MessageScope
表示几个消息对象的 '域', 即消息对象的集合. 用于最小化将同一条消息发送给多个类型不同的目标的付出.
支持的消息对象类型
Contact, CommandSender, MessageScope (递归).
在下文, A 或 B 指代这三种类型的其中两种, 允许排列组合. 如 A.scopeWith(B) 可能表示 Contact.scopeWith(MessageScope).
获得 MessageScope
A.asMessageScope().C<A>.toMessageScope(). 其中C表示Iterable,Sequence,Flow,Array其中任一.
连接 MessageScope
A?.scopeWith(vararg B?).A?.scopeWith(vararg A?).
null 项将会被过滤.
自动去重
在连接时, MessageScope 会自动根据真实的 收信对象 去重.
如 member.asCommandSender().scopeWith(member.group), 返回的 MessageScope 实际上只包含 member.group. 因为 member.asCommandSender() 的最终收信对象就是 member.group.
因此在使用 scopeWith 时, 无需考虑重复性, 只需要把希望发送的目标全部列入.
使用 MessageScope
在 scopeWith 或 scopeWithNotNull 后加 lambda 参数即可表示使用 MessageScope. 如:
A.scopeWith(B) { // this: MessageScope
sendMessage(...)
}典例
在处理指令时, 目标群对象可能与发件人群对象不同, 如用户在 A 群发指令, 以禁言 B 群的成员. 此时机器人可能需要同时广播通知到 A 群和 B 群.
由于 CommandSender 与 Contact 无公共接口, 无法使用 listOfNotNull 遍历处理. MessageScope 就是设计为解决这样的问题.
Kotlin
// 在一个 SimpleCommand 内
@Handler
suspend fun CommandSender.handle(target: Member) {
val duration = Random.nextInt(1, 15)
target.mute(duration)
// 不使用 MessageScope
val thisGroup = this.getGroupOrNull()
val message = "${this.name} 禁言 ${target.nameCardOrNick} $duration 秒"
if (target.group != thisGroup) {
target.group.sendMessage(message)
}
sendMessage(message)
// 使用 MessageScope
// 表示至少发送给 `this`, 当 `this` 的真实发信对象与 `target.group` 不同时, 还额外发送给 `target.group`
this.scopeWith(target.group) {
sendMessage("${name} 禁言了 ${target.nameCardOrNick} $duration 秒")
}
// 同样地, 可以扩展用法, 同时私聊指令执行者:
// this.scopeWith(
// target,
// target.group
// ) { ... }
}Java
// 在一个 SimpleCommand 内
@Handler
public void handle(sender: CommandSender, target: Member) {
int duration = Random.nextInt(1, 15);
target.mute(duration);
// 不使用 MessageScope
Group thisGroup = this.getGroupOrNull();
String message = "${this.name} 禁言 ${target.nameCardOrNick} $duration 秒";
if (!target.group.equals(thisGroup)) {
target.group.sendMessage(message);
}
sender.sendMessage(message);
// 使用 MessageScope
// 表示至少发送给 `this`, 当 `this` 的真实发信对象与 `target.group` 不同时, 还额外发送给 `target.group`
MessageScope scope = MessageScopeKt.scopeWith(sender, target);
scope.sendMessage("${name} 禁言了 ${target.nameCardOrNick} $duration 秒");
// 或是只用一行:
MessageScopeKt.scopeWith(sender, target).sendMessage("${name} 禁言了 ${target.nameCardOrNick} $duration 秒");
}Functions
立刻以此发送消息给所有在此 MessageScope 下的消息对象