UNPKG

meta-cloud-api

Version:
3 lines 8.4 kB
import {c,b,a as a$1}from'./chunk-WGGN32O2.js';import {a as a$2,b as b$1}from'./chunk-BAOZ4U74.js';import {a}from'./chunk-FKXSL2JK.js';import y from'crypto';var O="WEBHOOK_UTILS",s=new a(O,process.env.DEBUG==="true");async function M(a,e,r){try{s.info("Processing webhook messages request");let t=await a.json();if(s.info("Webhook request body:",t),t.object!=="whatsapp_business_account"){let p="Received webhook for non-WhatsApp event";return s.warn(p,{body:t}),new Response(JSON.stringify({error:p}),{status:404})}let o=[];for(let p of t.entry)try{s.info("Processing webhook entry:",{entryId:p.id});let d=p.changes;for(let i of d)i.field==="messages"&&(s.info("Processing messages change:",{change:i}),await T(p.id,i.value,e,r));}catch(d){let i=`Error processing webhook: ${d}`;s.error(i,{entry:p,error:d}),o.push(i);}return s.info("Webhook processing complete",{errorCount:o.length}),new Response(o.length>0?JSON.stringify({errors:o}):null,{status:200})}catch(t){return s.error("Error processing webhook:",t),new Response(JSON.stringify({error:"Internal Server Error"}),{status:500})}}async function S(a,e,r,t){try{s.info("Processing flow request");let o=await a.text(),p=a.headers.get("x-hub-signature-256");if(s.info("Flow request signature:",{signature:p}),!_(o,p,e.WEBHOOK_VERIFICATION_TOKEN||""))return s.warn("Invalid request signature",{signature:p}),new Response(JSON.stringify({error:"Unauthorized"}),{status:401});let d=JSON.parse(o);s.info("Flow request data:",d);let{decryptedBody:i}=q(d,e);s.info("Decrypted flow request:",i);let g=t.get("*");if(!g)return s.warn("No handler registered for flow action:",{action:i.action}),new Response(JSON.stringify({error:"Handler not found"}),{status:404});if(c(i))return s.info("Handling flow ping request"),new Response(JSON.stringify({version:"3.0",data:{status:"active"}}),{status:200});if(b(i))return s.warn("Flow error request received:",i),new Response(null,{status:200});if(a$1(i)){s.info("Processing flow data exchange request");let u=await g(r,i);s.info("Flow handler result:",u);let l=A(u,Buffer.from(d.aes_key,"base64"),Buffer.from(d.initial_vector,"base64"));return s.info("Encrypted flow response generated"),new Response(JSON.stringify(l),{status:200})}return s.warn("Unknown flow request type:",i),new Response(JSON.stringify({error:"Unknown request type"}),{status:400})}catch(o){return s.error("Error handling flow request:",o),new Response(JSON.stringify({error:"Internal server error"}),{status:500})}}function _(a,e,r){if(!e)return s.warn("Missing signature in request"),false;s.info("Signature verification details:",{bodyLength:a.length,verificationTokenLength:r.length,rawSignature:e,cleanedSignature:e.replace("sha256=","")});let t=y.createHmac("sha256",r).update(a).digest("hex");return s.info("Signature verification:",{received:e.replace("sha256=",""),expected:t}),y.timingSafeEqual(Buffer.from(e.replace("sha256=","")),Buffer.from(t))}function C(a,e){let r=a["x-forwarded-proto"]||"http",t=a.host||"localhost";return `${r}://${t}${e||"/"}`}async function T(a,e,r,t){s.info("Processing messages:",{waba_id:a,value:e});let o=e.metadata,p=e.contacts,d=a,i=o?.display_phone_number||"",g=o?.phone_number_id||"",u=p?.[0]?.profile?.name||"";if(e.statuses&&e.statuses.length>0){s.info("Processing statuses:",{statusCount:e.statuses.length});let l=e.statuses;for(let n of l){let f={wabaId:d,id:n.id,from:n.recipient_id,timestamp:n.timestamp,type:"statuses",phoneNumberId:g,displayPhoneNumber:i,profileName:u,statuses:e.statuses[0],originalData:n};s.info("Processing status:",f),await w(t.messageHandlers.get("statuses"),r,f,"statuses");}return}if(e.messages&&e.messages.length>0){s.info("Processing messages:",{messageCount:e.messages.length});let l=e.messages;for(let n of l){let f=n.type;s.info("Processing message:",{messageType:f,messageId:n.id});let c={wabaId:d,id:n.id,from:n.from,timestamp:n.timestamp,type:n.type,phoneNumberId:g,displayPhoneNumber:i,profileName:u,originalData:n};switch(f){case "text":c.text=n.text;break;case "image":c.image=n.image;break;case "video":c.video=n.video;break;case "audio":c.audio=n.audio;break;case "document":c.document=n.document;break;case "sticker":c.sticker=n.sticker;break;case "location":c.location=n.location;break;case "contacts":c.contacts=n.contacts;break;case "interactive":c.interactive=n.interactive;break;case "button":c.button=n.button;break;case "order":c.order=n.order;break;case "system":c.system=n.system;break;case "reaction":c.reaction=n.reaction;break;default:s.warn("Unknown message type:",{messageType:f});break}s.info("Executing message handlers"),await w(t.preProcessHandler,r,c,"pre-process"),await w(t.messageHandlers.get(f),r,c,f),await w(t.postProcessHandler,r,c,"post-process");}}}async function w(a,e,r,t){if(a)try{s.info("Executing handler:",{handlerType:t,messageId:r.id}),await a(e,r),s.info("Handler execution complete:",{handlerType:t,messageId:r.id});}catch(o){s.error(`Error in ${t} handler:`,{error:o,messageId:r.id});}else s.info("No handler registered:",{handlerType:t});}function q(a,e){s.info("Decrypting flow request");let{encrypted_aes_key:r,encrypted_flow_data:t,initial_vector:o}=a;if(!r||!t||!o)throw s.error("Missing required encryption properties"),new Error("Missing required encryption properties");let p=e.FLOW_API_PRIVATE_PEM.replace(/\\n/g,` `),d=e.FLOW_API_PASSPHRASE,i=y.createPrivateKey({key:p,passphrase:d}),g;try{s.info("Decrypting AES key"),g=y.privateDecrypt({key:i,padding:y.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},Buffer.from(r,"base64"));}catch(F){throw s.error("Failed to decrypt AES key:",F),new Error("Failed to decrypt the request. Please verify your private key.")}let u=Buffer.from(t,"base64"),l=Buffer.from(o,"base64"),f=u.subarray(0,-16),c=u.subarray(-16);s.info("Decrypting flow data");let b=y.createDecipheriv("aes-128-gcm",g,l);b.setAuthTag(c);let v=Buffer.concat([b.update(f),b.final()]).toString("utf-8");return s.info("Flow request decryption complete"),{decryptedBody:JSON.parse(v),aesKeyBuffer:g,initialVectorBuffer:l}}function A(a,e,r){s.info("Encrypting flow response");let t=[];for(let o of Array.from(r.entries()))t.push(~o[1]);try{let o=y.createCipheriv("aes-128-gcm",e,Buffer.from(t)),p=Buffer.concat([o.update(JSON.stringify(a||{}),"utf-8"),o.final(),o.getAuthTag()]).toString("base64");return s.info("Flow response encryption complete"),p}catch(o){throw s.error("Response encryption error:",o),new Error("Failed to encrypt response. Internal server error.")}}var m=new a("WEBHOOK_PROCESSOR",process.env.DEBUG==="true"),W=class{config;client;messageHandlers=new Map;preProcessHandler=void 0;postProcessHandler=void 0;flowHandlers=new Map;constructor(e){this.config=a$2(e),this.client=new b$1(e),m.log("WebhookProcessor instantiated");}async processVerification(e,r,t){return e==="subscribe"&&r===this.config.WEBHOOK_VERIFICATION_TOKEN?{status:200,body:t||"",headers:{"Content-Type":"text/plain"}}:{status:403,body:JSON.stringify({error:"Forbidden"}),headers:{"Content-Type":"application/json"}}}async processWebhook(e){try{let r=await M(e,this.client,{messageHandlers:this.messageHandlers,preProcessHandler:this.preProcessHandler,postProcessHandler:this.postProcessHandler}),t=await r.text(),o=r.headers.get("content-type")||"application/json";return {status:r.status,body:t,headers:{"Content-Type":o}}}catch(r){return m.log(`Error processing webhook: ${r}`),{status:500,body:JSON.stringify({error:"Internal Server Error"}),headers:{"Content-Type":"application/json"}}}}async processFlow(e){try{let r=await S(e,this.config,this.client,this.flowHandlers),t=await r.text(),o=r.headers.get("content-type")||"application/json";return {status:r.status,body:t,headers:{"Content-Type":o}}}catch(r){return m.log(`Error processing flow: ${r}`),{status:500,body:JSON.stringify({error:"Internal Server Error"}),headers:{"Content-Type":"application/json"}}}}onMessage(e,r){this.messageHandlers.set(e,r),m.log(`Registered message handler for ${e}`);}onMessagePreProcess(e){this.preProcessHandler=e,m.log("Registered pre-process handler");}onMessagePostProcess(e){this.postProcessHandler=e,m.log("Registered post-process handler");}onFlow(e,r){this.flowHandlers.set(e,r),m.log(`Registered flow handler for ${e}`);}getClient(){return this.client}getConfig(){return this.config}};export{M as a,S as b,C as c,W as d};//# sourceMappingURL=chunk-JPGXONBQ.js.map //# sourceMappingURL=chunk-JPGXONBQ.js.map