File size: 5,770 Bytes
49ec9dc
6659834
7b7fd88
3241add
49ec9dc
 
444fc48
 
 
 
49ec9dc
 
 
 
7b7fd88
49ec9dc
3241add
49ec9dc
7b7fd88
554c43d
 
ded0e5f
49ec9dc
c80bb75
49ec9dc
7b7fd88
 
 
 
49ec9dc
 
444fc48
 
 
 
 
 
c80bb75
444fc48
 
 
 
 
 
49ec9dc
 
9d6ae27
3241add
 
49ec9dc
ded0e5f
49ec9dc
444fc48
49ec9dc
 
 
 
 
 
 
 
 
 
 
 
 
7b7fd88
2edcd19
 
49ec9dc
 
c80bb75
49ec9dc
 
c80bb75
6659834
 
444fc48
c80bb75
b6dfa24
 
 
 
444fc48
6659834
b6dfa24
49ec9dc
 
6659834
49ec9dc
6659834
49ec9dc
 
 
7b7fd88
49ec9dc
6659834
b6dfa24
 
6659834
b6dfa24
3241add
b6dfa24
3241add
 
 
 
 
 
6659834
 
49ec9dc
c80bb75
 
 
 
49ec9dc
 
 
3241add
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
115
116
117
118
119
120
121
122
# 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

# ── ν™˜κ²½ λ³€μˆ˜ ────────────────────────────────────────────────
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            # ꡬ쑰 μœ μ§€ (Replicate λ―Έμ‚¬μš©)

# ── Gradio μ„œλ²„ ─────────────────────────────────────────────
GRADIO_URL  = "http://211.233.58.201:7971"
GRADIO_API  = "/process_and_save_image"
DUMMY_IMG   = "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png"

# ── λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ (CPU) ───────────────────────────────────
translator = transformers_pipeline(
    "translation",
    model="Helsinki-NLP/opus-mt-ko-en",
    device=-1,
    **({"token": HF_TOKEN} if HF_TOKEN else {})
)

async def ko2en_async(text: str) -> str:
    """ν•œκΈ€ 포함 μ‹œ 별도 μ“°λ ˆλ“œμ—μ„œ μ˜μ–΄ λ²ˆμ—­."""
    if not re.search(r"[κ°€-힣]", text):
        return text
    loop = asyncio.get_running_loop()
    try:
        return await loop.run_in_executor(
            None,
            lambda: translator(text, max_length=256, num_beams=1)[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()])

# ── Discord μΈν…νŠΈ ──────────────────────────────────────────
intents = discord.Intents.default()
intents.message_content = True   # Portalμ—μ„œλ„ Message-Content Intent ON

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_raw = message.content.strip()
        if not prompt_raw:
            return

        prompt_en = await ko2en_async(prompt_raw)
        await message.channel.typing()

        # ── Gradio 호좜 ────────────────────────────────────
        def generate_image():
            client = Client(GRADIO_URL)
            return client.predict(
                height=768,
                width=768,
                steps=30,                       # inference_steps β†’ steps
                scales=3.5,                     # guidance β†’ scales
                prompt=prompt_en,
                seed=random.randint(0, 2**32 - 1),
                api_name=GRADIO_API
            )[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 isinstance(img_info, str):      # 경우 1: λ¬Έμžμ—΄ 경둜/URL
                data = requests.get(img_info).content if img_info.startswith("http") else open(img_info, "rb").read()
                files.append(discord.File(io.BytesIO(data), filename="generated.webp"))
            elif isinstance(img_info, dict):   # 경우 2: dict(path|url)
                if img_info.get("path"):
                    data = open(img_info["path"], "rb").read()
                elif img_info.get("url"):
                    data = requests.get(img_info["url"]).content
                else:
                    data = None
                if data:
                    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)  # ꡬ쑰 μœ μ§€(μ‚¬μš© μ•ˆ 함)
    ImageBot(intents=intents).run(TOKEN)