fix (schedule): Setting tweaks and more bugfixes.

Add the schedule dashboard to the config dashboard.
Move the schedule cost to the second page.
Allow categories to be selected for the session room.

Fix an issue where blacklist role would be checked with no guild data.
Fix typos in session unloading.
Delay session notification.
More logging.
This commit is contained in:
2023-07-08 12:46:49 +03:00
parent d7fa97a12b
commit aebd5375c7
6 changed files with 52 additions and 28 deletions

View File

@@ -16,6 +16,7 @@ from modules.ranks.ui.config import RankDashboard
from modules.pomodoro.settingui import TimerDashboard from modules.pomodoro.settingui import TimerDashboard
from modules.rooms.settingui import RoomDashboard from modules.rooms.settingui import RoomDashboard
from babel.settingui import LocaleDashboard from babel.settingui import LocaleDashboard
from modules.schedule.ui.settingui import ScheduleDashboard
# from modules.statistics.settings import StatisticsConfigUI # from modules.statistics.settings import StatisticsConfigUI
from . import babel, logger from . import babel, logger
@@ -31,7 +32,8 @@ class GuildDashboard(BasePager):
pages = [ pages = [
(LocaleDashboard, EconomyDashboard, TasklistDashboard), (LocaleDashboard, EconomyDashboard, TasklistDashboard),
(VoiceTrackerDashboard, TextTrackerDashboard, ), (VoiceTrackerDashboard, TextTrackerDashboard, ),
(RankDashboard, TimerDashboard, RoomDashboard, ) (RankDashboard, TimerDashboard, RoomDashboard, ),
(ScheduleDashboard,),
] ]
def __init__(self, bot: LionBot, guild: discord.Guild, callerid: int, channelid: int, **kwargs): def __init__(self, bot: LionBot, guild: discord.Guild, callerid: int, channelid: int, **kwargs):

View File

@@ -87,7 +87,7 @@ class ScheduleCog(LionCog):
slot.run_task.cancel() slot.run_task.cancel()
for session in slot.sessions.values(): for session in slot.sessions.values():
if session._updater and not session._updater.done(): if session._updater and not session._updater.done():
session._update.cancel() session._updater.cancel()
if session._status_task and not session._status_task.done(): if session._status_task and not session._status_task.done():
session._status_task.cancel() session._status_task.cancel()
@@ -217,6 +217,8 @@ class ScheduleCog(LionCog):
for bookingid in bookingids: for bookingid in bookingids:
await self._cancel_booking_active(*bookingid) await self._cancel_booking_active(*bookingid)
conn = await self.bot.db.get_connection()
async with conn.transaction():
# Now delete from data # Now delete from data
records = await self.data.ScheduleSessionMember.table.delete_where( records = await self.data.ScheduleSessionMember.table.delete_where(
MULTIVALUE_IN( MULTIVALUE_IN(
@@ -240,6 +242,7 @@ class ScheduleCog(LionCog):
) )
return records return records
@log_wrap(action='Cancel Active Booking')
async def _cancel_booking_active(self, slotid, guildid, userid): async def _cancel_booking_active(self, slotid, guildid, userid):
""" """
Booking cancel worker for active slots. Booking cancel worker for active slots.
@@ -259,7 +262,7 @@ class ScheduleCog(LionCog):
return return
async with session.lock: async with session.lock:
# Update message if it has already been sent # Update message if it has already been sent
session.update_message_soon(resend=False) session.update_status_soon(resend=False)
room = session.room_channel room = session.room_channel
member = session.guild.get_member(userid) if room else None member = session.guild.get_member(userid) if room else None
if room and member and session.prepared: if room and member and session.prepared:
@@ -564,7 +567,7 @@ class ScheduleCog(LionCog):
if new_roles: if new_roles:
# This should be in cache in the vast majority of cases # This should be in cache in the vast majority of cases
guild_data = await self.data.ScheduleGuild.fetch(guild.id) guild_data = await self.data.ScheduleGuild.fetch(guild.id)
if (roleid := guild_data.blacklist_role) is not None and roleid in new_roles: if guild_data and (roleid := guild_data.blacklist_role) is not None and roleid in new_roles:
# Clear member schedule # Clear member schedule
await self.clear_member_schedule(guild.id, after.id) await self.clear_member_schedule(guild.id, after.id)

View File

@@ -5,6 +5,7 @@ import asyncio
import discord import discord
from meta import LionBot from meta import LionBot
from meta.logger import log_wrap
from utils.lib import utc_now from utils.lib import utc_now
from utils.lib import MessageArgs from utils.lib import MessageArgs
@@ -79,6 +80,7 @@ class ScheduledSession:
self._last_update = None self._last_update = None
self._updater = None self._updater = None
self._status_task = None self._status_task = None
self._notify_task = None
def __repr__(self): def __repr__(self):
return ' '.join(( return ' '.join((
@@ -193,6 +195,7 @@ class ScheduledSession:
if hook: if hook:
return hook.as_webhook(client=self.bot) return hook.as_webhook(client=self.bot)
@log_wrap(action='Lobby Send')
async def send(self, *args, wait=True, **kwargs): async def send(self, *args, wait=True, **kwargs):
lobby_hook = await self.get_lobby_hook() lobby_hook = await self.get_lobby_hook()
if lobby_hook: if lobby_hook:
@@ -209,6 +212,7 @@ class ScheduledSession:
exc_info=True exc_info=True
) )
@log_wrap(action='Session Prepare')
async def prepare(self, **kwargs): async def prepare(self, **kwargs):
""" """
Execute prepare stage for this guild. Execute prepare stage for this guild.
@@ -218,6 +222,7 @@ class ScheduledSession:
await self.update_status(**kwargs) await self.update_status(**kwargs)
self.prepared = True self.prepared = True
@log_wrap(action='Prepare Room')
async def prepare_room(self): async def prepare_room(self):
""" """
Add overwrites allowing current members to connect. Add overwrites allowing current members to connect.
@@ -258,6 +263,7 @@ class ScheduledSession:
)).format(room=room.mention) )).format(room=room.mention)
) )
@log_wrap(action='Open Room')
async def open_room(self): async def open_room(self):
""" """
Remove overwrites for non-members. Remove overwrites for non-members.
@@ -302,10 +308,15 @@ class ScheduledSession:
self.prepared = True self.prepared = True
self.opened = True self.opened = True
async def notify(self): @log_wrap(action='Notify')
async def _notify(self, wait=60):
""" """
Ghost ping members who have not yet attended. Ghost ping members who have not yet attended.
""" """
try:
await asyncio.sleep(wait)
except asyncio.CancelledError:
return
missing = [mid for mid, m in self.members.items() if m.total_clock == 0 and m.clock_start is None] missing = [mid for mid, m in self.members.items() if m.total_clock == 0 and m.clock_start is None]
if missing: if missing:
ping = ''.join(f"<@{mid}>" for mid in missing) ping = ''.join(f"<@{mid}>" for mid in missing)
@@ -313,6 +324,12 @@ class ScheduledSession:
if message is not None: if message is not None:
asyncio.create_task(message.delete()) asyncio.create_task(message.delete())
def notify(self):
"""
Trigger notify after one minute.
"""
self._notify_task = asyncio.create_task(self._notify())
async def current_status(self) -> MessageArgs: async def current_status(self) -> MessageArgs:
""" """
Lobby status message args. Lobby status message args.
@@ -474,6 +491,7 @@ class ScheduledSession:
args = MessageArgs(embed=embed, view=view) args = MessageArgs(embed=embed, view=view)
return args return args
@log_wrap(action='Update Status')
async def _update_status(self, save=True, resend=True): async def _update_status(self, save=True, resend=True):
""" """
Send or update the lobby message. Send or update the lobby message.
@@ -530,6 +548,7 @@ class ScheduledSession:
self._status_task.cancel() self._status_task.cancel()
await self._update_status(**kwargs) await self._update_status(**kwargs)
@log_wrap(action='Status Loop')
async def update_loop(self): async def update_loop(self):
""" """
Keep the lobby message up to date with a message per minute. Keep the lobby message up to date with a message per minute.

View File

@@ -297,11 +297,10 @@ class TimeSlot:
for session in sessions for session in sessions
if session.lobby_channel is not None if session.lobby_channel is not None
] ]
notify_tasks = [ # Trigger notify tasks
asyncio.create_task(session.notify()) for session in fresh:
for session in fresh if session.lobby_channel is not None:
if session.lobby_channel is not None and session.data.opened_at is None session.notify()
]
# Start lobby update loops # Start lobby update loops
for session in sessions: for session in sessions:
@@ -317,7 +316,6 @@ class TimeSlot:
async for task in limit_concurrency(voice_coros, 5): async for task in limit_concurrency(voice_coros, 5):
await task await task
await asyncio.gather(*message_tasks) await asyncio.gather(*message_tasks)
await asyncio.gather(*notify_tasks)
# Write opened # Write opened
if fresh: if fresh:

View File

@@ -99,12 +99,14 @@ class ScheduleSettings(SettingGroup):
"will be given permission to join the voice channel (via permission overwrites). " "will be given permission to join the voice channel (via permission overwrites). "
"I require the `MANAGE_CHANNEL`, `MANAGE_PERMISSIONS`, `CONNECT`, and `VIEW_CHANNEL` permissions " "I require the `MANAGE_CHANNEL`, `MANAGE_PERMISSIONS`, `CONNECT`, and `VIEW_CHANNEL` permissions "
"in this channel, and my highest role must be higher than all permission overwrites set in the channel. " "in this channel, and my highest role must be higher than all permission overwrites set in the channel. "
"Furthermore, if this is set to a *category* channel, then the permission overwrites will apply "
"to all *synced* channels under the category, as usual."
) )
_accepts = _p( _accepts = _p(
'guildset:session_room|accepts', 'guildset:session_room|accepts',
"Name or id of the session room voice channel." "Name or id of the session room voice channel."
) )
channel_types = [discord.VoiceChannel] channel_types = [discord.VoiceChannel, discord.CategoryChannel]
_model = ScheduleData.ScheduleGuild _model = ScheduleData.ScheduleGuild
_column = ScheduleData.ScheduleGuild.room_channel.name _column = ScheduleData.ScheduleGuild.room_channel.name

View File

@@ -22,8 +22,8 @@ class ScheduleSettingUI(ConfigUI):
ScheduleSettings.SessionLobby, ScheduleSettings.SessionLobby,
ScheduleSettings.SessionRoom, ScheduleSettings.SessionRoom,
ScheduleSettings.SessionChannels, ScheduleSettings.SessionChannels,
ScheduleSettings.ScheduleCost,
), ( ), (
ScheduleSettings.ScheduleCost,
ScheduleSettings.AttendanceReward, ScheduleSettings.AttendanceReward,
ScheduleSettings.AttendanceBonus, ScheduleSettings.AttendanceBonus,
ScheduleSettings.MinAttendance, ScheduleSettings.MinAttendance,
@@ -89,7 +89,7 @@ class ScheduleSettingUI(ConfigUI):
)) ))
# Room channel selector # Room channel selector
@select(cls=ChannelSelect, channel_types=[discord.ChannelType.voice], @select(cls=ChannelSelect, channel_types=[discord.ChannelType.category, discord.ChannelType.voice],
min_values=0, max_values=1, min_values=0, max_values=1,
placeholder='ROOM_PLACEHOLDER') placeholder='ROOM_PLACEHOLDER')
async def room_menu(self, selection: discord.Interaction, selected: ChannelSelect): async def room_menu(self, selection: discord.Interaction, selected: ChannelSelect):