def query(): address = request.args.get("address") port = int(request.args.get("port")) conn = MinecraftServer(address, port) try: conn.ping() # except ConnectionRefusedError: # Commented out because for some reason on the production server, # attempting to catch this error causes the site to break and display # 'Internal Server Error'. Logs from such events say that # 'ConnectionRefusedError' is undefined, although there seem to be no # issues when testing locally. except: response = jsonify({ "status": "Offline", "players_online": 0, "player_names": None, }) else: q = conn.query() response = jsonify({ "status": "Online", "players_online": q.players.online, "players_max": q.players.max, "player_names": q.players.names, }) return response
def index(): """Index (and only) page of site.""" render_obj = [] message_objects = Message.query.filter_by(display=True).all() server_objects = Server.query.all() for server in server_objects: address = server.address port = server.port conn = MinecraftServer(address, port) try: conn.ping() # except ConnectionRefusedError: # Commented out because for some reason on the production server, # attempting to catch this error causes the site to break and display # 'Internal Server Error'. Logs from such events say that # 'ConnectionRefusedError' is undefined, although there seem to be no # issues when testing locally. except: render_obj.append({ "address": address, "port": port, "modpack_version": server.modpack_version, "client_config": server.client_config, "status": "Offline", }) else: add_to_render = {} q = conn.query() motd = q.motd players = { "max": q.players.max, "online": q.players.online, "names": q.players.names, } jar_version = q.software.version add_to_render.update({ "address": address, "port": port, "modpack_version": server.modpack_version, "client_config": server.client_config, "status": "Online", "motd": motd, "players": players, "jar_version": jar_version, }) render_obj.append(add_to_render) return render_template( "index.html", servers=render_obj, messages=message_objects, )
class minecraftStatus(models.Model): # TODO: add query to get online player usernames def __init__(self): self.server = MinecraftServer("minecraft-1", 25565) def reload(self): try: self.ping() self.status() self.onlinePlayers() return True except Exception as e: self.error = e return False def status(self): raw = self.server.status().raw self.description = raw['description']['text'] self.players = raw['players']['online'] self.version = raw['version']['name'] def onlinePlayers (self): self.playerNames = self.server.query().players.names def ping(self): self.latency = self.server.ping() def get_absolute_url(self): """Returns the url to access a particular instance of MyModelName.""" return reverse('model-detail-view', args=[str(self.id)])
def checkserver(): try: global oldList global newList global online if not online: toaster.show_toast("Info", "Server has Startet!") online = True server = MinecraftServer(cfg.ip, cfg.port) # 'query' has to be enabled in a servers' server.properties file. query = server.query() newList = query.players.names newList.sort() print(newList) if newList != oldList: print("changed") checklists(oldList, newList) oldList = newList else: print("same") except: print("Server not reachable!") if online: toaster.show_toast("Error", "Server crashed!") online = False return
def get_status(self): print("MC Server: {} at {}:{}".format(self.name, self.address, self.query_port)) self.reset_status() server = MinecraftServer(self.address, self.query_port) try: response = server.query() self.software.version = response.software.version self.software.brand = response.software.brand.split(" ", 1)[0].strip() self.players.online = response.players.online self.players.max = response.players.max self.players.names = sorted(response.players.names, key=str.lower) if not self.status_override: self.status = Status.ONLINE except Exception as e: print(e) if not self.status_override: self.status = Status.OFFLINE print("> Version: {} {}, Players: {}/{}, Status: {}, Message: {}".format( \ self.software.brand, \ self.software.version, \ self.players.online, \ self.players.max, \ self.status.name, \ self.message))
async def playerCountUpdate(): """Bot status for player count in the sidebar and output. The top part of this function is for the sidebar player count, the bottom part is for the output channel (if requested). """ await client.wait_until_ready() while not client.is_closed(): #Sidebar portion mcServer = MinecraftServer(cIP, cPort) serverStatus = mcServer.status() sidebarCount = discord.Game('{0} Players Online'.format(serverStatus.players.online)) await client.change_presence(status=discord.Status.online, activity=sidebarCount) #Output portion if cEnableNames is True: mcQuery = mcServer.query() try: lastSetOfPlayers except NameError: lastSetOfPlayers = "Notch" #Check if requested if cEnableOutput is True and cEnableNames is True: if cDynamicOutput is True: #This is dynamic output, essentially sending a new output #message only when player counts change. diffOfPlayers = (mcQuery.players.names != lastSetOfPlayers) if diffOfPlayers is True: lastSetOfPlayers = mcQuery.players.names if serverStatus.players.online != 0: playerNames = ", ".join(mcQuery.players.names) outputMessage = """ {0} | {1} Players Online | {2}""".format(getTime(), serverStatus.players.online, playerNames) else: outputMessage = ("{0} | No players online".format(getTime())) if diffOfPlayers is True: await cOutputChannel.send(outputMessage) elif cDynamicOutput is False: #Just print every <cRefresh> seconds if serverStatus.players.online != 0: playerNames = ", ".join(mcQuery.players.names) outputMessage = """ {0} | {1} Players Online | {2}""".format(getTime(), serverStatus.players.online, playerNames) else: outputMessage = ("{0} | No players online".format(getTime())) await cOutputChannel.send(outputMessage) #Change the player count on the basis of how many seconds were inputted into cRefresh await asyncio.sleep(int(cRefresh))
async def playerlist(ctx): # crating the query object serverquery = MinecraftServer(IP, QPORT) query = serverquery.query() # creating the embed ListEmbed = discord.Embed(colour=discord.Colour.light_gray()) ListEmbed.set_author( name="The server has the following players online: {0}".format( ", ".join(query.players.names))) # sending the embed in the channel the command was run in await ctx.send(embed=ListEmbed)
async def players(ctx): await ctx.send("Checking who is playing") instance = get_instance_state() if instance.state["Name"] == "running": server = MinecraftServer(instance.public_ip_address, 25565) query = server.query() if query.players.online > 0: await ctx.send("Currently playing:\n {0}".format("\n".join( query.players.names))) else: await ctx.send("No one is playing") else: await ctx.send(f"The server is not running")
def query_server(game): """Requests advanced server status data for minecraft servers(must be enabled in server.properties)""" names = '' query_server = MinecraftServer(game.ip, game.port) query = query_server.query() if query.players.online == 0: output = f'There are no players on the currently running {game.title} server' elif query.players.online == 1: output = f'{query.players.names[0]} is on the currently running {game.title} server' else: for name in query.players.names: names = names + name + ', ' output = f'{query.players.online} players are on the {game.title} server: {names}' return output
async def online(ctx): # declaring the objects for the minecraft server server = MinecraftServer(IP, PORT) status = server.status() serverquery = MinecraftServer(IP, QPORT) query = serverquery.query() Embed = discord.Embed( colour=discord.Colour.light_gray(), description="The server has the following players online: {0}".format( ", ".join(query.players.names))) Embed.set_author( name="The server has {0} players online".format(status.players.online)) await ctx.send(embed=Embed)
def status(): server = MinecraftServer("localhost", 25565) try: query = server.query() qtup = { "players": { "online": query.players.online, "max": query.players.max, "names": query.players.names }, "serverUp": True } except socket.error: qtup = {"serverUp": False} return jsonify(qtup)
def server_status(port, variant): if variant is None: variant = 'status' try: if variant == 'ping' or variant == 'status' or variant == 'query' or variant == 'test': server = MinecraftServer('127.0.0.1', port) if variant == 'ping': pyprint("Ping: %sms" % server.ping()) elif variant == 'status': s = server.status() f = 'x' if s.favicon is None else '^_^' description = format_strip(s.description) if isinstance( s.description, str) else format_strip( s.description['text']) sample = s.players.sample if sample is None: if s.players.online > 0: sample = "<Hidden>" else: sample = "<None>" pyprint("Status returned:\n" " - ping: %s ms [%s]\n" " - version: %s (protocol %s)\n" " - description: %s\n" " - players (%s/%s): %s" % (s.latency, f, s.version.name, s.version.protocol, description, s.players.online, s.players.max, sample)) elif variant == 'query': s = server.query() pyprint( "Query returned:\n" " - game: %s (%s)\n" " - ip: %s:%s\n" " - version: %s (%s)\n" " - description: %s\n" " - map: %s\n" " - plugins: %s\n" " - players (%s/%s): %s" % (s.raw['game_id'], s.raw['gametype'], s.raw['hostip'], s.raw['hostport'], s.software.version, s.software.brand, format_strip(s.motd), s.map, s.software.plugins, s.players.online, s.players.max, s.players.names)) except ConnectionRefusedError: pyprint("Could not connect to the server!", 3) except ConnectionResetError: pyprint("Query is not enabled on the server!", 3) except IOError: pyprint("Server is not ready yet!", 3)
def sync_mcserver(self, serverip): server = MinecraftServer(serverip) try: query = server.query(retries=1) except Exception: # Either query is disabled or failed to connect try: status = server.status(retries=1) except Exception: return False else: return (status.players.online, list(map(lambda x: x.name, status.players.sample)), status.players.max, status.version.name) else: return (query.players.online, query.players.names, query.players.max, query.software.version)
def v1_minecraft_serverinfo(): try: server = MinecraftServer( config.get_setting('minecraft-server-host', '127.0.0.1'), config.get_setting('minecraft-server-port', 25565)) q = server.query() response = requests.get( f"https://api.mcsrvstat.us/2/{config.get_setting('minecraft-server-host', '127.0.0.1')}" ) obj = response.json() obj["players"]["online"] = q.players.online obj["players"]["list"] = q.players.names return make_response(obj, 200) except: return make_response( jsonify(["ERROR: The specified server is not online."]), 500)
def mcServerQuery(update): global mcPort global mcQueryResult global mcServerSelected global mcServer print(mcServer) try: # just gotta find the port number to the server provided with open('/home/minecraft/' + mcServer + '/server.properties') as conf: for line in conf.readlines(): if 'server-port' in line: mcPort = int(line.split('=')[1]) except: update.message.reply_text( 'Something went wrong. Did you give me a valid name (case-sensitive)?' ) return False server = MinecraftServer("127.0.0.1", mcPort) mcQueryResult = server.query() return True
async def printStatus(): """Print the updating status to the console.""" await client.wait_until_ready() while not client.is_closed(): mcServer = MinecraftServer(cIP, cPort) serverStatus = mcServer.status() if cEnableNames is True and '{1}' in cMessageSend and serverStatus.players.online != 0: mcQuery = mcServer.query() if serverStatus.players.online == 1: print('{0} Player :: {2} :: {1}'.format(serverStatus.players.online, ", ".join(mcQuery.players.names), getTime())) else: print('{0} Players :: {2} :: {1}'.format(serverStatus.players.online, ", ".join(mcQuery.players.names), getTime())) else: if serverStatus.players.online == 1: print('{0} Player :: {1}'.format(serverStatus.players.online, getTime())) else: print('{0} Players :: {1}'.format(serverStatus.players.online, getTime())) await asyncio.sleep(int(cRefresh))
def check_upstate(): data = {} # If the app has been started in debug mode, return dummy data. if app.debug: data["online"] = True data["players_online"] = ["testname1", "testname2"] data["players_max"] = 20 data["version"] = "CraftBukkit 1.8.8" data["plugins"] = ["WorldEdit", "WorldGuard"] return json.dumps(data) # Otherwise, an actual server query should be made. server = MinecraftServer("localhost", 25565) try: query = server.query() data["online"] = True data["players_online"] = query.players.names data["players_max"] = query.players.max data["version"] = query.software.brand data["plugins"] = query.software.plugins except: data["online"] = False return json.dumps(data)
def getMCStats(): global server_status global server_status_time server = MinecraftServer("localhost", 25565) try: javaProcess = getJavaProcess() query = server.query() status = server.status() except (subprocess.CalledProcessError, socket.gaierror, ConnectionRefusedError, BrokenPipeError, socket.timeout): if server_status is not None: return {"online": server_status} else: return {"online": "offline"} javaMemory = javaProcess.memory_info().rss javaMemory = toSi(javaMemory, 1024) javaCPU = javaProcess.cpu_percent() size = subprocess.check_output("du -sh {}".format(PATH), shell=True) size_rx = re.search("^(.*?)(.)\t", size.decode("UTF-8", errors="replace")) size = size_rx.group(1) + " " + size_rx.group(2) resp = query.raw resp["online"] = "online" resp["players"] = query.players.names resp["latency"] = status.latency resp["minecraft_RAM"] = javaMemory resp["minecraft_CPU"] = javaCPU resp["minecraft_HDD"] = size if server_status == "stopping": resp["online"] = server_status return resp
def get_player_list(address, port): server = MinecraftServer(address, port=25565) players = server.query() return players.players.names
async def on_message(message): """On message portion, most of the actual programming is in this function.""" if message.author == client.user: return msgSplit = message.content.split() #If the message content is **only** an image, this #prevents an error message from clogging the console. try: msgSplit[0] except IndexError: return #Makes cBasePrompt = 0 usable if cBasePrompt == "0": cPrompt = '<@' + str(client.user.id) + '>' else: cPrompt = cBasePrompt #Detects if the bot was called if msgSplit[0] == cPrompt: #<prompt> help - Lists commands if msgSplit[1].lower() == 'help': await message.channel.send('''The commands available are: {0} Help - Displays this message {0} List - List the players online at {1} {0} Ping - Ping the bot {0} Source - Github Source Code'''.format(cPrompt, cIP)) #<prompt> ping - Pings the bot if msgSplit[1].lower() == 'ping': await message.channel.send('Pong!') print('Pong\'ed user ' + str(message.author) + ' :: ' + str(getTime())) #<prompt> list - Lists players online. Only the amount is #listed if cEnableNames is False if msgSplit[1].lower() == 'list': mcServer = MinecraftServer(cIP, cPort) serverStatus = mcServer.status() if serverStatus.players.online == 0: if cSkipNoPlayers is False: await message.channel.send(cNoPlayers.format(cIP)) elif cEnableNames is True and '{1}' in cMessageSend: if serverStatus.players.online != 0: onPlayers = serverStatus.players.online mcQuery = mcServer.query() await messagge.channel.send(cMessageSend.format(onPlayers, ", ".join(mcQuery.players.names), cIP)) else: await message.channel.send(cMessageSend.format(serverStatus.players.online)) #<prompt> source - Github link if msgSplit[1].lower() == 'source': await message.channel.send('''MCPD v2.0, licensed under the MIT license. Full source code at: https://github.com/SuperShadowPlay/MCPD''') print(str(message.author) + ' Requested Source :: ' + getTime())
# This file is © TheBloodyscreen # It was created as part of the Minecraft Controller project in May of 2019 # If you want to use all or part of the code in this file, # please contact [email protected] from mcrcon import MCRcon from config import config from bloodyterminal import btext from mcstatus import MinecraftServer from rcon import Rcon # inits and stuffs colorCodes = [ "§1", "§4", "§c", "§6", "§e", "§2", "§a", "§b", "§3", "§9", "§d", "§5", "§f", "§7", "§8", "§0", "§r", "§l", "§o", "§n", "§m", "§k" ] # list of every available stylization for removal later server = MinecraftServer(config["serverIP"], config["serverPORT"]) status = server.status() description = status.description["text"] for color in colorCodes: # removing stylization from minecraft motd for better readability description = description.replace(color, "") ping = server.ping() image = status.favicon version = status.version.name worldName = server.query().map playersMax = server.query().players.max playersOnline = server.query().players.names playersOnlineAmount = server.query().players.online if __name__ == '__main__': pass
class MServer: def __init__(self, address_in, port_in, yag_in): logging.debug('Initializing server') self.bad_internet = None if cfg.test_connection: self.test_internet() self.yag = yag_in self.int_server = MinecraftServer(address_in, port_in) self.server_info = {} self.server_stats = {} self.timers = { 'update timer': None, 'message timer': None, 'ping timer': PTimer(15 * 60, None) } self.uptime = [] self.downtime = [] self.last_status = None self.reason_offline = None # send a first message (will run first update and populate info) self.send_message() # this uses the initial info and starts the loop self.previous_update = self.online() self.loop() def test_internet(self): if self.bad_internet is not None and (time.time() - self.bad_internet) / 60 < 15: logging.debug( 'Internet already tested bad less than 15 minutes ago') return None logging.info('Testing internet connection...') test = speedtest.Speedtest() test.download() if test.results.ping > 100 or test.results.download < 1.0e6: logging.warning( f'Slow internet connection detected: {test.results.ping:.0f} ping {test.results.download / 1.0e6:.2f} Mbps download' ) logging.warning( 'Server results could be affected by poor internet connection') self.bad_internet = time.time() else: logging.info( f'Good internet connection: {test.results.ping:.0f} ping {test.results.download / 1.0e6:.2f} Mbps download' ) self.bad_internet = None def loop(self): # checks if the status of the server has changed while triggering an update if not (self.update() == self.previous_update): self.timers['message timer'].cancel() # does not update before message sent because there was just an update self.send_message(update_before=False) # set update timer and previous status self.timers['update timer'] = PTimer(cfg.check_interval, self.loop) self.previous_update = self.online() def update(self, log=True, retries=0): logging.debug(f'Contacting Server {cfg.server_address}') try: self.last_status = self.int_server.status(cfg.fails_required) except socket.timeout: # this is usually what happens when the server is offline self.uptime = [] self.downtime.append(time.time()) logging.info('Attempt to contact server timed out') self.last_status = None self.reason_offline = 'Attempt to contact server timed out' return False except socket.gaierror: # this is usually what happens when the address is incorrect so the program exits logging.critical('Unable to resolve server address from config') input('Press enter to exit...') sys.exit(0) except OSError: # this usualyl happens when the server is still loading or overloaded self.uptime = [] self.downtime.append(time.time()) logging.warning('The server responded but not with info') time.sleep(2) self.last_status = None self.reason_offline = 'The server responded but not with info' # this retries the check a few times if retries < 3: return self.update(retries=retries + 1) else: return None self.uptime.append(time.time()) self.downtime = [] logging.debug('Contact with server successful') if cfg.high_ping is not 0 and self.last_status.latency > cfg.high_ping: logging.warning( f'High latency detected! ({self.last_status.latency:.1f} ms)') if cfg.test_on_high_ping: self.test_internet() if cfg.text_on_high_ping and self.bad_internet is None and not self.timers[ 'ping timer'].is_alive(): subject = f'{cfg.server_address} High Ping!' message = [] if cfg.include_timestamp: message.append( f'[{datetime.now().strftime("%I:%M:%S %p")}]') message.append( f'High ping of {self.last_status.latency:.0f} ms detected') self.yag.send(cfg.sms_gateway, subject, '\r'.join(message)) logging.info(f'Sent text to {cfg.phone_str}') self.timers['ping timer'] = PTimer(15 * 60, None) # tests if this is the first successful contact with the server if not self.server_info: self.set_server_info() # after the server info is initially populated it is printed self.print_server_info() # if this update is supposed to be logged info is recorded if log: self.log_stats() return True def set_server_info(self): self.server_info['address'] = f'{cfg.server_address}:{cfg.server_port}' if type(self.last_status.description) is str: self.server_info['description'] = self.last_status.description else: self.server_info['description'] = self.last_status.description[ 'text'] self.server_info['max players'] = self.last_status.players.max self.server_info['version'] = self.last_status.version.name if len(self.last_status.raw['modinfo']['modList']) > 0: self.server_info[ 'version'] += f" - {len(self.last_status.raw['modinfo']['modList'])} mods" else: self.server_info['version'] += ' - Vanilla' # this tests to see if query is enabled and disables player logging if needed try: query = self.int_server.query() self.server_info['query allowed'] = True self.server_info['gametype'] = query.raw['gametype'] except socket.timeout: self.server_info['query allowed'] = False if cfg.include_player_log: logging.error( 'Query is not allowed on this server so individual players will not be logged!' ) cfg.try_player_log = False # TODO should do a thing here where I record the sample players if query is disabled # TODO maybe there should be an option to print the sample players along with the status # TODO need to figure out if sample players go in server info or stats # TODO probably just make it a regular stats thing def log_stats(self): if 'pings' not in self.server_stats.keys(): self.server_stats['pings'] = [{ 'ping': self.last_status.latency, 'time': time.time() }] else: self.server_stats['pings'].append({ 'ping': self.last_status.latency, 'time': time.time() }) if 'max online' not in self.server_stats.keys(): self.server_stats['max online'] = self.last_status.players.online else: self.server_stats['max online'] = max( self.server_stats['max online'], self.last_status.players.online) if cfg.include_player_log: query = self.int_server.query() if len(query.players.names) > 0: current_players = [] for player_ob in query.players.names: current_players.append(player_ob.name) if 'player summary' not in self.server_stats.keys(): self.server_stats['player summary'] = {} for player in self.server_stats['player summary'].keys(): self.server_stats['player summary'][player].append({ 'online': player in current_players, 'time': time.time() }) for player in current_players: if player not in self.server_stats['player summary'].keys( ): self.server_stats['player summary'][player] = [{ 'online': True, 'time': time.time() }] def print_server_info(self): if not self.server_info: logging.warning('No server info has been gathered yet') else: for data in self.server_info.keys(): logging.info( f'[SERVER INFO] {data.capitalize()}: {self.server_info[data]}' ) def send_message(self, console=True, text=True, update_before=True): if update_before: self.update() # creates message and subject using config message = [] if self.online(): log_title = '[SERVER ONLINE]' subject = f'Status {cfg.server_address}: Online' if cfg.include_uptime: uptime_msg = f'Uptime: {int((self.get_uptime() - (self.get_uptime() % 86400)) / 86400)} days ' uptime_msg += f'{(self.get_uptime() % 86400) / 3600:.1f} hrs' message.append(uptime_msg) if cfg.include_avg_ping: message.append(f'Avg ping: {self.get_avg_ping():.0f} ms') if cfg.include_max_ping: message.append(f'Max ping: {self.get_max_ping():.0f} ms') if cfg.include_last_ping: message.append( f'Last ping: {self.server_stats["pings"][-1]["ping"]}') if cfg.include_max_players: message.append( f'Max online: {self.server_stats["max online"]}/{self.server_info["max players"]}' ) if cfg.include_player_log: message.append('Players online:') if not self.server_stats['player summary']: message.append('None') else: for player in self.server_stats['player summary'].keys(): message.append( f'\r{player}: {self.get_player_time(player) / 3600:.1f} hrs' ) else: log_title = '[SERVER OFFLINE]' subject = f'{cfg.server_address} Status: Offline!' if cfg.include_downtime: downtime_msg = f'Downtime: {(self.get_downtime() - self.get_downtime() % 86400) / 3600:.1f} days ' downtime_msg += f'{self.get_downtime() / 3600:.1f} hrs' message.append(downtime_msg) if cfg.include_fail_reason: message.append(self.reason_offline) # sends message to log if console: for line in message: logging.info(f'{log_title} {line}') # sends message through sms gateway if text: if cfg.include_timestamp: message.insert(0, datetime.now().strftime('%I:%M:%S %p')) self.yag.send(cfg.sms_gateway, subject, '\r'.join(message)) logging.info(f'Sent text to {cfg.phone_str}') # clears out temporary data once message is sent self.server_stats = {} # sets next timer if self.timers['message timer'] is not None and self.timers[ 'message timer'].is_alive(): self.timers['message timer'].cancel() if self.online() and cfg.up_text_interval > 0: self.timers['message timer'] = PTimer(cfg.up_text_interval, self.send_message) if not self.online() and cfg.down_text_interval > 0: self.timers['message timer'] = PTimer(cfg.down_text_interval, self.send_message) def online(self): return self.last_status is not None def get_avg_ping(self): if len(self.server_stats['pings']) == 1: return self.server_stats['pings'][0]['ping'] total = 0 for i in range(len(self.server_stats['pings']) - 1): total += self.server_stats['pings'][i]['ping'] * ( self.server_stats['pings'][i + 1]['time'] - self.server_stats['pings'][i]['time']) return total / (self.server_stats['pings'][-1]['time'] - self.server_stats['pings'][0]['time']) def get_player_time(self, player): if len(self.server_stats['player summary'][player]) == 1: return 0 total = 0 for i in range(len(self.server_stats['player summary'][player]) - 1): if self.server_stats['player summary'][player][i]['online']: total += self.server_stats['player summary'][player][i + 1]['time'] - \ self.server_stats['player summary'][player][i]['time'] return total / ( self.server_stats['player summary'][player][-1]['time'] - self.server_stats['player summary'][player][0]['time']) def get_max_ping(self): ping_vals = [] for point in self.server_stats['pings']: ping_vals.append(point['ping']) return max(ping_vals) def get_uptime(self): return self.uptime[-1] - self.uptime[0] def get_downtime(self): return self.downtime[-1] - self.downtime[0] def stop(self): for timer in self.timers.keys(): self.timers[timer].cancel()
def getMCServerData(): cfg.debug(f"getMCServerData", DEBUG) # get mc server info mcServer = "minecraft.tas.qld.edu.au" conn = create_connection(cfg.DB) sql = "SELECT MAX(maxPing), date from ping" cfg.debug(sql, DEBUG) cur = conn.cursor() cur.execute(sql) maxPing = cur.fetchone()[0] sql = "SELECT COUNT(name) FROM members" cur.execute(sql) count = cur.fetchone()[0] try: server = MinecraftServer(mcServer) status = server.status() latency = status.latency playersOnLine = status.players.online playersMax = status.players.max query = server.query() playersList = query.players.names cfg.debug(f"Playerlist: {playersList}", DEBUG) now = datetime.datetime.now() # get max ping from db. if latency > maxPing: sql = f"INSERT INTO ping (maxPing, date) VALUES ({status.latency}, '{now}')" cfg.debug(sql , DEBUG) cur.execute(sql ) conn.commit() maxPing = f"{latency} ms" percent = math.floor(playersOnLine / playersMax * 100) except Exception as e: cfg.debug(f"MC error {e}", True) playersList = [] playersOnLine = 0 playersMax = 20 percent = 0 latency = "OFFLINE" count = 0 # listOfPlayers = "THIS WILL BE A LIST OF ALL PLAYERS" serverData = { "ip": mcServer, "latency": f"{latency} ms", "playersList": playersList, "playerCount": playersOnLine, "playersMax": playersMax, "percent": percent, "maxPing": f"{maxPing} ms", "docLink": latestDoc, "discord": discordInvite, "members": count } cfg.debug(f"mc server data: {serverData} ", True) return serverData
from mcstatus import MinecraftServer # If you know the host and port, you may skip this and use MinecraftServer("example.org", 1234) server = MinecraftServer("localhost", 25565) # '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. # 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. qserver = MinecraftServer("127.0.0.1", 25566) query = qserver.query() print("The server has the following players online: {0}".format(", ".join(query.players.names)))
def get_query(mc_server, port=25565): mc = MinecraftServer(mc_server, port) query = mc.query() return query.players.names
async def on_message(message): #Variable set up global storedStats, storedEmojiUnique, storedEmojiUniversal #Used for user identification isVerified = "false" isAdmin = "false" #Address to server mcServer = MinecraftServer(IP, PORT) #If the bot sent the message, ignore if message.author == client.user: return #Determines user permissions(will later check agaisnt role name) for item in message.author.roles: if (str(item) == "Minecraft"): isVerified = "true" if (str(item) == "ADMIN"): isAdmin = "true" #Depending on which server the message was in: what emoji set should be used if str(message.guild.id) == str(UNIQUE_SERVER): animatedEmoji = storedEmojiUnique else: #All other servers use the generic set animatedEmoji = storedEmojiUniversal #Show info about the minecraft server if message.content.lower() == "!mc": if (isVerified == "true"): try: status = mcServer.status() query = mcServer.query() players = query.players.online if players == 0: await message.channel.send( "The server is Online with no active players") elif players == 1: await message.channel.send( "The server is Online with 1 active player: {}".format( ", ".join(query.players.names))) elif players > 1: await message.channel.send( "The server is Online with {} active players: {}". format(players, ", ".join(query.players.names))) except ConnectionError: await message.channel.send( "Server is Offline (Unless it has just been booted up)") else: await message.channel.send("You do not have permission to do that") #Run the mc server, if it is not running if message.content.lower() == "!mcstart": if (isVerified == "true"): try: status = mcServer.status() await message.channel.send("The server is already Online!") except ConnectionError: os.system( '(cd {}; ./{})'.format(MC_FOLDER, MC_RUNNABLE_SCRIPT) ) #Run a script that will correctly start your server await message.channel.send( "Server is Offline. Bootup has started, it usually takes up to about 2 minutes to finish booting and become visible online so please be patient" ) return return else: await message.channel.send("You do not have permission to do that") #Stop the mc server, if it is empty if message.content.lower() == "!mcstop": if (isVerified == "true"): try: status = mcServer.status() players = status.players.online if players > 0: await message.channel.send( "The server still has players on it! The server must be empty before shutdown can happen" ) else: with open( "{}".format(PID_TXT), "r" ) as myfile: #path to text file that stores the PID of the minecraft server, so that the server can be told to shut down pid = myfile.read() os.system("kill -15 {}".format(pid)) await message.channel.send("Server has shut down") except ConnectionError: await message.channel.send( "The server is already Offline (Or if you just booted it up, hasn't come Online yet)" ) else: await message.channel.send("You do not have permission to do that") #Splits the message, so the first word can be matched to a command, and use the rest of the words as parameters splitMessage = message.content.lower().split() if (len(splitMessage) == 2): #If the command has a parameter if (splitMessage[0] == "!react"): for emoji in animatedEmoji: if splitMessage[1] == emoji: await message.delete() async for react in message.channel.history(limit=1): await react.add_reaction(animatedEmoji[emoji]) return return if (splitMessage[0] == "!delete"): if (isAdmin == "true"): #This can be optimized by sending a batch delete rather then increment once #It's somehwere in the discord.py api async for delete in message.channel.history( limit=(int(splitMessage[1]) + 1)): await delete.delete() return else: message.channel.send('You do not have permission to do that') return if (splitMessage[0] == '!attack'): #A little game where users can attack eachother #These variable names NEED to be cleaned up messageParameter = splitMessage[1] targetUserID = [ messageParameter[:2], messageParameter[2:-1], messageParameter[-1:] ] #This isolates just the ID number of the targeted user if targetUserID[ 1][: 1] == '!': #Sometimes discord leaves an ! in the id, but sometimes not. Not sure why but this purges it as it causes bugs with storing data(duplicated users) targetUserID[1] = targetUserID[1][1:] if targetUserID[0] == '<@' and targetUserID[ 2] == '>': #After formatting the code, if it is correctly formatted if int(targetUserID[1]) == int( client.user.id ): #Checks if it was the bot that was targeted in the attack await message.channel.send( '<a:angryAwooGlitch:691087516819914772>') return damage = random.randint(1, 29) if str(message.author.id) not in storedStats: storedStats[str(message.author.id)] = { 'hp': 50, 'damage': 0, 'deaths': 0 } elif str(targetUserID[1]) not in storedStats: storedStats[str(targetUserID[1])] = { 'hp': 50, 'damage': 0, 'deaths': 0 } storedStats[str(targetUserID[1])]['hp'] -= damage if storedStats[str(targetUserID[1])]['hp'] <= 0: storedStats[str(targetUserID[1])]['deaths'] += 1 storedStats[str(targetUserID[1])]['hp'] = 50 if str(message.author.id) == str(targetUserID[1]): await message.channel.send( '<a:blobhang:691023822576549930>') await message.channel.send( '<@{}> killed themselves'.format(message.author.id) ) return await message.channel.send('<:killed:690998665686548483>') await message.channel.send( '<@{}> dealt {} damage, killing {}!'.format( message.author.id, '{:,}'.format(damage), messageParameter)) storedStats[str(message.author.id)]['damage'] += damage else: await message.channel.send( 'You dealt {0} damage to {1}\n{1} has {2} HP remaining' .format( '{:,}'.format(damage), messageParameter, '{:,}'.format( (storedStats[str(targetUserID[1])]['hp'])))) storedStats[str(message.author.id)]['damage'] += damage return if splitMessage[0] == '!roll': if len(splitMessage) == 2: await message.channel.send("<@{}> rolled a {}".format( message.author.id, random.randint(1, int(splitMessage[1])))) else: await message.channel.send( "Type a space and a number after !roll to roll a dice that size" ) return if message.content.lower() == '!stats': if str(message.author.id) not in storedStats: storedStats[str(message.author.id)] = { 'hp': 50, 'damage': 0, 'deaths': 0 } await message.channel.send( '<@{}>\nHP: {}\nDamage Dealt: {}\nDeaths: {}'.format( str(message.author.id), '{:,}'.format(storedStats[str(message.author.id)]['hp']), '{:,}'.format(storedStats[str(message.author.id)]['damage']), '{:,}'.format(storedStats[str(message.author.id)]['deaths']))) if message.content.lower() == '!save' and (isAdmin == "true"): with open('attacks.json', 'w') as fp: json.dump(storedStats, fp) print("data saved to server") await message.channel.send("data saved to server") if message.content.lower() == '!load' and (isAdmin == "true"): jsonFile = open('attacks.json') jsonStr = jsonFile.read() storedStats = json.loads(jsonStr) print("save data loaded") await message.channel.send("save data loaded") if message.content.lower() == '!flip': if random.randint(1, 2) == 1: #heads await message.add_reaction('👧') #react heads else: await message.add_reaction('🐀') #react tails return if message.content.lower() == '!list': listedEmoji = '' #initializes the variable so that values can be 'added' into it for key in animatedEmoji: listedEmoji += '{} --> {}\n'.format(key, animatedEmoji[key]) await message.channel.send(listedEmoji) return #The following searches the user's message to see if any of the custom emoji set matches #If it does then it will replace it, and resend the message on behalf of the user # while also deleting the original users message #To identify the original user who sent the message, it also @'s them modifiedMessage = message.content switchFlag = 0 #A flag that determines of a match was made, and if the users message should be replaced for key in animatedEmoji: matchCheck = re.search( re.escape(key), message.content, flags=re.I) #Check if the message has a replacable emoji if (str(matchCheck) != "None"): modifiedMessage = re.sub(re.escape(key), animatedEmoji[key], modifiedMessage, flags=re.I) switchFlag = 1 #sets a flag that a match was made, and should replace the message if switchFlag == 1: #ONLY replace if a match was found await message.channel.send('<@{}>:'.format(message.author.id)) await message.delete() await message.channel.send(modifiedMessage)
async def on_message(message): #!!reload if message.content.startswith('!!reload'): await client.send_message( message.channel, '**Warning:** all files reloading, this might take a moment') starttime = time.time() load_files() em = discord.Embed(description='Reloaded: **' + str(len(uuids)) + '** files', colour=0x003763) em.set_author( name='File Reload', icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer(text='Time: ' + str(round(time.time() - starttime, 2)) + 's') await client.send_message(message.channel, embed=em) #!!stat player NAME STAT | stats list STAT elif message.content.startswith('!!stat'): args = message.content.split(" ") #stat player if len(args) == 4 and args[1] == 'player': try: name = ''.join(get_close_matches(args[2], names, 1)) uuid = convert_uuid(uuids[names.index(name)]) try: with open(os.path.join(STAT_FOLDER, uuid + '.json')) as json_data: stats = json.load(json_data) stat = ''.join( get_close_matches('stat.' + args[3], stat_list, 1)) try: stat_result = str(stats[stat]) except: stat_result = str(0) em = discord.Embed(description='', colour=0x003763) em.add_field(name='Stat', inline=True, value=stat) em.add_field(name='Result', inline=True, value=stat_result) em.set_author(name=name + ' - Statistics', icon_url='https://crafatar.com/avatars/' + uuid) await client.send_message(message.channel, embed=em) except: await client.send_message(message.channel, 'No playerfile or stat found') except: await client.send_message(message.channel, 'Invalid username') #stat list elif len(args) == 3 and args[1] == 'list': try: stat = ''.join( get_close_matches('stat.' + args[2], stat_list, 1)) text1 = [] text2 = [] total = 0 for item in uuids: with open( os.path.join(STAT_FOLDER, convert_uuid(item) + '.json')) as json_data: stats = json.load(json_data) try: text1.append(stats[stat]) text2.append(names[uuids.index(item)]) total += stats[stat] except: pass text1, text2 = zip(*sorted(zip(text1, text2))) if not text1 == []: em = discord.Embed(description='', colour=0x003763) em.add_field(name='Players', inline=True, value='\n'.join(text2[::-1])) em.add_field(name='Result', inline=True, value='\n'.join(str(x) for x in text1[::-1])) em.set_author( name=stat + ' - Ranking', icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer(text='Total: ' + str(total) + ' | ' + str(round((total / 1000000), 2)) + ' M') await client.send_message(message.channel, embed=em) except: await client.send_message(message.channel, 'No playerfile or stat found') else: await client.send_message(message.channel, 'Invalid syntax') #!!scoreboard NAME elif message.content.startswith('!!scoreboard'): nbtfile = nbt.NBTFile(os.path.join(DATA_FOLDER, 'scoreboard.dat')) args = message.content.split(" ") scoreboard_objectives = [] for tag in nbtfile['data']['Objectives']: scoreboard_objectives.append(str(tag["Name"])) if len(args) == 2: objective_name = get_close_matches(args[1], scoreboard_objectives, 1) text1 = [] text2 = [] total = 0 if not objective_name == []: scoreboard = dict() for tag in nbtfile["data"]["PlayerScores"]: if str(tag["Objective"]) == ''.join(objective_name): scoreboard[str(tag["Name"])] = int(str(tag["Score"])) scoreboard = sorted(scoreboard.items(), key=lambda x: x[1]) scoreboard.reverse() for item in scoreboard: name, amount = item if not name == 'Total': text1.append(name) text2.append(str(amount)) total += amount em = discord.Embed(description='', colour=0x003763) em.add_field(name='Players', inline=True, value='\n'.join(text1)) em.add_field(name='Amount', inline=True, value='\n'.join(text2)) em.set_author( name='Scoreboard: ' + ''.join(objective_name), icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer(text='Total: ' + str(total) + ' | ' + str(round((total / 1000000), 2)) + ' M') await client.send_message(message.channel, embed=em) else: await client.send_message(message.channel, 'Scoreboard not found') else: await client.send_message(message.channel, 'Invalid syntax') #!!help elif message.content.startswith('!!help'): em = discord.Embed( description= 'This bot provides general information about the Dugged server. \nThe command prefix is **!!**.\n ', colour=0x003763) em.add_field( name='Commands', inline=False, value= ('`!!reload` **-** Reloads all files\n' '`!!help` **-** Shows this page\n' '`!!worldsize` **-** Shows current worldsize\n' '`!!tps` **-** Shows average TPS from the last 45 seconds\n' '`!!list` **-** Displays currently online players and their dimension\n' '`!!stat player <user_name> <stat_name>` **-** Shows statistics value\n' '`!!stat list <stat_name>` **-** Shows statistics ranking\n' '`!!structure <file[ATTACHED]>` **-** Uploads structure file to creative\n' '`!!scoreboard <scoreboard_name>` **-** Displays scoreboard\n' '`!!benchmark <start> <stat_name>` **-** Starts a benchmark for given stat\n' '`!!benchmark <stop>` **-** Displays benchmark results\n')) em.set_author( name='Help', url='https://twitter.com/Robitobi01', icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer( text='Made by Robitobi01', icon_url= 'https://pbs.twimg.com/profile_images/924434100441755649/MZOP8WK7.jpg' ) await client.send_message(message.channel, embed=em) #!!structure FILE[attached] elif message.content.startswith('!!structure'): data = message.attachments url = data[0]['url'] filename = data[0]['filename'] filesize = str(data[0]['size']) if filename.rsplit('.', 1)[1] == 'nbt': req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) response = urllib.request.urlopen(req) response = response.read() f = open(os.path.join(STRUCTURE_FOLDER, filename), 'wb') f.write(response) f.close em = discord.Embed(description='Filename: ' + filename, colour=0x003763) em.set_author( name='Structure file uploaded', icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer(text='Filesize: ' + str(round(int(filesize) / 1000, 2)) + 'KB') await client.send_message(message.channel, embed=em) else: await client.send_message(message.channel, 'No nbt file detected') #!!tps elif message.content.startswith('!!tps'): level_file = nbt.NBTFile(os.path.join(SURVIVAL_FOLDER, 'level.dat')) time_start = int(level_file['Data']['LastPlayed'].value) level_file = nbt.NBTFile(os.path.join(SURVIVAL_FOLDER, 'level.dat')) time_current = int(level_file['Data']['LastPlayed'].value) level_file = nbt.NBTFile(os.path.join(SURVIVAL_FOLDER, 'level.dat_old')) time_old = int(level_file['Data']['LastPlayed'].value) tps = time_current - time_old tps = 45 / (tps / 1000) * 20 if tps > 20: tps = float(20) if tps < 0: tps = float(0) await client.send_message( message.channel, 'The Current TPS is: **' + str(round(tps, 2)) + '** | TPS only updates roughly every 45 seconds') #!!benchmark start STAT elif message.content.startswith('!!benchmark'): args = message.content.split(" ") global benchmark_started, benchmark_results, benchmark_start_time, benchmark_stat if len(args) == 3 and args[1] == 'start' and benchmark_stat == '': benchmark_results = [] benchmark_stat = ''.join( get_close_matches('stat.' + args[2], stat_list, 1)) for item in uuids: with open( os.path.join(STAT_FOLDER, convert_uuid(item) + '.json')) as json_data: stats = json.load(json_data) try: benchmark_results.append(stats[benchmark_stat]) except: benchmark_results.append(str(0)) benchmark_start_time = time.time() await client.send_message( message.channel, 'Benchmark started for: ' + benchmark_stat) await client.send_message( message.channel, '**Warning:** Benchmarks need to run atleast 1 minute to detect any changes' ) #!!benchmark stop elif len(args) == 2 and args[1] == 'stop' and benchmark_stat != '': benchmark_results_final = [] for item in uuids: with open( os.path.join(STAT_FOLDER, convert_uuid(item) + '.json')) as json_data: stats = json.load(json_data) try: benchmark_results_final.append(stats[benchmark_stat]) except: benchmark_results_final.append(str(0)) benchmark_time = int(time.time() - benchmark_start_time) benchmark_stat = '' text1 = [] text2 = [] for i in range(0, len(uuids)): benchmark_result = int(benchmark_results_final[i]) - int( benchmark_results[i]) if benchmark_result > 0: text1.append(names[i] + ': ' + str(benchmark_result)) text2.append( str(int(benchmark_result / (benchmark_time / 3600))) + ' per hour') if not text1 == []: em = discord.Embed(description='', colour=0x003763) em.add_field(name='Players', inline=True, value='\n'.join(text1)) em.add_field(name='Per Hour', inline=True, value='\n'.join(text2)) em.set_author( name='Benchmark', icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer(text='Total Time: ' + str(datetime.timedelta(seconds=benchmark_time))) await client.send_message(message.channel, embed=em) else: await client.send_message(message.channel, 'No changes detected') else: await client.send_message( message.channel, 'Invalid syntax or benchmark currently running') #!!list elif message.content.startswith('!!list'): try: server = MinecraftServer(ip, 25565) query = server.query() if query.players.online > 0: online_list = query.players.names text1 = [] dimensions = {-1: 'N', 0: 'O', 1: 'E'} for item in online_list: nbtfile = nbt.NBTFile( os.path.join( PLAYERDATA_FOLDER, convert_uuid(uuids[names.index(item)]) + '.dat')) dimension = nbtfile['Dimension'].value x, y, z = (int(i.value) for i in nbtfile['Pos']) known_location = listcmd.first( known_locations[dimension], lambda i: i.is_contained(x, z)) text1.append('**' + item + '** (' + dimensions.get(dimension, '?') + ('' if known_location == None else '@*' + known_location.location_name + '*') + ')') await client.send_message(message.channel, 'Players: ' + ", ".join(text1)) else: await client.send_message(message.channel, 'No Player is currently online') except: await client.send_message( message.channel, 'An error occurred while loading playerlist') #!!worldsize elif message.content.startswith('!!worldsize'): try: total_size = get_size(SURVIVAL_FOLDER) ow_size = get_size(OVERWORLD_FOLDER) nether_size = get_size(NETHER_FOLDER) end_size = get_size(END_FOLDER) em = discord.Embed(description='', colour=0x003763) em.add_field(name='Dimension', inline=True, value='Overworld\nNether\nEnd') em.add_field( name='Size', inline=True, value='**' + str(round(ow_size / 1000000000, 2)) + ' **GB**\n' + str(round(nether_size / 1000000000, 2)) + ' **GB**\n' + str(round(end_size / 1000000000, 2)) + ' **GB') em.set_author( name='Worldsize:', icon_url= 'https://cdn.discordapp.com/icons/336592624624336896/31615259cca237257e3204767959a967.png' ) em.set_footer(text='Total Worldsize: ' + str(round(total_size / 1000000000, 2)) + 'GB') await client.send_message(message.channel, embed=em) except: await client.send_message( message.channel, 'An error occurred while calculating worldsize') #!!synchronize elif message.content.startswith('!!synchronize'): #removes entries that store namehistory usernames nbtfile = nbt.NBTFile(os.path.join(DATA_FOLDER, 'scoreboard.dat')) for uuid in uuids: history = get_name_history(uuid) for i, tag in zip( range(len(nbtfile['data']['PlayerScores']) - 1, -1, -1), reversed(nbtfile['data']['PlayerScores'])): if any(d['name'] == str(tag['Name']) for d in history): del nbtfile['data']['PlayerScores'][i] nbtfile.write_file(os.path.join(DATA_FOLDER, 'scoreboard.dat')) #updates all playerscores to stat value if objective does not contain a number nbtfile = nbt.NBTFile(os.path.join(DATA_FOLDER, 'scoreboard.dat')) for i, tag in zip( range(len(nbtfile['data']['PlayerScores']) - 1, -1, -1), reversed(nbtfile['data']['PlayerScores'])): for objective in nbtfile['data']['Objectives']: if tag['Objective'].value == objective[ 'DisplayName'].value and not any( char.isdigit() for char in objective['DisplayName'].value): try: uuid = uuids[names.index(tag['Name'].value)] with open( os.path.join(STAT_FOLDER, convert_uuid(uuid) + '.json')) as json_data: stats = json.load(json_data) nbtfile['data']['PlayerScores'][i][ 'Score'].value = stats[ objective['CriteriaName'].value] print( str(stats[objective['CriteriaName'].value]) + " " + str(tag) + " " + str(objective)) except: pass nbtfile.write_file(os.path.join(DATA_FOLDER, 'scoreboard.dat')) await client.send_message( message.channel, 'Scoreboard and Statistics are now synchronized')
class Server: def __init__(self): self.name = '' self.GameName = '' self.nameArray = [] self.idleName = '' self.minecraftserver = None self.timer = 0 async def run(self, ctx, macadress): if self.name in minecraftNameArray: send_magic_packet(macadress) self.GameName = 'Minecraft' self.nameArray = minecraftNameArray self.idleName = 'Minecraft' embed = discord.Embed(title=f'Abriendo server de {self.GameName}', colour=discord.Color.blue(), description='Puede tardar un poco...') embed.set_image( url= 'https://i.pinimg.com/originals/02/a3/09/02a3098f242e38c1b8e76c37bbd3c5d6.gif' ) message = await ctx.send(embed=embed) await asyncio.sleep(5) p = subprocess.Popen("RunMinecraftServer.bat", stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True) err = p.communicate()[1] if err[2:35] == 'remote_abrir_mcserver.bat started': embed = discord.Embed( title=f'Servidor de Minecraft abierto :white_check_mark:', colour=discord.Color.green()) embed.set_image( url= 'https://media1.tenor.com/images/b5947d684ea4b0f0ed083c0b217fb76e/tenor.gif?itemid=15531052' ) await message.edit(embed=embed) self.minecraftserver = MinecraftServer(localServerIp) else: raise er.CantAccessRemoteServer elif self.name in conanExilesNameArray: # subprocess.Popen("RunConanExilesServer.bat") # self.GameName = 'Conan Exiles' raise er.ServerNotYetImplemented elif self.name in killingFloorNameArray: # subprocess.Popen("RunKillingFloorServer.bat") # self.GameName = 'Conan Exiles' raise er.ServerNotYetImplemented else: raise er.UnexpectedRunError async def stop(self, ctx, client): # noqa if self.GameName == 'Minecraft': if await self.isNotEmpty(): raise er.CantClosePopulatedServer with MCRcon(localServerIp, rconPass) as mcr: mcr.command("stop") embed = discord.Embed( title=f'Cerrando server de {self.GameName}...', colour=discord.Color.orange()) embed.set_image( url= 'https://media1.tenor.com/images/217c1afecaa90100c7796949ee045173/tenor.gif' ) message = await ctx.send(embed=embed) while True: await asyncio.sleep(5) try: self.minecraftserver.status() except socket.timeout: break try: await self.removeFromActiveServers() except ValueError: await ctx.send("Este servidor no está abierto.") return embed = discord.Embed(title=f'Server de {self.GameName} cerrado.', colour=discord.Color.green()) embed.set_image( url= 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/284b6a8e-dc16-4274-bab4-ce7f8d872263' '/d6byo72-78d16a50-a398-4176-ae84-72c6083b50a7.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9' '.eyJzdWIiOiJ1cm46YXBwOiIsImlzcyI6InVybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvMjg0YjZhOGUtZGMxNi' '00Mjc0LWJhYjQtY2U3ZjhkODcyMjYzXC9kNmJ5bzcyLTc4ZDE2YTUwLWEzOTgtNDE3Ni1hZTg0LTcyYzYwODNiNTBhNy5wbmc' 'ifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6ZmlsZS5kb3dubG9hZCJdfQ.qiOeCjNfyNe3RQ7FZekhvvvKTlc1K' '5BmTdDG75tQSVY') await message.edit(embed=embed) if not activeServers: current_status = 'Servers Cerrados' discord_status = discord.Status.idle await client.change_presence( status=discord_status, activity=discord.Game(name=current_status)) loop = asyncio.get_event_loop() await loop.run_in_executor(ThreadPoolExecutor(), sleepserverpc) async def playerlist(self): # noqa if self.GameName == 'Minecraft': try: query = self.minecraftserver.query() except socket.timeout: await self.removeFromActiveServers() raise er.ServerIsNotRunning playerlist = query.players.names return playerlist async def isNotEmpty(self): # noqa if self.GameName == 'Minecraft': try: status = self.minecraftserver.status() except socket.timeout: await self.removeFromActiveServers() raise er.ServerIsNotRunning if status.players.online == 0: return False else: return True async def playerCount(self): # noqa if self.GameName == 'Minecraft': try: status = self.minecraftserver.status() except socket.timeout: await self.removeFromActiveServers() return return status.players.online async def removeFromActiveServers(self): # noqa for server in activeServers: if server.GameName == self.GameName: activeServers.remove(server) async def shutdown(self): if self.GameName == 'Minecraft': if await self.isNotEmpty(): self.timer = 0 return with MCRcon(localServerIp, rconPass) as mcr: mcr.command("stop") while True: await asyncio.sleep(5) try: self.minecraftserver.status() except socket.timeout: break try: await self.removeFromActiveServers() except ValueError: return loop = asyncio.get_event_loop() await loop.run_in_executor(ThreadPoolExecutor(), sleepserverpc)
async def mcpe(self, ctx, server, port=19132): try: srv = MinecraftServer(f"{server}", int(port)) motd = srv.query() except Exception: embed_error = discord.Embed( color=self.bot.embed_color, title="→ Timeout Error:", description= "• The server is offline or you entered invalid information!") await ctx.send(embed=embed_error) else: players_string = ", ".join(str(p) for p in motd.players.names) plugins_string = ", ".join(str(l) for l in motd.software.plugins) players_string_hastebin = ", \n".join( str(p) for p in motd.players.names) plugins_string_hastebin = ", \n".join( str(l) for l in motd.software.plugins) players_post = requests.post( "https://hasteb.in/documents", data=players_string_hastebin.encode('utf-8')) hastebin_players_link = f"https://hasteb.in/{players_post.json()['key']}" plugins_post = requests.post( "https://hasteb.in/documents", data=plugins_string_hastebin.encode('utf-8')) hastebin_plugins_link = f"https://hasteb.in/{plugins_post.json()['key']}" embed = discord.Embed(color=self.bot.embed_color, title="→ Minecraft Bedrock Command") embed.add_field(name="• IP Address:", inline=True, value=f"`{server}`") embed.add_field(name="• Port:", inline=True, value=f"`{port}`") embed.add_field( name="• Players:", inline=True, value=f"`{len(motd.players.names)}/{motd.players.max}`") embed.add_field(name="• Map:", inline=True, value=f"`{motd.map}`") embed.add_field(name="• Software:", inline=True, value=f"`{motd.software.brand}`") embed.add_field(name="• MOTD:", inline=True, value=f"`{motd.motd}`") embed.add_field(name="• Version:", inline=False, value=f"`{motd.software.version}`") if not len(motd.players.names): embed.add_field( name="• Player names:", inline=False, value="`No Player Information / No Players Online!`") elif len(players_string) > 1024: players_string = players_string[:1018] players_string, _, _ = players_string.rpartition(', ') players_string = '`' + players_string + '...`' embed.add_field(name="• Player names:", inline=False, value=players_string) else: embed.add_field(name="• Player names:", inline=False, value='`' + '' + ', '.join(motd.players.names) + ', '[:-0] + '`') if not len(plugins_string): embed.add_field(name="• Plugins:", inline=False, value="`No Plugin Information / No Plugins`") elif len(plugins_string) > 1024: plugins_string = plugins_string[:1018] plugins_string, _, _ = plugins_string.rpartition(', ') plugins_string = '`' + plugins_string + '...`' embed.add_field(name="• Plugins:", inline=False, value=plugins_string) else: embed.add_field(name="• Plugins:", inline=False, value='`' + '' + ', '.join(motd.software.plugins) + ', '[:-0] + '`') embed.add_field(name="• Full plugins and players list:", value=f"[**Players**]({hastebin_players_link})" f"\n[**Plugins**]({hastebin_plugins_link})") await ctx.send(embed=embed) logger.info( f"Utility | Sent MCPE: {ctx.author} | Server: {server} | Port: {port}" )
from mcstatus import MinecraftServer import time # Server details. server_hostname = "mc.mxc42.com" # The port for the query server is running on a different port than the world server. server_port = 4243 # Make a server object with the right connection properties. server = MinecraftServer(server_hostname, server_port) query = server.query() print(query.players.names)
class MyClient(discord.Client): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) async def on_ready(self): print('Logged in as') print(self.user.name) print(self.user.id) print('------') self.channel = self.get_channel(int( os.environ['DISCORD_CHANNEL'])) # channel ID goes here self.mine_manager = os.environ["MINE_MANAGER"] self.mc_server = MinecraftServer(os.environ['MC_SERVER']) # await self.channel.send(WELCOME_MSG) activity = discord.CustomActivity("Miners: {}".format(0)) await self.change_presence(status=discord.Status.idle, activity=activity) self.mc_is_up = True self.user_count = 0 self.current_players = set() # create the background task and run it in the background self.bg_task = self.loop.create_task(self.my_background_task()) async def my_background_task(self): await self.wait_until_ready() while not self.is_closed(): await self.check_server_up() if self.is_up: await self.check_user_count() await self.check_shifts() await asyncio.sleep(15) # task runs every 15 seconds async def check_server_up(self): change = False is_up = False # for i in range(0,3): try: ping = self.mc_server.ping() is_up = True except: pass change = self.mc_is_up != is_up if change: if is_up: # server came online await self.channel.send(SERVER_UP) else: await self.channel.send(SERVER_DOWN.format(self.mine_manager)) self.is_up = is_up async def check_user_count(self): try: status = self.mc_server.status() except: return count = status.players.online change = count != self.user_count if change: status = discord.Status.online if count == 0: status = discord.Status.idle activity = discord.CustomActivity("Miners {}".format(count)) await self.change_presence(status=status, activity=activity) async def check_shifts(self): try: query = self.mc_server.query() except: return current_players = set(query.players.names) diff = current_players - self.current_players self.current_players = current_players if len(diff) > 0: for p in diff: await self.channel.send(random.choice(LOGIN_MSG).format(p))
from mcstatus import MinecraftServer # If you know the host and port, you may skip this and use MinecraftServer("example.org", 1234) # server = MinecraftServer.lookup("bcsn.us:25565") server = MinecraftServer("184.18.202.133:25565") # '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. # 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() print("The server has the following players online: {0}".format(", ".join(query.players.names)))
class MinecraftCommandModule(BaseCommandModule): def __init__(self, *, minecraft_host: str, minecraft_port: int): super().__init__() self.name = "MinecraftCommandModule" self.keywords = ["minecraft", "mc"] self.description = "Minecraft related commands for Gothbot" self.help_embed = self.generate_help_embed( title="Gothbot Minecraft Module", description=self.description, aliases=self.keywords, commands=[ ("help", "Prints this help box"), ("ping", "Checks if minecraft server is up"), ("players", "Checks who is online"), ("ip", "Prints the current IP for the server"), ], ) self.command_prefix = os.environ["COMMAND_PREFIX"] self.host = minecraft_host self.port = minecraft_port self.ip_string = self.host if self.port == 25565 else f"{self.host}:{self.port}" self.server = MinecraftServer(self.host, self.port) async def handle(self, message: discord.Message): segments = message.content.split(" ", 3) if len(segments) == 2: await self._handle_help(message.channel) return command = segments.pop() if command == "help": await self._handle_help(message.channel) elif command == "ping": await self._handle_ping(message.channel) elif command == "ip": await self._handle_ip(message.channel) elif command == "players": await self._handle_players(message.channel) else: await message.channel.send( f"Unknown command. Type `{self.command_prefix} {self.keywords[0]} help` to see available commands" ) async def _handle_help(self, channel: discord.TextChannel): logger.debug("Handling minecraft help request") await channel.send(embed=self.help_embed) async def _handle_ping(self, channel: discord.TextChannel): logger.debug("Handling minecraft ping request") message = f"`{self.ip_string}` appears to be down" try: latency = self.server.ping() message = f"`{self.ip_string}` is up and replied in {latency} ms" except Exception: pass await channel.send(message) async def _handle_ip(self, channel: discord.TextChannel): logger.debug("Handling minecraft ip request") await channel.send(f"The current minecraft ip is `{self.ip_string}`") async def _handle_players(self, channel: discord.TextChannel): logger.debug("Handling minecraft player request") message = f"Could not fetch players for `{self.ip_string}`" try: query = self.server.query() if query.players.names: message = f"`{self.ip_string}` has the following players online: {', '.join(query.players.names)}" else: message = f"`{self.ip_string}` has no players online" except Exception: pass await channel.send(message)