Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,32 +325,44 @@ async def maint(interaction: discord.Interaction, status: bool = True):

await interaction.response.send_message("🛠️ Toggling maintenance mode... please wait")
await STATE_MANAGER.set_maint(status=status)

active_guild_ids = STATE_MANAGER.all_active_guild_ids()
for guild_id in active_guild_ids:
text_channel = bot.get_channel(STATE_MANAGER.get_state(guild_id, 'text_channel_id'))
if status:
is_active = STATE_MANAGER.get_state(guild_id, 'is_active') or False
if status and is_active is True:
embed_data = {
'title': "Maintenance",
'color': 0xfce053,
'description': "The bot is entering maintenance mode. Commands and playback will be unavailable until maintenance is complete",
'timestamp': str(datetime.datetime.now(datetime.UTC)),
}
await stop_playback(bot.get_guild(guild_id))
STATE_MANAGER.set_state(guild_id, 'was_active', True)
embed = discord.Embed.from_dict(embed_data)
await text_channel.send(embed=embed)
else:
embed_data = {
'title': "Maintenance",
'color': 0xfce053,
'description': "Maintenance has concluded.",
'timestamp': str(datetime.datetime.now(datetime.UTC)),
was_active = STATE_MANAGER.get_state(guild_id, 'was_active') or False
if was_active is True and status == False:
embed_data = {
'title': "Maintenance",
'color': 0xfce053,
'description': "Maintenance has concluded.",
'timestamp': str(datetime.datetime.now(datetime.UTC)),
}
embed = discord.Embed.from_dict(embed_data)
await text_channel.send(embed=embed)
embed = discord.Embed.from_dict(embed_data)
await text_channel.send(embed=embed)

if status:
await interaction.edit_original_response(content="💾 saving state...")
await STATE_MANAGER.save_state()
asyncio.sleep(5)
await interaction.edit_original_response(content="👷 Maintenance mode enabled")
else:
STATE_MANAGER.clear_state()
await interaction.edit_original_response(content="🧼 Purging State + DB...")
STATE_MANAGER.clear_state(force=True)
await STATE_MANAGER.clear_state_db()
asyncio.sleep(5)
await STATE_MANAGER.set_maint(status=status)
await interaction.edit_original_response(content="👷 Maintenance mode disabled")

else:
Expand Down Expand Up @@ -948,6 +960,7 @@ def stream_finished_callback(error):
STATE_MANAGER.set_state(interaction.guild.id, 'current_stream_url', url)
STATE_MANAGER.set_state(interaction.guild.id, 'text_channel_id', interaction.channel.id)
STATE_MANAGER.set_state(interaction.guild.id, 'start_time', datetime.datetime.now(datetime.UTC))
STATE_MANAGER.set_state(interaction.guild.id, 'is_active', True)

# And let the user know what song is playing
await send_song_info(interaction.guild.id)
Expand Down
18 changes: 11 additions & 7 deletions models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,23 @@ class GuildState(Base):
# text_channel = Text channel original play command came from
# start_time = Time the current stream started playing
# last_active_user_time = Time the last active user was spotted in the voice channel
# is_active = Boolean for if the bot is currently active in the guild True|None
# was_active = Boolean for if the bot was active before going into maintenance True|None
# cleaning_up = Boolean for if the bot is currently stopping/cleaning up True|None
# health_error_count = Int number of times a health error occurred in a row
# ffmpeg_process_pid = PID for the FFMPEG process associated with the guild
__tablename__ = "guild_state"

guild_id: Mapped[int] = mapped_column(primary_key=True)
current_stream_url: Mapped[str] = mapped_column(String)
private_stream: Mapped[bool] = mapped_column(Boolean)
text_channel_id: Mapped[int] = mapped_column(Integer)
start_time: Mapped[datetime] = mapped_column(DateTime)
last_active_user_time: Mapped[datetime] = mapped_column(DateTime)
cleaning_up: Mapped[bool] = mapped_column(Boolean)
ffmpeg_process_pid: Mapped[int] = mapped_column(Integer)
current_stream_url: Mapped[str] = mapped_column(String, nullable=True)
private_stream: Mapped[bool] = mapped_column(Boolean, nullable=True)
text_channel_id: Mapped[int] = mapped_column(Integer, nullable=True)
start_time: Mapped[datetime] = mapped_column(DateTime, nullable=True)
last_active_user_time: Mapped[datetime] = mapped_column(DateTime, nullable=True)
cleaning_up: Mapped[bool] = mapped_column(Boolean, nullable=True)
is_active: Mapped[bool] = mapped_column(Boolean, nullable=True)
was_active: Mapped[bool] = mapped_column(Boolean, nullable=True)
ffmpeg_process_pid: Mapped[int] = mapped_column(Integer, nullable=True)
health_error_count: list[{ErrorStates, int}] = []

class BotState(Base):
Expand Down
12 changes: 8 additions & 4 deletions services/state_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class StateManager:
# text_channel = Text channel original play command came from
# start_time = Time the current stream started playing
# last_active_user_time = Time the last active user was spotted in the voice channel
# is_active = Boolean for if the bot is currently active in the guild True|None
# was_active = Boolean for if the bot was active before going into maintenance True|None
# cleaning_up = Boolean for if the bot is currently stopping/cleaning up True|None
# health_error_count = Int number of times a health error occurred in a row
# ffmpeg_process_pid = PID for the FFMPEG process associated with the guild
Expand Down Expand Up @@ -72,7 +74,8 @@ def clear_state(self, guild_id: int=None, force: bool=False):

saved_state = {
'text_channel_id': self.guild_state[guild_id].text_channel_id,
'private_stream': self.guild_state[guild_id].private_stream
'private_stream': self.guild_state[guild_id].private_stream,
'was_active': self.guild_state[guild_id].was_active
}
self.guild_state[guild_id] = GuildState()
if not force:
Expand All @@ -82,7 +85,7 @@ def clear_state(self, guild_id: int=None, force: bool=False):
# Update maintenance status
async def set_maint(self, status: bool):
self.bot_state.maint = status
await self.save_state()
# await self.save_state()
def get_maint(self):
return self.bot_state.maint

Expand All @@ -94,11 +97,11 @@ def all_active_guild_ids(self):
guild = self.bot.get_guild(guild_id)

# Sometimes we need to exclude some state variables when considering if the guild is active
vars_to_exclude = ['cleaning_up', 'text_channel_id', 'private_stream']
vars_to_exclude = ['cleaning_up', 'text_channel_id', 'private_stream', 'is_active', 'was_active']
temp_state = {key: value for key, value in self.get_state(guild_id).items() if key not in vars_to_exclude}

state_active = bool(temp_state)
vc_active = guild and guild.voice_client and guild.voice_client.is_connected()
vc_active = guild and guild.voice_client and guild.voice_client.is_connected()
if state_active or vc_active:
active_ids.append(guild_id)
return active_ids
Expand Down Expand Up @@ -127,4 +130,5 @@ async def clear_state_db(self):
async with self.ASYNC_SESSION_LOCAL() as session:
stmt = delete(GuildState)
await session.execute(stmt)
session.add(self.bot_state)
await session.commit()