示例#1
2
文件: mc_site.py 项目: tlake/mc_site
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
示例#2
1
文件: mc_site.py 项目: tlake/mc_site
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,
    )
示例#3
0
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)])
示例#4
0
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
示例#5
0
    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))
示例#6
0
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))
示例#7
0
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)
示例#8
0
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
示例#10
0
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)
示例#11
0
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)
示例#12
0
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)
示例#13
0
 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)
示例#14
0
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)
示例#15
0
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
示例#16
0
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))
示例#17
0
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)
示例#18
0
文件: ammd.py 项目: zeroflow/AMMD
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
示例#20
0
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())
示例#21
0
# 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
示例#22
0
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()
示例#23
0
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
示例#24
0
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)))
示例#25
0
def get_query(mc_server, port=25565):
    mc = MinecraftServer(mc_server, port)
    query = mc.query()
    return query.players.names
示例#26
0
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)
示例#27
0
def get_query(mc_server, port=25565):
    mc = MinecraftServer(mc_server, port)
    query = mc.query()
    return query.players.names
示例#28
0
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')
示例#29
0
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)
示例#30
0
    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}"
            )
示例#31
0
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)
示例#32
0
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))
示例#33
0
文件: ping.py 项目: SimpleAOB/MCSZ
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)))
示例#34
0
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)