commit dded6acff08dc925213bb7ab80a172d52da462e6
parent c791fbbd005f1ec1acece35a6434ae3695d58290
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Thu, 31 Aug 2023 15:42:24 +0200
feat: add friend source spoof
Diffstat:
9 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/core/src/main/assets/lang/en_US.json b/core/src/main/assets/lang/en_US.json
@@ -366,6 +366,10 @@
"no_friend_score_delay": {
"name": "No Friend Score Delay",
"description": "Removes the delay when viewing a friends score"
+ },
+ "add_friend_source_spoof": {
+ "name": "Add Friend Source Spoof",
+ "description": "Spoofs the source of a friend request"
}
}
}
@@ -461,6 +465,13 @@
"ngs_community_icon_container": "Community / Stories",
"ngs_spotlight_icon_container": "Spotlight",
"ngs_search_icon_container": "Search"
+ },
+ "add_friend_source_spoof": {
+ "added_by_username": "By Username",
+ "added_by_mention": "By Mention",
+ "added_by_group_chat": "By Group Chat",
+ "added_by_qr_code": "By QR Code",
+ "added_by_community": "By Community"
}
}
},
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MappingsWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/wrapper/MappingsWrapper.kt
@@ -14,6 +14,7 @@ import me.rhunk.snapmapper.impl.CallbackMapper
import me.rhunk.snapmapper.impl.CompositeConfigurationProviderMapper
import me.rhunk.snapmapper.impl.DefaultMediaItemMapper
import me.rhunk.snapmapper.impl.EnumMapper
+import me.rhunk.snapmapper.impl.FriendRelationshipChangerMapper
import me.rhunk.snapmapper.impl.FriendsFeedEventDispatcherMapper
import me.rhunk.snapmapper.impl.MediaQualityLevelProviderMapper
import me.rhunk.snapmapper.impl.OperaPageViewControllerMapper
@@ -41,7 +42,8 @@ class MappingsWrapper : FileLoaderWrapper(BridgeFileType.MAPPINGS, "{}".toByteAr
StoryBoostStateMapper::class,
FriendsFeedEventDispatcherMapper::class,
CompositeConfigurationProviderMapper::class,
- ScoreUpdateMapper::class
+ ScoreUpdateMapper::class,
+ FriendRelationshipChangerMapper::class,
)
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Experimental.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Experimental.kt
@@ -12,4 +12,11 @@ class Experimental : ConfigContainer() {
val meoPasscodeBypass = boolean("meo_passcode_bypass")
val unlimitedMultiSnap = boolean("unlimited_multi_snap") { addNotices(FeatureNotice.MAY_BAN)}
val noFriendScoreDelay = boolean("no_friend_score_delay")
+ val addFriendSourceSpoof = unique("add_friend_source_spoof",
+ "added_by_username",
+ "added_by_mention",
+ "added_by_group_chat",
+ "added_by_qr_code",
+ "added_by_community",
+ ) { addNotices(FeatureNotice.MAY_BAN) }
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt
@@ -49,6 +49,9 @@ class DatabaseAccess(private val context: ModContext) : Manager {
query: (SQLiteDatabase) -> T?
): T? {
synchronized(databaseLock) {
+ if (!database.isOpen) {
+ return null
+ }
return runCatching {
query(database)
}.onFailure {
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/Feature.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/Feature.kt
@@ -3,7 +3,7 @@ package me.rhunk.snapenhance.features
import me.rhunk.snapenhance.ModContext
abstract class Feature(
- val nameKey: String,
+ val featureKey: String,
val loadParams: Int = FeatureLoadParams.INIT_SYNC
) {
lateinit var context: ModContext
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AddFriendSourceSpoof.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AddFriendSourceSpoof.kt
@@ -0,0 +1,55 @@
+package me.rhunk.snapenhance.features.impl.experiments
+
+import me.rhunk.snapenhance.features.Feature
+import me.rhunk.snapenhance.features.FeatureLoadParams
+import me.rhunk.snapenhance.hook.HookStage
+import me.rhunk.snapenhance.hook.hook
+
+class AddFriendSourceSpoof : Feature("AddFriendSourceSpoof", loadParams = FeatureLoadParams.ACTIVITY_CREATE_ASYNC) {
+ override fun asyncOnActivityCreate() {
+ val friendRelationshipChangerMapping = context.mappings.getMappedMap("FriendRelationshipChanger")
+
+ findClass(friendRelationshipChangerMapping["class"].toString())
+ .hook(friendRelationshipChangerMapping["addFriendMethod"].toString(), HookStage.BEFORE) { param ->
+ val spoofedSource = context.config.experimental.addFriendSourceSpoof.getNullable() ?: return@hook
+
+ context.log.verbose("addFriendMethod: ${param.args().toList()}", featureKey)
+
+ fun setEnum(index: Int, value: String) {
+ val enumData = param.arg<Any>(index)
+ enumData::class.java.enumConstants.first { it.toString() == value }.let {
+ param.setArg(index, it)
+ }
+ }
+
+ when (spoofedSource) {
+ "added_by_group_chat" -> {
+ setEnum(1, "PROFILE")
+ setEnum(2, "GROUP_PROFILE")
+ setEnum(3, "ADDED_BY_GROUP_CHAT")
+ }
+ "added_by_username" -> {
+ setEnum(1, "SEARCH")
+ setEnum(2, "SEARCH")
+ setEnum(3, "ADDED_BY_USERNAME")
+ }
+ "added_by_qr_code" -> {
+ setEnum(1, "PROFILE")
+ setEnum(2, "PROFILE")
+ setEnum(3, "ADDED_BY_QR_CODE")
+ }
+ "added_by_mention" -> {
+ setEnum(1, "CONTEXT_CARDS")
+ setEnum(2, "CONTEXT_CARD")
+ setEnum(3, "ADDED_BY_MENTION")
+ }
+ "added_by_community" -> {
+ setEnum(1, "PROFILE")
+ setEnum(2, "PROFILE")
+ setEnum(3, "ADDED_BY_COMMUNITY")
+ }
+ else -> return@hook
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt
@@ -9,6 +9,7 @@ import me.rhunk.snapenhance.features.impl.ConfigurationOverride
import me.rhunk.snapenhance.features.impl.Messaging
import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader
import me.rhunk.snapenhance.features.impl.downloader.ProfilePictureDownloader
+import me.rhunk.snapenhance.features.impl.experiments.AddFriendSourceSpoof
import me.rhunk.snapenhance.features.impl.experiments.AmoledDarkMode
import me.rhunk.snapenhance.features.impl.experiments.AppPasscode
import me.rhunk.snapenhance.features.impl.experiments.DeviceSpooferHook
@@ -93,6 +94,7 @@ class FeatureManager(private val context: ModContext) : Manager {
register(GooglePlayServicesDialogs::class)
register(NoFriendScoreDelay::class)
register(ProfilePictureDownloader::class)
+ register(AddFriendSourceSpoof::class)
initializeFeatures()
}
@@ -103,8 +105,8 @@ class FeatureManager(private val context: ModContext) : Manager {
runCatching {
action(feature)
}.onFailure {
- Logger.xposedLog("Failed to init feature ${feature.nameKey}", it)
- context.longToast("Failed to init feature ${feature.nameKey}")
+ context.log.error("Failed to init feature ${feature.featureKey}", it)
+ context.longToast("Failed to load feature ${feature.featureKey}! Check logcat for more details.")
}
}
if (!isAsync) {
diff --git a/mapper/src/main/kotlin/me/rhunk/snapmapper/impl/FriendRelationshipChangerMapper.kt b/mapper/src/main/kotlin/me/rhunk/snapmapper/impl/FriendRelationshipChangerMapper.kt
@@ -0,0 +1,27 @@
+package me.rhunk.snapmapper.impl
+
+import me.rhunk.snapmapper.AbstractClassMapper
+import me.rhunk.snapmapper.MapperContext
+import me.rhunk.snapmapper.ext.findConstString
+import me.rhunk.snapmapper.ext.getClassName
+import me.rhunk.snapmapper.ext.isEnum
+
+class FriendRelationshipChangerMapper : AbstractClassMapper() {
+ override fun run(context: MapperContext) {
+ for (classDef in context.classes) {
+ classDef.methods.firstOrNull { it.name == "<init>" }?.implementation?.findConstString("FriendRelationshipChangerImpl")?.takeIf { it } ?: continue
+ val addFriendMethod = classDef.methods.first {
+ it.parameterTypes.size > 4 &&
+ context.getClass(it.parameterTypes[1])?.isEnum() == true &&
+ context.getClass(it.parameterTypes[2])?.isEnum() == true &&
+ context.getClass(it.parameterTypes[3])?.isEnum() == true &&
+ it.parameters[4].type == "Ljava/lang/String;"
+ }
+
+ context.addMapping("FriendRelationshipChanger",
+ "class" to classDef.getClassName(),
+ "addFriendMethod" to addFriendMethod.name
+ )
+ }
+ }
+}+
\ No newline at end of file
diff --git a/mapper/src/test/kotlin/me/rhunk/snapenhance/mapper/tests/TestMappings.kt b/mapper/src/test/kotlin/me/rhunk/snapenhance/mapper/tests/TestMappings.kt
@@ -24,6 +24,7 @@ class TestMappings {
FriendsFeedEventDispatcherMapper::class,
CompositeConfigurationProviderMapper::class,
ScoreUpdateMapper::class,
+ FriendRelationshipChangerMapper::class,
)
val gson = GsonBuilder().setPrettyPrinting().create()