142 lines
3.5 KiB
TypeScript
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();
|