Skip to content

Commit

Permalink
Add feature to show message content in notifications.
Browse files Browse the repository at this point in the history
  • Loading branch information
rodit committed May 16, 2022
1 parent 4883815 commit 919e163
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 12 deletions.
Binary file modified app/libs/snapmod.jar
Binary file not shown.
43 changes: 43 additions & 0 deletions app/src/main/java/xyz/rodit/snapmod/arroyo/ArroyoReader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package xyz.rodit.snapmod.arroyo

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import xyz.rodit.snapmod.logging.log
import xyz.rodit.snapmod.util.ProtoReader
import java.io.File

class ArroyoReader(private val context: Context) {

fun getMessageContent(conversationId: String, messageId: String): String? {
try {
val db: SQLiteDatabase =
SQLiteDatabase.openDatabase(
File(context.filesDir, "../databases/arroyo.db").path,
null,
0
)
val cursor =
db.rawQuery(
"SELECT message_content FROM conversation_message WHERE client_conversation_id='$conversationId' AND server_message_id=$messageId",
null
)
if (cursor.moveToFirst()) {
var parts = ProtoReader(cursor.getBlob(0)).read()
var container = parts.firstOrNull { it.index == 4 }?.value ?: return null
parts = ProtoReader(container).read()
container = parts.firstOrNull { it.index == 4 }?.value ?: return null
parts = ProtoReader(container).read()
container = parts.firstOrNull { it.index == 2 }?.value ?: return null
parts = ProtoReader(container).read()
container = parts.firstOrNull { it.index == 1 }?.value ?: return null
return String(container)
} else {
log.debug("No result in db.")
}
} catch (e: Exception) {
log.error("Error reading arroyo db", e)
}

return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import xyz.rodit.snapmod.features.saving.ChatSaving
import xyz.rodit.snapmod.features.saving.PublicProfileSaving
import xyz.rodit.snapmod.features.saving.StoriesSaving
import xyz.rodit.snapmod.features.tweaks.*
import xyz.rodit.snapmod.notifications.ShowMessageContent

class FeatureManager(context: FeatureContext) : Contextual(context) {

Expand All @@ -35,6 +36,9 @@ class FeatureManager(context: FeatureContext) : Contextual(context) {
// Message context menu
add(::MessageMenuModifier)

// Notifications
add(::ShowMessageContent)

// Opera (story/snap view)
add(::OperaModelModifier)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package xyz.rodit.snapmod.notifications

import xyz.rodit.snapmod.arroyo.ArroyoReader
import xyz.rodit.snapmod.features.Feature
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.mappings.NotificationData
import xyz.rodit.snapmod.mappings.NotificationHandler
import xyz.rodit.snapmod.util.before

class ShowMessageContent(context: FeatureContext) : Feature(context) {

private val arroyoReader = ArroyoReader(context.appContext)

override fun performHooks() {
NotificationHandler.handle.before(context, "show_notification_content") {
val data = NotificationData.wrap(NotificationHandler.wrap(it.thisObject).data)
val bundle = data.bundle
val conversationId = bundle.getString("arroyo_convo_id")
val messageId = bundle.getString("arroyo_message_id")
if (conversationId.isNullOrBlank() || messageId.isNullOrBlank()) return@before

val content = arroyoReader.getMessageContent(conversationId, messageId) ?: return@before
bundle.putString("ab_cnotif_body", content)
}
}
}
89 changes: 89 additions & 0 deletions app/src/main/java/xyz/rodit/snapmod/util/ProtoReader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package xyz.rodit.snapmod.util

import xyz.rodit.snapmod.logging.log
import java.math.BigInteger

private val BIGINT_2 = BigInteger.valueOf(2)
private const val TYPE_VAR_INT = 0
private const val TYPE_STRING = 2

internal inline infix fun Byte.and(other: Int): Int = toInt() and other

internal inline infix fun Byte.shl(other: Int): Int = toInt() shl other

class ProtoReader(private val data: ByteArray) {

private var position = 0
private var checkpoint = 0

fun read(): List<ProtoPart> {
val parts = mutableListOf<ProtoPart>()

while (position < data.size) {
checkpoint = position

val varInt = internalReadVarint32()
val type = varInt and 0b111
val index = varInt shr 3

var value = ByteArray(0)

if (type == TYPE_VAR_INT) {
value = internalReadVarint32().toString().toByteArray()
} else if (type == TYPE_STRING) {
val length = internalReadVarint32()
value = ByteArray(length)
data.copyInto(value, 0, position, position + length)
position += length
} else {
log.error("Unknown protobuf type $type")
}

parts.add(ProtoPart(index, type, value))
}

return parts
}

private fun readByte(): Byte {
return data[position++]
}

private fun internalReadVarint32(): Int {
var tmp = readByte()
if (tmp >= 0) {
return tmp.toInt()
}
var result = tmp and 0x7f
tmp = readByte()
if (tmp >= 0) {
result = result or (tmp shl 7)
} else {
result = result or (tmp and 0x7f shl 7)
tmp = readByte()
if (tmp >= 0) {
result = result or (tmp shl 14)
} else {
result = result or (tmp and 0x7f shl 14)
tmp = readByte()
if (tmp >= 0) {
result = result or (tmp shl 21)
} else {
result = result or (tmp and 0x7f shl 21)
tmp = readByte()
result = result or (tmp shl 28)
if (tmp < 0) {
for (i in 0..4) {
if (readByte() >= 0) {
return result
}
}
}
}
}
}
return result
}
}

data class ProtoPart(val index: Int, val type: Int, val value: ByteArray)
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,7 @@

<string name="enable_new_voice_notes_title">Enable New Voice Notes</string>
<string name="enable_new_voice_notes_description">Force enables the new voice note UI.</string>

<string name="show_notification_content_title">Show Message In Notifications</string>
<string name="show_notification_content_description">Displays message content in notifications.</string>
</resources>
18 changes: 6 additions & 12 deletions app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,6 @@
app:title="@string/hide_read_title"
app:summary="@string/hide_read_description"
app:iconSpaceReserved="false"/>

<SwitchPreferenceCompat
app:key="hide_save"
app:title="@string/hide_save_title"
app:summary="@string/hide_save_description"
app:iconSpaceReserved="false" />

<SwitchPreferenceCompat
app:key="dont_release"
app:title="@string/dont_release_messages_title"
app:summary="@string/dont_release_description"
app:iconSpaceReserved="false" />
</PreferenceCategory>

<PreferenceCategory app:title="@string/tweaks_header"
Expand Down Expand Up @@ -175,6 +163,12 @@
app:title="@string/enable_new_voice_notes_title"
app:summary="@string/enable_new_voice_notes_description"
app:iconSpaceReserved="false" />

<SwitchPreferenceCompat
app:key="show_notification_content"
app:title="@string/show_notification_content_title"
app:summary="@string/show_notification_content_description"
app:iconSpaceReserved="false" />
</PreferenceCategory>

<PreferenceCategory app:title="@string/snaps_header"
Expand Down
49 changes: 49 additions & 0 deletions snap.ds
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;

import com.google.gson.annotations.SerializedName;
import com.google.protobuf.nano.MessageNano;
Expand Down Expand Up @@ -1668,4 +1669,52 @@ class ChatModelPlugin {
.field !ChatLayouts->!PLUGIN;
.field !ChatLayouts->!PLUGIN_STATUS;
}
}

[certain, discard]
class NotificationDisplayData {

String $toString() {
.string "DisplayData(senderDisplayName=";
.string ", systemText=";
.string ", title=";
}
}

[certain]
class NotificationData {

String id;
String key;
String recipientId;
String recipientUsername;
[discard] !NotificationDisplayData ndd0;
long timestamp0;
long timestamp1;
String revokeKey;
Bundle bundle;
}

[certain, obfuscated, discard]
enum NotificationHandlerStatus {

[late] static this .fields {
HANDLER_START,
DISPLAY_MODEL_CREATE,
RETURN_EMPTY_RATE_LIMITED
}
}

[certain]
class NotificationHandler {

[discard] Object o0;
[discard] int a0;
Object data;

* handle() {
.type !NotificationData;
.field !NotificationHandlerStatus->!RETURN_EMPTY_RATE_LIMITED;
.field !NotificationHandlerStatus->!DISPLAY_MODEL_CREATE;
}
}

0 comments on commit 919e163

Please sign in to comment.