File size: 5,743 Bytes
49ec9dc
6659834
 
 
49ec9dc
 
6659834
 
 
 
49ec9dc
 
 
 
898a986
49ec9dc
6659834
 
49ec9dc
6659834
 
 
49ec9dc
 
 
 
0b58fc4
49ec9dc
9d6ae27
49ec9dc
 
 
6659834
49ec9dc
 
 
 
 
 
 
 
9d6ae27
 
49ec9dc
6659834
49ec9dc
6659834
49ec9dc
 
 
 
 
 
 
 
 
 
 
 
 
 
2edcd19
 
49ec9dc
 
6659834
49ec9dc
 
6659834
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49ec9dc
 
6659834
49ec9dc
6659834
49ec9dc
 
 
6659834
49ec9dc
6659834
 
 
 
 
 
 
 
 
49ec9dc
9d6ae27
 
49ec9dc
 
 
6659834
49ec9dc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# img_bot.py
import discord, os, io, re, random, asyncio, logging, requests, replicate, subprocess
from transformers import pipeline as transformers_pipeline    # λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ
from gradio_client import Client, handle_file                 # NEW ─ Gradio API

# ── ν™˜κ²½ λ³€μˆ˜ ────────────────────────────────────────────────
TOKEN       = os.getenv("DISCORD_TOKEN")                      # Discord 봇 토큰
CHANNEL_ID  = int(os.getenv("DISCORD_CHANNEL_ID"))            # κ°μ‹œν•  채널 ID
REPL_TOKEN  = (os.getenv("OPENAI_API_KEY") or "").strip()     # κ·ΈλŒ€λ‘œ μœ μ§€(Replicate 토큰)
HF_TOKEN    = (os.getenv("HF_TOKEN") or "").strip()           # Hugging Face Personal Access Token

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 값을 λ„£μ–΄μ£Όμ„Έμš”.")

# Replicate λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ°Έμ‘°ν•˜λ„λ‘ 토큰 μ£Όμž… (비둝 μ‚¬μš© μ•ˆ ν•˜μ§€λ§Œ ꡬ쑰 μœ μ§€)
os.environ["REPLICATE_API_TOKEN"] = REPL_TOKEN

# ── Gradio μ„œλ²„ μ—”λ“œν¬μΈνŠΈ ──────────────────────────────────
GRADIO_URL = "http://211.233.58.201:7896"           # μ„œλ²„ μ£Όμ†Œ
GRADIO_API = "/generate_image"                      # μ‚¬μš©ν•  ν•¨μˆ˜ 이름

# ── λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ (CPU) ───────────────────────────────────
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")

# ── Discord μΈν…νŠΈ ──────────────────────────────────────────
intents = discord.Intents.default()
intents.message_content = True   # λ©”μ‹œμ§€ 읽기 (Portalμ—μ„œ ON ν•„μš”)

class ImageBot(discord.Client):
    async def on_ready(self):
        logging.info(f"Logged in as {self.user} (id={self.user.id})")
        # web.py 병렬 μ‹€ν–‰
        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_raw = message.content.strip()
        if not prompt_raw:
            return

        prompt_en = ko2en(prompt_raw)          # ν•œκΈ€ β†’ μ˜μ–΄
        await message.channel.typing()

        # ── Gradio 호좜 ────────────────────────────────────
        def generate_image():
            client = Client(GRADIO_URL)
            seed = random.randint(0, 2**32 - 1)
            result = client.predict(
                prompt=prompt_en,
                width=768,
                height=768,
                guidance=3.5,
                inference_steps=30,
                seed=seed,
                do_img2img=False,
                init_image=None,            # img2img μ‚¬μš© μ•ˆ 함
                image2image_strength=0.8,
                resize_img=True,
                api_name=GRADIO_API
            )
            return result[0]   # dict (path / url)

        try:
            img_info = await asyncio.get_running_loop().run_in_executor(None, generate_image)
        except Exception as e:
            logging.error(f"Gradio API error: {e}")
            await message.reply("⚠️ 이미지 생성 μ‹€νŒ¨!")
            return

        # ── 이미지 Discord 전솑 ─────────────────────────────
        files = []
        try:
            if img_info.get("path"):                 # μ„œλ²„κ°€ 파일 경둜둜 λ°˜ν™˜
                with open(img_info["path"], "rb") as f:
                    files.append(discord.File(io.BytesIO(f.read()), filename="generated.webp"))
            elif img_info.get("url"):                # URL λ˜λŠ” base64
                data = requests.get(img_info["url"]).content
                files.append(discord.File(io.BytesIO(data), filename="generated.webp"))
        except Exception as e:
            logging.warning(f"이미지 처리 μ‹€νŒ¨: {e}")

        await message.reply(files=files if files else None,
                            content=None if files else "⚠️ 이미지λ₯Ό 전솑할 수 μ—†μŠ΅λ‹ˆλ‹€.")

# ── μ‹€ν–‰ ────────────────────────────────────────────────────
if __name__ == "__main__":
    replicate.Client(api_token=REPL_TOKEN)    # ꡬ쑰 μœ μ§€: Replicate 인증(λ―Έμ‚¬μš©)
    ImageBot(intents=intents).run(TOKEN)