forked from LiteNet/freepbx-stats
158 lines
5.6 KiB
JavaScript
158 lines
5.6 KiB
JavaScript
require("dotenv").config();
|
|
const cron = require("node-cron");
|
|
const os = require("os");
|
|
const Discord = require('discord.js');
|
|
const mysql = require('mysql');
|
|
const { TimeSpan } = require("./timeSpan");
|
|
const { DateBuilder } = require("./dateBuilder");
|
|
const { CallStats } = require("./callStats");
|
|
const { CallRecord, Records } = require("./records");
|
|
const fs = require('fs').promises;
|
|
const fsSync = require('fs');
|
|
|
|
const hook = !!process.env.DISCORD_WEBHOOK_URL ? new Discord.WebhookClient({ url: process.env.DISCORD_WEBHOOK_URL }) : null;
|
|
|
|
const JSON_FILE = process.env.JSON_FILE || "records.json";
|
|
const records = fsSync.existsSync(JSON_FILE) ? Records.fromJSONFile(JSON_FILE) : new Records();
|
|
|
|
function getYesterday() {
|
|
return new TimeSpan(
|
|
new DateBuilder().addDays(-1).atStartOfDay().build().getTime(),
|
|
new DateBuilder().addDays(-1).atEndOfDay().build().getTime()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Fetch call statistics
|
|
* @returns {Promise<CallStats>}
|
|
*/
|
|
async function getPreviousDayData() {
|
|
return new Promise(async (resolve, reject) => {
|
|
const yesterday = getYesterday();
|
|
const connection = await mysql.createConnection({
|
|
host: process.env.DATABASE_HOST,
|
|
user: process.env.DATABASE_USER,
|
|
password: process.env.DATABASE_PASSWORD,
|
|
database: process.env.DATABASE_NAME,
|
|
multipleStatements: true
|
|
});
|
|
await connection.connect();
|
|
await connection.query(`
|
|
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
|
FROM cdr
|
|
WHERE calldate BETWEEN ? AND ?;
|
|
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
|
FROM cdr
|
|
WHERE MONTH (calldate) = MONTH (?) AND YEAR (calldate) = YEAR (?);
|
|
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
|
FROM cdr;
|
|
`, [ yesterday.start, yesterday.end, yesterday.start, yesterday.start ], (err, res) => {
|
|
if (err) {
|
|
reject(err);
|
|
}
|
|
connection.end();
|
|
// let output = {
|
|
// "Calls Made": res[0][0].call_count,
|
|
// "Monthly Total": res[1][0].call_count,
|
|
// "Total Calls Ever Placed": res[2][0].call_count,
|
|
// "System Uptime": getSystemUptime().toString(false, false),
|
|
// "All Time Record": null, // Placeholder
|
|
// }
|
|
|
|
const stats = new CallStats({
|
|
callsMadeToday: res[0][0].call_count,
|
|
totalCallsThisMonth: res[1][0].call_count,
|
|
totalCallsEverPlaced: res[2][0].call_count,
|
|
allTimeRecord: null // Placeholder
|
|
});
|
|
|
|
console.log(stats);
|
|
resolve(stats);
|
|
});
|
|
});
|
|
}
|
|
|
|
function getSystemUptime() {
|
|
const uptime = os.uptime();
|
|
const now = new Date();
|
|
return new TimeSpan(now - (uptime * 1000), now.getTime());
|
|
}
|
|
|
|
/**
|
|
* Update records with new data
|
|
* @param {CallStats} callStats
|
|
* @param {Records} records
|
|
* @returns {CallStats}
|
|
*/
|
|
function updateRecords(callStats, records) {
|
|
const yesterday = getYesterday().startDate;
|
|
const yesterdayDateString = yesterday.toISOString().split('T')[0];
|
|
let isNewRecord = false;
|
|
|
|
// Update all-time record
|
|
const allTimeRecord = records.callRecord || new CallRecord({ date: yesterdayDateString, count: 0 });
|
|
if (!records.callRecord) {
|
|
records.callRecord = { date: yesterdayDateString, count: callStats.totalCallsMade };
|
|
isNewRecord = true;
|
|
} else if (allTimeRecord.count < callStats.totalCallsThisMonth) {
|
|
allTimeRecord.count = callStats.totalCallsThisMonth;
|
|
isNewRecord = true;
|
|
}
|
|
callStats.allTimeRecord = `${allTimeRecord.count} calls on ${allTimeRecord.date}`;
|
|
|
|
// Update total calls ever placed
|
|
records.totalCallsEverPlaced = callStats.totalCallsEverPlaced;
|
|
|
|
// Update monthly totals
|
|
if (!records.monthlyTotals) records.monthlyTotals = {};
|
|
records.monthlyTotals[yesterday.getFullYear().toString()][yesterday.getMonth().toString()] = callStats.totalCallsThisMonth;
|
|
|
|
if (isNewRecord) {
|
|
callStats.isNewRecord = true;
|
|
}
|
|
return callStats;
|
|
}
|
|
|
|
async function sendSummary() {
|
|
console.log("Preparing summary.");
|
|
const data = await getPreviousDayData();
|
|
console.log("Updating records...");
|
|
const updatedData = await updateRecords(data, records);
|
|
console.log("Saving.");
|
|
await records.toJSONFile(JSON_FILE);
|
|
|
|
const yesterday = getYesterday();
|
|
const makeField = (name, value) => ({ name, value: value.toString(), inline: false });
|
|
|
|
let embed = {
|
|
title: `Summary from <t:${Math.floor(yesterday.start / 1000)}:f> to <t:${Math.floor(yesterday.end / 1000)}:f>`,
|
|
color: 0x1E90FF,
|
|
fields: [
|
|
makeField("Calls Made", updatedData.totalCallsMade),
|
|
makeField("Monthly Total", updatedData.totalCallsThisMonth),
|
|
makeField("Total Calls Ever Placed", updatedData.totalCallsEverPlaced),
|
|
makeField("System Uptime", getSystemUptime().toString(false, false)),
|
|
makeField("All Time Record", updatedData.allTimeRecord)
|
|
],
|
|
timestamp: new Date(),
|
|
footer: {}
|
|
}
|
|
|
|
if (updatedData.isNewRecord) {
|
|
embed.color = 0xFFD700; // Gold color for new record
|
|
embed.fields.push(makeField("🎉 NEW RECORD! 🎉", `A new record has been set, at ${updatedData.totalCallsMade}!`));
|
|
}
|
|
|
|
const payload = { embeds: [ embed ] };
|
|
console.log("Sending Discord message:", payload);
|
|
if (hook)
|
|
await hook.send(payload);
|
|
}
|
|
|
|
if (process.env.NOOP) {
|
|
sendSummary();
|
|
return;
|
|
}
|
|
console.log("Scheduling...");
|
|
const schedule = cron.schedule("0 1 * * *", sendSummary);
|