Spaces:
Sleeping
Sleeping
| import os | |
| import logging | |
| import asyncio | |
| from datetime import datetime | |
| from telegram import Update | |
| from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters | |
| # Import Agent and ReminderManager | |
| try: | |
| from .core import TelegramJadeAgent | |
| from .tools import ReminderManager | |
| except ImportError: | |
| from core import TelegramJadeAgent | |
| from tools import ReminderManager | |
| # Logging | |
| logging.basicConfig( | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', | |
| level=logging.INFO | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # Global instances | |
| reminder_manager = ReminderManager() | |
| agent = TelegramJadeAgent(reminder_manager=reminder_manager) | |
| async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): | |
| await context.bot.send_message(chat_id=update.effective_chat.id, text="Hi! I'm Jade, your 24h assistant. How can I help you?") | |
| async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): | |
| chat_id = update.effective_chat.id | |
| user_text = update.message.text | |
| # 1. Get response from Agent | |
| # agent.chat is blocking (sync), so we wrap it. | |
| response = await asyncio.to_thread(agent.chat, chat_id, user_text) | |
| await context.bot.send_message(chat_id=chat_id, text=response) | |
| async def send_reminder_job(context: ContextTypes.DEFAULT_TYPE): | |
| """Callback function for the scheduled job.""" | |
| job_data = context.job.data | |
| chat_id = job_data["chat_id"] | |
| reminder_message = job_data["message"] | |
| reminder_id = job_data["id"] | |
| # Check if reminder is still valid (not deleted) | |
| current_reminders = reminder_manager.get_due_reminders() | |
| if not any(r["id"] == reminder_id for r in current_reminders): | |
| logger.info(f"Reminder {reminder_id} skipped (deleted or sent).") | |
| return | |
| logger.info(f"Triggering reminder {reminder_id} for chat {chat_id}") | |
| # Generate message via Agent | |
| text = await asyncio.to_thread(agent.generate_reminder_message, chat_id, reminder_message) | |
| await context.bot.send_message(chat_id=chat_id, text=text) | |
| # Mark as sent | |
| reminder_manager.mark_as_sent(reminder_id) | |
| async def check_reminders_loop(context: ContextTypes.DEFAULT_TYPE): | |
| """ | |
| Background task running every X seconds to check for new reminders in DB | |
| and schedule them in the JobQueue. | |
| """ | |
| pending = reminder_manager.get_due_reminders() | |
| job_queue = context.job_queue | |
| # Get current scheduled jobs by name | |
| current_jobs = [j.name for j in job_queue.jobs()] | |
| for r in pending: | |
| job_name = f"reminder_{r['id']}" | |
| if job_name not in current_jobs: | |
| try: | |
| run_date = datetime.strptime(r["time"], "%Y-%m-%d %H:%M:%S") | |
| # If time is in past, schedule for immediate execution | |
| if run_date < datetime.now(): | |
| run_date = datetime.now() | |
| logger.info(f"Scheduling {job_name} for {run_date}") | |
| job_queue.run_once( | |
| send_reminder_job, | |
| when=run_date, | |
| data=r, | |
| name=job_name | |
| ) | |
| except Exception as e: | |
| logger.error(f"Failed to schedule {job_name}: {e}") | |
| # Build application at module level so it can be imported by app.py | |
| token = os.getenv("TELEGRAM_BOT_TOKEN") | |
| application = None | |
| if token: | |
| application = ApplicationBuilder().token(token).build() | |
| start_handler = CommandHandler('start', start) | |
| msg_handler = MessageHandler(filters.TEXT & (~filters.COMMAND), handle_message) | |
| application.add_handler(start_handler) | |
| application.add_handler(msg_handler) | |
| # Add a repeating job to sync reminders (e.g. every 10 seconds) | |
| if application.job_queue: | |
| application.job_queue.run_repeating(check_reminders_loop, interval=10, first=1) | |
| logger.info("Telegram application configured") | |
| else: | |
| logger.warning("TELEGRAM_BOT_TOKEN not found - bot will not start") | |
| if __name__ == '__main__': | |
| if not application: | |
| print("Error: TELEGRAM_BOT_TOKEN not found.") | |
| exit(1) | |
| print("Jade Telegram Bot is running...") | |
| application.run_polling() | |