Add autonomous webhooks and dynamic WebView discovery
This commit is contained in:
1 parent
ab69f287b6
commit
97f874d183
29 files changed
+3044
-1489
No files matched your search
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,63 @@
|
||||
(() => {
|
||||
const config=__CONFIG__, key='__whatsappWebhookV1';
|
||||
const existing=window[key];
|
||||
if(existing&&!existing.stopped){
|
||||
if(existing.listener_id!==config.listener_id)throw Error('Another listener is installed; stop it first');
|
||||
return existing.status();
|
||||
}
|
||||
const collection=require('WAWebMsgCollection').MsgCollection;
|
||||
const prefs=require('WAWebUserPrefsMeUser');
|
||||
if(typeof collection.on!=='function'||typeof collection.off!=='function')throw Error('Message events unavailable');
|
||||
const seen=new Set(), pending=new Map(), timers=new Set();
|
||||
const state={listener_id:config.listener_id,queue:[],stopped:false,delivered:0,
|
||||
dropped:0,decode_errors:0,last_error:null,observed:0,sequence:0,
|
||||
installed_at:Date.now(),self_only:config.self_only};
|
||||
const identity=m=>m?.id?.toString?.();
|
||||
function later(fn,delay){const timer=setTimeout(()=>{timers.delete(timer);if(!state.stopped)fn();},delay);timers.add(timer);}
|
||||
async function capture(model,attempt=0){
|
||||
const id=identity(model);if(!id||seen.has(id)||state.stopped)return;
|
||||
if(config.self_only&&!prefs.isMeAccount(model.id.remote))return;
|
||||
if(!Number.isFinite(model.t)||model.t*1000<config.since_ms-2000)return;
|
||||
pending.set(id,model);
|
||||
try{
|
||||
const row=await require('WAWebSchemaMessage').getMessageTable().get(id);
|
||||
if(state.stopped||seen.has(id))return;
|
||||
if(!row){if(attempt<8)later(()=>capture(model,attempt+1),250);else{state.decode_errors++;pending.delete(id);}return;}
|
||||
const decoded=require('WAWebDBMessageSerialization').messageFromDbRow(row);
|
||||
if(!decoded)throw Error('Message decoder returned no row');
|
||||
if(state.queue.length>=1000){state.dropped++;pending.delete(id);return;}
|
||||
const event={seq:++state.sequence,event_id:id,type:'message',message:{
|
||||
id,chat_id:model.id.remote.toString(),timestamp:decoded.t??model.t,
|
||||
from_me:!!model.id.fromMe,message_type:decoded.type??model.type??null,
|
||||
body:typeof decoded.body==='string'?decoded.body.slice(0,12000):null,
|
||||
caption:typeof decoded.caption==='string'?decoded.caption.slice(0,4000):null,
|
||||
text_truncated:(decoded.body?.length??0)>12000||(decoded.caption?.length??0)>4000,
|
||||
body_length:typeof decoded.body==='string'?decoded.body.length:0,
|
||||
caption_length:typeof decoded.caption==='string'?decoded.caption.length:0}};
|
||||
state.queue.push(event);seen.add(id);pending.delete(id);
|
||||
if(seen.size>10000)seen.delete(seen.values().next().value);
|
||||
}catch(error){
|
||||
state.last_error=String(error).slice(0,300);
|
||||
if(attempt<8)later(()=>capture(model,attempt+1),250);else{state.decode_errors++;pending.delete(id);}
|
||||
}
|
||||
}
|
||||
function onMessage(model){
|
||||
if(!model?.id||state.stopped)return;
|
||||
state.observed++;
|
||||
if(config.self_only&&!prefs.isMeAccount(model.id.remote))return;
|
||||
if(!Number.isFinite(model.t)||model.t*1000<config.since_ms-2000)return;
|
||||
const id=identity(model);if(!seen.has(id)&&!pending.has(id)){pending.set(id,model);later(()=>capture(model),50);}
|
||||
}
|
||||
const events=['add','change:body','change:caption'];
|
||||
state.status=()=>({installed:!state.stopped,listener_id:state.listener_id,
|
||||
queued:state.queue.length,pending:pending.size,delivered:state.delivered,
|
||||
dropped:state.dropped,decode_errors:state.decode_errors,last_error:state.last_error,
|
||||
observed:state.observed,installed_at:state.installed_at,self_only:state.self_only});
|
||||
state.stop=()=>{state.stopped=true;for(const event of events)collection.off(event,onMessage);
|
||||
for(const timer of timers)clearTimeout(timer);timers.clear();pending.clear();state.queue.length=0;return state.status();};
|
||||
window[key]=state;
|
||||
for(const event of events)collection.on(event,onMessage);
|
||||
// Reconcile recently loaded models on a reinstall; the receiver deduplicates IDs.
|
||||
if(config.reconcile)for(const model of collection.getModelsArray())onMessage(model);
|
||||
return state.status();
|
||||
})()
|
||||
Binary file not shown.
Reference in new issue
Block a user