import discord import logging import os from io import BytesIO from gradio_client import Client from gradio_client import exceptions as gradio_client_exceptions import subprocess # 로깅 설정 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s: %(message)s', handlers=[logging.StreamHandler()]) # 인텐트 설정 intents = discord.Intents.default() intents.message_content = True # API 클라이언트 설정 + id/pw 반영 방법임임 api_client = Client("http://211.233.58.202:7953") # 디스코드 봇 클래스 class MyClient(discord.Client): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.is_processing = False async def on_ready(self): logging.info(f'{self.user}로 로그인되었습니다!') # web.py 실행 try: subprocess.Popen(["python", "web.py"]) logging.info("web.py 서버가 시작되었습니다.") except Exception as e: logging.error(f"web.py 실행 중 오류 발생: {e}") # 상호 대화 기능 알림 channel = self.get_channel(int(os.getenv("DISCORD_CHANNEL_ID", "123456789012345678"))) await channel.send("저는 이미지 생성을 수행할 수 있으며, 생성된 이미지에 대한 설명을 한글로 제공하고 상호 대화를 할 수 있습니다. '프롬프트에 한글 또는 영문을 입력 하세요.") async def on_message(self, message): # 지정된 채널 ID TARGET_CHANNEL_ID = 1269529561914413106 # 메시지가 지정된 채널에서 오지 않았거나 봇 자신의 메시지인 경우 무시 if message.channel.id != TARGET_CHANNEL_ID or message.author == self.user: return # 메시지에서 '!'를 기준으로 명령어와 프롬프트 분리 if message.content.startswith('!'): command, *prompt_parts = message.content.split(' ') prompt = ' '.join(prompt_parts) else: prompt = message.content # 명령어 없이 프롬프트만 있으면 그대로 사용 if self.is_processing: await message.channel.send("이미지 생성이 이미 진행 중입니다. 잠시만 기다려 주세요.") return self.is_processing = True try: image_path, used_seed, translated_prompt = await self.generate_image(prompt) user_id = message.author.id await message.channel.send( content=f"<@{user_id}> 님이 요청하신 이미지입니다.\n사용된 시드: {used_seed}\n", file=discord.File(image_path) ) # 이미지 생성 후 설명 제공 및 대화 await initiate_conversation(prompt, message) except RuntimeError as e: await message.channel.send(f"이미지 생성 중 오류가 발생했습니다: {str(e)}") except Exception as e: logging.error(f'이미지 생성 중 예상치 못한 오류 발생: {e}') await message.channel.send("이미지 생성 중 예상치 못한 오류가 발생했습니다. 나중에 다시 시도해주세요.") finally: self.is_processing = False async def generate_image(self, prompt): if not prompt: raise ValueError("프롬프트가 비어있거나 None입니다") logging.debug(f"API에 요청 전송 중. 프롬프트: {prompt}") try: result = api_client.predict( prompt=prompt, seed=123, randomize_seed=False, width=1024, height=576, guidance_scale=5, num_inference_steps=28, api_name="/infer_t2i" ) logging.debug(f"API 응답 수신: {result}") if isinstance(result, tuple) and len(result) == 3: image_path, used_seed, translated_prompt = result logging.info(f"생성된 이미지 경로: {image_path}") logging.info(f"사용된 시드: {used_seed}") return image_path, used_seed, translated_prompt else: raise ValueError("예상치 못한 API 응답 형식") except gradio_client_exceptions.AppError as e: logging.error(f"Gradio 앱 오류: {e}") raise RuntimeError(f"API 서버 오류: {str(e)}. 서버 관리자에게 문의하세요.") except Exception as e: logging.error(f'API 요청 중 오류 발생: {e}', exc_info=True) raise RuntimeError(f"API 요청 중 오류 발생: {str(e)}") async def initiate_conversation(prompt, message): logging.debug(f'대화 시작 중: {prompt}') # 이미지 설명을 한글로 생성 description = "생성된 이미지입니다." logging.debug(f'이미지 설명: {description}') await message.channel.send(f"이미지 설명: {description}") await continue_conversation(prompt, message) async def continue_conversation(prompt, message): # 대화 지속 기능 logging.debug(f'대화 지속 중: {prompt}') # 계속 대화 내용을 받아 상호작용하도록 구현 # 디스코드 토큰 및 봇 실행 if __name__ == "__main__": discord_token = os.getenv('DISCORD_TOKEN') discord_client = MyClient(intents=intents) discord_client.run(discord_token)