Commit ef1c8149dcccd83e91dfa052ffb493bd2ae3bc8e
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 | }) |
lib/transport.js
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; |