aboutsummaryrefslogtreecommitdiff
path: root/modules/ext/cron.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-05-25 18:02:02 +0200
committerAgando <roduccomm@gmail.com>2026-05-25 18:02:02 +0200
commit4baa484b84c5184286cac2743575251454a5ee2b (patch)
treecb9002f93644f363d0f35831dc97e6492bbb0ed6 /modules/ext/cron.js
auto: 2026-05-25_18:02 changes
Diffstat (limited to 'modules/ext/cron.js')
-rw-r--r--modules/ext/cron.js110
1 files changed, 110 insertions, 0 deletions
diff --git a/modules/ext/cron.js b/modules/ext/cron.js
new file mode 100644
index 0000000..66cd18e
--- /dev/null
+++ b/modules/ext/cron.js
@@ -0,0 +1,110 @@
+class CronModule {
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ this.jobs = {};
+ this.counter = 0;
+ this.MIN_INTERVAL = 5;
+ this.STORAGE_KEY = 'webx11_cron_jobs';
+ this._restoreJobs();
+ }
+ requirements() {
+ return { met: true, missing: [] };
+ }
+ getHelpInfo() {
+ return {
+ 'cron-every': 'cron-every <seconds> <command> — Schedule a command to run every N seconds',
+ 'cron-list': 'cron-list — List all active cron jobs',
+ 'cron-stop': 'cron-stop <id> — Stop a specific cron job',
+ 'cron-clear': 'cron-clear — Stop all cron jobs'
+ };
+ }
+ registerCommands() {
+ this.commands['cron-every'] = (args) => this.every(args);
+ this.commands['cron-list'] = () => this.list();
+ this.commands['cron-stop'] = (args) => this.stop(args);
+ this.commands['cron-clear'] = () => this.clear();
+ }
+ _restoreJobs() {
+ try {
+ const saved = localStorage.getItem(this.STORAGE_KEY);
+ if (!saved) return;
+ const data = JSON.parse(saved);
+ if (!Array.isArray(data) || data.length === 0) return;
+ let maxId = 0;
+ data.forEach(j => {
+ if (j.id > maxId) maxId = j.id;
+ if (this.counter < j.id) this.counter = j.id;
+ this.jobs[j.id] = {
+ cmd: j.cmd,
+ interval: j.interval,
+ runs: j.runs || 0,
+ timer: setInterval(() => {
+ if (!this.jobs[j.id]) return;
+ this.jobs[j.id].runs++;
+ this.terminal.print(`[cron #${j.id}] Running: ${j.cmd}`, 'info');
+ this.terminal.executeCommand(j.cmd);
+ }, j.interval)
+ };
+ });
+ this.counter = maxId;
+ if (data.length > 0) this.terminal.print(`↻ Restored ${data.length} cron job(s) from storage`, 'info');
+ } catch (e) { /* silently ignore corrupt data */ }
+ }
+ _saveJobs() {
+ try {
+ const data = Object.entries(this.jobs).map(([id, j]) => ({
+ id: parseInt(id),
+ cmd: j.cmd,
+ interval: j.interval,
+ runs: j.runs
+ }));
+ localStorage.setItem(this.STORAGE_KEY, JSON.stringify(data));
+ } catch (e) { /* quota exceeded */ }
+ }
+ every(args) {
+ if (args.length < 2) return this.terminal.print('Usage: cron-every <seconds> <command>', 'warning');
+ const secs = parseInt(args[0]);
+ if (isNaN(secs) || secs < this.MIN_INTERVAL) return this.terminal.print(`Interval must be >= ${this.MIN_INTERVAL} seconds`, 'warning');
+ const cmd = args.slice(1).join(' ');
+ this.counter++;
+ const id = this.counter;
+ this.jobs[id] = {
+ cmd, interval: secs * 1000, runs: 0,
+ timer: setInterval(() => {
+ this.jobs[id].runs++;
+ this.terminal.print(`[cron #${id}] Running: ${cmd}`, 'info');
+ this.terminal.executeCommand(cmd);
+ }, secs * 1000)
+ };
+ this._saveJobs();
+ this.terminal.print(`Cron job #${id} started: "${cmd}" every ${secs}s`, 'success');
+ }
+ list() {
+ const ids = Object.keys(this.jobs);
+ if (ids.length === 0) return this.terminal.print('No active cron jobs', 'info');
+ this.terminal.print('=== Cron Jobs ===', 'info');
+ ids.forEach(id => {
+ const j = this.jobs[id];
+ this.terminal.print(` #${id}: "${j.cmd}" every ${j.interval / 1000}s (${j.runs} runs)`);
+ });
+ }
+ stop(args) {
+ if (!args[0]) return this.terminal.print('Usage: cron-stop <id>', 'warning');
+ const id = parseInt(args[0]);
+ if (!this.jobs[id]) return this.terminal.print(`Cron job #${id} not found`, 'error');
+ clearInterval(this.jobs[id].timer);
+ delete this.jobs[id];
+ this._saveJobs();
+ this.terminal.print(`Cron job #${id} stopped`, 'success');
+ }
+ clear() {
+ Object.keys(this.jobs).forEach(id => { clearInterval(this.jobs[id].timer); });
+ this.jobs = {};
+ localStorage.removeItem(this.STORAGE_KEY);
+ this.terminal.print('All cron jobs stopped', 'success');
+ }
+}
+if (typeof window.webx11 !== 'undefined' && window.webx11) {
+ webx11.moduleManager.registerModule(new CronModule(), 'https://webx11.duckdns.org/spaces/chatstudio/newos4/modules/cron.js');
+}