From 06de9919a37c71c75d5dea562478b399a077084f Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Thu, 14 Aug 2025 21:08:33 +0200 Subject: [PATCH] feat: Custom schedule rules --- cron-runner.js | 29 +++++++++++++++++++++++++---- package-lock.json | 4 ++-- package.json | 3 +-- scheduleRules.js | 43 +++++++++++++++++++++++++++++++++++++++++++ server.js | 16 ++++++++++++---- 5 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 scheduleRules.js diff --git a/cron-runner.js b/cron-runner.js index 54d2c35..9e0d5fb 100644 --- a/cron-runner.js +++ b/cron-runner.js @@ -1,8 +1,9 @@ const cron = require('node-cron'); const { exec } = require('child_process'); +const { scheduleRules, toMinutes } = require('./scheduleRules'); function runScraper() { - console.log('Running scraper...'); + console.log(`Running scraper at ${new Date().toLocaleString()}...`); exec('node scrape/scraper.js', (error, stdout, stderr) => { if (error) { console.error(`Scraper error: ${error.message}`); @@ -13,10 +14,30 @@ function runScraper() { }); } +function createSchedules(rules) { + rules.forEach(rule => { + const startMin = toMinutes(rule.start); + const endMin = toMinutes(rule.end === "0:00" ? "24:00" : rule.end); + const times = []; + + const adjustedEnd = endMin <= startMin ? endMin + 1440 : endMin; + for (let t = startMin; t < adjustedEnd; t += rule.interval) { + const h = Math.floor(t % 1440 / 60); + const m = t % 60; + times.push({ h, m }); + } + + times.forEach(({ h, m }) => { + const cronExpr = `${m} ${h} * * *`; + cron.schedule(cronExpr, runScraper); + console.log(`Scheduled: ${cronExpr}`); + }); + }); +} + // Run immediately at start runScraper(); -// Schedule to run every 10 minutes -cron.schedule('*/10 * * * *', runScraper); +createSchedules(scheduleRules); -console.log('Cron scheduler started. Scraper will run every 10 minutes.'); +console.log('Cron scheduler started with custom intervals.'); diff --git a/package-lock.json b/package-lock.json index 5dce1f5..cc17ef7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "tablescraper", + "name": "jecnarozvrh", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "tablescraper", + "name": "jecnarozvrh", "version": "1.0.0", "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 149d392..c8c0541 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "tablescraper", + "name": "jecnarozvrh", "version": "1.0.0", "description": "", "license": "ISC", @@ -7,7 +7,6 @@ "type": "commonjs", "main": "server.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", "start": "concurrently \"node server.js\" \"node cron-runner.js\"" }, "dependencies": { diff --git a/scheduleRules.js b/scheduleRules.js new file mode 100644 index 0000000..b8219c8 --- /dev/null +++ b/scheduleRules.js @@ -0,0 +1,43 @@ +// Rules: start and end in 24h format, interval in minutes +const scheduleRules = [ + { start: "0:00", end: "3:00", interval: 180 }, + { start: "3:00", end: "4:00", interval: 60 }, + { start: "5:00", end: "6:00", interval: 30 }, + { start: "6:00", end: "7:30", interval: 15 }, + { start: "7:30", end: "16:00", interval: 5 }, + { start: "16:00", end: "19:00", interval: 60 }, + { start: "19:00", end: "0:00", interval: 180 } +]; + +function toMinutes(timeStr) { + const [h, m] = timeStr.split(":").map(Number); + return h * 60 + (m || 0); +} + +function getCurrentInterval(date = new Date()) { + const nowMinutes = date.getHours() * 60 + date.getMinutes(); + + for (const rule of scheduleRules) { + let startMin = toMinutes(rule.start); + let endMin = toMinutes(rule.end === "0:00" ? "24:00" : rule.end); + + // Handle wrap-around midnight + if (endMin <= startMin) { + if (nowMinutes >= startMin || nowMinutes < endMin) { + return rule.interval; + } + } else { + if (nowMinutes >= startMin && nowMinutes < endMin) { + return rule.interval; + } + } + } + + return null; +} + +module.exports = { + scheduleRules, + getCurrentInterval, + toMinutes +}; diff --git a/server.js b/server.js index dbbdeea..5e26ace 100644 --- a/server.js +++ b/server.js @@ -2,11 +2,19 @@ const express = require("express"); const path = require("path"); const app = express(); const fs = require("fs/promises"); +const { getCurrentInterval } = require("./scheduleRules"); const PORT = process.env.PORT || 3000; -app.get('/', (_, res) => { - res.sendFile(path.join(__dirname, "db", "current.json")); +app.get('/', async (_, res) => { + const dataStr = fs.readFile(path.join(__dirname, "db", "current.json")); + const data = JSON.parse(dataStr); + + data["status"] = { + currentUpdateSchedule: getCurrentInterval(), + }; + + res.json(data); }); app.get("/status", async (_, res) => { @@ -14,9 +22,9 @@ app.get("/status", async (_, res) => { const data = JSON.parse(dataStr); if (data.working) { - res.json({working: true}) + res.json({ working: true }) } else { - res.json({working: data.working, message: data.message}) + res.json({ working: data.working, message: data.message }) } })