- Added integration with Discord Webhooks
- Added daily report summaries
- Other fixes and improvements
This commit is contained in:
Sefinek committed 2025-02-10 02:54:35 +01:00
1 parent da212951a6
commit d9ad94e579
10 files changed
+174 -32

No files matched your search

+45
View File
@@ -0,0 +1,45 @@
const axios = require('axios');
const log = require('../utils/log.js');
const { SERVER_ID, DISCORD_WEBHOOKS_ENABLED, DISCORD_WEBHOOKS_URL } = require('../config.js').MAIN;
const TYPES = {
0: { type: 'SUCCESS', emoji: '\\✅', color: 0x60D06D },
1: { type: 'WARN', emoji: '\\⚠️', color: 0xFFB02E },
2: { type: 'ERROR', emoji: '\\❌', color: 0xF92F60 },
3: { type: 'FAIL', emoji: '\\🔴', color: 0xF8312F },
4: { type: 'INFO', emoji: '\\📄', color: 0xF2EEF8 },
5: { type: 'DEBUG', emoji: '\\🛠️', color: 0xB4ACBC },
6: { type: 'CRITICAL', emoji: '\\🔴', color: 0xF8312F },
7: { type: 'NOTICE', emoji: '\\📝', color: 0xF3EEF8 },
};
module.exports = async (id, description) => {
if (!DISCORD_WEBHOOKS_ENABLED || !DISCORD_WEBHOOKS_URL) return;
const logType = TYPES[id];
if (!logType) return log(1, 'Invalid log type ID provided!');
const config = {
method: 'POST',
url: DISCORD_WEBHOOKS_URL,
headers: { 'Content-Type': 'application/json' },
data: {
embeds: [{
title: `${logType.emoji} ${SERVER_ID}: ${logType.type} [ID ${id}]`,
description,
color: logType.color,
footer: {
text: `Date: ${new Date().toLocaleString()} | sefinek/UFW-AbuseIPDB-Reporter`,
},
timestamp: new Date().toISOString(),
}],
},
};
try {
const res = await axios(config);
if (res.status !== 204) log(1, 'Failed to deliver Discord Webhook');
} catch (err) {
log(2, `Failed to send Discord Webhook! ${err.stack}`);
}
};
+9 -4
View File
@@ -1,7 +1,9 @@
const { exec } = require('node:child_process');
const ecosystem = require('../ecosystem.config.js');
const discordWebhooks = require('./discord.js');
const log = require('../utils/log.js');
const executeCommand = cmd =>
const executeCmd = cmd =>
new Promise((resolve, reject) => {
exec(cmd, (err, stdout, stderr) => {
if (err || stderr) reject(err || stderr);
@@ -10,10 +12,13 @@ const executeCommand = cmd =>
});
module.exports = async () => {
const process = ecosystem.apps[0].name;
await discordWebhooks(4, `Restarting the ${process} process...`);
try {
console.log(await executeCommand('npm install --omit=dev'));
console.log(await executeCommand(`pm2 restart ${ecosystem.apps[0].name}`));
console.log(await executeCmd('npm install --omit=dev'));
console.log(await executeCmd(`pm2 restart ${process}`));
} catch (err) {
console.error(err);
log(2, err);
}
};
+73
View File
@@ -0,0 +1,73 @@
const { CronJob } = require('cron');
const fs = require('node:fs/promises');
const discordWebhooks = require('./discord.js');
const log = require('../utils/log.js');
const { CACHE_FILE } = require('../config.js').MAIN;
const formatHourRange = hour => `${hour.toString().padStart(2, '0')}:00-${hour.toString().padStart(2, '0')}:59`;
const pluralizeReport = count => (count === 1 ? 'report' : 'reports');
const sendWebhook = async () => {
try {
await fs.access(CACHE_FILE);
} catch {
return log(2, `Cache file not found: ${CACHE_FILE}`);
}
let data;
try {
data = (await fs.readFile(CACHE_FILE, 'utf8')).trim();
} catch (err) {
return log(2, `Error reading file: ${err.message}`);
}
if (!data) {
log(0, `Cache file is empty: ${CACHE_FILE}`);
return discordWebhooks(4, `Cache file is empty: \`${CACHE_FILE}\``);
}
try {
const yesterday = new Date();
yesterday.setUTCDate(yesterday.getUTCDate() - 1);
const yesterdayString = yesterday.toISOString().split('T')[0];
const hourlySummary = {};
const uniqueEntries = new Set();
data.split('\n').forEach((line) => {
const [ip, timestamp] = line.split(' ');
if (!ip || isNaN(timestamp)) return;
const entryKey = `${ip}_${timestamp}`;
if (uniqueEntries.has(entryKey)) return;
uniqueEntries.add(entryKey);
const dateObj = new Date(parseInt(timestamp, 10) * 1000);
if (dateObj.toISOString().split('T')[0] !== yesterdayString) return;
const hour = dateObj.getUTCHours();
hourlySummary[hour] = (hourlySummary[hour] || 0) + 1;
});
const totalReports = Object.values(hourlySummary).reduce((sum, count) => sum + count, 0);
const sortedEntries = Object.entries(hourlySummary).sort((a, b) => b[1] - a[1]);
const maxReports = sortedEntries.length > 0 ? sortedEntries[0][1] : 0;
const topHours = sortedEntries
.filter(([, count]) => count === maxReports && count > 1)
.map(([hour]) => parseInt(hour));
const summaryString = Object.entries(hourlySummary)
.map(([hour, count]) => `${formatHourRange(parseInt(hour))}: ${count} ${pluralizeReport(count)}${topHours.includes(parseInt(hour)) ? ' 🔥' : ''}`)
.join('\n');
await discordWebhooks(7, `Midnight. Summary of IP address reports (${totalReports}) from yesterday (${yesterdayString}).\nGood night to you, sleep well! 😴\n\`\`\`${summaryString}\`\`\``);
log(0, `Reported IPs yesterday by hour:\n${summaryString}\nTotal reported IPs: ${totalReports} ${pluralizeReport(totalReports)}`);
} catch (err) {
log(2, err);
}
};
module.exports = async () => {
await sendWebhook();
new CronJob('0 0 * * *', sendWebhook, null, true, 'UTC');
};
+12 -5
View File
@@ -4,14 +4,21 @@ const simpleGit = require('simple-git');
const { CronJob } = require('cron');
const restartApp = require('./reloadApp.js');
const log = require('../utils/log.js');
const discordWebhooks = require('./discord.js');
const git = simpleGit();
const pull = async () => {
await discordWebhooks(4, 'Updating the local repository in progress `(git pull)`...');
log(0, '$ git pull');
const { summary } = await git.pull();
log(0, `Changes: ${summary.changes}; Deletions: ${summary.insertions}; Insertions: ${summary.insertions};`);
try {
const { summary } = await git.pull();
log(0, `Changes: ${summary.changes}; Deletions: ${summary.insertions}; Insertions: ${summary.insertions}`);
await discordWebhooks(4, `**Changes:** ${summary.changes}; **Deletions:** ${summary.insertions}; **Insertions:** ${summary.insertions}`);
} catch (err) {
log(2, err);
}
};
const pullAndRestart = async () => {
@@ -19,11 +26,11 @@ const pullAndRestart = async () => {
await pull();
await restartApp();
} catch (err) {
log(2, err.message);
log(2, err);
}
};
// https://crontab.guru
new CronJob(AUTO_UPDATE_SCHEDULE || '0 18 * * *', pullAndRestart, null, true, 'UTC'); // At 18:00
new CronJob(AUTO_UPDATE_SCHEDULE, pullAndRestart, null, true, 'UTC');
module.exports = { pull };
module.exports = pull;