Commit 96a58252 authored by Him188's avatar Him188

Add `nextEvent`, add docs

parent 37ce2660
...@@ -24,6 +24,8 @@ import kotlin.reflect.KClass ...@@ -24,6 +24,8 @@ import kotlin.reflect.KClass
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值 * @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
* *
* @see asyncFromEvent 本函数的异步版本 * @see asyncFromEvent 本函数的异步版本
* @see subscribe 普通地监听一个事件
* @see nextEvent 挂起当前协程, 并获取下一个事件实例
* *
* @throws TimeoutCancellationException 在超时后抛出. * @throws TimeoutCancellationException 在超时后抛出.
* @throws Throwable 当 [mapper] 抛出任何异常时, 本函数会抛出该异常 * @throws Throwable 当 [mapper] 抛出任何异常时, 本函数会抛出该异常
...@@ -55,6 +57,9 @@ suspend inline fun <reified E : Event, R : Any> syncFromEvent( ...@@ -55,6 +57,9 @@ suspend inline fun <reified E : Event, R : Any> syncFromEvent(
* @return 超时返回 `null`, 否则返回 [mapper] 返回的第一个非 `null` 值. * @return 超时返回 `null`, 否则返回 [mapper] 返回的第一个非 `null` 值.
* *
* @see asyncFromEvent 本函数的异步版本 * @see asyncFromEvent 本函数的异步版本
* @see subscribe 普通地监听一个事件
* @see nextEvent 挂起当前协程, 并获取下一个事件实例
*
* @throws Throwable 当 [mapper] 抛出任何异常时, 本函数会抛出该异常 * @throws Throwable 当 [mapper] 抛出任何异常时, 本函数会抛出该异常
*/ */
@JvmSynthetic @JvmSynthetic
...@@ -77,6 +82,11 @@ suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull( ...@@ -77,6 +82,11 @@ suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制 * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
* @param coroutineContext 额外的 [CoroutineContext] * @param coroutineContext 额外的 [CoroutineContext]
* @param mapper 过滤转换器. 返回非 `null` 则代表得到了需要的值. [syncFromEvent] 会返回这个值 * @param mapper 过滤转换器. 返回非 `null` 则代表得到了需要的值. [syncFromEvent] 会返回这个值
*
* @see syncFromEvent
* @see asyncFromEvent
* @see subscribe 普通地监听一个事件
* @see nextEvent 挂起当前协程, 并获取下一个事件实例
*/ */
@JvmSynthetic @JvmSynthetic
@Suppress("DeferredIsResult") @Suppress("DeferredIsResult")
...@@ -100,6 +110,11 @@ inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull( ...@@ -100,6 +110,11 @@ inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull(
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制 * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
* @param coroutineContext 额外的 [CoroutineContext] * @param coroutineContext 额外的 [CoroutineContext]
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值 * @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
*
* @see syncFromEvent
* @see asyncFromEventOrNull
* @see subscribe 普通地监听一个事件
* @see nextEvent 挂起当前协程, 并获取下一个事件实例
*/ */
@JvmSynthetic @JvmSynthetic
@Suppress("DeferredIsResult") @Suppress("DeferredIsResult")
...@@ -127,9 +142,12 @@ internal suspend inline fun <E : Event, R> syncFromEventImpl( ...@@ -127,9 +142,12 @@ internal suspend inline fun <E : Event, R> syncFromEventImpl(
crossinline mapper: suspend E.(E) -> R? crossinline mapper: suspend E.(E) -> R?
): R = suspendCancellableCoroutine { cont -> ): R = suspendCancellableCoroutine { cont ->
coroutineScope.subscribe(eventClass) { coroutineScope.subscribe(eventClass) {
cont.resumeWith(kotlin.runCatching { try {
mapper.invoke(this, it) ?: return@subscribe ListeningStatus.LISTENING cont.resumeWith(kotlin.runCatching {
}) mapper.invoke(this, it) ?: return@subscribe ListeningStatus.LISTENING
})
} catch (e: Exception) {
}
return@subscribe ListeningStatus.STOPPED return@subscribe ListeningStatus.STOPPED
} }
} }
\ No newline at end of file
/*
* Copyright 2020 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 net.mamoe.mirai.event
import kotlinx.coroutines.*
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.BotEvent
import kotlin.coroutines.resume
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass
/**
* 挂起当前协程, 直到监听到事件 [E] 的广播, 返回这个事件实例.
*
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制.
*
* @see subscribe 普通地监听一个事件
* @see syncFromEvent 挂起当前协程, 并尝试从事件中同步一个值
*
* @throws TimeoutCancellationException 在超时后抛出.
*/
@JvmSynthetic
suspend inline fun <reified E : Event> nextEvent(
timeoutMillis: Long = -1
): E {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
return withTimeoutOrCoroutineScope(timeoutMillis) {
nextEventImpl(E::class, this)
}
}
/**
* 挂起当前协程, 直到监听到事件 [E] 的广播, 返回这个事件实例.
* 将筛选 [BotEvent.bot] 与 [this] 相等的事件.
*
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制.
*
* @see subscribe 普通地监听一个事件
* @see syncFromEvent 挂起当前协程, 并尝试从事件中同步一个值
*
* @throws TimeoutCancellationException 在超时后抛出.
*/
@JvmSynthetic
suspend inline fun <reified E : BotEvent> Bot.nextEvent(
timeoutMillis: Long = -1
): E {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
return withTimeoutOrCoroutineScope(timeoutMillis) {
nextBotEventImpl(this@nextEvent, E::class, this)
}
}
@JvmSynthetic
@PublishedApi
internal suspend inline fun <E : Event> nextEventImpl(
eventClass: KClass<E>,
coroutineScope: CoroutineScope
): E = suspendCancellableCoroutine { cont ->
coroutineScope.subscribe(eventClass) {
try {
cont.resume(this)
} catch (e: Exception) {
}
return@subscribe ListeningStatus.STOPPED
}
}
@JvmSynthetic
@PublishedApi
internal suspend inline fun <E : BotEvent> nextBotEventImpl(
bot: Bot,
eventClass: KClass<E>,
coroutineScope: CoroutineScope
): E = suspendCancellableCoroutine { cont ->
coroutineScope.subscribe(eventClass) {
try {
if (this.bot == bot) cont.resume(this)
} catch (e: Exception) {
}
return@subscribe ListeningStatus.STOPPED
}
}
@JvmSynthetic
@PublishedApi
internal suspend inline fun <R> withTimeoutOrCoroutineScope(
timeoutMillis: Long,
noinline block: suspend CoroutineScope.() -> R
): R {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0 " }
return if (timeoutMillis == -1L) {
coroutineScope(block)
} else {
withTimeout(timeoutMillis, block)
}
}
\ No newline at end of file
...@@ -446,7 +446,7 @@ class MessageSelectionTimeoutException : RuntimeException() ...@@ -446,7 +446,7 @@ class MessageSelectionTimeoutException : RuntimeException()
@JvmSynthetic @JvmSynthetic
@PublishedApi @PublishedApi
internal suspend inline fun <R> withTimeoutOrCoroutineScope( internal suspend inline fun <R> withSilentTimeoutOrCoroutineScope(
timeoutMillis: Long, timeoutMillis: Long,
noinline block: suspend CoroutineScope.() -> R noinline block: suspend CoroutineScope.() -> R
): R { ): R {
...@@ -480,7 +480,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl( ...@@ -480,7 +480,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
filterContext: Boolean = true, filterContext: Boolean = true,
@BuilderInference @BuilderInference
crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, R>.() -> Unit crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, R>.() -> Unit
): R = withTimeoutOrCoroutineScope(timeoutMillis) { ): R = withSilentTimeoutOrCoroutineScope(timeoutMillis) {
var deferred: CompletableDeferred<R>? = CompletableDeferred() var deferred: CompletableDeferred<R>? = CompletableDeferred()
coroutineContext[Job]!!.invokeOnCompletion { coroutineContext[Job]!!.invokeOnCompletion {
deferred?.cancel() deferred?.cancel()
...@@ -500,7 +500,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl( ...@@ -500,7 +500,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
SELECT_MESSAGE_STUB, SELECT_MESSAGE_STUB,
outside outside
) { ) {
override fun obtainCurrentCoroutineScope(): CoroutineScope = this@withTimeoutOrCoroutineScope override fun obtainCurrentCoroutineScope(): CoroutineScope = this@withSilentTimeoutOrCoroutineScope
override fun obtainCurrentDeferred(): CompletableDeferred<R>? = deferred override fun obtainCurrentDeferred(): CompletableDeferred<R>? = deferred
override fun default(onEvent: MessageListener<T, R>) { override fun default(onEvent: MessageListener<T, R>) {
defaultListeners += onEvent defaultListeners += onEvent
...@@ -516,7 +516,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl( ...@@ -516,7 +516,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
SELECT_MESSAGE_STUB, SELECT_MESSAGE_STUB,
outside outside
) { ) {
override fun obtainCurrentCoroutineScope(): CoroutineScope = this@withTimeoutOrCoroutineScope override fun obtainCurrentCoroutineScope(): CoroutineScope = this@withSilentTimeoutOrCoroutineScope
override fun obtainCurrentDeferred(): CompletableDeferred<R>? = deferred override fun obtainCurrentDeferred(): CompletableDeferred<R>? = deferred
override fun default(onEvent: MessageListener<T, R>) { override fun default(onEvent: MessageListener<T, R>) {
defaultListeners += onEvent defaultListeners += onEvent
...@@ -577,7 +577,7 @@ internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl ...@@ -577,7 +577,7 @@ internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
filterContext: Boolean = true, filterContext: Boolean = true,
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
) = withTimeoutOrCoroutineScope(timeoutMillis) { ) = withSilentTimeoutOrCoroutineScope(timeoutMillis) {
var deferred: CompletableDeferred<Boolean>? = CompletableDeferred() var deferred: CompletableDeferred<Boolean>? = CompletableDeferred()
coroutineContext[Job]!!.invokeOnCompletion { coroutineContext[Job]!!.invokeOnCompletion {
deferred?.cancel() deferred?.cancel()
...@@ -596,7 +596,7 @@ internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl ...@@ -596,7 +596,7 @@ internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl
SELECT_MESSAGE_STUB, SELECT_MESSAGE_STUB,
outside outside
) { ) {
override fun obtainCurrentCoroutineScope(): CoroutineScope = this@withTimeoutOrCoroutineScope override fun obtainCurrentCoroutineScope(): CoroutineScope = this@withSilentTimeoutOrCoroutineScope
override fun obtainCurrentDeferred(): CompletableDeferred<Boolean>? = deferred override fun obtainCurrentDeferred(): CompletableDeferred<Boolean>? = deferred
override fun default(onEvent: MessageListener<T, Boolean>) { override fun default(onEvent: MessageListener<T, Boolean>) {
defaultListeners += onEvent defaultListeners += onEvent
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment