|
|
|
|
|
import discord, os, io, re, asyncio, logging, requests, replicate, subprocess |
|
|
from transformers import pipeline as transformers_pipeline |
|
|
|
|
|
|
|
|
TOKEN = os.getenv("DISCORD_TOKEN") |
|
|
CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID")) |
|
|
REPL_TOKEN = (os.getenv("OPENAI_API_KEY") or "").strip() |
|
|
HF_TOKEN = (os.getenv("HF_TOKEN") or "").strip() |
|
|
|
|
|
if not TOKEN or not CHANNEL_ID: |
|
|
raise RuntimeError("DISCORD_TOKEN κ³Ό DISCORD_CHANNEL_ID νκ²½ λ³μλ₯Ό λͺ¨λ μ§μ νμΈμ.") |
|
|
|
|
|
if not REPL_TOKEN: |
|
|
raise RuntimeError( |
|
|
"OPENAI_API_KEY νκ²½ λ³μμ Replicate Personal Access Token κ°μ λ£μ΄μ£ΌμΈμ." |
|
|
) |
|
|
|
|
|
|
|
|
os.environ["REPLICATE_API_TOKEN"] = REPL_TOKEN |
|
|
|
|
|
|
|
|
MODEL = "luma/ray-flash-2-540p" |
|
|
|
|
|
|
|
|
translator_kwargs = {"device": -1} |
|
|
if HF_TOKEN: |
|
|
translator_kwargs["token"] = HF_TOKEN |
|
|
|
|
|
translator = transformers_pipeline( |
|
|
"translation", |
|
|
model="Helsinki-NLP/opus-mt-ko-en", |
|
|
**translator_kwargs |
|
|
) |
|
|
|
|
|
def ko2en(text: str) -> str: |
|
|
"""νκΈ ν¬ν¨ μ μμ΄ λ²μ, κ·Έλ μ§ μμΌλ©΄ μλ¬Έ λ°ν.""" |
|
|
if re.search(r"[κ°-ν£]", text): |
|
|
try: |
|
|
return translator(text, max_length=512)[0]["translation_text"].strip() |
|
|
except Exception as e: |
|
|
logging.warning(f"λ²μ μ€ν¨, μλ¬Έ μ¬μ©: {e}") |
|
|
return text |
|
|
|
|
|
|
|
|
logging.basicConfig( |
|
|
level=logging.INFO, |
|
|
format="%(asctime)s [%(levelname)s] %(message)s", |
|
|
handlers=[logging.StreamHandler()] |
|
|
) |
|
|
|
|
|
|
|
|
intents = discord.Intents.default() |
|
|
intents.message_content = True |
|
|
|
|
|
class ImageBot(discord.Client): |
|
|
async def on_ready(self): |
|
|
logging.info(f"Logged in as {self.user} (id={self.user.id})") |
|
|
|
|
|
try: |
|
|
subprocess.Popen(["python", "web.py"]) |
|
|
logging.info("web.py server has been started.") |
|
|
except Exception as e: |
|
|
logging.warning(f"web.py μ€ν μ€ν¨: {e}") |
|
|
|
|
|
async def on_message(self, message: discord.Message): |
|
|
|
|
|
if message.author.id == self.user.id or message.channel.id != CHANNEL_ID: |
|
|
return |
|
|
|
|
|
prompt = message.content.strip() |
|
|
if not prompt: |
|
|
return |
|
|
|
|
|
prompt_en = ko2en(prompt) |
|
|
await message.channel.typing() |
|
|
|
|
|
|
|
|
def run_replicate(): |
|
|
|
|
|
return replicate.run(MODEL, input={"prompt": prompt_en}) |
|
|
|
|
|
try: |
|
|
output = await asyncio.get_running_loop().run_in_executor(None, run_replicate) |
|
|
except Exception as e: |
|
|
logging.error(f"Replicate error: {e}") |
|
|
await message.reply("β οΈ λΉλμ€ μμ± μ€ν¨!") |
|
|
return |
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
if isinstance(output, (list, tuple)): |
|
|
output = output[0] |
|
|
|
|
|
|
|
|
if isinstance(output, str): |
|
|
data = requests.get(output).content |
|
|
else: |
|
|
data = output.read() if hasattr(output, "read") else output |
|
|
|
|
|
video_file = discord.File(io.BytesIO(data), filename="output.mp4") |
|
|
await message.reply(files=[video_file]) |
|
|
except Exception as e: |
|
|
logging.warning(f"λΉλμ€ μ²λ¦¬ μ€ν¨: {e}") |
|
|
await message.reply("β οΈ λΉλμ€λ₯Ό μ μ‘ν μ μμ΅λλ€.") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
replicate.Client(api_token=REPL_TOKEN) |
|
|
ImageBot(intents=intents).run(TOKEN) |
|
|
|