rewrite: Ward refactor.
This commit is contained in:
@@ -13,7 +13,7 @@ from discord.ui.button import ButtonStyle
|
||||
from meta import LionBot, LionCog, LionContext
|
||||
from meta.errors import UserInputError
|
||||
from utils.ui import AButton, AsComponents
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
|
||||
from .translator import ctx_locale, ctx_translator, SOURCE_LOCALE
|
||||
from . import babel
|
||||
@@ -115,7 +115,8 @@ class BabelCog(LionCog):
|
||||
force_language=LocaleSettings.ForceLocale._display_name
|
||||
)
|
||||
@appcmds.guild_only() # Can be removed when attached as a subcommand
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def cmd_configure_language(self, ctx: LionContext,
|
||||
language: Optional[str] = None,
|
||||
force_language: Optional[appcmds.Choice[int]] = None):
|
||||
|
||||
@@ -28,6 +28,7 @@ class ConfigCog(LionCog):
|
||||
name=_p('group:configure', "configure"),
|
||||
)
|
||||
@appcmds.guild_only
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
async def configure_group(self, ctx: LionContext):
|
||||
"""
|
||||
Bare command group, has no function.
|
||||
|
||||
@@ -25,6 +25,7 @@ class DashCog(LionCog):
|
||||
description="At-a-glance view of the server's configuration."
|
||||
)
|
||||
@appcmds.guild_only
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
async def dashboard_cmd(self, ctx: LionContext):
|
||||
ui = GuildDashboard(self.bot, ctx.guild, ctx.author.id, ctx.channel.id)
|
||||
await ui.run(ctx.interaction)
|
||||
|
||||
@@ -13,7 +13,7 @@ from discord import app_commands as appcmds
|
||||
|
||||
from meta import LionBot, LionCog, LionContext, ctx_bot
|
||||
from meta.errors import UserInputError
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
from settings import ModelData
|
||||
from settings.setting_types import TimezoneSetting
|
||||
from settings.groups import SettingGroup
|
||||
@@ -101,7 +101,8 @@ class GeneralSettingsCog(LionCog):
|
||||
timezone=GeneralSettings.Timezone._desc
|
||||
)
|
||||
@appcmds.guild_only()
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def cmd_configure_general(self, ctx: LionContext,
|
||||
timezone: Optional[str] = None):
|
||||
t = self.bot.translator.t
|
||||
|
||||
@@ -11,7 +11,7 @@ from data import ORDER
|
||||
|
||||
from utils.ui import Confirm, Pager
|
||||
from utils.lib import error_embed, MessageArgs, utc_now
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
from constants import MAX_COINS
|
||||
|
||||
from . import babel, logger
|
||||
@@ -801,7 +801,8 @@ class Economy(LionCog):
|
||||
appcmds.Choice(name=EconomySettings.AllowTransfers._outputs[False], value=0),
|
||||
]
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_economy(self, ctx: LionContext,
|
||||
allow_transfers: Optional[appcmds.Choice[int]] = None,
|
||||
coins_per_xp: Optional[appcmds.Range[int, 0, 2**15]] = None):
|
||||
|
||||
@@ -31,6 +31,6 @@ class MetaCog(LionCog):
|
||||
ctx.bot,
|
||||
ctx.author,
|
||||
ctx.guild,
|
||||
show_admin=await low_management(ctx),
|
||||
show_admin=await low_management(ctx.bot, ctx.author),
|
||||
)
|
||||
await ui.run(ctx.interaction)
|
||||
|
||||
@@ -11,7 +11,7 @@ from meta.logger import log_wrap
|
||||
from meta.sharding import THIS_SHARD
|
||||
from utils.lib import utc_now
|
||||
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
|
||||
from . import babel, logger
|
||||
from .data import TimerData
|
||||
@@ -807,7 +807,8 @@ class TimerCog(LionCog):
|
||||
@appcmds.describe(
|
||||
pomodoro_channel=TimerSettings.PomodoroChannel._desc
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_pomodoro_command(self, ctx: LionContext,
|
||||
pomodoro_channel: Optional[discord.VoiceChannel | discord.TextChannel] = None):
|
||||
t = self.bot.translator.t
|
||||
|
||||
@@ -9,7 +9,7 @@ from discord.app_commands.transformers import AppCommandOptionType
|
||||
from cachetools import LRUCache
|
||||
|
||||
from meta import LionBot, LionContext, LionCog
|
||||
from wards import high_management
|
||||
from wards import high_management_ward
|
||||
from core.data import RankType
|
||||
from utils.ui import ChoicedEnum, Transformed
|
||||
from utils.lib import utc_now, replace_multiple
|
||||
@@ -435,7 +435,8 @@ class RankCog(LionCog):
|
||||
|
||||
# ---------- Commands ----------
|
||||
@cmds.hybrid_command(name=_p('cmd:ranks', "ranks"))
|
||||
@cmds.check(high_management)
|
||||
@appcmds.default_permissions(administrator=True)
|
||||
@high_management_ward
|
||||
async def ranks_cmd(self, ctx: LionContext):
|
||||
"""
|
||||
Command to access the Rank Overview UI.
|
||||
@@ -472,7 +473,8 @@ class RankCog(LionCog):
|
||||
dm_ranks=RankSettings.DMRanks._desc,
|
||||
rank_channel=RankSettings.RankChannel._desc,
|
||||
)
|
||||
@cmds.check(high_management)
|
||||
@appcmds.default_permissions(administrator=True)
|
||||
@high_management_ward
|
||||
async def configure_ranks_cmd(self, ctx: LionContext,
|
||||
rank_type: Optional[Transformed[RankTypeChoice, AppCommandOptionType.string]] = None,
|
||||
dm_ranks: Optional[bool] = None,
|
||||
|
||||
@@ -5,11 +5,11 @@ from discord.ui.select import select, ChannelSelect, Select, SelectOption
|
||||
from discord.ui.button import button, Button, ButtonStyle
|
||||
|
||||
from meta import LionBot
|
||||
from wards import i_high_management
|
||||
from wards import high_management_iward
|
||||
from core.data import RankType
|
||||
|
||||
from utils.ui import ConfigUI, DashboardSection
|
||||
from utils.lib import MessageArgs
|
||||
from utils.lib import MessageArgs, error_embed
|
||||
|
||||
from ..settings import RankSettings
|
||||
from .. import babel, logger
|
||||
@@ -31,7 +31,20 @@ class RankConfigUI(ConfigUI):
|
||||
super().__init__(bot, guildid, channelid, **kwargs)
|
||||
|
||||
async def interaction_check(self, interaction: discord.Interaction) -> bool:
|
||||
return await i_high_management(interaction)
|
||||
passed = await high_management_iward(interaction)
|
||||
if passed:
|
||||
return True
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
embed=error_embed(
|
||||
self.bot.translator.t(_p(
|
||||
'ui:rankconfigui|check|not_permitted',
|
||||
"You have insufficient server permissions to use this UI!"
|
||||
))
|
||||
),
|
||||
ephemeral=True
|
||||
)
|
||||
return False
|
||||
|
||||
# ----- UI Components -----
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ from utils.ui import Confirm
|
||||
from constants import MAX_COINS
|
||||
from core.data import CoreData
|
||||
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
|
||||
from . import babel, logger
|
||||
from .data import RoomData
|
||||
@@ -888,7 +888,8 @@ class RoomCog(LionCog):
|
||||
@appcmds.describe(
|
||||
**{setting.setting_id: setting._desc for setting in RoomSettings.model_settings}
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_rooms_cmd(self, ctx: LionContext,
|
||||
rooms_category: Optional[discord.CategoryChannel] = None,
|
||||
rooms_price: Optional[Range[int, 0, MAX_COINS]] = None,
|
||||
|
||||
@@ -72,6 +72,7 @@ from discord import app_commands as appcmds
|
||||
from meta import LionBot, LionCog, LionContext
|
||||
from utils import ui
|
||||
from utils.lib import error_embed
|
||||
from wards import low_management_ward
|
||||
|
||||
from . import babel
|
||||
|
||||
@@ -106,6 +107,9 @@ class Shopping(LionCog):
|
||||
@cmds.hybrid_group(
|
||||
name=_p('group:editshop', 'editshop')
|
||||
)
|
||||
@appcmds.guild_only
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def editshop_group(self, ctx: LionContext):
|
||||
return
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from discord.ui.button import ButtonStyle
|
||||
from meta import LionBot, LionCog, LionContext
|
||||
from utils.lib import error_embed
|
||||
from utils.ui import LeoUI, AButton
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
|
||||
from . import babel
|
||||
from .data import StatsData
|
||||
@@ -97,7 +97,8 @@ class StatsCog(LionCog):
|
||||
"Time from which to start counting activity for rank badges and season leadeboards."
|
||||
)
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_statistics_cmd(self, ctx: LionContext,
|
||||
season_start: Optional[str] = None):
|
||||
t = self.bot.translator.t
|
||||
|
||||
@@ -20,7 +20,7 @@ from meta.app import shard_talk
|
||||
from utils.ui import ChoicedEnum, Transformed, FastModal, LeoUI, error_handler_for, ModalRetryUI
|
||||
from utils.lib import EmbedField, tabulate, MessageArgs, parse_ids, error_embed
|
||||
|
||||
from wards import sys_admin
|
||||
from wards import sys_admin_ward
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -168,7 +168,7 @@ class Blacklists(LionCog):
|
||||
name="blacklist",
|
||||
description="Display and modify the user and guild blacklists."
|
||||
)
|
||||
@cmds.check(sys_admin)
|
||||
@sys_admin_ward
|
||||
async def blacklist_cmd(
|
||||
self,
|
||||
ctx: LionContext,
|
||||
|
||||
@@ -7,7 +7,7 @@ import discord.ext.commands as cmds
|
||||
|
||||
from meta import LionBot, LionCog, LionContext
|
||||
from meta.app import appname
|
||||
from wards import sys_admin
|
||||
from wards import sys_admin_ward
|
||||
|
||||
from settings.groups import SettingGroup
|
||||
|
||||
@@ -23,7 +23,7 @@ class LeoSettings(LionCog):
|
||||
@cmds.hybrid_group(
|
||||
name="leo"
|
||||
)
|
||||
@cmds.check(sys_admin)
|
||||
@sys_admin_ward
|
||||
async def leo_group(self, ctx: LionContext):
|
||||
"""
|
||||
Base command group for global leo-only functions.
|
||||
@@ -35,7 +35,7 @@ class LeoSettings(LionCog):
|
||||
name='dashboard',
|
||||
description="Global setting dashboard"
|
||||
)
|
||||
@cmds.check(sys_admin)
|
||||
@sys_admin_ward
|
||||
async def dash_cmd(self, ctx: LionContext):
|
||||
embed = discord.Embed(
|
||||
title="System Admin Dashboard",
|
||||
@@ -56,7 +56,7 @@ class LeoSettings(LionCog):
|
||||
name='configure',
|
||||
description="Leo Configuration Group"
|
||||
)
|
||||
@cmds.check(sys_admin)
|
||||
@sys_admin_ward
|
||||
async def leo_configure_group(self, ctx: LionContext):
|
||||
"""
|
||||
Base command group for global configuration of Leo.
|
||||
|
||||
@@ -249,7 +249,7 @@ class Exec(LionCog):
|
||||
self.talk_async = shard_talk.register_route('exec')(_async)
|
||||
|
||||
async def cog_check(self, ctx: LionContext) -> bool: # type: ignore
|
||||
return await sys_admin(ctx)
|
||||
return await sys_admin(ctx.bot, ctx.author.id)
|
||||
|
||||
@commands.hybrid_command(
|
||||
name=_('async'),
|
||||
|
||||
@@ -21,7 +21,7 @@ from settings.data import ModelData
|
||||
from settings.setting_types import EnumSetting, StringSetting
|
||||
from settings.groups import SettingGroup
|
||||
|
||||
from wards import sys_admin
|
||||
from wards import sys_admin_ward
|
||||
|
||||
from . import babel
|
||||
|
||||
@@ -376,7 +376,7 @@ class PresenceCtrl(LionCog):
|
||||
name="presence",
|
||||
description="Globally set the bot status and activity."
|
||||
)
|
||||
@cmds.check(sys_admin)
|
||||
@sys_admin_ward
|
||||
@appcmds.describe(
|
||||
status="Online status (online | idle | dnd | offline)",
|
||||
type="Activity type (watching | listening | playing | streaming)",
|
||||
|
||||
@@ -12,7 +12,7 @@ from utils.lib import utc_now, error_embed
|
||||
from utils.ui import ChoicedEnum, Transformed
|
||||
|
||||
from data import Condition, NULL
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
|
||||
from . import babel, logger
|
||||
from .data import TasklistData
|
||||
@@ -712,7 +712,8 @@ class TasklistCog(LionCog):
|
||||
reward=TasklistSettings.task_reward._desc,
|
||||
reward_limit=TasklistSettings.task_reward_limit._desc
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_tasklist_cmd(self, ctx: LionContext,
|
||||
reward: Optional[int] = None,
|
||||
reward_limit: Optional[int] = None):
|
||||
|
||||
@@ -15,7 +15,7 @@ from meta.sharding import THIS_SHARD
|
||||
from meta.app import appname
|
||||
from utils.lib import utc_now, error_embed
|
||||
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
from . import babel, logger
|
||||
from .data import TextTrackerData
|
||||
|
||||
@@ -260,7 +260,8 @@ class TextTrackerCog(LionCog):
|
||||
xp_per_period=TextTrackerSettings.XPPerPeriod._desc,
|
||||
word_xp=TextTrackerSettings.WordXP._desc,
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_text_tracking_cmd(self, ctx: LionContext,
|
||||
xp_per_period: Optional[appcmds.Range[int, 0, 2**15]] = None,
|
||||
word_xp: Optional[appcmds.Range[int, 0, 2**15]] = None):
|
||||
|
||||
@@ -14,7 +14,7 @@ from meta.sharding import THIS_SHARD
|
||||
from utils.lib import utc_now, error_embed
|
||||
from core.lion_guild import VoiceMode
|
||||
|
||||
from wards import low_management
|
||||
from wards import low_management_ward
|
||||
|
||||
from . import babel, logger
|
||||
from .data import VoiceTrackerData
|
||||
@@ -625,7 +625,8 @@ class VoiceTrackerCog(LionCog):
|
||||
hourly_live_bonus=VoiceTrackerSettings.HourlyLiveBonus._desc,
|
||||
daily_voice_cap=VoiceTrackerSettings.DailyVoiceCap._desc,
|
||||
)
|
||||
@cmds.check(low_management)
|
||||
@appcmds.default_permissions(manage_guild=True)
|
||||
@low_management_ward
|
||||
async def configure_voice_tracking_cmd(self, ctx: LionContext,
|
||||
hourly_reward: Optional[int] = None, # TODO: Change these to Ranges
|
||||
hourly_live_bonus: Optional[int] = None,
|
||||
|
||||
@@ -6,7 +6,8 @@ from discord.ui.button import button, Button, ButtonStyle
|
||||
|
||||
from meta import conf, LionBot
|
||||
from meta.errors import UserInputError
|
||||
from wards import i_low_management
|
||||
from utils.lib import error_embed
|
||||
from wards import low_management_iward
|
||||
from babel.translator import ctx_translator, LazyStr
|
||||
|
||||
from ..lib import tabulate
|
||||
@@ -55,7 +56,20 @@ class ConfigUI(LeoUI):
|
||||
"""
|
||||
Default requirement for a Config UI is low management (i.e. manage_guild permissions).
|
||||
"""
|
||||
return await i_low_management(interaction)
|
||||
passed = await low_management_iward(interaction)
|
||||
if passed:
|
||||
return True
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
embed=error_embed(
|
||||
self.bot.translator.t(_p(
|
||||
'ui:configui|check|not_permitted',
|
||||
"You have insufficient server permissions to use this UI!"
|
||||
))
|
||||
),
|
||||
ephemeral=True
|
||||
)
|
||||
return False
|
||||
|
||||
async def cleanup(self):
|
||||
self._listening.pop(self.channelid, None)
|
||||
|
||||
97
src/wards.py
97
src/wards.py
@@ -1,47 +1,98 @@
|
||||
from typing import Optional
|
||||
import discord
|
||||
from discord.ext.commands.errors import CheckFailure
|
||||
import discord.ext.commands as cmds
|
||||
|
||||
from meta.LionContext import LionContext
|
||||
from meta import conf
|
||||
from babel.translator import LocalBabel
|
||||
|
||||
from meta import conf, LionContext, LionBot
|
||||
|
||||
babel = LocalBabel('wards')
|
||||
_p = babel._p
|
||||
|
||||
|
||||
# Interaction Wards
|
||||
|
||||
async def i_sys_admin(interaction: discord.Interaction) -> bool:
|
||||
# Raw checks, return True/False depending on whether they pass
|
||||
async def sys_admin(bot: LionBot, userid: int):
|
||||
"""
|
||||
Checks whether the context author is listed in the configuration file as a bot admin.
|
||||
"""
|
||||
admins = conf.bot.getintlist('admins')
|
||||
return interaction.user.id in admins
|
||||
admins = bot.config.bot.getintlist('admins')
|
||||
return userid in admins
|
||||
|
||||
|
||||
async def i_high_management(interaction: discord.Interaction) -> bool:
|
||||
if await i_sys_admin(interaction):
|
||||
async def high_management(bot: LionBot, member: discord.Member):
|
||||
if await sys_admin(bot, member.id):
|
||||
return True
|
||||
return member.guild_permissions.administrator
|
||||
|
||||
|
||||
async def low_management(bot: LionBot, member: discord.Member):
|
||||
if await high_management(bot, member):
|
||||
return True
|
||||
return member.guild_permissions.manage_guild
|
||||
|
||||
|
||||
# Interaction Wards, also return True/False
|
||||
|
||||
async def sys_admin_iward(interaction: discord.Interaction) -> bool:
|
||||
return await sys_admin(interaction.client, interaction.user.id)
|
||||
|
||||
|
||||
async def high_management_iward(interaction: discord.Interaction) -> bool:
|
||||
if not interaction.guild:
|
||||
return False
|
||||
return interaction.user.guild_permissions.administrator
|
||||
return await high_management(interaction.client, interaction.user)
|
||||
|
||||
|
||||
async def i_low_management(interaction: discord.Interaction) -> bool:
|
||||
if await i_high_management(interaction):
|
||||
return True
|
||||
async def low_management_iward(interaction: discord.Interaction) -> bool:
|
||||
if not interaction.guild:
|
||||
return False
|
||||
return interaction.user.guild_permissions.manage_guild
|
||||
return await low_management(interaction.client, interaction.user)
|
||||
|
||||
|
||||
async def sys_admin(ctx: LionContext) -> bool:
|
||||
admins = ctx.bot.config.bot.getintlist('admins')
|
||||
return ctx.author.id in admins
|
||||
# Command Wards, raise CheckFailure with localised error message
|
||||
|
||||
|
||||
async def high_management(ctx: LionContext) -> bool:
|
||||
if await sys_admin(ctx):
|
||||
@cmds.check
|
||||
async def sys_admin_ward(ctx: LionContext) -> bool:
|
||||
passed = await sys_admin(ctx.bot, ctx.author.id)
|
||||
if passed:
|
||||
return True
|
||||
else:
|
||||
raise CheckFailure(
|
||||
ctx.bot.translator.t(_p(
|
||||
'ward:sys_admin|failed',
|
||||
"You must be a bot owner to do this!"
|
||||
))
|
||||
)
|
||||
|
||||
|
||||
@cmds.check
|
||||
async def high_management_ward(ctx: LionContext) -> bool:
|
||||
if not ctx.guild:
|
||||
return False
|
||||
return ctx.author.guild_permissions.administrator
|
||||
passed = await high_management(ctx.bot, ctx.author)
|
||||
if passed:
|
||||
return True
|
||||
else:
|
||||
raise CheckFailure(
|
||||
ctx.bot.translator.t(_p(
|
||||
'ward:high_management|failed',
|
||||
"You must have the `ADMINISTRATOR` permission in this server to do this!"
|
||||
))
|
||||
)
|
||||
|
||||
|
||||
async def low_management(ctx: LionContext) -> bool:
|
||||
return (await high_management(ctx)) or ctx.author.guild_permissions.manage_guild
|
||||
@cmds.check
|
||||
async def low_management_ward(ctx: LionContext) -> bool:
|
||||
if not ctx.guild:
|
||||
return False
|
||||
passed = await low_management(ctx.bot, ctx.author)
|
||||
if passed:
|
||||
return True
|
||||
else:
|
||||
raise CheckFailure(
|
||||
ctx.bot.translator.t(_p(
|
||||
'ward:low_management|failed',
|
||||
"You must have the `MANAGE_GUILD` permission in this server to do this!"
|
||||
))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user