mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-19 15:34:42 +08:00
Catch and forward event broadcasting to EventDispatcher
This commit is contained in:
parent
9cf45bd9ca
commit
9619338d5b
@ -19,6 +19,9 @@ import io.ktor.client.engine.okhttp.*
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.UserProfile
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.broadcastImpl
|
||||
import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent
|
||||
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
|
||||
import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
@ -299,6 +302,13 @@ public interface IMirai : LowLevelApiAccessor {
|
||||
* @param event 邀请入群的事件对象
|
||||
*/
|
||||
public suspend fun ignoreInvitedJoinGroupRequest(event: BotInvitedJoinGroupRequestEvent)
|
||||
|
||||
/**
|
||||
* 广播一个事件. 由 [Event.broadcast] 调用.
|
||||
*/
|
||||
public suspend fun broadcastEvent(event: Event) {
|
||||
event.broadcastImpl()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,7 @@ package net.mamoe.mirai.event
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.event.events.MessageEvent
|
||||
import net.mamoe.mirai.internal.event.callAndRemoveIfRequired
|
||||
@ -144,7 +145,11 @@ public interface CancellableEvent : Event {
|
||||
* @see __broadcastJava Java 使用
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public suspend fun <E : Event> E.broadcast(): E {
|
||||
public suspend fun <E : Event> E.broadcast(): E = apply { Mirai.broadcastEvent(this) }
|
||||
|
||||
|
||||
@JvmName("broadcastImpl") // avoid mangling
|
||||
internal suspend fun <E : Event> E.broadcastImpl(): E {
|
||||
val event = this
|
||||
check(event is AbstractEvent) {
|
||||
"Events must extend AbstractEvent"
|
||||
|
@ -15,22 +15,23 @@ import io.ktor.client.features.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readBytes
|
||||
import kotlinx.serialization.json.*
|
||||
import net.mamoe.mirai.*
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.*
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent
|
||||
import net.mamoe.mirai.event.events.FriendAddEvent
|
||||
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
|
||||
import net.mamoe.mirai.event.events.NewFriendRequestEvent
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.message.*
|
||||
import net.mamoe.mirai.internal.message.DeepMessageRefiner.refineDeep
|
||||
import net.mamoe.mirai.internal.network.components.EventDispatcher
|
||||
import net.mamoe.mirai.internal.network.components.EventDispatcherScopeFlag
|
||||
import net.mamoe.mirai.internal.network.highway.*
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
||||
@ -284,6 +285,20 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
|
||||
override suspend fun ignoreInvitedJoinGroupRequest(event: BotInvitedJoinGroupRequestEvent) =
|
||||
solveInvitedJoinGroupRequest(event, accept = false)
|
||||
|
||||
override suspend fun broadcastEvent(event: Event) {
|
||||
if (currentCoroutineContext()[EventDispatcherScopeFlag] != null) {
|
||||
// called by [EventDispatcher]
|
||||
return super.broadcastEvent(event)
|
||||
}
|
||||
if (event is BotEvent) {
|
||||
val bot = event.bot
|
||||
if (bot is QQAndroidBot) {
|
||||
bot.components[EventDispatcher].broadcast(event)
|
||||
}
|
||||
} else {
|
||||
super.broadcastEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun solveInvitedJoinGroupRequest(event: BotInvitedJoinGroupRequestEvent, accept: Boolean) {
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
@ -19,8 +19,18 @@ import net.mamoe.mirai.utils.childScope
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* All events will be caught and forwarded to [EventDispatcher]. Invocation of [Event.broadcast] and [EventDispatcher.broadcast] are effectively equal.
|
||||
*/
|
||||
internal interface EventDispatcher {
|
||||
/**
|
||||
* Implementor must call `event.broadcast()` within a coroutine with [EventDispatcherScopeFlag]
|
||||
*/
|
||||
suspend fun broadcast(event: Event)
|
||||
|
||||
/**
|
||||
* Implementor must call `event.broadcast()` within a coroutine with [EventDispatcherScopeFlag]
|
||||
*/
|
||||
fun broadcastAsync(event: Event, additionalContext: CoroutineContext = EmptyCoroutineContext): EventBroadcastJob
|
||||
|
||||
/**
|
||||
@ -31,6 +41,10 @@ internal interface EventDispatcher {
|
||||
companion object : ComponentKey<EventDispatcher>
|
||||
}
|
||||
|
||||
internal object EventDispatcherScopeFlag : CoroutineContext.Element, CoroutineContext.Key<EventDispatcherScopeFlag> {
|
||||
override val key: CoroutineContext.Key<*> get() = this
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
internal value class EventBroadcastJob(
|
||||
private val job: Job
|
||||
@ -53,7 +67,9 @@ internal class EventDispatcherImpl(
|
||||
|
||||
override suspend fun broadcast(event: Event) {
|
||||
try {
|
||||
event.broadcast()
|
||||
withContext(EventDispatcherScopeFlag) {
|
||||
event.broadcast()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (logger.isEnabled) {
|
||||
val msg = optimizeEventToString(event)
|
||||
@ -63,7 +79,10 @@ internal class EventDispatcherImpl(
|
||||
}
|
||||
|
||||
override fun broadcastAsync(event: Event, additionalContext: CoroutineContext): EventBroadcastJob {
|
||||
val job = launch(additionalContext, start = CoroutineStart.UNDISPATCHED) { broadcast(event) }
|
||||
val job = launch(
|
||||
additionalContext + EventDispatcherScopeFlag,
|
||||
start = CoroutineStart.UNDISPATCHED
|
||||
) { broadcast(event) }
|
||||
// UNDISPATCHED: starts the coroutine NOW in the current thread until its first suspension point,
|
||||
// so that after `broadcastAsync` the job is always already started and `joinBroadcast` will work normally.
|
||||
return EventBroadcastJob(job)
|
||||
|
Loading…
Reference in New Issue
Block a user