from celery import Celery from celery.schedules import crontab from app.services.bot_service import BotService import os import json from datetime import datetime, timedelta from typing import List, Dict, Optional celery = Celery( 'tasks', broker=os.getenv("CELERY_BROKER_URL", "redis://localhost:6379/0"), backend=os.getenv("CELERY_RESULT_BACKEND", "redis://localhost:6379/0"), ) bot_service = BotService( os.getenv("TELEGRAM_BOT_TOKEN", ""), os.getenv("TELEGRAM_CHAT_ID", "") ) # Load schedules from JSON def load_schedules() -> List[Dict]: schedules_path = "/app/schedules.json" if os.path.exists(schedules_path): with open(schedules_path, "r") as f: return json.load(f) return [] # Save schedules to JSON def save_schedules(schedules: List[Dict]): with open("/app/schedules.json", "w") as f: json.dump(schedules, f, indent=2) def schedule_is_due(schedule: Dict) -> bool: raw = str(schedule.get("time", "")).replace("Z", "+00:00") when = datetime.fromisoformat(raw) if when.tzinfo is not None: when = when.astimezone().replace(tzinfo=None) return datetime.now() >= when @celery.task def send_scheduled_message(schedule_id: int = None): """Send enabled schedules whose time has arrived and that were not sent yet.""" schedules = load_schedules() due = [] for item in schedules: if schedule_id is not None and item.get("id") != schedule_id: continue if not item.get("enabled", True) or item.get("sent"): continue try: ready = schedule_is_due(item) except ValueError: print(f"Invalid schedule time: {item.get('time')}") continue if ready: due.append(item) if not due: print("No schedules due") return changed = False for schedule in due: try: bot_service.send_scheduled_message(schedule) schedule["sent"] = True changed = True print(f"Sent scheduled message: {schedule['time']}") except Exception as e: print(f"Error sending scheduled message: {e}") if changed: save_schedules(schedules) @celery.task def generate_daily_content(): """Generate daily content for all books.""" try: bot_service.generate_daily_content() print("Sent daily content") except Exception as e: print(f"Error generating daily content: {e}") # Periodic tasks celery.conf.beat_schedule = { 'send-scheduled-messages': { 'task': 'app.tasks.celery_tasks.send_scheduled_message', 'schedule': crontab(minute=0), # Every hour 'args': (None,), # Process all enabled schedules }, 'generate-daily-content': { 'task': 'app.tasks.celery_tasks.generate_daily_content', 'schedule': crontab(hour=8, minute=0), # Daily at 8 AM }, }