Snapchat Plus bug fixes
This commit is contained in:
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user