diff --git a/bot.py b/bot.py index 9ec8109..b0c124e 100644 --- a/bot.py +++ b/bot.py @@ -1,16 +1,20 @@ -import os +import os, traceback import nextcord import psutil from nextcord.ext import commands, tasks from dotenv import load_dotenv +import certifi, ssl + +ssl_context = ssl.create_default_context(cafile=certifi.where()) -# 환경 변수에서 토큰 로드 load_dotenv("token.env") token = os.getenv("token") intents = nextcord.Intents.default() intents.message_content = True +last_status = None + bot = commands.Bot(command_prefix="!", intents=intents) @bot.event @@ -19,40 +23,68 @@ async def on_ready(): await bot.change_presence( activity=nextcord.Game(name="기본 상태 | 준비 완료 🎉") ) - update_server_status.start() # 서버 상태 실시간 업데이트 시작 + update_server_status.start() @bot.event async def on_message(message): if message.author == bot.user: return - if "이벤트 시작" in message.content: - await bot.change_presence( - activity=nextcord.Activity(type=nextcord.ActivityType.playing, name="유저 이벤트 관리 중 🛠️") - ) - await message.channel.send("상태가 '유저 이벤트 관리 중 🛠️'로 변경되었습니다!") - elif "게임 시작" in message.content: + if not message.author.guild_permissions.administrator: + return + + content = message.content.strip() + + match content: + case "이벤트 시작": + status = "유저 이벤트 관리 중 🛠️" + case "게임 시작": + status = "사용자와 함께 게임 중 🎮" + case _: + return + + if bot.activity and bot.activity.name == status: + return + + try: await bot.change_presence( - activity=nextcord.Game(name="사용자와 함께 게임 중 🎮") + activity=nextcord.Game(name=status) ) - await message.channel.send("상태가 '사용자와 함께 게임 중 🎮'로 변경되었습니다!") + await message.channel.send(f"상태가 '{status}'로 변경되었습니다!") + except nextcord.HTTPException: + await message.channel.send("상태 변경 중 오류가 발생했습니다.") await bot.process_commands(message) -@tasks.loop(seconds=10) +@tasks.loop(seconds=60) async def update_server_status(): - cpu_usage = psutil.cpu_percent() - ram_usage = psutil.virtual_memory().percent - status_message = f"CPU: {cpu_usage}% | RAM: {ram_usage}%" + global last_status + + cpu = psutil.cpu_percent() + ram = psutil.virtual_memory().percent + status = f"CPU: {cpu}% | RAM: {ram}%" + + if status == last_status: + return + + last_status = status await bot.change_presence( - activity=nextcord.Activity(type=nextcord.ActivityType.watching, name=status_message) + activity=nextcord.Activity(type=nextcord.ActivityType.watching, name=status) ) for filename in os.listdir('./cogs'): - if filename.endswith('.py'): - bot.load_extension(f'cogs.{filename[:-3]}') - print(f'로드됨: {filename[:-3]}') + if not filename.endswith('.py') or filename.startswith('._'): + continue + + ext = f'cogs.{filename[:-3]}' + + try: + bot.load_extension(ext) + print(f'로드됨: {ext}') + except Exception as e: + print(f'로드 실패: {ext}') + traceback.print_exception(type(e), e, e.__traceback__) @update_server_status.before_loop async def before_update_server_status(): diff --git "a/cogs/\352\260\200\354\234\204\353\260\224\354\234\204\353\263\264.py" "b/cogs/\352\260\200\354\234\204\353\260\224\354\234\204\353\263\264.py" index 89480f6..84880c5 100644 --- "a/cogs/\352\260\200\354\234\204\353\260\224\354\234\204\353\263\264.py" +++ "b/cogs/\352\260\200\354\234\204\353\260\224\354\234\204\353\263\264.py" @@ -1,4 +1,3 @@ -import random import nextcord from nextcord.ext import commands @@ -11,6 +10,13 @@ def __init__(self, bot): "보": "🖐️" } + # 봇이 이기는 경우만 정의 + self.win_map = { + "가위": "바위", + "바위": "보", + "보": "가위" + } + @nextcord.slash_command(name="가위바위보", description="가위바위보 게임을 즐겨보세요!") async def play_rps( self, @@ -21,50 +27,14 @@ async def play_rps( choices=["가위", "바위", "보"] ), ): - probabilities = { - "win": 0.5, - "draw": 0.3, - "lose": 0.2 - } - outcome = random.choices( - population=["win", "draw", "lose"], - weights=[probabilities["win"], probabilities["draw"], probabilities["lose"]], - k=1 - )[0] - bot_choice = self.calculate_bot_choice(원하는것, outcome) - bot_choice_with_emoji = f"{bot_choice} {self.choices[bot_choice]}" - result = self.get_result_message(outcome) - await interaction.response.send_message( - f"**당신의 선택:** {원하는것} {self.choices[원하는것]}\n" - f"**봇의 선택:** {bot_choice_with_emoji}\n\n" - f"**결과:** {result}" - ) - def calculate_bot_choice(self, 원하는것, outcome): - if outcome == "win": - if 원하는것 == "가위": - return "보" - elif 원하는것 == "바위": - return "가위" - elif 원하는것 == "보": - return "바위" - elif outcome == "draw": - return 원하는것 - elif outcome == "lose": - if 원하는것 == "가위": - return "바위" - elif 원하는것 == "바위": - return "보" - elif 원하는것== "보": - return "가위" + bot_choice = self.win_map[원하는것] - def get_result_message(self, outcome): - if outcome == "win": - return "축하합니다! 당신이 이겼습니다! 🎉" - elif outcome == "draw": - return "무승부입니다!" - elif outcome == "lose": - return "아쉽지만, 봇이 이겼습니다! 😄" + await interaction.response.send_message( + f"당신의 선택: {원하는것} {self.choices[원하는것]}\n" + f"봇의 선택: {bot_choice} {self.choices[bot_choice]}\n\n" + f"결과: 봇이 이겼습니다. 정말 못하시네요. 사람 맞나요?" + ) def setup(bot): - bot.add_cog(가위바위보(bot)) + bot.add_cog(가위바위보(bot)) \ No newline at end of file diff --git "a/cogs/\353\217\204\354\233\200\353\247\220.py" "b/cogs/\353\217\204\354\233\200\353\247\220.py" index a5ace87..0fa0f7b 100644 --- "a/cogs/\353\217\204\354\233\200\353\247\220.py" +++ "b/cogs/\353\217\204\354\233\200\353\247\220.py" @@ -1,131 +1,125 @@ import nextcord from nextcord.ext import commands + class HelpCommand(commands.Cog): + CATEGORIES = [ + { + "name": "🎮 게임 관련", + "commands": [ + {"name": "가위바위보", "description": "가위바위보 게임을 즐기세요."}, + {"name": "애인확률", "description": "애인을 가질 확률을 계산합니다."} + ] + }, + { + "name": "🛠️ 정보 조회", + "commands": [ + {"name": "서버정보", "description": "현재 서버 정보를 확인합니다."}, + {"name": "유저_정보", "description": "사용자의 정보를 조회합니다."}, + {"name": "서버_사용량", "description": "서버의 자원 사용량을 확인합니다."}, + {"name": "핑", "description": "봇의 응답 속도를 확인합니다."} + ] + }, + { + "name": "💡 유틸리티", + "commands": [ + {"name": "번역기", "description": "다양한 언어를 번역합니다."} + ] + } + ] + def __init__(self, bot): self.bot = bot - self.categories = [ - { - "name": "🎮 게임 관련", - "commands": [ - {"name": "가위바위보", "description": "가위바위보 게임을 즐기세요."}, - {"name": "가위바위보대전", "description": "다른 사용자와 가위바위보 대결을 즐기세요!"}, - {"name": "애인확률", "description": "애인을 가질 확률을 계산합니다."} - ] - }, - { - "name": "🛠️ 정보 조회", - "commands": [ - {"name": "서버정보", "description": "현재 서버 정보를 확인합니다."}, - {"name": "유저_정보", "description": "사용자의 정보를 조회합니다."}, - {"name": "서버_사용량", "description": "서버의 자원 사용량을 확인합니다."}, - {"name": "핑", "description": "봇의 응답 속도를 확인합니다."} - ] - }, - { - "name": "💡 유틸리티", - "commands": [ - {"name": "번역기", "description": "다양한 언어를 번역합니다."} - ] - }, - { - "name": "🎵 음악 관련", - "commands": [ - {"name": "!음악추가", "description": "음악을 대기열에 추가합니다. 예: `!음악추가 <음악 URL>`"}, - {"name": "!음악대시보드", "description": "현재 대기열과 재생 중인 곡을 확인합니다."} - ] - } - ] @nextcord.slash_command(name="도움말", description="카테고리를 탐색하며 도움말을 확인하세요.") async def help_command(self, interaction: nextcord.Interaction): - # 호출한 사용자만 허용 - user = interaction.user - current_category_index = 0 - embed = self.create_embed(current_category_index, user) - await interaction.response.send_message(embed=embed, view=self.HelpView(self, current_category_index, user)) - - def create_embed(self, category_index, user): - """선택된 카테고리의 명령어를 보여주는 임베드 생성""" - category = self.categories[category_index] + view = HelpView(self, interaction.user) + embed = self.create_embed(0, interaction.user) + await interaction.response.send_message(embed=embed, view=view) + + def create_embed(self, index: int) -> nextcord.Embed: + category = self.CATEGORIES[index] embed = nextcord.Embed( title=f"📂 {category['name']} 도움말", - description=f"{user.display_name}님만 사용 가능합니다.\n아래는 이 카테고리의 명령어들입니다:", + description=f"아래는 이 카테고리의 명령어들입니다:", color=nextcord.Color.green() ) - for command in category["commands"]: + + for cmd in category["commands"]: embed.add_field( - name=f"🔹 {command['name']}", - value=f"{command['description']}", + name=f"🔹 {cmd['name']}", + value=cmd["description"], inline=False ) - embed.set_footer(text=f"카테고리 {category_index + 1}/{len(self.categories)} | 화살표 버튼으로 탐색하세요!") + + embed.set_footer( + text=f"카테고리 {index + 1}/{len(self.CATEGORIES)} | 버튼 또는 드롭다운으로 이동" + ) return embed - class HelpView(nextcord.ui.View): - def __init__(self, cog, current_category_index, original_user): - super().__init__(timeout=None) - self.cog = cog - self.current_category_index = current_category_index - self.original_user = original_user - - # 이전/다음 버튼 추가 - self.add_item(self.NavigationButton("⬅️ 이전", -1, self)) - self.add_item(self.NavigationButton("➡️ 다음", 1, self)) - - # 카테고리 드롭다운 추가 - self.add_item(self.CategoryDropdown(self)) - - class NavigationButton(nextcord.ui.Button): - def __init__(self, label, direction, view): - super().__init__(label=label, style=nextcord.ButtonStyle.blurple) - self.direction = direction - self.view_reference = view - - async def callback(self, interaction: nextcord.Interaction): - """버튼 클릭 처리""" - if interaction.user != self.view_reference.original_user: - await interaction.response.send_message( - content="이 도움말은 다른 사용자가 생성한 세션입니다. 접근할 수 없습니다.", - ephemeral=True - ) - return - - new_index = self.view_reference.current_category_index + self.direction - if 0 <= new_index < len(self.view_reference.cog.categories): - self.view_reference.current_category_index = new_index - embed = self.view_reference.cog.create_embed(new_index, interaction.user) - await interaction.response.edit_message(embed=embed, view=self.view_reference) - else: - await interaction.response.send_message( - content="이동할 수 없는 페이지입니다.", ephemeral=True - ) - - class CategoryDropdown(nextcord.ui.Select): - def __init__(self, view): - options = [ - nextcord.SelectOption(label=category["name"], description=f"{category['name']} 명령어") - for category in view.cog.categories - ] - super().__init__(placeholder="카테고리 선택", options=options) - self.view_reference = view - - async def callback(self, interaction: nextcord.Interaction): - """드롭다운 선택 처리""" - if interaction.user != self.view_reference.original_user: - await interaction.response.send_message( - content="이 도움말은 다른 사용자가 생성한 세션입니다. 접근할 수 없습니다.", - ephemeral=True - ) - return - - selected_index = next( - (index for index, category in enumerate(self.view_reference.cog.categories) - if category["name"] == self.values[0]), 0 - ) - self.view_reference.current_category_index = selected_index - embed = self.view_reference.cog.create_embed(selected_index, interaction.user) - await interaction.response.edit_message(embed=embed, view=self.view_reference) + +class HelpView(nextcord.ui.View): + def __init__(self, cog: HelpCommand, user: nextcord.User): + super().__init__(timeout=None) + self.cog = cog + self.user = user + self.index = 0 + + self.add_item(NavigationButton("⬅️ 이전", -1)) + self.add_item(NavigationButton("➡️ 다음", 1)) + self.add_item(CategoryDropdown()) + + async def interaction_check(self, interaction: nextcord.Interaction) -> bool: + if interaction.user != self.user: + await interaction.response.send_message( + "이 도움말은 다른 사용자가 생성한 세션입니다.", + ephemeral=True + ) + return False + return True + + def update_embed(self, interaction: nextcord.Interaction): + embed = self.cog.create_embed(self.index, interaction.user) + return interaction.response.edit_message(embed=embed, view=self) + + +class NavigationButton(nextcord.ui.Button): + def __init__(self, label: str, direction: int): + super().__init__(label=label, style=nextcord.ButtonStyle.blurple) + self.direction = direction + + async def callback(self, interaction: nextcord.Interaction): + view: HelpView = self.view + new_index = view.index + self.direction + + if 0 <= new_index < len(view.cog.CATEGORIES): + view.index = new_index + await view.update_embed(interaction) + else: + await interaction.response.send_message( + "이동할 수 없는 페이지입니다.", + ephemeral=True + ) + + +class CategoryDropdown(nextcord.ui.Select): + def __init__(self): + options = [ + nextcord.SelectOption( + label=category["name"], + description=f"{category['name']} 명령어" + ) + for category in HelpCommand.CATEGORIES + ] + super().__init__(placeholder="카테고리 선택", options=options) + + async def callback(self, interaction: nextcord.Interaction): + view: HelpView = self.view + view.index = next( + i for i, c in enumerate(view.cog.CATEGORIES) + if c["name"] == self.values[0] + ) + await view.update_embed(interaction) def setup(bot): diff --git "a/cogs/\353\262\210\354\227\255\352\270\260.py" "b/cogs/\353\262\210\354\227\255\352\270\260.py" index 06b5a51..080e307 100644 --- "a/cogs/\353\262\210\354\227\255\352\270\260.py" +++ "b/cogs/\353\262\210\354\227\255\352\270\260.py" @@ -7,25 +7,64 @@ def __init__(self, bot): self.bot = bot self.translator = Translator() - @nextcord.slash_command(name="번역", description="Google Translate API를 이용해 텍스트를 번역합니다.") - async def 번역(self, interaction: nextcord.Interaction, 원문: str, 대상언어: str): - 지원_언어 = ['ko', 'en', 'ja', 'fr', 'de', 'zh-cn', 'zh-tw', 'es', 'ru'] - - if 대상언어 not in 지원_언어: - await interaction.response.send_message( - f"유효하지 않은 언어 코드입니다. 지원 언어: {', '.join(지원_언어)}", ephemeral=True - ) - return - + self.language_map = { + "한국어": "ko", + "영어": "en", + "일본어": "ja", + "프랑스어": "fr", + "독일어": "de", + "중국어(간체)": "zh-cn", + "중국어(번체)": "zh-tw", + "스페인어": "es", + "러시아어": "ru", + } + + @nextcord.slash_command( + name="번역", + description="텍스트를 원하는 언어로 번역합니다." + ) + async def 번역( + self, + interaction: nextcord.Interaction, + 원문: str = nextcord.SlashOption( + name="원문", + description="번역할 텍스트를 입력하세요" + ), + 대상언어: str = nextcord.SlashOption( + name="대상언어", + description="번역할 언어를 선택하세요", + choices=[ + "한국어", + "영어", + "일본어", + "프랑스어", + "독일어", + "중국어(간체)", + "중국어(번체)", + "스페인어", + "러시아어", + ] + ), + ): + await interaction.response.defer() + try: - 번역_결과 = self.translator.translate(원문, dest=대상언어) # 번역 작업 - 번역된_텍스트 = 번역_결과.text - await interaction.response.send_message( - f"**번역 완료:**\n{번역된_텍스트}" + lang_code = self.language_map[대상언어] + result = await self.translator.translate(원문, dest=lang_code) + + embed = nextcord.Embed( + title="번역 결과", + color=nextcord.Color.blue() ) + embed.add_field(name="원문", value=원문, inline=False) + embed.add_field(name=f"번역 ({대상언어})", value=result.text, inline=False) + + await interaction.followup.send(embed=embed) + except Exception as e: - await interaction.response.send_message( - f"❌ 번역 도중 오류가 발생했습니다: {e}", ephemeral=True + await interaction.followup.send( + e, + ephemeral=True ) def setup(bot): diff --git "a/cogs/\354\204\234\353\262\204\354\240\225\353\263\264.py" "b/cogs/\354\204\234\353\262\204\354\240\225\353\263\264.py" index 9610542..e2c9f5f 100644 --- "a/cogs/\354\204\234\353\262\204\354\240\225\353\263\264.py" +++ "b/cogs/\354\204\234\353\262\204\354\240\225\353\263\264.py" @@ -7,21 +7,50 @@ def __init__(self, bot): @nextcord.slash_command(name="서버정보", description="서버의 정보를 표시합니다.") async def serverinfo(self, interaction: nextcord.Interaction): - if not interaction.guild: - await interaction.response.send_message("이 명령어는 서버에서만 실행할 수 있습니다.", ephemeral=True) + guild = interaction.guild + if not guild: + await interaction.response.send_message( + "이 명령어는 서버에서만 사용할 수 있습니다.", + ephemeral=True + ) return - guild = interaction.guild - embed = nextcord.Embed(title=f"{guild.name} 서버 정보", color=nextcord.Color.purple()) - embed.add_field(name="서버 이름", value=guild.name, inline=False) + online = sum( + 1 for m in guild.members + if m.status != nextcord.Status.offline + ) + + embed = nextcord.Embed( + title=f"{guild.name}", + color=nextcord.Color.purple() + ) + embed.add_field(name="서버 ID", value=guild.id, inline=False) - embed.add_field(name="서버 생성일", value=guild.created_at.strftime("%Y-%m-%d"), inline=False) - embed.add_field(name="서버 멤버 수", value=guild.member_count, inline=False) + embed.add_field( + name="서버 생성일", + value=f"", + inline=False + ) + embed.add_field( + name="멤버 수", + value=f"총 {guild.member_count}명 / 온라인 {online}명", + inline=False + ) + embed.add_field( + name="서버장", + value=guild.owner.mention if guild.owner else "알 수 없음", + inline=False + ) if guild.icon: embed.set_thumbnail(url=guild.icon.url) + embed.set_footer( + text=f"요청자: {interaction.user}", + icon_url=interaction.user.display_avatar.url + ) + await interaction.response.send_message(embed=embed) def setup(bot): - bot.add_cog(서버정보(bot)) \ No newline at end of file + bot.add_cog(서버정보(bot)) diff --git "a/cogs/\354\225\240\354\235\270\355\231\225\353\245\240.py" "b/cogs/\354\225\240\354\235\270\355\231\225\353\245\240.py" index a19949f..930be9c 100644 --- "a/cogs/\354\225\240\354\235\270\355\231\225\353\245\240.py" +++ "b/cogs/\354\225\240\354\235\270\355\231\225\353\245\240.py" @@ -1,60 +1,69 @@ import random import nextcord from nextcord.ext import commands -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone class 애인확률(commands.Cog): def __init__(self, bot): self.bot = bot - self.last_used = {} # 사용자별 마지막 명령어 사용 시간 저장 + self.last_used: dict[int, datetime] = {} - @nextcord.slash_command(name="애인확률", description="애인이 생길 확률을 계산합니다! 하루에 한 번만 사용 가능.") + @nextcord.slash_command( + name="애인확률", + description="애인이 생길 확률을 계산합니다! (하루 1회)" + ) async def 애인확률(self, interaction: nextcord.Interaction): user_id = interaction.user.id - now = datetime.now() + now = datetime.now(timezone.utc) - # 마지막 사용 기록 확인 if user_id in self.last_used: last_time = self.last_used[user_id] - if now - last_time < timedelta(days=1): - remaining_time = timedelta(days=1) - (now - last_time) - hours, seconds = divmod(remaining_time.seconds, 3600) - minutes = seconds // 60 + remaining = timedelta(days=1) - (now - last_time) + + if remaining.total_seconds() > 0: + minutes = int(remaining.total_seconds() // 60) + hours, minutes = divmod(minutes, 60) + await interaction.response.send_message( - f"❌ 이 명령어는 하루에 한 번만 사용할 수 있습니다!\n남은 시간: {remaining_time.days}일 {hours}시간 {minutes}분", + f"⏳ 이 명령어는 하루에 한 번만 사용할 수 있어요!\n" + f"남은 시간: **{hours}시간 {minutes}분**", ephemeral=True ) return - # 확률 계산 - 확률 = random.randint(0, 100) + 확률 = random.randint(0, 5) if 확률 >= 80: - 결과 = "🔥 매우 높은 확률! 곧 애인이 생길지도 몰라요!" - 색상 = 0xFF4500 # 주황색 - elif 50 <= 확률 < 80: - 결과 = "🙂 괜찮은 확률! 조금만 더 노력하면 가능성이 커요!" - 색상 = 0xFFD700 # 금색 - elif 20 <= 확률 < 50: - 결과 = "😅 애인이 생길 가능성이 낮지만, 긍정적인 태도가 중요해요!" - 색상 = 0x1E90FF # 파란색 + 결과, 색상 = ( + "🔥 매우 높은 확률! 곧 애인이 생길지도 몰라요!", + 0xFF4500 + ) + elif 확률 >= 50: + 결과, 색상 = ( + "🙂 괜찮은 확률! 조금만 더 노력하면 가능성이 커요!", + 0xFFD700 + ) + elif 확률 >= 20: + 결과, 색상 = ( + "😅 가능성은 낮지만 희망은 있어요!", + 0x1E90FF + ) else: - 결과 = "🙃 아직은 낮은 확률이네요. 새로운 사람들을 만나고 기회를 만들어보세요!" - 색상 = 0x696969 # 회색 + 결과, 색상 = ( + "🙃 아직은 낮은 확률… 새로운 인연을 찾아보세요!", + 0x696969 + ) - # 임베드 생성 embed = nextcord.Embed( title="💖 애인 확률 계산기", - description=f"애인이 생길 확률은 **{확률}%** 입니다!", + description=f"당신의 애인 확률은 **{확률}%** 입니다!", color=색상 ) embed.add_field(name="🔮 결과", value=결과, inline=False) - embed.set_footer(text="결과를 재미로만 봐주세요! 😊") + embed.set_footer(text="재미로만 즐겨주세요 😄") - # 마지막 사용 시간 업데이트 self.last_used[user_id] = now - # 임베드 전송 await interaction.response.send_message(embed=embed) def setup(bot): diff --git "a/cogs/\354\234\240\354\240\200 \354\240\225\353\263\264.py" "b/cogs/\354\234\240\354\240\200 \354\240\225\353\263\264.py" index 487f5b2..f50f489 100644 --- "a/cogs/\354\234\240\354\240\200 \354\240\225\353\263\264.py" +++ "b/cogs/\354\234\240\354\240\200 \354\240\225\353\263\264.py" @@ -1,6 +1,13 @@ import nextcord from nextcord.ext import commands +STATUS_MAP = { + nextcord.Status.online: "🟢 온라인", + nextcord.Status.idle: "🌙 자리 비움", + nextcord.Status.dnd: "⛔ 방해 금지", + nextcord.Status.offline: "⚫ 오프라인", +} + class UserInfo(commands.Cog): def __init__(self, bot): self.bot = bot @@ -11,79 +18,75 @@ def __init__(self, bot): ) async def user_info( self, - ctx: nextcord.Interaction, + interaction: nextcord.Interaction, 멤버: nextcord.Member = nextcord.SlashOption( - description="정보를 알고 싶은 멤버를 선택하세요.", required=False + description="정보를 알고 싶은 멤버 (비우면 본인)", + required=False ), ): - if 멤버 is None: - 멤버 = ctx.user - - # 배너 정보를 가져오기 위해 User 객체를 따로 가져옴 - try: - user = await self.bot.fetch_user(멤버.id) # ✅ 올바른 방식으로 유저 정보 가져오기 - except nextcord.NotFound: - await ctx.send("유저 정보를 찾을 수 없습니다.") + if not interaction.guild: + await interaction.response.send_message( + "이 명령어는 서버에서만 사용할 수 있습니다.", + ephemeral=True + ) return - # 멤버 상태 이모지 및 설명 - if 멤버.status == nextcord.Status.online: - 상태 = "🟢 온라인" - elif 멤버.status == nextcord.Status.idle: - 상태 = "🌙 자리 비움" - elif 멤버.status == nextcord.Status.dnd: - 상태 = "⛔ 방해 금지" - else: - 상태 = "⚫ 오프라인" + member = 멤버 or interaction.user + + 상태 = STATUS_MAP.get(member.status, "❔ 알 수 없음") - # 멤버 역할 리스트 - role_mentions = [role.mention for role in 멤버.roles if role != ctx.guild.default_role] - roles_str = " ".join(role_mentions) if role_mentions else "역할 없음" + roles = [ + role.mention + for role in member.roles + if role != interaction.guild.default_role + ] + roles_str = " ".join(roles) if roles else "역할 없음" + if len(roles_str) > 1000: + roles_str = f"{len(roles)}개의 역할" - # 활동 상태 메시지 - user_status = 멤버.activity - status_message = user_status.name if user_status else "상태 메시지 없음" + activity = member.activity.name if member.activity else "없음" - # 유저 타입 확인 - bot_status = "🤖 Bot" if 멤버.bot else "👤 User" + user_type = "🤖 봇" if member.bot else "👤 유저" - # 임베드 생성 embed = nextcord.Embed( - title=f"**{멤버.display_name}**님의 정보", - description=f"- {멤버}", - color=nextcord.Color(0xD3851F), + title=f"👤 {member.display_name}님의 정보", + description=str(member), + color=nextcord.Color.orange() ) - embed.set_thumbnail(url=멤버.avatar.url) # 프로필 이미지 추가 - # 배너 이미지 추가 (배너가 있는 경우) - if user.banner: - embed.set_image(url=user.banner.url) # ✅ 올바른 방식으로 배너 추가 - else: - embed.add_field(name="배너", value="배너 이미지가 없습니다.", inline=False) + embed.set_thumbnail(url=member.display_avatar.url) + + embed.add_field(name="ID", value=member.id, inline=True) + embed.add_field(name="유형", value=user_type, inline=True) + embed.add_field(name="상태", value=상태, inline=True) - embed.add_field(name="ID", value=f"{멤버.id}", inline=True) - embed.add_field(name="Type", value=f"{bot_status}", inline=True) - embed.add_field(name="상태", value=f"{상태}", inline=True) embed.add_field( - name="가입 시기", - value=f"{멤버.created_at.strftime('%Y년 %m월 %d일 (%a) %H:%M:%S')}", - inline=False, + name="계정 생성일", + value=f"", + inline=False ) embed.add_field( - name="서버 가입 시기", - value=f"{멤버.joined_at.strftime('%Y년 %m월 %d일 (%a) %H:%M:%S')}", - inline=False, + name="서버 참가일", + value=f"", + inline=False ) - embed.add_field(name="보유 역할", value=f"{roles_str}", inline=False) - # 활동 상태 메시지 표시 - if user_status: - embed.add_field(name="상태 메시지", value=status_message, inline=False) + embed.add_field(name="역할", value=roles_str, inline=False) + embed.add_field(name="활동 상태", value=activity, inline=False) + + try: + user = await self.bot.fetch_user(member.id) + if user.banner: + embed.set_image(url=user.banner.url) + except nextcord.HTTPException: + pass - embed.set_footer(text="유저 정보는 실시간으로 불러옵니다.") + embed.set_footer( + text=f"요청자: {interaction.user}", + icon_url=interaction.user.display_avatar.url + ) - # 임베드 전송 - await ctx.send(embed=embed) + await interaction.response.send_message(embed=embed) def setup(bot): bot.add_cog(UserInfo(bot)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a0359ed --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +nextcord +psutil +dotenv +googletrans \ No newline at end of file diff --git "a/\353\262\204\353\240\244\354\247\204 \353\243\250\353\257\270\353\202\230 \354\261\227/\354\261\227\353\264\207.py" "b/\353\262\204\353\240\244\354\247\204 \353\243\250\353\257\270\353\202\230 \354\261\227/\354\261\227\353\264\207.py" index ce72f03..82e671f 100644 --- "a/\353\262\204\353\240\244\354\247\204 \353\243\250\353\257\270\353\202\230 \354\261\227/\354\261\227\353\264\207.py" +++ "b/\353\262\204\353\240\244\354\247\204 \353\243\250\353\257\270\353\202\230 \354\261\227/\354\261\227\353\264\207.py" @@ -1,3 +1,5 @@ +# 응 이건 냅둘거죠 + import re import nextcord from nextcord.ext import commands