From d0bab4a17958acbb9aa1e919e4dab680a3682dc3 Mon Sep 17 00:00:00 2001 From: Dustin Pianalto Date: Mon, 16 Dec 2019 19:10:47 -0900 Subject: [PATCH] Update listplayers command for new system --- geeksbot/config/bot_config.json | 3 +- geeksbot/exts/rcon.py | 1731 +++++++++++++++---------------- 2 files changed, 836 insertions(+), 898 deletions(-) diff --git a/geeksbot/config/bot_config.json b/geeksbot/config/bot_config.json index 0a46820..d9abbb9 100644 --- a/geeksbot/config/bot_config.json +++ b/geeksbot/config/bot_config.json @@ -7,6 +7,7 @@ "guild_events", "command_events", "tickets", - "inspect" + "inspect", + "rcon" ] } diff --git a/geeksbot/exts/rcon.py b/geeksbot/exts/rcon.py index 07decb8..5ee168b 100644 --- a/geeksbot/exts/rcon.py +++ b/geeksbot/exts/rcon.py @@ -1,5 +1,5 @@ import discord -from discord.ext.commands import Cog +from discord.ext import commands import logging from datetime import datetime import asyncio @@ -11,306 +11,227 @@ from geeksbot.imports import checks rcon_log = logging.getLogger('rcon') -class Rcon(Cog): +class Rcon(commands.Cog): def __init__(self, bot): self.bot = bot - async def connect_rcon_server(self, *, name: str, ip: str, port: int, password: str, - single_packet: bool = False, force: bool = False, monitor_chat: bool = False, - server_chat_channel: int = None, server_messages_channel: int = None) \ - -> typing.Union[int, str]: - - if name.replace('_', ' ').title() in self.bot.connected_ark_servers.keys() \ - and isinstance(self.bot.connected_ark_servers[name], arcon.ARKServer) \ - and self.bot.connected_ark_servers[name].writer \ - and not force: - rcon_log.info(f"{name.replace('_', ' ').title()} is already connected.") - return 1 - - server = arcon.ARKServer(host=ip, port=port, password=password, single_packet=single_packet, - monitor_chat=monitor_chat, server_chat_channel=server_chat_channel, - server_messages_channel=server_messages_channel) - rcon_log.info(f'{name.replace("_", " ").title()} configured.') - connected = await server.connect() - if connected == 1: - rcon_log.info(f'{name.replace("_", " ").title()} connected.') - self.bot.connected_ark_servers[name.replace('_', ' ').title()] = server - return 1 - elif connected == -1: - rcon_log.info(f'{name.replace("_", " ").title()} timeout error.') - return 'Timeout Error' - elif connected == 0: - rcon_log.info(f'{name.replace("_", " ").title()} auth error.') - return 'Authentication Failed' - else: - rcon_log.info(f'{name.replace("_", " ").title()} unknown error.') - return 'Unknown Error' - - async def get_rcon_server_by_name(self, *, guild_config: dict, name: str) \ - -> typing.Union[dict, arcon.ARKServer, None]: - guild_servers = guild_config.get('rcon_connections') - if guild_servers: - if name == '*': - server_list = {} - for server, info in guild_servers.items(): - if server == name.replace('_', ' ').title(): - if server not in self.bot.connected_ark_servers.keys(): - connection_result = await self.connect_rcon_server( - name=server, - ip=info['ip'], - port=info['port'], - password=info['password'], - monitor_chat=info.get('monitoring_chat', None), - server_chat_channel=info.get('game_chat_chan_id', None), - server_messages_channel=info.get('msg_chan_id', None) - ) - if connection_result != 1: - return None - return self.bot.connected_ark_servers[server] - elif name == '*': - if server not in self.bot.connected_ark_servers.keys(): - connection_result = await self.connect_rcon_server( - name=server, - ip=info['ip'], - port=info['port'], - password=info['password'], - monitor_chat=info.get('monitoring_chat', None), - server_chat_channel=info.get('game_chat_chan_id', None), - server_messages_channel=info.get('msg_chan_id', None) - ) - if connection_result != 1: - # noinspection PyUnboundLocalVariable - server_list[server] = f'Cannot connect to the {server} server.\n{connection_result}' - try: - # noinspection PyUnboundLocalVariable - server_list[server] = self.bot.connected_ark_servers[server] - except KeyError: - rcon_log.warning(server_list[server]) - del server_list[server] - else: - if name == '*': - return server_list - return None - else: - return None - - @staticmethod - async def admin(bot, guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): - player = msg.split(' ||| ')[1].split(' (')[0] - rcon_log.info(f'{player} requested admin assistance') - admin_roles = guild_config.get('admin_roles') - if admin_roles: - for role in admin_roles: - msg = '{0} {1}'.format(msg, discord.utils.get(guild.roles, id=admin_roles[role]).mention) - await server_con.server_chat_to_player_name(player, 'GeeksBot: Admin Geeks have been notified you need ' - 'assistance. Please be patient.') - return msg - - async def dinowipe(self, bot, guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): - player = msg.split(' ||| ')[1].split(' (')[0] - steam_ref = self.bot.fs_db.collection(f'users').where('steam_name', '==', player) - user_info = await self.bot.loop.run_in_executor(self.bot.tpe, steam_ref.get) - steamid = None - user = None - for user in user_info: - if user: - steamid = user.to_dict().get('steam_id') - break - if steamid: - if not self.bot.dino_wipe_request.get(server_name): - if user: - player = await patron.Patron.from_id(bot, steamid, discord_id=int(user.id)) - rcon_log.info(f'{player.steam_name} requested a wild dino wipe') - member = guild.get_member(player.discord_id) - self.bot.loop.create_task(self.request_dinowipe(member, server_name, server_con)) - else: - await server_con.server_chat_to_player_name(player, - 'Sorry, an error has occurred please try again.') - else: - await server_con.server_chat_to_player_name(player, 'A Wild Dino Wipe request is already in progress.') - else: - await server_con.server_chat_to_player_name(player, 'Sorry. You are not registered to run commands via the ' - 'in-game chat. Please send a chat message in-game ' - '$register steamid=your_steam_id and follow the ' - 'instructions so I can link your character with your ' - 'Discord account. Thanks') - return msg - - @staticmethod - async def delaywipe(bot, guild: discord.Guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): - player = msg.split(' ||| ')[1].split(' (')[0] - if bot.dino_wipe_request.get(server_name): - bot.dino_wipe_request[server_name] = False - await server_con.broadcast(f'Wild Dino Wipe has been delayed by {player}. ' - f'Please watch chat for timing updates') - elif bot.dino_wipe_request.get(server_name) is None: - await server_con.server_chat_to_player_name(player, 'There are no Wild Dino Wipes pending.') - else: - await server_con.server_chat_to_player_name(player, 'The dino wipe has already been delayed.') - return msg - - @staticmethod - async def register(bot, guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): - player = msg.split(' ||| ')[1].split(' (')[0] - steamid = msg.split(' ||| ')[1].split('steamid=')[1].split(' ')[0].replace('`', '').replace("'", '').strip() - rcon_log.info(f'{player} - {steamid}') - try: - int(steamid) - except ValueError: - await server_con.server_chat_to_player_name(player, 'That is not a valid SteamID') - return msg - else: - identifier = randint(10000, 99999) - prefix = guild_config.get("prefixes", bot.default_prefix) - await server_con.server_chat_to_player_name(player, - 'Your SteamID has been noted, to finish registering ' - 'please run the following command in the discord ' - f'channel. You will not be able to run commands ' - f'in-game until your registration is completed... ' - f'{prefix[0] if isinstance(prefix, list) else prefix}' - f'register {identifier}') - bot.pending_registrations[identifier] = (player, steamid) - return msg - - @commands.command(name='register') - async def register_discord_account(self, ctx, identifier: int=None): - user_ref = self.bot.fs_db.document(f'users/{ctx.author.id}') - user_info = (await self.bot.loop.run_in_executor(self.bot.tpe, user_ref.get)).to_dict() - if user_info.get('steam_id') and user_info.get('steam_name'): - await ctx.send('You are already registered to run commands in-game') - return - - if identifier not in self.bot.pending_registrations.keys(): - await ctx.send('That identifier is not in the pending registrations') - return - - steam_info = self.bot.pending_registrations[identifier] - - await self.bot.loop.run_in_executor(self.bot.tpe, user_ref.update, { - 'steam_name': steam_info[0], - 'steam_id': steam_info[1] - }) - await ctx.send('Registration complete. You are now authorized to run commands in-game on the ARK servers.') - del self.bot.pending_registrations[identifier] - - async def create_server_chat_chan(self, guild: discord.Guild, server_name: str, - server_con: arcon.ARKServer, guild_config: dict): - rcon_log.info(f'Creating channel for {server_name}') - category = discord.utils.get(guild.categories, name='Server Chats') - if category is None: - overrides = {guild.default_role: discord.PermissionOverwrite(read_messages=False)} - category = await guild.create_category('Server Chats', overwrites=overrides) - rcon_log.info(category) - channels = guild.channels - if category: - for channel in category.channels: - if server_con.server_chat_channel == channel.id: - return channel - else: - rcon_log.info(f'Creating {server_name}') - chan = await guild.create_text_channel(f'{server_name}', category=category) - server_con.server_chat_channel = chan.id - if guild_config.get('rcon_connections'): - guild_config['rcon_connections'][server_name]['game_chat_chan_id'] = chan.id - guild_ref = self.bot.fs_db.document(f'guilds/{guild.id}') - await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, guild_config) - return chan - - async def _monitor_chat(self, guild, server_name, server_con, guild_config: dict): - # noinspection PyShadowingNames - async def start_monitor_chat(bot, guild, *, server_name: str, - server_con: arcon.ARKServer, guild_config: dict): - while server_con.monitor_chat: - messages = await server_con.getchat() - rcon_log.debug('Got chat from {0}.'.format(server_name)) - for message in [msg.strip() for msg in messages.split('\n') - if msg.strip() != 'Server received, But no response!!']: - rcon_log.info(message) - message_out = f'```{datetime.now().strftime("%Y-%m-%d %H:%M:%S")} ||| {message}```' - for command in self.bot.game_commands: - prefix_command = '{0}{1}'.format(self.bot.game_prefix, command) - if message.split('): ')[-1].startswith(prefix_command): - try: - func = getattr(self, command) - except AttributeError: - rcon_log.warning('Function not found "{0}"'.format(command)) - else: - rcon_log.info(f'Sending to {command}') - message_out = await func(bot, guild, message_out, server_name, server_con, guild_config) - - await guild.get_channel(server_con.server_chat_channel).send(message_out) - await asyncio.sleep(1) - await guild.get_channel(server_con.server_chat_channel).send('Monitoring Stopped') - - rcon_log.info(server_con.server_chat_channel) - if server_con.server_chat_channel: - channel = self.bot.get_channel(server_con.server_chat_channel) - if not channel: - channel = await self.create_server_chat_chan(guild, server_name, server_con, guild_config) - else: - channel = await self.create_server_chat_chan(guild, server_name, server_con, guild_config) - rcon_log.info(channel) - self.bot.loop.create_task(start_monitor_chat(self.bot, guild, server_name=server_name, - server_con=server_con, guild_config=guild_config)) - await channel.send('Started monitoring on the {0} server.'.format(server_name)) - rcon_log.debug('Started monitoring on the {0} server.'.format(server_name)) - - @commands.command() - @commands.guild_only() - async def monitor_chat(self, ctx, *, server=None): - """Begins monitoring the specified ARK server for chat messages and other events. - The specified server must already be in the current guild\'s configuration. - To add and remove ARK servers from the guild see add_rcon_server and remove_rcon_server. - The server argument is not case sensitive and if the server name has two - words it can be in one of the following forms: - first last - first_last - "first last" - To view all the valid ARK servers for this guild see list_ark_servers.""" - - if await checks.is_rcon_admin(self.bot, ctx): - if server is not None: - server = server.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name=server) - if server_con: - server_con.monitor_chat = True - ctx.guild_config['rcon_connections'][server]["monitoring_chat"] = 1 - guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') - await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) - await self._monitor_chat(ctx.guild, server, server_con, ctx.guild_config) - await ctx.message.add_reaction('✅') - else: - await ctx.send(f'Server not found: {server}') - else: - await ctx.send(f'You must include a server in this command.') - else: - await ctx.send(f'You are not authorized to run this command.') - - @commands.command() - @commands.guild_only() - async def end_monitor_chat(self, ctx, *, server=None): - """Ends chat monitoring on the specified server. - Context is the same as monitor_chat""" - if await checks.is_rcon_admin(self.bot, ctx): - if server is not None: - server = server.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name=server) - if server_con: - server_con.monitor_chat = False - else: - await ctx.send(f'{server} is not connected currently.') - if server in ctx.guild_config.get('rcon_connections', []): - ctx.guild_config['rcon_connections'][server]["monitoring_chat"] = 0 - guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') - await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) - else: - await ctx.send(f'Server not found in config: {server}') - else: - await ctx.send(f'You must include a server in this command.') - else: - await ctx.send(f'You are not authorized to run this command.') + # @staticmethod + # async def admin(bot, guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): + # player = msg.split(' ||| ')[1].split(' (')[0] + # rcon_log.info(f'{player} requested admin assistance') + # admin_roles = guild_config.get('admin_roles') + # if admin_roles: + # for role in admin_roles: + # msg = '{0} {1}'.format(msg, discord.utils.get(guild.roles, id=admin_roles[role]).mention) + # await server_con.server_chat_to_player_name(player, 'GeeksBot: Admin Geeks have been notified you need ' + # 'assistance. Please be patient.') + # return msg + # + # async def dinowipe(self, bot, guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): + # player = msg.split(' ||| ')[1].split(' (')[0] + # steam_ref = self.bot.fs_db.collection(f'users').where('steam_name', '==', player) + # user_info = await self.bot.loop.run_in_executor(self.bot.tpe, steam_ref.get) + # steamid = None + # user = None + # for user in user_info: + # if user: + # steamid = user.to_dict().get('steam_id') + # break + # if steamid: + # if not self.bot.dino_wipe_request.get(server_name): + # if user: + # player = await patron.Patron.from_id(bot, steamid, discord_id=int(user.id)) + # rcon_log.info(f'{player.steam_name} requested a wild dino wipe') + # member = guild.get_member(player.discord_id) + # self.bot.loop.create_task(self.request_dinowipe(member, server_name, server_con)) + # else: + # await server_con.server_chat_to_player_name(player, + # 'Sorry, an error has occurred please try again.') + # else: + # await server_con.server_chat_to_player_name(player, 'A Wild Dino Wipe request is already in progress.') + # else: + # await server_con.server_chat_to_player_name(player, 'Sorry. You are not registered to run commands via the ' + # 'in-game chat. Please send a chat message in-game ' + # '$register steamid=your_steam_id and follow the ' + # 'instructions so I can link your character with your ' + # 'Discord account. Thanks') + # return msg + # + # @staticmethod + # async def delaywipe(bot, guild: discord.Guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): + # player = msg.split(' ||| ')[1].split(' (')[0] + # if bot.dino_wipe_request.get(server_name): + # bot.dino_wipe_request[server_name] = False + # await server_con.broadcast(f'Wild Dino Wipe has been delayed by {player}. ' + # f'Please watch chat for timing updates') + # elif bot.dino_wipe_request.get(server_name) is None: + # await server_con.server_chat_to_player_name(player, 'There are no Wild Dino Wipes pending.') + # else: + # await server_con.server_chat_to_player_name(player, 'The dino wipe has already been delayed.') + # return msg + # + # @staticmethod + # async def register(bot, guild, msg, server_name, server_con: arcon.ARKServer, guild_config: dict): + # player = msg.split(' ||| ')[1].split(' (')[0] + # steamid = msg.split(' ||| ')[1].split('steamid=')[1].split(' ')[0].replace('`', '').replace("'", '').strip() + # rcon_log.info(f'{player} - {steamid}') + # try: + # int(steamid) + # except ValueError: + # await server_con.server_chat_to_player_name(player, 'That is not a valid SteamID') + # return msg + # else: + # identifier = randint(10000, 99999) + # prefix = guild_config.get("prefixes", bot.default_prefix) + # await server_con.server_chat_to_player_name(player, + # 'Your SteamID has been noted, to finish registering ' + # 'please run the following command in the discord ' + # f'channel. You will not be able to run commands ' + # f'in-game until your registration is completed... ' + # f'{prefix[0] if isinstance(prefix, list) else prefix}' + # f'register {identifier}') + # bot.pending_registrations[identifier] = (player, steamid) + # return msg + # + # @commands.command(name='register') + # async def register_discord_account(self, ctx, identifier: int=None): + # user_ref = self.bot.fs_db.document(f'users/{ctx.author.id}') + # user_info = (await self.bot.loop.run_in_executor(self.bot.tpe, user_ref.get)).to_dict() + # if user_info.get('steam_id') and user_info.get('steam_name'): + # await ctx.send('You are already registered to run commands in-game') + # return + # + # if identifier not in self.bot.pending_registrations.keys(): + # await ctx.send('That identifier is not in the pending registrations') + # return + # + # steam_info = self.bot.pending_registrations[identifier] + # + # await self.bot.loop.run_in_executor(self.bot.tpe, user_ref.update, { + # 'steam_name': steam_info[0], + # 'steam_id': steam_info[1] + # }) + # await ctx.send('Registration complete. You are now authorized to run commands in-game on the ARK servers.') + # del self.bot.pending_registrations[identifier] + # + # async def create_server_chat_chan(self, guild: discord.Guild, server_name: str, + # server_con: arcon.ARKServer, guild_config: dict): + # rcon_log.info(f'Creating channel for {server_name}') + # category = discord.utils.get(guild.categories, name='Server Chats') + # if category is None: + # overrides = {guild.default_role: discord.PermissionOverwrite(read_messages=False)} + # category = await guild.create_category('Server Chats', overwrites=overrides) + # rcon_log.info(category) + # channels = guild.channels + # if category: + # for channel in category.channels: + # if server_con.server_chat_channel == channel.id: + # return channel + # else: + # rcon_log.info(f'Creating {server_name}') + # chan = await guild.create_text_channel(f'{server_name}', category=category) + # server_con.server_chat_channel = chan.id + # if guild_config.get('rcon_connections'): + # guild_config['rcon_connections'][server_name]['game_chat_chan_id'] = chan.id + # guild_ref = self.bot.fs_db.document(f'guilds/{guild.id}') + # await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, guild_config) + # return chan + # + # async def _monitor_chat(self, guild, server_name, server_con, guild_config: dict): + # # noinspection PyShadowingNames + # async def start_monitor_chat(bot, guild, *, server_name: str, + # server_con: arcon.ARKServer, guild_config: dict): + # while server_con.monitor_chat: + # messages = await server_con.getchat() + # rcon_log.debug('Got chat from {0}.'.format(server_name)) + # for message in [msg.strip() for msg in messages.split('\n') + # if msg.strip() != 'Server received, But no response!!']: + # rcon_log.info(message) + # message_out = f'```{datetime.now().strftime("%Y-%m-%d %H:%M:%S")} ||| {message}```' + # for command in self.bot.game_commands: + # prefix_command = '{0}{1}'.format(self.bot.game_prefix, command) + # if message.split('): ')[-1].startswith(prefix_command): + # try: + # func = getattr(self, command) + # except AttributeError: + # rcon_log.warning('Function not found "{0}"'.format(command)) + # else: + # rcon_log.info(f'Sending to {command}') + # message_out = await func(bot, guild, message_out, server_name, server_con, guild_config) + # + # await guild.get_channel(server_con.server_chat_channel).send(message_out) + # await asyncio.sleep(1) + # await guild.get_channel(server_con.server_chat_channel).send('Monitoring Stopped') + # + # rcon_log.info(server_con.server_chat_channel) + # if server_con.server_chat_channel: + # channel = self.bot.get_channel(server_con.server_chat_channel) + # if not channel: + # channel = await self.create_server_chat_chan(guild, server_name, server_con, guild_config) + # else: + # channel = await self.create_server_chat_chan(guild, server_name, server_con, guild_config) + # rcon_log.info(channel) + # self.bot.loop.create_task(start_monitor_chat(self.bot, guild, server_name=server_name, + # server_con=server_con, guild_config=guild_config)) + # await channel.send('Started monitoring on the {0} server.'.format(server_name)) + # rcon_log.debug('Started monitoring on the {0} server.'.format(server_name)) + # + # @commands.command() + # @commands.guild_only() + # async def monitor_chat(self, ctx, *, server=None): + # """Begins monitoring the specified ARK server for chat messages and other events. + # The specified server must already be in the current guild\'s configuration. + # To add and remove ARK servers from the guild see add_rcon_server and remove_rcon_server. + # The server argument is not case sensitive and if the server name has two + # words it can be in one of the following forms: + # first last + # first_last + # "first last" + # To view all the valid ARK servers for this guild see list_ark_servers.""" + # + # if await checks.is_rcon_admin(self.bot, ctx): + # if server is not None: + # server = server.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name=server) + # if server_con: + # server_con.monitor_chat = True + # ctx.guild_config['rcon_connections'][server]["monitoring_chat"] = 1 + # guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') + # await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) + # await self._monitor_chat(ctx.guild, server, server_con, ctx.guild_config) + # await ctx.message.add_reaction('✅') + # else: + # await ctx.send(f'Server not found: {server}') + # else: + # await ctx.send(f'You must include a server in this command.') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @commands.command() + # @commands.guild_only() + # async def end_monitor_chat(self, ctx, *, server=None): + # """Ends chat monitoring on the specified server. + # Context is the same as monitor_chat""" + # if await checks.is_rcon_admin(self.bot, ctx): + # if server is not None: + # server = server.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name=server) + # if server_con: + # server_con.monitor_chat = False + # else: + # await ctx.send(f'{server} is not connected currently.') + # if server in ctx.guild_config.get('rcon_connections', []): + # ctx.guild_config['rcon_connections'][server]["monitoring_chat"] = 0 + # guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') + # await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) + # else: + # await ctx.send(f'Server not found in config: {server}') + # else: + # await ctx.send(f'You must include a server in this command.') + # else: + # await ctx.send(f'You are not authorized to run this command.') @commands.command() @commands.guild_only() @@ -328,621 +249,637 @@ class Rcon(Cog): if server_name: server_name = server_name.replace('_', ' ').title() - server: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name=server_name) - if server: - msg = await ctx.send(f'**Getting Data for the {server_name} server**') - await ctx.channel.trigger_typing() - - message = await server.listplayers() + msg = await ctx.send(f'**Getting Data for the {server_name} server**') + await ctx.channel.trigger_typing() + resp = await self.bot.aio_session.get( + f'{self.bot.api_base}/rcon/{ctx.guild.id}/{server_name}/listplayers', + headers=self.bot.auth_header + ) + if resp.status == 200: + message = '\n'.join(await resp.json()) await ctx.channel.trigger_typing() await msg.delete() await ctx.send(f'**Players currently on the {server_name} server:**\n{message}') + return + elif resp.status < 500: + message = (await resp.json()).get('details', 'There was a problem. Please try again') else: - await ctx.send(f'That server is not in my configuration.\nPlease add it via !add_rcon_server ' - f'"{server_name}" "ip" port "password" if you would like to get info from it.') + message = "There was an error on my server. I have notified the maintainers." + await ctx.send(message) else: futures = [] - guild_servers: dict = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name='*' + resp = await self.bot.aio_session.get( + f'{self.bot.api_base}/rcon/{ctx.guild.id}/', + headers=self.bot.auth_header ) - if guild_servers is not None: - for name, server in guild_servers.items(): - if not isinstance(server, arcon.ARKServer): - await ctx.send(f'__**{server}**__') + if resp.status != 200: + await ctx.send('There was a problem getting the servers for this guild.') + return + guild_servers = await resp.json() + for server in guild_servers: + msg = await ctx.send(f'**Getting Data for the {server["name"]} server**') + + # noinspection PyShadowingNames + async def _listplayers(server_name: str, msg: discord.Message): + resp = await self.bot.aio_session.get( + f'{self.bot.api_base}/rcon/{ctx.guild.id}/{server_name}/listplayers', + headers=self.bot.auth_header + ) + if resp.status == 200: + message = '\n'.join(await resp.json()) + await ctx.channel.trigger_typing() + await msg.delete() + await ctx.send(f'**Players currently on the {server_name} server:**\n{message}') + return + elif resp.status < 500: + message = f'Error getting data for {server_name}' + \ + (await resp.json()).get('details', 'Please try again') else: - msg = await ctx.send(f'**Getting Data for the {name} server**') - - # noinspection PyShadowingNames - async def _listplayers(*, name, server_con: arcon.ARKServer, mess: discord.Message): - name = name.replace('_', ' ').title() - - response = await server_con.listplayers() - await mess.edit(content=f'**Players currently on the {name} server:**\n{response}') - - futures.append(_listplayers(mess=msg, server_con=server, name=name)) - if futures: - asyncio.ensure_future(asyncio.gather(*futures)) - else: - await ctx.send('There are no available servers for this guild.') - else: - await ctx.send('There are no available servers for this guild.') - else: - await ctx.send(f'You are not authorized to run this command.') - - @commands.command() - @commands.guild_only() - async def add_rcon_server(self, ctx, server, ip, port, password): - """Adds the specified server to the current guild\'s rcon config. - All multi-word strings (, , ) must be contained inside double quotes.""" - if await checks.is_rcon_admin(self.bot, ctx): - server = server.replace('_', ' ').title() - if ctx.guild_config.get('rcon_connections'): - if server not in ctx.guild_config['rcon_connections']: - ctx.guild_config['rcon_connections'][server] = { - 'ip': ip, - 'port': port, - 'password': password, - 'game_chat_chan_id': 0, - 'msg_chan_id': 0, - 'monitoring_chat': 0 - } - guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') - await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) - await ctx.send('{0} server has been added to my configuration.'.format(server)) - else: - await ctx.send('This server name is already in my configuration. Please choose another.') - else: - ctx.guild_config['rcon_connections'] = {server: { - 'ip': ip, - 'port': port, - 'password': password, - 'game_chat_chan_id': 0, - 'msg_chan_id': 0, - 'monitoring_chat': 0 - }} - guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') - await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) - await ctx.send('{0} server has been added to my configuration.'.format(server)) - else: - await ctx.send(f'You are not authorized to run this command.') - await ctx.message.delete() - await ctx.send('Command deleted to prevent password leak.') - - @commands.command() - @commands.guild_only() - async def remove_rcon_server(self, ctx, *, server: str): - """removes the specified server from the current guild\'s rcon config.""" - if await checks.is_rcon_admin(self.bot, ctx): - server = server.replace('_', ' ').title() - if server in ctx.guild_config.get('rcon_connections', []): - del ctx.guild_config['rcon_connections'][server] - guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') - await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) - await ctx.send('{0} has been removed from my configuration.'.format(server)) - else: - await ctx.send('{0} is not in my configuration.'.format(server)) - else: - await ctx.send(f'You are not authorized to run this command.') - - @staticmethod - async def _whitelist(*, server_name: str, server_con: arcon.ARKServer, - player: patron.Patron, message: discord.Message, message_lock: asyncio.Lock): - result = await server_con.whitelist(player.steam_id) - if result == f'{player.steam_id} Allow Player To Join No Check': - with await message_lock: - message = await message.channel.get_message(message.id) - await message.edit(content=f'{message.content}\n{server_name.replace("_", " ").title()}' - f' Done!') - else: - with await message_lock: - message = await message.channel.get_message(message.id) - await message.edit(content=f'{message.content}\n{server_name.replace("_", " ").title()}' - f' Failed!') - - @commands.command(name='add_whitelist') - @commands.guild_only() - async def add_whitelist(self, ctx, *, members: str=None): - if await checks.is_rcon_admin(self.bot, ctx): - if members: - futures = [] - members = members.replace(', ', '').split(',') - converter = commands.MemberConverter() - for member in members: - try: - member = await converter.convert(ctx, member) - except commands.errors.BadArgument: - try: - member = int(member) - except ValueError: - raise ValueError(f'Member {member} can\'t be found and is not a valid Steam64 ID.') - - if isinstance(member, discord.Member): - player = await patron.Patron.from_name(self.bot, discord_name=member) - else: - player = await patron.Patron.from_id(self.bot, steam_id=member) - - if player == -1: - await ctx.send(f'{ctx.author.mention} I Cannot find a player with a discord name/steam id of ' - f'{member} in the current whitelist sheet. Did you forget to ' - f'move them to the correct sheet?') - else: - rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name='*') - if rcon_connections: - msg = await ctx.send(f'**Whitelisting {player.discord_name} on all servers**') - lock = asyncio.Lock() - for server_name, server_con in rcon_connections.items(): - futures.append(self._whitelist(server_name=server_name, server_con=server_con, - player=player, message=msg, message_lock=lock)) + message = "There was an error on my server. I have notified the maintainers." + await ctx.send(message) + futures.append(_listplayers(msg=msg, server_name=server['name'])) if futures: - asyncio.ensure_future(asyncio.gather(*futures), loop=self.bot.loop) - else: - await ctx.send('Nothing for me to do') - return - - else: - await ctx.send('I need a list of members to whitelist.') - else: - await ctx.send(f'You are not authorized to run this command.') - - @commands.command(name='new_patron') - @commands.guild_only() - async def register_new_patron(self, ctx, *, members: str=None): - """Adds the included Steam 64 IDs to the running whitelist on all the ARK servers in the current guild\'s rcon config. - Steam 64 IDs should be a comma separated list of IDs. - Example: 76561198024193239,76561198024193239,76561198024193239""" - if await checks.is_rcon_admin(self.bot, ctx): - if members is not None: - async with ctx.typing(): - members = members.replace(', ', ',').split(',') - converter = commands.MemberConverter() - members = [await converter.convert(ctx, m) for m in members] - futures = [] - patrons = [] - rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name='*') - - if not isinstance(members, list): - members = [members, ] - for member in members: - member: discord.Member - player = await patron.Patron.from_name(self.bot, discord_name=member) - if player == -1: - await ctx.send(f'{ctx.author.mention} I Cannot find a player with a discord name of ' - f'{member.display_name} in the current whitelist sheet. Did you forget to ' - f'move them to the correct sheet?') - else: - if rcon_connections: - msg = await ctx.send(f'**Whitelisting {player.discord_name} on all servers**') - lock = asyncio.Lock() - for server_name, server_con in rcon_connections.items(): - futures.append(self._whitelist(server_name=server_name, server_con=server_con, - player=player, message=msg, message_lock=lock)) - - roles = [] - patron_roles = ctx.guild_config.get('patreon_tiers') - creator_roles = ctx.guild_config.get('patreon_creators') - if creator_roles: - rcon_log.info(f'patron_of {player.patron_of}') - if 'both' in player.patron_of.casefold(): - rcon_log.info('found both') - for role_id in creator_roles.values(): - - roles.append(ctx.guild.get_role(int(role_id))) - else: - roles.append(ctx.guild.get_role( - int(creator_roles[player.patron_of + '_Patron']) - )) - if patron_roles: - roles.append(ctx.guild.get_role( - int(patron_roles[player.patreon_tier.strip().title()]) - )) - if roles: - role_str = '\n'.join([role.name for role in roles]) - await ctx.send(f'Adding {player.discord_name} to the following roles:\n' - f'{role_str}') - await ctx.guild.get_member(int(player.discord_id)).add_roles(*roles) - - patrons.append(player) - - if futures: - asyncio.ensure_future(asyncio.gather(*futures), loop=self.bot.loop) - else: - await ctx.send('Nothing for me to do') - return - - if patrons: - new_patron_message = ctx.guild_config.get('new_patron_message') - new_patron_channel = ctx.guild_config.get('new_patron_channel') - if new_patron_message and new_patron_channel: - channel = ctx.guild.get_channel(int(new_patron_channel)) - if channel: - patron_mentions = [] - for p in patrons: - member = ctx.guild.get_member(int(p.discord_id)) - patron_mentions.append(member.mention) - prelude = new_patron_message.get('prelude') - message = '' - if prelude: - if len(patron_mentions) > 1: - message = prelude.get('plural') - else: - message = prelude.get('singular') - body = new_patron_message.get('body') - if body: - server_info_channel = ctx.guild.get_channel(int( - ctx.guild_config.get('server_info') - )) - message += ' ' + body.format(users=', '.join(patron_mentions), - server_info=server_info_channel.mention if - server_info_channel else "server_info") - await channel.send(message) - else: - await ctx.send('I need a list of members to add roles to and whitelist.') - else: - await ctx.send(f'You are not authorized to run this command.') - - @commands.command() - @commands.guild_only() - async def saveworld(self, ctx, *, server=None): - """Runs SaveWorld on the specified ARK server. - If a server is not specified it will default to running saveworld on all servers in the guild\'s config. - Will print out "World Saved" for each server when the command completes successfully.""" - if await checks.is_rcon_admin(self.bot, ctx): - - # noinspection PyShadowingNames - async def _saveworld(ctx, server_name: str, server_con: arcon.ARKServer): - response = await server_con.saveworld() - if response == 'World Saved': - await ctx.send(f'{server_name} Saved') - else: - await ctx.send(f'Failed to save {server_name}') - - futures = [] - async with ctx.typing(): - if server is None: - rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name='*') - if rcon_connections: - for server_name, server_con in rcon_connections.items(): - futures.append(_saveworld(ctx, server_name, server_con)) - self.bot.loop.create_task(asyncio.gather(*futures)) - else: - await ctx.send('There are no available servers for this guild.') - else: - server = server.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name=server - ) - if server_con: - # noinspection PyTypeChecker - await _saveworld(ctx, server, server_con) - else: - await ctx.send(f'{server} is not currently in the configuration for this guild.') - else: - await ctx.send(f'You are not authorized to run this command.') - - @commands.group(case_insensitive=True) - async def broadcast(self, ctx): - """Run help broadcast for more info""" - pass - - @broadcast.command(name='all', aliases=['a']) - @commands.guild_only() - async def broadcast_all(self, ctx, *, message=None): - """Sends a broadcast message to all servers in the guild config. - The message will be prefixed with the Discord name of the person running the command. - Will print "Success" for each server once the broadcast is sent.""" - if await checks.is_rcon_admin(self.bot, ctx): - if message is not None: - - # noinspection PyShadowingNames - async def _broadcast(*, message: str, server_con: arcon.ARKServer, server_name: str, - msg: discord.Message, message_lock: asyncio.Lock): - print(server_con.host, server_con.port) - response = await server_con.broadcast(message) - if response == 'Server received, But no response!!': - with await message_lock: - msg = await msg.channel.get_message(msg.id) - await msg.edit(content=f'{msg.content}\n{server_name} Success') - else: - with await message_lock: - msg = await msg.channel.get_message(msg.id) - await msg.edit(content=f'{msg.content}\n{server_name} Failed') - futures = [] - rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name='*') - if rcon_connections: - message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) - msg = await ctx.send(f'Broadcasting "{message}" to all servers.') - lock = asyncio.Lock() - for server_name, server_con in rcon_connections.items(): - futures.append(_broadcast(message=message, server_con=server_con, server_name=server_name, - msg=msg, message_lock=lock)) - self.bot.loop.create_task(asyncio.gather(*futures)) - await ctx.message.add_reaction('✅') + asyncio.ensure_future(asyncio.gather(*futures)) else: await ctx.send('There are no available servers for this guild.') - else: - await ctx.send('You must include a message with this command.') else: await ctx.send(f'You are not authorized to run this command.') - @broadcast.command(name='server') - @commands.guild_only() - async def broadcast_server(self, ctx, server, *, message=None): - """Sends a broadcast message to the specified server that is in the guild's config. - The message will be prefixed with the Discord name of the person running the command. - If has more than one word in it's name it will either need to be surrounded - by double quotes or the words separated by _""" - if await checks.is_rcon_admin(self.bot, ctx): - if server is not None: - server = server.replace('_', ' ').title() - if message is not None: - message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) - server_con: arcon.ARKServer = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name=server - ) - if server_con: - msg = await ctx.send(f'Broadcasting "{message}" to {server}.') - response = await server_con.broadcast(message) - if response == 'Server received, But no response!!': - await msg.add_reaction(self.bot.unicode_emojis['y']) - else: - await msg.add_reaction(self.bot.unicode_emojis['x']) - else: - await ctx.send(f'{server} is not in the config for this guild') - else: - await ctx.send('You must include a message with this command.') - else: - await ctx.send('You must include a server with this command') - else: - await ctx.send(f'You are not authorized to run this command.') + # @commands.command() + # @commands.guild_only() + # async def add_rcon_server(self, ctx, server, ip, port, password): + # """Adds the specified server to the current guild\'s rcon config. + # All multi-word strings (, , ) must be contained inside double quotes.""" + # if await checks.is_rcon_admin(self.bot, ctx): + # server = server.replace('_', ' ').title() + # if ctx.guild_config.get('rcon_connections'): + # if server not in ctx.guild_config['rcon_connections']: + # ctx.guild_config['rcon_connections'][server] = { + # 'ip': ip, + # 'port': port, + # 'password': password, + # 'game_chat_chan_id': 0, + # 'msg_chan_id': 0, + # 'monitoring_chat': 0 + # } + # guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') + # await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) + # await ctx.send('{0} server has been added to my configuration.'.format(server)) + # else: + # await ctx.send('This server name is already in my configuration. Please choose another.') + # else: + # ctx.guild_config['rcon_connections'] = {server: { + # 'ip': ip, + # 'port': port, + # 'password': password, + # 'game_chat_chan_id': 0, + # 'msg_chan_id': 0, + # 'monitoring_chat': 0 + # }} + # guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') + # await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) + # await ctx.send('{0} server has been added to my configuration.'.format(server)) + # else: + # await ctx.send(f'You are not authorized to run this command.') + # await ctx.message.delete() + # await ctx.send('Command deleted to prevent password leak.') + # + # @commands.command() + # @commands.guild_only() + # async def remove_rcon_server(self, ctx, *, server: str): + # """removes the specified server from the current guild\'s rcon config.""" + # if await checks.is_rcon_admin(self.bot, ctx): + # server = server.replace('_', ' ').title() + # if server in ctx.guild_config.get('rcon_connections', []): + # del ctx.guild_config['rcon_connections'][server] + # guild_ref = self.bot.fs_db.document(f'guilds/{ctx.guild.id}') + # await self.bot.loop.run_in_executor(self.bot.tpe, guild_ref.update, ctx.guild_config) + # await ctx.send('{0} has been removed from my configuration.'.format(server)) + # else: + # await ctx.send('{0} is not in my configuration.'.format(server)) + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @staticmethod + # async def _whitelist(*, server_name: str, server_con: arcon.ARKServer, + # player: patron.Patron, message: discord.Message, message_lock: asyncio.Lock): + # result = await server_con.whitelist(player.steam_id) + # if result == f'{player.steam_id} Allow Player To Join No Check': + # with await message_lock: + # message = await message.channel.get_message(message.id) + # await message.edit(content=f'{message.content}\n{server_name.replace("_", " ").title()}' + # f' Done!') + # else: + # with await message_lock: + # message = await message.channel.get_message(message.id) + # await message.edit(content=f'{message.content}\n{server_name.replace("_", " ").title()}' + # f' Failed!') + # + # @commands.command(name='add_whitelist') + # @commands.guild_only() + # async def add_whitelist(self, ctx, *, members: str=None): + # if await checks.is_rcon_admin(self.bot, ctx): + # if members: + # futures = [] + # members = members.replace(', ', '').split(',') + # converter = commands.MemberConverter() + # for member in members: + # try: + # member = await converter.convert(ctx, member) + # except commands.errors.BadArgument: + # try: + # member = int(member) + # except ValueError: + # raise ValueError(f'Member {member} can\'t be found and is not a valid Steam64 ID.') + # + # if isinstance(member, discord.Member): + # player = await patron.Patron.from_name(self.bot, discord_name=member) + # else: + # player = await patron.Patron.from_id(self.bot, steam_id=member) + # + # if player == -1: + # await ctx.send(f'{ctx.author.mention} I Cannot find a player with a discord name/steam id of ' + # f'{member} in the current whitelist sheet. Did you forget to ' + # f'move them to the correct sheet?') + # else: + # rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name='*') + # if rcon_connections: + # msg = await ctx.send(f'**Whitelisting {player.discord_name} on all servers**') + # lock = asyncio.Lock() + # for server_name, server_con in rcon_connections.items(): + # futures.append(self._whitelist(server_name=server_name, server_con=server_con, + # player=player, message=msg, message_lock=lock)) + # + # if futures: + # asyncio.ensure_future(asyncio.gather(*futures), loop=self.bot.loop) + # else: + # await ctx.send('Nothing for me to do') + # return + # + # else: + # await ctx.send('I need a list of members to whitelist.') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @commands.command(name='new_patron') + # @commands.guild_only() + # async def register_new_patron(self, ctx, *, members: str=None): + # """Adds the included Steam 64 IDs to the running whitelist on all the ARK servers in the current guild\'s rcon config. + # Steam 64 IDs should be a comma separated list of IDs. + # Example: 76561198024193239,76561198024193239,76561198024193239""" + # if await checks.is_rcon_admin(self.bot, ctx): + # if members is not None: + # async with ctx.typing(): + # members = members.replace(', ', ',').split(',') + # converter = commands.MemberConverter() + # members = [await converter.convert(ctx, m) for m in members] + # futures = [] + # patrons = [] + # rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name='*') + # + # if not isinstance(members, list): + # members = [members, ] + # for member in members: + # member: discord.Member + # player = await patron.Patron.from_name(self.bot, discord_name=member) + # if player == -1: + # await ctx.send(f'{ctx.author.mention} I Cannot find a player with a discord name of ' + # f'{member.display_name} in the current whitelist sheet. Did you forget to ' + # f'move them to the correct sheet?') + # else: + # if rcon_connections: + # msg = await ctx.send(f'**Whitelisting {player.discord_name} on all servers**') + # lock = asyncio.Lock() + # for server_name, server_con in rcon_connections.items(): + # futures.append(self._whitelist(server_name=server_name, server_con=server_con, + # player=player, message=msg, message_lock=lock)) + # + # roles = [] + # patron_roles = ctx.guild_config.get('patreon_tiers') + # creator_roles = ctx.guild_config.get('patreon_creators') + # if creator_roles: + # rcon_log.info(f'patron_of {player.patron_of}') + # if 'both' in player.patron_of.casefold(): + # rcon_log.info('found both') + # for role_id in creator_roles.values(): + # + # roles.append(ctx.guild.get_role(int(role_id))) + # else: + # roles.append(ctx.guild.get_role( + # int(creator_roles[player.patron_of + '_Patron']) + # )) + # if patron_roles: + # roles.append(ctx.guild.get_role( + # int(patron_roles[player.patreon_tier.strip().title()]) + # )) + # if roles: + # role_str = '\n'.join([role.name for role in roles]) + # await ctx.send(f'Adding {player.discord_name} to the following roles:\n' + # f'{role_str}') + # await ctx.guild.get_member(int(player.discord_id)).add_roles(*roles) + # + # patrons.append(player) + # + # if futures: + # asyncio.ensure_future(asyncio.gather(*futures), loop=self.bot.loop) + # else: + # await ctx.send('Nothing for me to do') + # return + # + # if patrons: + # new_patron_message = ctx.guild_config.get('new_patron_message') + # new_patron_channel = ctx.guild_config.get('new_patron_channel') + # if new_patron_message and new_patron_channel: + # channel = ctx.guild.get_channel(int(new_patron_channel)) + # if channel: + # patron_mentions = [] + # for p in patrons: + # member = ctx.guild.get_member(int(p.discord_id)) + # patron_mentions.append(member.mention) + # prelude = new_patron_message.get('prelude') + # message = '' + # if prelude: + # if len(patron_mentions) > 1: + # message = prelude.get('plural') + # else: + # message = prelude.get('singular') + # body = new_patron_message.get('body') + # if body: + # server_info_channel = ctx.guild.get_channel(int( + # ctx.guild_config.get('server_info') + # )) + # message += ' ' + body.format(users=', '.join(patron_mentions), + # server_info=server_info_channel.mention if + # server_info_channel else "server_info") + # await channel.send(message) + # else: + # await ctx.send('I need a list of members to add roles to and whitelist.') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @commands.command() + # @commands.guild_only() + # async def saveworld(self, ctx, *, server=None): + # """Runs SaveWorld on the specified ARK server. + # If a server is not specified it will default to running saveworld on all servers in the guild\'s config. + # Will print out "World Saved" for each server when the command completes successfully.""" + # if await checks.is_rcon_admin(self.bot, ctx): + # + # # noinspection PyShadowingNames + # async def _saveworld(ctx, server_name: str, server_con: arcon.ARKServer): + # response = await server_con.saveworld() + # if response == 'World Saved': + # await ctx.send(f'{server_name} Saved') + # else: + # await ctx.send(f'Failed to save {server_name}') + # + # futures = [] + # async with ctx.typing(): + # if server is None: + # rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name='*') + # if rcon_connections: + # for server_name, server_con in rcon_connections.items(): + # futures.append(_saveworld(ctx, server_name, server_con)) + # self.bot.loop.create_task(asyncio.gather(*futures)) + # else: + # await ctx.send('There are no available servers for this guild.') + # else: + # server = server.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name=server + # ) + # if server_con: + # # noinspection PyTypeChecker + # await _saveworld(ctx, server, server_con) + # else: + # await ctx.send(f'{server} is not currently in the configuration for this guild.') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @commands.group(case_insensitive=True) + # async def broadcast(self, ctx): + # """Run help broadcast for more info""" + # pass + # + # @broadcast.command(name='all', aliases=['a']) + # @commands.guild_only() + # async def broadcast_all(self, ctx, *, message=None): + # """Sends a broadcast message to all servers in the guild config. + # The message will be prefixed with the Discord name of the person running the command. + # Will print "Success" for each server once the broadcast is sent.""" + # if await checks.is_rcon_admin(self.bot, ctx): + # if message is not None: + # + # # noinspection PyShadowingNames + # async def _broadcast(*, message: str, server_con: arcon.ARKServer, server_name: str, + # msg: discord.Message, message_lock: asyncio.Lock): + # print(server_con.host, server_con.port) + # response = await server_con.broadcast(message) + # if response == 'Server received, But no response!!': + # with await message_lock: + # msg = await msg.channel.get_message(msg.id) + # await msg.edit(content=f'{msg.content}\n{server_name} Success') + # else: + # with await message_lock: + # msg = await msg.channel.get_message(msg.id) + # await msg.edit(content=f'{msg.content}\n{server_name} Failed') + # futures = [] + # rcon_connections: dict = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name='*') + # if rcon_connections: + # message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) + # msg = await ctx.send(f'Broadcasting "{message}" to all servers.') + # lock = asyncio.Lock() + # for server_name, server_con in rcon_connections.items(): + # futures.append(_broadcast(message=message, server_con=server_con, server_name=server_name, + # msg=msg, message_lock=lock)) + # self.bot.loop.create_task(asyncio.gather(*futures)) + # await ctx.message.add_reaction('✅') + # else: + # await ctx.send('There are no available servers for this guild.') + # else: + # await ctx.send('You must include a message with this command.') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @broadcast.command(name='server') + # @commands.guild_only() + # async def broadcast_server(self, ctx, server, *, message=None): + # """Sends a broadcast message to the specified server that is in the guild's config. + # The message will be prefixed with the Discord name of the person running the command. + # If has more than one word in it's name it will either need to be surrounded + # by double quotes or the words separated by _""" + # if await checks.is_rcon_admin(self.bot, ctx): + # if server is not None: + # server = server.replace('_', ' ').title() + # if message is not None: + # message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name=server + # ) + # if server_con: + # msg = await ctx.send(f'Broadcasting "{message}" to {server}.') + # response = await server_con.broadcast(message) + # if response == 'Server received, But no response!!': + # await msg.add_reaction(self.bot.unicode_emojis['y']) + # else: + # await msg.add_reaction(self.bot.unicode_emojis['x']) + # else: + # await ctx.send(f'{server} is not in the config for this guild') + # else: + # await ctx.send('You must include a message with this command.') + # else: + # await ctx.send('You must include a server with this command') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @commands.command(aliases=['servers', 'list_servers']) + # @commands.guild_only() + # @commands.check(checks.is_restricted_chan) + # async def list_ark_servers(self, ctx): + # """Returns a list of all the ARK servers in the current guild\'s config.""" + # servers = ctx.guild_config.get('rcon_connections', []) + # em = discord.Embed(style='rich', + # title=f'__**There are currently {len(servers)} ARK servers in my config:**__', + # color=discord.Colour.green() + # ) + # if ctx.guild.icon: + # em.set_thumbnail(url=f'{ctx.guild.icon_url}') + # for server in servers: + # description = f""" + # ឵ **IP:** {servers[server]['ip']}:{servers[server]['port']} + # ឵ **Steam Connect:** [steam://connect/{servers[server]['ip']}:{servers[server]['port']}]\ + # (steam://connect/{servers[server]['ip']}:{servers[server]['port']})""" + # em.add_field(name=f'__***{server}***__', value=description, inline=False) + # await ctx.send(embed=em) + # + # @commands.command(name='server_chat') + # @commands.guild_only() + # async def send_chat_to_server(self, ctx, server: str=None, *, message: str=None): + # if await checks.is_rcon_admin(self.bot, ctx): + # if server is not None: + # server = server.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, + # name=server) + # if server_con: + # if message is not None: + # message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) + # msg = await ctx.send(f'Sending "{message}" to {server}\'s chat') + # response = await server_con.serverchat(message) + # if response == 'Server received, But no response!!': + # await msg.add_reaction(self.bot.unicode_emojis['y']) + # else: + # await msg.add_reaction(self.bot.unicode_emojis['x']) + # else: + # await ctx.send('You must include a message with this command.') + # else: + # await ctx.send(f'That server is not in my configuration.\nPlease add it via !add_rcon_server ' + # f'"{server}" "ip" port "password" if you would like to get info from it.') + # else: + # await ctx.send('You must include a server with this command') + # else: + # await ctx.send('You are not authorized to run this command.') + # + # @commands.command(name='restart_server', aliases=['restart']) + # @commands.guild_only() + # async def restart_rcon_server(self, ctx, message: str, server_name: str=None, + # delay_time: int=15, sleep_time: int=60): + # if await checks.is_rcon_admin(self.bot, ctx): + # + # if server_name is None or server_name == 'all': + # futures = [] + # rcon_servers: dict = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name='*' + # ) + # for server_name, server_con in rcon_servers.items(): + # message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) + # futures.append(utils.restart_rcon_server(ctx, server_name=server_name, server_con=server_con, + # message=message, delay=delay_time, sleep=sleep_time)) + # self.bot.loop.create_task(asyncio.gather(*futures)) + # + # elif server_name.startswith('exclude='): + # futures = [] + # exclude_servers = server_name.split('exclude=')[1].replace('_', ' ').title().split(',') + # rcon_servers: dict = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name='*' + # ) + # for server_name, server_con in rcon_servers.items(): + # if server_name not in exclude_servers: + # message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) + # futures.append(utils.restart_rcon_server(ctx, server_name=server_name, server_con=server_con, + # message=message, delay=delay_time, sleep=sleep_time)) + # self.bot.loop.create_task(asyncio.gather(*futures)) + # + # else: + # async with ctx.typing(): + # server_name = server_name.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name=server_name + # ) + # if server_con: + # message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) + # await utils.restart_rcon_server(ctx, server_name=server_name, server_con=server_con, + # message=message, delay=delay_time, sleep=sleep_time) + # else: + # await ctx.send(f'That server is not in my configuration.\nPlease add it via !add_rcon_server ' + # f'"{server_name}" "ip" port "password" if you would like to get info from it.') + # else: + # await ctx.send('You are not authorized to run this command.') + # + # # noinspection PyShadowingNames + # @staticmethod + # async def start_dinowipe(channel, server_name: str, server_con: arcon.ARKServer): + # msg = await channel.send(f'Wild dinos will be wiped on {server_name} in 2 minutes.') + # await server_con.broadcast(f'Wild dino wipe incoming in 2 minutes, expect a small amount of lag while ' + # f'the dinos repopulate.') + # await asyncio.sleep(90) + # await server_con.serverchat(f'Wild Dino Wipe in 30 seconds') + # await asyncio.sleep(26) + # await server_con.serverchat(f'Wild Dino Wipe in 3') + # await asyncio.sleep(1) + # await server_con.serverchat(f'Wild Dino Wipe in 2') + # await asyncio.sleep(1) + # await server_con.serverchat(f'Wild Dino Wipe in 1') + # await asyncio.sleep(1) + # response = await server_con.destroy_wild_dinos() + # if response == 'All Wild Dinos Destroyed': + # await msg.edit(content=f'Wild Dinos Wiped on {server_name}') + # await server_con.serverchat(f'Wild dinos have been wiped.') + # else: + # await msg.edit(content=f'Failed to wipe wild dinos on {server_name}') + # await server_con.serverchat(f'Wild Dino Wipe failed, Please let the Admin know of this issue') + # + # # noinspection PyShadowingNames,PyUnresolvedReferences + # async def request_dinowipe(self, requester, server_name: str, server_con: arcon.ARKServer): + # self.bot.dino_wipe_request[server_name] = True + # if server_con.server_messages_channel and self.bot.get_channel(int(server_con.server_messages_channel)): + # channel = self.bot.get_channel(int(server_con.server_messages_channel)) + # else: + # channel = self.bot.get_channel(server_con.server_chat_channel) + # msg = False + # if channel: + # msg = await channel.send(f'@here {requester.mention} has requested wild dinos be wiped on the ' + # f'{server_name} server\n' + # f'If you are in the middle of taming or have some other reason to ' + # f'delay the wipe please react to this message with ' + # f'{self.bot.unicode_emojis["x"]}.\n' + # f'Doing so will delay the wipe for 10 minutes.') + # await server_con.broadcast(f'{requester.display_name} has requested wild dinos be wiped.\n' + # f'if you are in the middle of taming or have some other reason to delay the wipe ' + # f'please send a chat message containing "$delaywipe" here in-game.\n' + # f'Doing so will delay the wipe for 10 minutes.') + # await asyncio.sleep(5) + # await server_con.serverchat('The wipe will continue in 2 minutes if there are no requests to delay. ' + # 'Send a message containing $delaywipe to delay for 10 minutes.') + # rcon_log.info('Dino Wipe messages sent') + # if msg: + # def check(reaction, user): + # return str(reaction.emoji) == self.bot.unicode_emojis['x'] and reaction.message.id == msg.id and \ + # user != self.bot.user + # + # user = None + # await msg.add_reaction(self.bot.unicode_emojis['x']) + # try: + # reaction, user = await self.bot.wait_for('reaction_add', check=check, timeout=120) + # except asyncio.TimeoutError: + # rcon_log.info('Message timed out...') + # if self.bot.dino_wipe_request.get(server_name): + # rcon_log.info('Starting dino wipe') + # await self.start_dinowipe(channel, server_name, server_con) + # rcon_log.info('Wild Dino Wipe Completed') + # return + # else: + # rcon_log.info('Dino Wipe Delayed.') + # await server_con.broadcast(f'Wild Dino Wipe has been delayed by {user.display_name}. ' + # f'Please watch chat for timing updates') + # await channel.send(f'Dino wipe has been delayed by {user.mention if user else "Game Chat"}...') + # for i in range(10): + # await asyncio.sleep(60) + # if i >= 5 or i == 0: + # await server_con.serverchat(f'The Wild Dino Wipe process will continue in {9 - i} ' + # f'{"minute" if 9 - i == 1 else "minutes"}') + # await self.request_dinowipe(requester, server_name, server_con) + # else: + # rcon_log.info('No channels configured, running wipe.') + # await asyncio.sleep(120) + # if not self.bot.dino_wipe_request.get(server_name): + # rcon_log.info('Wipe Delay requested') + # for i in range(10): + # await asyncio.sleep(60) + # await server_con.serverchat(f'The Wino Dino Wipe process will continue in {9 - i} ' + # f'{"minute" if 9 - i == 1 else "minutes"}') + # await self.request_dinowipe(requester, server_name, server_con) + # + # @commands.command(name='dinowipe') + # @commands.guild_only() + # async def run_dino_wipe(self, ctx, *, server=None): + # """Runs DestroyWildDinos on the specified ARK server. + # If a server is not specified it will default to wiping the wild dinos on all servers in the guild\'s config. + # Will print out "Wild Dinos Wiped on " for each server when the command completes successfully.""" + # if await checks.is_rcon_admin(self.bot, ctx): + # futures = [] + # async with ctx.typing(): + # if server is None: + # rcon_connections: dict = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name='*' + # ) + # if rcon_connections: + # for server_name, server_con in rcon_connections.items(): + # futures.append(self.start_dinowipe(ctx.channel, server_name, server_con)) + # self.bot.loop.create_task(asyncio.gather(*futures)) + # else: + # await ctx.send('There are no available servers for this guild.') + # else: + # server = server.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name=server + # ) + # if server_con: + # # noinspection PyTypeChecker + # await self.start_dinowipe(ctx.channel, server, server_con) + # else: + # await ctx.send(f'{server} is not currently in the configuration for this guild.') + # else: + # await ctx.send(f'You are not authorized to run this command.') + # + # @commands.command(name='run_command', aliases=['run']) + # @commands.guild_only() + # async def run_rcon_command(self, ctx, server=None, *, command=None): + # if await checks.is_rcon_admin(self.bot, ctx): + # if not server: + # await ctx.send('You must include a server when running this command.') + # return + # async with ctx.typing(): + # server = server.replace('_', ' ').title() + # server_con: arcon.ARKServer = await self.get_rcon_server_by_name( + # guild_config=ctx.guild_config, name=server + # ) + # if server_con: + # if not command: + # await ctx.send('You must include a command to run on the server.') + # return + # + # command = command.split(' ') + # + # if ctx.guild_config.get('allowed_rcon_commands'): + # pass + # + # response = await server_con.run_command(command=' '.join(command), multi_packet=True) + # if isinstance(response, str): + # await ctx.send(response) + # else: + # body = response.body + # pag = utils.Paginator(bot=self.bot) + # pag.add(body) + # book = utils.Book(pag, (None, ctx.channel, self.bot, ctx.message)) + # await book.create_book() + # else: + # await ctx.send('That server was not found in the config for this guild.') - @commands.command(aliases=['servers', 'list_servers']) - @commands.guild_only() - @commands.check(checks.is_restricted_chan) - async def list_ark_servers(self, ctx): - """Returns a list of all the ARK servers in the current guild\'s config.""" - servers = ctx.guild_config.get('rcon_connections', []) - em = discord.Embed(style='rich', - title=f'__**There are currently {len(servers)} ARK servers in my config:**__', - color=discord.Colour.green() - ) - if ctx.guild.icon: - em.set_thumbnail(url=f'{ctx.guild.icon_url}') - for server in servers: - description = f""" - ឵ **IP:** {servers[server]['ip']}:{servers[server]['port']} - ឵ **Steam Connect:** [steam://connect/{servers[server]['ip']}:{servers[server]['port']}]\ - (steam://connect/{servers[server]['ip']}:{servers[server]['port']})""" - em.add_field(name=f'__***{server}***__', value=description, inline=False) - await ctx.send(embed=em) - - @commands.command(name='server_chat') - @commands.guild_only() - async def send_chat_to_server(self, ctx, server: str=None, *, message: str=None): - if await checks.is_rcon_admin(self.bot, ctx): - if server is not None: - server = server.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name(guild_config=ctx.guild_config, - name=server) - if server_con: - if message is not None: - message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) - msg = await ctx.send(f'Sending "{message}" to {server}\'s chat') - response = await server_con.serverchat(message) - if response == 'Server received, But no response!!': - await msg.add_reaction(self.bot.unicode_emojis['y']) - else: - await msg.add_reaction(self.bot.unicode_emojis['x']) - else: - await ctx.send('You must include a message with this command.') - else: - await ctx.send(f'That server is not in my configuration.\nPlease add it via !add_rcon_server ' - f'"{server}" "ip" port "password" if you would like to get info from it.') - else: - await ctx.send('You must include a server with this command') - else: - await ctx.send('You are not authorized to run this command.') - - @commands.command(name='restart_server', aliases=['restart']) - @commands.guild_only() - async def restart_rcon_server(self, ctx, message: str, server_name: str=None, - delay_time: int=15, sleep_time: int=60): - if await checks.is_rcon_admin(self.bot, ctx): - - if server_name is None or server_name == 'all': - futures = [] - rcon_servers: dict = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name='*' - ) - for server_name, server_con in rcon_servers.items(): - message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) - futures.append(utils.restart_rcon_server(ctx, server_name=server_name, server_con=server_con, - message=message, delay=delay_time, sleep=sleep_time)) - self.bot.loop.create_task(asyncio.gather(*futures)) - - elif server_name.startswith('exclude='): - futures = [] - exclude_servers = server_name.split('exclude=')[1].replace('_', ' ').title().split(',') - rcon_servers: dict = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name='*' - ) - for server_name, server_con in rcon_servers.items(): - if server_name not in exclude_servers: - message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) - futures.append(utils.restart_rcon_server(ctx, server_name=server_name, server_con=server_con, - message=message, delay=delay_time, sleep=sleep_time)) - self.bot.loop.create_task(asyncio.gather(*futures)) - - else: - async with ctx.typing(): - server_name = server_name.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name=server_name - ) - if server_con: - message = ''.join(i for i in f'{ctx.author.display_name}: {message}' if ord(i) < 128) - await utils.restart_rcon_server(ctx, server_name=server_name, server_con=server_con, - message=message, delay=delay_time, sleep=sleep_time) - else: - await ctx.send(f'That server is not in my configuration.\nPlease add it via !add_rcon_server ' - f'"{server_name}" "ip" port "password" if you would like to get info from it.') - else: - await ctx.send('You are not authorized to run this command.') - - # noinspection PyShadowingNames - @staticmethod - async def start_dinowipe(channel, server_name: str, server_con: arcon.ARKServer): - msg = await channel.send(f'Wild dinos will be wiped on {server_name} in 2 minutes.') - await server_con.broadcast(f'Wild dino wipe incoming in 2 minutes, expect a small amount of lag while ' - f'the dinos repopulate.') - await asyncio.sleep(90) - await server_con.serverchat(f'Wild Dino Wipe in 30 seconds') - await asyncio.sleep(26) - await server_con.serverchat(f'Wild Dino Wipe in 3') - await asyncio.sleep(1) - await server_con.serverchat(f'Wild Dino Wipe in 2') - await asyncio.sleep(1) - await server_con.serverchat(f'Wild Dino Wipe in 1') - await asyncio.sleep(1) - response = await server_con.destroy_wild_dinos() - if response == 'All Wild Dinos Destroyed': - await msg.edit(content=f'Wild Dinos Wiped on {server_name}') - await server_con.serverchat(f'Wild dinos have been wiped.') - else: - await msg.edit(content=f'Failed to wipe wild dinos on {server_name}') - await server_con.serverchat(f'Wild Dino Wipe failed, Please let the Admin know of this issue') - - # noinspection PyShadowingNames,PyUnresolvedReferences - async def request_dinowipe(self, requester, server_name: str, server_con: arcon.ARKServer): - self.bot.dino_wipe_request[server_name] = True - if server_con.server_messages_channel and self.bot.get_channel(int(server_con.server_messages_channel)): - channel = self.bot.get_channel(int(server_con.server_messages_channel)) - else: - channel = self.bot.get_channel(server_con.server_chat_channel) - msg = False - if channel: - msg = await channel.send(f'@here {requester.mention} has requested wild dinos be wiped on the ' - f'{server_name} server\n' - f'If you are in the middle of taming or have some other reason to ' - f'delay the wipe please react to this message with ' - f'{self.bot.unicode_emojis["x"]}.\n' - f'Doing so will delay the wipe for 10 minutes.') - await server_con.broadcast(f'{requester.display_name} has requested wild dinos be wiped.\n' - f'if you are in the middle of taming or have some other reason to delay the wipe ' - f'please send a chat message containing "$delaywipe" here in-game.\n' - f'Doing so will delay the wipe for 10 minutes.') - await asyncio.sleep(5) - await server_con.serverchat('The wipe will continue in 2 minutes if there are no requests to delay. ' - 'Send a message containing $delaywipe to delay for 10 minutes.') - rcon_log.info('Dino Wipe messages sent') - if msg: - def check(reaction, user): - return str(reaction.emoji) == self.bot.unicode_emojis['x'] and reaction.message.id == msg.id and \ - user != self.bot.user - - user = None - await msg.add_reaction(self.bot.unicode_emojis['x']) - try: - reaction, user = await self.bot.wait_for('reaction_add', check=check, timeout=120) - except asyncio.TimeoutError: - rcon_log.info('Message timed out...') - if self.bot.dino_wipe_request.get(server_name): - rcon_log.info('Starting dino wipe') - await self.start_dinowipe(channel, server_name, server_con) - rcon_log.info('Wild Dino Wipe Completed') - return - else: - rcon_log.info('Dino Wipe Delayed.') - await server_con.broadcast(f'Wild Dino Wipe has been delayed by {user.display_name}. ' - f'Please watch chat for timing updates') - await channel.send(f'Dino wipe has been delayed by {user.mention if user else "Game Chat"}...') - for i in range(10): - await asyncio.sleep(60) - if i >= 5 or i == 0: - await server_con.serverchat(f'The Wild Dino Wipe process will continue in {9 - i} ' - f'{"minute" if 9 - i == 1 else "minutes"}') - await self.request_dinowipe(requester, server_name, server_con) - else: - rcon_log.info('No channels configured, running wipe.') - await asyncio.sleep(120) - if not self.bot.dino_wipe_request.get(server_name): - rcon_log.info('Wipe Delay requested') - for i in range(10): - await asyncio.sleep(60) - await server_con.serverchat(f'The Wino Dino Wipe process will continue in {9 - i} ' - f'{"minute" if 9 - i == 1 else "minutes"}') - await self.request_dinowipe(requester, server_name, server_con) - - @commands.command(name='dinowipe') - @commands.guild_only() - async def run_dino_wipe(self, ctx, *, server=None): - """Runs DestroyWildDinos on the specified ARK server. - If a server is not specified it will default to wiping the wild dinos on all servers in the guild\'s config. - Will print out "Wild Dinos Wiped on " for each server when the command completes successfully.""" - if await checks.is_rcon_admin(self.bot, ctx): - futures = [] - async with ctx.typing(): - if server is None: - rcon_connections: dict = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name='*' - ) - if rcon_connections: - for server_name, server_con in rcon_connections.items(): - futures.append(self.start_dinowipe(ctx.channel, server_name, server_con)) - self.bot.loop.create_task(asyncio.gather(*futures)) - else: - await ctx.send('There are no available servers for this guild.') - else: - server = server.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name=server - ) - if server_con: - # noinspection PyTypeChecker - await self.start_dinowipe(ctx.channel, server, server_con) - else: - await ctx.send(f'{server} is not currently in the configuration for this guild.') - else: - await ctx.send(f'You are not authorized to run this command.') - - @commands.command(name='run_command', aliases=['run']) - @commands.guild_only() - async def run_rcon_command(self, ctx, server=None, *, command=None): - if await checks.is_rcon_admin(self.bot, ctx): - if not server: - await ctx.send('You must include a server when running this command.') - return - async with ctx.typing(): - server = server.replace('_', ' ').title() - server_con: arcon.ARKServer = await self.get_rcon_server_by_name( - guild_config=ctx.guild_config, name=server - ) - if server_con: - if not command: - await ctx.send('You must include a command to run on the server.') - return - - command = command.split(' ') - - if ctx.guild_config.get('allowed_rcon_commands'): - pass - - response = await server_con.run_command(command=' '.join(command), multi_packet=True) - if isinstance(response, str): - await ctx.send(response) - else: - body = response.body - pag = utils.Paginator(bot=self.bot) - pag.add(body) - book = utils.Book(pag, (None, ctx.channel, self.bot, ctx.message)) - await book.create_book() - else: - await ctx.send('That server was not found in the config for this guild.') def setup(bot): bot.add_cog(Rcon(bot))