class BotClient(discord.Client): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.mcsa = MCServerActions() self.chat_service = ChatService() self.bg_task = self.loop.create_task(self.background_task()) async def on_ready(self): print(f"We have logged in as {client.user}") async def on_message(self, message: discord.message.Message): if self.chat_service.filter_message(message, client): return await message.channel.send(self.chat_service.handle_message(message)) async def background_task(self): await self.wait_until_ready() channel = self.get_channel(MC_CHANNEL_ID) while not self.is_closed(): if self.mcsa.shutdown_if_server_inactive(): await channel.send("Server inactive, shutting down") await asyncio.sleep(SERVER_CHECK_INTERVAL)
def test_shutdown_if_server_inactive_instance_stopped( self, aws_service_mock, mc_service_mock): aws_service_mock.return_value.is_instance_running = False mcsa = MCServerActions() shutdown_action = mcsa.shutdown_if_server_inactive() self.assertEqual( aws_service_mock.return_value.update_instance_details.call_count, 2) mc_service_mock.assert_not_called() self.assertIsNone(mcsa.mc_service) aws_service_mock.return_value.stop_instance.assert_not_called() self.assertFalse(shutdown_action)
def test_shutdown_if_server_inactive_instance_running_server_offline( self, aws_service_mock, mc_service_mock): aws_service_mock.return_value.is_instance_running = True aws_service_mock.return_value.instance_ip = MOCK_INSTANCE_IP mc_service_mock.return_value = None mcsa = MCServerActions() shutdown_action = mcsa.shutdown_if_server_inactive() self.assertEqual( aws_service_mock.return_value.update_instance_details.call_count, 3) mc_service_mock.assert_called_with(MOCK_INSTANCE_IP) self.assertIsNone(mcsa.mc_service) aws_service_mock.return_value.stop_instance.assert_called_once() self.assertTrue(shutdown_action)
def test_shutdown_if_server_inactive_instance_running_server_running_inactive( self, aws_service_mock, mc_service_mock): aws_service_mock.return_value.is_instance_running = True aws_service_mock.return_value.instance_ip = MOCK_INSTANCE_IP mc_service_mock.return_value.number_of_users = INACTIVE_NUMBER_OF_USERS mcsa = MCServerActions() shutdown_action = mcsa.shutdown_if_server_inactive() self.assertEqual( aws_service_mock.return_value.update_instance_details.call_count, 3) mc_service_mock.assert_called_once_with(MOCK_INSTANCE_IP) mc_service_mock.return_value.stop_server.assert_called_once() aws_service_mock.return_value.stop_instance.assert_called_once() self.assertTrue(shutdown_action)
class ChatService: def __init__(self): self.mcsa = MCServerActions() def filter_message(self, message: discord.message.Message, client: discord.client.Client) -> bool: if message.author == client.user: return True if AUTHORIZED_CHANNEL != message.channel.name: return True user_role_names = [role.name for role in message.author.roles] if AUTHORIZED_ROLE not in user_role_names: return True if not message.content.startswith("!mc "): return True return False def handle_message(self, message: discord.message.Message) -> str: message_params = message.content.split(" ")[1:] number_of_arguments = len(message_params) if number_of_arguments == 2: if message_params[0] == "server" and message_params[1] == "status": return "Server status:\n" + self._server_status() elif message_params[0] == "server" and message_params[1] == "start": return self._server_start() elif message_params[0] == "server" and message_params[1] == "stop": return self._server_stop_check() elif number_of_arguments == 3: if (message_params[0] == "server" and message_params[1] == "stop" and message_params[2] == "force"): return self._server_stop() return self._help_message() def _server_status(self, is_server_starting=False, is_server_stopping=False) -> str: server_status = self.mcsa.get_server_status() aws_instance = server_status.get("aws_instance") mc_server = server_status.get("mc_server") instance_state = aws_instance.get("state") is_instance_running = aws_instance.get("is_running") instance_ip = aws_instance.get("ip") is_server_reachable = mc_server.get("is_server_reachable") mc_active_users = mc_server.get("active_users", 0) mc_max_users = mc_server.get("max_users", 0) mc_users = mc_server.get("users", []) message = f"\t Instance State: {instance_state}\n" if is_instance_running: message += f"\t Server IP: {instance_ip}:25565\n" if is_server_stopping: message += "\t Server State: stopping\n" elif is_server_reachable: message += "\t Server State: running\n" message += f"\t Users: {mc_active_users}/{mc_max_users} online\n" if mc_active_users: for user in mc_users: message += f"\t\t - {user}\n" elif not is_server_reachable and is_server_starting: message += "\t Server State: starting\n" elif not is_server_reachable and is_instance_running: message += "\n Minecraft Server not reachable!\n" return message def _server_start(self) -> str: message = "" if self.mcsa.start_server(): message = "Instance Starting:\n" + self._server_status( is_server_starting=True) else: message = "Instance Already Running:\n" + self._server_status( is_server_starting=True) return message def _server_stop_check(self) -> str: message = "" if self.mcsa.shutdown_if_server_inactive(): message = "Server Stopping:\n" + self._server_status( is_server_stopping=True) else: message = "Server Not Stopped:\n" + self._server_status() return message def _server_stop(self) -> str: message = "" if self.mcsa.shutdown_server(): message = "Server Stopping:\n" + self._server_status( is_server_stopping=True) else: message = "Server Already Stopped:\n" + self._server_status() return message def _help_message(self) -> str: return ("Available Commands:\n" "\t- !mc server status\n" "\t- !mc server start\n" "\t- !mc server stop\n" "\t- !mc server stop force\n")