Fix slash command decorators using wrong prefix command checks

Bug: Several slash commands (@app_commands.command) were using prefix command
decorators (@commands.has_any_role, @commands.check) which don't work with
app_commands. This caused errors caught by the global error handler, resulting
in "Unknown interaction" (404) errors being displayed before the command executed.

Affected commands:
- /comeonmanineedthis: Both role and channel checks were wrong
- /selldupes: Channel check was wrong
- /team: Channel check was wrong

Fix:
- Created app_legal_channel() decorator in helpers.py for slash commands
- Changed @commands.has_any_role to @app_commands.checks.has_any_role
- Changed @commands.check(legal_channel) to @app_legal_channel()

Bumps version to 1.7.5

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2025-11-17 07:29:08 -06:00
parent 563820fe93
commit 584a8a95ab
4 changed files with 19 additions and 6 deletions

View File

@ -1 +1 @@
1.7.4 1.7.5

View File

@ -518,8 +518,8 @@ class Economy(commands.Cog):
await display_cards(c_query['cards'], team, ctx.channel, ctx.author, self.bot, pack_cover=pack_cover) await display_cards(c_query['cards'], team, ctx.channel, ctx.author, self.bot, pack_cover=pack_cover)
@app_commands.command(name='comeonmanineedthis', description='Daily check-in for cards, currency, and packs') @app_commands.command(name='comeonmanineedthis', description='Daily check-in for cards, currency, and packs')
@commands.has_any_role(PD_PLAYERS) @app_commands.checks.has_any_role(PD_PLAYERS)
@commands.check(legal_channel) @app_legal_channel()
async def daily_checkin(self, interaction: discord.Interaction): async def daily_checkin(self, interaction: discord.Interaction):
await interaction.response.defer() await interaction.response.defer()
team = await get_team_by_owner(interaction.user.id) team = await get_team_by_owner(interaction.user.id)
@ -984,7 +984,7 @@ class Economy(commands.Cog):
@app_commands.command(name='selldupes', description='Sell all of your duplicate cards') @app_commands.command(name='selldupes', description='Sell all of your duplicate cards')
@app_commands.checks.has_any_role(PD_PLAYERS) @app_commands.checks.has_any_role(PD_PLAYERS)
@commands.check(legal_channel) @app_legal_channel()
@app_commands.describe( @app_commands.describe(
immediately='Skip all prompts and sell dupes immediately; default False', immediately='Skip all prompts and sell dupes immediately; default False',
skip_live='Skip all live series cards; default True' skip_live='Skip all live series cards; default True'

View File

@ -30,7 +30,7 @@ from in_game.gameplay_models import Lineup, Play, Session, engine
from api_calls import db_get, db_post, db_patch, get_team_by_abbrev from api_calls import db_get, db_post, db_patch, get_team_by_abbrev
from helpers import ACTIVE_EVENT_LITERAL, PD_PLAYERS_ROLE_NAME, IMAGES, PD_SEASON, random_conf_gif, fuzzy_player_search, ALL_MLB_TEAMS, \ from helpers import ACTIVE_EVENT_LITERAL, PD_PLAYERS_ROLE_NAME, IMAGES, PD_SEASON, random_conf_gif, fuzzy_player_search, ALL_MLB_TEAMS, \
fuzzy_search, get_channel, display_cards, get_card_embeds, get_team_embed, cardset_search, get_blank_team_card, \ fuzzy_search, get_channel, display_cards, get_card_embeds, get_team_embed, cardset_search, get_blank_team_card, \
get_team_by_owner, get_rosters, get_roster_sheet, legal_channel, random_conf_word, embed_pagination, get_cal_user, \ get_team_by_owner, get_rosters, get_roster_sheet, legal_channel, app_legal_channel, random_conf_word, embed_pagination, get_cal_user, \
team_summary_embed, SelectView, SelectPaperdexCardset, SelectPaperdexTeam, get_context_user team_summary_embed, SelectView, SelectPaperdexCardset, SelectPaperdexTeam, get_context_user
from utilities.buttons import ask_with_buttons from utilities.buttons import ask_with_buttons
from utilities.autocomplete import cardset_autocomplete, player_autocomplete from utilities.autocomplete import cardset_autocomplete, player_autocomplete
@ -596,7 +596,7 @@ class Players(commands.Cog):
@app_commands.command(name='team', description='Show team overview and rosters') @app_commands.command(name='team', description='Show team overview and rosters')
@app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME)
@commands.check(legal_channel) @app_legal_channel()
async def team_command(self, interaction: discord.Interaction, team_abbrev: Optional[str] = None): async def team_command(self, interaction: discord.Interaction, team_abbrev: Optional[str] = None):
await interaction.response.defer() await interaction.response.defer()
if team_abbrev: if team_abbrev:

View File

@ -1004,6 +1004,7 @@ def post_ratings_guide(team, bot, this_sheet=None):
async def legal_channel(ctx): async def legal_channel(ctx):
"""Check for prefix commands (commands.Context)."""
bad_channels = ['paper-dynasty-chat', 'pd-news-ticker', 'pd-network-news'] bad_channels = ['paper-dynasty-chat', 'pd-news-ticker', 'pd-network-news']
if isinstance(ctx, commands.Context): if isinstance(ctx, commands.Context):
@ -1022,6 +1023,18 @@ async def legal_channel(ctx):
return True return True
def app_legal_channel():
"""Check for slash commands (app_commands). Use as @app_legal_channel()"""
async def predicate(interaction: discord.Interaction) -> bool:
bad_channels = ['paper-dynasty-chat', 'pd-news-ticker', 'pd-network-news']
if interaction.channel.name in bad_channels:
raise discord.app_commands.CheckFailure(
f'Slide on down to the {get_channel(interaction, "pd-bot-hole").mention} ;)'
)
return True
return discord.app_commands.check(predicate)
def is_ephemeral_channel(channel) -> bool: def is_ephemeral_channel(channel) -> bool:
"""Check if channel requires ephemeral responses (chat channels).""" """Check if channel requires ephemeral responses (chat channels)."""
if not channel or not hasattr(channel, 'name'): if not channel or not hasattr(channel, 'name'):