/** * Cron Manager Plugin v1.1.0 * Schedules delayed tasks and sends results back to the original conversation. */ var JOBS_KEY = 'cron_jobs'; // Initialize state with jobs from storage (if any) var storedJobs = shadowman.storage.get(JOBS_KEY); if (!storedJobs) storedJobs = []; shadowman.state.set(JOBS_KEY, storedJobs); // --- Tools --- shadowman.tools.register('schedule_job', function(args) { var schedule = args.schedule; var instructions = args.instructions; var conversationId = args.conversationId; var jobs = shadowman.state.get(JOBS_KEY) || []; var jobId = 'job_' + Math.random().toString(36).substr(2, 9); var triggerTime = null; var intervalMs = null; // Parser: number = minutes interval, string = ISO timestamp if (!isNaN(schedule)) { intervalMs = parseInt(schedule) * 60 * 1000; } else { var date = new Date(schedule); if (!isNaN(date.getTime())) { triggerTime = date.getTime(); } else { return { error: "Invalid schedule format. Use an ISO timestamp or a number of minutes for intervals." }; } } var job = { id: jobId, schedule: schedule, instructions: instructions, conversationId: conversationId, triggerTime: triggerTime, intervalMs: intervalMs, lastRun: 0, createdAt: Date.now() }; jobs.push(job); shadowman.storage.set(JOBS_KEY, jobs); shadowman.state.set(JOBS_KEY, jobs); return { status: "success", jobId: jobId, message: "Job scheduled. It will trigger at " + schedule + " and notify conversation " + conversationId + "." }; }); shadowman.tools.register('list_jobs', function() { var jobs = shadowman.state.get(JOBS_KEY) || []; return { jobs: jobs }; }); shadowman.tools.register('cancel_job', function(args) { var jobId = args.jobId; var jobs = shadowman.state.get(JOBS_KEY) || []; var filtered = []; for (var i = 0; i < jobs.length; i++) { if (jobs[i].id !== jobId) { filtered.push(jobs[i]); } } if (jobs.length === filtered.length) { return { error: "Job not found." }; } shadowman.storage.set(JOBS_KEY, filtered); shadowman.state.set(JOBS_KEY, filtered); return { status: "success", message: "Job " + jobId + " cancelled." }; }); // --- Background Worker --- shadowman.background.run(function() { var JOBS_KEY = 'cron_jobs'; shadowman.log.info("Cron Manager worker started"); while (true) { try { var jobs = shadowman.state.get(JOBS_KEY); if (jobs && jobs.length > 0) { var currentTime = Date.now(); var jobsToTrigger = []; var jobsToRemove = []; for (var i = 0; i < jobs.length; i++) { var job = jobs[i]; if (job.triggerTime && currentTime >= job.triggerTime) { jobsToTrigger.push(job); jobsToRemove.push(job.id); } else if (job.intervalMs && (currentTime - job.lastRun) >= job.intervalMs) { jobsToTrigger.push(job); } } for (var i = 0; i < jobsToTrigger.length; i++) { var job = jobsToTrigger[i]; shadowman.log.info("Triggering cron job " + job.id); shadowman.events.emit('message', { text: "⏰ **Cron Job Triggered**\n\n**Instructions:** " + job.instructions + "\n\n*This is an automated notification from Cron Manager.*", conversationId: job.conversationId, platform: 'CronManager', sender: 'Cron Manager' }); if (job.intervalMs) { job.lastRun = currentTime; } } if (jobsToRemove.length > 0) { var remainingJobs = []; for (var i = 0; i < jobs.length; i++) { if (jobsToRemove.indexOf(jobs[i].id) === -1) { remainingJobs.push(jobs[i]); } } shadowman.state.set(JOBS_KEY, remainingJobs); } } shadowman.utils.sleep(10000); } catch (e) { shadowman.log.error("Cron worker error: " + e.toString()); shadowman.utils.sleep(5000); } } }); shadowman.log.info("Cron Manager plugin v1.1.0 ready");