ananse
Version:
Ananse is a lightweight NodeJs framework with batteries included for building efficient, scalable and maintainable USSD applications.
168 lines (167 loc) • 6.33 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// src/cli/simulator.ts
var import_crypto = require("crypto");
var readline = __toESM(require("readline"));
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var CACHE = { wigal: {}, emergent_technology: {} };
var Simulator = class {
constructor() {
this.args = {};
}
// TODO: Implement emergent ussd
get provider() {
return this.args.provider;
}
get baseUrl() {
return `${this.args.url || "http://localhost:3000"}`;
}
// get generateRequestUrl(): string {
// if (this.provider == "wigal") {
// return `${this.baseUrl}?network=wigal_tigo_gh&sessionid=12345&mode=start&msisdn=${this.args.phone}&userdata&username=stevkky&trafficid=adc62161-05b2-4af5-98b1-a66c67f85c9d&other=first_menu`;
// }
// throw new Error(`${this.provider} is not implemented`);
// }
async init() {
this.parseArguments();
}
parseArguments() {
var _a;
this.args["phone"] = process.argv.slice(2)[0];
this.args["provider"] = process.argv.slice(2)[1];
this.args["url"] = process.argv.slice(2)[2];
if (this.args.phone == null || ((_a = this.args.phone) == null ? void 0 : _a.trim()) == "") {
console.log("Please provide a phone number!");
process.exit(1);
}
if (!/[0-9]{10,}/.test(this.args.phone)) {
console.log("Invalid phone number!");
process.exit(1);
}
process.argv.slice(2).forEach((arg) => {
const [key, value] = arg.split("=");
this.args[key.replace(/(-)+/, "")] = value;
});
}
async start(url, requestBody) {
try {
if (this.provider == "wigal" /* wigal */) {
const resp = await fetch(url || this.reply());
const data = await resp.text();
let wigal = this.parseResponse(data);
console.log("");
console.log(this.displayText(wigal.userdata));
console.log("");
if (wigal.isEndSession)
process.exit(0);
rl.question("Response: ", async (input) => {
return await this.start(this.reply(wigal, input));
});
} else if (this.provider == "emergent_technology" /* emergent_technology */) {
const { url: url2, body } = this.reply(requestBody);
const resp = await fetch(url2, {
method: "POST",
body: JSON.stringify(body),
headers: { "Content-Type": "application/json" }
});
const json = await resp.json();
console.log("");
console.log(this.displayText(json.Message));
console.log("");
if (json.Type == "Release")
process.exit(0);
rl.question("Response: ", async (input) => {
const { url: url3, body: body2 } = this.reply(json, input);
return await this.start(url3, body2);
});
}
} catch (e) {
console.log("Simulator error: ", e);
this.log(e);
process.exit(1);
}
}
reply(data, input) {
var _a;
if (this.provider === "wigal" /* wigal */) {
input = input == null ? void 0 : input.replace(/#/g, "%23");
data != null ? data : data = {};
data.userdata = input != null ? input : data.userdata;
const url = `${this.baseUrl}?network=${data.network || "wigal_mtn_gh"}&sessionid=${data.sessionid || (0, import_crypto.randomUUID)()}&mode=${data.mode || "start"}&msisdn=${data.msisdn || this.args.phone}&userdata=${input}&username=${data.username || "test_user"}&trafficid=${(0, import_crypto.randomUUID)()}&other=${data.other || ""}`;
this.log(url);
return url;
}
if (this.provider == "emergent_technology" /* emergent_technology */) {
data != null ? data : data = {
Mobile: this.args.phone,
Message: "*714#"
};
data.Message = input != null ? input : data.Message;
data.SessionId = CACHE[this.provider].sessionId || (0, import_crypto.randomUUID)();
(_a = data.Type) != null ? _a : data.Type = "Initiation";
data.Mobile = this.args.phone;
data.Operator = "Vodafone";
data.ServiceCode = "714";
CACHE[this.provider].sessionId = data.SessionId;
return { url: this.baseUrl, body: data };
}
throw new Error(`Reply is not implemented for ${this.provider}`);
}
parseResponse(data) {
this.log(data);
if (this.provider == "wigal") {
let resp = data.split("|");
return {
network: resp[0],
mode: resp[1],
msisdn: resp[2],
sessionid: resp[3],
userdata: resp[4].replace(/\^/g, "\n"),
username: resp[5],
trafficid: resp[6],
other: resp[7],
isEndSession: resp[1] == "end"
};
}
throw new Error(`Response parsing is not implemented for ${this.provider}`);
}
displayText(text) {
text != null ? text : text = "Unable to parse text from response";
return text == null ? void 0 : text.replace(/\^/g, "\n");
}
log(data) {
if (this.args.debug === true || this.args.debug === "true") {
console.log("");
console.log(data);
console.log("");
}
}
};
var simulator = new Simulator();
simulator.init().then(() => simulator.start());
//# sourceMappingURL=simulator.js.map