1
0
forked from sass/tipibot

Change admin command permissions

This commit is contained in:
Rene Arumetsa
2026-06-01 22:11:44 +03:00
parent 8d7ac504ca
commit b0e23c1a17
6 changed files with 66 additions and 19 deletions

4
bot.py
View File

@@ -22,6 +22,7 @@ import psutil
import config
import strings as S
from core import economy, pb_client, sheets
from core.admin import is_bot_admin
from core.member_sync import SyncResult
from commands.dev_member_commands import register_dev_member_commands
from commands.dev_member_runtime import handle_member_join, run_birthday_daily
@@ -593,8 +594,7 @@ class HelpSelect(discord.ui.Select):
@tree.command(name="help", description=S.CMD["help"])
async def cmd_help(interaction: discord.Interaction):
perms = interaction.user.guild_permissions if interaction.guild else None
is_admin = bool(perms and (perms.manage_roles or perms.manage_guild))
is_admin = is_bot_admin(interaction.user)
await interaction.response.send_message(
embed=_help_embed("üldine"), view=HelpView(is_admin), ephemeral=True
)

View File

@@ -8,6 +8,7 @@ import discord
from discord import app_commands
from core import sheets
from core.admin import bot_admin_check
import strings as S
from core.member_sync import announce_birthday, sync_member, today_local
@@ -167,7 +168,7 @@ def register_dev_member_commands(
@tree.command(name="check", description=S.CMD["check"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_roles=True)
@bot_admin_check()
async def cmd_check(interaction: discord.Interaction):
await interaction.response.defer(ephemeral=True)
@@ -281,7 +282,7 @@ def register_dev_member_commands(
@tree.command(name="member", description=S.CMD["member"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_roles=True)
@bot_admin_check()
async def cmd_member(interaction: discord.Interaction, user: discord.Member):
row = sheets.find_member(user.id, user.name)
if row is None:

View File

@@ -8,6 +8,7 @@ import discord
from discord import app_commands
from core import economy
from core.admin import bot_admin_check
import strings as S
@@ -29,7 +30,7 @@ def register_economy_admin_commands(
) -> None:
@tree.command(name="adminseason", description=S.CMD["adminseason"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
@app_commands.describe(top_n=S.OPT["adminseason_top_n"])
async def cmd_adminseason(interaction: discord.Interaction, top_n: int = 10):
await interaction.response.defer(ephemeral=True)
@@ -73,7 +74,7 @@ def register_economy_admin_commands(
kogus=S.OPT["admincoins_kogus"],
põhjus=S.OPT["admin_põhjus"],
)
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_admincoins(interaction: discord.Interaction, kasutaja: discord.Member, kogus: int, põhjus: str):
if kogus == 0:
await interaction.response.send_message(S.ERR["admincoins_zero"], ephemeral=True)
@@ -112,7 +113,7 @@ def register_economy_admin_commands(
minutid=S.OPT["adminjail_minutid"],
põhjus=S.OPT["admin_põhjus"],
)
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminjail(interaction: discord.Interaction, kasutaja: discord.Member, minutid: int, põhjus: str):
if minutid <= 0:
await interaction.response.send_message(S.ERR["positive_duration"], ephemeral=True)
@@ -133,7 +134,7 @@ def register_economy_admin_commands(
@tree.command(name="adminunjail", description=S.CMD["adminunjail"])
@app_commands.guild_only()
@app_commands.describe(kasutaja=S.OPT["admin_kasutaja"])
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminunjail(interaction: discord.Interaction, kasutaja: discord.Member):
await economy.do_admin_unjail(kasutaja.id, interaction.user.id)
await interaction.response.send_message(
@@ -148,7 +149,7 @@ def register_economy_admin_commands(
kasutaja=S.OPT["admin_kasutaja"],
põhjus=S.OPT["admin_põhjus"],
)
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminban(interaction: discord.Interaction, kasutaja: discord.Member, põhjus: str):
if bot.user and kasutaja.id == bot.user.id:
await interaction.response.send_message(S.ERR["admin_ban_bot"], ephemeral=True)
@@ -164,7 +165,7 @@ def register_economy_admin_commands(
@tree.command(name="adminunban", description=S.CMD["adminunban"])
@app_commands.guild_only()
@app_commands.describe(kasutaja=S.OPT["admin_kasutaja"])
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminunban(interaction: discord.Interaction, kasutaja: discord.Member):
await economy.do_admin_unban(kasutaja.id, interaction.user.id)
await interaction.response.send_message(
@@ -179,7 +180,7 @@ def register_economy_admin_commands(
kasutaja=S.OPT["admin_kasutaja"],
põhjus=S.OPT["admin_põhjus"],
)
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminreset(interaction: discord.Interaction, kasutaja: discord.Member, põhjus: str):
if bot.user and kasutaja.id == bot.user.id:
await interaction.response.send_message(S.ERR["admin_reset_bot"], ephemeral=True)
@@ -195,7 +196,7 @@ def register_economy_admin_commands(
@tree.command(name="adminview", description=S.CMD["adminview"])
@app_commands.guild_only()
@app_commands.describe(kasutaja=S.OPT["admin_kasutaja"])
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminview(interaction: discord.Interaction, kasutaja: discord.Member):
res = await economy.do_admin_inspect(kasutaja.id)
data = res["data"]
@@ -238,7 +239,7 @@ def register_economy_admin_commands(
kogus=S.OPT["adminexp_kogus"],
põhjus=S.OPT["admin_põhjus"],
)
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminexp(interaction: discord.Interaction, kasutaja: discord.Member, kogus: int, põhjus: str):
if kogus == 0:
await interaction.response.send_message(S.ERR["admincoins_zero"], ephemeral=True)
@@ -281,7 +282,7 @@ def register_economy_admin_commands(
ese=S.OPT["adminitem_ese"],
tegevus=S.OPT["adminitem_tegevus"],
)
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_adminitem(interaction: discord.Interaction, kasutaja: discord.Member, ese: str, tegevus: str):
action = tegevus.strip().lower()
if action not in ("anna", "eemalda"):

View File

@@ -13,6 +13,7 @@ from pathlib import Path
import discord
from discord import app_commands
from core.admin import bot_admin_check
import strings as S
@@ -32,7 +33,7 @@ def register_ops_admin_commands(
) -> None:
@tree.command(name="status", description=S.CMD["status"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_status(interaction: discord.Interaction):
mem = process.memory_info()
cpu = process.cpu_percent(interval=0.1)
@@ -95,7 +96,7 @@ def register_ops_admin_commands(
@tree.command(name="sync", description=S.CMD["sync"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_sync(interaction: discord.Interaction):
await interaction.response.defer(ephemeral=True)
tree.copy_global_to(guild=guild_obj)
@@ -107,7 +108,7 @@ def register_ops_admin_commands(
@tree.command(name="restart", description=S.CMD["restart"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_restart(interaction: discord.Interaction):
restart_file.write_text(json.dumps({"channel_id": interaction.channel_id}), encoding="utf-8")
await interaction.response.send_message(S.MSG_RESTARTING, ephemeral=True)
@@ -117,7 +118,7 @@ def register_ops_admin_commands(
@tree.command(name="shutdown", description=S.CMD["shutdown"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_shutdown(interaction: discord.Interaction):
await interaction.response.send_message(S.MSG_SHUTTING_DOWN, ephemeral=True)
log.info("/shutdown triggered by %s", interaction.user)
@@ -125,7 +126,7 @@ def register_ops_admin_commands(
@tree.command(name="pause", description=S.CMD["pause"])
@app_commands.guild_only()
@app_commands.default_permissions(manage_guild=True)
@bot_admin_check()
async def cmd_pause(interaction: discord.Interaction):
paused = not get_paused()
set_paused(paused)

View File

@@ -42,6 +42,23 @@ BIRTHDAY_CHANNEL_ID = (
BIRTHDAY_WINDOW_DAYS = int(os.getenv("BIRTHDAY_WINDOW_DAYS", "7"))
BASE_ROLE_IDS: list[int] = [1478304631930228779, 1478302278862766190]
def _parse_admin_roles(raw: str) -> dict[int, int]:
"""Parse BOT_ADMIN_ROLES env var as "guild_id:role_id,guild_id:role_id"."""
result: dict[int, int] = {}
for pair in raw.split(","):
pair = pair.strip()
if not pair:
continue
guild_str, _, role_str = pair.partition(":")
if not role_str:
raise SystemExit(f"BOT_ADMIN_ROLES: expected 'guild_id:role_id', got {pair!r}")
result[int(guild_str)] = int(role_str)
return result
BOT_ADMIN_ROLES: dict[int, int] = _parse_admin_roles(os.getenv("BOT_ADMIN_ROLES", ""))
PB_URL = os.getenv("PB_URL", "http://127.0.0.1:8090")
PB_ADMIN_EMAIL = os.getenv("PB_ADMIN_EMAIL", "")
PB_ADMIN_PASSWORD = os.getenv("PB_ADMIN_PASSWORD", "")

27
core/admin.py Normal file
View File

@@ -0,0 +1,27 @@
from __future__ import annotations
import discord
from discord import app_commands
import config
def is_bot_admin(member: discord.abc.User | None) -> bool:
"""True when the member has the configured admin role for their guild."""
if not isinstance(member, discord.Member) or member.guild is None:
return False
role_id = config.BOT_ADMIN_ROLES.get(member.guild.id)
if role_id is None:
return False
return any(r.id == role_id for r in member.roles)
def bot_admin_check():
"""Slash-command decorator that gates execution behind ``is_bot_admin``."""
async def predicate(interaction: discord.Interaction) -> bool:
if is_bot_admin(interaction.user):
return True
raise app_commands.MissingPermissions(["bot_admin_role"])
return app_commands.check(predicate)