From ceb3b9af3eb310b2945c622fa7214cecba8e9b6d Mon Sep 17 00:00:00 2001
From: Claude
Date: Wed, 16 Sep 2026 14:37:37 +0000
Subject: [PATCH] Retire the last references to the deleted legacy Xposed path
Dropping the API 93 entry left its traces behind in places that still
claimed it shipped. The README compatibility table was the one that
mattered: it advertised LSPosed 1.9.x, EdXposed and LSPatch as supported
and pointed them at assets/xposed_init -> MainHook, so a user on one of
those frameworks would install the module and get nothing, with the docs
insisting it should work. It now states plainly that those are not
supported and why.
The rest were stale in the same direction:
proguard-rules.pro kept com.my.televip.MainHook, a class that no
longer exists - a no-op rule that reads as if the
legacy entry still needed protecting
module.prop promised a fallback to assets/xposed_init for
frameworks that cannot read it; there is no
fallback, they simply will not load TeleVip
TeleVipModule javadoc said the legacy entry was "still shipped"
CHANGELOG documented 3.7.0 as shipping two entry points and
listed LegacyBackend; 3.7.0 is unreleased (latest
tag is 3.6.2), so it now describes what will
actually ship, and the Nekogram X entry points at
scope.list rather than the deleted xposedscope array
Verified the scope migration was faithful while here: all 22 packages
from the removed values/arrays.xml are present in
META-INF/xposed/scope.list, nekox.messenger included.
Also bumps the verified build for official Telegram to 12.10.1 (70382).
Every symbol the module resolves by name was checked against Telegram's
current source and none had changed - TLRPC.Message fields, readAttachPath
and TLdeserialize, TL_messages_readHistory, TL_channels_readHistory,
TL_messages_affectedMessages, TL_updateDeleteMessages, the
MessagesController, ConnectionsManager and UserConfig accessors, and
PeerStoriesView$StoryItemHolder#allowScreenshots - so no hook needed
updating and the pin was simply behind. The bracketed number is
PackageInfo.versionCode, which Telegram builds as code * 10 + channel
(1/2 store, 9 direct), so 7038 -> 70382; that encoding is now documented
next to the map since it is otherwise unreadable.
Co-Authored-By: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01JfCFkZp4NiGPGjTKwchmxj
---
CHANGELOG.md | 24 +++++++++++--------
README.md | 8 +++----
app/proguard-rules.pro | 3 ---
.../java/com/my/televip/ClientChecker.java | 7 +++++-
.../com/my/televip/xposed/ModernBackend.java | 2 +-
.../com/my/televip/xposed/TeleVipModule.java | 6 ++---
.../resources/META-INF/xposed/module.prop | 4 ++--
7 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40a2061..6e8181f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,22 +4,21 @@
### Modern Xposed API (libxposed 102)
-TeleVip now ships **two entry points in one APK** and runs on whichever contract the installed
-framework activates:
+TeleVip is now a **libxposed API 102 module**, loaded through a single modern entry point:
| Entry | Descriptor | Class |
|---|---|---|
| Modern (API 102) | `META-INF/xposed/java_init.list` + `module.prop` | `com.my.televip.xposed.TeleVipModule` |
-| Legacy (API 93) | `assets/xposed_init` | `com.my.televip.MainHook` |
-Both funnel into `com.my.televip.xposed.ModuleEntry#attach`, which is guarded so activating both
-can never double-hook.
+It funnels into `com.my.televip.xposed.ModuleEntry#attach`. The legacy API 93 entry
+(`assets/xposed_init` → `MainHook`) was dropped before release: leaving it in place would make
+LSPosed 1.9.x and EdXposed advertise the module and then fail at load time, because there is no
+longer a `de.robv` entry class for them to find.
New compatibility layer under `com.my.televip.xposed`:
- **`XBridge`** — the only seam to the framework: hooking, logging, module APK path, deoptimize,
framework name/version. Everything else in the module goes through it.
-- **`LegacyBackend`** — adapts to `de.robv.android.xposed.XposedBridge` / `XC_MethodHook`.
- **`ModernBackend`** — adapts to `XposedInterface.hook(Executable).intercept(Hooker)`. API 102
replaced the before/after pair with an OkHttp-style interceptor chain, so the adapter rebuilds
classic semantics on top of `Chain`: a result set in `beforeMethod` short-circuits the chain
@@ -49,19 +48,24 @@ the same best-match argument resolution (exact match → boxing → primitive wi
- Language packs moved from `assets/lang/` to `src/main/resources/lang/` and are read straight off
the module class loader — no APK path needed at all. The old ZIP scan is kept as a fallback and
still auto-discovers packs the index does not list.
-- `Logger` routes through `XBridge`, so logging works on both backends and degrades to
- `android.util.Log` if no backend is installed yet.
+- `Logger` routes through `XBridge` and degrades to `android.util.Log` if no backend is
+ installed yet.
- Startup now logs the active backend, framework name and version.
### Nekogram
- **Nekogram X added** (`nekox.messenger`): new `Clients/NekogramX.java` resolver, `ClientType`
- entry and `xposedscope` item. Like its Momogram fork, NekoX ships unobfuscated Telegram symbols,
- so the mapping tables are empty and names resolve to upstream Telegram names.
+ entry and `META-INF/xposed/scope.list` item. Like its Momogram fork, NekoX ships unobfuscated
+ Telegram symbols, so the mapping tables are empty and names resolve to upstream Telegram names.
- **Version drift is now visible.** `ClientChecker#checkClientVersion` records the build each
resolver table was generated against and logs one clear warning at startup when the installed
client differs — loud for the obfuscated clients (Nekogram, Cherrygram), where a mismatch means
essentially every hook silently fails.
+- **Official Telegram re-verified against 12.10.1** (build 70382). The symbols the module resolves
+ by name — `TLRPC.Message` fields, `TL_messages_readHistory` / `TL_channels_readHistory`,
+ `TL_updateDeleteMessages`, `MessagesController` / `ConnectionsManager` / `UserConfig` accessors
+ and `PeerStoriesView$StoryItemHolder#allowScreenshots` — are unchanged from the previously
+ verified build, so no hook needed updating.
> The Nekogram/Cherrygram R8 mapping tables themselves still have to be regenerated from the target
> APK whenever those clients update; that cannot be done from source.
diff --git a/README.md b/README.md
index 7ac1b78..112c7cd 100755
--- a/README.md
+++ b/README.md
@@ -80,14 +80,14 @@ A powerful Xposed module that adds advanced customization features to Telegram c
# 🧩 Supported frameworks
-TeleVip ships **two entry points** and uses whichever one the installed framework activates, so a
-single APK covers both the old and the new Xposed module contracts.
+TeleVip is a **libxposed API 102 module only**. It declares `minApiVersion=102`, so frameworks that
+implement the modern contract load it and older ones do not advertise it at all.
| Framework | Module API | Entry point |
|---|---|---|
| Vector 2.2+ (JingMatrix) | 102 (modern libxposed) | `META-INF/xposed/java_init.list` → `com.my.televip.xposed.TeleVipModule` |
-| LSPosed 1.10+ | 100/102 (modern libxposed) | same as above |
-| LSPosed (older), EdXposed, LSPatch | 93 (legacy) | `assets/xposed_init` → `com.my.televip.MainHook` |
+| LSPosed 1.10+ | 102 (modern libxposed) | same as above |
+| LSPosed 1.9.x, EdXposed, LSPatch | 93 (legacy) | **not supported** — the legacy `assets/xposed_init` entry was removed |
Zygisk providers: **Zygisk Next / NeoZygisk**, Magisk built-in Zygisk and KernelSU are all supported —
the module talks to the Xposed framework only through `com.my.televip.xposed.XBridge` and never
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 59c42c4..68b8329 100755
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -21,9 +21,6 @@
#-renamesourcefileattribute SourceFile
# --- Xposed -------------------------------------------------------------------
-# Legacy entry point, referenced by name from assets/xposed_init.
--keep class com.my.televip.MainHook { *; }
-
# Modern libxposed entry point, referenced by name from META-INF/xposed/java_init.list.
-dontwarn io.github.libxposed.annotation.**
-adaptresourcefilecontents META-INF/xposed/java_init.list
diff --git a/app/src/main/java/com/my/televip/ClientChecker.java b/app/src/main/java/com/my/televip/ClientChecker.java
index 828940a..e0622df 100755
--- a/app/src/main/java/com/my/televip/ClientChecker.java
+++ b/app/src/main/java/com/my/televip/ClientChecker.java
@@ -33,11 +33,16 @@ public static boolean isTgnetObfuscated()
* R8 name, and those names change on every client release. When the installed build differs
* from the one below, the module used to fail silently with a stream of "Not found ..." lines;
* {@link #checkClientVersion} now says so once, up front.
+ *
+ * The number in brackets is {@code PackageInfo.versionCode}. Telegram encodes its build
+ * code and distribution channel in it as {@code code * 10 + channel}, where 1 and 2 are the
+ * store bundles and 9 is the direct/web APK — so 70382 is build 7038 (12.10.1) from the
+ * Play Store.
*/
private static final Map VERIFIED_BUILD = new EnumMap<>(ClientType.class);
static {
- VERIFIED_BUILD.put(ClientType.Telegram, "12.8.3 (69222)");
+ VERIFIED_BUILD.put(ClientType.Telegram, "12.10.1 (70382)");
VERIFIED_BUILD.put(ClientType.TelegramBeta, "12.9.0 (69579)");
VERIFIED_BUILD.put(ClientType.TelegramWeb, "12.8.3 (69229)");
VERIFIED_BUILD.put(ClientType.TelegramPlus, "12.8.1.0 (22350)");
diff --git a/app/src/main/java/com/my/televip/xposed/ModernBackend.java b/app/src/main/java/com/my/televip/xposed/ModernBackend.java
index 31008f7..9e2e4dd 100644
--- a/app/src/main/java/com/my/televip/xposed/ModernBackend.java
+++ b/app/src/main/java/com/my/televip/xposed/ModernBackend.java
@@ -12,7 +12,7 @@
import io.github.libxposed.api.XposedInterfaceWrapper;
/**
- * Backend for the modern libxposed API (100 / 102), i.e. current LSPosed and Vector 2.2.
+ * Backend for the modern libxposed API 102, i.e. current LSPosed and Vector 2.2.
*
* API 102 replaced the before/after callback pair with an OkHttp-style interceptor chain. The
* adapter below rebuilds the classic semantics on top of it:
diff --git a/app/src/main/java/com/my/televip/xposed/TeleVipModule.java b/app/src/main/java/com/my/televip/xposed/TeleVipModule.java
index 2c2ace2..8d4803f 100644
--- a/app/src/main/java/com/my/televip/xposed/TeleVipModule.java
+++ b/app/src/main/java/com/my/televip/xposed/TeleVipModule.java
@@ -4,11 +4,11 @@
import io.github.libxposed.api.XposedModuleInterface;
/**
- * Modern entry point (libxposed API 100 / 102).
+ * Modern entry point (libxposed API 102).
*
* Registered through {@code META-INF/xposed/java_init.list}. Used by current LSPosed and by
- * Vector 2.2 running on Zygisk Next / NeoZygisk. The legacy {@code assets/xposed_init} entry is
- * still shipped for older frameworks; whichever the host picks, both land in
+ * Vector 2.2 running on Zygisk Next / NeoZygisk. This is the module's only entry point — the
+ * legacy {@code assets/xposed_init} path was removed — and it lands in
* {@link ModuleEntry#attach}.
*
* Per the API contract nothing is initialised in the constructor — the framework attaches itself
diff --git a/app/src/main/resources/META-INF/xposed/module.prop b/app/src/main/resources/META-INF/xposed/module.prop
index f082a9d..7917377 100644
--- a/app/src/main/resources/META-INF/xposed/module.prop
+++ b/app/src/main/resources/META-INF/xposed/module.prop
@@ -1,6 +1,6 @@
# Modern Xposed module descriptor (libxposed API).
-# Read by LSPosed 1.10+ and Vector 2.2. Frameworks that do not understand this file
-# fall back to assets/xposed_init + the xposedminversion meta-data (module API 93).
+# Read by LSPosed 1.10+ and Vector 2.2. This is the module's only descriptor: the legacy
+# API 93 path was removed, so a framework that cannot read this file will not load TeleVip.
minApiVersion=102
targetApiVersion=102
staticScope=false