From c947aa214872cd3c5429339a6fc81b763e74fea5 Mon Sep 17 00:00:00 2001 From: Corban-Lee Jones Date: Fri, 6 Dec 2024 14:10:16 +0000 Subject: [PATCH] handle mod updates --- cogs/console.py | 51 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/cogs/console.py b/cogs/console.py index 326ef56..3fd4920 100644 --- a/cogs/console.py +++ b/cogs/console.py @@ -4,11 +4,13 @@ Reads and handles updates in the server console file. import re import logging +import asyncio from pathlib import Path from dataclasses import dataclass import httpx import aiofiles +from rcon.source import rcon from discord import Embed, Colour from discord.ext import commands, tasks @@ -88,7 +90,7 @@ class ConsoleCog(commands.Cog): Determine how to handle the given line from the server console. """ - if "CheckModsNeedUpdate" in line: + if "CheckModsNeedUpdate: Mods need update" in line: await self.handle_mod_needs_update(line) elif "ConnectionManager: [fully-connected]" in line: @@ -97,8 +99,49 @@ class ConsoleCog(commands.Cog): elif "ConnectionManager: [disconnect]" in line: await self.handle_player_left(line) + async def alert_and_wait_for_restart(self, intervals_ms: list[int], reason: str): + for interval_ms in intervals_ms: + seconds_remaining = interval_ms / 1000 + log.info("Planned restart in %s seconds, reason: %s", seconds_remaining, reason) + await rcon("Planned restart in %s seconds, reason: %s", seconds_remaining, reason, **self.bot.rcon_details) + while seconds_remaining > 0: + await asyncio.sleep(1) + seconds_remaining -= 1 + + async def kick_all_users(self): + players_message = await rcon("players", **self.bot.rcon_details) + re_pattern = r"Players connected \(\d+\):\s*(-[\w-]+(?:\s*[\w-]+)*)" + re_match = re.search(re_pattern, players_message) + if not re_match: + log.info("No players found to kick") + + usernames_string = re_match.group(1) + for i, username in enumerate(usernames_string.split("-")): + if not username: + continue + + await rcon(f'kickuser "{username}" -r "Server is Updating. Kicked to ensure your progress is saved"', **self.bot.rcon_details) + + log.info("Kicked '%s' users for restart", i + 1) + async def handle_mod_needs_update(self, line: str): - log.debug("mod update instruction: %s", line) + """ + Report when one or more mods need to be updated. + """ + log.info("one or more mods are outdated") + + await self.alert_and_wait_for_restart( + intervals_ms=[300000, 60000, 6000], + reason="Mod needs updating" + ) + await self.kick_all_users() + await rcon("save", **self.bot.rcon_details) + await rcon("quit", **self.bot.rcon_details) + + channel = self.bot.get_channel(self.bot.in_game_channel_id) + channel = await self.bot.fetch_channel(self.bot.in_game_channel_id) if not channel else channel + await channel.send(content="The server is currently being restarted for mod updates.") + async def handle_player_joined(self, line: str): """ @@ -118,7 +161,7 @@ class ConsoleCog(commands.Cog): steam_id=re_match.group(3), access=re_match.group(4), username=re_match.group(5), - connection_type=re_match.group(6), + connection_type=re_match.group(6) ) channel = self.bot.get_channel(self.bot.in_game_channel_id) @@ -152,7 +195,7 @@ class ConsoleCog(commands.Cog): steam_id=re_match.group(3), access=re_match.group(4), username=re_match.group(5), - connection_type=re_match.group(6), + connection_type=re_match.group(6) ) channel = self.bot.get_channel(self.bot.in_game_channel_id)