43 lines
2.0 KiB
Python
43 lines
2.0 KiB
Python
"""Bounded oldest-message reading through the app's JavaScript database API."""
|
|||
|
|
|
||
|
|
PROBE = r'''(async () => {
|
||
|
|
if(location.origin!=='https://web.whatsapp.com')throw Error('Unexpected origin');
|
||
|
|
const table=require('WAWebSchemaMessage').getMessageTable();
|
||
|
|
const serializer=require('WAWebDBMessageSerialization');
|
||
|
|
if(!(await indexedDB.databases()).some(d=>d.name==='model-storage'))throw Error('Database absent');
|
||
|
|
const db=await new Promise((resolve,reject)=>{
|
||
|
|
const r=indexedDB.open('model-storage');
|
||
|
|
r.onupgradeneeded=()=>{r.transaction.abort();reject(Error('Refusing database upgrade'));};
|
||
|
|
r.onsuccess=()=>resolve(r.result);r.onerror=()=>reject(Error('Database open failed'));
|
||
|
|
});
|
||
|
|
let scanned=0;
|
||
|
|
try {
|
||
|
|
const oldest=await new Promise((resolve,reject)=>{
|
||
|
|
const tx=db.transaction('message','readonly'),store=tx.objectStore('message'),rows=[];
|
||
|
|
const r=store.openCursor();
|
||
|
|
r.onerror=()=>reject(Error('Cursor failed'));tx.onabort=()=>reject(Error('Transaction aborted'));
|
||
|
|
r.onsuccess=()=>{
|
||
|
|
const c=r.result;if(!c){resolve(rows);return;}
|
||
|
|
if(++scanned>100000) {reject(Error('History scan exceeds 100000 rows'));return;}
|
||
|
|
const t=c.value.t;
|
||
|
|
if(typeof t==='number'&&Number.isFinite(t)&&t>0){
|
||
|
|
rows.push({key:c.primaryKey,t});rows.sort((a,b)=>a.t-b.t);if(rows.length>5)rows.pop();
|
||
|
|
}
|
||
|
|
c.continue();
|
||
|
|
};
|
||
|
|
});
|
||
|
|
const messages=[];
|
||
|
|
for(const candidate of oldest){
|
||
|
|
const row=await table.get(candidate.key);
|
||
|
|
if(!row)throw Error('Selected row disappeared');
|
||
|
|
if(row.msgRowOpaqueData&&typeof row.msgRowOpaqueData==='object'&&'_data' in row.msgRowOpaqueData)
|
||
|
|
throw Error('Payload remains encrypted');
|
||
|
|
const m=serializer.messageFromDbRow(row);
|
||
|
|
messages.push({id:candidate.key,timestamp:m.t,type:m.type,
|
||
|
|
body:typeof m.body==='string'?m.body:null,caption:typeof m.caption==='string'?m.caption:null,
|
||
|
|
selected_timestamp:candidate.t});
|
||
|
|
}
|
||
|
|
return {scanned,sample_limit:5,source:'WAWebSchemaMessage.getMessageTable().get + WAWebDBMessageSerialization.messageFromDbRow',
|
||
|
|
cdp:false,messages};
|
||
|
|
}finally{db.close();}
|
||
|
|
})()'''
|