From a6ade86fad53f0cf5e38f790cc6db77df670747d Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Thu, 25 Sep 2014 23:53:15 +0200 Subject: [PATCH] API changes to server (closes #14) --- mcstatus/pinger.py | 4 +++- mcstatus/server.py | 22 ++++++++++++++++--- mcstatus/tests/test_server.py | 41 +++++++++++++++++++++++++---------- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/mcstatus/pinger.py b/mcstatus/pinger.py index 0b0a64e..9fcbf64 100644 --- a/mcstatus/pinger.py +++ b/mcstatus/pinger.py @@ -137,4 +137,6 @@ class PingResponse: self.description = raw["description"] if "favicon" in raw: - self.favicon = raw["favicon"] \ No newline at end of file + self.favicon = raw["favicon"] + + self.latency = None \ No newline at end of file diff --git a/mcstatus/server.py b/mcstatus/server.py index 2b12f2e..5e70c90 100644 --- a/mcstatus/server.py +++ b/mcstatus/server.py @@ -8,7 +8,7 @@ class MinecraftServer: self.host = host self.port = port - def ping_server(self, retries=3, **kwargs): + def ping(self, retries=3, **kwargs): attempt = 0 connection = TCPSocketConnection((self.host, self.port)) exception = None @@ -16,13 +16,29 @@ class MinecraftServer: try: pinger = ServerPinger(connection, host=self.host, port=self.port, **kwargs) pinger.handshake() - return pinger.read_status(), pinger.test_ping() + return pinger.test_ping() except Exception as e: exception = e attempt += 1 raise exception - def query_server(self, retries=3): + def status(self, retries=3, **kwargs): + attempt = 0 + connection = TCPSocketConnection((self.host, self.port)) + exception = None + while attempt < retries: + try: + pinger = ServerPinger(connection, host=self.host, port=self.port, **kwargs) + pinger.handshake() + result = pinger.read_status() + result.latency = pinger.test_ping() + return result + except Exception as e: + exception = e + attempt += 1 + raise exception + + def query(self, retries=3): attempt = 0 exception = None while attempt < retries: diff --git a/mcstatus/tests/test_server.py b/mcstatus/tests/test_server.py index b7ce100..bcb9579 100644 --- a/mcstatus/tests/test_server.py +++ b/mcstatus/tests/test_server.py @@ -11,27 +11,46 @@ class TestMinecraftServer(TestCase): self.socket = Connection() self.server = MinecraftServer("localhost", port=25565) - def test_ping_server(self): - self.socket.receive(bytearray.fromhex("6D006B7B226465736372697074696F6E223A2241204D696E65637261667420536572766572222C22706C6179657273223A7B226D6178223A32302C226F6E6C696E65223A307D2C2276657273696F6E223A7B226E616D65223A22312E38222C2270726F746F636F6C223A34377D7D09010000000001C54246")) + def test_ping(self): + self.socket.receive(bytearray.fromhex("09010000000001C54246")) with patch("mcstatus.server.TCPSocketConnection") as connection: connection.return_value = self.socket - info, latency = self.server.ping_server(ping_token=29704774, version=47) + latency = self.server.ping(ping_token=29704774, version=47) - self.assertEqual(self.socket.flush(), bytearray.fromhex("0F002F096C6F63616C686F737463DD01010009010000000001C54246")) + self.assertEqual(self.socket.flush(), bytearray.fromhex("0F002F096C6F63616C686F737463DD0109010000000001C54246")) self.assertEqual(self.socket.remaining(), 0, msg="Data is pending to be read, but should be empty") - self.assertEqual(info.raw, {"description":"A Minecraft Server","players":{"max":20,"online":0},"version":{"name":"1.8","protocol":47}}) self.assertTrue(latency >= 0) - def test_ping_server_retry(self): + def test_ping_retry(self): with patch("mcstatus.server.TCPSocketConnection") as connection: connection.return_value = None with patch("mcstatus.server.ServerPinger") as pinger: pinger.side_effect = [Exception, Exception, Exception] - self.assertRaises(Exception, self.server.ping_server) + self.assertRaises(Exception, self.server.ping) self.assertEqual(pinger.call_count, 3) - def test_query_server(self): + def test_status(self): + self.socket.receive(bytearray.fromhex("6D006B7B226465736372697074696F6E223A2241204D696E65637261667420536572766572222C22706C6179657273223A7B226D6178223A32302C226F6E6C696E65223A307D2C2276657273696F6E223A7B226E616D65223A22312E38222C2270726F746F636F6C223A34377D7D09010000000001C54246")) + + with patch("mcstatus.server.TCPSocketConnection") as connection: + connection.return_value = self.socket + info = self.server.status(ping_token=29704774, version=47) + + self.assertEqual(self.socket.flush(), bytearray.fromhex("0F002F096C6F63616C686F737463DD01010009010000000001C54246")) + self.assertEqual(self.socket.remaining(), 0, msg="Data is pending to be read, but should be empty") + self.assertEqual(info.raw, {"description":"A Minecraft Server","players":{"max":20,"online":0},"version":{"name":"1.8","protocol":47}}) + self.assertTrue(info.latency >= 0) + + def test_status_retry(self): + with patch("mcstatus.server.TCPSocketConnection") as connection: + connection.return_value = None + with patch("mcstatus.server.ServerPinger") as pinger: + pinger.side_effect = [Exception, Exception, Exception] + self.assertRaises(Exception, self.server.ping) + self.assertEqual(pinger.call_count, 3) + + def test_query(self): self.socket.receive(bytearray.fromhex("090000000035373033353037373800")) self.socket.receive(bytearray.fromhex("00000000000000000000000000000000686f73746e616d650041204d696e656372616674205365727665720067616d657479706500534d500067616d655f6964004d494e4543524146540076657273696f6e00312e3800706c7567696e7300006d617000776f726c64006e756d706c61796572730033006d6178706c617965727300323000686f7374706f727400323535363500686f73746970003139322e3136382e35362e31000001706c617965725f000044696e6e6572626f6e6500446a696e6e69626f6e650053746576650000")) @@ -40,7 +59,7 @@ class TestMinecraftServer(TestCase): with patch("mcstatus.server.UDPSocketConnection") as connection: connection.return_value = self.socket - info = self.server.query_server() + info = self.server.query() self.assertEqual(self.socket.flush(), bytearray.fromhex("FEFD090000000000000000FEFD000000000021FEDCBA00000000")) self.assertEqual(info.raw, { @@ -56,10 +75,10 @@ class TestMinecraftServer(TestCase): "hostip": "192.168.56.1", }) - def test_query_server_retry(self): + def test_query_retry(self): with patch("mcstatus.server.UDPSocketConnection") as connection: connection.return_value = None with patch("mcstatus.server.ServerQuerier") as querier: querier.side_effect = [Exception, Exception, Exception] - self.assertRaises(Exception, self.server.query_server) + self.assertRaises(Exception, self.server.query) self.assertEqual(querier.call_count, 3) \ No newline at end of file