diff --git a/bot.py b/bot.py index bf93035..88d3c44 100644 --- a/bot.py +++ b/bot.py @@ -1,7 +1,8 @@ +import logging + import discord from discord.ext import commands -from datetime import datetime -import logging +from discord.utils import utcnow logger = logging.getLogger(__name__) @@ -22,7 +23,7 @@ intents = discord.Intents( class RoboBot(commands.Bot): def __init__(self, command_prefix, config, **options): self.config = config - self.uptime = datetime.utcnow() # used for info :) + self.uptime = utcnow() # used for info :) self.src = config.get("github_url") # Set up the command prefix and intents from commands.Bot super().__init__(command_prefix=command_prefix, intents=intents, **options) diff --git a/cogs/info.py b/cogs/info.py index a33edaa..83b185b 100644 --- a/cogs/info.py +++ b/cogs/info.py @@ -1,10 +1,13 @@ import logging +import discord from discord.ext import commands from utils import about_me_embed from utils import handle_api_request +from table2ascii import table2ascii as t2a, PresetStyle + logger = logging.getLogger(__name__) @@ -27,14 +30,71 @@ class Info(commands.Cog): embed = about_me_embed(self.bot) await ctx.send(embed=embed, ephemeral=True) + @commands.hybrid_command( + name="server_info", + description="Displays information about a server.", + aliases=["server"], + ) + async def server_info(self, ctx, *, server_name: str): + result, message = handle_api_request("servers") + if not result: + await ctx.send(f"Failed to retrieve server status: {message}", ephemeral=True) + return + + for server in result: + if server_name.lower() in server["name"].lower(): + found_server = server + break + else: + await ctx.send(f"Couldn't find server with name {server_name}", ephemeral=True) + return + + game_map = server.get("mapAliasAndVersion", "Unknown") + map_alias, map_version = game_map.split('/') + + result, message = handle_api_request("maps") + if not result: + await ctx.send(f"Failed to retrieve maps: {message}", ephemeral=True) + return + + for game_map in result: + if map_alias == game_map["alias"]: + found_map = game_map + break + else: + await ctx.send(f"Couldn't find map with alias {map_alias}", ephemeral=True) + return + + # make the embed + embed = discord.Embed( + title=f"{found_server['name']}", + description="", + color=discord.Color.dark_orange(), + ) + # add fields + game_state = found_server["gameState"] + match game_state: + case "waiting": + game_state = "waiting for players" + case "running": + game_state = "game in progress" + case "ending": + game_state = "game over" + embed.add_field(name="Map", value=f"{found_map['name']}") + embed.add_field(name="Map version",value=f"{map_version}") + embed.add_field(name="Players", value=f"{found_server['onlinePlayers']}/{found_server['gameSettings']['maxPlayers']}") + embed.add_field(name="Status", value=f"{game_state}") + + await ctx.send(embed=embed, ephemeral=True) + @commands.hybrid_command( name="servers", description="Fetches info about the game servers", aliases=["server_list"] ) async def servers(self, ctx): result, message = handle_api_request("servers") + table_body = [] if result: - response = "Servers:" for server in result: name = server.get("name", "Unknown") online_players = server.get("onlinePlayers", -1) @@ -42,8 +102,16 @@ class Info(commands.Cog): map = server.get("mapAliasAndVersion", "Unknown") game_settings = server.get("gameSettings", {}) max_players = game_settings.get("maxPlayers", -1) - response += f"\n* {name} - {game_state} - {map} - {online_players}/{max_players}" - await ctx.send(response, ephemeral=True) + table_body.append([name, map, game_state, f"{online_players}/{max_players}"]) + output = t2a( + header=["Name", "Map", "State", "Players"], + body=table_body, + style=PresetStyle.thin_compact + ) + + await ctx.send(f"```\nServers:\n{output}\n```", ephemeral=True) + elif len(result) == 0: + await ctx.send("There are no servers online at the moment", ephemeral=True) else: await ctx.send(f"Failed to retrieve server status: {message}", ephemeral=True) diff --git a/config.example.yaml b/config.example.yaml index 99d57b9..438f766 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -18,6 +18,7 @@ routes: stop_server: "/server/stop" change_map: "/server/change_map" servers: "/servers" + maps: "/maps" # Mod IDs (for permissions) # Replicate if you want admins, gamemasters, etc. diff --git a/requirements.txt b/requirements.txt index 0e0d007..bfc7b12 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ humanfriendly==10.0 psutil==6.0.0 PyYAML==6.0.2 Requests==2.32.3 +table2ascii~=1.1.3 diff --git a/utils.py b/utils.py index c928002..4cdd799 100644 --- a/utils.py +++ b/utils.py @@ -76,7 +76,7 @@ def mod_only(): # Gross function, but it works. -def handle_api_request(route_key, data=None) -> tuple[Union[dict, list, None]]: +def handle_api_request(route_key, data=None) -> tuple[Union[dict, list, None], str]: # route_key is your YAML key # Data defaults to None so we don't have to set it