mirror of
https://github.com/BillyOutlast/GrindrPlus.git
synced 2026-07-01 15:43:22 -04:00
GrindrPlus: Update antiblock to 25.20
This commit is contained in:
@@ -8,38 +8,41 @@ import com.grindrplus.core.DatabaseHelper
|
||||
import com.grindrplus.core.Logger
|
||||
import com.grindrplus.core.logd
|
||||
import com.grindrplus.core.loge
|
||||
import com.grindrplus.core.logi
|
||||
import com.grindrplus.utils.Hook
|
||||
import com.grindrplus.utils.HookStage
|
||||
import com.grindrplus.utils.hook
|
||||
import com.grindrplus.utils.hookConstructor
|
||||
import de.robv.android.xposed.XposedHelpers.getObjectField
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
|
||||
// supported version: 25.20.0
|
||||
class AntiBlock : Hook(
|
||||
"Anti Block",
|
||||
"Notifies you when someone blocks or unblocks you"
|
||||
) {
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
private var myProfileId: Long = 0
|
||||
private val chatDeleteConversationPlugin = "F6.c" // search for 'com.grindrapp.android.chat.ChatDeleteConversationPlugin'
|
||||
private val inboxFragmentV2DeleteConversations = "ca.i" // search for '("chat_read_receipt", conversationId, null);'
|
||||
private val individualUnblockActivityViewModel = "ng.p" // search for 'SnackbarEvent.i.ERROR, R.string.unblock_individual_sync_blocks_failure, null, new SnackbarEvent'
|
||||
private val chatDeleteConversationPlugin = "R9.c" // search for '"com.grindrapp.android.chat.ChatDeleteConversationPlugin",' and use the outer class
|
||||
private val inboxFragmentV2DeleteConversations = "re.d" // search for '("chat_read_receipt", conversationId, null);'
|
||||
private val individualUnblockActivityViewModel = "bl.k" // search for 'SnackbarEvent.i.ERROR, R.string.unblock_individual_sync_blocks_failure, null, new SnackbarEvent'
|
||||
|
||||
override fun init() {
|
||||
// do not invoke antiblock notification when the user is unblocking someone else
|
||||
// search for '.setValue(new DialogMessage(116, null, 2, null));'
|
||||
findClass(individualUnblockActivityViewModel).hook("K", HookStage.BEFORE) { param ->
|
||||
GrindrPlus.shouldTriggerAntiblock = false
|
||||
}
|
||||
findClass(individualUnblockActivityViewModel)
|
||||
.hook("R", HookStage.BEFORE) { param ->
|
||||
GrindrPlus.shouldTriggerAntiblock = false
|
||||
}
|
||||
|
||||
// reenable antiblock notification after *above* is finished
|
||||
// search for '.setValue(new DialogMessage(116, null, 2, null));'
|
||||
findClass(individualUnblockActivityViewModel).hook("K", HookStage.AFTER) { param ->
|
||||
Thread.sleep(700) // Wait for WS to unblock
|
||||
GrindrPlus.shouldTriggerAntiblock = true
|
||||
}
|
||||
findClass(individualUnblockActivityViewModel)
|
||||
.hook("R", HookStage.AFTER) { param ->
|
||||
Thread.sleep(700) // Wait for WS to unblock
|
||||
GrindrPlus.shouldTriggerAntiblock = true
|
||||
}
|
||||
|
||||
if (Config.get("force_old_anti_block_behavior", false) as Boolean) {
|
||||
findClass("com.grindrapp.android.chat.model.ConversationDeleteNotification")
|
||||
@@ -49,34 +52,43 @@ class AntiBlock : Hook(
|
||||
param.setArg(0, emptyList<String>())
|
||||
}
|
||||
} else {
|
||||
// search for '("chat_read_receipt", conversationId, null);'
|
||||
findClass(inboxFragmentV2DeleteConversations)
|
||||
.hook("d", HookStage.BEFORE) { param ->
|
||||
.hook("b", HookStage.BEFORE) { param ->
|
||||
GrindrPlus.shouldTriggerAntiblock = false
|
||||
GrindrPlus.blockCaller = "inboxFragmentV2DeleteConversations"
|
||||
}
|
||||
|
||||
// search for '("chat_read_receipt", conversationId, null);'
|
||||
findClass(inboxFragmentV2DeleteConversations)
|
||||
.hook("d", HookStage.AFTER) { param ->
|
||||
.hook("b", HookStage.AFTER) { param ->
|
||||
val numberOfChatsToDelete = (param.args().firstOrNull() as? List<*>)?.size ?: 0
|
||||
if (numberOfChatsToDelete == 0) return@hook
|
||||
if (numberOfChatsToDelete == 0)
|
||||
return@hook
|
||||
// is this okay to return here? shouldTriggerAntiblock stays false.
|
||||
// Do we expect another invocation with number > 0 ?
|
||||
|
||||
logd("Request to delete $numberOfChatsToDelete chats")
|
||||
Thread.sleep((300 * numberOfChatsToDelete).toLong()) // FIXME
|
||||
GrindrPlus.shouldTriggerAntiblock = true
|
||||
GrindrPlus.blockCaller = ""
|
||||
}
|
||||
|
||||
findClass(chatDeleteConversationPlugin).hook("b", HookStage.BEFORE) { param ->
|
||||
myProfileId = GrindrPlus.myProfileId.toLong()
|
||||
if (!GrindrPlus.shouldTriggerAntiblock) {
|
||||
// search for 'Deleting conversations'
|
||||
findClass(chatDeleteConversationPlugin)
|
||||
.hook("b", HookStage.BEFORE) { param ->
|
||||
myProfileId = GrindrPlus.myProfileId.toLong()
|
||||
if (GrindrPlus.shouldTriggerAntiblock)
|
||||
return@hook
|
||||
|
||||
val whitelist = listOf(
|
||||
"inboxFragmentV2DeleteConversations",
|
||||
)
|
||||
if (GrindrPlus.blockCaller !in whitelist) {
|
||||
param.setResult(null)
|
||||
}
|
||||
return@hook
|
||||
if (GrindrPlus.blockCaller in whitelist)
|
||||
return@hook
|
||||
|
||||
param.setResult(null)
|
||||
}
|
||||
}
|
||||
|
||||
findClass("com.grindrapp.android.chat.model.ConversationDeleteNotification")
|
||||
.hookConstructor(HookStage.BEFORE) { param ->
|
||||
|
||||
@@ -41,7 +41,7 @@ class HookManager {
|
||||
runBlocking(Dispatchers.IO) {
|
||||
val hookList = listOf(
|
||||
AllowScreenshots(),
|
||||
// AntiBlock(),
|
||||
AntiBlock(),
|
||||
AntiDetection(),
|
||||
BanManagement(),
|
||||
ChatIndicators(),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Patches
|
||||
|
||||
- [online indicator](online_indicator.md)
|
||||
- [Anti Block](anti_block.md)
|
||||
- [Online indicator](online_indicator.md)
|
||||
@@ -0,0 +1,34 @@
|
||||
# Anti Block
|
||||
|
||||
This feature detects when the user has been blocked and sends a notification
|
||||
from the Gplus app. The current implementation relies on websocket notifications,
|
||||
so it works only when the app is open. The notification received is `chat.v1.conversation.delete`
|
||||
and it is used also when the other user deletes his account.
|
||||
|
||||
|
||||
## Conversations database
|
||||
Conversations are also stored in the `chat_conversations`, `_messages` etc. tables.
|
||||
Conversations get deleted by `ConversationRepo::updateConversationsInternal`
|
||||
and/or `::purgeInvalidatedConversations` when the event arrives or when the app refreshes the conversations.
|
||||
The method has an argument `isDeleteMissingConversations`, which if set to false, keeps
|
||||
the conversation in the db. This however is not enough to keep it visible in the app.
|
||||
The app uses primarily conversation list from the rest service.
|
||||
|
||||
If we wanted to keep the conversations visible, we would need to hook the rest service and inject
|
||||
these not-deleted conversations into the result.
|
||||
|
||||
This should do to prevent the conversations from being deleted. This however also applies when
|
||||
the user himself deletes the conversation - it stays in the db.
|
||||
```kotlin
|
||||
findClass("com.grindrapp.android.persistence.repository.ConversationRepo")
|
||||
.hook("purgeInvalidatedConversations", HookStage.BEFORE) { param ->
|
||||
val emptyList = emptyList<String>()
|
||||
param.setArg(0, emptyList)
|
||||
}
|
||||
|
||||
|
||||
findClass("com.grindrapp.android.persistence.repository.ConversationRepo\$updateConversationsInternal\$2")
|
||||
.hookConstructor(HookStage.BEFORE) { param ->
|
||||
param.setArg(1, false) // search for '$isDeleteMissingConversations'
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user