Prepare documented WhatsApp injector with portable Python bundle
This commit is contained in:
commit
d2b621bce7
49 files changed
+5737
No files matched your search
@@ -0,0 +1,62 @@
|
||||
// Fixture tests for pagination, decryption errors, and plaintext redaction.
|
||||
const assert = require('node:assert/strict');
|
||||
const vm = require('node:vm');
|
||||
const fs = require('node:fs');
|
||||
const probe = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
||||
const rows = ['a','b','c','d','e'].map(id => ({id, body:'text-'+id, type:'chat', t:123, invisible:id==='b'}));
|
||||
const events = [];
|
||||
function req(result) {
|
||||
const r = {};
|
||||
queueMicrotask(() => {r.result=result; r.onsuccess();});
|
||||
return r;
|
||||
}
|
||||
const store = {
|
||||
count:()=>req(rows.length),
|
||||
openKeyCursor(range,direction) {
|
||||
const selected=rows.filter(r=>!range || ((range.lower===undefined || r.id>range.lower) && r.id<=range.upper));
|
||||
if(direction==='prev')selected.reverse();
|
||||
const request={};let index=0;
|
||||
function next(){queueMicrotask(()=>{
|
||||
request.result=index<selected.length?{primaryKey:selected[index++].id,continue:next}:null;
|
||||
request.onsuccess();
|
||||
});}
|
||||
next();return request;
|
||||
}
|
||||
};
|
||||
const db={objectStoreNames:{contains:n=>n==='message'},transaction:(name,mode)=>{
|
||||
assert.equal(name,'message');assert.equal(mode,'readonly');return {objectStore:()=>store};
|
||||
},close:()=>events.push('close')};
|
||||
const modules={
|
||||
WAWebSchemaMessage:{getMessageTable:()=>({get:async key=>{
|
||||
events.push('decrypt:'+key);
|
||||
if(key==='c')throw Error('simulated unavailable decryption key');
|
||||
return {...rows.find(r=>r.id===key)};
|
||||
}})},
|
||||
WAWebDBMessageSerialization:{messageFromDbRow:row=>{
|
||||
events.push('decode:'+row.id);
|
||||
return {...row,id:{id:row.id,remote:'test-chat',fromMe:false}};
|
||||
}}
|
||||
};
|
||||
async function run(options){return vm.runInNewContext(probe.replace('__OPTIONS__',JSON.stringify(options)),{
|
||||
location:{origin:'https://web.whatsapp.com'}, require:n=>modules[n],
|
||||
indexedDB:{databases:async()=>[{name:'model-storage'}],open:()=>req(db)},
|
||||
IDBKeyRange:{upperBound:upper=>({upper}),bound:(lower,upper,openLower,openUpper)=>{
|
||||
assert.equal(openLower,true);assert.equal(openUpper,false);return {lower,upper};
|
||||
}}
|
||||
});}
|
||||
(async()=>{
|
||||
const bounds=await run({mode:'bounds'});assert.equal(bounds.count,5);assert.equal(bounds.upper,'e');
|
||||
let after=null,all=[];
|
||||
while(after!=='e'){
|
||||
const page=await run({mode:'batch',upper:'e',after,batch:2,redact:false});
|
||||
assert.ok(page.keys.length<=2);all.push(...page.messages);after=page.last;
|
||||
}
|
||||
assert.deepEqual(all.map(m=>m.id),['a','b','c','d','e']); // UI-invisible b remains included.
|
||||
assert.equal(all[2].error,'row_decryption_or_decoding_failed');
|
||||
assert.equal(all[1].body,'text-b');
|
||||
const redacted=await run({mode:'batch',upper:'b',after:null,batch:2,redact:true});
|
||||
assert.ok(redacted.messages.every(m=>!('body' in m)&&!('caption' in m)));
|
||||
assert.equal(redacted.messages[0].body_length,6);
|
||||
assert.ok(events.indexOf('decrypt:a')<events.indexOf('decode:a'));
|
||||
console.log('PASS: bounded pagination, upper bound, invisible rows, row errors, decryption order, redaction');
|
||||
})().catch(error=>{console.error(error);process.exitCode=1;});
|
||||
Reference in new issue
Block a user