62 lines
4.1 KiB
Python
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))
|