Commit ef1c8149dcccd83e91dfa052ffb493bd2ae3bc8e

Authored by Adhidarma Hadiwinoto
1 parent 9055e1bc19
Exists in master

Histori pengiriman pesan

Showing 2 changed files with 15 additions and 1 deletions Inline Diff

lib/apiserver/index.js
1 "use strict"; 1 "use strict";
2 2
3 /** 3 /**
4 * Modul untuk menerima callback dari modem handler jika ada SMS masuk. 4 * Modul untuk menerima callback dari modem handler jika ada SMS masuk.
5 */ 5 */
6 6
7 7
8 const express = require('express'); 8 const express = require('express');
9 const moment = require('moment'); 9 const moment = require('moment');
10 10
11 const messagingService = require('komodo-center-messaging-client-lib'); 11 const messagingService = require('komodo-center-messaging-client-lib');
12 12
13 const config = require('komodo-sdk/config'); 13 const config = require('komodo-sdk/config');
14 const logger = require('komodo-sdk/logger'); 14 const logger = require('komodo-sdk/logger');
15 15
16 const transport = require('../transport'); 16 const transport = require('../transport');
17 const partnerLastSeen = require('../partner-last-seen'); 17 const partnerLastSeen = require('../partner-last-seen');
18 const history = require('../history'); 18 const history = require('../history');
19 // const modems = require('../modems2'); 19 // const modems = require('../modems2');
20 20
21 const routerModems = require('./router-modems'); 21 const routerModems = require('./router-modems');
22 22
23 const app = express(); 23 const app = express();
24 messagingService.setTransport(transport); 24 messagingService.setTransport(transport);
25 25
26 function apikeyChecker(req, res, next) { 26 function apikeyChecker(req, res, next) {
27 res.locals.has_valid_apikey = req.params.apikey === config.handler_callback_server.apikey; 27 res.locals.has_valid_apikey = req.params.apikey === config.handler_callback_server.apikey;
28 if (res.locals.has_valid_apikey) { 28 if (res.locals.has_valid_apikey) {
29 next(); 29 next();
30 } 30 }
31 else { 31 else {
32 res.end('APISERVER: Invalid apikey'); 32 res.end('APISERVER: Invalid apikey');
33 } 33 }
34 } 34 }
35 35
36 function onIncomingSms(req, res) { 36 function onIncomingSms(req, res) {
37 res.end('OK'); 37 res.end('OK');
38 38
39 if (!req.query.number) return; 39 if (!req.query.number) return;
40 const numberWithSuffix = req.query.number.replace(/^\+/, '') + (config.number_suffix || ''); 40 const numberWithSuffix = req.query.number.replace(/^\+/, '') + (config.number_suffix || '');
41 41
42 partnerLastSeen.set(req.query.number, req.query.modem_imsi); 42 partnerLastSeen.set(req.query.number, req.query.modem_imsi);
43 43
44 history.push({ 44 history.push({
45 ts: req.query.ts || moment().format('YYYY-MM-DD HH:mm:ss'), 45 ts: req.query.ts || moment().format('YYYY-MM-DD HH:mm:ss'),
46 modem: { 46 modem: {
47 name: req.query.modem, 47 name: req.query.modem,
48 imsi: req.query.modem_imsi, 48 imsi: req.query.modem_imsi,
49 msisdn: req.query.modem_msisdn, 49 msisdn: req.query.modem_msisdn,
50 }, 50 },
51 direction: 'INCOMING', 51 direction: 'INCOMING',
52 partner: req.query.number, 52 partner: req.query.number,
53 message: req.query.msg, 53 message: req.query.msg,
54 }); 54 });
55 55
56 /* 56 /*
57 modems.set({ 57 modems.set({
58 name: req.query.modem, 58 name: req.query.modem,
59 device: req.query.modem_device, 59 device: req.query.modem_device,
60 imsi: req.query.modem_imsi, 60 imsi: req.query.modem_imsi,
61 msisdn: req.query.modem_msisdn, 61 msisdn: req.query.modem_msisdn,
62 networkId: req.query.modem.network_id, 62 networkId: req.query.modem.network_id,
63 networkName: req.query.modem_network_name, 63 networkName: req.query.modem_network_name,
64 signalStrength: req.query.modem_signal_strength, 64 signalStrength: req.query.modem_signal_strength,
65 uptime: req.query.uptime, 65 uptime: req.query.uptime,
66 reportIp: req.query.report_ip || req.ip, 66 reportIp: req.query.report_ip || req.ip,
67 reportPort: req.query.report_port, 67 reportPort: req.query.report_port,
68 reportApikey: req.query.report_apikey, 68 reportApikey: req.query.report_apikey,
69 reportPathSms: req.query.report_path_sms || '/sms', 69 reportPathSms: req.query.report_path_sms || '/sms',
70 }); 70 });
71 */ 71 */
72 72
73 logger.info('APISERVER: Incoming SMS', { modem: req.query.modem, from: req.query.number, from_with_suffix: numberWithSuffix, msg: req.query.msg }); 73 logger.info('APISERVER: Incoming SMS', { modem: req.query.modem, from: req.query.number, from_with_suffix: numberWithSuffix, msg: req.query.msg });
74 messagingService.onIncomingMessage({ 74 messagingService.onIncomingMessage({
75 me: req.query.modem, 75 me: req.query.modem,
76 partner: numberWithSuffix, 76 partner: numberWithSuffix,
77 partner_raw: req.query.number, 77 partner_raw: req.query.number,
78 msg: req.query.msg, 78 msg: req.query.msg,
79 origin_label: `IMSI_${req.query.modem_imsi || 'UNKNOWN'}`, 79 origin_label: `IMSI_${req.query.modem_imsi || 'UNKNOWN'}`,
80 origin_transport: 'SMS', 80 origin_transport: 'SMS',
81 origin_partner: req.query.number, 81 origin_partner: req.query.number,
82 do_not_forward_to_core: req.query.number.indexOf('+') !== 0, 82 do_not_forward_to_core: req.query.number.indexOf('+') !== 0,
83 }) 83 });
84 } 84 }
85 85
86 async function pageHistory(req, res) { 86 async function pageHistory(req, res) {
87 res.json(await history.dump()); 87 res.json(await history.dump());
88 } 88 }
89 89
90 app.use(function(req, res, next) { 90 app.use(function(req, res, next) {
91 if ( req && req.path && typeof req.path === 'string' && req.path.search(/\/modems\/set$/) >= 0 ) { 91 if ( req && req.path && typeof req.path === 'string' && req.path.search(/\/modems\/set$/) >= 0 ) {
92 next(); 92 next();
93 return; 93 return;
94 } 94 }
95 95
96 logger.verbose('APISERVER: Incoming http request', { ip: req.ip, path: req.path, url: req.url }); 96 logger.verbose('APISERVER: Incoming http request', { ip: req.ip, path: req.path, url: req.url });
97 next(); 97 next();
98 }) 98 })
99 99
100 app.use('/apikey/:apikey', apikeyChecker); 100 app.use('/apikey/:apikey', apikeyChecker);
101 app.get('/apikey/:apikey/on-sms', onIncomingSms); 101 app.get('/apikey/:apikey/on-sms', onIncomingSms);
102 app.get('/apikey/:apikey/inbox', onIncomingSms); 102 app.get('/apikey/:apikey/inbox', onIncomingSms);
103 app.get('/apikey/:apikey/on-sms/inbox', onIncomingSms); 103 app.get('/apikey/:apikey/on-sms/inbox', onIncomingSms);
104 app.get('/apikey/:apikey/history', pageHistory); 104 app.get('/apikey/:apikey/history', pageHistory);
105 app.use('/apikey/:apikey/modems', routerModems); 105 app.use('/apikey/:apikey/modems', routerModems);
106 106
107 const listenPort = config && config.handler_callback_server ? config.handler_callback_server.listen_port : null; 107 const listenPort = config && config.handler_callback_server ? config.handler_callback_server.listen_port : null;
108 listenPort && app.listen(listenPort, () => { 108 listenPort && app.listen(listenPort, () => {
109 logger.info('HTTP Handler Callback server listening on port ' + listenPort); 109 logger.info('HTTP Handler Callback server listening on port ' + listenPort);
110 }) 110 })
1 "use strict"; 1 "use strict";
2 2
3 const url = require('url'); 3 const url = require('url');
4 const request = require('request'); 4 const request = require('request');
5 const uuidv4 = require('uuid/v4'); 5 const uuidv4 = require('uuid/v4');
6 const moment = require('moment'); 6 const moment = require('moment');
7 7
8 const config = require('komodo-sdk/config'); 8 const config = require('komodo-sdk/config');
9 const logger = require('komodo-sdk/logger'); 9 const logger = require('komodo-sdk/logger');
10 10
11 const messagingService = require('komodo-center-messaging-client-lib');
12
11 const modemSelect = require('./modemSelect'); 13 const modemSelect = require('./modemSelect');
12 const modems = require('./modems2'); 14 const modems = require('./modems2');
13 const partnerLastSeen = require('./partner-last-seen'); 15 const partnerLastSeen = require('./partner-last-seen');
14 const history = require('./history'); 16 const history = require('./history');
15 17
16 function _send(destinationNumber, msg, handlerIMSI) { 18 function _send(destinationNumber, msg, handlerIMSI) {
17 19
18 if (msg.length > 160) { 20 if (msg.length > 160) {
19 logger.info('Splitting message'); 21 logger.info('Splitting message');
20 22
21 const newMsg = msg.slice(0, 160); 23 const newMsg = msg.slice(0, 160);
22 const remainingMsg = msg.slice(160); 24 const remainingMsg = msg.slice(160);
23 25
24 _send(destinationNumber, newMsg, handlerIMSI); 26 _send(destinationNumber, newMsg, handlerIMSI);
25 setTimeout(() => { 27 setTimeout(() => {
26 _send(destinationNumber, remainingMsg, handlerIMSI); 28 _send(destinationNumber, remainingMsg, handlerIMSI);
27 }, 1000); 29 }, 1000);
28 30
29 return; 31 return;
30 } 32 }
31 33
32 const modem = modems.get('imsi', handlerIMSI); 34 const modem = modems.get('imsi', handlerIMSI);
33 if (!modem) { 35 if (!modem) {
34 logger.warn('Not knowing modem to use. Ignoring message', { destination_number: destinationNumber, msg: msg, modem_imsi: handlerIMSI }); 36 logger.warn('Not knowing modem to use. Ignoring message', { destination_number: destinationNumber, msg: msg, modem_imsi: handlerIMSI });
35 return; 37 return;
36 } 38 }
37 39
38 if (!modem.reportIp || !modem.reportPort || !modem.reportApikey) { 40 if (!modem.reportIp || !modem.reportPort || !modem.reportApikey) {
39 logger.warn('Invalid modem configuration', { modem }); 41 logger.warn('Invalid modem configuration', { modem });
40 return; 42 return;
41 } 43 }
42 44
43 const reqId = uuidv4(); 45 const reqId = uuidv4();
44 46
45 history.push({ 47 history.push({
46 ts: moment().format('YYYY-MM-DD HH:mm:ss'), 48 ts: moment().format('YYYY-MM-DD HH:mm:ss'),
47 modem: { 49 modem: {
48 name: modem.name, 50 name: modem.name,
49 imsi: modem.imsi, 51 imsi: modem.imsi,
50 msisdn: modem.msisdn, 52 msisdn: modem.msisdn,
51 }, 53 },
52 direction: 'OUTGOING', 54 direction: 'OUTGOING',
53 partner: destinationNumber, 55 partner: destinationNumber,
54 message: msg, 56 message: msg,
55 }); 57 });
56 58
59 messagingService.onIncomingMessage({
60 me: modem.name,
61 partner: destinationNumber,
62 partner_raw: `+${destinationNumber}`.replace(/^\++/, '+'),
63 msg: msg,
64 origin_label: `IMSI_${modem.imsi || 'UNKNOWN'}`,
65 origin_transport: 'SMS',
66 origin_partner: destinationNumber,
67 do_not_forward_to_core: true,
68 is_outgoing: true,
69 });
70
57 const requestOptions = { 71 const requestOptions = {
58 url: url.format({ 72 url: url.format({
59 protocol: 'http', 73 protocol: 'http',
60 hostname: modem.reportIp, 74 hostname: modem.reportIp,
61 port: modem.reportPort, 75 port: modem.reportPort,
62 pathname: modem.reportPathSms || '/sms', 76 pathname: modem.reportPathSms || '/sms',
63 }), 77 }),
64 qs: { 78 qs: {
65 msg: msg, 79 msg: msg,
66 number: destinationNumber, 80 number: destinationNumber,
67 reqid: reqId, 81 reqid: reqId,
68 apikey: modem.reportApikey, 82 apikey: modem.reportApikey,
69 } 83 }
70 } 84 }
71 85
72 logger.info('Sending message to modem handler', { req_id: reqId, destination_number: destinationNumber, msg: msg, msg_length: msg.length, modem_name: modem.name, modem_imsi: modem.imsi }); 86 logger.info('Sending message to modem handler', { req_id: reqId, destination_number: destinationNumber, msg: msg, msg_length: msg.length, modem_name: modem.name, modem_imsi: modem.imsi });
73 request(requestOptions, function(err, res, body) { 87 request(requestOptions, function(err, res, body) {
74 if (err) { 88 if (err) {
75 logger.warn('Error requesting to modem handler. ' + err.toString(), { req_id: reqId, modem_name: modem.name, modem_imsi: modem.imsi }); 89 logger.warn('Error requesting to modem handler. ' + err.toString(), { req_id: reqId, modem_name: modem.name, modem_imsi: modem.imsi });
76 90
77 } 91 }
78 else if (res.statusCode != 200) { 92 else if (res.statusCode != 200) {
79 logger.warn('Modem handler not responding with HTTP status code 200.', { http_status_code: res.statusCode, req_id: reqId, modem_name: modem.name, modem_imsi: modem.imsi }); 93 logger.warn('Modem handler not responding with HTTP status code 200.', { http_status_code: res.statusCode, req_id: reqId, modem_name: modem.name, modem_imsi: modem.imsi });
80 } 94 }
81 else { 95 else {
82 logger.verbose('Message sent to handler', { req_id: reqId, modem_name: modem.name, modem_imsi: modem.imsi, response_body: body }); 96 logger.verbose('Message sent to handler', { req_id: reqId, modem_name: modem.name, modem_imsi: modem.imsi, response_body: body });
83 } 97 }
84 }) 98 })
85 99
86 } 100 }
87 101
88 async function send(partner, msg) { 102 async function send(partner, msg) {
89 if (!partner) return; 103 if (!partner) return;
90 104
91 if (typeof msg !== 'string') { 105 if (typeof msg !== 'string') {
92 logger.warn('Message to send is not a string, ignoring message'); 106 logger.warn('Message to send is not a string, ignoring message');
93 return; 107 return;
94 } 108 }
95 109
96 msg = msg.trim(); 110 msg = msg.trim();
97 if (!msg) return; 111 if (!msg) return;
98 112
99 const destinationNumber = modemSelect.removeSuffixFromNumber(partner, config); 113 const destinationNumber = modemSelect.removeSuffixFromNumber(partner, config);
100 114
101 // logger.verbose('Choosing handler name', { partner, destinationNumber, msg, origin }); 115 // logger.verbose('Choosing handler name', { partner, destinationNumber, msg, origin });
102 const handlerIMSI = await partnerLastSeen.get(destinationNumber) ; 116 const handlerIMSI = await partnerLastSeen.get(destinationNumber) ;
103 117
104 if (!handlerIMSI) { 118 if (!handlerIMSI) {
105 logger.warn(`Unknown handler for sending message to partner`, { partner, destinationNumber }); 119 logger.warn(`Unknown handler for sending message to partner`, { partner, destinationNumber });
106 return; 120 return;
107 } 121 }
108 122
109 _send(destinationNumber, msg, handlerIMSI); 123 _send(destinationNumber, msg, handlerIMSI);
110 } 124 }
111 125
112 exports.send = send; 126 exports.send = send;