112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
import { join } from 'path';
|
|
import { Main } from './Main';
|
|
import { pathExists, readJSON, writeJSON } from 'fs-extra';
|
|
|
|
const PREFIX = '[Twilio]';
|
|
export class TwilioHandler {
|
|
private _Main: Main;
|
|
|
|
counter: {
|
|
date: string;
|
|
count: number;
|
|
} = {
|
|
date: new Date().toLocaleDateString('nl-NL'),
|
|
count: 0,
|
|
};
|
|
|
|
client;
|
|
|
|
constructor(Main: Main) {
|
|
this._Main = Main;
|
|
}
|
|
|
|
canSendMessage() {
|
|
const maxMessages = this._Main.Config.twilio.maxMessagesPerDay;
|
|
return this.counter.count < maxMessages;
|
|
}
|
|
|
|
async incrementCounter() {
|
|
const today = new Date().toLocaleDateString('nl-NL');
|
|
if (this.counter.date !== today) {
|
|
this.counter.date = today;
|
|
this.counter.count = 0;
|
|
}
|
|
this.counter.count++;
|
|
await writeJSON(join(this._Main.dataPath, 'twilio.json'), this.counter);
|
|
}
|
|
|
|
async load() {
|
|
const twilioConfigPath = join(this._Main.dataPath, 'twilio.json');
|
|
const twilioConfigExists = await pathExists(twilioConfigPath);
|
|
if (twilioConfigExists) {
|
|
this.counter = await readJSON(twilioConfigPath);
|
|
}
|
|
|
|
this.client = require('twilio')(
|
|
this._Main.Config.twilio.accountSid,
|
|
this._Main.Config.twilio.authToken,
|
|
);
|
|
}
|
|
|
|
async resetError(category: TwilioCategories) {
|
|
if (!this.lastErrors.has(category)) return;
|
|
this.lastErrors.delete(category);
|
|
}
|
|
|
|
private lastErrors: Map<TwilioCategories, string> = new Map();
|
|
private errorLog: string[] = [];
|
|
private errorTimeout: NodeJS.Timeout;
|
|
async sendError(category: TwilioCategories, error: string) {
|
|
if (this.lastErrors.get(category) === error) return;
|
|
|
|
this.lastErrors.set(category, error);
|
|
if (error == null) return;
|
|
|
|
this.errorLog.push(`${category}: ${error}`);
|
|
clearTimeout(this.errorTimeout);
|
|
this.errorTimeout = setTimeout(async () => {
|
|
const errorMessage = this.errorLog
|
|
.map((error) => `- ${error}`)
|
|
.join('\n');
|
|
this.errorLog = [];
|
|
|
|
if (!this.canSendMessage())
|
|
return console.log(PREFIX, 'Max messages per day reached');
|
|
await this.incrementCounter();
|
|
|
|
console.log(PREFIX, `Sending to Twilio:\n`, errorMessage);
|
|
|
|
const promises = this._Main.Config.twilio.toNumbers.map(
|
|
(toNumber) => this.sendMessage(toNumber, errorMessage),
|
|
);
|
|
await Promise.all(promises);
|
|
}, this._Main.Config.twilio.aggregateTimeout);
|
|
}
|
|
|
|
sendMessage(to: string, message: string) {
|
|
return new Promise<boolean>((resolve) => {
|
|
this.client.messages
|
|
.create({
|
|
body: message,
|
|
from: `${this._Main.Config.twilio.fromNumber}`,
|
|
to: to,
|
|
})
|
|
.then((message: any) => {
|
|
console.log(`Twilio message sent with SID: ${message.sid}`);
|
|
resolve(true);
|
|
})
|
|
.catch((error: any) => {
|
|
console.error('Error sending Twilio message:', error);
|
|
resolve(false);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
type TwilioCategories =
|
|
| 'CameraRunner'
|
|
| 'UnityRunner'
|
|
| 'UnityWebSocket'
|
|
| 'Status'
|
|
| 'Audio';
|