commit 07daeaf994258139c83e145b5ff290e5aac1493f parent 3fc06550bf02d96f845abe0b541e775d8c2378e4 Author: rhunk <101876869+rhunk@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:26:08 +0100 refactor: wrappers Diffstat:
25 files changed, 149 insertions(+), 148 deletions(-)
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt @@ -176,7 +176,7 @@ class ExportChatMessages : AbstractAction() { } fetchedMessages.firstOrNull()?.let { - lastMessageId = it.messageDescriptor.messageId + lastMessageId = it.messageDescriptor!!.messageId!! } setStatus("Exporting (${foundMessages.size} / ${foundMessages.firstOrNull()?.orderKey})") } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ScopeSync.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ScopeSync.kt @@ -29,7 +29,7 @@ class ScopeSync : Feature("Scope Sync", loadParams = FeatureLoadParams.INIT_SYNC if (event.messageContent.contentType != ContentType.SNAP) return@subscribe event.addCallbackResult("onSuccess") { - event.destinations.conversations.map { it.toString() }.forEach { conversationId -> + event.destinations.conversations!!.map { it.toString() }.forEach { conversationId -> updateJobs[conversationId]?.also { it.cancel() } updateJobs[conversationId] = (context.coroutineScope.launch { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/MessageDecoder.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/downloader/decoder/MessageDecoder.kt @@ -77,7 +77,7 @@ object MessageDecoder { fun decode(messageContent: MessageContent): List<DecodedAttachment> { return decode( - ProtoReader(messageContent.content), + ProtoReader(messageContent.content!!), customMediaReferences = getEncodedMediaReferences(gson.toJsonTree(messageContent.instanceNonNull())) ) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/SnapToChatMedia.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/SnapToChatMedia.kt @@ -12,10 +12,10 @@ class SnapToChatMedia : Feature("SnapToChatMedia", loadParams = FeatureLoadParam if (!context.config.experimental.snapToChatMedia.get()) return context.event.subscribe(BuildMessageEvent::class, priority = 100) { event -> - if (event.message.messageContent.contentType != ContentType.SNAP) return@subscribe + if (event.message.messageContent!!.contentType != ContentType.SNAP) return@subscribe - val snapMessageContent = ProtoReader(event.message.messageContent.content).followPath(11)?.getBuffer() ?: return@subscribe - event.message.messageContent.content = ProtoWriter().apply { + val snapMessageContent = ProtoReader(event.message.messageContent!!.content!!).followPath(11)?.getBuffer() ?: return@subscribe + event.message.messageContent!!.content = ProtoWriter().apply { from(3) { addBuffer(3, snapMessageContent) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/BypassVideoLengthRestriction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/BypassVideoLengthRestriction.kt @@ -40,7 +40,7 @@ class BypassVideoLengthRestriction : }) context.event.subscribe(SendMessageWithContentEvent::class) { event -> - if (event.destinations.stories.isEmpty()) return@subscribe + if (event.destinations.stories!!.isEmpty()) return@subscribe fileObserver.startWatching() } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt @@ -26,8 +26,8 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, } private fun saveMessage(conversationId: SnapUUID, message: Message) { - val messageId = message.messageDescriptor.messageId - if (messageLogger.takeIf { it.isEnabled }?.isMessageDeleted(conversationId.toString(), message.messageDescriptor.messageId) == true) return + val messageId = message.messageDescriptor!!.messageId!! + if (messageLogger.takeIf { it.isEnabled }?.isMessageDeleted(conversationId.toString(), messageId) == true) return if (message.messageState != MessageState.COMMITTED) return runCatching { @@ -50,8 +50,8 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, private fun canSaveMessage(message: Message): Boolean { if (context.mainActivity == null || context.isMainActivityPaused) return false - if (message.messageMetadata.savedBy.any { uuid -> uuid.toString() == context.database.myUserId }) return false - val contentType = message.messageContent.contentType.toString() + if (message.messageMetadata!!.savedBy!!.any { uuid -> uuid.toString() == context.database.myUserId }) return false + val contentType = message.messageContent!!.contentType.toString() return autoSaveFilter.any { it == contentType } } @@ -96,7 +96,7 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, { autoSaveFilter.isNotEmpty() } ) { param -> val message = Message(param.arg(0)) - val conversationId = message.messageDescriptor.conversationId + val conversationId = message.messageDescriptor!!.conversationId!! if (!canSaveInConversation(conversationId.toString())) return@hook if (!canSaveMessage(message)) return@hook diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/InstantDelete.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/InstantDelete.kt @@ -68,11 +68,11 @@ class InstantDelete : Feature("InstantDelete", loadParams = FeatureLoadParams.AC if (chatActionMenuOptions["chat_action_menu_erase_quote"] == menuOptionText.text) { conversationManager.fetchMessage(conversationId, messageId.toLong(), onSuccess = { message -> - val quotedMessage = message.messageContent.quotedMessage.takeIf { it.isPresent() }!! + val quotedMessage = message.messageContent!!.quotedMessage!!.takeIf { it.isPresent() }!! conversationManager.updateMessage( conversationId, - quotedMessage.content.messageId, + quotedMessage.content!!.messageId!!, MessageUpdate.ERASE, onResult = onCallbackResult ) 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 @@ -27,7 +27,6 @@ import me.rhunk.snapenhance.core.features.FeatureLoadParams import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder import me.rhunk.snapenhance.core.features.impl.spying.StealthMode -import me.rhunk.snapenhance.core.util.CallbackBuilder import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.hook import me.rhunk.snapenhance.core.util.ktx.setObjectField @@ -264,14 +263,14 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN } } - val contentType = snapMessage.messageContent.contentType ?: return@onEach - val contentData = snapMessage.messageContent.content + val contentType = snapMessage.messageContent!!.contentType ?: return@onEach + val contentData = snapMessage.messageContent!!.content!! val formatUsername: (String) -> String = { "$senderUsername: $it" } val notificationCache = cachedMessages.let { it.computeIfAbsent(conversationId) { mutableListOf() } } val appendNotifications: () -> Unit = { setNotificationText(notificationData.notification, conversationId)} - setupNotificationActionButtons(contentType, conversationId, snapMessage.messageDescriptor.messageId, notificationData) + setupNotificationActionButtons(contentType, conversationId, snapMessage.messageDescriptor!!.messageId!!, notificationData) when (contentType) { ContentType.NOTE -> { @@ -286,14 +285,14 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN } ContentType.SNAP, ContentType.EXTERNAL_MEDIA -> { val mediaReferences = MessageDecoder.getMediaReferences( - messageContent = context.gson.toJsonTree(snapMessage.messageContent.instanceNonNull()) + messageContent = context.gson.toJsonTree(snapMessage.messageContent!!.instanceNonNull()) ) val mediaReferenceKeys = mediaReferences.map { reference -> reference.asJsonObject.getAsJsonArray("mContentObject").map { it.asByte }.toByteArray() } - MessageDecoder.decode(snapMessage.messageContent).firstOrNull()?.also { media -> + MessageDecoder.decode(snapMessage.messageContent!!).firstOrNull()?.also { media -> val mediaType = MediaReferenceType.valueOf(mediaReferences.first().asJsonObject["mMediaType"].asString) runCatching { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/SendOverride.kt @@ -58,7 +58,7 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI if (localMessageContent.contentType != ContentType.EXTERNAL_MEDIA) return@subscribe //prevent story replies - val messageProtoReader = ProtoReader(localMessageContent.content) + val messageProtoReader = ProtoReader(localMessageContent.content!!) if (messageProtoReader.contains(7)) return@subscribe event.canceled = true diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/UnlimitedSnapViewTime.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/UnlimitedSnapViewTime.kt @@ -15,13 +15,13 @@ class UnlimitedSnapViewTime : context.event.subscribe(BuildMessageEvent::class, { state }, priority = 101) { event -> if (event.message.messageState != MessageState.COMMITTED) return@subscribe - if (event.message.messageContent.contentType != ContentType.SNAP) return@subscribe + if (event.message.messageContent!!.contentType != ContentType.SNAP) return@subscribe val messageContent = event.message.messageContent - val mediaAttributes = ProtoReader(messageContent.content).followPath(11, 5, 2) ?: return@subscribe + val mediaAttributes = ProtoReader(messageContent!!.content!!).followPath(11, 5, 2) ?: return@subscribe if (mediaAttributes.contains(6)) return@subscribe - messageContent.content = ProtoEditor(messageContent.content).apply { + messageContent.content = ProtoEditor(messageContent.content!!).apply { edit(11, 5, 2) { remove(8) addBuffer(6, byteArrayOf()) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/MessageLogger.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/MessageLogger.kt @@ -101,14 +101,14 @@ class MessageLogger : Feature("MessageLogger", val messageInstance = event.message.instanceNonNull() if (event.message.messageState != MessageState.COMMITTED) return@subscribe - cachedIdLinks[event.message.messageDescriptor.messageId] = event.message.orderKey - val conversationId = event.message.messageDescriptor.conversationId.toString() + cachedIdLinks[event.message.messageDescriptor!!.messageId!!] = event.message.orderKey!! + val conversationId = event.message.messageDescriptor!!.conversationId.toString() //exclude messages sent by me if (event.message.senderId.toString() == context.database.myUserId) return@subscribe - val uniqueMessageIdentifier = computeMessageIdentifier(conversationId, event.message.orderKey) + val uniqueMessageIdentifier = computeMessageIdentifier(conversationId, event.message.orderKey!!) - if (event.message.messageContent.contentType != ContentType.STATUS) { + if (event.message.messageContent!!.contentType != ContentType.STATUS) { if (fetchedMessages.contains(uniqueMessageIdentifier)) return@subscribe fetchedMessages.add(uniqueMessageIdentifier) 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 @@ -13,13 +13,13 @@ import me.rhunk.snapenhance.core.features.impl.messaging.Messaging fun me.rhunk.snapenhance.core.wrapper.impl.Message.toBridge(): Message { return Message().also { output -> - output.conversationId = this.messageDescriptor.conversationId.toString() + output.conversationId = this.messageDescriptor!!.conversationId.toString() output.senderId = this.senderId.toString() - output.clientMessageId = this.messageDescriptor.messageId - output.serverMessageId = this.orderKey - output.contentType = this.messageContent.contentType?.id ?: -1 - output.content = this.messageContent.content - output.mediaReferences = MessageDecoder.getEncodedMediaReferences(this.messageContent) + output.clientMessageId = this.messageDescriptor!!.messageId!! + output.serverMessageId = this.orderKey!! + output.contentType = this.messageContent?.contentType?.id ?: -1 + output.content = this.messageContent?.content + output.mediaReferences = MessageDecoder.getEncodedMediaReferences(this.messageContent!!) } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageExporter.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageExporter.kt @@ -74,8 +74,8 @@ class MessageExporter( } private fun serializeMessageContent(message: Message): String? { - return if (message.messageContent.contentType == ContentType.CHAT) { - ProtoReader(message.messageContent.content).getString(2, 1) ?: "Failed to parse message" + return if (message.messageContent!!.contentType == ContentType.CHAT) { + ProtoReader(message.messageContent!!.content!!).getString(2, 1) ?: "Failed to parse message" } else null } @@ -93,8 +93,8 @@ class MessageExporter( val sender = conversationParticipants[message.senderId.toString()] val senderUsername = sender?.usernameForSorting ?: message.senderId.toString() val senderDisplayName = sender?.displayName ?: message.senderId.toString() - val messageContent = serializeMessageContent(message) ?: message.messageContent.contentType?.name - val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(message.messageMetadata.createdAt)) + val messageContent = serializeMessageContent(message) ?: message.messageContent!!.contentType?.name + val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(message.messageMetadata!!.createdAt!!)) writer.write("[$date] - $senderDisplayName (${senderUsername}): $messageContent\n") } writer.flush() @@ -110,17 +110,17 @@ class MessageExporter( fun updateProgress(type: String) { val total = messages.filter { - mediaToDownload?.contains(it.messageContent.contentType) ?: false + mediaToDownload?.contains(it.messageContent!!.contentType) ?: false }.size processCount++ printLog("$type $processCount/$total") } messages.filter { - mediaToDownload?.contains(it.messageContent.contentType) ?: false + mediaToDownload?.contains(it.messageContent!!.contentType) ?: false }.forEach { message -> threadPool.execute { - MessageDecoder.decode(message.messageContent).forEach decode@{ attachment -> + MessageDecoder.decode(message.messageContent!!).forEach decode@{ attachment -> val protoMediaReference = Base64.UrlSafe.decode(attachment.mediaUrlKey ?: return@decode) runCatching { @@ -145,8 +145,8 @@ class MessageExporter( updateProgress("downloaded") }.onFailure { - printLog("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}") - context.log.error("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}", it) + printLog("failed to download media for ${message.messageDescriptor!!.conversationId}_${message.orderKey}") + context.log.error("failed to download media for ${message.messageDescriptor!!.conversationId}_${message.orderKey}", it) } } } @@ -270,7 +270,7 @@ class MessageExporter( add(JsonObject().apply { addProperty("orderKey", message.orderKey) addProperty("senderId", participants.getOrDefault(message.senderId.toString(), -1)) - addProperty("type", message.messageContent.contentType.toString()) + addProperty("type", message.messageContent!!.contentType.toString()) fun addUUIDList(name: String, list: List<SnapUUID>) { add(name, JsonArray().apply { @@ -278,12 +278,12 @@ class MessageExporter( }) } - addUUIDList("savedBy", message.messageMetadata.savedBy) - addUUIDList("seenBy", message.messageMetadata.seenBy) - addUUIDList("openedBy", message.messageMetadata.openedBy) + addUUIDList("savedBy", message.messageMetadata!!.savedBy!!) + addUUIDList("seenBy", message.messageMetadata!!.seenBy!!) + addUUIDList("openedBy", message.messageMetadata!!.openedBy!!) add("reactions", JsonObject().apply { - message.messageMetadata.reactions.forEach { reaction -> + message.messageMetadata!!.reactions!!.forEach { reaction -> addProperty( participants.getOrDefault(reaction.userId.toString(), -1L).toString(), reaction.reactionId @@ -291,13 +291,13 @@ class MessageExporter( } }) - addProperty("createdTimestamp", message.messageMetadata.createdAt) - addProperty("readTimestamp", message.messageMetadata.readAt) + addProperty("createdTimestamp", message.messageMetadata!!.createdAt) + addProperty("readTimestamp", message.messageMetadata!!.readAt) addProperty("serializedContent", serializeMessageContent(message)) - addProperty("rawContent", Base64.UrlSafe.encode(message.messageContent.content)) + addProperty("rawContent", Base64.UrlSafe.encode(message.messageContent!!.content!!)) add("attachments", JsonArray().apply { - MessageDecoder.decode(message.messageContent) + MessageDecoder.decode(message.messageContent!!) .forEach attachments@{ attachments -> if (attachments.type == AttachmentType.STICKER) //TODO: implement stickers return@attachments diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageSender.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/messaging/MessageSender.kt @@ -94,12 +94,12 @@ class MessageSender( val localMessageContent = context.gson.fromJson(localMessageContentTemplate, context.classCache.localMessageContent) val messageDestinations = MessageDestinations(AbstractWrapper.newEmptyInstance(context.classCache.messageDestinations)).also { - it.conversations = conversations - it.mPhoneNumbers = arrayListOf() - it.stories = arrayListOf() + it.conversations = conversations.toCollection(ArrayList()) + it.mPhoneNumbers = arrayListOf<Any>() + it.stories = arrayListOf<Any>() } - sendMessageWithContentMethod.invoke(context.feature(Messaging::class).conversationManager, messageDestinations.instanceNonNull(), localMessageContent, callback) + sendMessageWithContentMethod.invoke(context.feature(Messaging::class).conversationManager?.instanceNonNull(), messageDestinations.instanceNonNull(), localMessageContent, callback) } fun sendChatMessage(conversations: List<SnapUUID>, message: String, onError: (Any) -> Unit = {}, onSuccess: () -> Unit = {}) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/AbstractWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/AbstractWrapper.kt @@ -2,24 +2,47 @@ package me.rhunk.snapenhance.core.wrapper import de.robv.android.xposed.XposedHelpers import me.rhunk.snapenhance.core.util.CallbackBuilder +import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID import kotlin.reflect.KProperty abstract class AbstractWrapper( protected var instance: Any? ) { + protected val uuidArrayListMapper: (Any?) -> ArrayList<SnapUUID> get() = { (it as ArrayList<*>).map { i -> SnapUUID(i) }.toCollection(ArrayList()) } + @Suppress("UNCHECKED_CAST") inner class EnumAccessor<T>(private val fieldName: String, private val defaultValue: T) { operator fun getValue(obj: Any, property: KProperty<*>): T? = getEnumValue(fieldName, defaultValue as Enum<*>) as? T operator fun setValue(obj: Any, property: KProperty<*>, value: Any?) = setEnumValue(fieldName, value as Enum<*>) } + inner class FieldAccessor<T>(private val fieldName: String, private val mapper: ((Any?) -> T?)? = null) { + @Suppress("UNCHECKED_CAST") + operator fun getValue(obj: Any, property: KProperty<*>): T? { + val value = XposedHelpers.getObjectField(instance, fieldName) + return if (mapper != null) { + mapper.invoke(value) + } else { + value as? T + } + } + + operator fun setValue(obj: Any, property: KProperty<*>, value: Any?) { + XposedHelpers.setObjectField(instance, fieldName, when (value) { + is AbstractWrapper -> value.instance + is ArrayList<*> -> value.map { if (it is AbstractWrapper) it.instance else it }.toMutableList() + else -> value + }) + } + } + companion object { fun newEmptyInstance(clazz: Class<*>): Any { return CallbackBuilder.createEmptyObject(clazz.constructors[0]) ?: throw NullPointerException() } } - fun instanceNonNull(): Any = instance!! + fun instanceNonNull(): Any = instance ?: throw NullPointerException("Instance of ${this::class.simpleName} is null") fun isPresent(): Boolean = instance != null override fun hashCode(): Int { @@ -31,6 +54,7 @@ abstract class AbstractWrapper( } protected fun <T> enum(fieldName: String, defaultValue: T) = EnumAccessor(fieldName, defaultValue) + protected fun <T> field(fieldName: String, mapper: ((Any?) -> T?)? = null) = FieldAccessor(fieldName, mapper) fun <T : Enum<*>> getEnumValue(fieldName: String, defaultValue: T?): T? { if (defaultValue == null) return null 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 @@ -7,7 +7,10 @@ import me.rhunk.snapenhance.core.wrapper.AbstractWrapper typealias CallbackResult = (error: String?) -> Unit -class ConversationManager(val context: ModContext, obj: Any) : AbstractWrapper(obj) { +class ConversationManager( + val context: ModContext, + obj: Any +) : AbstractWrapper(obj) { private fun findMethodByName(name: String) = context.classCache.conversationManager.declaredMethods.find { it.name == name } ?: throw RuntimeException("Could not find method $name") private val updateMessageMethod by lazy { findMethodByName("updateMessage") } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/FriendActionButton.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/FriendActionButton.kt @@ -1,38 +0,0 @@ -package me.rhunk.snapenhance.core.wrapper.impl - -import android.content.Context -import android.graphics.drawable.Drawable -import android.util.AttributeSet -import android.view.View -import me.rhunk.snapenhance.core.SnapEnhance -import me.rhunk.snapenhance.core.wrapper.AbstractWrapper - -class FriendActionButton( - obj: View -) : AbstractWrapper(obj) { - private val iconDrawableContainer by lazy { - instanceNonNull().javaClass.declaredFields.first { it.type != Int::class.javaPrimitiveType }[instanceNonNull()] - } - - private val setIconDrawableMethod by lazy { - iconDrawableContainer.javaClass.declaredMethods.first { - it.parameterTypes.size == 1 && - it.parameterTypes[0] == Drawable::class.java && - it.name != "invalidateDrawable" && - it.returnType == Void::class.javaPrimitiveType - } - } - - fun setIconDrawable(drawable: Drawable) { - setIconDrawableMethod.invoke(iconDrawableContainer, drawable) - } - - companion object { - fun new(context: Context): FriendActionButton { - val instance = SnapEnhance.classLoader.loadClass("com.snap.profile.shared.view.FriendActionButton") - .getConstructor(Context::class.java, AttributeSet::class.java) - .newInstance(context, null) as View - return FriendActionButton(instance) - } - } -}- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Message.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/Message.kt @@ -1,14 +1,21 @@ package me.rhunk.snapenhance.core.wrapper.impl import me.rhunk.snapenhance.common.data.MessageState -import me.rhunk.snapenhance.core.util.ktx.getObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class Message(obj: Any?) : AbstractWrapper(obj) { - val orderKey get() = instanceNonNull().getObjectField("mOrderKey") as Long - val senderId get() = SnapUUID(instanceNonNull().getObjectField("mSenderId")) - val messageContent get() = MessageContent(instanceNonNull().getObjectField("mMessageContent")) - val messageDescriptor get() = MessageDescriptor(instanceNonNull().getObjectField("mDescriptor")) - val messageMetadata get() = MessageMetadata(instanceNonNull().getObjectField("mMetadata")) + @get:JSGetter @set:JSSetter + var orderKey by field<Long>("mOrderKey") + @get:JSGetter @set:JSSetter + var senderId by field("mSenderId") { SnapUUID(it) } + @get:JSGetter @set:JSSetter + var messageContent by field("mMessageContent") { MessageContent(it) } + @get:JSGetter @set:JSSetter + var messageDescriptor by field("mDescriptor") { MessageDescriptor(it) } + @get:JSGetter @set:JSSetter + var messageMetadata by field("mMetadata") { MessageMetadata(it) } + @get:JSGetter @set:JSSetter var messageState by enum("mState", MessageState.COMMITTED) } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageContent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageContent.kt @@ -1,15 +1,15 @@ package me.rhunk.snapenhance.core.wrapper.impl import me.rhunk.snapenhance.common.data.ContentType -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class MessageContent(obj: Any?) : AbstractWrapper(obj) { - var content - get() = instanceNonNull().getObjectField("mContent") as ByteArray - set(value) = instanceNonNull().setObjectField("mContent", value) - val quotedMessage - get() = QuotedMessage(instanceNonNull().getObjectField("mQuotedMessage")) + @get:JSGetter @set:JSSetter + var content by field<ByteArray>("mContent") + @get:JSGetter @set:JSSetter + var quotedMessage by field("mQuotedMessage") { QuotedMessage(it) } + @get:JSGetter @set:JSSetter var contentType by enum("mContentType", ContentType.UNKNOWN) } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDescriptor.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageDescriptor.kt @@ -1,9 +1,11 @@ package me.rhunk.snapenhance.core.wrapper.impl -import me.rhunk.snapenhance.core.util.ktx.getObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class MessageDescriptor(obj: Any?) : AbstractWrapper(obj) { - val messageId: Long get() = instanceNonNull().getObjectField("mMessageId") as Long - val conversationId: SnapUUID get() = SnapUUID(instanceNonNull().getObjectField("mConversationId")!!) + @get:JSGetter @set:JSSetter + var messageId by field<Long>("mMessageId") + val conversationId by field("mConversationId") { SnapUUID(it) } } \ No newline at end of file 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 @@ -1,15 +1,10 @@ package me.rhunk.snapenhance.core.wrapper.impl -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper @Suppress("UNCHECKED_CAST") class MessageDestinations(obj: Any) : AbstractWrapper(obj){ - var conversations get() = (instanceNonNull().getObjectField("mConversations") as ArrayList<*>).map { SnapUUID(it) } - set(value) = instanceNonNull().setObjectField("mConversations", value.map { it.instanceNonNull() }.toCollection(ArrayList())) - var stories get() = instanceNonNull().getObjectField("mStories") as ArrayList<Any> - set(value) = instanceNonNull().setObjectField("mStories", value) - var mPhoneNumbers get() = instanceNonNull().getObjectField("mPhoneNumbers") as ArrayList<Any> - set(value) = instanceNonNull().setObjectField("mPhoneNumbers", value) + var conversations by field("mConversations", uuidArrayListMapper) + var stories by field<ArrayList<*>>("mStories") + var mPhoneNumbers by field<ArrayList<*>>("mPhoneNumbers") } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageMetadata.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/MessageMetadata.kt @@ -1,28 +1,26 @@ package me.rhunk.snapenhance.core.wrapper.impl import me.rhunk.snapenhance.common.data.PlayableSnapState -import me.rhunk.snapenhance.core.util.ktx.getObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class MessageMetadata(obj: Any?) : AbstractWrapper(obj){ - val createdAt: Long get() = instanceNonNull().getObjectField("mCreatedAt") as Long - val readAt: Long get() = instanceNonNull().getObjectField("mReadAt") as Long + @get:JSGetter @set:JSSetter + var createdAt by field<Long>("mCreatedAt") + @get:JSGetter @set:JSSetter + var readAt by field<Long>("mReadAt") + @get:JSGetter @set:JSSetter var playableSnapState by enum("mPlayableSnapState", PlayableSnapState.PLAYABLE) - private fun getUUIDList(name: String): List<SnapUUID> { - return (instanceNonNull().getObjectField(name) as List<*>).map { SnapUUID(it!!) } - } - - val savedBy: List<SnapUUID> by lazy { - getUUIDList("mSavedBy") - } - val openedBy: List<SnapUUID> by lazy { - getUUIDList("mOpenedBy") - } - val seenBy: List<SnapUUID> by lazy { - getUUIDList("mSeenBy") - } - val reactions: List<UserIdToReaction> by lazy { - (instanceNonNull().getObjectField("mReactions") as List<*>).map { UserIdToReaction(it!!) } + @get:JSGetter @set:JSSetter + var savedBy by field("mSavedBy", uuidArrayListMapper) + @get:JSGetter @set:JSSetter + var openedBy by field("mOpenedBy", uuidArrayListMapper) + @get:JSGetter @set:JSSetter + var seenBy by field("mSeenBy", uuidArrayListMapper) + @get:JSGetter @set:JSSetter + var reactions by field("mReactions") { + (it as ArrayList<*>).map { i -> UserIdToReaction(i) }.toMutableList() } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessage.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessage.kt @@ -1,8 +1,10 @@ package me.rhunk.snapenhance.core.wrapper.impl -import me.rhunk.snapenhance.core.util.ktx.getObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class QuotedMessage(obj: Any?) : AbstractWrapper(obj) { - val content get() = QuotedMessageContent(instanceNonNull().getObjectField("mContent")) + @get:JSGetter @set:JSSetter + var content by field("mContent") { QuotedMessageContent(it) } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessageContent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/QuotedMessageContent.kt @@ -1,10 +1,10 @@ package me.rhunk.snapenhance.core.wrapper.impl -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class QuotedMessageContent(obj: Any?) : AbstractWrapper(obj) { - var messageId get() = instanceNonNull().getObjectField("mMessageId") as Long - set(value) = instanceNonNull().setObjectField("mMessageId", value) + @get:JSGetter @set:JSSetter + var messageId by field<Long>("mMessageId") } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/UserIdToReaction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/wrapper/impl/UserIdToReaction.kt @@ -1,11 +1,21 @@ package me.rhunk.snapenhance.core.wrapper.impl import me.rhunk.snapenhance.core.util.ktx.getObjectField +import me.rhunk.snapenhance.core.util.ktx.setObjectField import me.rhunk.snapenhance.core.wrapper.AbstractWrapper +import org.mozilla.javascript.annotations.JSGetter +import org.mozilla.javascript.annotations.JSSetter class UserIdToReaction(obj: Any?) : AbstractWrapper(obj) { - val userId = SnapUUID(instanceNonNull().getObjectField("mUserId")) - val reactionId = (instanceNonNull().getObjectField("mReaction") + @get:JSGetter @set:JSSetter + var userId by field("mUserId") { SnapUUID(it) } + @get:JSGetter @set:JSSetter + var reactionId get() = (instanceNonNull().getObjectField("mReaction") ?.getObjectField("mReactionContent") - ?.getObjectField("mIntentionType") as Long?) ?: 0 + ?.getObjectField("mIntentionType") as Long?) ?: -1 + set(value) { + instanceNonNull().getObjectField("mReaction") + ?.getObjectField("mReactionContent") + ?.setObjectField("mIntentionType", value) + } } \ No newline at end of file