mirror of
https://github.com/Dinnerbone/mcstatus.git
synced 2026-04-06 03:51:23 +08:00
Added a MinecraftServer.lookup method, converts a string to host/port (including SRV lookup)
This closes #12
This commit is contained in:
@@ -3,6 +3,6 @@ python:
|
|||||||
- 3.3
|
- 3.3
|
||||||
- 2.7
|
- 2.7
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt --use-mirrors
|
- if [[ $TRAVIS_PYTHON_VERSION == 2* ]]; then pip install -r requirements/python2.txt --use-mirrors; fi
|
||||||
- pip install mock --use-mirrors
|
- if [[ $TRAVIS_PYTHON_VERSION == 3* ]]; then pip install -r requirements/python3.txt --use-mirrors; fi
|
||||||
script: nosetests
|
script: nosetests
|
||||||
16
README.md
16
README.md
@@ -2,7 +2,7 @@ mcstatus
|
|||||||
========
|
========
|
||||||
|
|
||||||
`mcstatus` provides an easy way to query Minecraft servers for any information they can expose.
|
`mcstatus` provides an easy way to query Minecraft servers for any information they can expose.
|
||||||
It provides two modes of access, `query` and `ping`, the differences of which are listed below in usage.
|
It provides three modes of access (`query`, `status` and `ping`), the differences of which are listed below in usage.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
@@ -10,15 +10,21 @@ Usage
|
|||||||
```python
|
```python
|
||||||
from mcstatus import MinecraftServer
|
from mcstatus import MinecraftServer
|
||||||
|
|
||||||
server = MinecraftServer("localhost", 25565)
|
# If you know the host and port, you may skip this and use MinecraftServer("example.org", 1234)
|
||||||
|
server = MinecraftServer.lookup("example.org:1234")
|
||||||
|
|
||||||
|
# 'status' is supported by all Minecraft servers that are version 1.7 or higher.
|
||||||
|
status = server.status()
|
||||||
|
print("The server has {0} players and replied in {1} ms".format(status.players.online, status.latency))
|
||||||
|
|
||||||
# 'ping' is supported by all Minecraft servers that are version 1.7 or higher.
|
# 'ping' is supported by all Minecraft servers that are version 1.7 or higher.
|
||||||
status, ping = server.ping_server()
|
# It is included in a 'status' call, but is exposed separate if you do not require the additional info.
|
||||||
print("The server has {0} players".format(status.players.online))
|
latency = server.ping()
|
||||||
|
print("The server replied in {0} ms".format(latency))
|
||||||
|
|
||||||
# 'query' has to be enabled in a servers' server.properties file.
|
# 'query' has to be enabled in a servers' server.properties file.
|
||||||
# It may give more information than a ping, such as a full player list or mod information.
|
# It may give more information than a ping, such as a full player list or mod information.
|
||||||
query = server.query_server()
|
query = server.query()
|
||||||
print("The server has the following players online: {0}".format(", ".join(query.players.names)))
|
print("The server has the following players online: {0}".format(", ".join(query.players.names)))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from mcstatus.pinger import ServerPinger
|
from mcstatus.pinger import ServerPinger
|
||||||
from mcstatus.protocol.connection import TCPSocketConnection, UDPSocketConnection
|
from mcstatus.protocol.connection import TCPSocketConnection, UDPSocketConnection
|
||||||
from mcstatus.querier import ServerQuerier
|
from mcstatus.querier import ServerQuerier
|
||||||
|
import dns.resolver
|
||||||
|
|
||||||
|
|
||||||
class MinecraftServer:
|
class MinecraftServer:
|
||||||
@@ -8,6 +9,29 @@ class MinecraftServer:
|
|||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def lookup(address):
|
||||||
|
host = address
|
||||||
|
port = None
|
||||||
|
if ":" in address:
|
||||||
|
parts = address.split(":")
|
||||||
|
if len(parts) > 2:
|
||||||
|
raise ValueError("Invalid address '%s'" % address)
|
||||||
|
host = parts[0]
|
||||||
|
port = int(parts[1])
|
||||||
|
if port is None:
|
||||||
|
port = 25565
|
||||||
|
try:
|
||||||
|
answers = dns.resolver.query("_minecraft._tcp." + host, "SRV")
|
||||||
|
if len(answers):
|
||||||
|
answer = answers[0]
|
||||||
|
host = str(answer.target).rstrip(".")
|
||||||
|
port = int(answer.port)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return MinecraftServer(host, port)
|
||||||
|
|
||||||
def ping(self, retries=3, **kwargs):
|
def ping(self, retries=3, **kwargs):
|
||||||
attempt = 0
|
attempt = 0
|
||||||
connection = TCPSocketConnection((self.host, self.port))
|
connection = TCPSocketConnection((self.host, self.port))
|
||||||
|
|||||||
@@ -81,4 +81,42 @@ class TestMinecraftServer(TestCase):
|
|||||||
with patch("mcstatus.server.ServerQuerier") as querier:
|
with patch("mcstatus.server.ServerQuerier") as querier:
|
||||||
querier.side_effect = [Exception, Exception, Exception]
|
querier.side_effect = [Exception, Exception, Exception]
|
||||||
self.assertRaises(Exception, self.server.query)
|
self.assertRaises(Exception, self.server.query)
|
||||||
self.assertEqual(querier.call_count, 3)
|
self.assertEqual(querier.call_count, 3)
|
||||||
|
|
||||||
|
def test_by_address_no_srv(self):
|
||||||
|
with patch("dns.resolver.query") as query:
|
||||||
|
query.return_value = []
|
||||||
|
self.server = MinecraftServer.lookup("example.org")
|
||||||
|
query.assert_called_once_with("_minecraft._tcp.example.org", "SRV")
|
||||||
|
self.assertEqual(self.server.host, "example.org")
|
||||||
|
self.assertEqual(self.server.port, 25565)
|
||||||
|
|
||||||
|
def test_by_address_invalid_srv(self):
|
||||||
|
with patch("dns.resolver.query") as query:
|
||||||
|
query.side_effect = [Exception]
|
||||||
|
self.server = MinecraftServer.lookup("example.org")
|
||||||
|
query.assert_called_once_with("_minecraft._tcp.example.org", "SRV")
|
||||||
|
self.assertEqual(self.server.host, "example.org")
|
||||||
|
self.assertEqual(self.server.port, 25565)
|
||||||
|
|
||||||
|
def test_by_address_with_srv(self):
|
||||||
|
with patch("dns.resolver.query") as query:
|
||||||
|
answer = Mock()
|
||||||
|
answer.target = "different.example.org."
|
||||||
|
answer.port = 12345
|
||||||
|
query.return_value = [answer]
|
||||||
|
self.server = MinecraftServer.lookup("example.org")
|
||||||
|
query.assert_called_once_with("_minecraft._tcp.example.org", "SRV")
|
||||||
|
self.assertEqual(self.server.host, "different.example.org")
|
||||||
|
self.assertEqual(self.server.port, 12345)
|
||||||
|
|
||||||
|
def test_by_address_with_port(self):
|
||||||
|
self.server = MinecraftServer.lookup("example.org:12345")
|
||||||
|
self.assertEqual(self.server.host, "example.org")
|
||||||
|
self.assertEqual(self.server.port, 12345)
|
||||||
|
|
||||||
|
def test_by_address_with_multiple_ports(self):
|
||||||
|
self.assertRaises(ValueError, MinecraftServer.lookup, "example.org:12345:6789")
|
||||||
|
|
||||||
|
def test_by_address_with_invalid_port(self):
|
||||||
|
self.assertRaises(ValueError, MinecraftServer.lookup, "example.org:port")
|
||||||
@@ -1 +1 @@
|
|||||||
six==1.7.3
|
-r requirements/base.txt
|
||||||
2
requirements/base.txt
Normal file
2
requirements/base.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
six==1.7.3
|
||||||
|
mock==1.0.1
|
||||||
3
requirements/python2.txt
Normal file
3
requirements/python2.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-r base.txt
|
||||||
|
|
||||||
|
dnspython==1.12.0
|
||||||
3
requirements/python3.txt
Normal file
3
requirements/python3.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-r base.txt
|
||||||
|
|
||||||
|
dnspython3==1.12.0
|
||||||
18
setup.py
18
setup.py
@@ -1,4 +1,18 @@
|
|||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
|
from six import PY2
|
||||||
|
|
||||||
|
install_requires = [
|
||||||
|
'six'
|
||||||
|
]
|
||||||
|
|
||||||
|
if PY2:
|
||||||
|
install_requires.append('dnspython')
|
||||||
|
else:
|
||||||
|
install_requires.append('dnspython3')
|
||||||
|
|
||||||
|
tests_require = [
|
||||||
|
'mock'
|
||||||
|
]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='mcstatus',
|
name='mcstatus',
|
||||||
@@ -8,8 +22,8 @@ setup(
|
|||||||
url='https://pypi.python.org/pypi/mcstatus',
|
url='https://pypi.python.org/pypi/mcstatus',
|
||||||
packages=['mcstatus', 'mcstatus.protocol'],
|
packages=['mcstatus', 'mcstatus.protocol'],
|
||||||
description='A library to query Minecraft Servers for their status and capabilities.',
|
description='A library to query Minecraft Servers for their status and capabilities.',
|
||||||
install_requires=['six'],
|
install_requires=install_requires,
|
||||||
tests_require=['mock'],
|
tests_require=tests_require,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
|
|||||||
Reference in New Issue
Block a user