|
import discord |
|
from discord.ext import commands |
|
import gradio as gr |
|
import os |
|
import random |
|
import typing |
|
import enum |
|
import json |
|
from re import A |
|
from discord import app_commands |
|
|
|
|
|
intents = discord.Intents.default() |
|
intents.message_content = True |
|
intents.dm_messages = True |
|
|
|
bot = commands.Bot(command_prefix='/', intents=intents) |
|
|
|
TARGET_CHANNEL_ID = 1244200163682029569 |
|
ALLOWED_USER_ID = 676049087300239369 |
|
MENTION_USER_ID = 676049087300239369 |
|
CHANNEL_ID = 1206322474158133318 |
|
MESSAGE_ID = 1249008553025605775 |
|
|
|
|
|
TRIPLES_FIRST_IMAGE_FOLDER_PATH = "shop/tripleS/first" |
|
TRIPLES_DOUBLE_IMAGE_FOLDER_PATH = "shop/tripleS/double" |
|
ARTMS_FIRST_IMAGE_FOLDER_PATH = "shop/ARTMS/first" |
|
ARTMS_DOUBLE_IMAGE_FOLDER_PATH = "shop/ARTMS/double" |
|
|
|
|
|
TRIPLES_WELCOME_FOLDER_PATH = 'follow/tripleS' |
|
ARTMS_WELCOME_FOLDER_PATH = 'follow/ARTMS' |
|
|
|
|
|
user_image_mapping = {} |
|
|
|
|
|
USER_DATA_FILE = 'user_image_mapping.json' |
|
|
|
|
|
USER_IMAGE_MAPPING_PATH = "user_image_mapping.json" |
|
|
|
|
|
def load_user_image_mapping(): |
|
if os.path.exists(USER_IMAGE_MAPPING_PATH): |
|
with open(USER_IMAGE_MAPPING_PATH, "r") as f: |
|
return json.load(f) |
|
return {} |
|
|
|
|
|
def save_user_image_mapping(mapping): |
|
with open(USER_IMAGE_MAPPING_PATH, "w") as f: |
|
json.dump(mapping, f, indent=4) |
|
|
|
user_image_mapping = load_user_image_mapping() |
|
|
|
|
|
bot_status = "Initializing..." |
|
|
|
@bot.event |
|
async def on_ready(): |
|
global bot_status |
|
bot_status = f"Logged in as {bot.user}" |
|
print(bot_status) |
|
try: |
|
synced = await bot.tree.sync() |
|
print(f"Synced {len(synced)} command(s)") |
|
except Exception as e: |
|
print(f"Failed to sync commands: {e}") |
|
|
|
@bot.event |
|
async def on_message(message): |
|
if isinstance(message.channel, discord.DMChannel) and message.author != bot.user: |
|
target_channel = bot.get_channel(TARGET_CHANNEL_ID) |
|
if target_channel is None: |
|
print("지정된 채널을 찾을 수 없습니다.") |
|
return |
|
|
|
if message.author.id != ALLOWED_USER_ID: |
|
try: |
|
await message.author.send("이 메시지를 보낼 권한이 없습니다.") |
|
except discord.Forbidden: |
|
print(f"Cannot send DM to {message.author}.") |
|
return |
|
|
|
if message.content or message.attachments: |
|
files = [await attachment.to_file() for attachment in message.attachments if attachment.filename.lower().endswith(('png', 'jpg', 'jpeg', 'gif', 'bmp'))] |
|
await target_channel.send(content=f"{message.content}", files=files) |
|
|
|
async def class_autocompletion( |
|
interaction: discord.Interaction, |
|
current: str |
|
) -> typing.List[app_commands.Choice[str]]: |
|
"""Class 자동 완성을 위한 함수""" |
|
classes = ['first', 'double'] |
|
return [ |
|
app_commands.Choice(name=cls, value=cls) |
|
for cls in classes if current.lower() in cls.lower() |
|
] |
|
|
|
async def artist_autocompletion( |
|
interaction: discord.Interaction, |
|
current: str |
|
) -> typing.List[app_commands.Choice[str]]: |
|
"""Artist 자동 완성을 위한 함수""" |
|
artists = ['tripleS', 'ARTMS'] |
|
return [ |
|
app_commands.Choice(name=art, value=art) |
|
for art in artists if current.lower() in art.lower() |
|
] |
|
|
|
@bot.tree.command(name="mention") |
|
async def mention(interaction: discord.Interaction): |
|
"""봇 주인장을 언급할 수 있습니다.""" |
|
user = await bot.fetch_user(MENTION_USER_ID) |
|
await interaction.response.send_message(f"{user.mention}", ephemeral=False) |
|
|
|
@bot.tree.command(name="oddcosmo") |
|
async def oddcosmo(interaction: discord.Interaction): |
|
"""ODDCOSMO로 향하는 포탈을 엽니다.""" |
|
link = "https://oddpaint.wav.haus/" |
|
await interaction.response.send_message(f"{link}", ephemeral=False) |
|
|
|
@bot.tree.command(name="update") |
|
async def update_message(interaction: discord.Interaction): |
|
"""Chanbot의 업데이트 내역을 볼 수 있습니다. 아마도.""" |
|
try: |
|
|
|
channel = bot.get_channel(CHANNEL_ID) |
|
if channel is None: |
|
raise ValueError("지정된 채널을 찾을 수 없습니다.") |
|
|
|
|
|
message = await channel.fetch_message(MESSAGE_ID) |
|
|
|
|
|
await interaction.response.send_message(f"{message.content}") |
|
except ValueError as ve: |
|
await interaction.response.send_message(str(ve)) |
|
except discord.NotFound: |
|
await interaction.response.send_message("해당 메시지를 찾을 수 없습니다.") |
|
except Exception as e: |
|
await interaction.response.send_message(f"메시지를 가져오는 도중 오류가 발생했습니다: {e}") |
|
|
|
@bot.tree.command(name="shop") |
|
@app_commands.autocomplete(class_=class_autocompletion, artist=artist_autocompletion) |
|
async def shop_tree(interaction: discord.Interaction, |
|
artist: str, |
|
class_: str): |
|
"""오브젝트를 구매해볼 수 있습니다. (KRW 0)""" |
|
if artist.lower() == "triples": |
|
if class_.lower() == "first": |
|
folder_path = TRIPLES_FIRST_IMAGE_FOLDER_PATH |
|
text = "# Cosmo로 불러왔어요!" |
|
elif class_.lower() == "double": |
|
folder_path = TRIPLES_DOUBLE_IMAGE_FOLDER_PATH |
|
text = "# Cosmo로 불러왔어요!" |
|
else: |
|
await interaction.response.send_message("올바른 Class를 선택하세요.", ephemeral=False) |
|
return |
|
elif artist.lower() == "artms": |
|
if class_.lower() == "first": |
|
folder_path = ARTMS_FIRST_IMAGE_FOLDER_PATH |
|
text = "# Cosmo로 불러왔어요!" |
|
elif class_.lower() == "double": |
|
folder_path = ARTMS_DOUBLE_IMAGE_FOLDER_PATH |
|
text = "# Cosmo로 불러왔어요!" |
|
else: |
|
await interaction.response.send_message("올바른 Class를 선택하세요.", ephemeral=False) |
|
return |
|
else: |
|
await interaction.response.send_message("올바른 Artist를 선택하세요.", ephemeral=False) |
|
return |
|
|
|
if not os.path.exists(folder_path) or not os.listdir(folder_path): |
|
await interaction.response.send_message("Objekt가 준비되지 않았습니다.", ephemeral=False) |
|
return |
|
|
|
random_image = random.choice(os.listdir(folder_path)) |
|
with open(os.path.join(folder_path, random_image), "rb") as f: |
|
image_data = discord.File(f) |
|
await interaction.response.send_message(content=text, file=image_data) |
|
|
|
@bot.tree.command(name="follow") |
|
@app_commands.autocomplete(artist=artist_autocompletion) |
|
async def follow(interaction: discord.Interaction, artist: str): |
|
"""Artist의 이미지를 받아보세요.""" |
|
global user_image_mapping |
|
|
|
user_id = str(interaction.user.id) |
|
artist_key = artist.lower() |
|
|
|
|
|
if user_id not in user_image_mapping: |
|
user_image_mapping[user_id] = {} |
|
|
|
|
|
print(f"Current mapping for user {user_id}: {user_image_mapping[user_id]}") |
|
|
|
try: |
|
|
|
if artist_key in user_image_mapping[user_id]: |
|
image_path = user_image_mapping[user_id][artist_key] |
|
text = "다시 찾아주셔서 감사합니다!" |
|
else: |
|
|
|
if artist_key == "triples": |
|
folder_path = "follow/tripleS" |
|
elif artist_key == "artms": |
|
folder_path = "follow/ARTMS" |
|
else: |
|
await interaction.response.send_message("올바른 Artist를 선택하세요.", ephemeral=True) |
|
return |
|
|
|
if not os.path.exists(folder_path) or not os.listdir(folder_path): |
|
await interaction.response.send_message("이미지가 준비되지 않았습니다.", ephemeral=True) |
|
return |
|
|
|
image_path = os.path.join(folder_path, random.choice(os.listdir(folder_path))) |
|
user_image_mapping[user_id][artist_key] = image_path |
|
save_user_image_mapping(user_image_mapping) |
|
text = "환영합니다! 이 이미지를 받아보세요." |
|
|
|
|
|
with open(image_path, "rb") as f: |
|
image_data = discord.File(f) |
|
await interaction.response.send_message(content=text, file=image_data) |
|
|
|
except Exception as e: |
|
print(f"An error occurred: {e}") |
|
await interaction.response.send_message("오류가 발생했습니다. 다시 시도해 주세요.", ephemeral=True) |
|
|
|
@bot.tree.command(name="mapping") |
|
@app_commands.autocomplete(artist=artist_autocompletion) |
|
async def mapping(interaction: discord.Interaction, artist: str): |
|
"""사용자 이미지 매핑 데이터를 확인하세요.""" |
|
global user_image_mapping |
|
|
|
if interaction.user.id != ALLOWED_USER_ID: |
|
await interaction.response.send_message("이 명령어를 사용할 권한이 없습니다.", ephemeral=True) |
|
return |
|
|
|
artist_key = artist.lower() |
|
response_text = "" |
|
|
|
for user_id, artist_data in user_image_mapping.items(): |
|
if artist_key in artist_data: |
|
image_path = artist_data[artist_key] |
|
response_text += f"User ID: {user_id} -> Image Path: {image_path}\n" |
|
|
|
if not response_text: |
|
response_text = "해당 아티스트에 대한 저장된 이미지가 없습니다." |
|
|
|
await interaction.response.send_message(content=response_text, ephemeral=True) |
|
|
|
@bot.tree.command(name="reset_mapping") |
|
@app_commands.autocomplete(artist=artist_autocompletion) |
|
async def reset_mapping(interaction: discord.Interaction, artist: str): |
|
"""특정 아티스트의 이미지 매핑을 초기화합니다.""" |
|
global user_image_mapping |
|
|
|
|
|
if interaction.user.id != ALLOWED_USER_ID: |
|
await interaction.response.send_message("이 명령어를 사용할 권한이 없습니다.", ephemeral=True) |
|
return |
|
|
|
user_id = str(interaction.user.id) |
|
artist_key = artist.lower() |
|
|
|
if user_id in user_image_mapping and artist_key in user_image_mapping[user_id]: |
|
del user_image_mapping[user_id][artist_key] |
|
save_user_image_mapping(user_image_mapping) |
|
text = f"{artist}에 대한 이미지 매핑이 초기화되었습니다." |
|
else: |
|
text = f"{artist}에 대한 저장된 이미지가 없습니다." |
|
|
|
await interaction.response.send_message(content=text, ephemeral=True) |
|
|
|
|
|
def check_bot_status(): |
|
return bot_status |
|
|
|
|
|
iface = gr.Interface( |
|
fn=check_bot_status, |
|
inputs=[], |
|
outputs="text", |
|
live=False, |
|
title="Discord Bot Status", |
|
description="Click the button to check if the bot is running." |
|
) |
|
|
|
if __name__ == "__main__": |
|
import threading |
|
token = os.environ['token'] |
|
def run_discord_bot(): |
|
bot.run(token) |
|
|
|
discord_thread = threading.Thread(target=run_discord_bot) |
|
discord_thread.start() |
|
|
|
iface.launch() |