diff --git a/discord_utils.py b/discord_utils.py deleted file mode 100644 index 3f9c2d5..0000000 --- a/discord_utils.py +++ /dev/null @@ -1,252 +0,0 @@ -""" -Discord Utilities - -This module contains Discord helper functions for channels, roles, embeds, -and other Discord-specific operations. -""" -import logging -import os -import asyncio -from typing import Optional - -import discord -from discord.ext import commands -from helpers.constants import SBA_COLOR, PD_SEASON, IMAGES - -logger = logging.getLogger('discord_app') - - -async def send_to_bothole(ctx, content, embed): - """Send a message to the pd-bot-hole channel.""" - await discord.utils.get(ctx.guild.text_channels, name='pd-bot-hole') \ - .send(content=content, embed=embed) - - -async def send_to_news(ctx, content, embed): - """Send a message to the pd-news-ticker channel.""" - await discord.utils.get(ctx.guild.text_channels, name='pd-news-ticker') \ - .send(content=content, embed=embed) - - -async def typing_pause(ctx, seconds=1): - """Show typing indicator for specified seconds.""" - async with ctx.typing(): - await asyncio.sleep(seconds) - - -async def pause_then_type(ctx, message): - """Show typing indicator based on message length, then send message.""" - async with ctx.typing(): - await asyncio.sleep(len(message) / 100) - await ctx.send(message) - - -async def check_if_pdhole(ctx): - """Check if the current channel is pd-bot-hole.""" - if ctx.message.channel.name != 'pd-bot-hole': - await ctx.send('Slide on down to my bot-hole for running commands.') - await ctx.message.add_reaction('❌') - return False - return True - - -async def bad_channel(ctx): - """Check if current channel is in the list of bad channels for commands.""" - bad_channels = ['paper-dynasty-chat', 'pd-news-ticker'] - if ctx.message.channel.name in bad_channels: - await ctx.message.add_reaction('❌') - bot_hole = discord.utils.get( - ctx.guild.text_channels, - name=f'pd-bot-hole' - ) - await ctx.send(f'Slide on down to the {bot_hole.mention} ;)') - return True - else: - return False - - -def get_channel(ctx, name) -> Optional[discord.TextChannel]: - """Get a text channel by name.""" - # Handle both Context and Interaction objects - guild = ctx.guild if hasattr(ctx, 'guild') else None - if not guild: - return None - - channel = discord.utils.get( - guild.text_channels, - name=name - ) - if channel: - return channel - return None - - -async def get_emoji(ctx, name, return_empty=True): - """Get an emoji by name, with fallback options.""" - try: - emoji = await commands.converter.EmojiConverter().convert(ctx, name) - except: - if return_empty: - emoji = '' - else: - return name - return emoji - - -async def react_and_reply(ctx, reaction, message): - """Add a reaction to the message and send a reply.""" - await ctx.message.add_reaction(reaction) - await ctx.send(message) - - -async def send_to_channel(bot, channel_name, content=None, embed=None): - """Send a message to a specific channel by name or ID.""" - guild = bot.get_guild(int(os.environ.get('GUILD_ID'))) - if not guild: - logger.error('Cannot send to channel - bot not logged in') - return - - this_channel = discord.utils.get(guild.text_channels, name=channel_name) - - if not this_channel: - this_channel = discord.utils.get(guild.text_channels, id=channel_name) - if not this_channel: - raise NameError(f'**{channel_name}** channel not found') - - return await this_channel.send(content=content, embed=embed) - - -async def get_or_create_role(ctx, role_name, mentionable=True): - """Get an existing role or create it if it doesn't exist.""" - this_role = discord.utils.get(ctx.guild.roles, name=role_name) - - if not this_role: - this_role = await ctx.guild.create_role(name=role_name, mentionable=mentionable) - - return this_role - - -def get_special_embed(special): - """Create an embed for a special item.""" - embed = discord.Embed(title=f'{special.name} - Special #{special.get_id()}', - color=discord.Color.random(), - description=f'{special.short_desc}') - embed.add_field(name='Description', value=f'{special.long_desc}', inline=False) - if special.thumbnail.lower() != 'none': - embed.set_thumbnail(url=f'{special.thumbnail}') - if special.url.lower() != 'none': - embed.set_image(url=f'{special.url}') - - return embed - - -def get_random_embed(title, thumb=None): - """Create a basic embed with random color.""" - embed = discord.Embed(title=title, color=discord.Color.random()) - if thumb: - embed.set_thumbnail(url=thumb) - - return embed - - -def get_team_embed(title, team=None, thumbnail: bool = True): - """Create a team-branded embed.""" - if team: - embed = discord.Embed( - title=title, - color=int(team["color"], 16) if team["color"] else int(SBA_COLOR, 16) - ) - embed.set_footer(text=f'Paper Dynasty Season {team["season"]}', icon_url=IMAGES['logo']) - if thumbnail: - embed.set_thumbnail(url=team["logo"] if team["logo"] else IMAGES['logo']) - else: - embed = discord.Embed( - title=title, - color=int(SBA_COLOR, 16) - ) - embed.set_footer(text=f'Paper Dynasty Season {PD_SEASON}', icon_url=IMAGES['logo']) - if thumbnail: - embed.set_thumbnail(url=IMAGES['logo']) - - return embed - - -async def create_channel_old( - ctx, channel_name: str, category_name: str, everyone_send=False, everyone_read=True, allowed_members=None, - allowed_roles=None): - """Create a text channel with specified permissions (legacy version).""" - this_category = discord.utils.get(ctx.guild.categories, name=category_name) - if not this_category: - raise ValueError(f'I couldn\'t find a category named **{category_name}**') - - overwrites = { - ctx.guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True), - ctx.guild.default_role: discord.PermissionOverwrite(read_messages=everyone_read, send_messages=everyone_send) - } - if allowed_members: - if isinstance(allowed_members, list): - for member in allowed_members: - overwrites[member] = discord.PermissionOverwrite(read_messages=True, send_messages=True) - if allowed_roles: - if isinstance(allowed_roles, list): - for role in allowed_roles: - overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True) - - this_channel = await ctx.guild.create_text_channel( - channel_name, - overwrites=overwrites, - category=this_category - ) - - logger.info(f'Creating channel ({channel_name}) in ({category_name})') - - return this_channel - - -async def create_channel( - ctx, channel_name: str, category_name: str, everyone_send=False, everyone_read=True, - read_send_members: list = None, read_send_roles: list = None, read_only_roles: list = None): - """Create a text channel with specified permissions.""" - # Handle both Context and Interaction objects - guild = ctx.guild if hasattr(ctx, 'guild') else None - if not guild: - raise ValueError(f'Unable to access guild from context object') - - # Get bot member - different for Context vs Interaction - if hasattr(ctx, 'me'): # Context object - bot_member = ctx.me - elif hasattr(ctx, 'client'): # Interaction object - bot_member = guild.get_member(ctx.client.user.id) - else: - # Fallback - try to find bot member by getting the first member with bot=True - bot_member = next((m for m in guild.members if m.bot), None) - if not bot_member: - raise ValueError(f'Unable to find bot member in guild') - - this_category = discord.utils.get(guild.categories, name=category_name) - if not this_category: - raise ValueError(f'I couldn\'t find a category named **{category_name}**') - - overwrites = { - bot_member: discord.PermissionOverwrite(read_messages=True, send_messages=True), - guild.default_role: discord.PermissionOverwrite(read_messages=everyone_read, send_messages=everyone_send) - } - if read_send_members: - for member in read_send_members: - overwrites[member] = discord.PermissionOverwrite(read_messages=True, send_messages=True) - if read_send_roles: - for role in read_send_roles: - overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True) - if read_only_roles: - for role in read_only_roles: - overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=False) - - this_channel = await guild.create_text_channel( - channel_name, - overwrites=overwrites, - category=this_category - ) - - logger.info(f'Creating channel ({channel_name}) in ({category_name})') - - return this_channel \ No newline at end of file diff --git a/helpers.py b/helpers.py index 9485437..44b4bc6 100644 --- a/helpers.py +++ b/helpers.py @@ -33,7 +33,7 @@ from utils import ( get_context_user, ) from search_utils import * -from discord_utils import * +from helpers.discord_utils import * async def get_player_photo(player): @@ -1682,9 +1682,9 @@ async def paperdex_team_embed(team: dict, mlb_team: dict) -> list[discord.Embed] for cardset_id in coll_data: if cardset_id != "total_owned": if coll_data[cardset_id]["players"]: - coll_data[cardset_id]["embeds"][0].description = ( - f"{mlb_team['lname']} / {coll_data[cardset_id]['name']}" - ) + coll_data[cardset_id]["embeds"][ + 0 + ].description = f"{mlb_team['lname']} / {coll_data[cardset_id]['name']}" coll_data[cardset_id]["embeds"][0].add_field( name="# Collected / # Total Cards", value=f"{coll_data[cardset_id]['owned']} / {len(coll_data[cardset_id]['players'])}", diff --git a/helpers/main.py b/helpers/main.py index ed16a3b..deb6727 100644 --- a/helpers/main.py +++ b/helpers/main.py @@ -33,7 +33,7 @@ from utils import ( get_context_user, ) from search_utils import * -from discord_utils import * +from .discord_utils import * async def get_player_photo(player): @@ -1681,9 +1681,9 @@ async def paperdex_team_embed(team: dict, mlb_team: dict) -> list[discord.Embed] for cardset_id in coll_data: if cardset_id != "total_owned": if coll_data[cardset_id]["players"]: - coll_data[cardset_id]["embeds"][0].description = ( - f"{mlb_team['lname']} / {coll_data[cardset_id]['name']}" - ) + coll_data[cardset_id]["embeds"][ + 0 + ].description = f"{mlb_team['lname']} / {coll_data[cardset_id]['name']}" coll_data[cardset_id]["embeds"][0].add_field( name="# Collected / # Total Cards", value=f"{coll_data[cardset_id]['owned']} / {len(coll_data[cardset_id]['players'])}",