Add FIRST_RUN_AGE variable

Allows setting the maximum age of voicemails to fetch on the first run.

Other changes:
- Refactor `from` to `age` in function parameters
- Improve README
This commit is contained in:
Matt Low 2021-03-11 11:55:50 -07:00
parent 39cd664b3c
commit 0946158005
3 changed files with 45 additions and 21 deletions

View File

@ -5,7 +5,7 @@
## Configuration ## Configuration
```shell ```shell
# Required API/authentication variables: # Required API endpoint/authentication variables
SONAR_URL=https://instance.sonar.software/api/graphql SONAR_URL=https://instance.sonar.software/api/graphql
SONAR_TOKEN= SONAR_TOKEN=
RC_APP_KEY= RC_APP_KEY=
@ -17,15 +17,25 @@ RC_LOGIN_PASSWORD=
# Set to any value to enable use of RingCentral's sandbox API # Set to any value to enable use of RingCentral's sandbox API
RC_SANDBOX= RC_SANDBOX=
# The database to use
# valid options: pg, sqlite
# default: sqlite
DB_ENGINE=sqlite # can be pg DB_ENGINE=sqlite # can be pg
# only used when DB_ENGINE=pg
# Only used when DB_ENGINE=pg
DB_URL= DB_URL=
# only used when DB_ENGINE=sqlite # Only used when DB_ENGINE=sqlite
# default: voicemails.db
DB_FILE=voicemails.db DB_FILE=voicemails.db
# A mapping of extension number to Sonar Ticket Group # A mapping of extension number to Sonar Ticket Group
# Only the voicemail boxes of these extensions will be checked # Only the voicemail boxes of these extensions will be checked
EXTENSION_TICKET_GROUPS=1:1,2:2,2:3 EXTENSION_TICKET_GROUPS=1:1,2:2,2:3
# Upon first run, query RingCentral voicemails up to FIRST_RUN_AGE seconds old.
# Useful when the application is restarted after not running for some time.
# default: 86400 (1 day)
FIRST_RUN_AGE=86400
``` ```
## Deployment ## Deployment
@ -45,6 +55,8 @@ services:
environment: environment:
# ... see Configuration above # ... see Configuration above
DB_FILE: /data/voicemails.db DB_FILE: /data/voicemails.db
# so the created tickets show the correct 'Received' date & time
TZ: America/Creston
volumes: volumes:
- data:/data - data:/data
``` ```

View File

@ -30,6 +30,22 @@ function getExtensionToTicketGroupMapping() {
return mapping; 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() { async function initSonar() {
const sonar = new Sonar(process.env.SONAR_URL!, process.env.SONAR_TOKEN!); const sonar = new Sonar(process.env.SONAR_URL!, process.env.SONAR_TOKEN!);
// simple query to test API cedentials // simple query to test API cedentials
@ -79,9 +95,7 @@ async function main() {
const db = await initDB(); const db = await initDB();
console.log("Starting ticketizer..."); console.log("Starting ticketizer...");
const intervals = ticketize(sonar, rcsdk, db, { const intervals = ticketize(sonar, rcsdk, db, getTicketizeConfig());
extensionToTicketGroup: getExtensionToTicketGroupMapping(),
});
["SIGINT", "SIGTERM", "SIGQUIT"].forEach((sig) => { ["SIGINT", "SIGTERM", "SIGQUIT"].forEach((sig) => {
process.on(sig, async () => { process.on(sig, async () => {

View File

@ -49,6 +49,7 @@ function rcapi(short: string, version = "v1.0") {
} }
interface TicketizeConfig { interface TicketizeConfig {
firstRunAge: number;
extensionToTicketGroup: { [key: string]: number }; extensionToTicketGroup: { [key: string]: number };
} }
@ -62,7 +63,7 @@ export function ticketize(
sonar: Sonar, sonar: Sonar,
rcsdk: SDK, rcsdk: SDK,
db: Knex, db: Knex,
{ extensionToTicketGroup }: TicketizeConfig { firstRunAge, extensionToTicketGroup }: TicketizeConfig
) { ) {
/** /**
* Uploads a file to Sonar, returning its ID. * Uploads a file to Sonar, returning its ID.
@ -92,17 +93,17 @@ export function ticketize(
} }
/** /**
* Returns `extensionId`s messages that are up to `from` seconds old. * Returns `extensionId`s messages that are up to `age` seconds old.
* *
* @param extensionId * @param extensionId
* @param from how many seconds ago to retrieve messages from * @param age the maximum age (in seconds) of voicemails to fetch
*/ */
async function getExtensionVoicemails(extensionId: number, from = 86000) { async function getExtensionVoicemails(extensionId: number, age = 86000) {
const result = await rcsdk.get( const result = await rcsdk.get(
rcapi(`/account/~/extension/${extensionId}/message-store`), rcapi(`/account/~/extension/${extensionId}/message-store`),
{ {
messageType: "VoiceMail", messageType: "VoiceMail",
dateFrom: new Date(Date.now() - from * 1000).toISOString(), dateFrom: new Date(Date.now() - age * 1000).toISOString(),
} }
); );
return (await result.json()).records as RCMessage[]; return (await result.json()).records as RCMessage[];
@ -305,16 +306,13 @@ export function ticketize(
} }
/** /**
* Retrieves and stores the voicemails for `extension` that are up to `from` * Retrieves and stores the voicemails for `extension` that are up to `age`
* seconds old. * seconds old.
* @param extension * @param extension
* @param from * @param age
*/ */
async function storeExtensionVoicemails( async function storeExtensionVoicemails(extension: RCExtension, age: number) {
extension: RCExtension, const messages = await getExtensionVoicemails(extension.id, age);
from: number
) {
const messages = await getExtensionVoicemails(extension.id, from);
const isStored = await Promise.all( const isStored = await Promise.all(
messages.map((message) => isMessageStored(message.id)) messages.map((message) => isMessageStored(message.id))
); );
@ -335,15 +333,15 @@ export function ticketize(
/** /**
* Fetch and store new voicemails. If this is the first run, we get the last * Fetch and store new voicemails. If this is the first run, we get the last
* day's worth of voicemails. Otherwise, we fetch only the last 15 minutes. * day's worth of voicemails. Otherwise, we fetch only the last 5 minutes.
* *
* @param firstRun whether this is the first run or not * @param firstRun whether this is the first run
*/ */
async function fetchAndStoreNewVoicemails(firstRun = false) { async function fetchAndStoreNewVoicemails(firstRun = false) {
const extensions = await getValidRCExtensions(); const extensions = await getValidRCExtensions();
return Promise.all( return Promise.all(
extensions.map((extension) => extensions.map((extension) =>
storeExtensionVoicemails(extension, firstRun ? 86400 : 900) storeExtensionVoicemails(extension, firstRun ? firstRunAge : 300)
) )
); );
} }