diff --git a/mirai-core-api/src/commonMain/kotlin/event/subscribeMessages.kt b/mirai-core-api/src/commonMain/kotlin/event/subscribeMessages.kt index 6a1514102..1671269ca 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/subscribeMessages.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/subscribeMessages.kt @@ -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 许可证的约束, 可以在以下链接找到该许可证. * 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 -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.channels.ReceiveChannel import net.mamoe.mirai.Bot import net.mamoe.mirai.event.Listener.ConcurrencyKind.CONCURRENT -import net.mamoe.mirai.event.events.FriendMessageEvent -import net.mamoe.mirai.event.events.GroupMessageEvent -import net.mamoe.mirai.event.events.MessageEvent -import net.mamoe.mirai.event.events.TempMessageEvent +import net.mamoe.mirai.event.events.* +import net.mamoe.mirai.message.data.content import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext -public typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder, Unit, Unit> +public typealias MessageEventSubscribersBuilder = MessageSubscribersBuilder, Unit, Unit> /** * 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话. @@ -38,24 +34,10 @@ public fun EventChannel<*>.subscribeMessages( coroutineContext: CoroutineContext = EmptyCoroutineContext, concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, priority: Listener.EventPriority = EventPriority.MONITOR, - listeners: MessagePacketSubscribersBuilder.() -> R + listeners: MessageEventSubscribersBuilder.() -> R ): R { - // contract 可帮助 IDE 进行类型推断. 无实际代码作用. - contract { - callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) - } - - return MessageSubscribersBuilder(Unit) - { filter, messageListener: MessageListener -> - // subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener] - // messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块. - subscribeAlways(coroutineContext, concurrencyKind, priority) { - // this.message.contentToString() 即为 messageListener 中 it 接收到的值 - val toString = this.message.contentToString() - if (filter.invoke(this, toString)) - messageListener.invoke(this, toString) - } - }.run(listeners) + contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } + return createBuilder(::MessageEventSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners) } public typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder, Unit, Unit> @@ -72,16 +54,8 @@ public fun EventChannel<*>.subscribeGroupMessages( priority: Listener.EventPriority = EventPriority.MONITOR, listeners: GroupMessageSubscribersBuilder.() -> R ): R { - contract { - callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) - } - return GroupMessageSubscribersBuilder(Unit) { filter, listener -> - subscribeAlways(coroutineContext, concurrencyKind, priority) { - val toString = this.message.contentToString() - if (filter(this, toString)) - listener(this, toString) - } - }.run(listeners) + contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } + return createBuilder(::GroupMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners) } public typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder, Unit, Unit> @@ -98,16 +72,8 @@ public fun EventChannel<*>.subscribeFriendMessages( priority: Listener.EventPriority = EventPriority.MONITOR, listeners: FriendMessageSubscribersBuilder.() -> R ): R { - contract { - callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) - } - return FriendMessageSubscribersBuilder(Unit) { filter, listener -> - subscribeAlways(coroutineContext, concurrencyKind, priority) { - val toString = this.message.contentToString() - if (filter(this, toString)) - listener(this, toString) - } - }.run(listeners) + contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } + return createBuilder(::FriendMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners) } public typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder, Unit, Unit> @@ -124,40 +90,44 @@ public fun EventChannel<*>.subscribeTempMessages( priority: Listener.EventPriority = EventPriority.MONITOR, listeners: TempMessageSubscribersBuilder.() -> R ): R { - contract { - callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) - } - return TempMessageSubscribersBuilder(Unit) { filter, listener -> - subscribeAlways(coroutineContext, concurrencyKind, priority) { - val toString = this.message.contentToString() - if (filter(this, toString)) - listener(this, toString) - } - }.run(listeners) + contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } + return createBuilder(::TempMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority).run(listeners) } +public typealias StrangerMessageSubscribersBuilder = MessageSubscribersBuilder, Unit, Unit> + /** - * 打开一个指定事件的接收通道 - * - * @param capacity 同 [Channel] 的参数, 参见 [Channel.Factory] 中的常量. - * - * @see capacity 默认无限大小. 详见 [Channel.Factory] 中的常量 [Channel.UNLIMITED], [Channel.CONFLATED], [Channel.RENDEZVOUS]. - * 请谨慎使用 [Channel.RENDEZVOUS]: 在 [Channel] 未被 [接收][Channel.receive] 时他将会阻塞事件处理 + * 订阅来自所有 [Bot] 的所有陌生人消息事件 * * @see subscribe 事件监听基础 - * - * @see subscribeFriendMessages - * @see subscribeMessages - * @see subscribeGroupMessages + * @see EventChannel 事件通道 */ -@Deprecated("Use asChannel", ReplaceWith("asChannel(capacity, coroutineContext, concurrencyKind, priority)")) -public fun EventChannel.incoming( +public fun EventChannel<*>.subscribeStrangerMessages( coroutineContext: CoroutineContext = EmptyCoroutineContext, concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, priority: Listener.EventPriority = EventPriority.MONITOR, - capacity: Int = Channel.UNLIMITED -): ReceiveChannel { - return asChannel(capacity, coroutineContext, concurrencyKind, priority) + listeners: StrangerMessageSubscribersBuilder.() -> R +): R { + contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } + return createBuilder(::StrangerMessageSubscribersBuilder, coroutineContext, concurrencyKind, priority) + .run(listeners) } +private typealias MessageSubscriberBuilderConstructor = ( + Unit, + (E.(String) -> Boolean, MessageListener) -> Listener +) -> MessageSubscribersBuilder, Unit, Unit> + +private inline fun EventChannel<*>.createBuilder( + constructor: MessageSubscriberBuilderConstructor, + coroutineContext: CoroutineContext, + concurrencyKind: Listener.ConcurrencyKind, + priority: Listener.EventPriority +): MessageSubscribersBuilder, Unit, Unit> = constructor(Unit) { filter, listener -> + subscribeAlways(coroutineContext, concurrencyKind, priority) { + val toString = this.message.content + if (filter(this, toString)) + listener(this, toString) + } +} \ No newline at end of file