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(
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 view = instance::class.java.methods.firstOrNull {
it.name == getViewMethod.get().toString()
@@ -161,7 +161,6 @@ class EventDispatcher(
adapter = param
}
) {
if (canceled) param.setResult(null)
postHookEvent()
}
}

View File

@@ -17,67 +17,59 @@ class SnapchatPlus: Feature("SnapchatPlus") {
override fun init() {
val snapchatPlusTier = context.config.global.snapchatPlus.getNullable()
if (snapchatPlusTier == null || snapchatPlusTier == "not_subscribed") return
if (snapchatPlusTier != null) {
context.mappings.useMapper(PlusSubscriptionMapper::class) {
classReference.get()?.hookConstructor(HookStage.AFTER) { param ->
param.thisObject<Any>().dataBuilder {
//subscription tier
if (get<Any>(tierField.getAsString()!!)?.javaClass?.isEnum == true) {
set(tierField.getAsString()!!, when (snapchatPlusTier) {
"not_subscribed" -> "NO_ACCESS"
"basic" -> "SNAPCHAT_PLUS"
"ad_free" -> "SNAPCHAT_PLUS_AD_FREE"
else -> "SNAPCHAT_PLUS"
})
} else {
set(tierField.getAsString()!!, when (snapchatPlusTier) {
"not_subscribed" -> 1
"basic" -> 2
"ad_free" -> 3
else -> 2
})
}
// Pre-calculate custom purchase date to eliminate main thread lag
val customPurchaseDateRaw = context.config.global.snapchatPlusPurchaseDate.get().trim()
val customPurchaseDateMillis = if (customPurchaseDateRaw.isNotEmpty()) {
runCatching {
LocalDate.parse(customPurchaseDateRaw, DateTimeFormatter.ISO_LOCAL_DATE)
.atStartOfDay(ZoneId.systemDefault())
.toInstant()
.toEpochMilli()
}.getOrNull()
} else (System.currentTimeMillis() - 7776000000L) // 3 months fallback
//subscription status
set(statusField.getAsString()!!, 2)
val fallbackOriginalSubscriptionTime = System.currentTimeMillis() - 7776000000L
val customPurchaseDate = context.config.global.snapchatPlusPurchaseDate.get().trim()
val customPurchaseDateMillis = if (customPurchaseDate.isNotEmpty()) {
runCatching {
LocalDate
.parse(customPurchaseDate, DateTimeFormatter.ISO_LOCAL_DATE)
.atStartOfDay(ZoneId.systemDefault())
.toInstant()
.toEpochMilli()
}.getOrNull()
} else {
null
}
set(
originalSubscriptionTimeMillisField.getAsString()!!,
customPurchaseDateMillis ?: fallbackOriginalSubscriptionTime
)
set(expirationTimeMillisField.getAsString()!!, expirationTimeMillis)
context.mappings.useMapper(PlusSubscriptionMapper::class) {
classReference.get()?.hookConstructor(HookStage.AFTER) { param ->
param.thisObject<Any>().dataBuilder {
//subscription tier
if (get<Any>(tierField.getAsString()!!)?.javaClass?.isEnum == true) {
set(tierField.getAsString()!!, when (snapchatPlusTier) {
"not_subscribed" -> "NO_ACCESS"
"basic" -> "SNAPCHAT_PLUS"
"ad_free" -> "SNAPCHAT_PLUS_AD_FREE"
else -> "SNAPCHAT_PLUS"
})
} else {
set(tierField.getAsString()!!, when (snapchatPlusTier) {
"not_subscribed" -> 1
"basic" -> 2
"ad_free" -> 3
else -> 2
})
}
//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()) {
findClass("com.snap.plus.FeatureCatalog").methods.last {
!it.name.contains("init") &&
it.parameterTypes.isNotEmpty() &&
it.parameterTypes[0].name != "java.lang.Boolean"
}.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)
runCatching {
val featureCatalogClass = findClass("com.snap.plus.FeatureCatalog")
featureCatalogClass.hook("isFeatureEnabled", HookStage.BEFORE) { param ->
param.setResult(true)
}
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 hide() {
if (visibility == View.GONE && layoutParams?.width == 0 && layoutParams?.height == 0) return
isEnabled = false
visibility = View.GONE
setWillNotDraw(true)