"""Export all locally stored contact records through WhatsApp's JavaScript API.""" import argparse import datetime as dt import json from pathlib import Path from .live import run_math from .zip_export import evaluate PROBE = r'''(async () => { const table=require('WAWebSchemaContact_DO_NOT_USE_DIRECTLY').getContactTable(); const rows=await table.all(); if(!Array.isArray(rows))throw Error('Unexpected contact table result'); const fields=['id','phoneNumber','name','shortName','pushname','notifyName','verifiedName', 'addressBookName','isAddressBookContact','isMyContact','isBusiness','isEnterprise']; const contacts=rows.map(row=>{ const out={};for(const field of fields){const value=row[field]; if(value==null||['string','number','boolean'].includes(typeof value))out[field]=value??null; else if(field==='id')out.id=value.toString(); } if(typeof out.id!=='string'||!out.id)throw Error('Contact ID unavailable'); return out; }); return {source:'WAWebSchemaContact_DO_NOT_USE_DIRECTLY.getContactTable().all', scope:'All local contact rows, not only loaded models or phone address-book entries', count:contacts.length,contacts,cdp:false,ui_automation:false}; })()''' def export_contacts(output,pid=None): output=Path(output) if output.exists():raise ValueError('Output exists; choose a new --output') def operation(execute,session,report): data=evaluate(execute,PROBE,session) if not isinstance(data.get('contacts'),list) or data.get('count')!=len(data['contacts']): raise RuntimeError('Incomplete contact export response') report['data']=data report=run_math(pid,'contacts-export',_operation=operation) output.parent.mkdir(parents=True,exist_ok=True) with output.open('x',encoding='utf-8') as stream: json.dump(report,stream,ensure_ascii=True,indent=2) return report def main(argv=None): parser=argparse.ArgumentParser(description=__doc__) parser.add_argument('--pid',type=int) parser.add_argument('--output',type=Path,default=Path('exports')/('contacts-'+dt.datetime.now().strftime('%Y%m%d-%H%M%S')+'.json')) args=parser.parse_args(argv) report=export_contacts(args.output,args.pid) print(json.dumps({'passed':report['passed'],'error':report.get('error'),'contacts':report.get('data',{}).get('count'),'output':str(args.output)})) return 0 if report['passed'] else 1