import os import logging import asyncio import socket from datetime import datetime from telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters from telegram.request import HTTPXRequest # --- A GAMBIARRA SUPREMA DA BERTA (HARDCODED DNS) --- # Se o DNS do Hugging Face não funciona, nós somos o DNS. # Este é o IP oficial da API do Telegram. original_getaddrinfo = socket.getaddrinfo def fixed_ip_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): # Se for o Telegram, retornamos o IP direto (149.154.167.220) if host == 'api.telegram.org': return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', ('149.154.167.220', port))] # Para todo o resto (Google, DuckDuckGo), tentamos usar o sistema normal try: return original_getaddrinfo(host, port, family, type, proto, flags) except socket.gaierror: # Se falhar no DuckDuckGo, paciência, mas o bot liga. return original_getaddrinfo(host, port, family, type, proto, flags) socket.getaddrinfo = fixed_ip_getaddrinfo # ---------------------------------------------------- # Carrega variáveis try: from dotenv import load_dotenv load_dotenv() except ImportError: pass # Imports seguros try: from core import TelegramJadeAgent from tools import ReminderManager except ImportError: import sys sys.path.append(os.path.dirname(os.path.abspath(__file__))) from core import TelegramJadeAgent from tools import ReminderManager # Logging setup logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) logger = logging.getLogger(__name__) 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="Oi! Eu sou a Jade. Estou viva graças à Berta!") async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): chat_id = update.effective_chat.id user_text = update.message.text try: await context.bot.send_chat_action(chat_id=chat_id, action="typing") response = await asyncio.to_thread(agent.chat, chat_id, user_text) await context.bot.send_message(chat_id=chat_id, text=response) except Exception as e: logger.error(f"Erro ao processar mensagem: {e}") await context.bot.send_message(chat_id=chat_id, text="Tive um erro interno, desculpe.") async def send_reminder_job(context: ContextTypes.DEFAULT_TYPE): job_data = context.job.data chat_id = job_data["chat_id"] reminder_message = job_data["message"] reminder_id = job_data["id"] current_reminders = reminder_manager.get_due_reminders() if not any(r["id"] == reminder_id for r in current_reminders): return text = await asyncio.to_thread(agent.generate_reminder_message, chat_id, reminder_message) await context.bot.send_message(chat_id=chat_id, text=text) reminder_manager.mark_as_sent(reminder_id) async def check_reminders_loop(context: ContextTypes.DEFAULT_TYPE): reminder_manager._load_reminders() pending = [r for r in reminder_manager.reminders if r["status"] == "pending"] job_queue = context.job_queue 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 run_date < datetime.now(): run_date = datetime.now() 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}") if __name__ == '__main__': token = os.getenv("TELEGRAM_BOT_TOKEN") if not token: logger.error("Error: TELEGRAM_BOT_TOKEN not found.") exit(1) # Removemos configurações complexas de HTTPXRequest para usar o padrão (que agora usa nosso IP fixo) application = ApplicationBuilder().token(token).build() application.add_handler(CommandHandler('start', start)) application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), handle_message)) if application.job_queue: application.job_queue.run_repeating(check_reminders_loop, interval=10, first=1) print("Jade Telegram Bot is running...") application.run_polling(drop_pending_updates=True)