Core MTProxy resilience improvements: - Implement 45s negative DNS cache to prevent rapid retry storms on NXDOMAIN/timeout - Detect and reject 0.0.0.0 (IPv4) and :: (IPv6) blocked zero addresses from DNS resolvers - Add resetTransportSocketForOpenConnection() to safely tear down stale sockets before new connection - Enhance secret domain sanitization with better error classification (control chars vs invalid domain) - Add pre-handshake DNS preflight check via isHostResolveNegativeCached() JNI Plugin system expansion: - Add pre_request_hook for request modification before send - Add on_send_message_hook for outgoing message interception - Add on_update/on_updates_hook for incoming update inspection - Add app lifecycle hooks (start/stop/pause/resume) - Add menu item system for plugin UI integration - Refactor extera_utils to package with DexMaker class-proxy stubs Proxy UX improvements: - Manual proxy list reordering (drag-and-drop, no auto-sort by ping) - Add diagnostic strings for new DNS failure phases - Proxy health store now treats invalid-secret domains as punitive failures requiring rotation Audio & maintenance: - Set voice recording bitrate to 16 kbps (explicit, not OPUS_BITRATE_MAX) - Enable VBR and voice signal hint for better speech compression - Fix DialogsActivity AppName to use local resources, bypassing cloud strings - Add guards for DNS resolver fallback chain, voice bitrate, and main title brand
74 lines
2 KiB
Python
74 lines
2 KiB
Python
#!/usr/bin/env python3
|
|
from pathlib import Path
|
|
import re
|
|
import sys
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
AUDIO_C = ROOT / "TMessagesProj/jni/audio.c"
|
|
|
|
|
|
def read(path: Path) -> str:
|
|
return path.read_text(encoding="utf-8", errors="replace")
|
|
|
|
|
|
def require(condition: bool, message: str, failures: list[str]) -> None:
|
|
if not condition:
|
|
failures.append(message)
|
|
|
|
|
|
def main() -> int:
|
|
failures: list[str] = []
|
|
audio_c = read(AUDIO_C)
|
|
|
|
bitrate_match = re.search(
|
|
r"const\s+opus_int32\s+voice_record_bitrate\s*=\s*(\d+)\s*;",
|
|
audio_c,
|
|
)
|
|
require(
|
|
bitrate_match is not None,
|
|
"audio.c must define an explicit voice_record_bitrate for voice notes",
|
|
failures,
|
|
)
|
|
if bitrate_match is not None:
|
|
bitrate = int(bitrate_match.group(1))
|
|
require(
|
|
12000 <= bitrate <= 24000,
|
|
"voice_record_bitrate must stay in the compact speech range of 12-24 kbps",
|
|
failures,
|
|
)
|
|
|
|
require(
|
|
"OPUS_SET_BITRATE(OPUS_BITRATE_MAX)" not in audio_c
|
|
and "bitrate = OPUS_BITRATE_MAX" not in audio_c,
|
|
"voice recorder must not ask Opus for OPUS_BITRATE_MAX",
|
|
failures,
|
|
)
|
|
require(
|
|
"OPUS_SET_BITRATE(voice_record_bitrate)" in audio_c,
|
|
"initRecorder() must apply voice_record_bitrate to the Opus encoder",
|
|
failures,
|
|
)
|
|
require(
|
|
"OPUS_SET_VBR(1)" in audio_c,
|
|
"voice recorder must keep Opus VBR enabled for compact speech",
|
|
failures,
|
|
)
|
|
require(
|
|
"OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)" in audio_c,
|
|
"voice recorder must explicitly bias Opus toward voice",
|
|
failures,
|
|
)
|
|
|
|
if failures:
|
|
print("Voice recording bitrate guard failed:", file=sys.stderr)
|
|
for failure in failures:
|
|
print(f" - {failure}", file=sys.stderr)
|
|
return 1
|
|
|
|
print("Voice recording bitrate guard passed.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|