|
50 | 50 | ) |
51 | 51 | from ghdcbot.logging.setup import configure_logging |
52 | 52 | from ghdcbot.plugins.registry import build_adapter |
| 53 | +from ghdcbot.discord_command_permissions import ( |
| 54 | + format_slash_command_permission_denied, |
| 55 | + slash_command_allowed, |
| 56 | +) |
| 57 | + |
| 58 | +# Slash command names used for permission checks (must match @tree.command name=...) |
| 59 | +SLASH_CMD_ASSIGN_ISSUE = "assign-issue" |
| 60 | +SLASH_CMD_ISSUE_REQUESTS = "issue-requests" |
| 61 | +SLASH_CMD_SYNC = "sync" |
53 | 62 |
|
54 | 63 |
|
55 | 64 | def run_bot(config_path: str) -> None: |
@@ -888,24 +897,20 @@ async def cancel_assignment(self, interaction: discord.Interaction, button: disc |
888 | 897 | except Exception: |
889 | 898 | pass |
890 | 899 |
|
891 | | - # Create a check function for mentor-only commands |
892 | | - def mentor_check(interaction: discord.Interaction) -> bool: |
893 | | - """Check if user has mentor role.""" |
894 | | - mentor_roles = getattr(config, "assignments", None) |
895 | | - if not mentor_roles: |
896 | | - return False |
897 | | - issue_assignee_roles = getattr(mentor_roles, "issue_assignees", []) |
898 | | - if not issue_assignee_roles: |
899 | | - return False |
900 | | - user_roles = [role.name for role in interaction.user.roles] |
901 | | - return any(role in issue_assignee_roles for role in user_roles) |
| 900 | + def command_permission_check(command_name: str): |
| 901 | + """Restrict slash commands via discord.command_permissions or legacy issue_assignees.""" |
| 902 | + |
| 903 | + def check(interaction: discord.Interaction) -> bool: |
| 904 | + return slash_command_allowed(interaction, config, command_name) |
| 905 | + |
| 906 | + return check |
902 | 907 |
|
903 | 908 | @tree.command( |
904 | 909 | name="assign-issue", |
905 | 910 | description="Assign a GitHub issue to a Discord user (mentor-only, requires confirmation)", |
906 | 911 | guild=discord.Object(id=guild_id), |
907 | 912 | ) |
908 | | - @app_commands.check(mentor_check) |
| 913 | + @app_commands.check(command_permission_check(SLASH_CMD_ASSIGN_ISSUE)) |
909 | 914 | @app_commands.describe( |
910 | 915 | issue_url="GitHub issue URL (e.g., https://github.com/owner/repo/issues/123)", |
911 | 916 | assignee="Discord user to assign the issue to" |
@@ -1579,7 +1584,7 @@ async def request_issue_cmd(interaction: discord.Interaction, issue_url: str) -> |
1579 | 1584 | description="List pending issue assignment requests (mentor-only); pick a repo first.", |
1580 | 1585 | guild=discord.Object(id=guild_id), |
1581 | 1586 | ) |
1582 | | - @app_commands.check(mentor_check) |
| 1587 | + @app_commands.check(command_permission_check(SLASH_CMD_ISSUE_REQUESTS)) |
1583 | 1588 | async def issue_requests_cmd(interaction: discord.Interaction) -> None: |
1584 | 1589 | await interaction.response.defer(ephemeral=True) |
1585 | 1590 | pending = getattr(storage, "list_pending_issue_requests", None) |
@@ -1684,7 +1689,7 @@ async def on_message(message: discord.Message) -> None: |
1684 | 1689 | description="Sync GitHub events and send notifications (mentor-only)", |
1685 | 1690 | guild=discord.Object(id=guild_id), |
1686 | 1691 | ) |
1687 | | - @app_commands.check(mentor_check) |
| 1692 | + @app_commands.check(command_permission_check(SLASH_CMD_SYNC)) |
1688 | 1693 | async def sync_cmd(interaction: discord.Interaction) -> None: |
1689 | 1694 | """Manually trigger run-once to sync GitHub events and send notifications.""" |
1690 | 1695 | await interaction.response.defer(ephemeral=True) |
@@ -1751,17 +1756,13 @@ async def on_app_command_error(interaction: discord.Interaction, error: app_comm |
1751 | 1756 | """Handle app command errors, including check failures.""" |
1752 | 1757 | if isinstance(error, app_commands.CheckFailure): |
1753 | 1758 | try: |
1754 | | - mentor_roles = getattr(config, "assignments", None) |
1755 | | - issue_assignee_roles = getattr(mentor_roles, "issue_assignees", []) if mentor_roles else [] |
1756 | | - role_list = ', '.join(issue_assignee_roles) if issue_assignee_roles else 'configure issue_assignees' |
1757 | | - error_message = f"❌ Permission denied. Only mentors with roles **{role_list}** can use this command." |
1758 | | - |
| 1759 | + cmd_name = interaction.command.name if interaction.command else "unknown" |
| 1760 | + error_message = format_slash_command_permission_denied(config, cmd_name) |
1759 | 1761 | logger.info( |
1760 | | - "Check failure for user %s (%s) on command %s. Required roles: %s", |
| 1762 | + "Check failure for user %s (%s) on command %s.", |
1761 | 1763 | interaction.user.name, |
1762 | 1764 | interaction.user.id, |
1763 | | - interaction.command.name if interaction.command else "unknown", |
1764 | | - role_list, |
| 1765 | + cmd_name, |
1765 | 1766 | ) |
1766 | 1767 |
|
1767 | 1768 | # Check if response is already sent (shouldn't happen for check failures, but be safe) |
|
0 commit comments