58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
"""Shared workspace paths and text normalization."""
|
|
import os
|
|
import sys
|
|
import unicodedata
|
|
from pathlib import Path
|
|
|
|
_BUNDLE = getattr(sys, '_whatsapp_bundle', None)
|
|
BASE = Path(_BUNDLE['base']) if _BUNDLE else Path(__file__).resolve().parent.parent
|
|
ASSETS = Path(__file__).resolve().parent / "assets"
|
|
PROFILE = Path(os.environ.get("LOCALAPPDATA", str(Path.home() / "AppData/Local"))) / "Packages/5319275A.WhatsAppDesktop_cv1g1gvanyjgm/LocalCache/EBWebView/Default"
|
|
|
|
def normalized(value):
|
|
return unicodedata.normalize('NFC', value).casefold()
|
|
|
|
|
|
def resource_bytes(name):
|
|
"""Read an embedded bundle resource or its development-tree equivalent."""
|
|
if _BUNDLE:
|
|
return _BUNDLE['read'](name)
|
|
return (BASE / name).read_bytes()
|
|
|
|
|
|
def asset_bytes(name):
|
|
return resource_bytes('whatsapp_suite/assets/' + name)
|
|
|
|
|
|
def cli_command(*arguments):
|
|
if _BUNDLE:
|
|
return [sys.executable, str(_BUNDLE['launcher']), *arguments]
|
|
return [sys.executable, '-m', 'whatsapp_suite', *arguments]
|
|
|
|
|
|
def verified_helper(asset, digest, cache_dir, filename):
|
|
"""Materialize a hash-verified DLL only when a live probe needs it."""
|
|
import ctypes
|
|
import hashlib
|
|
import tempfile
|
|
if os.name != 'nt' or ctypes.sizeof(ctypes.c_void_p) != 8:
|
|
raise ValueError('Native helpers require Windows and 64-bit Python')
|
|
payload = asset_bytes(asset)
|
|
if hashlib.sha256(payload).hexdigest() != digest:
|
|
raise ValueError('Bundled helper failed SHA-256 verification')
|
|
folder = BASE / cache_dir / digest
|
|
folder.mkdir(parents=True, exist_ok=True)
|
|
dll = folder / filename
|
|
existed = dll.exists()
|
|
if existed and hashlib.sha256(dll.read_bytes()).hexdigest() == digest:
|
|
return dll, 'reused'
|
|
descriptor, temporary = tempfile.mkstemp(prefix='helper-', suffix='.tmp', dir=folder)
|
|
try:
|
|
with os.fdopen(descriptor, 'wb') as stream:
|
|
stream.write(payload)
|
|
os.replace(temporary, dll)
|
|
finally:
|
|
Path(temporary).unlink(missing_ok=True)
|
|
return dll, 'repaired' if existed else 'extracted'
|
|
|