Usa o modelo multilingual, ignora trechos curtos e o template do Llama 3.2 para a resposta sair em uma frase completa. O chat deixa a API livre durante a geração, o upload indexa o PDF e os agendamentos não são gravados duas vezes.
96 lines
2.9 KiB
Python
96 lines
2.9 KiB
Python
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
|
|
},
|
|
}
|