"""Read only existing decrypted caches; output schema and aggregates only.""" import json, re, sqlite3, sys, time from pathlib import Path from datetime import datetime ROOT=Path('C:/wechat_rpa') OUT=Path('C:/kefu/deploy/my-customers-20260918') sys.dont_write_bytecode=True sys.path.insert(0,str(ROOT)) import review_assistant_contacts as contacts active=contacts.active_context() account=str(active.get('account_id') or '') roots=[ROOT/'wxwork_reply_cache',ROOT/'archive_auto_backup/decrypted',ROOT/'wxwork_decrypted'] accounts=sorted({p.name for r in roots for p in r.iterdir() if p.is_dir() and re.fullmatch(r'\d+',p.name)}) labels={a:('current-account' if a==account else 'other-account-'+str(i+1)) for i,a in enumerate(accounts)} result={'active_ready':bool(active.get('ready')),'active_reason':str(active.get('reason') or ''),'accounts':list(labels.values()),'databases':[]} for acct in accounts: for root in roots: for name in ('user.db','user_extend.db','session.db','company.db','message_lookup.db','message.db'): path=root/acct/name if not path.is_file():continue entry={'account':labels[acct],'cache':str(root.relative_to(ROOT)).replace('\\','/'),'database':name,'bytes':path.stat().st_size,'modified':datetime.fromtimestamp(contacts._modified(path)/1e9).isoformat(timespec='seconds'),'tables':{}} conn=None try: conn=sqlite3.connect(path.resolve().as_uri()+'?mode=ro',uri=True,timeout=3) conn.execute('PRAGMA query_only=ON');conn.execute('BEGIN') names=[r[0] for r in conn.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")] entry['table_names']=names for table in names: if name=='message.db' and table!='message_table':continue if name not in ('message.db','session.db') and not re.search(r'user|external|relation|customer|contact|friend|follow|client|service',table,re.I):continue if name=='session.db' and table!='conversation_table':continue quoted='"'+table.replace('"','""')+'"' columns=[{'name':r[1],'type':r[2],'pk':r[5]} for r in conn.execute('PRAGMA table_info('+quoted+')')] info={'columns':columns,'count':conn.execute('SELECT count(*) FROM '+quoted).fetchone()[0]} entry['tables'][table]=info except Exception as exc:entry['error']=type(exc).__name__+': '+str(exc) finally: if conn is not None:conn.close() result['databases'].append(entry) OUT.mkdir(parents=True,exist_ok=True) (OUT/'schema-aggregates.json').write_text(json.dumps(result,ensure_ascii=False,indent=2),encoding='utf-8') print(json.dumps({'active_ready':result['active_ready'],'active_reason':result['active_reason'],'accounts':result['accounts'],'databases':[{'account':e['account'],'cache':e['cache'],'database':e['database'],'tables':{t:v['count'] for t,v in e['tables'].items()},'error':e.get('error')} for e in result['databases']]},ensure_ascii=False))