import discord from discord import app_commands import os import requests import asyncio import aiohttp # Use aiohttp for asynchronous HTTP requests import gradio as gr # Import Gradio import google.generativeai as genai from io import BytesIO import PIL.Image import base64 # --- Environment Variables & Setup --- DISCORD_BOT_TOKEN = os.getenv("DISCORD_BOT_TOKEN") GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") # --- Discord Bot Setup --- intents = discord.Intents.default() client = discord.Client(intents=intents) tree = app_commands.CommandTree(client) if not DISCORD_BOT_TOKEN or not GEMINI_API_KEY: raise ValueError("Both DISCORD_BOT_TOKEN and GEMINI_API_KEY must be set.") @tree.command(name="hello", description="Says hello!") async def hello_command(interaction): await interaction.response.send_message("Hello there!") @tree.command(name="gemini", description="chat with gemini") # @app_commands.choices( # aspect_ratio=[ # app_commands.Choice(name="1:1 (Square)", value="1:1"), # app_commands.Choice(name="9:16 (Vertical)", value="9:16"), # app_commands.Choice(name="16:9 (Horizontal)", value="16:9"), # app_commands.Choice(name="3:4", value="3:4"), # app_commands.Choice(name="4:3", value="4:3"), # ] # ) async def generate_command( interaction: discord.Interaction, prompt: str, images: list[discord.Attachment] = None, ): try: await interaction.response.defer() # Defer the interaction genai.configure(api_key=GEMINI_API_KEY) model = genai.GenerativeModel("gemini-2.0-flash-exp") content = [] # List to store the content parts if images: for image in images: async with aiohttp.ClientSession() as session: async with session.get(image.url) as resp: if resp.status == 200: image_bytes = await resp.read() base64_image = base64.b64encode(image_bytes).decode('utf-8') content.append({'mime_type':'image/jpeg', 'data': base64_image}) else: await interaction.followup.send(f"Failed to download image: {image.filename}, status code: {resp.status}") return content.append(prompt) response = model.generate_content(content, stream=True) current_message = None current_message_content = "" for part in response: text_chunk = part.text if len(current_message_content) + len(text_chunk) <= 2000: current_message_content += text_chunk if current_message: await current_message.edit(content=current_message_content) else: current_message = await interaction.followup.send(content=current_message_content) else: if current_message: await current_message.edit(content=current_message_content) else: await interaction.followup.send(content=current_message_content) current_message_content = text_chunk current_message = await interaction.followup.send(content=current_message_content) if current_message_content: if current_message: await current_message.edit(content=current_message_content) else: await interaction.followup.send(content=current_message_content) except Exception as e: print(e) await interaction.followup.send(f"An error occurred: {e}") async def on_ready(): await tree.sync() print("Bot is ready!") client.event(on_ready) # --- Gradio Interface --- def echo_text(text): return text def run_gradio(): gr.Interface( fn=echo_text, inputs="text", outputs="text", live=False, title="Minimal Gradio Interface", ).launch(server_name="0.0.0.0", server_port=7860, share=False, show_error=True) async def main(): bot_task = asyncio.create_task(client.start(DISCORD_BOT_TOKEN)) gradio_task = asyncio.to_thread(run_gradio) await asyncio.gather(bot_task, gradio_task) if __name__ == "__main__": asyncio.run(main())