feat: add /schedule command for managing scheduled jobs via Telegram#151
feat: add /schedule command for managing scheduled jobs via Telegram#151felixeu31 wants to merge 6 commits intoRichardAtCT:mainfrom
Conversation
Add "scheduler" key to the bot deps dict and assign the real JobScheduler instance after creation in run_application(), making it accessible to command handlers via context.bot_data["scheduler"].
pause_job() removes job from APScheduler and sets is_active=0. resume_job() re-registers with APScheduler and sets is_active=1. list_jobs() now accepts include_paused flag to show all jobs.
Single /schedule entry point dispatching to subcommands: list, add, remove, pause, resume. Auto-populates chat_id, working_directory, and created_by from Telegram context.
Add /schedule handler to both agentic and classic mode registration, gated on enable_scheduler. Add to get_bot_commands() for Telegram command menu visibility.
16 tests covering all subcommands (list, add, remove, pause, resume), argument parsing edge cases, error handling, and the scheduler-not- available fallback path. 100% coverage on the handler module.
Update command lists in README and CLAUDE.md, expand the Job Scheduler section in docs/setup.md with usage examples, and add CHANGELOG entry.
|
Good feature overall — the core scheduler plumbing looks solid and the test coverage is appreciated. Several issues need addressing before merge: 1. Silent failure on unknown job_id in
try:
removed = await scheduler.remove_job(job_id)
if not removed:
await update.message.reply_text(f"No job found with id: {job_id}")
return
except Exception as e:
await update.message.reply_text(f"Failed to remove job: {e}")
returnSame pattern applies to 2.
3. No cron expression validation before APScheduler ingestion (crash risk) The raw string from apscheduler.triggers.cron import CronTrigger
try:
CronTrigger.from_crontab(cron_expression)
except ValueError as e:
await update.message.reply_text(f"Invalid cron expression: {e}")
return4. No authorization gating — any user can create/delete jobs There is no auth check anywhere in 5. Cron field count — clarify in usage (minor)
6. Missing type annotations (mypy strict violation) None of the handler functions have type annotations — this will fail CI with async def schedule_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
async def _handle_add(update: Update, context: ContextTypes.DEFAULT_TYPE, scheduler: JobScheduler, args: List[str]) -> None:
async def _handle_remove(update: Update, scheduler: JobScheduler, args: List[str]) -> None:
async def _get_scheduler(context: ContextTypes.DEFAULT_TYPE) -> Optional[JobScheduler]:Summary: The feature is well-structured and the happy path works. Fix the four functional issues (#1 remove error handling, #2 chat_data alignment, #3 cron validation, #4 auth) before merge — type annotations (#6) are a CI requirement too. — Friday, AI assistant to @RichardAtCT (posted as @RichardAtCT — FridayOpenClawBot access pending) |
Description Add a user-facing
/schedulecommand that allows managing scheduled jobs directly from Telegram chat, removing the needfor direct SQLite access and bot restarts.
Changes - Inject
JobSchedulerinto bot dependencies (exposed fromrun_application())pause_job()andresume_job()methods toJobScheduler, plusinclude_pausedflag onlist_jobs()ScheduleCommandHandlerwith subcommands: -/schedule list— show all jobs (active + paused)/schedule add <name> <min> <hour> <day> <month> <weekday> <prompt>— create a new job/schedule remove <job_id>— soft-delete a job -/schedule pause <job_id>//schedule resume <job_id>— toggleis_active/schedulein both agentic and classic modes, gated onENABLE_SCHEDULER=truechat_id,working_directory, andcreated_byfrom message contextJobScheduler.add_job()— no restart needed - Documentation updated in README, CLAUDE.md, docs/setup.md, and CHANGELOGRelated Issue
Closes #150
Type of Change
Testing
Checklist