Snapchat Plus bug fixes

This commit is contained in:
DarkKnight2122
2026-04-25 04:36:36 +05:30
parent d19257869b
commit 347115f8d3
3 changed files with 47 additions and 54 deletions

View File

@@ -47,7 +47,7 @@ class EventDispatcher(
cacheHook( cacheHook(
methodParam.thisObject<Any>()::class.java methodParam.thisObject<Any>()::class.java
) { ) {
hook(bindMethod.get().toString(), HookStage.BEFORE) bindViewMethod@{ param -> hook(bindMethod.get().toString(), HookStage.AFTER) bindViewMethod@{ param ->
val instance = param.thisObject<Any>() val instance = param.thisObject<Any>()
val view = instance::class.java.methods.firstOrNull { val view = instance::class.java.methods.firstOrNull {
it.name == getViewMethod.get().toString() it.name == getViewMethod.get().toString()
@@ -161,7 +161,6 @@ class EventDispatcher(
adapter = param adapter = param
} }
) { ) {
if (canceled) param.setResult(null)
postHookEvent() postHookEvent()
} }
} }

View File

@@ -17,67 +17,59 @@ class SnapchatPlus: Feature("SnapchatPlus") {
override fun init() { override fun init() {
val snapchatPlusTier = context.config.global.snapchatPlus.getNullable() val snapchatPlusTier = context.config.global.snapchatPlus.getNullable()
if (snapchatPlusTier == null || snapchatPlusTier == "not_subscribed") return
if (snapchatPlusTier != null) { // Pre-calculate custom purchase date to eliminate main thread lag
context.mappings.useMapper(PlusSubscriptionMapper::class) { val customPurchaseDateRaw = context.config.global.snapchatPlusPurchaseDate.get().trim()
classReference.get()?.hookConstructor(HookStage.AFTER) { param -> val customPurchaseDateMillis = if (customPurchaseDateRaw.isNotEmpty()) {
param.thisObject<Any>().dataBuilder { runCatching {
//subscription tier LocalDate.parse(customPurchaseDateRaw, DateTimeFormatter.ISO_LOCAL_DATE)
if (get<Any>(tierField.getAsString()!!)?.javaClass?.isEnum == true) { .atStartOfDay(ZoneId.systemDefault())
set(tierField.getAsString()!!, when (snapchatPlusTier) { .toInstant()
"not_subscribed" -> "NO_ACCESS" .toEpochMilli()
"basic" -> "SNAPCHAT_PLUS" }.getOrNull()
"ad_free" -> "SNAPCHAT_PLUS_AD_FREE" } else (System.currentTimeMillis() - 7776000000L) // 3 months fallback
else -> "SNAPCHAT_PLUS"
})
} else {
set(tierField.getAsString()!!, when (snapchatPlusTier) {
"not_subscribed" -> 1
"basic" -> 2
"ad_free" -> 3
else -> 2
})
}
//subscription status context.mappings.useMapper(PlusSubscriptionMapper::class) {
set(statusField.getAsString()!!, 2) classReference.get()?.hookConstructor(HookStage.AFTER) { param ->
param.thisObject<Any>().dataBuilder {
val fallbackOriginalSubscriptionTime = System.currentTimeMillis() - 7776000000L //subscription tier
val customPurchaseDate = context.config.global.snapchatPlusPurchaseDate.get().trim() if (get<Any>(tierField.getAsString()!!)?.javaClass?.isEnum == true) {
val customPurchaseDateMillis = if (customPurchaseDate.isNotEmpty()) { set(tierField.getAsString()!!, when (snapchatPlusTier) {
runCatching { "not_subscribed" -> "NO_ACCESS"
LocalDate "basic" -> "SNAPCHAT_PLUS"
.parse(customPurchaseDate, DateTimeFormatter.ISO_LOCAL_DATE) "ad_free" -> "SNAPCHAT_PLUS_AD_FREE"
.atStartOfDay(ZoneId.systemDefault()) else -> "SNAPCHAT_PLUS"
.toInstant() })
.toEpochMilli() } else {
}.getOrNull() set(tierField.getAsString()!!, when (snapchatPlusTier) {
} else { "not_subscribed" -> 1
null "basic" -> 2
} "ad_free" -> 3
else -> 2
set( })
originalSubscriptionTimeMillisField.getAsString()!!,
customPurchaseDateMillis ?: fallbackOriginalSubscriptionTime
)
set(expirationTimeMillisField.getAsString()!!, expirationTimeMillis)
} }
//subscription status
set(statusField.getAsString()!!, 2)
set(
originalSubscriptionTimeMillisField.getAsString()!!,
customPurchaseDateMillis
)
set(expirationTimeMillisField.getAsString()!!, expirationTimeMillis)
} }
} }
} }
// Force enable all premium features in the catalog
if (context.config.experimental.hiddenSnapchatPlusFeatures.get()) { if (context.config.experimental.hiddenSnapchatPlusFeatures.get()) {
findClass("com.snap.plus.FeatureCatalog").methods.last { runCatching {
!it.name.contains("init") && val featureCatalogClass = findClass("com.snap.plus.FeatureCatalog")
it.parameterTypes.isNotEmpty() && featureCatalogClass.hook("isFeatureEnabled", HookStage.BEFORE) { param ->
it.parameterTypes[0].name != "java.lang.Boolean" param.setResult(true)
}.hook(HookStage.BEFORE) { param ->
val instance = param.thisObject<Any>()
val firstArg = param.argNullable<Any>(0) ?: return@hook
instance.findFieldNamesByType(firstArg::class.java).forEach { fieldName ->
instance.setObjectField(fieldName, firstArg)
} }
context.log.verbose("Successfully unlocked premium Snapchat features")
} }
} }
} }

View File

@@ -137,6 +137,8 @@ fun View.onAttachChange(onAttach: (View.OnAttachStateChangeListener) -> Unit = {
fun View.hideViewCompletely() { fun View.hideViewCompletely() {
fun hide() { fun hide() {
if (visibility == View.GONE && layoutParams?.width == 0 && layoutParams?.height == 0) return
isEnabled = false isEnabled = false
visibility = View.GONE visibility = View.GONE
setWillNotDraw(true) setWillNotDraw(true)