Files
kefu/deploy/my-customers-20260918/audit_customer_schema.py
T
2026-09-21 10:34:06 +08:00

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))