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

62 lines
4.1 KiB
Python

import sys,json,re,sqlite3,hashlib,time
from pathlib import Path
from datetime import datetime
from collections import Counter
sys.dont_write_bytecode=True;sys.path.insert(0,'C:/wechat_rpa')
import review_assistant_contacts as contacts
ctx=contacts.active_context();assert ctx['ready'];account=ctx['account_id']
base=Path('C:/Users/isard/AppData/Local/ZhenYangTangRPA')
roots=[base/'wxwork_reply_cache',base/'archive_auto_backup/decrypted',base/'wxwork_decrypted']
out=Path('C:/kefu/deploy/my-customers-20260918');report={'inventory':[]}
for root in roots:
for name in ['user.db','session.db','message.db','user_extend.db']:
p=root/account/name
if not p.is_file():continue
db=contacts._open(p)
try:
tables={r[0] for r in db.execute("SELECT name FROM sqlite_master WHERE type='table'")}
counts={t:db.execute('SELECT count(*) FROM "'+t+'"').fetchone()[0] for t in ['user_table','external_user_relation_v3','external_user_ids','wx_friend','wechat_contactV1','message_table','conversation_table'] if t in tables}
report['inventory'].append({'cache':str(root.relative_to(base)).replace('\\','/'),'database':name,'counts':counts,'modified':datetime.fromtimestamp(contacts._modified(p)/1e9).isoformat(timespec='seconds')})
finally:db.close()
paths=contacts._databases(account,cache_roots=roots)
u=contacts._open(paths['user.db']);s=contacts._open(paths['session.db']);m=contacts._open(paths['message.db'])
try:
relations={str(r[0]):(r[1],r[2],r[3]) for r in u.execute('SELECT user_id,status,stranger_type,add_customer_time FROM external_user_relation_v3')}
external={str(r[0]) for r in u.execute('SELECT value FROM external_user_ids')}
convs={str(r[0]) for r in s.execute('SELECT id FROM conversation_table')}
msgs={str(r[0]) for r in m.execute('SELECT DISTINCT conversation_id FROM message_table')}
report['selected']={name:str(path.parent.parent.relative_to(base)).replace('\\','/') for name,path in paths.items()}
report['relations']={'count':len(relations),'status_distribution':dict(Counter(str(v[0]) for v in relations.values())),'stranger_distribution':dict(Counter(str(v[1]) for v in relations.values())),'positive_add_customer_time':sum(bool(v[2]) and v[2]>0 for v in relations.values()),'in_external_ids':len(set(relations)&external),'external_count':len(external)}
report['conversation_prefixes']={tag:dict(Counter(c.split(':',1)[0] if ':' in c else 'unprefixed' for c in seq)) for tag,seq in [('session',convs),('message',msgs)]}
maps={}
for tag,seq in [('session',convs),('message',msgs)]:
match={'S':set(),'M':set()}
for c in seq:
if re.fullmatch(r'S:\d+_\d+',c):
p=c[2:].split('_')
if account in p:
other=[v for v in p if v!=account]
if len(other)==1 and other[0] in relations:match['S'].add(other[0])
elif re.fullmatch(r'M:\d+',c) and c[2:] in relations:match['M'].add(c[2:])
maps[tag]={'S':len(match['S']),'M':len(match['M']),'unmapped':len(set(relations)-match['S']-match['M'])}
report['relation_mappings']=maps
report['relation_name_coverage']=[list(r) for r in u.execute("SELECT r.status,count(*),sum(length(trim(coalesce(u.name,'')))>0),sum(length(trim(coalesce(r.real_remarks,'')))>0),sum(length(trim(coalesce(r.remarks,'')))>0) FROM external_user_relation_v3 r LEFT JOIN user_table u ON u.id=r.user_id GROUP BY r.status")]
# Existing persistent guard maps contain hashes only; match in memory and report counts.
guard=[]
for root in [Path('C:/wechat_rpa'),base]:
p=root/'pending_replies.protocol.json'
if not p.is_file():continue
raw=json.loads(p.read_text(encoding='utf-8-sig'));blocked=raw.get('contactBlocked',{})
matching=0;active=0
for c in convs:
key=hashlib.blake2b((account+'\0'+c).encode(),digest_size=40).hexdigest()
if key in blocked:
matching+=1
try:active+=int(0<=time.time()-float(blocked[key])<6*3600)
except (ValueError,TypeError):pass
guard.append({'location':'packaged' if root==base else 'source','total':len(blocked),'matching_current_conversations':matching,'active_6h':active})
report['contact_guard']=guard
finally:u.close();s.close();m.close()
(out/'packaged-aggregates.json').write_text(json.dumps(report,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps(report,ensure_ascii=False))