Files
ghostMode/src/hooking.py
T
lyuksovannyyandClaude Opus 5.5 00553970b7
Publish plugin / publish (push) Successful in 5s
[no bump] Ghost Mode: AyuGram's ghost mode with per-account and per-chat settings
Read receipts, story views, typing and online status are held back per
the options; read on interact, scheduled and silent sending as in AyuGram.
Every option resolves chat -> account -> global; forum topics follow
their group. Settings live in the plugin page, a chat/profile menu popup,
and a drawer row for the current account.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 15:54:41 +02:00

57 lines
1.6 KiB
Python

"""Small helpers around the SDK's Xposed hooking and Java threading."""
from hook_utils import find_class
def hook_all(plugin, class_name, method_name, hook):
"""Hooks every overload of `class_name.method_name`; returns the unhook handles."""
clazz = find_class(class_name)
if clazz is None:
plugin.log(f"class not found: {class_name}")
return []
try:
unhooks = plugin.hook_all_methods(clazz, method_name, hook)
except Exception as exc:
plugin.log(f"failed to hook {class_name}.{method_name}: {exc}")
return []
unhooks = list(unhooks or [])
if not unhooks:
plugin.log(f"no overloads hooked for {class_name}.{method_name}")
return unhooks
def unhook_all(plugin, handles):
for handle in handles:
try:
plugin.unhook_method(handle)
except Exception:
pass
del handles[:]
def field(obj, name, default=None):
"""A (possibly private) field of a Java object."""
value = getattr(obj, name, None)
if value is not None:
return value
try:
from hook_utils import get_private_field
value = get_private_field(obj, name)
except Exception:
value = None
return default if value is None else value
def on_ui(plugin, fn, delay_ms=0):
"""Runs `fn` on the UI thread; exceptions are logged, not lost."""
from android_utils import run_on_ui_thread
def run():
try:
fn()
except Exception as exc:
plugin.log(f"ui task failed: {exc}")
run_on_ui_thread(run, delay_ms)