diff --git a/src/main/kotlin/crimera/patches/twitter/logging/responseLogging/ResponseLogging.kt b/src/main/kotlin/crimera/patches/twitter/logging/responseLogging/ResponseLogging.kt
new file mode 100644
index 00000000..be3429eb
--- /dev/null
+++ b/src/main/kotlin/crimera/patches/twitter/logging/responseLogging/ResponseLogging.kt
@@ -0,0 +1,46 @@
+package crimera.patches.twitter.logging.responseLogging
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
+import app.revanced.patcher.fingerprint.MethodFingerprint
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchException
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import crimera.patches.twitter.misc.settings.SettingsPatch
+import crimera.patches.twitter.misc.settings.fingerprints.SettingsStatusLoadFingerprint
+
+object InpStreamFingerprint : MethodFingerprint(
+ returnType = "Ljava/io/InputStream",
+ customFingerprint = { methodDef, classDef ->
+ classDef.type.contains("fasterxml/jackson/core/") &&
+ methodDef.parameters.size == 2
+ },
+)
+
+@Patch(
+ name = "Log server response",
+ description = "Log json responses received from server",
+ dependencies = [SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.twitter.android")],
+ requiresIntegrations = true,
+)
+@Suppress("unused")
+object RequestLogging : BytecodePatch(
+ setOf(SettingsStatusLoadFingerprint, InpStreamFingerprint),
+) {
+ override fun execute(context: BytecodeContext) {
+ val result = InpStreamFingerprint.result ?: throw PatchException("InpStreamFingerprint is not found")
+
+ result.mutableMethod.addInstructions(
+ 0,
+ """
+ invoke-static {p1}, ${SettingsPatch.PATCHES_DESCRIPTOR}/loggers/ResponseLogger;->saveInputStream(Ljava/io/InputStream;)Ljava/io/InputStream;
+ move-result-object p1
+ """.trimIndent(),
+ )
+
+ SettingsStatusLoadFingerprint.enableSettings("serverResponseLogging")
+ SettingsStatusLoadFingerprint.enableSettings("serverResponseLoggingOverwriteFile")
+ }
+}
diff --git a/src/main/kotlin/crimera/patches/twitter/timeline/hideCommunityBadge/HideCommunityBadge.kt b/src/main/kotlin/crimera/patches/twitter/timeline/hideCommunityBadge/HideCommunityBadge.kt
new file mode 100644
index 00000000..0ff03162
--- /dev/null
+++ b/src/main/kotlin/crimera/patches/twitter/timeline/hideCommunityBadge/HideCommunityBadge.kt
@@ -0,0 +1,61 @@
+package crimera.patches.twitter.timeline.hideCommunityBadge
+
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
+import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
+import app.revanced.patcher.fingerprint.MethodFingerprint
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchException
+import app.revanced.patcher.patch.annotation.CompatiblePackage
+import app.revanced.patcher.patch.annotation.Patch
+import app.revanced.patcher.util.smali.ExternalLabel
+import com.android.tools.smali.dexlib2.Opcode
+import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
+import crimera.patches.twitter.misc.settings.SettingsPatch
+import crimera.patches.twitter.misc.settings.fingerprints.SettingsStatusLoadFingerprint
+import crimera.patches.twitter.misc.shareMenu.nativeDownloader.extractDescriptors
+
+object CommModelFingerprint : MethodFingerprint(
+ strings =
+ listOf(
+ "actionResults",
+ "role",
+ ),
+)
+
+@Patch(
+ name = "Hide community badges",
+ description = "",
+ dependencies = [SettingsPatch::class],
+ compatiblePackages = [CompatiblePackage("com.twitter.android")],
+ requiresIntegrations = true,
+)
+@Suppress("unused")
+object HideCommunityBadge : BytecodePatch(
+ setOf(SettingsStatusLoadFingerprint, CommModelFingerprint),
+) {
+ override fun execute(context: BytecodeContext) {
+ val result = CommModelFingerprint.result ?: throw PatchException("CommModelFingerprint not found")
+
+ val method =
+ result.mutableMethod
+ val instructions = method.getInstructions()
+
+ val iputObj = instructions.last { it.opcode == Opcode.IPUT_OBJECT }
+ val iputObjIns = iputObj as Instruction22c
+ val ref = iputObjIns.reference.extractDescriptors()[1]
+ val reg = iputObjIns.registerA
+ val index = iputObj.location.index
+
+ method.addInstructionsWithLabels(
+ index,
+ """
+ sget-boolean v0, ${SettingsPatch.PREF_DESCRIPTOR};->HIDE_COMM_BADGE:Z
+ if-eqz v0, :piko
+ sget-object v$reg, $ref->NON_MEMBER:$ref
+ """.trimIndent(),
+ ExternalLabel("piko", iputObj),
+ )
+ SettingsStatusLoadFingerprint.enableSettings("hideCommBadge")
+ }
+}
diff --git a/src/main/resources/twitter/settings/values/strings.xml b/src/main/resources/twitter/settings/values/strings.xml
index e8798223..a6f597dc 100644
--- a/src/main/resources/twitter/settings/values/strings.xml
+++ b/src/main/resources/twitter/settings/values/strings.xml
@@ -121,6 +121,7 @@
Hides follow/subscribe/follow back buttons on posts
Hide followed by context
Hides followed by context under profile
+ Hide community badges
Customization
@@ -139,6 +140,13 @@
Post font size
Search suggestions to hide
+
+ Logging
+ Log server response
+ Log json responses received from the server in 'Download/Piko'
+ Overwrite response log file
+ Clear existing response log data on launch
+
Backup and restore
Export %s