Advertisement
Guest User

Untitled

a guest
Aug 18th, 2019
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.63 KB | None | 0 0
  1. #!/home/winston/venv/ping_servers/bin/python
  2. # pip3 install nbt mcstatus tabulate
  3.  
  4.  
  5. """
  6. Ping servers in the servers.dat
  7.  
  8. Works on Mac, should work on Windows and Linux.
  9. """
  10.  
  11.  
  12. from nbt.nbt import NBTFile
  13. import os
  14. from mcstatus import MinecraftServer
  15. from collections import namedtuple
  16. import platform
  17. import multiprocessing
  18. from tabulate import tabulate
  19.  
  20.  
  21. Server = namedtuple('Server', ['name', 'ip', 'port'])
  22. PingResult = namedtuple('PingResult', ['server', 'status', 'error'])
  23.  
  24. # To deal with a Pickler error on the PingResponse object.
  25. Status = namedtuple('Status', ['players', 'latency', 'motd', 'version'])
  26. Players = namedtuple('Players', ['online', 'max'])
  27.  
  28.  
  29. MINECRAFT_DIRS = {
  30. 'Darwin': 'Library/Application Support/minecraft',
  31. 'Linux': '.minecraft',
  32. 'Windows': '.minecraft',
  33. }
  34.  
  35.  
  36. def get_minecraft_dir():
  37. return os.path.join(
  38. os.getenv('HOME'),
  39. MINECRAFT_DIRS[platform.system()]
  40. )
  41.  
  42.  
  43. def get_servers():
  44. minecraft_dir = get_minecraft_dir()
  45. os.chdir(minecraft_dir)
  46. with open('servers.dat', 'rb') as buf:
  47. s = NBTFile(buffer=buf)
  48. for server in s['servers']:
  49. name = server['name'].valuestr()
  50. address = server['ip'].valuestr()
  51. ip, port = get_host_port(address)
  52. yield Server(name=name, ip=ip, port=port)
  53.  
  54.  
  55. def get_host_port(address, default=25565):
  56. address = address.strip(' \t')
  57. if address[0] == '[' or address.count(':') == 1:
  58. host, _, port = address.rpartition(':')
  59. return host.strip('[]'), int(port)
  60. return address, default
  61.  
  62.  
  63. def ping_server(server):
  64. s = MinecraftServer(server.ip, server.port)
  65. try:
  66. res = s.status()
  67. # avoid pickler error on PingResponse class
  68. p = Players(res.players.online, res.players.max)
  69. res = Status(
  70. players=p,
  71. latency=res.latency,
  72. motd=res.description,
  73. version=res.version.name,
  74. )
  75. error = None
  76. except IOError as ex:
  77. res = None
  78. error = ex
  79. return PingResult(server, res, error)
  80.  
  81.  
  82. def ping_servers(servers):
  83. for server in servers:
  84. yield ping_server(server)
  85.  
  86.  
  87. def ping_servers_async(servers):
  88. pool = multiprocessing.Pool(10)
  89. yield from pool.map(ping_server, servers)
  90.  
  91.  
  92. def format_address(ip, port, default_port=25565):
  93. if int(port) == default_port:
  94. return ip
  95. L = []
  96. if ':' in ip: # ipv6
  97. L.append('[', ip, ']')
  98. else:
  99. L.append(ip)
  100. L.extend([':', str(port)])
  101. return ''.join(L)
  102.  
  103.  
  104. def format_server(s):
  105. head = '{0} ({1})'.format(
  106. s.server.name,
  107. format_address(s.server.ip, s.server.port),
  108. )
  109. if not s.status:
  110. body = 'is offline.'
  111. else:
  112. body = '{v}, has {online}/{cap} players, ~{lag} ms lag.'.format(
  113. # s.status.motd,
  114. v=s.status.version,
  115. online=s.status.players.online,
  116. cap=s.status.players.max,
  117. lag=round(s.status.latency),
  118. )
  119. return ' '.join([head, body])
  120.  
  121.  
  122. def tabulate_servers(servers):
  123. L = []
  124. for s in servers:
  125. entry = [s.server.name, format_address(s.server.ip, s.server.port)]
  126. if s.status:
  127. entry.extend([
  128. s.status.version,
  129. s.status.players.online,
  130. s.status.players.max,
  131. round(s.status.latency),
  132. ])
  133. else:
  134. entry.extend([None]*4)
  135. L.append(entry)
  136. return tabulate(
  137. L,
  138. headers=['Name', 'Address', 'Version', 'Online', 'Max', 'Lag (ms)'],
  139. )
  140.  
  141.  
  142. def main():
  143. responses = ping_servers_async(get_servers())
  144. print(tabulate_servers(responses))
  145.  
  146.  
  147. if __name__ == '__main__':
  148. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement