voicemail-ticketizer/src/index.ts
2021-03-14 20:53:53 -06:00

142 lines
3.5 KiB
TypeScript

import knex from "knex";
import knexConfig from "./db";
import { Sonar, gql } from "./sonar";
import { SDK } from "@ringcentral/sdk";
import { ticketize } from "./ticketize";
import { logger, DEBUG } from "./util";
function checkEnv() {
[
"SONAR_URL",
"SONAR_TOKEN",
"RC_APP_KEY",
"RC_APP_SECRET",
"RC_LOGIN_USERNAME",
"RC_LOGIN_EXT",
"RC_LOGIN_PASSWORD",
"EXTENSION_TICKET_GROUPS",
].forEach((env) => {
if (process.env[env] === undefined) {
throw new Error(`${env} environment variable is not set.`);
}
});
}
function getExtensionToTicketGroupMapping() {
const mapping: { [key: string]: number } = {};
process.env.EXTENSION_TICKET_GROUPS!.split(",").forEach((entry) => {
const [extension, ticketGroupId] = entry.split(":");
mapping[extension] = parseInt(ticketGroupId);
});
return mapping;
}
const DEFAULT_FIRST_RUN_AGE = 86400;
function getTicketizeConfig() {
const firstRunAge = process.env.FIRST_RUN_AGE
? parseInt(process.env.FIRST_RUN_AGE)
: DEFAULT_FIRST_RUN_AGE;
if (isNaN(firstRunAge) || firstRunAge <= 0) {
throw new Error("FIRST_RUN_AGE must be a valid positive integer");
}
return {
firstRunAge,
extensionToTicketGroup: getExtensionToTicketGroupMapping(),
};
}
async function initSonar() {
const sonar = new Sonar(process.env.SONAR_URL!, process.env.SONAR_TOKEN!);
// simple query to test API cedentials
const user = await sonar.request(
gql`
{
me {
name
}
}
`
);
logger.info(`Authenticated to Sonar as '${user.me.name}'.`);
return sonar;
}
async function initRingCentralSDK() {
const sdk = new SDK({
server: SDK.server[process.env.RC_SANDBOX ? "sandbox" : "production"],
clientId: process.env.RC_APP_KEY,
clientSecret: process.env.RC_APP_SECRET,
});
const login = () =>
sdk.login({
username: process.env.RC_LOGIN_USERNAME,
extension: process.env.RC_LOGIN_EXT,
password: process.env.RC_LOGIN_PASSWORD,
});
if (DEBUG) {
const client = sdk.client();
client.on(client.events.beforeRequest, (req) => {
logger.debug(req.url);
});
}
const platform = sdk.platform();
platform.on(platform.events.refreshError, async (err) => {
logger.error("Refresh token error:", err);
await login();
logger.info("RingCentral re-authentication successful.");
});
await login();
logger.info("Authenticated to RingCentral.");
return sdk;
}
async function initDB() {
const db = knex(knexConfig);
if (!process.env.DB_SKIP_MIGRATIONS) {
await db.migrate.latest();
logger.info("Database migrations run successfully.");
}
return db;
}
async function main() {
try {
checkEnv();
const sonar = await initSonar();
const rcsdk = await initRingCentralSDK();
const db = await initDB();
logger.info("Starting ticketizer...");
const intervals = ticketize(sonar, rcsdk, db, getTicketizeConfig());
["SIGINT", "SIGTERM", "SIGQUIT"].forEach((sig) => {
process.on(sig, async () => {
logger.info(`\nCaught ${sig}, shutting down...`);
const results = await Promise.allSettled(
intervals.map((interval) => interval.clear())
);
let errors = false;
results.forEach((result) => {
if (result.status === "rejected") {
errors = true;
logger.error(result.reason);
}
});
process.exit(errors ? 1 : 0);
});
});
} catch (err) {
logger.error(err);
}
}
main();