From 58705f3f0e7e0c80a7fd93e58af7eed94e0e01d5 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:42:18 +0900 Subject: [PATCH] fix(YouTube/Return YouTube Dislike): add support for RollingNumber --- .../general/ReturnYouTubeDislikePatch.kt | 5 +- .../ReturnYouTubeDislikeRollingNumberPatch.kt | 120 ++++++++++++++++++ .../RollingNumberTextViewFingerprint.kt | 26 ++++ .../RollingNumberTypeFingerprint.kt | 16 +++ .../youtube/utils/settings/SettingsPatch.kt | 2 + 5 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTextViewFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTypeFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt index c4db2da0d..a57cfaffa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt @@ -3,7 +3,6 @@ package app.revanced.patches.youtube.utils.returnyoutubedislike.general import app.revanced.extensions.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction @@ -11,8 +10,6 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.misc.spoofappversion.SpoofAppVersionPatch import app.revanced.patches.youtube.utils.litho.LithoFilterPatch import app.revanced.patches.youtube.utils.playerresponse.PlayerResponsePatch import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.DislikeFingerprint @@ -24,6 +21,7 @@ import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerpri import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentContextFingerprint import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentTmpFingerprint import app.revanced.patches.youtube.utils.returnyoutubedislike.oldlayout.ReturnYouTubeDislikeOldLayoutPatch +import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.ReturnYouTubeDislikeRollingNumberPatch import app.revanced.patches.youtube.utils.returnyoutubedislike.shorts.ReturnYouTubeDislikeShortsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch @@ -42,6 +40,7 @@ import com.android.tools.smali.dexlib2.iface.reference.Reference LithoFilterPatch::class, PlayerResponsePatch::class, ReturnYouTubeDislikeOldLayoutPatch::class, + ReturnYouTubeDislikeRollingNumberPatch::class, ReturnYouTubeDislikeShortsPatch::class, SettingsPatch::class, VideoIdPatch::class diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt new file mode 100644 index 000000000..2a6d85222 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt @@ -0,0 +1,120 @@ +package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber + +import app.revanced.extensions.exception +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchException +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberTextViewFingerprint +import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberTypeFingerprint +import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.integrations.Constants.UTILS_PATH +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +@Patch(dependencies = [SettingsPatch::class]) +object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( + setOf( + RollingNumberTextViewFingerprint, + RollingNumberTypeFingerprint + ) +) { + private const val CONVERSION_CONTEXT_PARAMETER = 2 + + private const val INTEGRATIONS_RYD_CLASS_DESCRIPTOR = + "$UTILS_PATH/ReturnYouTubeDislikePatch;" + + override fun execute(context: BytecodeContext) { + /** + * RollingNumber is applied to YouTube v18.41.39+. + * + * In order to maintain compatibility with YouTube v18.40.34 or previous versions, + * This patch is applied only to the version after YouTube v18.41.39 + * + * Resolves following issue: + * https://github.com/revanced/revanced-patches/issues/2904 + */ + if (SettingsPatch.upward1841) { + + RollingNumberTypeFingerprint.result?.let { + it.mutableMethod.apply { + val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex + val rollingNumberClassReference = + getInstruction(rollingNumberClassIndex).reference + val rollingNumberClass = + context.findClass(rollingNumberClassReference.toString())!!.mutableClass + + /** + * This class handles RollingNumber. + * Pass an instance of this class to integrations to use Java Reflection. + */ + rollingNumberClass.methods.find { method -> method.name == "" } + ?.apply { + val rollingNumberFieldIndex = + implementation!!.instructions.indexOfFirst { instruction -> + instruction.opcode == Opcode.IPUT_OBJECT + } + val rollingNumberFieldName = + (getInstruction(rollingNumberFieldIndex).reference as FieldReference).name + + addInstructions( + 1, """ + const-string v0, "$rollingNumberFieldName" + invoke-static {p0, v0}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;Ljava/lang/String;)V + """ + ) + } ?: throw PatchException("RollingNumberClass not found!") + + /** + * RollingNumber is initialized in this method. + * This method also contains information about ConversionContext. + */ + addInstruction( + 1, + "invoke-static {p$CONVERSION_CONTEXT_PARAMETER}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberTextLoaded(Ljava/lang/Object;)V" + ) + } + } ?: throw RollingNumberTypeFingerprint.exception + + /** + * TextView with RollingNumber. + * Apply spanned text to TextView. + */ + RollingNumberTextViewFingerprint.result?.let { + // Initial TextView is set in this method. + val initiallyCreatedTextViewMethod = it.mutableMethod + + // Video less than 24 hours after uploaded, like counts will be updated in real time. + // Whenever like counts are updated, TextView is set in this method. + val realTimeUpdateTextViewMethod = it.mutableClass.methods.find { + method -> method.parameterTypes.first() == "Landroid/graphics/Bitmap;" + } ?: throw PatchException("Failed to find realTimeUpdateTextViewMethod") + + arrayOf( + initiallyCreatedTextViewMethod, + realTimeUpdateTextViewMethod + ).forEach { insertMethod -> + insertMethod.apply { + val setTextIndex = implementation!!.instructions.indexOfFirst { instruction -> + ((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.name == "setText" + } + val textViewRegister = + getInstruction(setTextIndex).registerC + + addInstruction( + setTextIndex + 1, + "invoke-static {v$textViewRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumberTextView(Landroid/widget/TextView;)V" + ) + } + } + } ?: throw RollingNumberTextViewFingerprint.exception + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTextViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTextViewFingerprint.kt new file mode 100644 index 000000000..0af040cca --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTextViewFingerprint.kt @@ -0,0 +1,26 @@ +package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +/** + * This fingerprint is compatible with YouTube v18.32.39+ + */ +object RollingNumberTextViewFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("L", "F", "F"), + opcodes = listOf( + Opcode.IPUT, + null, // invoke-direct or invoke-virtual + Opcode.IPUT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.RETURN_VOID + ), + customFingerprint = custom@{ _, classDef -> + classDef.methods.count() == 4 + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTypeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTypeFingerprint.kt new file mode 100644 index 000000000..785e98933 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberTypeFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +/** + * This fingerprint is compatible with YouTube v18.29.38+ + */ +object RollingNumberTypeFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.CHECK_CAST, + Opcode.IGET, + Opcode.AND_INT_LIT8 + ), + strings = listOf("RollingNumberType required properties missing! Need updateCount, fontName, color and fontSize.") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt index fb3999e95..b3cec0f61 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt @@ -92,6 +92,7 @@ object SettingsPatch : AbstractSettingsResourcePatch( is1836 = playServicesVersion in 233700000..233801999 upward1828 = 232900000 <= playServicesVersion upward1834 = 233502000 <= playServicesVersion + upward1841 = 234200000 <= playServicesVersion break } @@ -201,6 +202,7 @@ object SettingsPatch : AbstractSettingsResourcePatch( internal var is1836: Boolean = false internal var upward1828: Boolean = false internal var upward1834: Boolean = false + internal var upward1841: Boolean = false internal fun addPreference(settingArray: Array) { contexts.addPreference(settingArray)