commit 7aa05e996a3e0119c6c8cbfe41718551a5bde1ba
parent 2a8fcacd2fec0aeb6246b197d6ef758745bb66c3
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Wed, 27 Dec 2023 23:19:59 +0100

feat(scripting): messaging module

Diffstat:
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/data/SnapEnums.kt | 19+++++++++++++++++--
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/scripting/CoreScriptRuntime.kt | 2++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreMessaging.kt | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ConversationManager.kt | 4++--
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDestinations.kt | 1-
7 files changed, 171 insertions(+), 7 deletions(-)

diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/SnapEnums.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/data/SnapEnums.kt @@ -108,8 +108,23 @@ enum class MediaReferenceType { } -enum class MessageUpdate { - UNKNOWN, READ, RELEASE, SAVE, UNSAVE, ERASE, SCREENSHOT, SCREEN_RECORD, REPLAY, REACTION, REMOVEREACTION, REVOKETRANSCRIPTION, ALLOWTRANSCRIPTION, ERASESAVEDSTORYMEDIA +enum class MessageUpdate( + val key: String, +) { + UNKNOWN("unknown"), + READ("read"), + RELEASE("release"), + SAVE("save"), + UNSAVE("unsave"), + ERASE("erase"), + SCREENSHOT("screenshot"), + SCREEN_RECORD("screen_record"), + REPLAY("replay"), + REACTION("reaction"), + REMOVEREACTION("remove_reaction"), + REVOKETRANSCRIPTION("revoke_transcription"), + ALLOWTRANSCRIPTION("allow_transcription"), + ERASESAVEDSTORYMEDIA("erase_saved_story_media"), } enum class FriendLinkType(val value: Int, val shortName: String) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt @@ -421,7 +421,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN context.coroutineScope.launch(coroutineDispatcher) { suspendCoroutine { continuation -> - conversationManager.fetchMessageByServerId(conversationId, serverMessageId, onSuccess = { + conversationManager.fetchMessageByServerId(conversationId, serverMessageId.toLong(), onSuccess = { if (it.senderId.toString() == context.database.myUserId) { param.invokeOriginal() continuation.resumeWith(Result.success(Unit)) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/CoreMessagingBridge.kt @@ -65,7 +65,7 @@ class CoreMessagingBridge( suspendCancellableCoroutine { continuation -> conversationManager?.fetchMessageByServerId( conversationId, - serverMessageId, + serverMessageId.toLong(), onSuccess = { continuation.resumeWith(Result.success(it.toBridge())) }, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/CoreScriptRuntime.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/CoreScriptRuntime.kt @@ -7,6 +7,7 @@ import me.rhunk.snapenhance.common.scripting.ScriptRuntime import me.rhunk.snapenhance.common.scripting.bindings.BindingSide import me.rhunk.snapenhance.core.ModContext import me.rhunk.snapenhance.core.scripting.impl.CoreIPC +import me.rhunk.snapenhance.core.scripting.impl.CoreMessaging import me.rhunk.snapenhance.core.scripting.impl.CoreScriptConfig import me.rhunk.snapenhance.core.scripting.impl.CoreScriptHooker @@ -23,6 +24,7 @@ class CoreScriptRuntime( CoreScriptConfig(), CoreIPC(), CoreScriptHooker(), + CoreMessaging(modContext) ) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreMessaging.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/scripting/impl/CoreMessaging.kt @@ -0,0 +1,148 @@ +package me.rhunk.snapenhance.core.scripting.impl + +import me.rhunk.snapenhance.common.data.MessageUpdate +import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding +import me.rhunk.snapenhance.common.scripting.bindings.BindingSide +import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject +import me.rhunk.snapenhance.core.ModContext +import me.rhunk.snapenhance.core.features.impl.messaging.Messaging +import me.rhunk.snapenhance.core.wrapper.impl.Message +import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import org.mozilla.javascript.Scriptable +import org.mozilla.javascript.annotations.JSFunction + +@Suppress("unused") +class CoreMessaging( + private val modContext: ModContext +) : AbstractBinding("messaging", BindingSide.CORE) { + private val conversationManager get() = modContext.feature(Messaging::class).conversationManager + + @JSFunction + fun isPresent() = conversationManager != null + + @JSFunction + fun newSnapUUID(uuid: String) = SnapUUID.fromString(uuid) + + @JSFunction + fun updateMessage( + conversationId: String, + messageId: Number, + action: String, + callback: (error: String?) -> Unit + ) { + conversationManager?.updateMessage(conversationId, messageId.toLong(), MessageUpdate.entries.find { it.key == action } + ?: throw RuntimeException("Could not find message update $action"), + callback) + } + + @JSFunction + fun fetchConversationWithMessagesPaginated( + conversationId: String, + lastMessageId: Long, + amount: Int, + callback: (error: String?, message: List<Message>) -> Unit, + ) { + conversationManager?.fetchConversationWithMessagesPaginated(conversationId, lastMessageId, amount, onSuccess = { + callback(null, it) + }, onError = { + callback(it, emptyList()) + }) + } + + @JSFunction + fun fetchConversationWithMessages( + conversationId: String, + callback: (error: String?, List<Message>) -> Unit + ) { + conversationManager?.fetchConversationWithMessages(conversationId, onSuccess = { + callback(null, it) + }, onError = { + callback(it, emptyList()) + }) + } + + @JSFunction + fun fetchMessageByServerId( + conversationId: String, + serverId: Long, + callback: (error: String?, message: Message?) -> Unit, + ) { + conversationManager?.fetchMessageByServerId(conversationId, serverId, onSuccess = { + callback(null, it) + }, onError = { + callback(it, null) + }) + } + + @JSFunction + fun fetchMessagesByServerIds( + conversationId: String, + serverIds: List<Number>, + callback: (error: String?, List<Message>) -> Unit + ) { + conversationManager?.fetchMessagesByServerIds(conversationId, serverIds.map { + it.toLong() + }, onSuccess = { + callback(null, it) + }, onError = { + callback(it, emptyList()) + }) + } + + @JSFunction + fun displayedMessages( + conversationId: String, + lastMessageId: Number, + callback: (error: String?) -> Unit + ) { + conversationManager?.displayedMessages(conversationId, lastMessageId.toLong(), callback) + } + + @JSFunction + fun fetchMessage( + conversationId: String, + messageId: Number, + callback: (error: String?, message: Message?) -> Unit + ) { + conversationManager?.fetchMessage(conversationId, messageId.toLong(), onSuccess = { + callback(null, it) + }, onError = { callback(it, null) }) + } + + @JSFunction + fun clearConversation( + conversationId: String, + callback: (error: String?) -> Unit + ) { + conversationManager?.clearConversation(conversationId, onSuccess = { + callback(null) + }, onError = { + callback(it) + }) + } + + @JSFunction + fun getOneOnOneConversationIds(userIds: List<String>, callback: (error: String?, List<Scriptable>) -> Unit) { + conversationManager?.getOneOnOneConversationIds(userIds, onSuccess = { + callback(null, it.map { (userId, conversationId) -> + scriptableObject { + putConst("conversationId", this, conversationId) + putConst("userId", this, userId) + } + }) + }, onError = { + callback(it, emptyList()) + }) + } + + @JSFunction + fun sendChatMessage( + conversationId: String, + message: String, + result: (error: String?) -> Unit + ) { + modContext.messageSender.sendChatMessage(listOf(SnapUUID.fromString(conversationId)), message, onSuccess = { result(null) }, onError = { result(it.toString()) }) + } + + override fun getObject() = this +} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ConversationManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/ConversationManager.kt @@ -91,10 +91,10 @@ class ConversationManager( ) } - fun fetchMessageByServerId(conversationId: String, serverMessageId: String, onSuccess: (Message) -> Unit, onError: (error: String) -> Unit) { + fun fetchMessageByServerId(conversationId: String, serverMessageId: Long, onSuccess: (Message) -> Unit, onError: (error: String) -> Unit) { val serverMessageIdentifier = CallbackBuilder.createEmptyObject(context.classCache.serverMessageIdentifier.constructors.first())?.apply { setObjectField("mServerConversationId", conversationId.toSnapUUID().instanceNonNull()) - setObjectField("mServerMessageId", serverMessageId.toLong()) + setObjectField("mServerMessageId", serverMessageId) } fetchMessageByServerId.invoke( diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDestinations.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDestinations.kt @@ -2,7 +2,6 @@ package me.rhunk.snapenhance.core.wrapper.impl import me.rhunk.snapenhance.core.wrapper.AbstractWrapper -@Suppress("UNCHECKED_CAST") class MessageDestinations(obj: Any) : AbstractWrapper(obj){ var conversations by field("mConversations", uuidArrayListMapper) var stories by field<ArrayList<*>>("mStories")