@apostlejs/whatsapp 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("zod");function t(e){return e&&e.__esModule?e:{default:e}}var a=t(require("node:crypto")),r=Object.defineProperty,n=(e,t)=>{for(var a in t)r(e,a,{get:t[a],enumerable:!0})},o={create:{url:"/{waba_id}/flows",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},updateMetadata:{url:"/{flow_id}",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},readMany:{url:"/{waba_id}/flows",method:"get",response:null},delete:{url:"/{flow_id}",method:"delete",response:null},read:{url:"/{flow_id}",method:"get",request:{query:null},response:null},updateJson:{url:"/{flow_id}/assets",method:"post",request:{body:null},response:null},getPreview:{url:"/{flow_id}?fields=preview.invalidate(false)",method:"get",response:null},publish:{url:"/{flow_id}/publish",method:"post",response:null}},s={send:{url:"/{number_id}/messages",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null}},i={updateEncryption:{url:"/{number_id}/whatsapp_business_encryption",method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},request:{body:null}},registerNumber:{url:"/{number_id}/register",method:"post",headers:{"Content-Type":"application/json"},request:{body:null}}},c={flows:o,messages:s,waba:i},l=e.z.enum(["INIT","BACK","data_exchange","navigate","ping"]),p=e.z.enum(["SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY","OTHER"]),u=e.z.object({media_id:e.z.string(),cdn_url:e.z.string(),file_name:e.z.string(),encryption_metadata:e.z.object({encrypted_hash:e.z.string(),iv:e.z.string(),encryption_key:e.z.string(),hmac_key:e.z.string(),plaintext_hash:e.z.string()})}),d=e.z.object({name:e.z.string(),categories:e.z.array(p),application_id:e.z.string().optional(),endpoint_uri:e.z.string().optional()}),f=e.z.union([e.z.literal("SUCCESS"),e.z.string()]),m=e.z.enum(["DRAFT","PUBLISHED","DEPRECATED","BLOCKED","THROTTLED"]),y=e.z.enum(["AVAILABLE","LIMITED","BLOCKED"]),_=e.z.object({error:e.z.string(),error_type:e.z.string(),message:e.z.string(),line_start:e.z.number(),line_end:e.z.number(),column_start:e.z.number(),column_end:e.z.number()}),h={},w={setup:e=>{Object.assign(h,e)},get:e=>{const t=h[e]??process.env[e];if(!t)throw new Error(`Missing environment variable: ${e}`);return t}},g={};n(g,{actions:()=>H,flows:()=>U,parsers:()=>q,security:()=>K,utils:()=>j});var b={};async function v(e,t,a){const r=`https://graph.facebook.com/v${w.get("GRAPH_API_VERSION")}`,n={Authorization:`Bearer ${w.get("META_APP_ACCESS_TOKEN")}`};let o=e.url;const s={...n,...e.headers,...t.headers},i=new URLSearchParams(t.query).toString();"/"===o[0]&&(o=o.slice(1)),o=`${r}/${o}`,i&&(o=`${o}?${i}`);const c={waba_id:w.get("WHATSAPP_ACCOUNT_ID"),number_id:w.get("WHATSAPP_NUMBER_ID"),...t.params};for(const e in c)o=o.replace(`{${e}}`,c[e]);const l=t.body;let p;if(l&&a?.asFormData){const e=new FormData;for(const t in l)e.append(t,l[t]);p=e}else l&&a?.asUrlEncoded?p=new URLSearchParams(l).toString():l&&(p=JSON.stringify(l));return await fetch(o,{method:e.method,headers:s,body:p}).then((e=>e.json())).then((e=>{if("error"in e)throw{response:{data:e.error}};return e})).catch((async e=>{throw e.response.data}))}async function E(e){return v(c.flows.create,{body:e})}async function S(e,t){const a=c.flows.updateMetadata;return await v(a,{body:t,params:{flow_id:e}})}async function A(e,t){return v(c.flows.updateJson,{params:{flow_id:e},body:{name:"flow.json",asset_type:"FLOW_JSON",file:new Blob([JSON.stringify(t,null,2)],{type:"application/json"})}},{asFormData:!0})}async function I(e,t){const a=c.flows.getPreview,{preview:r}=await v(a,{params:{flow_id:e}}),n=r.preview_url.replaceAll("\\",""),o=Object.entries(t??{}).reduce(((e,[t,a])=>(e[t]="flow_action_payload"===t?encodeURIComponent(JSON.stringify(a)):a.toString(),e)),{});return`${n}&${new URLSearchParams(o).toString()}`}async function P(e){return v(c.flows.delete,{params:{flow_id:e}})}async function N(e,t){return v(c.flows.read,{params:{flow_id:e},query:{fields:t?.fields.join(",")??""}})}async function T(){return v(c.flows.readMany,{})}async function x(e){return v(c.flows.publish,{params:{flow_id:e}})}n(b,{create:()=>E,delete:()=>P,get:()=>N,getMany:()=>T,getPreview:()=>I,publish:()=>x,updateJson:()=>A,updateMetadata:()=>S});var C={};async function O(e){const t=w.get("WHATSAPP_UNNOFICIAL_AUTHENTICATION_STRING"),a=await async function(e){const t=w.get("WHATSAPP_UNNOFICIAL_AUTHENTICATION_STRING");return await fetch("https://business.facebook.com/latest/whatsapp_manager/flows?flow_id="+e,{headers:{accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8","accept-language":"en-US,en;q=0.5","cache-control":"no-cache",pragma:"no-cache",priority:"u=0, i","sec-ch-ua":'"Brave";v="131", "Chromium";v="131", "Not_A Brand";v="24"',"sec-ch-ua-full-version-list":'"Brave";v="131.0.0.0", "Chromium";v="131.0.0.0", "Not_A Brand";v="24.0.0.0"',"sec-ch-ua-mobile":"?0","sec-ch-ua-model":'""',"sec-ch-ua-platform":'"Linux"',"sec-ch-ua-platform-version":'"6.11.9"',"sec-fetch-dest":"document","sec-fetch-mode":"navigate","sec-fetch-site":"same-origin","sec-fetch-user":"?1","sec-gpc":"1","upgrade-insecure-requests":"1",cookie:t},referrerPolicy:"strict-origin-when-cross-origin",body:null,method:"GET"}).then((e=>e.text())).then((e=>{const t=/<script\b[^>]*\bid=["']__eqmc["'][^>]*>(.*?)<\/script>/is.exec(e);if(!t)throw new Error("No matching <script> tag found.");const{f:a}=JSON.parse(t[1]);return a}))}(e),r={__aaid:"0",__bid:"250887754468924",__user:"100072333227027",__a:"1",__req:"m",dpr:"1",__ccg:"EXCELLENT",__rev:"1019090278",__comet_req:"11",fb_dtsg:a,__spin_b:"trunk",__jssesw:"1",fb_api_caller_class:"RelayModern",fb_api_req_friendly_name:"WAMFlowsBuilderDynamicSetupHealthCheckQuery",variables:JSON.stringify({flowID:e}),server_timestamps:"true",doc_id:" 7983200618385332"},n=new URLSearchParams(r).toString();return await fetch("https://business.facebook.com/api/graphql",{headers:{accept:"*/*","accept-language":"en-US,en;q=0.5","cache-control":"no-cache","content-type":"application/x-www-form-urlencoded",pragma:"no-cache",priority:"u=1, i","sec-ch-ua":'"Brave";v="131", "Chromium";v="131", "Not_A Brand";v="24"',"sec-ch-ua-full-version-list":'"Brave";v="131.0.0.0", "Chromium";v="131.0.0.0", "Not_A Brand";v="24.0.0.0"',"sec-ch-ua-mobile":"?0","sec-ch-ua-model":'""',"sec-ch-ua-platform":'"Linux"',"sec-ch-ua-platform-version":'"6.11.9"',"sec-fetch-dest":"empty","sec-fetch-mode":"cors","sec-fetch-site":"same-origin","sec-gpc":"1","x-fb-friendly-name":"WAMFlowsBuilderDynamicSetupHealthCheckQuery",cookie:t,Referer:"https://business.facebook.com/latest/whatsapp_manager/flows?flow_id=1137578314629992","Referrer-Policy":"strict-origin-when-cross-origin"},body:n,method:"POST"}).then((e=>e.text())).then((e=>e)).catch((e=>{console.error(e)}))}n(C,{verifyFlowIntegrity:()=>O});var B=e=>e.split("?")[0],U={createToken:({flow_name:e,flow_parameters:t,chatId:a})=>{const r=new URLSearchParams({chat_id:a});if(r.set("flow_identifier",crypto.randomUUID()),t)for(const[e,a]of Object.entries(t))r.set(e,a.toString());return`${e}?${decodeURIComponent(r.toString())}`},getName:B,destructureFlowToken:e=>{const t=B(e);let a=e.split("?")?.[1];"&"===a?.[0]&&(a=a.slice(1));const r=new URLSearchParams(a),n=r.get("chat_id")||r.get("chatId"),o=r.get("flow_identifier")||r.get("flowIdentifier"),s={};for(const[e,t]of r.entries())"chat_id"!==e&&"chatId"!==e&&"flow_identifier"!==e&&"flowIdentifier"!==e&&(s[e]=t);return{paramsString:a,flowName:t,chatId:n,flowIdentifier:o,flowParameters:s}}},R=e=>{const t={to:e.to,messaging_product:"whatsapp",recipient_type:"individual"};return e.reply&&(t.context=e.reply),e.showUrlPreviewImage&&(t.preview_url=e.showUrlPreviewImage),t},k={flow:e=>{if("flow"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{flow:r,...n}=t,o=R(a);r.mode||(r.mode=w.get("WHATSAPP_FLOWS_MODE"));const s=U.createToken({chatId:o.to,flow_name:r.name,flow_parameters:r.parameters});return{type:"interactive",...o,interactive:{...n,type:"flow",action:{name:"flow",parameters:{flow_name:r.name,flow_token:s,flow_message_version:"3",flow_cta:r.buttonText,flow_action:r.action??"navigate",mode:r.mode,...r.payload&&{flow_action_payload:{...r.payload,screen:r.payload.screen.toUpperCase()}}}}}}},text:e=>{if("text"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,r=R(a),n={type:"text",text:{body:t.text},...r};return e.message.previewUrl&&n.text&&(n.text.preview_url=e.message.previewUrl),n},list:e=>{if("list"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{list:r,type:n,...o}=t;return{...R(a),type:"interactive",interactive:{...o,type:n,action:{button:r.buttonText,sections:r.sections}}}},button:e=>{if("button"!==e.message.type)throw new Error("Invalid type");const{message:t,...a}=e,{buttons:r,type:n,...o}=t;return{...R(a),type:"interactive",interactive:{...o,type:n,action:{buttons:r.map((e=>({id:e.id,title:e.text,type:"reply"})))}}}},template:e=>{if("template"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...a},...r}=e,n={...R(r),type:t,template:{...a,language:{code:a.language}}};return n.template&&(n.template.namespace=process.env.WHATSAPP_MESSAGE_NAMESPACE),n},media:e=>{if("media"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...a},...r}=e,n=Object.entries(a)[0],[o,{ref:s,...i}]=n,c=i,l=R(r);return Number.isNaN(Number(s))?c.link=s:c.id=s,{type:o,[o]:c,...l}}};function z(e){const{encrypted_aes_key:t,encrypted_flow_data:r,initial_vector:n}=e,o=a.default.createPrivateKey({key:w.get("WHATSAPP_ACCOUNT_ENCRYPTION_PRIVATE_KEY"),passphrase:w.get("WHATSAPP_ACCOUNT_ENCRYPTION_PASSPHRASE")}),s=a.default.privateDecrypt({key:o,padding:a.default.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},Buffer.from(t,"base64")),i=Buffer.from(r,"base64"),c=Buffer.from(n,"base64"),l=i.subarray(0,-16),p=i.subarray(-16),u=a.default.createDecipheriv("aes-128-gcm",s,c);u.setAuthTag(p);const d=Buffer.concat([u.update(l),u.final()]).toString("utf-8");return{payload:JSON.parse(d),encryptionMetadata:{aesKeyBuffer:s,initialVectorBuffer:c}}}function M(e){const t=new URL(e.url).searchParams,a=t.get("hub.verify_token"),r=t.get("hub.challenge");return!(!a||!r)&&a===w.get("WHATSAPP_WEBHOOK_KEY")&&r}async function D(e,t){const r=e.headers.get("x-hub-signature-256");if(!r)return!1;const n=r.replace("sha256=",""),o=a.default.createHmac("sha256",w.get("WHATSAPP_WEBHOOK_KEY")).update(t,"utf-8").digest("hex");return!!a.default.timingSafeEqual(Buffer.from(n),Buffer.from(o))}var q={toGraph:{sendMessage:e=>k[e.message.type](e),flowResponse:(e,t)=>{if(!t.data)throw new Error("Missing data in flow response");if(!t.screen)throw new Error("Missing screen in flow response");if(t.screen=t.screen.toUpperCase(),"SUCCESS"===t.screen){const a=t.data??{};t.data={extension_message_response:{params:{flow_token:e,...a}}}}return t}},toSDK:{webhook:async function(e){if("GET"===e.method){const t=M(e);if(!t)throw new Error("Invalid request");return{type:"healthCheck",payload:t}}const t=await e.text(),a=JSON.parse(t);if("entry"in a){if(!D(e,t))throw new Error("Invalid request");const n=a.entry.flatMap((e=>e.changes)).filter((e=>"messages"===e.field)).flatMap((e=>e.value.messages)).filter(Boolean).map((e=>function(e){const t=e.from,a={id:e.id,type:e.type,timestamp:e.timestamp,metadata:{forwarded:e.context?.forwarded,frequentlyForwarded:e.context?.frequently_forwarded}},r=function(e){if(!(e.audio||e.document||e.video||e.image))return null;const t=e.audio?.id??e.document?.id??e.image?.id??e.video?.id,a=e.audio?.mime_type??e.document?.mime_type??e.image?.mime_type??e.video?.mime_type,r=["audio","document","image","video"].find((t=>e[t])),n=e.image?.sha256??e.document?.sha256??e.video?.sha256;return{id:t,type:r,caption:e.document?.caption??e.image?.caption??e.video?.caption??null,mime_type:a,sha256:n,filename:e.document?.filename??e.video?.filename}}(e),n=function(e){return e.text?.body??e.button?.text??e.interactive?.button_reply?.title??e.interactive?.list_reply?.title??e.document?.caption??null}(e),o=function(e){return e.interactive?{...e.interactive?.button_reply||e.button?{button:{id:e.interactive?.button_reply?.id??null,title:e.button?.text??e.interactive.button_reply?.title,payload:e.button?.payload??null}}:{},...e.interactive.list_reply?{selectedOption:{id:e.interactive.list_reply.id,title:e.interactive.list_reply.title,description:e.interactive.list_reply.description}}:{},...e.interactive.nfm_reply?{flowResponse:JSON.parse(e.interactive.nfm_reply.response_json)}:{}}:null}(e);return{...a,...o&&{interaction:o},...r&&{media:r},text:n,chatId:t}}(e)));return{type:"application",payload:{messageReceived:(r=n,r.length?r:void 0)}}}var r;if("encrypted_flow_data"in a)return{type:"flowExchange",payload:{...z(a),pingResponse:{data:{status:"active"}}}};throw new Error("Invalid request")}}},H={messages:{send:async function(e){const t=q.toGraph.sendMessage(e),a=c.messages.send;return await v(a,{body:t})}},flows:{...b,unnoficial:C},waba:{registerNumber:async function({dataRegion:e,pin:t}){const a=c.waba.registerNumber,r={messaging_product:"whatsapp",pin:t};return e&&(r.data_localization_region=e),await v(a,{body:r},{asUrlEncoded:!0})},encryption:{upload:async function(e){const t=c.waba.updateEncryption,a={business_public_key:e};return await v(t,{body:a},{asUrlEncoded:!0})}}}};async function L(e){return await fetch(e).then((async e=>{const t=await e.arrayBuffer();return Buffer.from(t)}))}var K={verifyHub:M,verifySignature:D,generateWabaEncryption:async function(){const e=a.default.randomUUID(),{publicKey:t,privateKey:r}=a.default.generateKeyPairSync("rsa",{modulusLength:2048,publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem",cipher:"aes-256-cbc",passphrase:e}});return{passphrase:e,publicKey:t,privateKey:r}},decryptFlowBody:z,encryptFlowResponse:function(e,t){const r=[];for(const e of Buffer.from(t.initialVectorBuffer).entries())r.push(~e[1]);const n=a.default.createCipheriv("aes-128-gcm",Buffer.from(t.aesKeyBuffer),Buffer.from(r));return Buffer.concat([n.update(JSON.stringify(e),"utf-8"),n.final(),n.getAuthTag()]).toString("base64")},decryptFlowMedia:async function(e){const t=[];for(const r of e){let{cdn_url:e,encryption_metadata:n}=r;if("EXAMPLE_DATA__CDN_URL_WILL_COME_IN_THIS_FIELD"===e){e="https://picsum.photos/seed/picsum/200";const a=await L(e);t.push(a);continue}const o=await L(e),{iv:s,encryption_key:i,hmac_key:c,encrypted_hash:l,plaintext_hash:p}=n,u={iv:Buffer.from(s,"base64"),encryption_key:Buffer.from(i,"base64"),hmac_key:Buffer.from(c,"base64")};if(a.default.createHash("sha256").update(o).digest("base64")!==l)throw new Error("Encrypted hash validation failed");const d=o.subarray(0,o.length-10),f=o.subarray(-10);if(!a.default.createHmac("sha256",u.hmac_key).update(Buffer.concat([u.iv,d])).digest().subarray(0,10).equals(f))throw new Error("HMAC validation failed");const m=a.default.createDecipheriv("aes-256-cbc",u.encryption_key,u.iv),y=m.update(d),_=Buffer.concat([y,m.final()]);if(a.default.createHash("sha256").update(_).digest("base64")!==p)throw new Error("Decrypted media hash validation failed");t.push(_)}return t}},j={flows:U},W={graph:{endpoints:c},settings:w,sdk:g};exports.actions=H,exports.endpoints=c,exports.flowAction=l,exports.flowCanSendMessageStatus=y,exports.flowCategory=p,exports.flowMediaData=u,exports.flowMetadata=d,exports.flowScreen=f,exports.flowStatus=m,exports.flowValidationError=_,exports.flows=U,exports.flowsEndpoints=o,exports.messagesEndpoints=s,exports.parsers=q,exports.security=K,exports.utils=j,exports.wabaEndpoints=i,exports.whatsapp=W;
1
+ "use strict";var e=require("zod");function t(e){return e&&e.__esModule?e:{default:e}}var r=t(require("node:crypto")),a=Object.defineProperty,n=(e,t)=>{for(var r in t)a(e,r,{get:t[r],enumerable:!0})},o={create:{url:"/{waba_id}/flows",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},updateMetadata:{url:"/{flow_id}",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null},readMany:{url:"/{waba_id}/flows",method:"get",response:null},delete:{url:"/{flow_id}",method:"delete",response:null},read:{url:"/{flow_id}",method:"get",request:{query:null},response:null},updateJson:{url:"/{flow_id}/assets",method:"post",request:{body:null},response:null},getPreview:{url:"/{flow_id}?fields=preview.invalidate(false)",method:"get",response:null},publish:{url:"/{flow_id}/publish",method:"post",response:null}},s={send:{url:"/{number_id}/messages",method:"post",headers:{"Content-Type":"application/json"},request:{body:null},response:null}},i={updateEncryption:{url:"/{number_id}/whatsapp_business_encryption",method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},request:{body:null}},registerNumber:{url:"/{number_id}/register",method:"post",headers:{"Content-Type":"application/json"},request:{body:null}}},l={flows:o,messages:s,waba:i},p=e.z.enum(["INIT","BACK","data_exchange","navigate","ping"]),c=e.z.enum(["SIGN_UP","SIGN_IN","APPOINTMENT_BOOKING","LEAD_GENERATION","CONTACT_US","CUSTOMER_SUPPORT","SURVEY","OTHER"]),d=e.z.object({media_id:e.z.string(),cdn_url:e.z.string(),file_name:e.z.string(),encryption_metadata:e.z.object({encrypted_hash:e.z.string(),iv:e.z.string(),encryption_key:e.z.string(),hmac_key:e.z.string(),plaintext_hash:e.z.string()})}),u=e.z.object({name:e.z.string(),categories:e.z.array(c),application_id:e.z.string().optional(),endpoint_uri:e.z.string().optional()}),f=e.z.union([e.z.literal("SUCCESS"),e.z.string()]),m=e.z.enum(["DRAFT","PUBLISHED","DEPRECATED","BLOCKED","THROTTLED"]),y=e.z.enum(["AVAILABLE","LIMITED","BLOCKED"]),w=e.z.object({error:e.z.string(),error_type:e.z.string(),message:e.z.string(),line_start:e.z.number(),line_end:e.z.number(),column_start:e.z.number(),column_end:e.z.number()}),_={},g={setup:e=>{Object.assign(_,e)},get:e=>{const t=_[e]??process.env[e];if(!t)throw new Error(`Missing environment variable: ${e}`);return t}},h={};n(h,{actions:()=>k,flows:()=>C,parsers:()=>D,security:()=>K,utils:()=>L});var b={};async function v(e,t,r){const a=`https://graph.facebook.com/v${g.get("GRAPH_API_VERSION")}`,n={Authorization:`Bearer ${g.get("META_APP_ACCESS_TOKEN")}`};let o=e.url;const s={...n,...e.headers,...t.headers},i=new URLSearchParams(t.query).toString();"/"===o[0]&&(o=o.slice(1)),o=`${a}/${o}`,i&&(o=`${o}?${i}`);const l={waba_id:g.get("WHATSAPP_ACCOUNT_ID"),number_id:g.get("WHATSAPP_NUMBER_ID"),...t.params};for(const e in l)o=o.replace(`{${e}}`,l[e]);const p=t.body;let c;if(p&&r?.asFormData){const e=new FormData;for(const t in p)e.append(t,p[t]);c=e}else p&&r?.asUrlEncoded?c=new URLSearchParams(p).toString():p&&(c=JSON.stringify(p));return await fetch(o,{method:e.method,headers:s,body:c}).then((e=>e.json())).then((e=>{if("error"in e)throw{response:{data:e.error}};return e})).catch((async e=>{throw e.response.data}))}async function E(e){return v(l.flows.create,{body:e})}async function S(e,t){const r=l.flows.updateMetadata;return await v(r,{body:t,params:{flow_id:e}})}async function A(e,t){return v(l.flows.updateJson,{params:{flow_id:e},body:{name:"flow.json",asset_type:"FLOW_JSON",file:new Blob([JSON.stringify(t,null,2)],{type:"application/json"})}},{asFormData:!0})}async function P(e,t){const r=l.flows.getPreview,{preview:a}=await v(r,{params:{flow_id:e}}),n=a.preview_url.replaceAll("\\",""),o=Object.entries(t??{}).reduce(((e,[t,r])=>(e[t]="flow_action_payload"===t?encodeURIComponent(JSON.stringify(r)):r.toString(),e)),{});return`${n}&${new URLSearchParams(o).toString()}`}async function I(e){return v(l.flows.delete,{params:{flow_id:e}})}async function T(e,t){return v(l.flows.read,{params:{flow_id:e},query:{fields:t?.fields.join(",")??""}})}async function x(){return v(l.flows.readMany,{})}async function N(e){return v(l.flows.publish,{params:{flow_id:e}})}n(b,{create:()=>E,delete:()=>I,get:()=>T,getMany:()=>x,getPreview:()=>P,publish:()=>N,updateJson:()=>A,updateMetadata:()=>S});var O=e=>e.split("?")[0],C={createToken:({flow_name:e,flow_parameters:t,chatId:r})=>{const a=new URLSearchParams({chat_id:r});if(a.set("flow_identifier",crypto.randomUUID()),t)for(const[e,r]of Object.entries(t))a.set(e,r.toString());return`${e}?${decodeURIComponent(a.toString())}`},getName:O,destructureFlowToken:e=>{const t=O(e);let r=e.split("?")?.[1];"&"===r?.[0]&&(r=r.slice(1));const a=new URLSearchParams(r),n=a.get("chat_id")||a.get("chatId"),o=a.get("flow_identifier")||a.get("flowIdentifier"),s={};for(const[e,t]of a.entries())"chat_id"!==e&&"chatId"!==e&&"flow_identifier"!==e&&"flowIdentifier"!==e&&(s[e]=t);return{paramsString:r,flowName:t,chatId:n,flowIdentifier:o,flowParameters:s}}},B=e=>{const t={to:e.to,messaging_product:"whatsapp",recipient_type:"individual"};return e.reply&&(t.context=e.reply),e.showUrlPreviewImage&&(t.preview_url=e.showUrlPreviewImage),t},U={flow:e=>{if("flow"!==e.message.type)throw new Error("Invalid type");const{message:t,...r}=e,{flow:a,...n}=t,o=B(r);a.mode||(a.mode=g.get("WHATSAPP_FLOWS_MODE"));const s=C.createToken({chatId:o.to,flow_name:a.name,flow_parameters:a.parameters});return{type:"interactive",...o,interactive:{...n,type:"flow",action:{name:"flow",parameters:{flow_name:a.name,flow_token:s,flow_message_version:"3",flow_cta:a.buttonText,flow_action:a.action??"navigate",mode:a.mode,...a.payload&&{flow_action_payload:{...a.payload,screen:a.payload.screen.toUpperCase()}}}}}}},text:e=>{if("text"!==e.message.type)throw new Error("Invalid type");const{message:t,...r}=e,a=B(r),n={type:"text",text:{body:t.text},...a};return e.message.previewUrl&&n.text&&(n.text.preview_url=e.message.previewUrl),n},list:e=>{if("list"!==e.message.type)throw new Error("Invalid type");const{message:t,...r}=e,{list:a,type:n,...o}=t;return{...B(r),type:"interactive",interactive:{...o,type:n,action:{button:a.buttonText,sections:a.sections}}}},button:e=>{if("button"!==e.message.type)throw new Error("Invalid type");const{message:t,...r}=e,{buttons:a,type:n,...o}=t;return{...B(r),type:"interactive",interactive:{...o,type:n,action:{buttons:a.map((e=>({id:e.id,title:e.text,type:"reply"})))}}}},template:e=>{if("template"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...r},...a}=e,n={...B(a),type:t,template:{...r,language:{code:r.language}}};return n.template&&(n.template.namespace=process.env.WHATSAPP_MESSAGE_NAMESPACE),n},media:e=>{if("media"!==e.message.type)throw new Error("Invalid type");const{message:{type:t,...r},...a}=e,n=Object.entries(r)[0],[o,{ref:s,...i}]=n,l=i,p=B(a);return Number.isNaN(Number(s))?l.link=s:l.id=s,{type:o,[o]:l,...p}}};function z(e){const{encrypted_aes_key:t,encrypted_flow_data:a,initial_vector:n}=e,o=r.default.createPrivateKey({key:g.get("WHATSAPP_ACCOUNT_ENCRYPTION_PRIVATE_KEY"),passphrase:g.get("WHATSAPP_ACCOUNT_ENCRYPTION_PASSPHRASE")}),s=r.default.privateDecrypt({key:o,padding:r.default.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},Buffer.from(t,"base64")),i=Buffer.from(a,"base64"),l=Buffer.from(n,"base64"),p=i.subarray(0,-16),c=i.subarray(-16),d=r.default.createDecipheriv("aes-128-gcm",s,l);d.setAuthTag(c);const u=Buffer.concat([d.update(p),d.final()]).toString("utf-8");return{payload:JSON.parse(u),encryptionMetadata:{aesKeyBuffer:s,initialVectorBuffer:l}}}function R(e){const t=new URL(e.url).searchParams,r=t.get("hub.verify_token"),a=t.get("hub.challenge");return!(!r||!a)&&r===g.get("WHATSAPP_WEBHOOK_KEY")&&a}async function M(e,t){const a=e.headers.get("x-hub-signature-256");if(!a)return!1;const n=a.replace("sha256=",""),o=r.default.createHmac("sha256",g.get("WHATSAPP_WEBHOOK_KEY")).update(t,"utf-8").digest("hex");return!!r.default.timingSafeEqual(Buffer.from(n),Buffer.from(o))}var D={toGraph:{sendMessage:e=>U[e.message.type](e),flowResponse:(e,t)=>{if(!t.data)throw new Error("Missing data in flow response");if(!t.screen)throw new Error("Missing screen in flow response");if(t.screen=t.screen.toUpperCase(),"SUCCESS"===t.screen){const r=t.data??{};t.data={extension_message_response:{params:{flow_token:e,...r}}}}return t}},toSDK:{webhook:async function(e){if("GET"===e.method){const t=R(e);if(!t)throw new Error("Invalid request");return{type:"healthCheck",payload:t}}const t=await e.text(),r=JSON.parse(t);if("entry"in r){if(!M(e,t))throw new Error("Invalid request");const n=r.entry.flatMap((e=>e.changes)).filter((e=>"messages"===e.field)).flatMap((e=>e.value.messages)).filter(Boolean).map((e=>function(e){const t=e.from,r={id:e.id,type:e.type,timestamp:e.timestamp,metadata:{forwarded:e.context?.forwarded,frequentlyForwarded:e.context?.frequently_forwarded}},a=function(e){if(!(e.audio||e.document||e.video||e.image))return null;const t=e.audio?.id??e.document?.id??e.image?.id??e.video?.id,r=e.audio?.mime_type??e.document?.mime_type??e.image?.mime_type??e.video?.mime_type,a=["audio","document","image","video"].find((t=>e[t])),n=e.image?.sha256??e.document?.sha256??e.video?.sha256;return{id:t,type:a,caption:e.document?.caption??e.image?.caption??e.video?.caption??null,mime_type:r,sha256:n,filename:e.document?.filename??e.video?.filename}}(e),n=function(e){return e.text?.body??e.button?.text??e.interactive?.button_reply?.title??e.interactive?.list_reply?.title??e.document?.caption??null}(e),o=function(e){return e.interactive?{...e.interactive?.button_reply||e.button?{button:{id:e.interactive?.button_reply?.id??null,title:e.button?.text??e.interactive.button_reply?.title,payload:e.button?.payload??null}}:{},...e.interactive.list_reply?{selectedOption:{id:e.interactive.list_reply.id,title:e.interactive.list_reply.title,description:e.interactive.list_reply.description}}:{},...e.interactive.nfm_reply?{flowResponse:JSON.parse(e.interactive.nfm_reply.response_json)}:{}}:null}(e);return{...r,...o&&{interaction:o},...a&&{media:a},text:n,chatId:t}}(e)));return{type:"application",payload:{messageReceived:(a=n,a.length?a:void 0)}}}var a;if("encrypted_flow_data"in r)return{type:"flowExchange",payload:{...z(r),pingResponse:{data:{status:"active"}}}};throw new Error("Invalid request")}}},k={messages:{send:async function(e){const t=D.toGraph.sendMessage(e),r=l.messages.send;return await v(r,{body:t})}},flows:{...b},waba:{registerNumber:async function({dataRegion:e,pin:t}){const r=l.waba.registerNumber,a={messaging_product:"whatsapp",pin:t};return e&&(a.data_localization_region=e),await v(r,{body:a},{asUrlEncoded:!0})},encryption:{upload:async function(e){const t=l.waba.updateEncryption,r={business_public_key:e};return await v(t,{body:r},{asUrlEncoded:!0})}}}};async function H(e){return await fetch(e).then((async e=>{const t=await e.arrayBuffer();return Buffer.from(t)}))}var K={verifyHub:R,verifySignature:M,generateWabaEncryption:async function(){const e=r.default.randomUUID(),{publicKey:t,privateKey:a}=r.default.generateKeyPairSync("rsa",{modulusLength:2048,publicKeyEncoding:{type:"spki",format:"pem"},privateKeyEncoding:{type:"pkcs8",format:"pem",cipher:"aes-256-cbc",passphrase:e}});return{passphrase:e,publicKey:t,privateKey:a}},decryptFlowBody:z,encryptFlowResponse:function(e,t){const a=[];for(const e of Buffer.from(t.initialVectorBuffer).entries())a.push(~e[1]);const n=r.default.createCipheriv("aes-128-gcm",Buffer.from(t.aesKeyBuffer),Buffer.from(a));return Buffer.concat([n.update(JSON.stringify(e),"utf-8"),n.final(),n.getAuthTag()]).toString("base64")},decryptFlowMedia:async function(e){const t=[];for(const a of e){let{cdn_url:e,encryption_metadata:n}=a;if("EXAMPLE_DATA__CDN_URL_WILL_COME_IN_THIS_FIELD"===e){e="https://picsum.photos/seed/picsum/200";const r=await H(e);t.push(r);continue}const o=await H(e),{iv:s,encryption_key:i,hmac_key:l,encrypted_hash:p,plaintext_hash:c}=n,d={iv:Buffer.from(s,"base64"),encryption_key:Buffer.from(i,"base64"),hmac_key:Buffer.from(l,"base64")};if(r.default.createHash("sha256").update(o).digest("base64")!==p)throw new Error("Encrypted hash validation failed");const u=o.subarray(0,o.length-10),f=o.subarray(-10);if(!r.default.createHmac("sha256",d.hmac_key).update(Buffer.concat([d.iv,u])).digest().subarray(0,10).equals(f))throw new Error("HMAC validation failed");const m=r.default.createDecipheriv("aes-256-cbc",d.encryption_key,d.iv),y=m.update(u),w=Buffer.concat([y,m.final()]);if(r.default.createHash("sha256").update(w).digest("base64")!==c)throw new Error("Decrypted media hash validation failed");t.push(w)}return t}},L={flows:C},q={graph:{endpoints:l},settings:g,sdk:h};exports.actions=k,exports.endpoints=l,exports.flowAction=p,exports.flowCanSendMessageStatus=y,exports.flowCategory=c,exports.flowMediaData=d,exports.flowMetadata=u,exports.flowScreen=f,exports.flowStatus=m,exports.flowValidationError=w,exports.flows=C,exports.flowsEndpoints=o,exports.messagesEndpoints=s,exports.parsers=D,exports.security=K,exports.utils=L,exports.wabaEndpoints=i,exports.whatsapp=q;
package/dist/index.d.cts CHANGED
@@ -783,13 +783,6 @@ interface WhatsappFlowInfo {
783
783
 
784
784
  declare function _delete(flow_id: string): Promise<WhatsappDeleteFlowResponse>;
785
785
 
786
- declare function verifyFlowIntegrity(flowID: string): Promise<string | void>;
787
-
788
- declare const unnoficial_verifyFlowIntegrity: typeof verifyFlowIntegrity;
789
- declare namespace unnoficial {
790
- export { unnoficial_verifyFlowIntegrity as verifyFlowIntegrity };
791
- }
792
-
793
786
  type WaSDKButtonMessage = Omit<WaInteractiveBase, "type"> & {
794
787
  type: "button";
795
788
  buttons: Array<{
@@ -907,7 +900,6 @@ declare const actions: {
907
900
  send: typeof send;
908
901
  };
909
902
  flows: {
910
- unnoficial: typeof unnoficial;
911
903
  create(body: WhatsappCreateFlowRequestBody): Promise<WhatsappCreateFlowResponse>;
912
904
  updateMetadata(flow_id: string, body: WhatsappFlowUpdateMetadataRequestBody): Promise<WhatsappFlowUpdateMetadataResponse>;
913
905
  updateJson(flow_id: string, json: Record<string, AnyType>): Promise<WhatsappUpdateFlowJsonResponse>;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.0.0",
7
+ "version": "0.0.2",
8
8
  "type": "module",
9
9
  "files": [
10
10
  "dist"