[Review] subscribeMessages: simplify implementations

This commit is contained in:
Him188 2021-01-08 10:04:44 +08:00
parent f31fbafd02
commit abcac7ff23

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020 Mamoe Technologies and contributors. * Copyright 2019-2021 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -13,20 +13,16 @@
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Listener.ConcurrencyKind.CONCURRENT import net.mamoe.mirai.event.Listener.ConcurrencyKind.CONCURRENT
import net.mamoe.mirai.event.events.FriendMessageEvent import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.events.GroupMessageEvent import net.mamoe.mirai.message.data.content
import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.event.events.TempMessageEvent
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
public typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<MessageEvent, Listener<MessageEvent>, Unit, Unit> public typealias MessageEventSubscribersBuilder = MessageSubscribersBuilder<MessageEvent, Listener<MessageEvent>, Unit, Unit>
/** /**
* 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话. * 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
@ -38,24 +34,10 @@ public fun <R> EventChannel<*>.subscribeMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: MessagePacketSubscribersBuilder.() -> R listeners: MessageEventSubscribersBuilder.() -> R
): R { ): R {
// contract 可帮助 IDE 进行类型推断. 无实际代码作用. contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
contract { return createBuilder(::MessageEventSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners)
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
}
return MessageSubscribersBuilder(Unit)
{ filter, messageListener: MessageListener<MessageEvent, Unit> ->
// subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener]
// messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块.
subscribeAlways<MessageEvent>(coroutineContext, concurrencyKind, priority) {
// this.message.contentToString() 即为 messageListener 中 it 接收到的值
val toString = this.message.contentToString()
if (filter.invoke(this, toString))
messageListener.invoke(this, toString)
}
}.run(listeners)
} }
public typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<GroupMessageEvent, Listener<GroupMessageEvent>, Unit, Unit> public typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<GroupMessageEvent, Listener<GroupMessageEvent>, Unit, Unit>
@ -72,16 +54,8 @@ public fun <R> EventChannel<*>.subscribeGroupMessages(
priority: Listener.EventPriority = EventPriority.MONITOR, priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: GroupMessageSubscribersBuilder.() -> R listeners: GroupMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) return createBuilder(::GroupMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners)
}
return GroupMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.contentToString()
if (filter(this, toString))
listener(this, toString)
}
}.run(listeners)
} }
public typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<FriendMessageEvent, Listener<FriendMessageEvent>, Unit, Unit> public typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<FriendMessageEvent, Listener<FriendMessageEvent>, Unit, Unit>
@ -98,16 +72,8 @@ public fun <R> EventChannel<*>.subscribeFriendMessages(
priority: Listener.EventPriority = EventPriority.MONITOR, priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: FriendMessageSubscribersBuilder.() -> R listeners: FriendMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) return createBuilder(::FriendMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners)
}
return FriendMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.contentToString()
if (filter(this, toString))
listener(this, toString)
}
}.run(listeners)
} }
public typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempMessageEvent, Listener<TempMessageEvent>, Unit, Unit> public typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempMessageEvent, Listener<TempMessageEvent>, Unit, Unit>
@ -124,40 +90,44 @@ public fun <R> EventChannel<*>.subscribeTempMessages(
priority: Listener.EventPriority = EventPriority.MONITOR, priority: Listener.EventPriority = EventPriority.MONITOR,
listeners: TempMessageSubscribersBuilder.() -> R listeners: TempMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) return createBuilder(::TempMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners)
}
return TempMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.contentToString()
if (filter(this, toString))
listener(this, toString)
}
}.run(listeners)
} }
public typealias StrangerMessageSubscribersBuilder = MessageSubscribersBuilder<StrangerMessageEvent, Listener<StrangerMessageEvent>, Unit, Unit>
/** /**
* 打开一个指定事件的接收通道 * 订阅来自所有 [Bot] 的所有陌生人消息事件
*
* @param capacity [Channel] 的参数, 参见 [Channel.Factory] 中的常量.
*
* @see capacity 默认无限大小. 详见 [Channel.Factory] 中的常量 [Channel.UNLIMITED], [Channel.CONFLATED], [Channel.RENDEZVOUS].
* 请谨慎使用 [Channel.RENDEZVOUS]: [Channel] 未被 [接收][Channel.receive] 时他将会阻塞事件处理
* *
* @see subscribe 事件监听基础 * @see subscribe 事件监听基础
* * @see EventChannel 事件通道
* @see subscribeFriendMessages
* @see subscribeMessages
* @see subscribeGroupMessages
*/ */
@Deprecated("Use asChannel", ReplaceWith("asChannel(capacity, coroutineContext, concurrencyKind, priority)")) public fun <R> EventChannel<*>.subscribeStrangerMessages(
public fun <E : Event> EventChannel<E>.incoming(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: Listener.EventPriority = EventPriority.MONITOR,
capacity: Int = Channel.UNLIMITED listeners: StrangerMessageSubscribersBuilder.() -> R
): ReceiveChannel<E> { ): R {
return asChannel(capacity, coroutineContext, concurrencyKind, priority) contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
return createBuilder(::StrangerMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority)
.run(listeners)
} }
private typealias MessageSubscriberBuilderConstructor<E> = (
Unit,
(E.(String) -> Boolean, MessageListener<E, Unit>) -> Listener<E>
) -> MessageSubscribersBuilder<E, Listener<E>, Unit, Unit>
private inline fun <reified E : MessageEvent> EventChannel<*>.createBuilder(
constructor: MessageSubscriberBuilderConstructor<E>,
coroutineContext: CoroutineContext,
concurrencyKind: Listener.ConcurrencyKind,
priority: Listener.EventPriority
): MessageSubscribersBuilder<E, Listener<E>, Unit, Unit> = constructor(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.content
if (filter(this, toString))
listener(this, toString)
}
}