mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2026-01-25 02:07:56 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c4c5b6ba8 | ||
|
|
381eee9bcb | ||
|
|
7dc6b782f5 | ||
|
|
18d2dfa053 | ||
|
|
2e3d783dee | ||
|
|
6dc019e836 | ||
|
|
a22bc8ea42 | ||
|
|
0356b996ba | ||
|
|
271587617e | ||
|
|
0b29e67a0c | ||
|
|
e656d275fe | ||
|
|
fabf01f8b5 | ||
|
|
85ab75d8e3 | ||
|
|
5c2630fe1f | ||
|
|
9942313ea1 |
@@ -1,4 +1,4 @@
|
||||
FROM --platform=linux/amd64 node:18.14.1-alpine3.16 as base
|
||||
FROM --platform=linux/amd64 node:18.15-alpine3.16 as base
|
||||
|
||||
RUN apk --update --no-cache add --virtual .builds-deps build-base python3
|
||||
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
"at the tone",
|
||||
"leave a message",
|
||||
"leave me a message",
|
||||
"not available right now",
|
||||
"not available to take your call",
|
||||
"not available",
|
||||
"can't take your call",
|
||||
"I will get back to you",
|
||||
"will get back to you",
|
||||
"I'll get back to you",
|
||||
"we will get back to you",
|
||||
"we are unable",
|
||||
"we are not available"
|
||||
"we are unable"
|
||||
],
|
||||
"es-ES": [
|
||||
"le pasamos la llamada",
|
||||
@@ -48,5 +45,18 @@
|
||||
"ens posarem en contacto",
|
||||
"ara no estem disponibles",
|
||||
"no hi som"
|
||||
],
|
||||
"de-DE": [
|
||||
"nicht erreichbar",
|
||||
"nnruf wurde weitergeleitet",
|
||||
"beim piepsen",
|
||||
"am ton",
|
||||
"eine nachricht hinterlassen",
|
||||
"hinterlasse mir eine Nachricht",
|
||||
"nicht verfügbar",
|
||||
"kann ihren anruf nicht entgegennehmen",
|
||||
"wird sich bei Ihnen melden",
|
||||
"ich melde mich bei dir",
|
||||
"wir können nicht"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ router.post('/', async(req, res) => {
|
||||
const target = restDial.to;
|
||||
const opts = {
|
||||
callingNumber: restDial.from,
|
||||
...(restDial.callerName && {callingName: restDial.callerName}),
|
||||
headers: req.body.headers || {}
|
||||
};
|
||||
|
||||
@@ -90,8 +91,13 @@ router.post('/', async(req, res) => {
|
||||
* check if from-number matches any existing numbers on Jambonz
|
||||
* */
|
||||
if (target.type === 'phone' && !target.trunk) {
|
||||
const {lookupCarrierByPhoneNumber} = dbUtils(this.logger, srf);
|
||||
const voip_carrier_sid = await lookupCarrierByPhoneNumber(req.body.account_sid, restDial.from);
|
||||
const {lookupCarrierByPhoneNumber, lookupCarrierByLcr} = dbUtils(this.logger, srf);
|
||||
// firstly LCR
|
||||
let voip_carrier_sid = await lookupCarrierByLcr(req.body.account_sid, to);
|
||||
if (!voip_carrier_sid) {
|
||||
// later by phone
|
||||
voip_carrier_sid = await lookupCarrierByPhoneNumber(req.body.account_sid, restDial.from);
|
||||
}
|
||||
logger.info(
|
||||
`createCall: selected ${voip_carrier_sid} for requested phone number: ${restDial.from || 'unspecified'})`);
|
||||
if (voip_carrier_sid) {
|
||||
|
||||
@@ -248,8 +248,9 @@ module.exports = function(srf, logger) {
|
||||
const app2 = JAMBONES_MYSQL_REFRESH_TTL ? JSON.parse(JSON.stringify(app)) : app;
|
||||
if ('WS' === app.call_hook?.method ||
|
||||
app.call_hook?.url.startsWith('ws://') || app.call_hook?.url.startsWith('wss://')) {
|
||||
app2.requestor = new WsRequestor(logger, account_sid, app.call_hook, accountInfo.account.webhook_secret) ;
|
||||
app2.notifier = app.requestor;
|
||||
const requestor = new WsRequestor(logger, account_sid, app.call_hook, accountInfo.account.webhook_secret) ;
|
||||
app2.requestor = requestor;
|
||||
app2.notifier = requestor;
|
||||
app2.call_hook.method = 'WS';
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -529,7 +529,7 @@ class CallSession extends Emitter {
|
||||
this.logger.info({currInput, newInput},
|
||||
'CallSession:enableBotMode - restarting background gather to apply new input type');
|
||||
this.backgroundGatherTask.sticky = false;
|
||||
this.disableBotMode();
|
||||
await this.disableBotMode();
|
||||
}
|
||||
}
|
||||
this.backgroundGatherTask = task;
|
||||
@@ -568,12 +568,12 @@ class CallSession extends Emitter {
|
||||
this.logger.info({err, gather}, 'CallSession:enableBotMode - Error creating gather task');
|
||||
}
|
||||
}
|
||||
disableBotMode() {
|
||||
async disableBotMode() {
|
||||
this._bargeInEnabled = false;
|
||||
if (this.backgroundGatherTask) {
|
||||
try {
|
||||
this.backgroundGatherTask.removeAllListeners();
|
||||
this.backgroundGatherTask.kill().catch((err) => {});
|
||||
await this.backgroundGatherTask.kill();
|
||||
} catch (err) {}
|
||||
this.backgroundGatherTask = null;
|
||||
}
|
||||
@@ -724,7 +724,7 @@ class CallSession extends Emitter {
|
||||
}
|
||||
else {
|
||||
this.logger.info('CallSession:exec disabling bot mode to start gather with new options');
|
||||
this.disableBotMode();
|
||||
await this.disableBotMode();
|
||||
}
|
||||
}
|
||||
if (!skip) {
|
||||
@@ -1192,7 +1192,7 @@ class CallSession extends Emitter {
|
||||
}
|
||||
|
||||
_onCommand({msgid, command, call_sid, queueCommand, data}) {
|
||||
this.logger.info({msgid, command, queueCommand}, 'CallSession:_onCommand - received command');
|
||||
this.logger.info({msgid, command, queueCommand, data}, 'CallSession:_onCommand - received command');
|
||||
const resolution = {reason: 'received command', queue: queueCommand, command};
|
||||
switch (command) {
|
||||
case 'redirect':
|
||||
|
||||
@@ -85,6 +85,7 @@ class TaskDial extends Task {
|
||||
|
||||
this.earlyMedia = this.data.answerOnBridge === true;
|
||||
this.callerId = this.data.callerId;
|
||||
this.callerName = this.data.callerName;
|
||||
this.dialMusic = this.data.dialMusic;
|
||||
this.headers = this.data.headers || {};
|
||||
this.method = this.data.method || 'POST';
|
||||
@@ -398,7 +399,7 @@ class TaskDial extends Task {
|
||||
const {req, srf} = cs;
|
||||
const {getSBC} = srf.locals;
|
||||
const {lookupTeamsByAccount, lookupAccountBySid} = srf.locals.dbHelpers;
|
||||
const {lookupCarrier, lookupCarrierByPhoneNumber} = dbUtils(this.logger, cs.srf);
|
||||
const {lookupCarrier, lookupCarrierByLcr} = dbUtils(this.logger, cs.srf);
|
||||
const sbcAddress = this.proxy || getSBC();
|
||||
const teamsInfo = {};
|
||||
let fqdn;
|
||||
@@ -415,7 +416,8 @@ class TaskDial extends Task {
|
||||
const opts = {
|
||||
headers: this.headers,
|
||||
proxy: `sip:${sbcAddress}`,
|
||||
callingNumber: this.callerId || req.callingNumber
|
||||
callingNumber: this.callerId || req.callingNumber,
|
||||
...(this.callerName && {callingName: this.callerName})
|
||||
};
|
||||
|
||||
const t = this.target.find((t) => t.type === 'teams');
|
||||
@@ -465,10 +467,10 @@ class TaskDial extends Task {
|
||||
|
||||
/**
|
||||
* trunk isn't specified,
|
||||
* check if number matches any existing numbers
|
||||
* check if number matches any LCR routes
|
||||
* */
|
||||
if (t.type === 'phone' && !t.trunk) {
|
||||
const voip_carrier_sid = await lookupCarrierByPhoneNumber(req.body.account_sid, t.number);
|
||||
const voip_carrier_sid = lookupCarrierByLcr(req.body.account_sid, t.number);
|
||||
this.logger.info(
|
||||
`Dial:_attemptCalls: selected ${voip_carrier_sid} for requested phone number: ${t.number})`);
|
||||
if (voip_carrier_sid) {
|
||||
|
||||
@@ -11,6 +11,7 @@ class TaskRestDial extends Task {
|
||||
super(logger, opts);
|
||||
|
||||
this.from = this.data.from;
|
||||
this.callerName = this.data.callerName;
|
||||
this.fromHost = this.data.fromHost;
|
||||
this.to = this.data.to;
|
||||
this.call_hook = this.data.call_hook;
|
||||
|
||||
@@ -184,7 +184,7 @@ module.exports = (logger) => {
|
||||
const {vendor, language} = ep.amd;
|
||||
ep.startTranscription({
|
||||
vendor,
|
||||
language,
|
||||
locale: language,
|
||||
interim: true,
|
||||
bugname
|
||||
}).catch((err) => {
|
||||
|
||||
@@ -150,10 +150,41 @@ module.exports = (logger, srf) => {
|
||||
}
|
||||
};
|
||||
|
||||
const sqlQueryLcrByAccountSid = `SELECT lcr_sid FROM lcr WHERE account_sid = ? OR
|
||||
service_provider_sid = (SELECT service_provider_sid from accounts where account_sid = ?)`;
|
||||
const sqlQueryLcrRouteByLcrSid = 'SELECT * FROM lcr_routes WHERE lcr_sid = ? ORDER BY priority';
|
||||
const sqlQueryLcrCarrierSetEntryByLcrRouteSid = `SELECT * FROM lcr_carrier_set_entry
|
||||
WHERE lcr_route_sid = ? ORDER BY priority`;
|
||||
const lookupCarrierByLcr = async(account_sid, toNumber) => {
|
||||
const pp = pool.promise();
|
||||
try {
|
||||
const [lcrs] = await pp.query(sqlQueryLcrByAccountSid, [account_sid, account_sid]);
|
||||
if (lcrs.length) {
|
||||
const lcr_sid = lcrs[0];
|
||||
const [lcr_routes] = await pp.query(sqlQueryLcrRouteByLcrSid, [lcr_sid]);
|
||||
if (lcr_routes.length) {
|
||||
for (const r of lcr_routes) {
|
||||
var matcher = new RegExp(r.regex);
|
||||
if (matcher.test(toNumber)) {
|
||||
const [entries] = await pp.query(sqlQueryLcrCarrierSetEntryByLcrRouteSid, [r.lcr_route_sid]);
|
||||
// Currently just support first entry;
|
||||
if (entries.length) {
|
||||
return entries[0].voip_carrier_sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error({error}, `lookupCarrierByLcr: Error ${account_sid}:${toNumber}`);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
lookupAccountDetails,
|
||||
updateSpeechCredentialLastUsed,
|
||||
lookupCarrier,
|
||||
lookupCarrierByPhoneNumber
|
||||
lookupCarrierByPhoneNumber,
|
||||
lookupCarrierByLcr
|
||||
};
|
||||
};
|
||||
|
||||
28
package-lock.json
generated
28
package-lock.json
generated
@@ -15,7 +15,7 @@
|
||||
"@jambonz/speech-utils": "^0.0.12",
|
||||
"@jambonz/stats-collector": "^0.1.8",
|
||||
"@jambonz/time-series": "^0.2.5",
|
||||
"@jambonz/verb-specifications": "^0.0.12",
|
||||
"@jambonz/verb-specifications": "^0.0.16",
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"@opentelemetry/exporter-jaeger": "^1.9.0",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "^0.35.0",
|
||||
@@ -29,7 +29,7 @@
|
||||
"bent": "^7.3.12",
|
||||
"debug": "^4.3.4",
|
||||
"deepcopy": "^2.1.0",
|
||||
"drachtio-fsmrf": "^3.0.20",
|
||||
"drachtio-fsmrf": "^3.0.21",
|
||||
"drachtio-srf": "^4.5.23",
|
||||
"express": "^4.18.2",
|
||||
"ip": "^1.1.8",
|
||||
@@ -1664,9 +1664,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@jambonz/verb-specifications": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.12.tgz",
|
||||
"integrity": "sha512-NU+9iVCqyn8GI/QG1gKhBb9h9poEIAxfydFdDOpXOXcT4nlwuT/RLM+6X2wJcysqcc2hA/4aPhk0lMnw0H6ejg==",
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.16.tgz",
|
||||
"integrity": "sha512-2ZHpbBmqhRT9a4Cs8HEQncvdp1zS7MbzLsFynVu3gSpvgfeepRtqWX8rxG9VF9Mr+AbJoeCfo+MO0PyJCPWTMA==",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
"pino": "^8.8.0"
|
||||
@@ -3220,9 +3220,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/drachtio-fsmrf": {
|
||||
"version": "3.0.20",
|
||||
"resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.20.tgz",
|
||||
"integrity": "sha512-ksOe5XiR0LjASHiEIOUT7YMbowKdlB1eFoM+fmSkrBi5ogcbM7RNYg6ugt+WrSc01DMbi/5BN2QhefwdzelaEQ==",
|
||||
"version": "3.0.21",
|
||||
"resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.21.tgz",
|
||||
"integrity": "sha512-j5C1KFFEr+N8Qqp5ZjfqQTox+nDKoII3eJOaRMj0zHmFzr7tFzHbwPf8JSQS9n0OjrY6iM1zJJxHO+zDp8974g==",
|
||||
"dependencies": {
|
||||
"camel-case": "^4.1.2",
|
||||
"debug": "^2.6.9",
|
||||
@@ -10011,9 +10011,9 @@
|
||||
}
|
||||
},
|
||||
"@jambonz/verb-specifications": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.12.tgz",
|
||||
"integrity": "sha512-NU+9iVCqyn8GI/QG1gKhBb9h9poEIAxfydFdDOpXOXcT4nlwuT/RLM+6X2wJcysqcc2hA/4aPhk0lMnw0H6ejg==",
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.16.tgz",
|
||||
"integrity": "sha512-2ZHpbBmqhRT9a4Cs8HEQncvdp1zS7MbzLsFynVu3gSpvgfeepRtqWX8rxG9VF9Mr+AbJoeCfo+MO0PyJCPWTMA==",
|
||||
"requires": {
|
||||
"debug": "^4.3.4",
|
||||
"pino": "^8.8.0"
|
||||
@@ -11213,9 +11213,9 @@
|
||||
}
|
||||
},
|
||||
"drachtio-fsmrf": {
|
||||
"version": "3.0.20",
|
||||
"resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.20.tgz",
|
||||
"integrity": "sha512-ksOe5XiR0LjASHiEIOUT7YMbowKdlB1eFoM+fmSkrBi5ogcbM7RNYg6ugt+WrSc01DMbi/5BN2QhefwdzelaEQ==",
|
||||
"version": "3.0.21",
|
||||
"resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.21.tgz",
|
||||
"integrity": "sha512-j5C1KFFEr+N8Qqp5ZjfqQTox+nDKoII3eJOaRMj0zHmFzr7tFzHbwPf8JSQS9n0OjrY6iM1zJJxHO+zDp8974g==",
|
||||
"requires": {
|
||||
"camel-case": "^4.1.2",
|
||||
"debug": "^2.6.9",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@jambonz/speech-utils": "^0.0.12",
|
||||
"@jambonz/stats-collector": "^0.1.8",
|
||||
"@jambonz/time-series": "^0.2.5",
|
||||
"@jambonz/verb-specifications": "^0.0.12",
|
||||
"@jambonz/verb-specifications": "^0.0.16",
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"@opentelemetry/exporter-jaeger": "^1.9.0",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "^0.35.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"bent": "^7.3.12",
|
||||
"debug": "^4.3.4",
|
||||
"deepcopy": "^2.1.0",
|
||||
"drachtio-fsmrf": "^3.0.20",
|
||||
"drachtio-fsmrf": "^3.0.21",
|
||||
"drachtio-srf": "^4.5.23",
|
||||
"express": "^4.18.2",
|
||||
"ip": "^1.1.8",
|
||||
|
||||
@@ -31,6 +31,7 @@ test('\'dial-phone\'', async(t) => {
|
||||
{
|
||||
"verb": "dial",
|
||||
"callerId": from,
|
||||
"callerName": "test_callerName",
|
||||
"actionHook": "/actionHook",
|
||||
"timeLimit": 5,
|
||||
"target": [
|
||||
@@ -56,6 +57,7 @@ test('\'dial-phone\'', async(t) => {
|
||||
"method": "POST",
|
||||
},
|
||||
"from": from,
|
||||
"callerName": "Tom",
|
||||
"to": {
|
||||
"type": "phone",
|
||||
"number": "15583084808"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const Websocket = require('ws');
|
||||
const {PORT} = require('../../lib/config');
|
||||
const listenPort = PORT;
|
||||
const listenPort = process.env.HTTP_PORT || 3000;
|
||||
let json_mapping = new Map();
|
||||
let hook_mapping = new Map();
|
||||
let ws_packet_count = new Map();
|
||||
|
||||
@@ -12,6 +12,7 @@ const {
|
||||
OTEL_EXPORTER_JAEGER_AGENT_HOST,
|
||||
OTEL_EXPORTER_JAEGER_ENDPOINT,
|
||||
OTEL_EXPORTER_ZIPKIN_URL,
|
||||
OTEL_EXPORTER_COLLECTOR_URL
|
||||
} = require('./lib/config');
|
||||
|
||||
module.exports = (serviceName) => {
|
||||
@@ -33,7 +34,7 @@ module.exports = (serviceName) => {
|
||||
}
|
||||
else {
|
||||
exporter = new OTLPTraceExporter({
|
||||
url: process.OTEL_EXPORTER_COLLECTOR_URL
|
||||
url: OTEL_EXPORTER_COLLECTOR_URL
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user