diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index 1869dc838..259978db9 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -1516,6 +1516,7 @@ public class net/mamoe/mirai/event/EventChannel { public final fun context ([Lkotlin/coroutines/CoroutineContext;)Lnet/mamoe/mirai/event/EventChannel; public final fun exceptionHandler (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/event/EventChannel; public final fun exceptionHandler (Lkotlinx/coroutines/CoroutineExceptionHandler;)Lnet/mamoe/mirai/event/EventChannel; + public final fun filter (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/event/EventChannel; public final synthetic fun filter (Lkotlin/jvm/functions/Function2;)Lnet/mamoe/mirai/event/EventChannel; public final fun filterIsInstance (Ljava/lang/Class;)Lnet/mamoe/mirai/event/EventChannel; public final fun filterIsInstance (Lkotlin/reflect/KClass;)Lnet/mamoe/mirai/event/EventChannel; diff --git a/mirai-core-api/src/commonMain/kotlin/event/EventChannel.kt b/mirai-core-api/src/commonMain/kotlin/event/EventChannel.kt index 5eb36a2cf..9362d376f 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/EventChannel.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/EventChannel.kt @@ -148,6 +148,48 @@ public open class EventChannel @JvmOverloads internal con } } + /** + * [EventChannel.filter] 的 Java 版本. + * + * 添加一个过滤器. 过滤器将在收到任何事件之后, 传递给通过 [EventChannel.subscribe] 注册的监听器之前调用. + * + * 若 [filter] 返回 `true`, 该事件将会被传给监听器. 否则将会被忽略, **监听器继续监听**. + * + * ## 线性顺序 + * 多个 [filter] 的处理是线性且有顺序的. 若一个 [filter] 已经返回了 `false` (代表忽略这个事件), 则会立即忽略, 而不会传递给后续过滤器. + * + * 示例: + * ``` + * GlobalEventChannel // GlobalEventChannel 会收到全局所有事件, 事件类型是 Event + * .filterIsInstance(BotEvent.class) // 过滤, 只接受 BotEvent + * .filter(event -> + * // 此时的 event 一定是 BotEvent + * event.bot.id == 123456 // 再过滤 event 的 bot.id + * ) + * .subscribeAlways(event -> { + * // 现在 event 是 BotEvent, 且 bot.id == 123456 + * }) + * ``` + * + * ## 过滤器阻塞 + * [filter] 允许阻塞线程. **过滤器的阻塞将被认为是事件监听器的阻塞**. + * + * 过滤器阻塞是否会影响事件处理, + * 取决于 [subscribe] 时的 [ConcurrencyKind] 和 [EventPriority]. + * + * ## 过滤器异常处理 + * 若 [filter] 抛出异常, 将被包装为 [ExceptionInEventChannelFilterException] 并重新抛出. + * + * @see filterIsInstance 过滤指定类型的事件 + * + * @since 2.2 + */ + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + @kotlin.internal.LowPriorityInOverloadResolution + public fun filter(filter: (event: BaseEvent) -> Boolean): EventChannel { + return filter { runInterruptible { filter(it) } } + } + /** * 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel] * @see filter 获取更多信息 diff --git a/mirai-core-api/src/jvmTest/kotlin/event/EventChannelJavaTest.java b/mirai-core-api/src/jvmTest/kotlin/event/EventChannelJavaTest.java new file mode 100644 index 000000000..cc0609b8a --- /dev/null +++ b/mirai-core-api/src/jvmTest/kotlin/event/EventChannelJavaTest.java @@ -0,0 +1,32 @@ +/* + * 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. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package event; + +import net.mamoe.mirai.event.Event; +import net.mamoe.mirai.event.GlobalEventChannel; +import net.mamoe.mirai.event.events.GroupMessageEvent; +import net.mamoe.mirai.event.events.MessageEvent; + +/** + * 仅测试可以使用, 不会被编译运行 + */ +public class EventChannelJavaTest { + + public static void main(String[] args) { + GlobalEventChannel.INSTANCE + .filter(event -> { + return event.toString() == "test"; + }) + .filterIsInstance(MessageEvent.class) + .subscribeAlways(GroupMessageEvent.class, groupMessageEvent -> { + + }); + } +} diff --git a/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt b/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt index 75c1c8fff..310e1a1c1 100644 --- a/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.kt +++ b/mirai-core-api/src/jvmTest/kotlin/event/EventChannelTest.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. @@ -16,15 +16,25 @@ import net.mamoe.mirai.event.events.MessageEvent import org.junit.jupiter.api.Test internal class EventChannelTest { + suspend fun suspendCall() { + + } + @Suppress("UNUSED_VARIABLE") @Test fun testVariance() { var global: EventChannel = GlobalEventChannel var a: EventChannel = global.filterIsInstance() + + val filterLambda: (ev: MessageEvent) -> Boolean = { true } + + // Kotlin can't resolve to the non-suspend one a.filter { // it: Event + suspendCall() // would be allowed in Kotlin it.isIntercepted } + val messageEventChannel = a.filterIsInstance() // group.asChannel()