feat(eventlog): Add eventlog setting.
Also refactors the GeneralSettings to use the new style.
This commit is contained in:
@@ -93,3 +93,12 @@ class LionGuild(Timezoned):
|
|||||||
"""
|
"""
|
||||||
if self.data.name != guild.name:
|
if self.data.name != guild.name:
|
||||||
await self.data.update(name=guild.name)
|
await self.data.update(name=guild.name)
|
||||||
|
|
||||||
|
async def _event_log(self, ...):
|
||||||
|
...
|
||||||
|
|
||||||
|
def event_log(self, **kwargs):
|
||||||
|
asyncio.create_task(self._event_log(**kwargs), name='event-log')
|
||||||
|
|
||||||
|
def error_log(self, ...):
|
||||||
|
...
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ babel = LocalBabel('config')
|
|||||||
|
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
from .general import GeneralSettingsCog
|
from .cog import GuildConfigCog
|
||||||
from .cog import DashCog
|
|
||||||
|
|
||||||
await bot.add_cog(GeneralSettingsCog(bot))
|
await bot.add_cog(GuildConfigCog(bot))
|
||||||
await bot.add_cog(DashCog(bot))
|
|
||||||
|
|||||||
@@ -3,22 +3,31 @@ from discord import app_commands as appcmds
|
|||||||
from discord.ext import commands as cmds
|
from discord.ext import commands as cmds
|
||||||
|
|
||||||
from meta import LionBot, LionContext, LionCog
|
from meta import LionBot, LionContext, LionCog
|
||||||
|
from wards import low_management_ward
|
||||||
|
|
||||||
from . import babel
|
from . import babel
|
||||||
from .dashboard import GuildDashboard
|
from .dashboard import GuildDashboard
|
||||||
|
from .settings import GeneralSettings
|
||||||
|
from .settingui import GeneralSettingUI
|
||||||
|
|
||||||
_p = babel._p
|
_p = babel._p
|
||||||
|
|
||||||
|
|
||||||
class DashCog(LionCog):
|
class GuildConfigCog(LionCog):
|
||||||
|
depends = {'CoreCog'}
|
||||||
|
|
||||||
def __init__(self, bot: LionBot):
|
def __init__(self, bot: LionBot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
self.settings = GeneralSettings()
|
||||||
|
|
||||||
async def cog_load(self):
|
async def cog_load(self):
|
||||||
...
|
self.bot.core.guild_config.register_model_setting(GeneralSettings.Timezone)
|
||||||
|
self.bot.core.guild_config.register_model_setting(GeneralSettings.Eventlog)
|
||||||
|
|
||||||
async def cog_unload(self):
|
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)
|
||||||
|
|
||||||
@cmds.hybrid_command(
|
@cmds.hybrid_command(
|
||||||
name="dashboard",
|
name="dashboard",
|
||||||
@@ -30,3 +39,72 @@ class DashCog(LionCog):
|
|||||||
ui = GuildDashboard(self.bot, ctx.guild, ctx.author.id, ctx.channel.id)
|
ui = GuildDashboard(self.bot, ctx.guild, ctx.author.id, ctx.channel.id)
|
||||||
await ui.run(ctx.interaction)
|
await ui.run(ctx.interaction)
|
||||||
await ui.wait()
|
await ui.wait()
|
||||||
|
|
||||||
|
@cmds.hybrid_group("configure", with_app_command=False)
|
||||||
|
async def configure_group(self, ctx: LionContext):
|
||||||
|
# Placeholder configure group command.
|
||||||
|
...
|
||||||
|
|
||||||
|
@configure_group.command(
|
||||||
|
name=_p('cmd:configure_general', "general"),
|
||||||
|
description=_p('cmd:configure_general|desc', "General configuration panel")
|
||||||
|
)
|
||||||
|
@appcmds.rename(
|
||||||
|
timezone=GeneralSettings.Timezone._display_name,
|
||||||
|
event_log=GeneralSettings.EventLog._display_name,
|
||||||
|
)
|
||||||
|
@appcmds.describe(
|
||||||
|
timezone=GeneralSettings.Timezone._desc,
|
||||||
|
event_log=GeneralSettings.EventLog._display_name,
|
||||||
|
)
|
||||||
|
@appcmds.guild_only()
|
||||||
|
@appcmds.default_permissions(manage_guild=True)
|
||||||
|
@low_management_ward
|
||||||
|
async def cmd_configure_general(self, ctx: LionContext,
|
||||||
|
timezone: Optional[str] = None,
|
||||||
|
event_log: Optional[discord.TextChannel] = None,
|
||||||
|
):
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
# Typechecker guards because they don't understand the check ward
|
||||||
|
if not ctx.guild:
|
||||||
|
return
|
||||||
|
if not ctx.interaction:
|
||||||
|
return
|
||||||
|
await ctx.interaction.response.defer(thinking=True)
|
||||||
|
|
||||||
|
# ----- Configuration -----
|
||||||
|
@LionCog.placeholder_group
|
||||||
|
@cmds.hybrid_group("configure", with_app_command=False)
|
||||||
|
async def configure_group(self, ctx: LionContext):
|
||||||
|
# Placeholder configure group command.
|
||||||
|
...
|
||||||
|
|
||||||
|
@configure_group.command(
|
||||||
|
name=_p('cmd:configure_general', "general"),
|
||||||
|
description=_p('cmd:configure_general|desc', "General configuration panel")
|
||||||
|
)
|
||||||
|
@appcmds.rename(
|
||||||
|
timezone=GeneralSettings.Timezone._display_name,
|
||||||
|
event_log=GeneralSettings.EventLog._display_name,
|
||||||
|
)
|
||||||
|
@appcmds.describe(
|
||||||
|
timezone=GeneralSettings.Timezone._desc,
|
||||||
|
event_log=GeneralSettings.EventLog._display_name,
|
||||||
|
)
|
||||||
|
@appcmds.guild_only()
|
||||||
|
@appcmds.default_permissions(manage_guild=True)
|
||||||
|
@low_management_ward
|
||||||
|
async def cmd_configure_general(self, ctx: LionContext,
|
||||||
|
timezone: Optional[str] = None,
|
||||||
|
event_log: Optional[discord.TextChannel] = None,
|
||||||
|
):
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
# Typechecker guards because they don't understand the check ward
|
||||||
|
if not ctx.guild:
|
||||||
|
return
|
||||||
|
if not ctx.interaction:
|
||||||
|
return
|
||||||
|
await ctx.interaction.response.defer(thinking=True)
|
||||||
|
# TODO
|
||||||
|
|||||||
@@ -26,48 +26,6 @@ from . import babel
|
|||||||
_p = babel._p
|
_p = babel._p
|
||||||
|
|
||||||
|
|
||||||
class GeneralSettings(SettingGroup):
|
|
||||||
class Timezone(ModelData, TimezoneSetting):
|
|
||||||
"""
|
|
||||||
Guild timezone configuration.
|
|
||||||
|
|
||||||
Exposed via `/configure 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 = 'guild_setting_update_timezone'
|
|
||||||
|
|
||||||
_display_name = _p('guildset:timezone', "timezone")
|
|
||||||
_desc = _p(
|
|
||||||
'guildset:timezone|desc',
|
|
||||||
"Guild timezone for statistics display."
|
|
||||||
)
|
|
||||||
_long_desc = _p(
|
|
||||||
'guildset:timezone|long_desc',
|
|
||||||
"Guild-wide timezone. "
|
|
||||||
"Used to determine start of the day for the leaderboards, "
|
|
||||||
"and as the default statistics timezone for members who have not set one."
|
|
||||||
)
|
|
||||||
_default = 'UTC'
|
|
||||||
|
|
||||||
_model = CoreData.Guild
|
|
||||||
_column = CoreData.Guild.timezone.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def update_message(self):
|
|
||||||
t = ctx_translator.get().t
|
|
||||||
return t(_p(
|
|
||||||
'guildset:timezone|response',
|
|
||||||
"The guild timezone has been set to `{timezone}`."
|
|
||||||
)).format(timezone=self.data)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def set_str(self):
|
|
||||||
bot = ctx_bot.get()
|
|
||||||
return bot.core.mention_cmd('configure general') if bot else None
|
|
||||||
|
|
||||||
|
|
||||||
class GeneralSettingsCog(LionCog):
|
class GeneralSettingsCog(LionCog):
|
||||||
depends = {'CoreCog'}
|
depends = {'CoreCog'}
|
||||||
|
|
||||||
@@ -95,16 +53,20 @@ class GeneralSettingsCog(LionCog):
|
|||||||
description=_p('cmd:configure_general|desc', "General configuration panel")
|
description=_p('cmd:configure_general|desc', "General configuration panel")
|
||||||
)
|
)
|
||||||
@appcmds.rename(
|
@appcmds.rename(
|
||||||
timezone=GeneralSettings.Timezone._display_name
|
timezone=GeneralSettings.Timezone._display_name,
|
||||||
|
event_log=GeneralSettings.EventLog._display_name,
|
||||||
)
|
)
|
||||||
@appcmds.describe(
|
@appcmds.describe(
|
||||||
timezone=GeneralSettings.Timezone._desc
|
timezone=GeneralSettings.Timezone._desc,
|
||||||
|
event_log=GeneralSettings.EventLog._display_name,
|
||||||
)
|
)
|
||||||
@appcmds.guild_only()
|
@appcmds.guild_only()
|
||||||
@appcmds.default_permissions(manage_guild=True)
|
@appcmds.default_permissions(manage_guild=True)
|
||||||
@low_management_ward
|
@low_management_ward
|
||||||
async def cmd_configure_general(self, ctx: LionContext,
|
async def cmd_configure_general(self, ctx: LionContext,
|
||||||
timezone: Optional[str] = None):
|
timezone: Optional[str] = None,
|
||||||
|
event_log: Optional[discord.TextChannel] = None,
|
||||||
|
):
|
||||||
t = self.bot.translator.t
|
t = self.bot.translator.t
|
||||||
|
|
||||||
# Typechecker guards because they don't understand the check ward
|
# Typechecker guards because they don't understand the check ward
|
||||||
|
|||||||
79
src/modules/config/settings.py
Normal file
79
src/modules/config/settings.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
from settings import ModelData
|
||||||
|
from settings.setting_types import TimezoneSetting, ChannelSetting
|
||||||
|
from settings.groups import SettingGroup
|
||||||
|
|
||||||
|
from core.data import CoreData
|
||||||
|
from babel.translator import ctx_translator
|
||||||
|
|
||||||
|
from . import babel
|
||||||
|
|
||||||
|
_p = babel._p
|
||||||
|
|
||||||
|
|
||||||
|
class GeneralSettings(SettingGroup):
|
||||||
|
class Timezone(ModelData, TimezoneSetting):
|
||||||
|
"""
|
||||||
|
Guild timezone configuration.
|
||||||
|
|
||||||
|
Exposed via `/configure 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 = 'guild_setting_update_timezone'
|
||||||
|
|
||||||
|
_display_name = _p('guildset:timezone', "timezone")
|
||||||
|
_desc = _p(
|
||||||
|
'guildset:timezone|desc',
|
||||||
|
"Guild timezone for statistics display."
|
||||||
|
)
|
||||||
|
_long_desc = _p(
|
||||||
|
'guildset:timezone|long_desc',
|
||||||
|
"Guild-wide timezone. "
|
||||||
|
"Used to determine start of the day for the leaderboards, "
|
||||||
|
"and as the default statistics timezone for members who have not set one."
|
||||||
|
)
|
||||||
|
_default = 'UTC'
|
||||||
|
|
||||||
|
_model = CoreData.Guild
|
||||||
|
_column = CoreData.Guild.timezone.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def update_message(self):
|
||||||
|
t = ctx_translator.get().t
|
||||||
|
return t(_p(
|
||||||
|
'guildset:timezone|response',
|
||||||
|
"The guild timezone has been set to `{timezone}`."
|
||||||
|
)).format(timezone=self.data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def set_str(self):
|
||||||
|
bot = ctx_bot.get()
|
||||||
|
return bot.core.mention_cmd('configure general') if bot else None
|
||||||
|
|
||||||
|
class EventLog(ModelData, ChannelSetting):
|
||||||
|
"""
|
||||||
|
Guild event log channel.
|
||||||
|
"""
|
||||||
|
setting_id = 'eventlog'
|
||||||
|
_event = 'guildset_eventlog'
|
||||||
|
|
||||||
|
_display_name = _p('guildset:eventlog', "event_log")
|
||||||
|
_desc = _p(
|
||||||
|
'guildset:eventlog|desc',
|
||||||
|
"Channel to which to log server events, such as voice sessions and equipped roles."
|
||||||
|
)
|
||||||
|
# TODO: Reword
|
||||||
|
_long_desc = _p(
|
||||||
|
'guildset:eventlog|long_desc',
|
||||||
|
"An audit log for my own systems, "
|
||||||
|
"I will send most significant actions and events that occur through my interface "
|
||||||
|
"to this channel. For example, this includes:\n"
|
||||||
|
"- Member voice activity\n"
|
||||||
|
"- Roles equipped and expiring from rolemenus\n"
|
||||||
|
"- Privated rooms rented and expiring\n"
|
||||||
|
"- Activity ranks earned\n"
|
||||||
|
"I must have the 'Manage Webhooks' permission in this channel."
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO: Updatestr
|
||||||
0
src/modules/config/settingsui.py
Normal file
0
src/modules/config/settingsui.py
Normal file
107
src/modules/config/settingui.py
Normal file
107
src/modules/config/settingui.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import asyncio
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from discord.ui.select import select, ChannelSelect
|
||||||
|
|
||||||
|
from meta import LionBot
|
||||||
|
|
||||||
|
from utils.ui import ConfigUI, DashboardSection
|
||||||
|
from utils.lib import MessageArgs
|
||||||
|
|
||||||
|
from . import babel
|
||||||
|
from .settings import GeneralSettings
|
||||||
|
|
||||||
|
|
||||||
|
_p = babel._p
|
||||||
|
|
||||||
|
|
||||||
|
class GeneralSettingUI(ConfigUI):
|
||||||
|
setting_classes = (
|
||||||
|
GeneralSettings.Timezone,
|
||||||
|
GeneralSettings.Eventlog,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, bot: LionBot, guildid: int, channelid: int, **kwargs):
|
||||||
|
self.settings = bot.get_cog('GeneralSettingsCog').settings
|
||||||
|
super().__init__(bot, guildid, channelid, **kwargs)
|
||||||
|
|
||||||
|
# ----- UI Components -----
|
||||||
|
# Event log
|
||||||
|
@select(
|
||||||
|
cls=ChannelSelect,
|
||||||
|
channel_types=[discord.ChannelType.text, discord.ChannelType.voice],
|
||||||
|
placeholder='EVENT_LOG_PLACEHOLDER',
|
||||||
|
min_values=0, max_values=1,
|
||||||
|
)
|
||||||
|
async def eventlog_menu(self, selection: discord.Interaction, selected: ChannelSelect):
|
||||||
|
"""
|
||||||
|
Single channel selector for the event log.
|
||||||
|
"""
|
||||||
|
await selection.response.defer(thinking=True, ephemeral=True)
|
||||||
|
|
||||||
|
setting = self.get_instance(GeneralSettings.Eventlog)
|
||||||
|
|
||||||
|
value = selected.values[0] if selected.values else None
|
||||||
|
if issue := (await setting.check_value(value)):
|
||||||
|
raise UserInputError(issue)
|
||||||
|
|
||||||
|
setting.value = value
|
||||||
|
await setting.write()
|
||||||
|
await selection.delete_original_response()
|
||||||
|
|
||||||
|
async def eventlog_menu_refresh(self):
|
||||||
|
menu = self.eventlog_menu
|
||||||
|
t = self.bot.translator.t
|
||||||
|
menu.placeholder = t(_p(
|
||||||
|
'ui:general_config|menu:event_log|placeholder',
|
||||||
|
"Select Event Log"
|
||||||
|
))
|
||||||
|
|
||||||
|
# ----- UI Flow -----
|
||||||
|
async def make_message(self) -> MessageArgs:
|
||||||
|
t = self.bot.translator.t
|
||||||
|
title = t(_p(
|
||||||
|
'ui:general_config|embed:title',
|
||||||
|
"General Configuration"
|
||||||
|
))
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=title,
|
||||||
|
colour=discord.Colour.orange()
|
||||||
|
)
|
||||||
|
for setting in self.instances:
|
||||||
|
embed.add_field(**setting.embed_field, inline=False)
|
||||||
|
|
||||||
|
return MessageArgs(embed=embed)
|
||||||
|
|
||||||
|
async def reload(self):
|
||||||
|
self.instances = [
|
||||||
|
await setting.get(self.guildid)
|
||||||
|
for setting in self.setting_classes
|
||||||
|
]
|
||||||
|
|
||||||
|
async def refresh_components(self):
|
||||||
|
to_refresh = (
|
||||||
|
self.edit_button_refresh(),
|
||||||
|
self.close_button_refresh(),
|
||||||
|
self.reset_button_refresh(),
|
||||||
|
self.eventlog_menu_refresh(),
|
||||||
|
)
|
||||||
|
await asyncio.gather(*to_refresh)
|
||||||
|
|
||||||
|
self.set_layout(
|
||||||
|
(self.eventlog_menu,),
|
||||||
|
(self.edit_button, self.reset_button, self.close_button,),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class GeneralDashboard(DashboardSection):
|
||||||
|
section_name = _p(
|
||||||
|
"dash:general|title",
|
||||||
|
"General Dashboard Settings ({commands[configure general]})"
|
||||||
|
)
|
||||||
|
_option_name = _p(
|
||||||
|
"dash:general|option|name",
|
||||||
|
"General Configuration Panel"
|
||||||
|
)
|
||||||
|
configui = GeneralSettingsUI
|
||||||
|
setting_classes = configui.setting_classes
|
||||||
Reference in New Issue
Block a user