feat(config): Split mod and admin config.

This commit is contained in:
2023-10-16 21:43:54 +03:00
parent d9c58806cf
commit ab39ceee71
44 changed files with 227 additions and 102 deletions

View File

@@ -41,7 +41,7 @@ class BabelCog(LionCog):
self.bot.core.user_config.register_model_setting(LocaleSettings.UserLocale)
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
userconfigcog = self.bot.get_cog('UserConfigCog')
self.crossload_group(self.userconfig_group, userconfigcog.userconfig_group)
@@ -114,8 +114,6 @@ class BabelCog(LionCog):
language=LocaleSettings.GuildLocale._display_name,
force_language=LocaleSettings.ForceLocale._display_name
)
@appcmds.guild_only() # Can be removed when attached as a subcommand
@appcmds.default_permissions(manage_guild=True)
@low_management_ward
async def cmd_configure_language(self, ctx: LionContext,
language: Optional[str] = None,

View File

@@ -7,6 +7,7 @@ from settings.groups import SettingGroup
from meta.errors import UserInputError
from meta.context import ctx_bot
from core.data import CoreData
from wards import low_management_iward
from .translator import ctx_translator
from . import babel
@@ -104,9 +105,10 @@ class LocaleSettings(SettingGroup):
"""
Guild configuration for whether to force usage of the guild locale.
Exposed via `/configure language` command and standard configuration interface.
Exposed via `/config language` command and standard configuration interface.
"""
setting_id = 'force_locale'
_write_ward = low_management_iward
_display_name = _p('guildset:force_locale', 'force_language')
_desc = _p('guildset:force_locale|desc',
@@ -144,15 +146,16 @@ class LocaleSettings(SettingGroup):
def set_str(self):
bot = ctx_bot.get()
if bot:
return bot.core.mention_cmd('configure language')
return bot.core.mention_cmd('config language')
class GuildLocale(ModelData, LocaleSetting):
"""
Guild-configured locale.
Exposed via `/configure language` command, and standard configuration interface.
Exposed via `/config language` command, and standard configuration interface.
"""
setting_id = 'guild_locale'
_write_ward = low_management_iward
_display_name = _p('guildset:locale', 'language')
_desc = _p('guildset:locale|desc', "Your preferred language for interacting with me.")
@@ -180,4 +183,4 @@ class LocaleSettings(SettingGroup):
def set_str(self):
bot = ctx_bot.get()
if bot:
return bot.core.mention_cmd('configure language')
return bot.core.mention_cmd('config language')

View File

@@ -29,6 +29,7 @@ class LocaleSettingUI(ConfigUI):
async def force_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer()
setting = next(inst for inst in self.instances if inst.setting_id == LocaleSettings.ForceLocale.setting_id)
await setting.interaction_check(self.guildid, press)
setting.value = not setting.value
await setting.write()
@@ -80,7 +81,7 @@ class LocaleSettingUI(ConfigUI):
class LocaleDashboard(DashboardSection):
section_name = _p(
'dash:locale|title',
"Server Language Configuration ({commands[configure language]})"
"Server Language Configuration ({commands[config language]})"
)
_option_name = _p(
"dash:locale|dropdown|placeholder",

View File

@@ -25,12 +25,35 @@ class ConfigCog(LionCog):
...
@cmds.hybrid_group(
name=_p('group:configure', "configure"),
description=_p('group:configure|desc', "View and adjust my configuration options."),
name=_p('group:config', "config"),
description=_p('group:config|desc', "View and adjust moderation-level configuration."),
)
@appcmds.guild_only
@appcmds.default_permissions(manage_guild=True)
async def configure_group(self, ctx: LionContext):
async def config_group(self, ctx: LionContext):
"""
Bare command group, has no function.
"""
return
@cmds.hybrid_group(
name=_p('group:admin', "admin"),
description=_p('group:admin|desc', "Administrative commands."),
)
@appcmds.guild_only
@appcmds.default_permissions(administrator=True)
async def admin_group(self, ctx: LionContext):
"""
Bare command group, has no function.
"""
return
@admin_group.group(
name=_p('group:admin_config', "config"),
description=_p('group:admin_config|desc', "View and adjust admin-level configuration."),
)
@appcmds.guild_only
async def admin_config_group(self, ctx: LionContext):
"""
Bare command group, has no function.
"""

View File

@@ -29,14 +29,14 @@ class GuildConfigCog(LionCog):
configcog = self.bot.get_cog('ConfigCog')
if configcog is None:
raise ValueError("Cannot load GuildConfigCog without ConfigCog")
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
@cmds.hybrid_command(
name="dashboard",
description="At-a-glance view of the server's configuration."
)
@appcmds.guild_only
@appcmds.default_permissions(manage_guild=True)
@low_management_ward
async def dashboard_cmd(self, ctx: LionContext):
if not ctx.guild or not ctx.interaction:
return
@@ -64,8 +64,6 @@ class GuildConfigCog(LionCog):
timezone=GeneralSettings.Timezone._desc,
event_log=GeneralSettings.EventLog._desc,
)
@appcmds.guild_only()
@appcmds.default_permissions(manage_guild=True)
@low_management_ward
async def cmd_configure_general(self, ctx: LionContext,
timezone: Optional[str] = None,

View File

@@ -9,6 +9,7 @@ from meta.context import ctx_bot
from meta.errors import UserInputError
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward
from . import babel
@@ -20,13 +21,14 @@ class GeneralSettings(SettingGroup):
"""
Guild timezone configuration.
Exposed via `/configure general timezone:`, and the standard interface.
Exposed via `/config general timezone:`, and the standard interface.
The `timezone` setting acts as the default timezone for all members,
and the timezone used to display guild-wide statistics.
"""
setting_id = 'timezone'
_event = 'guildset_timezone'
_set_cmd = 'configure general'
_set_cmd = 'config general'
_write_ward = low_management_iward
_display_name = _p('guildset:timezone', "timezone")
_desc = _p(
@@ -58,7 +60,8 @@ class GeneralSettings(SettingGroup):
"""
setting_id = 'eventlog'
_event = 'guildset_eventlog'
_set_cmd = 'configure general'
_set_cmd = 'config general'
_write_ward = low_management_iward
_display_name = _p('guildset:eventlog', "event_log")
_desc = _p(

View File

@@ -41,6 +41,7 @@ class GeneralSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(GeneralSettings.EventLog)
await setting.interaction_check(setting.parent_id, selection)
value = selected.values[0].resolve() if selected.values else None
setting = await setting.from_value(self.guildid, value)
@@ -95,7 +96,7 @@ class GeneralSettingUI(ConfigUI):
class GeneralDashboard(DashboardSection):
section_name = _p(
"dash:general|title",
"General Configuration ({commands[configure general]})"
"General Configuration ({commands[admin config general]})"
)
_option_name = _p(
"dash:general|option|name",

View File

@@ -64,7 +64,7 @@ class Economy(LionCog):
"Attempting to load the EconomyCog before ConfigCog! Failed to crossload configuration group."
)
else:
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
# ----- Economy Bonus registration -----
def register_economy_bonus(self, bonus_coro, name=None):
@@ -903,7 +903,6 @@ class Economy(LionCog):
appcmds.Choice(name=EconomySettings.AllowTransfers._outputs[False], value=0),
]
)
@appcmds.default_permissions(manage_guild=True)
@moderator_ward
async def configure_economy(self, ctx: LionContext,
allow_transfers: Optional[appcmds.Choice[int]] = None,

View File

@@ -17,6 +17,7 @@ from meta.logger import log_wrap
from core.data import CoreData
from core.setting_types import CoinSetting
from babel.translator import ctx_translator
from wards import low_management_iward
from . import babel, logger
from .data import EconomyData
@@ -32,6 +33,7 @@ class EconomySettings(SettingGroup):
"""
class CoinsPerXP(ModelData, CoinSetting):
setting_id = 'coins_per_xp'
_write_ward = low_management_iward
_display_name = _p('guildset:coins_per_xp', "coins_per_100xp")
_desc = _p(
@@ -63,10 +65,11 @@ class EconomySettings(SettingGroup):
@property
def set_str(self):
bot = ctx_bot.get()
return bot.core.mention_cmd('configure economy') if bot else None
return bot.core.mention_cmd('config economy') if bot else None
class AllowTransfers(ModelData, BoolSetting):
setting_id = 'allow_transfers'
_write_ward = low_management_iward
_display_name = _p('guildset:allow_transfers', "allow_transfers")
_desc = _p(
@@ -91,7 +94,7 @@ class EconomySettings(SettingGroup):
@property
def set_str(self):
bot = ctx_bot.get()
return bot.core.mention_cmd('configure economy') if bot else None
return bot.core.mention_cmd('config economy') if bot else None
@property
def update_message(self):
@@ -115,6 +118,7 @@ class EconomySettings(SettingGroup):
class StartingFunds(ModelData, CoinSetting):
setting_id = 'starting_funds'
_write_ward = low_management_iward
_display_name = _p('guildset:starting_funds', "starting_funds")
_desc = _p(

View File

@@ -64,7 +64,7 @@ class EconomyConfigUI(ConfigUI):
class EconomyDashboard(DashboardSection):
section_name = _p(
'dash:economy|title',
"Economy Configuration ({commands[configure economy]})"
"Economy Configuration ({commands[config economy]})"
)
_option_name = _p(
"dash:economy|dropdown|placeholder",

View File

@@ -46,7 +46,7 @@ class MemberAdminCog(LionCog):
"Configuration command cannot be crossloaded."
)
else:
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
# ----- Cog API -----
async def absent_remove_role(self, guildid, userid, roleid):

View File

@@ -9,6 +9,7 @@ from settings import ListData, ModelData
from settings.groups import SettingGroup
from settings.setting_types import BoolSetting, ChannelSetting, RoleListSetting
from utils.lib import recurse_map, replace_multiple, tabulate
from wards import low_management_iward, high_management_iward
from . import babel
from .data import MemberAdminData
@@ -36,6 +37,7 @@ _greeting_subkey_desc = {
class MemberAdminSettings(SettingGroup):
class GreetingChannel(ModelData, ChannelSetting):
setting_id = 'greeting_channel'
_write_ward = low_management_iward
_display_name = _p('guildset:greeting_channel', "welcome_channel")
_desc = _p(
@@ -87,6 +89,7 @@ class MemberAdminSettings(SettingGroup):
class GreetingMessage(ModelData, MessageSetting):
setting_id = 'greeting_message'
_write_ward = low_management_iward
_display_name = _p(
'guildset:greeting_message', "welcome_message"
@@ -209,6 +212,7 @@ class MemberAdminSettings(SettingGroup):
class ReturningMessage(ModelData, MessageSetting):
setting_id = 'returning_message'
_write_ward = low_management_iward
_display_name = _p(
'guildset:returning_message', "returning_message"
@@ -335,6 +339,7 @@ class MemberAdminSettings(SettingGroup):
class Autoroles(ListData, RoleListSetting):
setting_id = 'autoroles'
_write_ward = high_management_iward
_display_name = _p(
'guildset:autoroles', "autoroles"
@@ -357,6 +362,7 @@ class MemberAdminSettings(SettingGroup):
class BotAutoroles(ListData, RoleListSetting):
setting_id = 'bot_autoroles'
_write_ward = high_management_iward
_display_name = _p(
'guildset:bot_autoroles', "bot_autoroles"
@@ -379,6 +385,7 @@ class MemberAdminSettings(SettingGroup):
class RolePersistence(ModelData, BoolSetting):
setting_id = 'role_persistence'
_event = 'guildset_role_persistence'
_write_ward = low_management_iward
_display_name = _p('guildset:role_persistence', "role_persistence")
_desc = _p(

View File

@@ -45,6 +45,7 @@ class MemberAdminUI(ConfigUI):
"""
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(Settings.GreetingChannel)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
await selection.delete_original_response()
@@ -73,6 +74,7 @@ class MemberAdminUI(ConfigUI):
await equippable_role(self.bot, role, selection.user)
setting = self.get_instance(Settings.Autoroles)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
# Instance hooks will update the menu
@@ -102,6 +104,7 @@ class MemberAdminUI(ConfigUI):
await equippable_role(self.bot, role, selection.user)
setting = self.get_instance(Settings.BotAutoroles)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
# Instance hooks will update the menu
@@ -131,6 +134,7 @@ class MemberAdminUI(ConfigUI):
await press.response.defer(thinking=True, ephemeral=True)
t = self.bot.translator.t
setting = self.get_instance(Settings.GreetingMessage)
await setting.interaction_check(setting.parent_id, press)
value = setting.value
if value is None:
@@ -173,6 +177,7 @@ class MemberAdminUI(ConfigUI):
await press.response.defer(thinking=True, ephemeral=True)
t = self.bot.translator.t
setting = self.get_instance(Settings.ReturningMessage)
await setting.interaction_check(setting.parent_id, press)
greeting = self.get_instance(Settings.GreetingMessage)
value = setting.value
@@ -254,7 +259,7 @@ class MemberAdminUI(ConfigUI):
class MemberAdminDashboard(DashboardSection):
section_name = _p(
"dash:member_admin|title",
"Greetings and Initial Roles ({commands[configure welcome]})"
"Greetings and Initial Roles ({commands[admin config welcome]})"
)
_option_name = _p(
"dash:member_admin|dropdown|placeholder",
@@ -278,7 +283,7 @@ class MemberAdminDashboard(DashboardSection):
page.add_field(
name=t(_p(
'dash:member_admin|section:greeting_messages|name',
"Greeting Messages ({commands[configure welcome]})"
"Greeting Messages ({commands[admin config welcome]})"
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
@@ -289,7 +294,7 @@ class MemberAdminDashboard(DashboardSection):
page.add_field(
name=t(_p(
'dash:member_admin|section:initial_roles|name',
"Initial Roles ({commands[configure welcome]})"
"Initial Roles ({commands[admin config welcome]})"
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False

View File

@@ -74,8 +74,8 @@ admin_extra = _p(
Use {cmd_dashboard} to see an overview of the server configuration, \
and quickly jump to the feature configuration panels to modify settings.
Configuration panels are also accessible directly through the `/configure` commands \
and most features may be configured through these commands.
Most settings may also be directly set through the `/config` and `/admin config` commands, \
depending on whether the settings require moderator (manage server) or admin level permissions, respectively.
Other relevant commands for guild configuration below:
`/editshop`: Add/Edit/Remove colour roles from the {coin} shop.

View File

@@ -51,7 +51,7 @@ class ModerationCog(LionCog):
"Moderation configuration will not crossload."
)
else:
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.admin_config_group)
if self.bot.is_ready():
await self.initialise()

View File

@@ -6,6 +6,7 @@ from settings.setting_types import (
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward, high_management_iward
from . import babel
@@ -16,6 +17,7 @@ class ModerationSettings(SettingGroup):
class TicketLog(ModelData, ChannelSetting):
setting_id = "ticket_log"
_event = 'guildset_ticket_log'
_write_ward = low_management_iward
_display_name = _p('guildset:ticket_log', "ticket_log")
_desc = _p(
@@ -66,6 +68,7 @@ class ModerationSettings(SettingGroup):
class AlertChannel(ModelData, ChannelSetting):
setting_id = "alert_channel"
_event = 'guildset_alert_channel'
_write_ward = low_management_iward
_display_name = _p('guildset:alert_channel', "alert_channel")
_desc = _p(
@@ -119,18 +122,23 @@ class ModerationSettings(SettingGroup):
class ModRole(ModelData, RoleSetting):
setting_id = "mod_role"
_event = 'guildset_mod_role'
_write_ward = high_management_iward
_display_name = _p('guildset:mod_role', "mod_role")
_desc = _p(
'guildset:mod_role|desc',
"Guild role permitted to view configuration and perform moderation tasks."
"Server role permitted to perform moderation and minor bot configuration."
)
_long_desc = _p(
'guildset:mod_role|long_desc',
"Members with the set role will be able to access my configuration panels, "
"and perform some moderation tasks, such as setting up pomodoro timers. "
"Moderators cannot reconfigure most bot configuration, "
"or perform operations they do not already have permission for in Discord."
"Members with the moderator role are considered moderators,"
" and are permitted to use moderator commands,"
" such as viewing and pardoning moderation tickets,"
" creating moderation notes,"
" and performing minor reconfiguration through the `/config` command.\n"
"Moderators are never permitted to perform actions (such as giving roles)"
" that they do not already have the Discord permissions for.\n"
"Members with the 'Manage Guild' permission are always considered moderators."
)
_accepts = _p(
'guildset:mod_role|accepts',
@@ -149,11 +157,13 @@ class ModerationSettings(SettingGroup):
resp = t(_p(
'guildset:mod_role|set_response:set',
"Members with {role} will be considered moderators."
" You may need to grant them access to view moderation commands"
" via the server integration settings."
)).format(role=value.mention)
else:
resp = t(_p(
'guildset:mod_role|set_response:unset',
"No members will be given moderation privileges."
"Only members with the 'Manage Guild' permission will be considered moderators."
))
return resp
@@ -171,6 +181,7 @@ class ModerationSettings(SettingGroup):
class AdminRole(ModelData, RoleSetting):
setting_id = "admin_role"
_event = 'guildset_admin_role'
_write_ward = high_management_iward
_display_name = _p('guildset:admin_role', "admin_role")
_desc = _p(

View File

@@ -42,6 +42,7 @@ class ModerationSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(ModerationSettings.TicketLog)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
await selection.delete_original_response()
@@ -67,6 +68,7 @@ class ModerationSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(ModerationSettings.AlertChannel)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
await selection.delete_original_response()
@@ -92,6 +94,7 @@ class ModerationSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(ModerationSettings.ModRole)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
await selection.delete_original_response()
@@ -117,6 +120,7 @@ class ModerationSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(ModerationSettings.AdminRole)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
await selection.delete_original_response()
@@ -175,7 +179,7 @@ class ModerationSettingUI(ConfigUI):
class ModerationDashboard(DashboardSection):
section_name = _p(
"dash:moderation|title",
"Moderation Settings ({commands[configure moderation]})"
"Moderation Settings ({commands[admin config moderation]})"
)
_option_name = _p(
"dash:moderation|dropdown|placeholder",

View File

@@ -90,7 +90,7 @@ class TimerCog(LionCog):
self.bot.core.guild_config.register_model_setting(self.settings.PomodoroChannel)
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
if self.bot.is_ready():
await self.initialise()
@@ -977,7 +977,6 @@ class TimerCog(LionCog):
@appcmds.describe(
pomodoro_channel=TimerSettings.PomodoroChannel._desc
)
@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):

View File

@@ -4,6 +4,7 @@ from settings.setting_types import ChannelSetting
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward
from . import babel
@@ -14,7 +15,8 @@ class TimerSettings(SettingGroup):
class PomodoroChannel(ModelData, ChannelSetting):
setting_id = 'pomodoro_channel'
_event = 'guildset_pomodoro_channel'
_set_cmd = 'configure pomodoro'
_set_cmd = 'config pomodoro'
_write_ward = low_management_iward
_display_name = _p('guildset:pomodoro_channel', "pomodoro_channel")
_desc = _p(

View File

@@ -30,6 +30,7 @@ class TimerConfigUI(ConfigUI):
async def channel_menu(self, selection: discord.Interaction, selected: ChannelSelect):
await selection.response.defer()
setting = self.instances[0]
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
@@ -78,7 +79,7 @@ class TimerConfigUI(ConfigUI):
class TimerDashboard(DashboardSection):
section_name = _p(
'dash:pomodoro|title',
"Pomodoro Configuration ({commands[configure pomodoro]})"
"Pomodoro Configuration ({commands[admin config pomodoro]})"
)
_option_name = _p(
"dash:stats|dropdown|placeholder",

View File

@@ -140,7 +140,7 @@ class RankCog(LionCog):
self.bot.core.guild_config.register_model_setting(self.settings.DMRanks)
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.admin_config_group)
def ranklock(self, guildid):
lock = self._rank_locks.get(guildid, None)
@@ -926,7 +926,6 @@ class RankCog(LionCog):
dm_ranks=RankSettings.DMRanks._desc,
rank_channel=RankSettings.RankChannel._desc,
)
@appcmds.default_permissions(administrator=True)
@high_management_ward
async def configure_ranks_cmd(self, ctx: LionContext,
rank_type: Optional[Transformed[RankTypeChoice, AppCommandOptionType.string]] = None,

View File

@@ -4,6 +4,7 @@ from settings.setting_types import BoolSetting, ChannelSetting, EnumSetting
from core.data import RankType, CoreData
from babel.translator import ctx_translator
from wards import high_management_iward
from . import babel
@@ -40,7 +41,8 @@ class RankSettings(SettingGroup):
setting_id = 'rank_type'
_event = 'guildset_rank_type'
_set_cmd = 'configure ranks'
_set_cmd = 'admin config ranks'
_write_ward = high_management_iward
_display_name = _p('guildset:rank_type', "rank_type")
_desc = _p(
@@ -98,7 +100,8 @@ class RankSettings(SettingGroup):
If DMRanks is set, this will only be used when the target user has disabled DM notifications.
"""
setting_id = 'rank_channel'
_set_cmd = 'configure ranks'
_set_cmd = 'admin config ranks'
_write_ward = high_management_iward
_display_name = _p('guildset:rank_channel', "rank_channel")
_desc = _p(
@@ -148,7 +151,8 @@ class RankSettings(SettingGroup):
Whether to DM rank notifications.
"""
setting_id = 'dm_ranks'
_set_cmd = 'configure ranks'
_set_cmd = 'admin config ranks'
_write_ward = high_management_iward
_display_name = _p('guildset:dm_ranks', "dm_ranks")
_desc = _p(

View File

@@ -69,6 +69,7 @@ class RankConfigUI(ConfigUI):
async def type_menu(self, selection: discord.Interaction, selected: Select):
await selection.response.defer(thinking=True)
setting = self.instances[0]
await setting.interaction_check(setting.parent_id, selection)
value = selected.values[0]
data = RankType((value,))
setting.data = data
@@ -117,6 +118,7 @@ class RankConfigUI(ConfigUI):
async def channel_menu(self, selection: discord.Interaction, selected: ChannelSelect):
await selection.response.defer()
setting = self.instances[2]
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
@@ -168,7 +170,7 @@ class RankConfigUI(ConfigUI):
class RankDashboard(DashboardSection):
section_name = _p(
'dash:rank|title',
"Rank Configuration ({commands[configure ranks]})",
"Rank Configuration ({commands[admin config ranks]})",
)
_option_name = _p(
"dash:rank|dropdown|placeholder",

View File

@@ -430,7 +430,7 @@ class RankOverviewUI(MessageUI):
"Ranks are determined by *all-time* statistics.\n"
"To reward ranks from a later time (e.g. to have monthly/quarterly/yearly ranks) "
"set the `season_start` with {stats_cmd}"
)).format(stats_cmd=self.bot.core.mention_cmd('configure statistics'))
)).format(stats_cmd=self.bot.core.mention_cmd('admin config statistics'))
if self.rank_type is RankType.VOICE:
addendum = t(_p(
'ui:rank_overview|embed|field:note|value|voice_addendum',

View File

@@ -16,7 +16,7 @@ from utils.ui import Confirm
from constants import MAX_COINS
from core.data import CoreData
from wards import low_management_ward
from wards import high_management_ward
from . import babel, logger
from .data import RoomData
@@ -47,7 +47,7 @@ class RoomCog(LionCog):
self.bot.core.guild_config.register_model_setting(setting)
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.admin_config_group)
if self.bot.is_ready():
await self.initialise()
@@ -414,7 +414,7 @@ class RoomCog(LionCog):
t(_p(
'cmd:room_rent|error:not_setup',
"The private room system has not been set up! "
"A private room category needs to be set first with `/configure rooms`."
"A private room category needs to be set first with `/admin config rooms`."
))
), ephemeral=True
)
@@ -987,8 +987,7 @@ class RoomCog(LionCog):
@appcmds.describe(
**{setting.setting_id: setting._desc for setting in RoomSettings.model_settings}
)
@appcmds.default_permissions(manage_guild=True)
@low_management_ward
@high_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,

View File

@@ -5,6 +5,7 @@ from settings.setting_types import ChannelSetting, IntegerSetting, BoolSetting
from meta import conf
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward, high_management_iward
from . import babel
@@ -15,7 +16,8 @@ class RoomSettings(SettingGroup):
class Category(ModelData, ChannelSetting):
setting_id = 'rooms_category'
_event = 'guildset_rooms_category'
_set_cmd = 'configure rooms'
_set_cmd = 'admin config rooms'
_write_ward = high_management_iward
_display_name = _p(
'guildset:room_category', "rooms_category"
@@ -70,7 +72,8 @@ class RoomSettings(SettingGroup):
class Rent(ModelData, IntegerSetting):
setting_id = 'rooms_price'
_event = 'guildset_rooms_price'
_set_cmd = 'configure rooms'
_set_cmd = 'admin config rooms'
_write_ward = low_management_iward
_display_name = _p(
'guildset:rooms_price', "room_rent"
@@ -107,7 +110,8 @@ class RoomSettings(SettingGroup):
class MemberLimit(ModelData, IntegerSetting):
setting_id = 'rooms_slots'
_event = 'guildset_rooms_slots'
_set_cmd = 'configure rooms'
_set_cmd = 'admin config rooms'
_write_ward = low_management_iward
_display_name = _p('guildset:rooms_slots', "room_member_cap")
_desc = _p(
@@ -141,7 +145,8 @@ class RoomSettings(SettingGroup):
class Visible(ModelData, BoolSetting):
setting_id = 'rooms_visible'
_event = 'guildset_rooms_visible'
_set_cmd = 'configure rooms'
_set_cmd = 'admin config rooms'
_write_ward = high_management_iward
_display_name = _p('guildset:rooms_visible', "room_visibility")
_desc = _p(

View File

@@ -29,6 +29,7 @@ class RoomSettingUI(ConfigUI):
async def category_menu(self, selection: discord.Interaction, selected: ChannelSelect):
await selection.response.defer()
setting = self.instances[0]
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
@@ -42,6 +43,7 @@ class RoomSettingUI(ConfigUI):
async def visible_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer()
setting = next(inst for inst in self.instances if inst.setting_id == RoomSettings.Visible.setting_id)
await setting.interaction_check(setting.parent_id, press)
setting.value = not setting.value
await setting.write()
@@ -95,7 +97,7 @@ class RoomSettingUI(ConfigUI):
class RoomDashboard(DashboardSection):
section_name = _p(
'dash:rooms|title',
"Private Room Configuration ({commands[configure rooms]})"
"Private Room Configuration ({commands[admin config rooms]})"
)
_option_name = _p(
"dash:economy|dropdown|placeholder",

View File

@@ -17,7 +17,7 @@ from meta.monitor import ComponentMonitor, ComponentStatus, StatusLevel
from utils.lib import utc_now, error_embed
from utils.ui import Confirm
from utils.data import MULTIVALUE_IN, MEMBERS
from wards import low_management_ward
from wards import high_management_ward
from core.data import CoreData
from data import NULL, ORDER
from modules.economy.data import TransactionType
@@ -118,7 +118,7 @@ class ScheduleCog(LionCog):
await self.settings.SessionChannels.setup(self.bot)
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.admin_config_group)
if self.bot.is_ready():
await self.initialise()
@@ -1090,7 +1090,7 @@ class ScheduleCog(LionCog):
@appcmds.describe(
**{param: option._desc for param, option in config_params.items()}
)
@low_management_ward
@high_management_ward
async def configure_schedule_command(self, ctx: LionContext,
session_lobby: Optional[discord.TextChannel | discord.VoiceChannel] = None,
session_room: Optional[discord.VoiceChannel] = None,

View File

@@ -11,6 +11,7 @@ from meta import conf
from meta.errors import UserInputError
from meta.sharding import THIS_SHARD
from meta.logger import log_wrap
from wards import low_management_iward, high_management_iward
from babel.translator import ctx_translator
@@ -63,7 +64,8 @@ class ScheduleSettings(SettingGroup):
class SessionLobby(ModelData, ChannelSetting):
setting_id = 'session_lobby'
_event = 'guildset_session_lobby'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = high_management_iward
_display_name = _p('guildset:session_lobby', "session_lobby")
_desc = _p(
@@ -119,7 +121,8 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class SessionRoom(ModelData, ChannelSetting):
setting_id = 'session_room'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = high_management_iward
_display_name = _p('guildset:session_room', "session_room")
_desc = _p(
@@ -163,6 +166,7 @@ class ScheduleSettings(SettingGroup):
class SessionChannels(ListData, ChannelListSetting):
setting_id = 'session_channels'
_write_ward = high_management_iward
_display_name = _p('guildset:session_channels', "session_channels")
_desc = _p(
@@ -238,7 +242,8 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class ScheduleCost(ModelData, CoinSetting):
setting_id = 'schedule_cost'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = low_management_iward
_display_name = _p('guildset:schedule_cost', "schedule_cost")
_desc = _p(
@@ -283,7 +288,8 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class AttendanceReward(ModelData, CoinSetting):
setting_id = 'attendance_reward'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = low_management_iward
_display_name = _p('guildset:attendance_reward', "attendance_reward")
_desc = _p(
@@ -327,7 +333,8 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class AttendanceBonus(ModelData, CoinSetting):
setting_id = 'attendance_bonus'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = low_management_iward
_display_name = _p('guildset:attendance_bonus', "group_attendance_bonus")
_desc = _p(
@@ -370,7 +377,8 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class MinAttendance(ModelData, IntegerSetting):
setting_id = 'min_attendance'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = low_management_iward
_display_name = _p('guildset:min_attendance', "min_attendance")
_desc = _p(
@@ -437,8 +445,9 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class BlacklistRole(ModelData, RoleSetting):
setting_id = 'schedule_blacklist_role'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_event = 'guildset_schedule_blacklist_role'
_write_ward = high_management_iward
_display_name = _p('guildset:schedule_blacklist_role', "schedule_blacklist_role")
_desc = _p(
@@ -495,7 +504,8 @@ class ScheduleSettings(SettingGroup):
@ScheduleConfig.register_model_setting
class BlacklistAfter(ModelData, IntegerSetting):
setting_id = 'schedule_blacklist_after'
_set_cmd = 'configure schedule'
_set_cmd = 'admin config schedule'
_write_ward = low_management_iward
_display_name = _p('guildset:schedule_blacklist_after', "schedule_blacklist_after")
_desc = _p(

View File

@@ -78,6 +78,7 @@ class ScheduleSettingUI(ConfigUI):
# TODO: Setting value checks
await selection.response.defer()
setting = self.get_instance(ScheduleSettings.SessionLobby)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
@@ -95,6 +96,7 @@ class ScheduleSettingUI(ConfigUI):
async def room_menu(self, selection: discord.Interaction, selected: ChannelSelect):
await selection.response.defer()
setting = self.get_instance(ScheduleSettings.SessionRoom)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
await setting.write()
@@ -113,6 +115,7 @@ class ScheduleSettingUI(ConfigUI):
# TODO: Consider XORing input
await selection.response.defer()
setting = self.get_instance(ScheduleSettings.SessionChannels)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
@@ -158,6 +161,7 @@ class ScheduleSettingUI(ConfigUI):
async def blacklist_role_menu(self, selection: discord.Interaction, selected: RoleSelect):
await selection.response.defer()
setting = self.get_instance(ScheduleSettings.BlacklistRole)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
# TODO: Warning for insufficient permissions?
await setting.write()
@@ -227,7 +231,7 @@ class ScheduleSettingUI(ConfigUI):
class ScheduleDashboard(DashboardSection):
section_name = _p(
'dash:schedule|title',
"Scheduled Session Configuration ({commands[configure schedule]})"
"Scheduled Session Configuration ({commands[admin config schedule]})"
)
_option_name = _p(
"dash:schedule|dropdown|placeholder",
@@ -248,7 +252,7 @@ class ScheduleDashboard(DashboardSection):
page.add_field(
name=t(_p(
'dash:schedule|section:schedule_channels|name',
"Scheduled Session Channels ({commands[configure schedule]})",
"Scheduled Session Channels ({commands[admin config schedule]})",
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
@@ -258,7 +262,7 @@ class ScheduleDashboard(DashboardSection):
page.add_field(
name=t(_p(
'dash:schedule|section:schedule_rewards|name',
"Scheduled Session Rewards ({commands[configure schedule]})",
"Scheduled Session Rewards ({commands[admin config schedule]})",
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
@@ -268,7 +272,7 @@ class ScheduleDashboard(DashboardSection):
page.add_field(
name=t(_p(
'dash:schedule|section:schedule_blacklist|name',
"Scheduled Session Blacklist ({commands[configure schedule]})",
"Scheduled Session Blacklist ({commands[admin config schedule]})",
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False

View File

@@ -12,7 +12,7 @@ from core.lion_guild import VoiceMode
from utils.lib import error_embed
from utils.ui import LeoUI, AButton, utc_now
from gui.base import CardMode
from wards import low_management_ward
from wards import high_management_ward
from . import babel
from .data import StatsData
@@ -41,7 +41,7 @@ class StatsCog(LionCog):
self.bot.core.guild_config.register_setting(self.settings.UnrankedRoles)
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.admin_config_group)
@cmds.hybrid_command(
name=_p('cmd:me', "me"),
@@ -204,8 +204,7 @@ class StatsCog(LionCog):
"Time from which to start counting activity for rank badges and season leaderboards. (YYYY-MM-DD)"
)
)
@appcmds.default_permissions(manage_guild=True)
@low_management_ward
@high_management_ward
async def configure_statistics_cmd(self, ctx: LionContext,
season_start: Optional[str] = None):
t = self.bot.translator.t

View File

@@ -21,6 +21,7 @@ from utils.lib import MessageArgs
from core.data import CoreData
from core.lion_guild import VoiceMode
from babel.translator import ctx_translator
from wards import low_management_iward, high_management_iward
from . import babel
from .data import StatsData, StatisticType
@@ -83,7 +84,8 @@ class StatisticsSettings(SettingGroup):
Time is assumed to be in set guild timezone (although supports +00 syntax)
"""
setting_id = 'season_start'
_set_cmd = 'configure statistics'
_set_cmd = 'admin config statistics'
_write_ward = high_management_iward
_display_name = _p('guildset:season_start', "season_start")
_desc = _p(
@@ -155,6 +157,7 @@ class StatisticsSettings(SettingGroup):
List of roles not displayed on the leaderboard
"""
setting_id = 'unranked_roles'
_write_ward = high_management_iward
_display_name = _p('guildset:unranked_roles', "unranked_roles")
_desc = _p(
@@ -211,6 +214,7 @@ class StatisticsSettings(SettingGroup):
Default is determined by current guild mode
"""
setting_id = 'visible_stats'
_write_ward = high_management_iward
_setting = StatTypeSetting
@@ -263,6 +267,7 @@ class StatisticsSettings(SettingGroup):
Which of the three stats to display by default
"""
setting_id = 'default_stat'
_write_ward = high_management_iward
_display_name = _p('guildset:default_stat', "default_stat")
_desc = _p(
@@ -294,6 +299,7 @@ class StatisticsConfigUI(ConfigUI):
"""
await selection.response.defer(thinking=True)
setting = self.instances[1]
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
# Don't need to refresh due to instance hooks
@@ -314,6 +320,7 @@ class StatisticsConfigUI(ConfigUI):
"""
await selection.response.defer(thinking=True)
setting = self.instances[2]
await setting.interaction_check(setting.parent_id, selection)
data = [StatisticType((value,)) for value in selected.values]
setting.data = data
await setting.write()
@@ -405,7 +412,7 @@ class StatisticsConfigUI(ConfigUI):
class StatisticsDashboard(DashboardSection):
section_name = _p(
'dash:stats|title',
"Activity Statistics Configuration ({commands[configure statistics]})"
"Activity Statistics Configuration ({commands[admin config statistics]})"
)
_option_name = _p(
"dash:stats|dropdown|placeholder",

View File

@@ -139,7 +139,7 @@ class TasklistCog(LionCog):
self.bot.add_view(TasklistCaller(self.bot))
configcog = self.bot.get_cog('ConfigCog')
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
@LionCog.listener('on_tasks_completed')
@log_wrap(action="reward tasks completed")
@@ -984,7 +984,6 @@ class TasklistCog(LionCog):
reward=TasklistSettings.task_reward._desc,
reward_limit=TasklistSettings.task_reward_limit._desc
)
@appcmds.default_permissions(manage_guild=True)
@low_management_ward
async def configure_tasklist_cmd(self, ctx: LionContext,
reward: Optional[int] = None,

View File

@@ -13,6 +13,7 @@ from utils.lib import tabulate
from utils.ui import LeoUI, FastModal, error_handler_for, ModalRetryUI, DashboardSection
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward, high_management_iward
from . import babel
from .data import TasklistData
@@ -28,7 +29,8 @@ class TasklistSettings(SettingGroup):
Exposed via `/configure tasklist`, and the standard configuration interface.
"""
setting_id = 'task_reward'
_set_cmd = 'configure tasklist'
_set_cmd = 'config tasklist'
_write_ward = low_management_iward
_display_name = _p('guildset:task_reward', "task_reward")
_desc = _p(
@@ -68,7 +70,8 @@ class TasklistSettings(SettingGroup):
class task_reward_limit(ModelData, IntegerSetting):
setting_id = 'task_reward_limit'
_set_cmd = 'configure tasklist'
_set_cmd = 'config tasklist'
_write_ward = low_management_iward
_display_name = _p('guildset:task_reward_limit', "task_reward_limit")
_desc = _p(
@@ -109,6 +112,7 @@ class TasklistSettings(SettingGroup):
class tasklist_channels(ListData, ChannelListSetting):
setting_id = 'tasklist_channels'
_write_ward = low_management_iward
_display_name = _p('guildset:tasklist_channels', "tasklist_channels")
_desc = _p(
@@ -317,7 +321,7 @@ class TasklistConfigUI(LeoUI):
class TasklistDashboard(DashboardSection):
section_name = _p('dash:tasklist|name', "Tasklist Configuration ({commands[configure tasklist]})")
section_name = _p('dash:tasklist|name', "Tasklist Configuration ({commands[config tasklist]})")
_option_name = _p(
"dash:tasklist|dropdown|placeholder",
"Tasklist Options Panel"

View File

@@ -57,7 +57,7 @@ class VideoCog(LionCog):
"Could not load ConfigCog. VideoCog configuration will not crossload."
)
else:
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.admin_config_group)
if self.bot.is_ready():
await self.initialise()
@@ -522,7 +522,7 @@ class VideoCog(LionCog):
video_blacklist_durations=VideoSettings.VideoBlacklistDurations._desc,
video_grace_period=VideoSettings.VideoGracePeriod._desc,
)
@low_management_ward
@high_management_ward
async def configure_video(self, ctx: LionContext,
video_blacklist: Optional[discord.Role] = None,
video_blacklist_durations: Optional[str] = None,
@@ -572,4 +572,3 @@ class VideoCog(LionCog):
ui = VideoSettingUI(self.bot, ctx.guild.id, ctx.channel.id)
await ui.run(ctx.interaction)
await ui.wait()

View File

@@ -14,6 +14,7 @@ from meta.sharding import THIS_SHARD
from meta.logger import log_wrap
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward, high_management_iward
from . import babel, logger
from .data import VideoData
@@ -25,6 +26,7 @@ class VideoSettings(SettingGroup):
class VideoChannels(ListData, ChannelListSetting):
setting_id = "video_channels"
_event = 'guildset_video_channels'
_write_ward = high_management_iward
_display_name = _p('guildset:video_channels', "video_channels")
_desc = _p(
@@ -101,6 +103,7 @@ class VideoSettings(SettingGroup):
class VideoBlacklist(ModelData, RoleSetting):
setting_id = "video_blacklist"
_event = 'guildset_video_blacklist'
_write_ward = high_management_iward
_display_name = _p('guildset:video_blacklist', "video_blacklist")
_desc = _p(
@@ -158,6 +161,7 @@ class VideoSettings(SettingGroup):
class VideoBlacklistDurations(ListData, ListSetting, InteractiveSetting):
setting_id = 'video_durations'
_setting = DurationSetting
_write_ward = high_management_iward
_display_name = _p('guildset:video_durations', "video_blacklist_durations")
_desc = _p(
@@ -217,6 +221,7 @@ class VideoSettings(SettingGroup):
class VideoGracePeriod(ModelData, DurationSetting):
setting_id = "video_grace_period"
_event = 'guildset_video_grace_period'
_write_ward = high_management_iward
_display_name = _p('guildset:video_grace_period', "video_grace_period")
_desc = _p(
@@ -252,6 +257,7 @@ class VideoSettings(SettingGroup):
class VideoExempt(ListData, RoleListSetting):
setting_id = "video_exempt"
_event = 'guildset_video_exempt'
_write_ward = high_management_iward
_display_name = _p('guildset:video_exempt', "video_exempt")
_desc = _p(

View File

@@ -45,6 +45,7 @@ class VideoSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(VideoSettings.VideoChannels)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
await selection.delete_original_response()
@@ -70,6 +71,7 @@ class VideoSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(VideoSettings.VideoExempt)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
await selection.delete_original_response()
@@ -95,6 +97,7 @@ class VideoSettingUI(ConfigUI):
await selection.response.defer(thinking=True, ephemeral=True)
setting = self.get_instance(VideoSettings.VideoBlacklist)
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values[0] if selected.values else None
if setting.value:
await equippable_role(self.bot, setting.value, selection.user)
@@ -153,7 +156,7 @@ class VideoSettingUI(ConfigUI):
class VideoDashboard(DashboardSection):
section_name = _p(
"dash:video|title",
"Video Channel Settings ({commands[configure video_channels]})"
"Video Channel Settings ({commands[admin config video_channels]})"
)
_option_name = _p(
"dash:video|option|name",

View File

@@ -7,6 +7,7 @@ from discord import ui
from discord.ui.button import ButtonStyle, Button, button
from discord.ui.modal import Modal
from discord.ui.text_input import TextInput
from meta.errors import UserInputError
from utils.lib import tabulate, recover_context
from utils.ui import FastModal
@@ -192,6 +193,9 @@ class InteractiveSetting(BaseSetting[ParentID, SettingData, SettingValue]):
# Event handlers should be of the form Callable[ParentID, SettingData]
_event: Optional[str] = None
# Interaction ward that should be validated via interaction_check
_write_ward: Optional[Callable[[discord.Interaction], Coroutine[Any, Any, bool]]] = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -488,6 +492,16 @@ class InteractiveSetting(BaseSetting[ParentID, SettingData, SettingValue]):
"""
pass
@classmethod
async def interaction_check(cls, parent_id, interaction: discord.Interaction, **kwargs):
if cls._write_ward is not None and not await cls._write_ward(interaction):
# TODO: Combine the check system so we can do customised errors here
t = ctx_translator.get().t
raise UserInputError(t(_p(
'setting|interaction_check|error',
"You do not have sufficient permissions to do this!"
)))
"""
command callback for set command?

View File

@@ -16,7 +16,7 @@ from meta.app import appname
from meta.monitor import ComponentMonitor, ComponentStatus, StatusLevel
from utils.lib import utc_now, error_embed
from wards import low_management_ward, sys_admin_ward
from wards import low_management_ward, sys_admin_ward, low_management_iward
from . import babel, logger
from .data import TextTrackerData
@@ -116,7 +116,7 @@ class TextTrackerCog(LionCog):
"Attempting to load the TextTrackerCog before ConfigCog! Failed to crossload configuration group."
)
else:
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
if self.bot.is_ready():
await self.initialise()
@@ -318,7 +318,6 @@ class TextTrackerCog(LionCog):
xp_per_period=TextTrackerSettings.XPPerPeriod._desc,
word_xp=TextTrackerSettings.WordXP._desc,
)
@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,

View File

@@ -11,6 +11,7 @@ from meta.sharding import THIS_SHARD
from meta.logger import log_wrap
from core.data import CoreData
from babel.translator import ctx_translator
from wards import low_management_iward
from . import babel, logger
from .data import TextTrackerData
@@ -28,7 +29,8 @@ class TextTrackerSettings(SettingGroup):
"""
class XPPerPeriod(ModelData, IntegerSetting):
setting_id = 'xp_per_period'
_set_cmd = 'configure message_exp'
_set_cmd = 'config message_exp'
_write_ward = low_management_iward
_display_name = _p('guildset:xp_per_period', "xp_per_5min")
_desc = _p(
@@ -60,7 +62,8 @@ class TextTrackerSettings(SettingGroup):
class WordXP(ModelData, IntegerSetting):
setting_id = 'word_xp'
_set_cmd = 'configure message_exp'
_set_cmd = 'config message_exp'
_write_ward = low_management_iward
_display_name = _p('guildset:word_xp', "xp_per_100words")
_desc = _p(
@@ -91,6 +94,7 @@ class TextTrackerSettings(SettingGroup):
class UntrackedTextChannels(ListData, ChannelListSetting):
setting_id = 'untracked_text_channels'
_write_ward = low_management_iward
_display_name = _p('guildset:untracked_text_channels', "untracked_text_channels")
_desc = _p(

View File

@@ -35,6 +35,7 @@ class TextTrackerConfigUI(ConfigUI):
async def untracked_channels_menu(self, selection: discord.Interaction, selected):
await selection.response.defer()
setting = self.instances[2]
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
@@ -86,7 +87,7 @@ class TextTrackerConfigUI(ConfigUI):
class TextTrackerDashboard(DashboardSection):
section_name = _p(
'dash:text_tracking|title',
"Message XP configuration ({commands[configure message_exp]})",
"Message XP configuration ({commands[config message_exp]})",
)
_option_name = _p(
"dash:text_tracking|dropdown|placeholder",

View File

@@ -133,7 +133,7 @@ class VoiceTrackerCog(LionCog):
"Attempting to load VoiceTrackerCog before ConfigCog! Cannot crossload configuration group."
)
else:
self.crossload_group(self.configure_group, configcog.configure_group)
self.crossload_group(self.configure_group, configcog.config_group)
if self.bot.is_ready():
await self.initialise()
@@ -867,7 +867,6 @@ class VoiceTrackerCog(LionCog):
hourly_live_bonus=VoiceTrackerSettings.HourlyLiveBonus._desc,
daily_voice_cap=VoiceTrackerSettings.DailyVoiceCap._desc,
)
@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

View File

@@ -14,6 +14,7 @@ from meta.sharding import THIS_SHARD
from meta.logger import log_wrap
from utils.lib import MessageArgs
from utils.ui import LeoUI, ConfigUI, DashboardSection
from wards import low_management_iward
from core.data import CoreData
from core.lion_guild import VoiceMode
@@ -35,7 +36,8 @@ class VoiceTrackerSettings(SettingGroup):
class UntrackedChannels(ListData, ChannelListSetting):
setting_id = 'untracked_channels'
_event = 'guildset_untracked_channels'
_set_cmd = 'configure voice_rewards'
_set_cmd = 'config voice_rewards'
_write_ward = low_management_iward
_display_name = _p('guildset:untracked_channels', "untracked_channels")
_desc = _p(
@@ -112,7 +114,8 @@ class VoiceTrackerSettings(SettingGroup):
class HourlyReward(ModelData, IntegerSetting):
setting_id = 'hourly_reward'
_event = 'on_guildset_hourly_reward'
_set_cmd = 'configure voice_rewards'
_set_cmd = 'config voice_rewards'
_write_ward = low_management_iward
_display_name = _p('guildset:hourly_reward', "hourly_reward")
_desc = _p(
@@ -192,7 +195,8 @@ class VoiceTrackerSettings(SettingGroup):
"""
setting_id = 'hourly_live_bonus'
_event = 'on_guildset_hourly_live_bonus'
_set_cmd = 'configure voice_rewards'
_set_cmd = 'config voice_rewards'
_write_ward = low_management_iward
_display_name = _p('guildset:hourly_live_bonus', "hourly_live_bonus")
_desc = _p(
@@ -243,7 +247,8 @@ class VoiceTrackerSettings(SettingGroup):
class DailyVoiceCap(ModelData, DurationSetting):
setting_id = 'daily_voice_cap'
_event = 'on_guildset_daily_voice_cap'
_set_cmd = 'configure voice_rewards'
_set_cmd = 'config voice_rewards'
_write_ward = low_management_iward
_display_name = _p('guildset:daily_voice_cap', "daily_voice_cap")
_desc = _p(
@@ -465,6 +470,7 @@ class VoiceTrackerConfigUI(ConfigUI):
async def untracked_channels_menu(self, selection: discord.Interaction, selected):
await selection.response.defer()
setting = self.instances[3]
await setting.interaction_check(setting.parent_id, selection)
setting.value = selected.values
await setting.write()
@@ -528,7 +534,7 @@ class VoiceTrackerConfigUI(ConfigUI):
class VoiceTrackerDashboard(DashboardSection):
section_name = _p(
'dash:voice_tracker|title',
"Voice Tracker Configuration ({commands[configure voice_rewards]})"
"Voice Tracker Configuration ({commands[config voice_rewards]})"
)
_option_name = _p(
"dash:voice_tracking|dropdown|placeholder",

View File

@@ -126,6 +126,7 @@ class ConfigUI(LeoUI):
new_data = None
else:
# If this raises a UserInputError, it will be caught and the modal retried
await setting.interaction_check(setting.parent_id, interaction)
new_data = await setting._parse_string(setting.parent_id, input_value)
setting.data = new_data
modified.append(setting)