def test_get_server_status_instance_running_server_running_inactive(
            self, aws_service_mock, mc_service_mock):
        aws_service_mock.return_value.instance_state = INSTANCE_RUNNING_STATE
        aws_service_mock.return_value.instance_ip = MOCK_INSTANCE_IP
        aws_service_mock.return_value.is_instance_running = True
        mc_service_mock.return_value.number_of_users = INACTIVE_NUMBER_OF_USERS
        mc_service_mock.return_value.max_users = MAX_NUMBER_OF_USERS
        mc_service_mock.return_value.users = INACTIVE_MC_USERNAMES

        mcsa = MCServerActions()
        server_status = mcsa.get_server_status()
        aws_instance = server_status.get("aws_instance")
        mc_server = server_status.get("mc_server")

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            2)
        mc_service_mock.assert_called_once()
        mc_service_mock.assert_called_with(MOCK_INSTANCE_IP)
        mc_service_mock.return_value.update_server_details.assert_called_once()
        self.assertEqual(aws_instance.get("state"), INSTANCE_RUNNING_STATE)
        self.assertEqual(aws_instance.get("ip"), MOCK_INSTANCE_IP)
        self.assertTrue(aws_instance.get("is_running"))
        self.assertFalse(mc_server.get("is_active"))
        self.assertTrue(mc_server.get("is_server_reachable"))
        self.assertEqual(mc_server.get("active_users"),
                         INACTIVE_NUMBER_OF_USERS)
        self.assertEqual(mc_server.get("max_users"), MAX_NUMBER_OF_USERS)
        self.assertEqual(mc_server.get("users"), INACTIVE_MC_USERNAMES)
    def test_update_mc_server_details_instance_running_mc_connection(
            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

        mcsa = MCServerActions()
        mcsa._update_mc_server_details()

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            2)
        mc_service_mock.assert_called_once_with(MOCK_INSTANCE_IP)
        mc_service_mock.return_value.update_server_details.assert_called_once()
    def test_start_server_instance_stopped(self, aws_service_mock,
                                           mc_service_mock):
        aws_service_mock.return_value.is_instance_running = False

        mcsa = MCServerActions()
        start_action = mcsa.start_server()

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            1)
        mc_service_mock.assert_not_called()
        self.assertIsNone(mcsa.mc_service)
        aws_service_mock.return_value.start_instance.assert_called_once()
        self.assertTrue(start_action)
    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_server_instance_running_server_running(
            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

        mcsa = MCServerActions()
        shutdown_action = mcsa.shutdown_server()

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            2)
        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)
    def test_start_server_instance_running(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
        aws_service_mock.return_value.start_instance.return_value = False

        mcsa = MCServerActions()
        start_action = mcsa.start_server()

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            1)
        mc_service_mock.assert_called_with(MOCK_INSTANCE_IP)
        aws_service_mock.return_value.start_instance.assert_called_once()
        self.assertFalse(start_action)
    def test_shutdown_server_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 = None

        mcsa = MCServerActions()
        shutdown_action = mcsa.shutdown_server()

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            2)
        mc_service_mock.assert_not_called()
        mc_service_mock.return_value.stop_server.assert_not_called()
        aws_service_mock.return_value.stop_instance.assert_called_once()
        self.assertTrue(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)
Example #9
0
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_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)
    def test_update_mc_server_details_instance_stopped(self, aws_service_mock,
                                                       mc_service_mock):
        aws_service_mock.return_value.is_instance_running = False

        mcsa = MCServerActions()

        aws_service_mock.return_value.update_instance_details.assert_called()
        mc_service_mock.assert_not_called()
    def test_update_mc_server_details_instance_running(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

        mcsa = MCServerActions()

        aws_service_mock.return_value.update_instance_details.assert_called_once(
        )
        mc_service_mock.assert_called_once_with(MOCK_INSTANCE_IP)
    def test_get_server_status_instance_stopped(self, aws_service_mock,
                                                mc_service_mock):
        aws_service_mock.return_value.instance_state = INSTANCE_STOPPED_STATE
        aws_service_mock.return_value.instance_ip = None
        aws_service_mock.return_value.is_instance_running = False

        mcsa = MCServerActions()
        server_status = mcsa.get_server_status()
        aws_instance = server_status.get("aws_instance")
        mc_server = server_status.get("mc_server")

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            2)
        mc_service_mock.assert_not_called()
        self.assertEqual(aws_instance.get("state"), INSTANCE_STOPPED_STATE)
        self.assertIsNone(aws_instance.get("ip"))
        self.assertFalse(aws_instance.get("is_running"))
        self.assertEqual(mc_server, {})
    def test_get_server_status_instance_running_server_stopped(
            self, aws_service_mock, mc_service_mock):
        aws_service_mock.return_value.instance_state = INSTANCE_RUNNING_STATE
        aws_service_mock.return_value.instance_ip = MOCK_INSTANCE_IP
        aws_service_mock.return_value.is_instance_running = True
        mc_service_mock.return_value = None

        mcsa = MCServerActions()
        server_status = mcsa.get_server_status()
        aws_instance = server_status.get("aws_instance")
        mc_server = server_status.get("mc_server")

        self.assertEqual(
            aws_service_mock.return_value.update_instance_details.call_count,
            2)
        self.assertEqual(mc_service_mock.call_count, 2)
        mc_service_mock.assert_called_with(MOCK_INSTANCE_IP)
        self.assertEqual(aws_instance.get("state"), INSTANCE_RUNNING_STATE)
        self.assertEqual(aws_instance.get("ip"), MOCK_INSTANCE_IP)
        self.assertTrue(aws_instance.get("is_running"))
        self.assertEqual(mc_server, {})
Example #15
0
    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())
Example #16
0
 def __init__(self):
     self.mcsa = MCServerActions()
Example #17
0
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")