mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-01-25 02:08:24 +00:00
Compare commits
41 Commits
v0.7.1-rc2
...
v0.7.5-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c432b71a64 | ||
|
|
77f945bc6b | ||
|
|
8c54e80d46 | ||
|
|
815aea5c75 | ||
|
|
8097f0afda | ||
|
|
31a98d5c81 | ||
|
|
9205cd76a7 | ||
|
|
090bfbce92 | ||
|
|
038e1d3917 | ||
|
|
252de64d10 | ||
|
|
c65e50e79f | ||
|
|
cd935999a6 | ||
|
|
863d7a02c8 | ||
|
|
45c023e374 | ||
|
|
f634ca4076 | ||
|
|
654f93b30c | ||
|
|
280aaef120 | ||
|
|
e6931574e3 | ||
|
|
1bd21cb39d | ||
|
|
480e1155f3 | ||
|
|
75e7c1058b | ||
|
|
a5e4fafda4 | ||
|
|
2e041df6e4 | ||
|
|
3ee82d6c8c | ||
|
|
d396c5b252 | ||
|
|
daef0ee215 | ||
|
|
1d168e93e1 | ||
|
|
605a0e762f | ||
|
|
c9bf943656 | ||
|
|
3aac11560a | ||
|
|
bb4a20a375 | ||
|
|
45c4c626f2 | ||
|
|
65e6d75f72 | ||
|
|
c6bb273aa0 | ||
|
|
256b295be1 | ||
|
|
693ba51339 | ||
|
|
531366ee58 | ||
|
|
a36604029c | ||
|
|
63a88844aa | ||
|
|
24f6833493 | ||
|
|
4119d766d5 |
@@ -8,7 +8,7 @@
|
||||
"jsx": false,
|
||||
"modules": false
|
||||
},
|
||||
"ecmaVersion": 2018
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"plugins": ["promise"],
|
||||
"rules": {
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
package-lock.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
|
||||
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm run jslint
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:17.0.1-slim
|
||||
FROM node:17
|
||||
WORKDIR /opt/app/
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
|
||||
14
app.js
14
app.js
@@ -9,7 +9,8 @@ const opts = Object.assign({
|
||||
const logger = require('pino')(opts);
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
app.disable('x-powered-by');
|
||||
const helmet = require('helmet');
|
||||
const rateLimit = require('express-rate-limit');
|
||||
const cors = require('cors');
|
||||
const passport = require('passport');
|
||||
const routes = require('./lib/routes');
|
||||
@@ -89,6 +90,17 @@ const unless = (paths, middleware) => {
|
||||
return middleware(req, res, next);
|
||||
};
|
||||
};
|
||||
|
||||
const limiter = rateLimit({
|
||||
windowMs: (process.env.RATE_LIMIT_WINDOWS_MINS || 5) * 60 * 1000, // 5 minutes
|
||||
max: process.env.RATE_LIMIT_MAX_PER_WINDOW || 600, // Limit each IP to 600 requests per `window`
|
||||
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
|
||||
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
|
||||
});
|
||||
|
||||
app.use(limiter);
|
||||
app.use(helmet());
|
||||
app.use(helmet.hidePoweredBy());
|
||||
app.use(passport.initialize());
|
||||
app.use(cors());
|
||||
app.use(express.urlencoded({extended: true}));
|
||||
|
||||
@@ -365,7 +365,7 @@ CREATE TABLE webhooks
|
||||
(
|
||||
webhook_sid CHAR(36) NOT NULL UNIQUE ,
|
||||
url VARCHAR(1024) NOT NULL,
|
||||
method ENUM("GET","POST") NOT NULL DEFAULT 'POST',
|
||||
method ENUM("GET","POST","WS") NOT NULL DEFAULT 'POST',
|
||||
username VARCHAR(255),
|
||||
password VARCHAR(255),
|
||||
PRIMARY KEY (webhook_sid)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
const {promisePool} = require('../lib/db');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const {generateHashedPassword} = require('../lib/utils/password-utils');
|
||||
const sqlInsert = `INSERT into users
|
||||
(user_sid, name, email, hashed_password, force_change, provider, email_validated)
|
||||
|
||||
@@ -2,7 +2,8 @@ const debug = require('debug')('jambonz:api-server');
|
||||
const Model = require('./model');
|
||||
const {getMysqlConnection} = require('../db');
|
||||
const {promisePool} = require('../db');
|
||||
const uuid = require('uuid').v4;
|
||||
const { v4: uuid } = require('uuid');
|
||||
|
||||
const {encrypt} = require('../utils/encrypt-decrypt');
|
||||
|
||||
const retrieveSql = `SELECT * from accounts acc
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const Emitter = require('events');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const assert = require('assert');
|
||||
const {getMysqlConnection} = require('../db');
|
||||
const {DbErrorBadRequest} = require('../utils/errors');
|
||||
|
||||
@@ -8,7 +8,7 @@ const ApiKey = require('../../models/api-key');
|
||||
const ServiceProvider = require('../../models/service-provider');
|
||||
const {deleteDnsRecords} = require('../../utils/dns-utils');
|
||||
const {deleteCustomer} = require('../../utils/stripe-utils');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const snakeCase = require('../../utils/snake-case');
|
||||
const sysError = require('../error');
|
||||
const {promisePool} = require('../../db');
|
||||
@@ -19,6 +19,23 @@ const translator = short();
|
||||
|
||||
let idx = 0;
|
||||
|
||||
const getFsUrl = async(logger, retrieveSet, setName) => {
|
||||
if (process.env.K8S) return `http://${process.env.K8S_FEATURE_SERVER_SERVICE_NAME}:3000/v1/createCall`;
|
||||
|
||||
try {
|
||||
const fs = await retrieveSet(setName);
|
||||
if (0 === fs.length) {
|
||||
logger.info('No available feature servers to handle createCall API request');
|
||||
return ;
|
||||
}
|
||||
const ip = stripPort(fs[idx++ % fs.length]);
|
||||
logger.info({fs}, `feature servers available for createCall API request, selecting ${ip}`);
|
||||
return `http://${ip}:3000/v1/createCall`;
|
||||
} catch (err) {
|
||||
logger.error({err}, 'getFsUrl: error retreving feature servers from redis');
|
||||
}
|
||||
};
|
||||
|
||||
const stripPort = (hostport) => {
|
||||
const arr = /^(.*):(.*)$/.exec(hostport);
|
||||
if (arr) return arr[1];
|
||||
@@ -99,7 +116,9 @@ function validateUpdateCall(opts) {
|
||||
'listen_status',
|
||||
'conf_hold_status',
|
||||
'conf_mute_status',
|
||||
'mute_status']
|
||||
'mute_status',
|
||||
'sip_request'
|
||||
]
|
||||
.reduce((acc, prop) => (opts[prop] ? ++acc : acc), 0);
|
||||
|
||||
switch (count) {
|
||||
@@ -133,6 +152,10 @@ function validateUpdateCall(opts) {
|
||||
if (opts.conf_mute_status && !['mute', 'unmute'].includes(opts.conf_mute_status)) {
|
||||
throw new DbErrorBadRequest('invalid conf_mute_status');
|
||||
}
|
||||
if (opts.sip_request &&
|
||||
(!opts.sip_request.method && !opts.sip_request.content_type || !opts.sip_request.content_type)) {
|
||||
throw new DbErrorBadRequest('sip_request requires content_type and content properties');
|
||||
}
|
||||
}
|
||||
|
||||
function validateTo(to) {
|
||||
@@ -567,18 +590,11 @@ router.post('/:sid/Calls', async(req, res) => {
|
||||
const setName = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-fs`;
|
||||
const {retrieveSet, logger} = req.app.locals;
|
||||
|
||||
const serviceUrl = await getFsUrl(logger, retrieveSet, setName);
|
||||
if (!serviceUrl) res.json({msg: 'no available feature servers at this time'}).status(480);
|
||||
try {
|
||||
const fs = await retrieveSet(setName);
|
||||
if (0 === fs.length) {
|
||||
logger.info('No available feature servers to handle createCall API request');
|
||||
return res.json({msg: 'no available feature servers at this time'}).status(500);
|
||||
}
|
||||
const ip = stripPort(fs[idx++ % fs.length]);
|
||||
logger.info({fs}, `feature servers available for createCall API request, selecting ${ip}`);
|
||||
const serviceUrl = `http://${ip}:3000/v1/createCall`;
|
||||
await validateCreateCall(logger, sid, req);
|
||||
|
||||
logger.debug({payload: req.body}, `sending createCall API request to to ${ip}`);
|
||||
updateLastUsed(logger, sid, req).catch((err) => {});
|
||||
request({
|
||||
url: serviceUrl,
|
||||
@@ -587,11 +603,11 @@ router.post('/:sid/Calls', async(req, res) => {
|
||||
body: Object.assign(req.body, {account_sid: sid})
|
||||
}, (err, response, body) => {
|
||||
if (err) {
|
||||
logger.error(err, `Error sending createCall POST to ${ip}`);
|
||||
logger.error(err, `Error sending createCall POST to ${serviceUrl}`);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
if (response.statusCode !== 201) {
|
||||
logger.error({statusCode: response.statusCode}, `Non-success response returned by createCall ${ip}`);
|
||||
logger.error({statusCode: response.statusCode}, `Non-success response returned by createCall ${serviceUrl}`);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
res.status(201).json(body);
|
||||
@@ -714,14 +730,8 @@ router.post('/:sid/Messages', async(req, res) => {
|
||||
const {retrieveSet, logger} = req.app.locals;
|
||||
|
||||
try {
|
||||
const fs = await retrieveSet(setName);
|
||||
if (0 === fs.length) {
|
||||
logger.info('No available feature servers to handle createMessage API request');
|
||||
return res.json({msg: 'no available feature servers at this time'}).status(500);
|
||||
}
|
||||
const ip = stripPort(fs[idx++ % fs.length]);
|
||||
logger.info({fs}, `feature servers available for createMessage API request, selecting ${ip}`);
|
||||
const serviceUrl = `http://${ip}:3000/v1/createMessage/${account_sid}`;
|
||||
const serviceUrl = await getFsUrl(logger, retrieveSet, setName);
|
||||
if (!serviceUrl) res.json({msg: 'no available feature servers at this time'}).status(480);
|
||||
await validateCreateMessage(logger, account_sid, req);
|
||||
|
||||
const payload = {
|
||||
@@ -729,7 +739,7 @@ router.post('/:sid/Messages', async(req, res) => {
|
||||
account_sid,
|
||||
...req.body
|
||||
};
|
||||
logger.debug({payload}, `sending createMessage API request to to ${ip}`);
|
||||
logger.debug({payload}, `sending createMessage API request to to ${serviceUrl}`);
|
||||
updateLastUsed(logger, account_sid, req).catch(() => {});
|
||||
request({
|
||||
url: serviceUrl,
|
||||
@@ -738,7 +748,7 @@ router.post('/:sid/Messages', async(req, res) => {
|
||||
body: payload
|
||||
}, (err, response, body) => {
|
||||
if (err) {
|
||||
logger.error(err, `Error sending createMessage POST to ${ip}`);
|
||||
logger.error(err, `Error sending createMessage POST to ${serviceUrl}`);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const router = require('express').Router();
|
||||
const {DbErrorBadRequest} = require('../../utils/errors');
|
||||
const PredefinedCarrier = require('../../models/predefined-carrier');
|
||||
const VoipCarrier = require('../../models/voip-carrier');
|
||||
const SipGateway = require('../../models/sip-gateway');
|
||||
const SmppGateway = require('../../models/smpp-gateway');
|
||||
const {parseServiceProviderSid} = require('./utils');
|
||||
const short = require('short-uuid');
|
||||
const {promisePool} = require('../../db');
|
||||
const sysError = require('../error');
|
||||
|
||||
@@ -43,8 +43,7 @@ router.post('/:sid', async(req, res) => {
|
||||
await promisePool.query(sqlSelectCarrierByNameForSP, [service_provider_sid, template.name]);
|
||||
|
||||
if (r2.length > 0) {
|
||||
logger.info({account_sid}, `Failed to add carrier with name ${template.name}, carrier of that name exists`);
|
||||
throw new DbErrorBadRequest(`A carrier with name ${template.name} already exists`);
|
||||
template.name = `${template.name}-${short.generate()}`;
|
||||
}
|
||||
|
||||
/* retrieve all the sip gateways */
|
||||
|
||||
@@ -3,7 +3,7 @@ const {DbErrorBadRequest} = require('../../utils/errors');
|
||||
const ApiKey = require('../../models/api-key');
|
||||
const Account = require('../../models/account');
|
||||
const decorate = require('./decorate');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const sysError = require('../error');
|
||||
const preconditions = {
|
||||
'add': validateAddToken,
|
||||
|
||||
@@ -4,7 +4,7 @@ const {DbErrorBadRequest, DbErrorUnprocessableRequest} = require('../../utils/er
|
||||
const {promisePool} = require('../../db');
|
||||
const {doGithubAuth, doGoogleAuth, doLocalAuth} = require('../../utils/oauth-utils');
|
||||
const {validateEmail} = require('../../utils/email-utils');
|
||||
const uuid = require('uuid').v4;
|
||||
const { v4: uuid } = require('uuid');
|
||||
const short = require('short-uuid');
|
||||
const translator = short();
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
@@ -2,7 +2,7 @@ const router = require('express').Router();
|
||||
const {promisePool} = require('../../db');
|
||||
const {DbErrorBadRequest} = require('../../utils/errors');
|
||||
const {createDnsRecords, deleteDnsRecords} = require('../../utils/dns-utils');
|
||||
const uuid = require('uuid').v4;
|
||||
const { v4: uuid } = require('uuid');
|
||||
const sysError = require('../error');
|
||||
const insertDnsRecords = `INSERT INTO dns_records
|
||||
(dns_record_sid, account_sid, record_type, record_id)
|
||||
|
||||
@@ -1,19 +1,41 @@
|
||||
const router = require('express').Router();
|
||||
const request = require('request');
|
||||
const getProvider = require('../../utils/sms-provider');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const sysError = require('../error');
|
||||
let idx = 0;
|
||||
|
||||
const getFsUrl = async(logger, retrieveSet, setName, provider) => {
|
||||
if (process.env.K8S) return `http://${process.env.K8S_FEATURE_SERVER_SERVICE_NAME}:3000/v1/messaging/${provider}`;
|
||||
|
||||
async function doSendResponse(res, respondFn, body) {
|
||||
try {
|
||||
const fs = await retrieveSet(setName);
|
||||
if (0 === fs.length) {
|
||||
logger.info('No available feature servers to handle createCall API request');
|
||||
return ;
|
||||
}
|
||||
const ip = stripPort(fs[idx++ % fs.length]);
|
||||
logger.info({fs}, `feature servers available for createCall API request, selecting ${ip}`);
|
||||
return `http://${ip}:3000/v1/messaging/${provider}`;
|
||||
} catch (err) {
|
||||
logger.error({err}, 'getFsUrl: error retreving feature servers from redis');
|
||||
}
|
||||
};
|
||||
|
||||
const stripPort = (hostport) => {
|
||||
const arr = /^(.*):(.*)$/.exec(hostport);
|
||||
if (arr) return arr[1];
|
||||
return hostport;
|
||||
};
|
||||
|
||||
const doSendResponse = async(res, respondFn, body) => {
|
||||
if (typeof respondFn === 'number') res.sendStatus(respondFn);
|
||||
else if (typeof respondFn !== 'function') res.sendStatus(200);
|
||||
else {
|
||||
const payload = await respondFn(body);
|
||||
res.status(200).json(payload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
router.post('/:provider', async(req, res) => {
|
||||
const provider = req.params.provider;
|
||||
@@ -67,17 +89,8 @@ router.post('/:provider', async(req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const fs = await retrieveSet(setName);
|
||||
if (0 === fs.length) {
|
||||
logger.info('No available feature servers to handle createCall API request');
|
||||
return res
|
||||
.json({
|
||||
msg: 'no available feature servers at this time'
|
||||
})
|
||||
.status(480);
|
||||
}
|
||||
const ip = fs[idx++ % fs.length];
|
||||
const serviceUrl = `http://${ip}:3000/v1/messaging/${provider}`;
|
||||
const serviceUrl = await getFsUrl(logger, retrieveSet, setName, provider);
|
||||
if (!serviceUrl) res.json({msg: 'no available feature servers at this time'}).status(480);
|
||||
const messageSid = uuidv4();
|
||||
const payload = await Promise.resolve(filterFn({messageSid}, req.body));
|
||||
|
||||
@@ -113,7 +126,7 @@ router.post('/:provider', async(req, res) => {
|
||||
|
||||
logger.debug({body: req.body, payload}, 'filtered incoming SMS');
|
||||
|
||||
logger.info({payload, url: serviceUrl}, `sending incomingSms API request to FS at ${ip}`);
|
||||
logger.info({payload, url: serviceUrl}, `sending incomingSms API request to FS at ${serviceUrl}`);
|
||||
|
||||
request({
|
||||
url: serviceUrl,
|
||||
@@ -123,7 +136,7 @@ router.post('/:provider', async(req, res) => {
|
||||
},
|
||||
async(err, response, body) => {
|
||||
if (err) {
|
||||
logger.error(err, `Error sending incomingSms POST to ${ip}`);
|
||||
logger.error(err, `Error sending incomingSms POST to ${serviceUrl}`);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
if (200 === response.statusCode) {
|
||||
@@ -131,7 +144,7 @@ router.post('/:provider', async(req, res) => {
|
||||
logger.info({body}, 'sending response to provider for incomingSMS');
|
||||
return doSendResponse(res, respondFn, body);
|
||||
}
|
||||
logger.error({statusCode: response.statusCode}, `Non-success response returned by incomingSms ${ip}`);
|
||||
logger.error({statusCode: response.statusCode}, `Non-success response returned by incomingSms ${serviceUrl}`);
|
||||
return res.sendStatus(500);
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -10,7 +10,8 @@ const {
|
||||
testAwsTts,
|
||||
testAwsStt,
|
||||
testMicrosoftStt,
|
||||
testMicrosoftTts
|
||||
testMicrosoftTts,
|
||||
testWellSaidTts
|
||||
} = require('../../utils/speech-utils');
|
||||
|
||||
router.post('/', async(req, res) => {
|
||||
@@ -66,6 +67,12 @@ router.post('/', async(req, res) => {
|
||||
});
|
||||
encrypted_credential = encrypt(data);
|
||||
}
|
||||
else if (vendor === 'wellsaid') {
|
||||
const data = JSON.stringify({
|
||||
api_key
|
||||
});
|
||||
encrypted_credential = encrypt(data);
|
||||
}
|
||||
else throw new DbErrorBadRequest(`invalid speech vendor ${vendor}`);
|
||||
const uuid = await SpeechCredential.make({
|
||||
account_sid,
|
||||
@@ -109,6 +116,10 @@ router.get('/', async(req, res) => {
|
||||
obj.api_key = o.api_key;
|
||||
obj.region = o.region;
|
||||
}
|
||||
else if ('wellsaid' === obj.vendor) {
|
||||
const o = decrypt(credential);
|
||||
obj.api_key = o.api_key;
|
||||
}
|
||||
return obj;
|
||||
}));
|
||||
} catch (err) {
|
||||
@@ -291,6 +302,19 @@ router.get('/:sid/test', async(req, res) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cred.vendor === 'wellsaid') {
|
||||
const {api_key} = credential;
|
||||
if (cred.use_for_tts) {
|
||||
try {
|
||||
await testWellSaidTts(logger, {api_key});
|
||||
results.tts.status = 'ok';
|
||||
SpeechCredential.ttsTestResult(sid, true);
|
||||
} catch (err) {
|
||||
results.tts = {status: 'fail', reason: err.message};
|
||||
SpeechCredential.ttsTestResult(sid, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.status(200).json(results);
|
||||
} catch (err) {
|
||||
sysError(logger, res, err);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const uuid = require('uuid').v4;
|
||||
const { v4: uuid } = require('uuid');
|
||||
const bent = require('bent');
|
||||
const Account = require('../../models/account');
|
||||
const {promisePool} = require('../../db');
|
||||
|
||||
@@ -3102,9 +3102,12 @@ paths:
|
||||
enum:
|
||||
- completed
|
||||
- no-answer
|
||||
conf_mute:
|
||||
type: boolean
|
||||
conf_status:
|
||||
conf_mute_status:
|
||||
type: string
|
||||
enum:
|
||||
- mute
|
||||
- unmute
|
||||
conf_hold_status:
|
||||
type: string
|
||||
enum:
|
||||
- hold
|
||||
@@ -3120,8 +3123,21 @@ paths:
|
||||
- mute
|
||||
- unmute
|
||||
whisper:
|
||||
$ref: '#/components/schemas/Webhook'
|
||||
$ref: '#/components/schemas/Webhook'
|
||||
sip_request:
|
||||
type: object
|
||||
properties:
|
||||
method:
|
||||
type: string
|
||||
content_type:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
headers:
|
||||
type: object
|
||||
responses:
|
||||
200:
|
||||
description: Accepted
|
||||
202:
|
||||
description: Accepted
|
||||
400:
|
||||
|
||||
@@ -75,11 +75,37 @@ const testMicrosoftStt = async(logger, credentials) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const testWellSaidTts = async(logger, credentials) => {
|
||||
const {api_key} = credentials;
|
||||
try {
|
||||
const post = bent('https://api.wellsaidlabs.com', 'POST', 'buffer', {
|
||||
'X-Api-Key': api_key,
|
||||
'Accept': 'audio/mpeg',
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
const mp3 = await post('/v1/tts/stream', {
|
||||
text: 'Hello, world',
|
||||
speaker_id: '3'
|
||||
});
|
||||
return mp3;
|
||||
} catch (err) {
|
||||
logger.info({err}, 'testWellSaidTts returned error');
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
const testWellSaidStt = async(logger, credentials) => {
|
||||
//TODO
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
testGoogleTts,
|
||||
testGoogleStt,
|
||||
testAwsTts,
|
||||
testWellSaidTts,
|
||||
testAwsStt,
|
||||
testMicrosoftTts,
|
||||
testMicrosoftStt
|
||||
testMicrosoftStt,
|
||||
testWellSaidStt,
|
||||
};
|
||||
|
||||
12299
package-lock.json
generated
Normal file
12299
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
package.json
40
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jambonz-api-server",
|
||||
"version": "v0.7.1",
|
||||
"version": "v0.7.5",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
@@ -9,7 +9,8 @@
|
||||
"integration-test": "NODE_ENV=test JAMBONES_TIME_SERIES_HOST=127.0.0.1 AWS_REGION='us-east-1' JAMBONES_CURRENCY=USD JWT_SECRET=foobarbazzle JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_PORT=3360 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=debug JAMBONES_CREATE_CALL_URL=http://localhost/v1/createCall node test/serve-integration.js",
|
||||
"upgrade-db": "node ./db/upgrade-jambonz-db.js",
|
||||
"coverage": "./node_modules/.bin/nyc --reporter html --report-dir ./coverage npm run test",
|
||||
"jslint": "eslint app.js lib"
|
||||
"jslint": "eslint app.js lib",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"author": "Dave Horton",
|
||||
"license": "MIT",
|
||||
@@ -17,36 +18,39 @@
|
||||
"url": "https://github.com/jambonz/jambonz-api-server.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google-cloud/speech": "^4.2.0",
|
||||
"@google-cloud/text-to-speech": "^3.1.3",
|
||||
"@jambonz/db-helpers": "^0.6.12",
|
||||
"@jambonz/realtimedb-helpers": "^0.4.3",
|
||||
"@jambonz/time-series": "^0.1.5",
|
||||
"@google-cloud/speech": "^4.10.0",
|
||||
"@google-cloud/text-to-speech": "^3.4.0",
|
||||
"@jambonz/db-helpers": "^0.6.16",
|
||||
"@jambonz/realtimedb-helpers": "^0.4.24",
|
||||
"@jambonz/time-series": "^0.1.6",
|
||||
"argon2-ffi": "^2.0.0",
|
||||
"aws-sdk": "^2.839.0",
|
||||
"aws-sdk": "^2.1073.0",
|
||||
"bent": "^7.3.12",
|
||||
"cors": "^2.8.5",
|
||||
"debug": "^4.3.1",
|
||||
"express": "^4.17.1",
|
||||
"form-data": "^2.3.3",
|
||||
"form-urlencoded": "^6.0.4",
|
||||
"debug": "^4.3.3",
|
||||
"express": "^4.17.2",
|
||||
"express-rate-limit": "^6.3.0",
|
||||
"form-data": "^2.5.1",
|
||||
"form-urlencoded": "^6.0.5",
|
||||
"helmet": "^5.0.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mailgun.js": "^3.3.0",
|
||||
"mailgun.js": "^3.7.3",
|
||||
"microsoft-cognitiveservices-speech-sdk": "^1.19.0",
|
||||
"mysql2": "^2.2.5",
|
||||
"passport": "^0.5.0",
|
||||
"mysql2": "^2.3.3",
|
||||
"passport": "^0.5.2",
|
||||
"passport-http-bearer": "^1.0.1",
|
||||
"pino": "^5.17.0",
|
||||
"request-debug": "^0.2.0",
|
||||
"short-uuid": "^4.1.0",
|
||||
"stripe": "^8.138.0",
|
||||
"swagger-ui-express": "^4.1.6",
|
||||
"uuid": "^3.4.0",
|
||||
"stripe": "^8.196.0",
|
||||
"swagger-ui-express": "^4.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
"yamljs": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.17.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"husky": "7.0.4",
|
||||
"nyc": "^15.1.0",
|
||||
"request": "^2.88.2",
|
||||
"request-promise-native": "^1.0.9",
|
||||
|
||||
@@ -37,7 +37,7 @@ services:
|
||||
|
||||
influxdb:
|
||||
platform: linux/x86_64
|
||||
image: influxdb:1.8-alpine
|
||||
image: influxdb:1.8
|
||||
ports:
|
||||
- "8086:8086"
|
||||
networks:
|
||||
|
||||
@@ -133,6 +133,30 @@ test('speech credentials tests', async(t) => {
|
||||
json: true,
|
||||
});
|
||||
console.log(JSON.stringify(result));
|
||||
}
|
||||
|
||||
/* add a credential for wellsaid */
|
||||
if (process.env.WELLSAID_API_KEY) {
|
||||
result = await request.post(`/Accounts/${account_sid}/SpeechCredentials`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
vendor: 'wellsaid',
|
||||
use_for_tts: true,
|
||||
api_key: process.env.WELLSAID_API_KEY
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully added speech credential');
|
||||
const ms_sid = result.body.sid;
|
||||
|
||||
/* test the speech credential */
|
||||
result = await request.get(`/Accounts/${account_sid}/SpeechCredentials/${ms_sid}/test`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
console.log(JSON.stringify(result));
|
||||
|
||||
/* delete the credential */
|
||||
result = await request.delete(`/Accounts/${account_sid}/SpeechCredentials/${ms_sid}`, {
|
||||
@@ -144,7 +168,6 @@ test('speech credentials tests', async(t) => {
|
||||
|
||||
await deleteObjectBySid(request, '/Accounts', account_sid);
|
||||
await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid);
|
||||
|
||||
//t.end();
|
||||
}
|
||||
catch (err) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const bytesToUuid = require("uuid/lib/bytesToUuid");
|
||||
const uuid = require('uuid').v4;
|
||||
const { v4: uuid } = require('uuid');
|
||||
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
|
||||
Reference in New Issue
Block a user