UNPKG

advanced-ussd-builder

Version:

Advanced USSD Menu Builder with persistent state and navigation

2 lines (1 loc) 4.91 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProxyHandler=void 0;const helper_1=require("./helper");class ProxyHandler{constructor(t){this.config={timeout:25e3,retry_attempts:1,retry_delay:1e3,session_bridge:!0,...t}}async fetchWithTimeout(t,d,c){const f=new AbortController,i=setTimeout(()=>f.abort(),c);try{const a=await fetch(t,{...d,signal:f.signal});return clearTimeout(i),a}catch(a){throw clearTimeout(i),a}}async forwardRequest(t,d){if(this.config.proxy_handler)return this.config.proxy_handler(t,d);if(!this.config.target_url)throw new Error("Either target_url or proxy_handler must be provided");const c=t.ussd_args,f=t;let i=f.raw_body,a;if(this.config.forward_original_format!==!1){a=f.raw_args||c;const n=t.session?.menu_metadata?.active_proxy_route;if(t.opts.provider==="mtn"&&a.ussdString!==void 0){const r=a.serviceCode||"*988";a={...a,ussdString:n?d:r,messageType:n?"1":"0"}}else if(t.opts.provider==="telecel"&&a.msg!==void 0){const r=t.opts.service_code||"*988";i&&n?i=i.replace(/<msg>[^<]*<\/msg>/i,`<msg>${d}</msg>`).replace(/<type>[^<]*<\/type>/i,"<type>2</type>"):i&&!n?i=i.replace(/<msg>[^<]*<\/msg>/i,`<msg>${r}</msg>`).replace(/<type>[^<]*<\/type>/i,"<type>1</type>"):a={...a,msg:n?d:r,type:n?2:1}}else t.opts.provider==="airtel-tigo"&&a.userData!==void 0&&(i&&n?i=i.replace(/<userData>[^<]*<\/userData>/i,`<userData>${d}</userData>`):a={...a,userData:n?d:""})}else{const n=(0,helper_1.getNetworkFromPhoneNumber)(c.msisdn),r=t.session?.menu_metadata?.active_proxy_route;a={msisdn:c.msisdn,session_id:c.session_id,user_input:d,service_code:t.opts.service_code,is_new_request:!r,provider:t.opts.provider,network:n!=="UNKNOWN"?n:c.network||t.opts.provider.toUpperCase(),session_data:this.config.session_bridge?t.session:void 0,original_request:c}}this.config.transform_request&&(a=this.config.transform_request(a));let m,u;const _=(f.raw_headers||{})["content-type"]?.includes("xml");i&&_&&this.config.forward_original_format!==!1?(m=i,u="text/xml"):(m=JSON.stringify(a),u="application/json");const h={method:"POST",body:m,headers:{"Content-Type":u,"X-USSD-Provider":t.opts.provider,"X-USSD-Proxy":"true",...this.config.headers}};for(let n=0;n<=(this.config.retry_attempts||0);n++)try{const r=await this.fetchWithTimeout(this.config.target_url,h,this.config.timeout||25e3);if(!r.ok){if(r.status>=400&&r.status<500){const e=await r.text();try{return{message:JSON.parse(e).message||`Request failed with status ${r.status}`,require_feedback:!1}}catch{return{message:`Request failed with status ${r.status}`,require_feedback:!1}}}throw new Error(`HTTP ${r.status}: ${r.statusText}`)}let s;if((r.headers.get("content-type")||"").includes("xml")){const e=await r.text();try{const o=(w,g)=>{const q=new RegExp(`<${g}>([^<]*)</${g}>`,"i"),y=w.match(q);return y&&y[1]||""};e.includes("<ussd>")&&e.includes("<sessionid>")?s={msisdn:o(e,"msisdn"),sessionid:o(e,"sessionid"),type:o(e,"type"),msg:o(e,"msg")}:e.includes("USSDDynMenuResponse")?s={USSDDynMenuResponse:{msisdn:o(e,"msisdn"),requestId:o(e,"requestId"),sessionId:o(e,"sessionId"),starCode:o(e,"starCode"),langId:o(e,"langId"),encodingScheme:o(e,"encodingScheme"),transferCode:o(e,"transferCode"),dataSet:{param:{id:o(e,"id"),value:o(e,"value"),rspFlag:o(e,"rspFlag"),rspURL:o(e,"rspURL"),appendIndex:o(e,"appendIndex")}}}}:s={message:e}}catch{throw new Error("Invalid XML response from proxy target")}}else try{s=await r.json()}catch{throw new Error("Invalid JSON response from proxy target")}let p=s;if(this.config.forward_original_format!==!1&&!this.config.transform_response){if(t.opts.provider==="mtn"&&s.data){const e=s.data;p={message:e.inboundResponse,require_feedback:e.userInputRequired}}else if(t.opts.provider==="telecel")if(s.ussd){const e=s.ussd,o=e.type==="2"||e.type===2;p={message:e.msg,require_feedback:o}}else if(s.msg!==void 0){const e=s.type==="2"||s.type===2;p={message:s.msg,require_feedback:e}}else s.message!==void 0?p={message:s.message,require_feedback:s.require_feedback!==!1&&s.type!=="3"&&s.type!==3}:p=s;else if(t.opts.provider==="airtel-tigo"&&s.USSDDynMenuResponse){const e=s.USSDDynMenuResponse;p={message:e.dataSet?.param?.value||"",require_feedback:e.dataSet?.param?.rspFlag==="1"}}}const l=this.config.transform_response?this.config.transform_response(p):p;return this.config.session_bridge&&l.session_data&&await t.set_session(l.session_data),{message:l.message||"Request processed",require_feedback:l.require_feedback!==!1}}catch(r){if(r instanceof Error&&r.name==="AbortError")return{message:"Service temporarily unavailable. Please try again.",require_feedback:!1};if(n<(this.config.retry_attempts||0))await new Promise(s=>setTimeout(s,this.config.retry_delay));else return{message:"An error occurred. Please try again later.",require_feedback:!1}}return{message:"An error occurred. Please try again later.",require_feedback:!1}}}exports.ProxyHandler=ProxyHandler;