diff --git a/src/builder.js b/src/builder.js new file mode 100644 index 0000000..dd0d52b --- /dev/null +++ b/src/builder.js @@ -0,0 +1,41 @@ +const crypto = require("crypto"); + +const scenario = require("./scenario"); +const config = require("./config"); +const request = require("./request").request; + +function builder(scenarioName, scenarioConfig) { + const scenes = []; + + const builtScenario = scenario[scenarioName](scenarioConfig); + const sessionId = crypto.randomBytes(16).toString("hex"); + + for (const scene of builtScenario) { + scene.sessionId = sessionId; + Object.assign(scene, config); + + scenes.push(scene); + } + + return scenes; +} + +function parseScenario(scenarioString) { + const parsedScenario = scenarioString.split(" "); + + return builder(parsedScenario[0], parseScenarioConfig(parsedScenario[1])); +} + +function parseScenarioConfig(scenarioConfigString) { + const configs = scenarioConfigString.split(","); + const configObject = {}; + + for (const conf of configs) { + [key, value] = conf.split("="); + configObject[key] = value; + } + + return configObject; +} + +module.exports = { parseScenario }; diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..0cf92a7 --- /dev/null +++ b/src/config.js @@ -0,0 +1,13 @@ +module.exports = { + ussd: { + serviceCode: "*483*061#", + endpoint: "https://ussd.grassecon.net", + timeout: 3000, + }, + test: { + waitNextMenu: 3000, + }, + user: { + ussdPhone: "254711777734", + }, +}; diff --git a/src/executor.js b/src/executor.js new file mode 100644 index 0000000..5885e51 --- /dev/null +++ b/src/executor.js @@ -0,0 +1,21 @@ +const setTimeout = require("timers/promises").setTimeout; + +const parseScenario = require("./builder").parseScenario; +const request = require("./request").request; + +let scenarioFile = `reset_pin current_pin=2222,new_pin=3333\nreset_pin current_pin=3333,new_pin=4444`; + +const parsedScenarioFile = scenarioFile.split("\n"); + +async function execute() { + for (const work of parsedScenarioFile) { + const parsedWork = parseScenario(work); + + for (const requestJob of parsedWork) { + await request(requestJob); + await setTimeout(requestJob.test.waitNextMenu); + } + } +} + +execute(); diff --git a/src/request.js b/src/request.js new file mode 100644 index 0000000..a31a045 --- /dev/null +++ b/src/request.js @@ -0,0 +1,34 @@ +const phin = require("phin"); +const rangi = require("rangi"); + +async function request(builtObject) { + const requestOptions = { + url: builtObject.ussd.endpoint, + method: "POST", + parse: "string", + timeout: builtObject.ussd.timeout, + form: { + sessionId: builtObject.sessionId, + phoneNumber: builtObject.user.ussdPhone, + serviceCode: builtObject.ussd.serviceCode, + text: builtObject.input, + }, + }; + + try { + const { body } = await phin(requestOptions); + + if (body.length > 1) { + console.log(rangi.yellow(`${builtObject.input}\n-------------`)); + console.log(rangi.cyan(`${body.slice(4)}\n-------------`)); + + return; + } + + throw new Error("EMPTY_BODY"); + } catch (error) { + console.log(error); + } +} + +module.exports = { request }; diff --git a/src/scenario.js b/src/scenario.js new file mode 100644 index 0000000..937b791 --- /dev/null +++ b/src/scenario.js @@ -0,0 +1,16 @@ +module.exports = { + reset_pin: function (input) { + return [ + { input: `` }, + { input: `3` }, + { input: `3*5` }, + { input: `3*5*1` }, + { input: `3*5*1*${input.current_pin}` }, + { input: `3*5*1*${input.current_pin}*${input.new_pin}` }, + { input: `3*5*1*${input.current_pin}*${input.new_pin}*${input.new_pin}` }, + { + input: `3*5*1*${input.current_pin}*${input.new_pin}*${input.new_pin}*99`, + }, + ]; + }, +};