Files
croccybot/src/modules/schedule/ui/settingui.py

280 lines
10 KiB
Python

import itertools
import asyncio
import discord
from discord.ui.button import button, Button, ButtonStyle
from discord.ui.select import select, ChannelSelect, RoleSelect
from meta import LionBot
from utils.ui import ConfigUI, DashboardSection
from utils.lib import MessageArgs
from ..settings import ScheduleSettings
from .. import babel
_p = babel._p
class ScheduleSettingUI(ConfigUI):
pages = [
(
ScheduleSettings.SessionLobby,
ScheduleSettings.SessionRoom,
ScheduleSettings.SessionChannels,
), (
ScheduleSettings.ScheduleCost,
ScheduleSettings.AttendanceReward,
ScheduleSettings.AttendanceBonus,
ScheduleSettings.MinAttendance,
), (
ScheduleSettings.BlacklistRole,
ScheduleSettings.BlacklistAfter,
)
]
setting_classes = list(itertools.chain(*pages))
def _init_children(self):
# HACK to stop ViewWeights complaining that this UI has too many children
# Children will be correctly initialised after parent init.
return []
def __init__(self, bot: LionBot, guildid: int, channelid: int, **kwargs):
self.settings = bot.get_cog('ScheduleCog').settings
super().__init__(bot, guildid, channelid, **kwargs)
self._children = super()._init_children()
self.page_num = 0
def get_instance(self, setting):
return next(instance for instance in self.instances if instance.setting_id == setting.setting_id)
@property
def page_instances(self):
start = sum(len(page) for page in self.pages[:self.page_num])
end = start + len(self.pages[self.page_num])
return self.instances[start:end]
# ----- UI Components -----
# Page 0 button
@button(label="PAGE0_BUTTON_PLACEHOLDER", style=ButtonStyle.grey)
async def page0_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer(thinking=True, ephemeral=True)
self.page_num = 0
await self.refresh(thinking=press)
async def page0_button_refresh(self):
t = self.bot.translator.t
self.page0_button.label = t(_p(
'ui:schedule_config|button:page0|label',
"Page 1"
))
self.page0_button.disabled = (self.page_num == 0)
# Lobby channel selector
@select(cls=ChannelSelect, channel_types=[discord.ChannelType.text, discord.ChannelType.voice],
min_values=0, max_values=1,
placeholder='LOBBY_PLACEHOLDER')
async def lobby_menu(self, selection: discord.Interaction, selected: ChannelSelect):
# 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()
async def lobby_menu_refresh(self):
t = self.bot.translator.t
self.lobby_menu.placeholder = t(_p(
'ui:schedule_config|menu:lobby|placeholder',
"Select Lobby Channel"
))
# Room channel selector
@select(cls=ChannelSelect, channel_types=[discord.ChannelType.category, discord.ChannelType.voice],
min_values=0, max_values=1,
placeholder='ROOM_PLACEHOLDER')
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()
async def room_menu_refresh(self):
t = self.bot.translator.t
self.room_menu.placeholder = t(_p(
'ui:schedule_config|menu:room|placeholder',
"Select Session Room"
))
# Session channels selector
@select(cls=ChannelSelect, channel_types=[discord.ChannelType.category, discord.ChannelType.voice],
min_values=0, max_values=25,
placeholder='CHANNELS_PLACEHOLDER')
async def channels_menu(self, selection: discord.Interaction, selected: ChannelSelect):
# 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()
async def channels_menu_refresh(self):
t = self.bot.translator.t
self.channels_menu.placeholder = t(_p(
'ui:schedule_config|menu:channels|placeholder',
"Select Session Channels"
))
# Page 1 button
@button(label="PAGE1_BUTTON_PLACEHOLDER", style=ButtonStyle.grey)
async def page1_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer(thinking=True, ephemeral=True)
self.page_num = 1
await self.refresh(thinking=press)
async def page1_button_refresh(self):
t = self.bot.translator.t
self.page1_button.label = t(_p(
'ui:schedule_config|button:page1|label',
"Page 2"
))
self.page1_button.disabled = (self.page_num == 1)
# Page 3 button
@button(label="PAGE2_BUTTON_PLACEHOLDER", style=ButtonStyle.grey)
async def page2_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer(thinking=True, ephemeral=True)
self.page_num = 2
await self.refresh(thinking=press)
async def page2_button_refresh(self):
t = self.bot.translator.t
self.page2_button.label = t(_p(
'ui:schedule_config|button:page2|label',
"Page 3"
))
self.page2_button.disabled = (self.page_num == 3)
# Blacklist role selector
@select(cls=RoleSelect, min_values=0, max_values=1, placeholder="BLACKLIST_ROLE_PLACEHOLDER")
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()
async def blacklist_role_menu_refresh(self):
t = self.bot.translator.t
self.blacklist_role_menu.placeholder = t(_p(
'ui:schedule_config|menu:blacklist_role|placeholder',
"Select Blacklist Role"
))
# ----- UI Flow -----
async def make_message(self) -> MessageArgs:
t = self.bot.translator.t
title = t(_p(
'ui:schedule_config|embed|title',
"Scheduled Session Configuration Panel"
))
embed = discord.Embed(
colour=discord.Colour.orange(),
title=title
)
for setting in self.page_instances:
embed.add_field(**setting.embed_field, inline=False)
args = MessageArgs(embed=embed)
return args
async def refresh_components(self):
await asyncio.gather(
self.page0_button_refresh(),
self.page1_button_refresh(),
self.page2_button_refresh(),
self.edit_button_refresh(),
self.reset_button_refresh(),
self.close_button_refresh(),
)
if self.page_num == 0:
await asyncio.gather(
self.lobby_menu_refresh(),
self.room_menu_refresh(),
self.channels_menu_refresh(),
)
self.set_layout(
(self.page0_button, self.page1_button, self.page2_button),
(self.lobby_menu,),
(self.room_menu,),
(self.channels_menu,),
(self.edit_button, self.reset_button, self.close_button),
)
elif self.page_num == 1:
self.set_layout(
(self.page0_button, self.page1_button, self.page2_button),
(self.edit_button, self.reset_button, self.close_button),
)
elif self.page_num == 2:
await asyncio.gather(
self.blacklist_role_menu_refresh()
)
self.set_layout(
(self.page0_button, self.page1_button, self.page2_button),
(self.blacklist_role_menu,),
(self.edit_button, self.reset_button, self.close_button),
)
class ScheduleDashboard(DashboardSection):
section_name = _p(
'dash:schedule|title',
"Scheduled Session Configuration ({commands[admin config schedule]})"
)
_option_name = _p(
"dash:schedule|dropdown|placeholder",
"Scheduled Sessions Panel"
)
configui = ScheduleSettingUI
setting_classes = ScheduleSettingUI.setting_classes
def apply_to(self, page: discord.Embed):
t = self.bot.translator.t
pages = [
self.instances[0:3],
self.instances[3:7],
self.instances[7:]
]
# Schedule Channels
table = self._make_table(pages[0])
page.add_field(
name=t(_p(
'dash:schedule|section:schedule_channels|name',
"Scheduled Session Channels ({commands[admin config schedule]})",
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
)
# Schedule Rewards
table = self._make_table(pages[1])
page.add_field(
name=t(_p(
'dash:schedule|section:schedule_rewards|name',
"Scheduled Session Rewards ({commands[admin config schedule]})",
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
)
# Schedule Blacklist
table = self._make_table(pages[2])
page.add_field(
name=t(_p(
'dash:schedule|section:schedule_blacklist|name',
"Scheduled Session Blacklist ({commands[admin config schedule]})",
)).format(commands=self.bot.core.mention_cache),
value=table,
inline=False
)