done
This commit is contained in:
143
abandoned-call-poller.js
Normal file
143
abandoned-call-poller.js
Normal file
@@ -0,0 +1,143 @@
|
||||
const config = require('./config');
|
||||
const apiClient = require('./api-client');
|
||||
|
||||
class AbandonedCallPoller {
|
||||
constructor(database, printer) {
|
||||
this.db = database;
|
||||
this.printer = printer;
|
||||
this.intervalId = null;
|
||||
this.isPolling = false;
|
||||
}
|
||||
|
||||
async start() {
|
||||
console.log('Starting abandoned call poller...');
|
||||
this.poll();
|
||||
this.scheduleNextPoll();
|
||||
}
|
||||
|
||||
scheduleNextPoll() {
|
||||
const appConfig = config.getAll();
|
||||
const interval = parseInt(appConfig.abandonedCallPollingInterval, 10) || 30000;
|
||||
|
||||
if (this.intervalId) {
|
||||
clearTimeout(this.intervalId);
|
||||
}
|
||||
|
||||
this.intervalId = setTimeout(() => {
|
||||
this.poll();
|
||||
this.scheduleNextPoll();
|
||||
}, interval);
|
||||
}
|
||||
|
||||
async poll() {
|
||||
if (this.isPolling) return;
|
||||
this.isPolling = true;
|
||||
|
||||
try {
|
||||
const appConfig = config.getAll();
|
||||
|
||||
if (!appConfig.authToken || !appConfig.selectedBotId) {
|
||||
this.isPolling = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (apiClient.isTokenNearExpiry(appConfig.tokenExpiry, 7)) {
|
||||
const refreshed = await apiClient.ensureValidToken();
|
||||
if (!refreshed) {
|
||||
this.isPolling = false;
|
||||
return;
|
||||
}
|
||||
Object.assign(appConfig, config.getAll());
|
||||
}
|
||||
|
||||
const result = await apiClient.getAbandonedCalls(
|
||||
appConfig.authToken,
|
||||
appConfig.selectedBotId,
|
||||
{ limit: 50 }
|
||||
);
|
||||
|
||||
if (result.error) {
|
||||
console.error('Abandoned calls poll error:', result.message);
|
||||
this.isPolling = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const calls = result.calls || [];
|
||||
|
||||
for (const call of calls) {
|
||||
this.db.cacheAbandonedCall(call.id, call);
|
||||
}
|
||||
|
||||
// Also fetch callback queue for the management page cache
|
||||
const queueResult = await apiClient.getAbandonedCallbackQueue(
|
||||
appConfig.authToken,
|
||||
appConfig.selectedBotId,
|
||||
50
|
||||
);
|
||||
|
||||
if (!queueResult.error && queueResult.queue) {
|
||||
for (const call of queueResult.queue) {
|
||||
this.db.cacheAbandonedCall(call.id, call);
|
||||
}
|
||||
}
|
||||
|
||||
// Print new abandoned calls that haven't been printed yet
|
||||
await this.printNewAbandonedCalls(calls, appConfig);
|
||||
|
||||
// Clean old cache periodically
|
||||
this.db.cleanOldAbandonedCallCache(7);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Abandoned call poll error:', error.message);
|
||||
}
|
||||
|
||||
this.isPolling = false;
|
||||
}
|
||||
|
||||
async printNewAbandonedCalls(calls, appConfig) {
|
||||
const printerConfigs = this.db.getAbandonedCallPrinters();
|
||||
if (!printerConfigs || printerConfigs.length === 0) return;
|
||||
|
||||
const cooldownSeconds = parseInt(appConfig.abandonedCallPrintCooldown, 10) || 300;
|
||||
const lastPrintTime = this.db.getLastAbandonedCallPrintTime();
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
const printablePriorities = new Set(['critical', 'high', 'medium']);
|
||||
|
||||
for (const call of calls) {
|
||||
if (this.db.hasAbandonedCallPrint(call.id)) continue;
|
||||
|
||||
const priority = call.callback_priority || 'none';
|
||||
if (!printablePriorities.has(priority)) continue;
|
||||
|
||||
if (lastPrintTime && (now - lastPrintTime) < cooldownSeconds) {
|
||||
console.log(`Abandoned call #${call.id}: skipping print (cooldown active)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.printer.printAbandonedCallReceipt(call, printerConfigs);
|
||||
const printedCount = result ? (result.successCount || printerConfigs.length) : 0;
|
||||
this.db.addAbandonedCallPrint(call.id, printedCount);
|
||||
console.log(`Abandoned call #${call.id}: printed on ${printedCount} printer(s)`);
|
||||
} catch (err) {
|
||||
console.error(`Abandoned call #${call.id}: print failed:`, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.intervalId) {
|
||||
clearTimeout(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
console.log('Abandoned call poller stopped');
|
||||
}
|
||||
|
||||
restart() {
|
||||
this.stop();
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AbandonedCallPoller;
|
||||
Reference in New Issue
Block a user