44 lines
3.0 KiB
Python
44 lines
3.0 KiB
Python
"""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))
|