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
|
||||
- 2.7
|
||||
install:
|
||||
- pip install -r requirements.txt --use-mirrors
|
||||
- pip install mock --use-mirrors
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 2* ]]; then pip install -r requirements/python2.txt --use-mirrors; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 3* ]]; then pip install -r requirements/python3.txt --use-mirrors; fi
|
||||
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.
|
||||
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
|
||||
-----
|
||||
@@ -10,15 +10,21 @@ Usage
|
||||
```python
|
||||
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.
|
||||
status, ping = server.ping_server()
|
||||
print("The server has {0} players".format(status.players.online))
|
||||
# It is included in a 'status' call, but is exposed separate if you do not require the additional info.
|
||||
latency = server.ping()
|
||||
print("The server replied in {0} ms".format(latency))
|
||||
|
||||
# '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.
|
||||
query = server.query_server()
|
||||
query = server.query()
|
||||
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.protocol.connection import TCPSocketConnection, UDPSocketConnection
|
||||
from mcstatus.querier import ServerQuerier
|
||||
import dns.resolver
|
||||
|
||||
|
||||
class MinecraftServer:
|
||||
@@ -8,6 +9,29 @@ class MinecraftServer:
|
||||
self.host = host
|
||||
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):
|
||||
attempt = 0
|
||||
connection = TCPSocketConnection((self.host, self.port))
|
||||
|
||||
@@ -81,4 +81,42 @@ class TestMinecraftServer(TestCase):
|
||||
with patch("mcstatus.server.ServerQuerier") as querier:
|
||||
querier.side_effect = [Exception, Exception, Exception]
|
||||
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 six import PY2
|
||||
|
||||
install_requires = [
|
||||
'six'
|
||||
]
|
||||
|
||||
if PY2:
|
||||
install_requires.append('dnspython')
|
||||
else:
|
||||
install_requires.append('dnspython3')
|
||||
|
||||
tests_require = [
|
||||
'mock'
|
||||
]
|
||||
|
||||
setup(
|
||||
name='mcstatus',
|
||||
@@ -8,8 +22,8 @@ setup(
|
||||
url='https://pypi.python.org/pypi/mcstatus',
|
||||
packages=['mcstatus', 'mcstatus.protocol'],
|
||||
description='A library to query Minecraft Servers for their status and capabilities.',
|
||||
install_requires=['six'],
|
||||
tests_require=['mock'],
|
||||
install_requires=install_requires,
|
||||
tests_require=tests_require,
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
|
||||
Reference in New Issue
Block a user