diff --git a/patches/api/patches.api b/patches/api/patches.api index 91942f4406..2091c7d27b 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -352,6 +352,10 @@ public final class app/revanced/patches/irplus/ad/RemoveAdsPatchKt { public static final fun getRemoveAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/jakdojade/ads/DisableAdsPatchKt { + public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/letterboxd/ads/HideAdsPatchKt { public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/jakdojade/ad/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ad/DisableAdsPatch.kt new file mode 100644 index 0000000000..63ebc9ed2f --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ad/DisableAdsPatch.kt @@ -0,0 +1,36 @@ +package app.revanced.patches.jakdojade.ad + +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val disableAdsPatch = bytecodePatch( + name = "Disable ads", +) { + compatibleWith("com.citynav.jakdojade.pl.android") + + execute { + // Spoof isPremium() to always return true. + // We can do this beacuse Jakdojade Premium's only feature is ad removal. + isPremiumFingerprint.method.returnEarly(true) + + // Spoof Premium renewal date in the UI. + // We need to do the spoofing in order to avoid app crashes when opening profile menu. + getPremiumRenewalDateFingerprint.method.replaceInstructions( + 0, + """ + const-string v0, "" + return-object v0 + """ + ) + // Spoof Premium type. + getGoogleProductFingerprint.method.replaceInstructions( + 0, + """ + sget-object v0, Lcom/citynav/jakdojade/pl/android/billing/output/GoogleProduct;->PREMIUM_YEARLY_V4:Lcom/citynav/jakdojade/pl/android/billing/output/GoogleProduct; + return-object v0 + """ + ) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/jakdojade/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ad/Fingerprints.kt new file mode 100644 index 0000000000..5c1bb21342 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ad/Fingerprints.kt @@ -0,0 +1,42 @@ +package app.revanced.patches.jakdojade.ad + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal val isPremiumFingerprint = fingerprint { + returns("Z") + accessFlags(AccessFlags.PUBLIC) + parameters() + opcodes( + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + ) +} + +internal val getPremiumRenewalDateFingerprint = fingerprint { + returns("Ljava/lang/String;") + accessFlags(AccessFlags.PUBLIC) + parameters() + opcodes( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + ) +} + +internal val getGoogleProductFingerprint = fingerprint { + returns("Lcom/citynav/jakdojade/pl/android/billing/output/GoogleProduct;") + accessFlags(AccessFlags.PUBLIC) + parameters("Lcom/citynav/jakdojade/pl/android/profiles/ui/profile/userprofile/model/PremiumType;") +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/jakdojade/ads/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ads/DisableAdsPatch.kt new file mode 100644 index 0000000000..b1f223ed94 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ads/DisableAdsPatch.kt @@ -0,0 +1,30 @@ +package app.revanced.patches.jakdojade.ads + +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val disableAdsPatch = bytecodePatch( + name = "Disable ads", +) { + compatibleWith("com.citynav.jakdojade.pl.android") + + execute { + // Spoof isPremium() to always return true. + // We can do this beacuse Jakdojade Premium's only feature is ad removal. + isPremiumFingerprint.method.returnEarly(true) + + // Spoof Premium renewal date in the UI. + // We need to do the spoofing in order to avoid app crashes when opening profile menu. + getPremiumRenewalDateFingerprint.method.returnEarly("") + // Spoof Premium type. + getGoogleProductFingerprint.method.replaceInstructions( + 0, + """ + sget-object v0, Lcom/citynav/jakdojade/pl/android/billing/output/GoogleProduct;->PREMIUM_YEARLY_V4:Lcom/citynav/jakdojade/pl/android/billing/output/GoogleProduct; + return-object v0 + """ + ) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/jakdojade/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ads/Fingerprints.kt new file mode 100644 index 0000000000..560eb80a40 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/jakdojade/ads/Fingerprints.kt @@ -0,0 +1,42 @@ +package app.revanced.patches.jakdojade.ads + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal val isPremiumFingerprint = fingerprint { + returns("Z") + accessFlags(AccessFlags.PUBLIC) + parameters() + opcodes( + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + ) +} + +internal val getPremiumRenewalDateFingerprint = fingerprint { + returns("Ljava/lang/String;") + accessFlags(AccessFlags.PUBLIC) + parameters() + opcodes( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + ) +} + +internal val getGoogleProductFingerprint = fingerprint { + returns("Lcom/citynav/jakdojade/pl/android/billing/output/GoogleProduct;") + accessFlags(AccessFlags.PUBLIC) + parameters("Lcom/citynav/jakdojade/pl/android/profiles/ui/profile/userprofile/model/PremiumType;") +} \ No newline at end of file