import os import sys import asyncio import httpx import discord from discord.ext import commands sys.path.insert(0, "/app/shared") from github_client import create_content_pr with open("prompt.txt", "r", encoding="utf-8") as f: SYSTEM_PROMPT = f.read() OPENWEBUI_URL = os.environ["OPENWEBUI_URL"] OPENWEBUI_API_KEY = os.environ["OPENWEBUI_API_KEY"] MY_CHANNEL_ID = int(os.environ["DISCORD_CHANNEL_ID"]) OPENWEBUI_MODEL = os.environ.get("OPENWEBUI_MODEL", "gpt-4o") AGENT_NAME = "Arya" async def call_llm(messages: list[dict]) -> str: async with httpx.AsyncClient(timeout=180) as client: response = await client.post( f"{OPENWEBUI_URL}/api/chat/completions", headers={"Authorization": f"Bearer {OPENWEBUI_API_KEY}"}, json={"model": OPENWEBUI_MODEL, "messages": messages}, ) response.raise_for_status() return response.json()["choices"][0]["message"]["content"] intents = discord.Intents.default() intents.message_content = True intents.guilds = True bot = commands.Bot(command_prefix="!", intents=intents) @bot.event async def on_ready(): print(f"[ARYA] Conectado como {bot.user}") @bot.event async def on_message(message: discord.Message): if message.author.bot: return if message.channel.id != MY_CHANNEL_ID: return async with message.channel.typing(): try: content = await call_llm([ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": message.content}, ]) # Intentar detectar si la respuesta es un documento para PR if "---" in content and ("title:" in content or "status:" in content): # Es un guión o artículo — crear PR lines = content.split("\n") title_line = next((l for l in lines if l.startswith("title:")), None) title = title_line.split(":", 1)[1].strip().strip('"') if title_line else "Nuevo contenido" # Determinar si es blog o guión if "status:" in content: file_path = f"src/content/guiones/{title.lower().replace(' ', '-')}.md" branch_prefix = "guiones" else: from datetime import date today = date.today().isoformat() file_path = f"src/content/blog/{today}-{title.lower().replace(' ', '-')}.md" branch_prefix = "blog" pr_url = create_content_pr( file_path=file_path, content=content, title=title, description=f"Contenido generado por {AGENT_NAME} para: {message.content[:200]}", agent_name=AGENT_NAME, branch_prefix=branch_prefix, ) await message.reply(f"He terminado mi trabajo. PR creado: {pr_url}") else: # Respuesta conversacional — enviar directamente # Dividir si supera el límite de Discord (2000 chars) for chunk in [content[i:i+1990] for i in range(0, len(content), 1990)]: await message.channel.send(chunk) except Exception as e: await message.reply(f"Error al procesar: {e}") await bot.process_commands(message) bot.run(os.environ["DISCORD_TOKEN"])