From 5e827d1c46e75bcbae3e33b6ebfab8b1979fc6b3 Mon Sep 17 00:00:00 2001 From: rhunk <101876869+rhunk@users.noreply.github.com> Date: Wed, 2 Aug 2023 09:17:17 +0200 Subject: [PATCH] event dispatcher --- .../me/rhunk/snapenhance/EventDispatcher.kt | 37 +++++++++++++++++++ .../kotlin/me/rhunk/snapenhance/ModContext.kt | 3 ++ .../me/rhunk/snapenhance/SnapEnhance.kt | 1 + .../snapenhance/{ => core}/event/EventBus.kt | 26 +++++++------ .../core/event/impl/OnSnapInteractionEvent.kt | 9 +++++ .../event/impl/SendMessageWithContentEvent.kt | 8 ++++ .../me/rhunk/snapenhance/event/Events.kt | 3 -- .../snapenhance/features/impl/Messaging.kt | 7 ++-- .../impl/privacy/PreventMessageSending.kt | 10 ++--- .../impl/spying/PreventReadReceipts.kt | 8 ++-- 10 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt rename core/src/main/kotlin/me/rhunk/snapenhance/{ => core}/event/EventBus.kt (63%) create mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/OnSnapInteractionEvent.kt create mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/SendMessageWithContentEvent.kt delete mode 100644 core/src/main/kotlin/me/rhunk/snapenhance/event/Events.kt diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt b/core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt new file mode 100644 index 00000000..862ff28c --- /dev/null +++ b/core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt @@ -0,0 +1,37 @@ +package me.rhunk.snapenhance + +import me.rhunk.snapenhance.core.event.impl.OnSnapInteractionEvent +import me.rhunk.snapenhance.core.event.impl.SendMessageWithContentEvent +import me.rhunk.snapenhance.data.wrapper.impl.MessageContent +import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID +import me.rhunk.snapenhance.hook.HookStage +import me.rhunk.snapenhance.hook.hook +import me.rhunk.snapenhance.manager.Manager + +class EventDispatcher( + private val context: ModContext +) : Manager { + override fun init() { + context.classCache.conversationManager.hook("sendMessageWithContent", HookStage.BEFORE) { param -> + val messageContent = MessageContent(param.arg(1)) + context.event.post(SendMessageWithContentEvent(messageContent))?.let { + if (it.canceled) { + param.setResult(null) + } + } + } + + context.classCache.snapManager.hook("onSnapInteraction", HookStage.BEFORE) { param -> + val conversationId = SnapUUID(param.arg(1)) + val messageId = param.arg(2) + context.event.post(OnSnapInteractionEvent( + conversationId = conversationId, + messageId = messageId + ))?.let { + if (it.canceled) { + param.setResult(null) + } + } + } + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt index 7fa0f779..a7253739 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.asCoroutineDispatcher import me.rhunk.snapenhance.bridge.BridgeClient import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper import me.rhunk.snapenhance.core.config.ModConfig +import me.rhunk.snapenhance.core.event.EventBus import me.rhunk.snapenhance.data.MessageSender import me.rhunk.snapenhance.database.DatabaseAccess import me.rhunk.snapenhance.features.Feature @@ -41,6 +42,8 @@ class ModContext { private val modConfig = ModConfig() val config by modConfig + val event = EventBus(this) + val eventDispatcher = EventDispatcher(this) val translation = TranslationWrapper() val features = FeatureManager(this) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt index 97036e65..a88578a2 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt @@ -99,6 +99,7 @@ class SnapEnhance { with(appContext) { reloadConfig() mappings.init() + eventDispatcher.init() //if mappings aren't loaded, we can't initialize features if (!mappings.areMappingsLoaded) return features.init() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/event/EventBus.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt similarity index 63% rename from core/src/main/kotlin/me/rhunk/snapenhance/event/EventBus.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt index dca07ff9..7c171b53 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/event/EventBus.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt @@ -1,10 +1,12 @@ -package me.rhunk.snapenhance.event +package me.rhunk.snapenhance.core.event +import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ModContext import kotlin.reflect.KClass abstract class Event { lateinit var context: ModContext + var canceled = false } interface IListener { @@ -23,12 +25,14 @@ class EventBus( subscribers[event]!!.add(listener) } - fun subscribe(event: KClass, listener: (T) -> Unit) { - subscribe(event, object : IListener { + inline fun subscribe(event: KClass, crossinline listener: (T) -> Unit): () -> Unit { + val obj = object : IListener { override fun handle(event: T) { listener(event) } - }) + } + subscribe(event, obj) + return { unsubscribe(event, obj) } } fun unsubscribe(event: KClass, listener: IListener) { @@ -38,22 +42,22 @@ class EventBus( subscribers[event]!!.remove(listener) } - fun post(event: T) { + fun post(event: T): T? { if (!subscribers.containsKey(event::class)) { - return + return null } event.context = context - subscribers[event::class]!!.forEach { listener -> + subscribers[event::class]?.forEach { listener -> @Suppress("UNCHECKED_CAST") - try { + runCatching { (listener as IListener).handle(event) - } catch (t: Throwable) { - println("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}") - t.printStackTrace() + }.onFailure { t -> + Logger.error("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}", t) } } + return event } fun clear() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/OnSnapInteractionEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/OnSnapInteractionEvent.kt new file mode 100644 index 00000000..91a3f333 --- /dev/null +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/OnSnapInteractionEvent.kt @@ -0,0 +1,9 @@ +package me.rhunk.snapenhance.core.event.impl + +import me.rhunk.snapenhance.core.event.Event +import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID + +class OnSnapInteractionEvent( + val conversationId: SnapUUID, + val messageId: Long +) : Event() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/SendMessageWithContentEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/SendMessageWithContentEvent.kt new file mode 100644 index 00000000..c2029283 --- /dev/null +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/impl/SendMessageWithContentEvent.kt @@ -0,0 +1,8 @@ +package me.rhunk.snapenhance.core.event.impl + +import me.rhunk.snapenhance.core.event.Event +import me.rhunk.snapenhance.data.wrapper.impl.MessageContent + +class SendMessageWithContentEvent( + val messageContent: MessageContent +) : Event() \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/event/Events.kt b/core/src/main/kotlin/me/rhunk/snapenhance/event/Events.kt deleted file mode 100644 index aae56c2d..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/event/Events.kt +++ /dev/null @@ -1,3 +0,0 @@ -package me.rhunk.snapenhance.event - -//TODO: addView event \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt index 99096ebe..ca98304c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt @@ -1,5 +1,6 @@ package me.rhunk.snapenhance.features.impl +import me.rhunk.snapenhance.core.event.impl.OnSnapInteractionEvent import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams @@ -72,9 +73,9 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C } //get last opened snap for media downloader - Hooker.hook(context.classCache.snapManager, "onSnapInteraction", HookStage.BEFORE) { param -> - openedConversationUUID = SnapUUID(param.arg(1)) - lastFocusedMessageId = param.arg(2) + context.event.subscribe(OnSnapInteractionEvent::class) { event -> + openedConversationUUID = event.conversationId + lastFocusedMessageId = event.messageId } Hooker.hook(context.classCache.conversationManager, "fetchMessage", HookStage.BEFORE) { param -> diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt index ada46e85..409ef0af 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt @@ -1,6 +1,7 @@ package me.rhunk.snapenhance.features.impl.privacy import me.rhunk.snapenhance.Logger +import me.rhunk.snapenhance.core.event.impl.SendMessageWithContentEvent import me.rhunk.snapenhance.data.NotificationType import me.rhunk.snapenhance.data.wrapper.impl.MessageContent import me.rhunk.snapenhance.features.Feature @@ -23,14 +24,13 @@ class PreventMessageSending : Feature("Prevent message sending", loadParams = Fe } } - context.classCache.conversationManager.hook("sendMessageWithContent", HookStage.BEFORE) { param -> - val message = MessageContent(param.arg(1)) - val contentType = message.contentType - val associatedType = NotificationType.fromContentType(contentType) ?: return@hook + context.event.subscribe(SendMessageWithContentEvent::class) { event -> + val contentType = event.messageContent.contentType + val associatedType = NotificationType.fromContentType(contentType) ?: return@subscribe if (preventMessageSending.contains(associatedType.key)) { Logger.debug("Preventing message sending for $associatedType") - param.setResult(null) + event.canceled = true } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt index aa530529..11731d42 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt @@ -1,5 +1,6 @@ package me.rhunk.snapenhance.features.impl.spying +import me.rhunk.snapenhance.core.event.impl.OnSnapInteractionEvent import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams @@ -19,9 +20,10 @@ class PreventReadReceipts : Feature("PreventReadReceipts", loadParams = FeatureL it.setResult(null) } } - Hooker.hook(context.classCache.snapManager, "onSnapInteraction", HookStage.BEFORE) { - if (isConversationInStealthMode(SnapUUID(it.arg(1) as Any))) { - it.setResult(null) + + context.event.subscribe(OnSnapInteractionEvent::class) { event -> + if (isConversationInStealthMode(event.conversationId)) { + event.canceled = true } } }