Files
croccybot/src/modules/member_admin/settingui.py

302 lines
10 KiB
Python

import asyncio
import discord
from discord.ui.button import button, Button, ButtonStyle
from discord.ui.select import select, RoleSelect, ChannelSelect
from meta import LionBot
from utils.ui import ConfigUI, DashboardSection
from utils.lib import MessageArgs
from utils.ui.msgeditor import MsgEditor
from wards import equippable_role
from .settings import MemberAdminSettings as Settings
from . import babel
_p = babel._p
class MemberAdminUI(ConfigUI):
setting_classes = (
Settings.GreetingChannel,
Settings.GreetingMessage,
Settings.ReturningMessage,
Settings.Autoroles,
Settings.BotAutoroles,
Settings.RolePersistence,
)
def __init__(self, bot: LionBot, guildid: int, channelid: int, **kwargs):
self.settings = bot.get_cog('MemberAdminCog').settings
super().__init__(bot, guildid, channelid, **kwargs)
# ----- UI Components -----
# Greeting Channel
@select(
cls=ChannelSelect,
channel_types=[discord.ChannelType.voice, discord.ChannelType.text],
placeholder="GREETCH_MENU_PLACEHOLDER",
min_values=0, max_values=1
)
async def greetch_menu(self, selection: discord.Interaction, selected: ChannelSelect):
"""
Selector for the `greeting_channel` setting.
"""
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()
async def greetch_menu_refresh(self):
menu = self.greetch_menu
t = self.bot.translator.t
menu.placeholder = t(_p(
'ui:memberadmin|menu:greetch|placeholder',
"Select Greeting Channel"
))
# Autoroles
@select(
cls=RoleSelect,
placeholder="AUTOROLES_MENU_PLACEHOLDER",
min_values=0, max_values=25
)
async def autoroles_menu(self, selection: discord.Interaction, selected: RoleSelect):
"""
Simple multi-role selector for the 'autoroles' setting.
"""
await selection.response.defer(thinking=True, ephemeral=True)
for role in selected.values:
# Check authority to set these roles (for author and client)
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
await selection.delete_original_response()
async def autoroles_menu_refresh(self):
menu = self.autoroles_menu
t = self.bot.translator.t
menu.placeholder = t(_p(
'ui:memberadmin|menu:autoroles|placeholder',
"Select Autoroles"
))
# Bot autoroles
@select(
cls=RoleSelect,
placeholder="BOT_AUTOROLES_MENU_PLACEHOLDER",
min_values=0, max_values=25
)
async def bot_autoroles_menu(self, selection: discord.Interaction, selected: RoleSelect):
"""
Simple multi-role selector for the 'bot_autoroles' setting.
"""
await selection.response.defer(thinking=True, ephemeral=True)
for role in selected.values:
# Check authority to set these roles (for author and client)
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
await selection.delete_original_response()
async def bot_autoroles_menu_refresh(self):
menu = self.bot_autoroles_menu
t = self.bot.translator.t
menu.placeholder = t(_p(
'ui:memberadmin|menu:bot_autoroles|placeholder',
"Select Bot Autoroles"
))
# Greeting Msg
@button(
label="GREET_MSG_BUTTON_PLACEHOLDER",
style=ButtonStyle.blurple
)
async def greet_msg_button(self, press: discord.Interaction, pressed: Button):
"""
Message Editor Button for the `greeting_message` setting.
This will open up a Message Editor with the current `greeting_message`,
if set, otherwise a default `greeting_message`.
This also generates a preview formatter using the calling user.
"""
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:
value = setting._data_to_value(self.guildid, t(setting._soft_default))
setting.value = value
await setting.write()
editor = MsgEditor(
self.bot,
value,
callback=setting.editor_callback,
formatter=await setting.generate_formatter(self.bot, press.user),
callerid=press.user.id,
)
self._slaves.append(editor)
await editor.run(press)
async def greet_msg_button_refresh(self):
button = self.greet_msg_button
t = self.bot.translator.t
button.label = t(_p(
'ui:member_admin|button:greet_msg|label',
"Greeting Msg"
))
# Returning Msg
@button(
label="RETURN_MSG_BUTTON_PLACEHOLDER",
style=ButtonStyle.blurple
)
async def return_msg_button(self, press: discord.Interaction, pressed: Button):
"""
Message Editor Button for the `returning_message` setting.
Similar to the `greet_msg_button`, this opens a Message Editor
with the current `returning_message`.
If the setting is unset, will instead either use the current `greeting_message`,
or if that is also unset, use a default `returning_message`.
"""
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
if value is not None:
pass
elif greeting.value is not None:
value = greeting.value
else:
value = setting._data_to_value(self.guildid, t(setting._soft_default))
setting.value = value
await setting.write()
editor = MsgEditor(
self.bot,
value,
callback=setting.editor_callback,
formatter=await setting.generate_formatter(
self.bot, press.user, press.user.joined_at.timestamp()
),
callerid=press.user.id,
)
self._slaves.append(editor)
await editor.run(press)
async def return_msg_button_refresh(self):
button = self.return_msg_button
t = self.bot.translator.t
button.label = t(_p(
'ui:memberadmin|button:return_msg|label',
"Returning Msg"
))
# ----- UI Flow -----
async def make_message(self) -> MessageArgs:
t = self.bot.translator.t
title = t(_p(
'ui:memberadmin|embed|title',
"Greetings and Initial Roles Panel"
))
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):
# Re-fetch data for each instance
# This should generally hit cache
self.instances = [
await setting.get(self.guildid)
for setting in self.setting_classes
]
async def refresh_components(self):
component_refresh = (
self.edit_button_refresh(),
self.close_button_refresh(),
self.reset_button_refresh(),
self.greetch_menu_refresh(),
self.autoroles_menu_refresh(),
self.bot_autoroles_menu_refresh(),
self.greet_msg_button_refresh(),
self.return_msg_button_refresh(),
)
await asyncio.gather(*component_refresh)
self.set_layout(
(self.greetch_menu,),
(self.autoroles_menu,),
(self.bot_autoroles_menu,),
(self.greet_msg_button, self.return_msg_button,
self.edit_button, self.reset_button, self.close_button),
)
class MemberAdminDashboard(DashboardSection):
section_name = _p(
"dash:member_admin|title",
"Greetings and Initial Roles ({commands[config welcome]})"
)
_option_name = _p(
"dash:member_admin|dropdown|placeholder",
"Greetings and Initial Roles Panel"
)
configui = MemberAdminUI
setting_classes = MemberAdminUI.setting_classes
def apply_to(self, page: discord.Embed):
"""
Overriding DashboardSection apply_to to split into two sections.
"""
t = self.bot.translator.t
sections = [
self.instances[:3],
self.instances[3:]
]
# Greeting messages
table = self._make_table(sections[0])
page.add_field(
name=t(_p(
'dash:member_admin|section:greeting_messages|name',
"Greeting Messages ({commands[admin config welcome]})"
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
)
# Initial Roles
table = self._make_table(sections[1])
page.add_field(
name=t(_p(
'dash:member_admin|section:initial_roles|name',
"Initial Roles ({commands[admin config welcome]})"
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
)