replace scheduler with round robin every x minutes

This commit is contained in:
2026-01-11 12:19:43 -05:00
parent b222d4a5d7
commit d00d5bb313
9 changed files with 77 additions and 59 deletions

View File

@@ -4,6 +4,7 @@
"alerts": "YOUR DISCORD USER ID", "alerts": "YOUR DISCORD USER ID",
"torn": "TORN API KEY", "torn": "TORN API KEY",
"httpPort": 3000, "httpPort": 3000,
"taskWaitMinutes": 5,
"channels": { "channels": {
"ocAlert": "000000000000000000" "ocAlert": "000000000000000000"
}, },

View File

@@ -1,4 +1,4 @@
const cron = require('node-cron');
const fs = require('fs'); const fs = require('fs');
const path = require('node:path'); const path = require('node:path');
const torn = require('./torn.js'); const torn = require('./torn.js');
@@ -52,17 +52,44 @@ client.tasks = {};
fs.readdir('./tasks/', (err, files) => { fs.readdir('./tasks/', (err, files) => {
if (err) return console.log(err); if (err) return console.log(err);
const taskNames = [];
files.forEach(file => { files.forEach(file => {
const taskFile = require(`./tasks/${file}`); const taskFile = require(`./tasks/${file}`);
const taskName = file.split('.')[0]; const taskName = file.split('.')[0];
client.tasks[taskName] = taskFile; client.tasks[taskName] = taskFile;
if (taskFile.schedule) { taskNames.push(taskName);
console.debug(`Tasks: Scheduling "${taskName}" for ${taskFile.schedule}`);
cron.schedule(taskFile.schedule, () => { taskFile(client, torn, config, state); });
} else {
console.debug(`Tasks: Registered "${taskName}"`); console.debug(`Tasks: Registered "${taskName}"`);
}
}); });
// Round-robin scheduler
let currentTaskIndex = 0;
const runNextTask = () => {
if (taskNames.length === 0) return;
const taskName = taskNames[currentTaskIndex];
const taskFile = client.tasks[taskName];
const now = new Date();
const dateString = now.toLocaleTimeString('en-US', { hour12: false }) + ' ' + now.toLocaleDateString('en-US');
try {
console.debug(`Tasks: Executing "${taskName}" at ${dateString}`);
taskFile(client, torn, config, state);
} catch (error) {
console.error(`Tasks: Error executing "${taskName}" at ${dateString}:`, error);
}
currentTaskIndex = (currentTaskIndex + 1) % taskNames.length;
const waitMinutes = config.taskWaitMinutes || 5;
setTimeout(runNextTask, waitMinutes * 60 * 1000);
};
// Start the loop with an initial delay
if (taskNames.length > 0) {
const waitMinutes = config.taskWaitMinutes || 5;
console.log(`Tasks: Scheduler started. First task will run in ${waitMinutes} minutes.`);
setTimeout(runNextTask, waitMinutes * 60 * 1000);
}
}); });
// discord command stuff also yoinked // discord command stuff also yoinked

24
package-lock.json generated
View File

@@ -12,8 +12,7 @@
"canvas": "^3.2.0", "canvas": "^3.2.0",
"discord.js": "^14.18.0", "discord.js": "^14.18.0",
"express": "^5.2.1", "express": "^5.2.1",
"fs": "^0.0.1-security", "fs": "^0.0.1-security"
"node-cron": "^3.0.3"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.24.0", "@eslint/js": "^9.24.0",
@@ -1835,18 +1834,6 @@
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-cron": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz",
"integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==",
"license": "ISC",
"dependencies": {
"uuid": "8.3.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.13.4", "version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -2547,15 +2534,6 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/vary": { "node_modules/vary": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

View File

@@ -20,8 +20,7 @@
"canvas": "^3.2.0", "canvas": "^3.2.0",
"discord.js": "^14.18.0", "discord.js": "^14.18.0",
"express": "^5.2.1", "express": "^5.2.1",
"fs": "^0.0.1-security", "fs": "^0.0.1-security"
"node-cron": "^3.0.3"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.24.0", "@eslint/js": "^9.24.0",

View File

@@ -1,5 +1,5 @@
module.exports = async (client, torn, config) => { module.exports = async (client, torn, config) => {
console.debug("Task: Executing autoUpdateUpgrades");
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const renderer = require('../utils/UpgradeRenderer.js'); const renderer = require('../utils/UpgradeRenderer.js');

View File

@@ -1,5 +1,5 @@
module.exports = async (client, torn, config) => { module.exports = async (client, torn, config) => {
console.debug("Task: Executing noItemOC");
const fs = require('fs'); const fs = require('fs');
const channel = client.channels.resolve(config.channels.ocAlert); const channel = client.channels.resolve(config.channels.ocAlert);
const now = new Date(); const now = new Date();

View File

@@ -1,5 +1,5 @@
module.exports = async (client, torn, config) => { module.exports = async (client, torn, config) => {
console.debug("Task: Executing unavailableOC");
const { EmbedBuilder } = require('discord.js'); const { EmbedBuilder } = require('discord.js');
const fs = require('fs'); const fs = require('fs');
const channel = client.channels.resolve(config.channels.ocAlert); const channel = client.channels.resolve(config.channels.ocAlert);
@@ -41,6 +41,10 @@ module.exports = async (client, torn, config) => {
let embed = new EmbedBuilder() let embed = new EmbedBuilder()
.setTitle('Crime Availability Check') .setTitle('Crime Availability Check')
await torn.faction.crimes({ category: 'recruiting', offset: 0, sort: 'DESC' }).then(crimeList => { await torn.faction.crimes({ category: 'recruiting', offset: 0, sort: 'DESC' }).then(crimeList => {
if (!crimeList) {
console.error("unavailableOC: API returned no crimes.");
return;
}
const data = { crimes: crimeList }; const data = { crimes: crimeList };
data.crimes.forEach(crime => { data.crimes.forEach(crime => {
crimes.difficulty[crime.difficulty - 1].count++ crimes.difficulty[crime.difficulty - 1].count++

View File

@@ -1,12 +1,17 @@
module.exports = async (client, torn, config) => { module.exports = async (client, torn, config) => {
console.debug("Task: Executing unpaidOC");
const { EmbedBuilder } = require('discord.js'); const { EmbedBuilder } = require('discord.js');
const fs = require('fs'); const fs = require('fs');
const channel = client.channels.resolve(config.channels.ocAlert); const channel = client.channels.resolve(config.channels.ocAlert);
const now = new Date(); const now = new Date();
const state = require('../state.json'); const state = require('../state.json');
let embeds = []; let embeds = [];
const data = { crimes: await torn.faction.crimes({ category: 'successful', from: now.getTime() / 1000 - 7 * 24 * 60 * 60, sort: 'DESC' }) }; const crimesList = await torn.faction.crimes({ category: 'successful', from: now.getTime() / 1000 - 7 * 24 * 60 * 60, sort: 'DESC' });
if (!crimesList) {
console.error("unpaidOC: API returned no crimes.");
return;
}
const data = { crimes: crimesList };
for (const crime of data.crimes) { for (const crime of data.crimes) {
if (!crime.rewards.payout) { if (!crime.rewards.payout) {
console.debug(`unpaidOC: Found unpaid crime: ${crime.name}:${crime.id}`); console.debug(`unpaidOC: Found unpaid crime: ${crime.name}:${crime.id}`);

14
torn.js
View File

@@ -97,7 +97,11 @@ async function getCached(collectionName, id, fetchFn, ttl) {
async function fetchApi(path) { async function fetchApi(path) {
const glue = path.includes('?') ? '&' : '?'; const glue = path.includes('?') ? '&' : '?';
const response = await fetch(`${path}${glue}key=${config.torn}`); const response = await fetch(`${path}${glue}key=${config.torn}`);
return response.json(); const data = await response.json();
if (data.error) {
console.error(`Torn API Error on ${path}:`, JSON.stringify(data.error));
}
return data;
} }
const api = { const api = {
@@ -199,12 +203,12 @@ const api = {
}, },
async crimes(options = {}) { async crimes(options = {}) {
let params = new URLSearchParams(); let params = new URLSearchParams();
let category = '';
if (typeof options === 'string') { if (typeof options === 'string') {
category = options; params.append('cat', options);
} else { } else {
if (options.category) category = options.category; if (options.category) params.append('cat', options.category);
if (options.from) params.append('from', options.from); if (options.from) params.append('from', options.from);
if (options.to) params.append('to', options.to); if (options.to) params.append('to', options.to);
if (options.limit) params.append('limit', options.limit); if (options.limit) params.append('limit', options.limit);
@@ -213,7 +217,7 @@ const api = {
if (options.initiator) params.append('initiator', options.initiator); if (options.initiator) params.append('initiator', options.initiator);
} }
const endpoint = category ? `https://api.torn.com/v2/faction/crimes/${category}` : `https://api.torn.com/v2/faction/crimes`; const endpoint = `https://api.torn.com/v2/faction/crimes`;
const queryString = params.toString() ? `?${params.toString()}` : ''; const queryString = params.toString() ? `?${params.toString()}` : '';
const data = await fetchApi(`${endpoint}${queryString}`); const data = await fetchApi(`${endpoint}${queryString}`);