Пример #1
0
def main():
    options = get_options()

    auth_token = authentication.AuthenticationToken()
    try:
        auth_token.authenticate(options.username, options.password)
    except YggdrasilError as e:
        print(e)
        sys.exit()
    connection = Connection(options.address, options.port, auth_token)
    connection.connect()

    print("Logged in as " + auth_token.username)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("", 9001))
    s.listen(5)

    connection.register_packet_listener(print_chat, ChatMessageClientboundPacket)

    #send_message("GET http://www.google.com/ HTTP/1.1\r\nhost: www.google.com\r\n\r\n", "address", connection)  #GET http://www.uga.edu/ HTTP/1.1\r\nHost: www.uga.edu\r\n

    #time.sleep(100)

    #sys.exit()
    while True:
        try:
            (conn, addr) = s.accept()
            print("got packet")
            data = conn.recv(8192)
            send_message(data, addr, connection)
        except KeyboardInterrupt:
            sys.exit()
    s.close()
Пример #2
0
    def __init__(self,
                 username,
                 password=None,
                 server=None,
                 versions=("1.12.2", "1.12.2"),
                 auto_connect=False):
        self.username = username
        self.password = password
        self.server = server
        self.versions = versions

        self.event = lambda x: print(x)

        self.auth_token = authentication.AuthenticationToken(
            username=self.username, access_token=self.password)
        print("authenticated: %s" % self.auth_token.authenticate(
            self.username, self.password, invalidate_previous=False))
        self.connection = Connection(self.server,
                                     auth_token=self.auth_token,
                                     allowed_versions=self.versions)

        self.connection.register_packet_listener(lambda x: self.print_chat(x),
                                                 ChatMessagePacket)

        print(self.auth_token)
        print(self.connection)

        if auto_connect:
            self._loop_reconect()
Пример #3
0
 def connect(self):
     self.connection = Connection(self.ip,
                                  self.port,
                                  auth_token=auth_token,
                                  handle_exception=self.exception_handler)
     print("connecting to", self.ip)
     self.connection.register_packet_listener(
         self.handle_join_game, clientbound.play.JoinGamePacket)
     self.connection.register_packet_listener(
         self.on_login_disconnect_packet,
         clientbound.play.DisconnectPacket,
         early=True)
     # self.connection.register_packet_listener(self.print_packet, Packet, early=True)
     self.connection.register_packet_listener(
         self.on_login_disconnect_packet,
         clientbound.login.DisconnectPacket,
         early=True)
     with timeout(2):
         self.connection.connect()
         start = time.time()
         while not self.done:
             time.sleep(0.01)
             now = time.time()
             diff = now - start
             if diff > 2:
                 self.done = True
Пример #4
0
    def run(self):
        self.logger.debug(
            "Checking if the server {} is online before connecting.")

        if not self.config.mc_online:
            self.logger.info("Connecting in offline mode...")
            while not self.is_server_online():
                self.logger.info(
                    'Not connecting to server because it appears to be offline.'
                )
                time.sleep(15)
            self.bot_username = self.config.mc_username
            self.connection = Connection(
                self.config.mc_server,
                self.config.mc_port,
                username=self.config.mc_username,
                handle_exception=self.minecraft_handle_exception)
        else:
            self.auth_token = authentication.AuthenticationToken()
            try:
                self.auth_token.authenticate(self.config.mc_username,
                                             self.config.mc_password)
            except YggdrasilError as ex:
                self.logger.info(ex)
                sys.exit(os.EX_TEMPFAIL)
            self.bot_username = self.auth_token.profile.name
            self.logger.info("Logged in as %s...",
                             self.auth_token.profile.name)
            while not self.is_server_online():
                self.logger.info(
                    'Not connecting to server because it appears to be offline.'
                )
                time.sleep(15)
            self.connection = Connection(
                self.config.mc_server,
                self.config.mc_port,
                auth_token=self.auth_token,
                handle_exception=self.minecraft_handle_exception)

        self.register_handlers(self.connection)
        self.connection_retries += 1
        self.reactor_thread.start()
        self.connection.connect()
        try:
            self.aioloop.run_until_complete(
                self.discord_bot.start(self.config.discord_token))
        except (KeyboardInterrupt, SystemExit):
            # log out of discord
            self.aioloop.run_until_complete(self.discord_bot.logout())
            # log out of minecraft
            self.connection.disconnect()
            # shut down auth server
            from twisted.internet import reactor
            reactor.callFromThread(reactor.stop)
            # clean up auth server thread
            self.reactor_thread.join()
        finally:
            # close the asyncio event loop discord uses
            self.aioloop.close()
        return self.return_code
Пример #5
0
def main():
    username = '******'
    # connection = Connection(address, port, username='******'.format(random.randint(0, 1000)))
    connection = Connection(address, port, username=username)
    bot = Bot(connection, username)
    
    def print_outgoing(packet):
        if type(packet) is not my_svbnd_play.DiggingPacket:
            print('<-- %s' % packet, file=sys.stderr)

    connection.register_packet_listener(
        bot.process_packet, Packet)
    connection.register_packet_listener(
        print_outgoing, Packet, outgoing=True)

    def handle_join_game(join_game_packet, early=True):
        print('Connected.')

    connection.register_packet_listener(
        handle_join_game, clientbound.play.JoinGamePacket)

    connection.connect()    

    while True:  # making a loop
        try:  # used try so that if user pressed other than the given key error will not be shown
            a = input()
        except Exception as e:
            # print(e)
            pass  #
Пример #6
0
    def SetServer(self, ip, port=25565, handler=None):
        """
        Sets the server, ready for connection

        Parameters
        ----------
        ip : str
            The server to connect to
        port : int, optional
            The port to connect on
        handler : Function pointer, optional
            Points to the function used to handle Clientbound chat packets

        """
        handler = handler or self.ReceiveChat

        self.ip = ip
        self.port = port
        self.connection = Connection(
            ip, port, auth_token=self.auth_token, handle_exception=print
        )

        self.connection.register_packet_listener(
            handler, clientbound.play.ChatMessagePacket
        )

        self.connection.exception_handler(print)
Пример #7
0
def create_conn(address, port, version, token):
    mc_conn = Connection(
        address=address,
        port=port,
        auth_token=token,
        initial_version=version,
        allowed_versions=[version],
    )
    mc_conn.connect()
    return mc_conn
Пример #8
0
    def __init__(self,
                 username,
                 password,
                 bot_ign,
                 reply_rate=20,
                 whitelist=False):
        self.username = username
        self.password = password
        self.bot_ign = bot_ign
        self.debug = False
        self.whitelist = whitelist

        self.reply_rate = int(reply_rate)

        self.auth_token = authentication.AuthenticationToken()
        try:
            self.auth_token.authenticate(self.username, self.password)
        except YggdrasilError as error:
            print(error)
            exit()
        print("Logged in as %s." % self.auth_token.username)
        self.connection = Connection("mc.hypixel.net",
                                     25565,
                                     auth_token=self.auth_token)

        self.command_delay = 0
        self.msgQueue = []
        self.partyQueue = []
        self.commandQueue = []
        self.msgCurrentChannel = ""
        self.party = {"inP": False, "from": "", "timestamp": 0}
        self.partyConfig = {}
        self.playercooldown = {}
        self.cooldownTimer = time.time()
        self.heartbeat = time.time() + 120
        self.heartbeatCooldown = time.time() + 120
        self.msgformat = msgformat.formats(self.bot_ign, 24)
        self.bots = {x: 0 for x in msgformat.bots if x != self.bot_ign}
        self.current_load = 0
        self.inQueue = False
        self.inQueueTime = 0
        self.muted = False
        self.muteDuration = 3600
        self.unmutetime = 0
        self.muteheartbeat = 0
        self.leaderBuffer = []
        self.mods = []
        self.whitelisted = []
        try:
            with open("whitelisted.txt", "r") as file:
                self.whitelisted = [x for x in file.read().split("\n")]
        except Exception:
            self.whitelisted = []
        print("whitelisted loaded", len(self.whitelisted))
Пример #9
0
	def __init__(self, username, server, port, commands):
		self.username = username
		self.server = server
		self.port = port
		self.commands = commands
		self.bot = Connection(server, port, username=username, allowed_versions=[47])
		self.bot.register_packet_listener(self.handle_join_game, clientbound.play.JoinGamePacket)

		log("INFO", "Trying to connect {0} to {1}:{2}.".format(username, server, port))
		self.bot.connect()
		threading.Thread(target=self.execute_go, args=["/go"], daemon=True).start()
Пример #10
0
def main():
    options = get_options()

    auth_token = authentication.AuthenticationToken()
    try:
        auth_token.authenticate(options.username, options.password)
    except YggdrasilError as e:
        print(e)
        sys.exit()

    print("Logged in as " + auth_token.username)

    connection = Connection(options.address, options.port, auth_token)
    connection.connect()

    def print_chat(chat_packet):
        print("Position: " + str(chat_packet.position))
        print("Data: " + chat_packet.json_data)

    connection.register_packet_listener(print_chat, ChatMessagePacket)
    while True:
        try:
            text = input()
            packet = ChatPacket()
            packet.message = text
            connection.write_packet(packet)
        except KeyboardInterrupt:
            print("Bye!")
            sys.exit()
Пример #11
0
class MinecraftBot():
	def __init__(self, username, server, port, commands):
		self.username = username
		self.server = server
		self.port = port
		self.commands = commands
		self.bot = Connection(server, port, username=username, allowed_versions=[47])
		self.bot.register_packet_listener(self.handle_join_game, clientbound.play.JoinGamePacket)

		log("INFO", "Trying to connect {0} to {1}:{2}.".format(username, server, port))
		self.bot.connect()
		threading.Thread(target=self.execute_go, args=["/go"], daemon=True).start()

	def execute_go(self, command):
		time.sleep(15)
		self.execute_command(command)

	def handle_join_game(self, join_game_packet):
		log("INFO", "{0} is connected to {1}:{2}.".format(self.username, self.server, self.port))
		time.sleep(3)
		self.execute_command(self.commands[0])

	def execute_command(self, command):
		log("INFO", "{0} is doing command {1}".format(self.username, command))
		packet = serverbound.play.ChatPacket()
		packet.message = command
		self.bot.write_packet(packet)

	def disconnect(self):
		log("INFO", "Disconnecting {0} from {1}:{2}.".format(self.username, self.server, self.port))
		self.bot.disconnect()
		log("INFO", "{0} is disconnected of {1}:{2}.".format(self.username, self.server, self.port))
Пример #12
0
def main():
    options = get_options()

    if options.offline:
        print("Connecting in offline mode")
        connection = Connection(
            options.address, options.port, username=options.username)
    else:
        auth_token = authentication.AuthenticationToken()
        try:
            auth_token.authenticate(options.username, options.password)
        except YggdrasilError as e:
            print(e)
            sys.exit()
        print("Logged in as " + auth_token.username)
        connection = Connection(
            options.address, options.port, auth_token=auth_token)

    connection.connect()

    def print_chat(chat_packet):
        print("Position: " + str(chat_packet.position))
        print("Data: " + chat_packet.json_data)

    connection.register_packet_listener(print_chat, ChatMessagePacket)
    while True:
        try:
            text = input()
            packet = ChatPacket()
            packet.message = text
            connection.write_packet(packet)
        except KeyboardInterrupt:
            print("Bye!")
            sys.exit()
Пример #13
0
    def __init__(self, terminal: Terminal, options: object):
        """
        Parameters
        ----------
        terminal : Terminal
            class representing and managing the terminal and it's subwindows
        options : object
            options parsed by the argument parser
        """
        self._terminal = terminal

        auth_token = authentication.AuthenticationToken()
        if options.auth_type == 'Mojang':
            try:
                auth_token.authenticate(options.username, options.password)
            except YggdrasilError as e:
                print(e)
                sys.exit() # TODO Use correct status and not default to 0 as it's a failure

        self._client = Client(auth_token.profile.name, auth_token.profile.id_)
        
        self._terminal.info.update(self._client.name, util.format_uuid(self._client.uuid))
        self._terminal.console.log('Successfully authenticated')

        self._address = options.address
        self._port = options.port

        self._connection = Connection(self._address, self._port, auth_token=auth_token)

        if hasattr(options, 'Bot'):
            self._bot = options.Bot(self._terminal, self._connection, self._client)
        else:
            self._bot = None

        self._register_listeners()

        self._connection.connect()

        while (True):
            key = self._terminal.stdscr.getkey()
            if (key == 'q'):
                sys.exit(0)
            
            if (key == 'KEY_UP'):
                self._terminal.console.scroll_up()
            elif (key == 'KEY_DOWN'):
                self._terminal.console.scroll_down()
            else:
                if hasattr(self._bot, 'keys') and key in self._bot.keys and inspect.ismethod(self._bot.keys[key]):
                    self._bot.keys[key]()
Пример #14
0
def startChat(update, context):
    usr = "******" + str(update.message.from_user.first_name)
    connection = Connection("ioya.de", username=usr)
    context.user_data["connection"] = connection

    id = update.effective_chat.id

    def handle_join_game(join_game_packet):
        print("handle_join_Game")
        context.bot.send_message(chat_id=id, text='Connected to Corona Land.')

    connection.register_packet_listener(handle_join_game,
                                        clientbound.play.JoinGamePacket)

    def print_chat(chat_packet):
        msg = json.loads(chat_packet.json_data)
        translate = msg["translate"]

        if translate == "chat.type.text":
            name = msg["with"][0]["text"]
            content = msg["with"][1]["text"]
            if name != usr:
                context.bot.send_message(chat_id=update.effective_chat.id,
                                         text="%s: %s" % (name, content))

    connection.register_packet_listener(print_chat,
                                        clientbound.play.ChatMessagePacket)

    connection.connect()
    return SENDMESSAGE
def main():
    config = read_config()

    # split port and host
    match = re.match(
        r"((?P<host>[^\[\]:]+)|\[(?P<addr>[^\[\]]+)\])"
        r"(:(?P<port>\d+))?$", config["server"])
    if match is None:
        raise ValueError(f"Invalid server address: '{config['server']}'")
    address = match.group("host") or match.group("addr")
    port = int(match.group("port") or 25565)

    auth_token = authentication.AuthenticationToken()
    try:
        auth_token.authenticate(config["username"], config["password"])
    except YggdrasilError as e:
        print(e)
        sys.exit()
    print(f"Authenticated successfully as {auth_token.username}")
    connection = Connection(address, port, auth_token=auth_token)

    def handle_goodbye(signum, frame):
        print("Signing out!")
        payload = {
            'username': config["username"],
            'password': config["password"]
        }
        try:
            authentication._make_request(authentication.AUTH_SERVER, "signout",
                                         payload)
        except:
            print("Failed to sign out with Yggdrasil")
        finally:
            sys.exit()

    def handle_disconnect():
        print("Disconnected from server")
        if config["reconnect"] == True:
            connection.connect()
        else:
            sys.exit()

    connection.register_packet_listener(
        lambda packet: print(f"Connected to {address}!"),
        clientbound.play.JoinGamePacket)

    connection.register_packet_listener(handle_disconnect,
                                        clientbound.login.DisconnectPacket)

    try:
        connection.connect()
    except Exception as err:
        print(err)
        print("Failed to connect to specified server")
        sys.exit()

    signal.signal(signal.SIGINT, handle_goodbye)
    while True:
        time.sleep(1)
Пример #16
0
    def connect(self):
        global viewing

        if viewing is None:
            viewing = self.email

        Connect.connections[str(self.authtoken.username)] = Connection(self.ip, self.port, auth_token=self.authtoken)

        connection = Connect.connections[str(self.authtoken.username)]

        def onjoin(packet):

            print(f"{Colors.colors['green']}[+] Connected as {self.authtoken.username}")

            time.sleep(Config.onjoin_wait_time)

            p = serverbound.play.ChatPacket()
            p.message = Config.onjoin_command
            connection.write_packet(p)

        connection.register_packet_listener(onjoin, clientbound.play.JoinGamePacket)

        c = Chat(self.email)
        connection.register_packet_listener(c.handleChatMessage, clientbound.play.ChatMessagePacket)

        if Config.autoreconnect_on:
            d = Disconnect(self.email, self.passw)
            connection.register_packet_listener(d.handleDisconnect, clientbound.play.DisconnectPacket)

        connection.connect()
Пример #17
0
def main():
    options = get_options()

    auth_token = authentication.AuthenticationToken()
    try:
        # Uncomment line to either authenticate to mojang, or create a fake auth token for offline servers.
        auth_token.authenticate(options.username, options.password)
        # auth_token.fake_authenticate(options.username)
    except YggdrasilError as e:
        print(e)
        sys.exit()

    print("Logged in as " + auth_token.username)

    connection = Connection(options.address, options.port, auth_token)
    connection.connect()

    def print_chat(chat_packet):
        print("Position: " + str(chat_packet.position))
        print("Data: " + chat_packet.json_data)

    connection.register_packet_listener(print_chat, ChatMessagePacket)
    while True:
        try:
            text = input()
            packet = ChatPacket()
            packet.message = text
            connection.write_packet(packet)
        except KeyboardInterrupt:
            print("Bye!")
            sys.exit()
Пример #18
0
    def __init__(self, account: str, password: str, server_address: str,
                 port: int, version: int, auto_reconnect: bool,
                 auto_respawn: bool, lang: Lang):
        self.__email = account
        self.__password = base64.b64encode(password.encode())
        self.__lang = lang

        self.__logger = logging.getLogger("Auth")
        logging.basicConfig(level=logging.INFO)

        tokens = self.__get_tokens()
        self.__auth = authentication.AuthenticationToken(
            username=self.__email,
            access_token=tokens["access"],
            client_token=tokens["client"])
        self.auth()

        self.__auto_reconnect = auto_reconnect
        self.__auto_respawn = auto_respawn
        self.__connection = Connection(address=server_address,
                                       port=port,
                                       initial_version=version,
                                       auth_token=self.__auth)
        if not self.__auth.authenticated:
            return
        self.username = self.__auth.profile.name

        self.__logger = logging.getLogger(self.username)

        self.__connection.register_packet_listener(
            self.handle_join_game, clientbound.play.JoinGamePacket)
        self.__connection.register_packet_listener(
            self.print_chat, clientbound.play.ChatMessagePacket)
        self.__connection.register_packet_listener(
            self.handle_disconnect, clientbound.play.DisconnectPacket)
        self.__connection.register_packet_listener(
            self.handle_health_change, clientbound.play.UpdateHealthPacket)
        self.__connection.register_exception_handler(self.handle_exception)
        try:
            self.__connection.connect()
        except Exception as e:
            self.__logger.error(str(e))
            self.__retry()
Пример #19
0
def main():
    options = get_options()

    auth_token = authentication.AuthenticationToken()
    try:
        auth_token.authenticate(options.username, options.password)
    except YggdrasilError as e:
        print(e)
        sys.exit()
    connection = Connection(options.address, options.port, auth_token)
    connection.connect()

    print("Logged in as " + auth_token.username)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("", 9001))
    s.listen(5)

    connection.register_packet_listener(print_chat,
                                        ChatMessageClientboundPacket)

    #send_message("GET http://www.google.com/ HTTP/1.1\r\nhost: www.google.com\r\n\r\n", "address", connection)  #GET http://www.uga.edu/ HTTP/1.1\r\nHost: www.uga.edu\r\n

    #time.sleep(100)

    #sys.exit()
    while True:
        try:
            (conn, addr) = s.accept()
            print("got packet")
            data = conn.recv(8192)
            send_message(data, addr, connection)
        except KeyboardInterrupt:
            sys.exit()
    s.close()
Пример #20
0
 def __init__(self, options):
     self.auth_token = authentication.AuthenticationToken()
     try:
         self.auth_token.authenticate(options.username, options.password)
     except YggdrasilError as e:
         print(e)
         sys.exit()
     print("Logged in as " + self.auth_token.username)
     self.network = Connection(options.address, options.port,
                               self.auth_token)
     self.network.connect()
     self.register_listeners()
     #sys.stdout = Speaker(self)
     while not self.network.playing:
         pass
     self.respawn()
     while True:
         try:
             self.tick()
         except KeyboardInterrupt:
             print("Bye!")
             sys.exit()
Пример #21
0
def ServerWakeUp():
    connection = Connection("ioya.de", username="******")

    def handle_join_game(join_game_packet):
        print('Connected.')

    connection.register_packet_listener(handle_join_game,
                                        clientbound.play.JoinGamePacket)

    def print_chat(chat_packet):
        print("Message (%s): %s" %
              (chat_packet.field_string('position'), chat_packet.json_data))

    connection.register_packet_listener(print_chat,
                                        clientbound.play.ChatMessagePacket)

    connection.connect()

    sleep(2)
Пример #22
0
 def __init__(self, options):
     self.auth_token = authentication.AuthenticationToken()
     try:
         self.auth_token.authenticate(options.username, options.password)
     except YggdrasilError as e:
         print(e)
         sys.exit()
     print("Logged in as " + self.auth_token.username)
     self.network = Connection(options.address, options.port, self.auth_token)
     self.network.connect()
     self.register_listeners()
     #sys.stdout = Speaker(self)
     while not self.network.playing: pass
     self.respawn()
     while True:
         try: self.tick()
         except KeyboardInterrupt:
             print("Bye!")
             sys.exit()
Пример #23
0
 def make_connection(*args, **kwds):
     kwds['initial_version'] = self.earliest_version
     return Connection(*args, **kwds)
Пример #24
0
    webhook_url = config['webhook']
    ACCOUNT = config["mcAcc"].split(":")
    #ACCOUNT =
    custom_answers = config["custom"]
auth_token = authentication.AuthenticationToken()
#auth_token.authenticate(ACCOUNT[0], ACCOUNT[1])
while 1:
    try:
        auth_token.authenticate(ACCOUNT[0], ACCOUNT[1])
        break
    except:
        print("waiting for mojang cooldown")
        time.sleep(10)

print("Logged in as %s..." % auth_token.username)
connection = Connection("gommehd.net", auth_token=auth_token)

#connection = Connection("localhost", 62139, username="******")
'''
def print_incoming(packet):
    if type(packet) is Packet:
        # This is a direct instance of the base Packet type, meaning
        # that it is a packet of unknown type, so we do not print it.
        return
    print('--&gt; %s' % packet, file=sys.stderr)


def print_outgoing(packet):
    print('&lt;-- %s' % packet, file=sys.stderr)

Пример #25
0
def main():
    options = get_options()

    if options.offline:
        print("Connecting in offline mode...")
        connection = Connection(
            options.address, options.port, username=options.username)
    else:
        auth_token = authentication.AuthenticationToken()
        try:
            auth_token.authenticate(options.username, options.password)
        except YggdrasilError as e:
            print(e)
            sys.exit()
        print("Logged in as %s..." % auth_token.username)
        connection = Connection(
            options.address, options.port, auth_token=auth_token)

    if options.dump_packets:
        def print_incoming(packet):
            if type(packet) is Packet:
                # This is a direct instance of the base Packet type, meaning
                # that it is a packet of unknown type, so we do not print it
                # unless explicitly requested by the user.
                if options.dump_unknown:
                    print('--> [unknown packet] %s' % packet, file=sys.stderr)
            else:
                print('--> %s' % packet, file=sys.stderr)

        def print_outgoing(packet):
            print('<-- %s' % packet, file=sys.stderr)

        connection.register_packet_listener(
            print_incoming, Packet, early=True)
        connection.register_packet_listener(
            print_outgoing, Packet, outgoing=True)

    def handle_join_game(join_game_packet):
        print('Connected.')

    connection.register_packet_listener(
        handle_join_game, clientbound.play.JoinGamePacket)

    def print_chat(chat_packet):
        print("Message (%s): %s" % (
            chat_packet.field_string('position'), chat_packet.json_data))

    connection.register_packet_listener(
        print_chat, clientbound.play.ChatMessagePacket)

    def handle_zzz(chat_packet):
        if json.loads(chat_packet.json_data).get("with", " ")[-1] == "zzz":
            connection.disconnect()
            time.sleep(5)
            connection.connect()
            
    connection.register_packet_listener(
        handle_zzz, clientbound.play.ChatMessagePacket)        

    connection.connect()

    while True:
        try:
            text = input()
            if text == "/respawn":
                print("respawning...")
                packet = serverbound.play.ClientStatusPacket()
                packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
                connection.write_packet(packet)
            else:
                packet = serverbound.play.ChatPacket()
                packet.message = text
                connection.write_packet(packet)
        except KeyboardInterrupt:
            print("Bye!")
            sys.exit()
Пример #26
0
            #playSong("thetop")

        if kb.is_pressed("ctrl+shift"):
            #MultiDimPrint("https://cdn.discordapp.com/attachments/255681374025941003/677868965674090526/wall.schematic", (219, 231, -155))
            while kb.is_pressed("ctrl+shift"):
                pass

        if kb.is_pressed("f4"):
            exit()

        updatePosition()


if __name__ == '__main__':
    # connect and register listeners
    dj = Connection("127.0.0.1", username="******")
    dj.connect()
    dj.register_packet_listener(
        _setPosition, clientbound.play.player_position_and_look_packet.
        PlayerPositionAndLookPacket)
    dj.register_packet_listener(_onChatMessage,
                                clientbound.play.ChatMessagePacket)

    print("Connecting...")
    while pos is None:
        # wait for server to update dj's position
        pass
    print("Connected")
    sendChat("<3")
    main()
Пример #27
0
 def make_connection(*args, **kwds):
     kwds["initial_version"] = self.lowest_version
     return Connection(*args, **kwds)
Пример #28
0
def main() -> int:

    # Handle program arguments
    ap = argparse.ArgumentParser(
        prog="mchat",
        description="A console chat client for most Minecraft server versions")
    ap.add_argument("server_address", help="IP address of a Minecraft server")
    ap.add_argument("-p",
                    "--port",
                    help="Minecraft server port (default: %(default)s)",
                    type=int,
                    default=25565)
    ap.add_argument("-u", "--username", help="Minecraft username or email")
    ap.add_argument(
        "-v",
        "--version",
        help="Client -> Server protocol version to use (default: %(default)s)",
        default="1.16.4")
    args = ap.parse_args()

    # Verify server version to keep the terminal looking clean
    if args.version not in SUPPORTED_MINECRAFT_VERSIONS.keys():
        console.print(
            f"[bold yellow]{args.version} is not a valid Minecraft version. Versions from {list(SUPPORTED_MINECRAFT_VERSIONS.keys())[0]} to {list(SUPPORTED_MINECRAFT_VERSIONS.keys())[-1]} are allowed."
        )
        return 1

    # Do authentication
    if not args.username:
        username = Prompt.ask("Username or email")
    else:
        username = args.username

    password = getpass.getpass("Password: "******"[bright_black]Loaded authentication information")

    # Determine the actual protocol version number
    protocol_version_num = SUPPORTED_MINECRAFT_VERSIONS[args.version]
    console.print(
        f"[bright_black]Selecting protocol version {protocol_version_num}")

    # Authenticate with Mojang
    auth_token = AuthenticationToken()
    console.print(f"[bright_black]Contacting Yggdrasil...")

    try:
        auth_token.authenticate(username, password)
    except YggdrasilError as e:
        console.print(f"[bold red]Failed to authenticate Minecraft session")
        return 1

    # Open a connection
    server_connection = Connection(args.server_address,
                                   args.port,
                                   auth_token,
                                   allowed_versions=[protocol_version_num])

    try:
        server_connection.connect()
    except:
        console.print(f"[bold red]Could not connect to server")
        return 1

    # Set up an incoming chat handler
    server_connection.register_packet_listener(incomingChatHandler,
                                               ChatMessagePacket)
    console.print(f"[bright_black]Listen to incoming chat packets")

    # Set up input loop
    console.print(
        "All further inputs will be sent to server chat. Press CTRL+C to stop")
    try:
        while True:

            # Get a line from the user
            chat_message = console.input()

            # Send the chat message
            packet = serverbound.play.ChatPacket()
            packet.message = chat_message
            server_connection.write_packet(packet)

    except KeyboardInterrupt as e:
        print("\rGoodbye")

    return 0
Пример #29
0
class Main(object):
    def __init__(self, options):
        self.auth_token = authentication.AuthenticationToken()
        try:
            self.auth_token.authenticate(options.username, options.password)
        except YggdrasilError as e:
            print(e)
            sys.exit()
        print("Logged in as " + self.auth_token.username)
        self.network = Connection(options.address, options.port, self.auth_token)
        self.network.connect()
        self.register_listeners()
        #sys.stdout = Speaker(self)
        while not self.network.playing: pass
        self.respawn()
        while True:
            try: self.tick()
            except KeyboardInterrupt:
                print("Bye!")
                sys.exit()

    def register_listeners(self):
        self.network.register_packet_listener(self.print_chat, ChatMessagePacket)
        self.network.register_packet_listener(self.set_pos, PlayerPositionAndLookPacket)
        self.network.register_packet_listener(self.recieve_plugin_message, PluginMessage)
        self.network.register_packet_listener(self.set_health, UpdateHealth)

    def tick(self):
        text = input()
        self.speak(text)
        
    def speak(self, message):
        packet = ChatPacket()
        packet.message = message
        self.network.write_packet(packet)
    
    def set_health(self, health_packet):
        if health_packet.health == 0.0:
            print "RESPAWN"
            self.respawn()
            
    def respawn(self):
        packet = ClientStatus()
        packet.action_id = 0
        self.network.write_packet(packet)
        #print packet
            
    def print_chat(self, chat_packet):
        print type(chat_packet)
        print("Position: " + str(chat_packet.position))
        print("Data: " + chat_packet.json_data)

    def recieve_plugin_message(self, plugin_message):
        data = plugin_message.data.split("|")
        if len(data) == 2 and data[0] == "MC":
            if data[1] == "Brand": print "Brand:", plugin_message.channel
            else:
                print "PLUGIN MESSAGE:", data[1], plugin_message.channel
Пример #30
0
def main():
    options = get_options()

    if options.offline:
        print("Connecting in offline mode...")
        connection = Connection(
            options.address, options.port, username=options.username)
    else:
        auth_token = authentication.AuthenticationToken()
        try:
            auth_token.authenticate(options.username, options.password)
        except YggdrasilError as e:
            print(e)
            sys.exit()
        print("Logged in as %s..." % auth_token.username)
        connection = Connection(
            options.address, options.port, auth_token=auth_token)

    if options.dump_packets:
        def print_incoming(packet):
            if type(packet) is Packet:
                # This is a direct instance of the base Packet type, meaning
                # that it is a packet of unknown type, so we do not print it.
                return
            print('--> %s' % packet, file=sys.stderr)

        def print_outgoing(packet):
            print('<-- %s' % packet, file=sys.stderr)

        connection.register_packet_listener(
            print_incoming, Packet, early=True)
        connection.register_packet_listener(
            print_outgoing, Packet, outgoing=True)

    once = False

    def handle_join_game(join_game_packet):
        message_queue.append(("CONNECTION", "**Connected**"))
        once = True
        print('Connected.')

    connection.register_packet_listener(
        handle_join_game, clientbound.play.JoinGamePacket)

    def print_chat(chat_packet):
        print("[%s]: %s" % (
            chat_packet.field_string('position'), parse_chat_item(json.loads(chat_packet.json_data))))

    connection.register_packet_listener(
        print_chat, clientbound.play.ChatMessagePacket)

    # Add a deque for chat messages and register a method to get them
    message_queue = deque()

    def forward_chat(chat_packet):
        msg = parse_chat_item(json.loads(chat_packet.json_data))
        if msg.startswith("<"):
            author, message = parse_message(msg)
            if (author != auth_token.username and message != ""): # Don't put in queue your own messages!
                message_queue.append((author, message))

    connection.register_packet_listener(
        forward_chat, clientbound.play.ChatMessagePacket)

    # More maybe? Add here shit for a chatbot

    # Auto respawn because we can't send chat while dead
    def auto_respawn(update_health_packet):
        if update_health_packet.health <= 0:
            print("Respawning")
            packet = serverbound.play.ClientStatusPacket()
            packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
            connection.write_packet(packet)

    connection.register_packet_listener(
        auto_respawn, clientbound.play.UpdateHealthPacket)

    # Start the discord thread and provide the message deque

    botThread = DiscordBotThread(message_queue, connection)
    botThread.daemon = True
    botThread.start()

    connection.connect()

    while True:
        try:
            text = input()
            if text == "/respawn":
                print("respawning...")
                packet = serverbound.play.ClientStatusPacket()
                packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
                connection.write_packet(packet)
            else:
                packet = serverbound.play.ChatPacket()
                packet.message = text
                connection.write_packet(packet)
        except KeyboardInterrupt:
            print("Bye!")
            sys.exit()
Пример #31
0
    auth_token.refresh()
except (IOError, YggdrasilError):
    # IF there is no authentication file authenticate using username and password
    try:
        options = get_options()
        auth_token.authenticate(options["username"], options["password"])
    except YggdrasilError as e:
        print(e)
        sys.exit()

with open('minecraft.auth', 'w') as fout:
    fout.write(auth_token.client_token + '\n')
    fout.write(auth_token.access_token)

print("Logged in as %s..." % auth_token.username)
connection = Connection("localhost", 25565, auth_token=auth_token)


def handle_join_game(join_game_packet):
    print('Connected.')


connection.register_packet_listener(handle_join_game,
                                    clientbound.play.JoinGamePacket)

# def print_chat(chat_packet):
# print("Message (%s): %s" % (
# chat_packet.field_string('position'), chat_packet.json_data))

# connection.register_packet_listener(
# print_chat, clientbound.play.ChatMessagePacket)
Пример #32
0
class MinecraftDiscordBridge():
    def __init__(self):
        self.return_code = os.EX_OK
        self.session_token = ""
        self.uuid_cache = bidict()
        self.webhooks = []
        self.bot_username = ""
        self.next_message_time = datetime.now(timezone.utc)
        self.previous_message = ""
        self.player_list = bidict()
        self.previous_player_list = bidict()
        self.accept_join_events = False
        self.tab_header = ""
        self.tab_footer = ""
        # Initialize the discord part
        self.discord_bot = discord.Client()
        self.config = Configuration("config.json")
        self.connection_retries = 0
        self.auth_token = None
        self.connection = None
        self.setup_logging(self.config.logging_level)
        self.database_session = DatabaseSession()
        self.logger = logging.getLogger("bridge")
        self.database_session.initialize(self.config)
        self.bot_perms = discord.Permissions()
        self.bot_perms.update(manage_messages=True, manage_webhooks=True)
        # Async http request pool
        self.req_future_session = FuturesSession(max_workers=100)
        self.reactor_thread = Thread(target=self.run_auth_server,
                                     args=(self.config.auth_port, ))
        self.aioloop = asyncio.get_event_loop()
        # We need to import twisted after setting up the logger because twisted hijacks our logging
        from . import auth_server
        auth_server.DATABASE_SESSION = self.database_session
        if self.config.es_enabled:
            if self.config.es_auth:
                self.es_logger = ElasticsearchLogger(self.req_future_session,
                                                     self.config.es_url,
                                                     self.config.es_username,
                                                     self.config.es_password)
            else:
                self.es_logger = ElasticsearchLogger(self.req_future_session,
                                                     self.config.es_url)

        @self.discord_bot.event
        async def on_ready():  # pylint: disable=W0612
            self.logger.info("Discord bot logged in as %s (%s)",
                             self.discord_bot.user.name,
                             self.discord_bot.user.id)
            self.logger.info(
                "Discord bot invite link: %s",
                discord.utils.oauth_url(client_id=self.discord_bot.user.id,
                                        permissions=self.bot_perms))
            await self.discord_bot.change_presence(
                activity=discord.Game("mc!help for help"))
            self.webhooks = []
            session = self.database_session.get_session()
            channels = session.query(DiscordChannel).all()
            session.close()
            for channel in channels:
                channel_id = channel.channel_id
                discord_channel = self.discord_bot.get_channel(channel_id)
                if discord_channel is None:
                    session = self.database_session.get_session()
                    session.query(DiscordChannel).filter_by(
                        channel_id=channel_id).delete()
                    session.close()
                    continue
                channel_webhooks = await discord_channel.webhooks()
                found = False
                for webhook in channel_webhooks:
                    if webhook.name == "_minecraft" and webhook.user == self.discord_bot.user:
                        self.webhooks.append(webhook.url)
                        found = True
                    self.logger.debug("Found webhook %s in channel %s",
                                      webhook.name, discord_channel.name)
                if not found:
                    # Create the hook
                    await discord_channel.create_webhook(name="_minecraft")

        @self.discord_bot.event
        async def on_message(message):  # pylint: disable=W0612
            # We do not want the bot to reply to itself
            if message.author == self.discord_bot.user:
                return
            this_channel = message.channel.id

            # PM Commands
            if message.content.startswith("mc!help"):
                try:
                    send_channel = message.channel
                    if isinstance(message.channel, discord.abc.GuildChannel):
                        await message.delete()
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        send_channel = message.author.dm_channel
                    msg = self.get_discord_help_string()
                    await send_channel.send(msg)
                    return
                except discord.errors.Forbidden:
                    if isinstance(message.author, discord.abc.User):
                        msg = "{}, please allow private messages from this bot.".format(
                            message.author.mention)
                        error_msg = await message.channel.send(msg)
                        await asyncio.sleep(3)
                        await error_msg.delete()
                    return

            elif message.content.startswith("mc!register"):
                try:
                    send_channel = message.channel
                    if isinstance(message.channel, discord.abc.GuildChannel):
                        await message.delete()
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        send_channel = message.author.dm_channel
                    session = self.database_session.get_session()
                    discord_account = session.query(DiscordAccount).filter_by(
                        discord_id=message.author.id).first()
                    if not discord_account:
                        new_discord_account = DiscordAccount(message.author.id)
                        session.add(new_discord_account)
                        session.commit()
                        discord_account = session.query(
                            DiscordAccount).filter_by(
                                discord_id=message.author.id).first()

                    new_token = self.generate_random_auth_token(16)
                    account_link_token = AccountLinkToken(
                        message.author.id, new_token)
                    discord_account.link_token = account_link_token
                    session.add(account_link_token)
                    session.commit()
                    msg = "Please connect your minecraft account to `{}.{}:{}` in order to link it to this bridge!"\
                        .format(new_token, self.config.auth_dns, self.config.auth_port)
                    session.close()
                    del session
                    await send_channel.send(msg)
                    return
                except discord.errors.Forbidden:
                    if isinstance(message.author, discord.abc.User):
                        msg = "{}, please allow private messages from this bot.".format(
                            message.author.mention)
                        error_msg = await message.channel.send(msg)
                        await asyncio.sleep(3)
                        await error_msg.delete()
                    return

            # Global Commands
            elif message.content.startswith("mc!chathere"):
                if isinstance(message.channel, discord.abc.PrivateChannel):
                    msg = "Sorry, this command is only available in public channels."
                    await message.channel.send(msg)
                    return
                if message.author.id not in self.config.admin_users:
                    await message.delete()
                    try:
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        dm_channel = message.author.dm_channel
                        msg = "Sorry, you do not have permission to execute that command!"
                        await dm_channel.send(msg)
                        return
                    except discord.errors.Forbidden:
                        if isinstance(message.author, discord.abc.User):
                            msg = "{}, please allow private messages from this bot.".format(
                                message.author.mention)
                            error_msg = await message.channel.send(msg)
                            await asyncio.sleep(3)
                            await error_msg.delete()
                        return
                session = self.database_session.get_session()
                channels = session.query(DiscordChannel).filter_by(
                    channel_id=this_channel).all()
                if not channels:
                    new_channel = DiscordChannel(this_channel)
                    session.add(new_channel)
                    session.commit()
                    session.close()
                    del session
                    webhook = await message.channel.create_webhook(
                        name="_minecraft")
                    self.webhooks.append(webhook.url)
                    msg = "The bot will now start chatting here! To stop this, run `mc!stopchathere`."
                    await message.channel.send(msg)
                else:
                    msg = "The bot is already chatting in this channel! To stop this, run `mc!stopchathere`."
                    await message.channel.send(msg)
                    return

            elif message.content.startswith("mc!stopchathere"):
                if isinstance(message.channel, discord.abc.PrivateChannel):
                    msg = "Sorry, this command is only available in public channels."
                    await message.channel.send(msg)
                    return
                if message.author.id not in self.config.admin_users:
                    await message.delete()
                    try:
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        dm_channel = message.author.dm_channel
                        msg = "Sorry, you do not have permission to execute that command!"
                        await dm_channel.send(msg)
                        return
                    except discord.errors.Forbidden:
                        if isinstance(message.author, discord.abc.User):
                            msg = "{}, please allow private messages from this bot.".format(
                                message.author.mention)
                            error_msg = await message.channel.send(msg)
                            await asyncio.sleep(3)
                            await error_msg.delete()
                        return
                session = self.database_session.get_session()
                deleted = session.query(DiscordChannel).filter_by(
                    channel_id=this_channel).delete()
                session.commit()
                session.close()
                for webhook in await message.channel.webhooks():
                    if webhook.name == "_minecraft" and webhook.user == self.discord_bot.user:
                        # Copy the list to avoid some problems since
                        # we're deleting indicies form it as we loop
                        # through it
                        if webhook.url in self.webhooks[:]:
                            self.webhooks.remove(webhook.url)
                        await webhook.delete()
                if deleted < 1:
                    msg = "The bot was not chatting here!"
                    await message.channel.send(msg)
                    return
                else:
                    msg = "The bot will no longer chat here!"
                    await message.channel.send(msg)
                    return

            elif message.content.startswith("mc!tab"):
                send_channel = message.channel
                try:
                    if isinstance(message.channel, discord.abc.GuildChannel):
                        await message.delete()
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        send_channel = message.author.dm_channel
                    player_list = ", ".join(
                        list(map(lambda x: x[1], self.player_list.items())))
                    msg = "{}\n" \
                        "Players online: {}\n" \
                        "{}".format(self.escape_markdown(
                            self.strip_colour(self.tab_header)), self.escape_markdown(
                                self.strip_colour(player_list)), self.escape_markdown(
                                    self.strip_colour(self.tab_footer)))
                    await send_channel.send(msg)
                    return
                except discord.errors.Forbidden:
                    if isinstance(message.author, discord.abc.User):
                        msg = "{}, please allow private messages from this bot.".format(
                            message.author.mention)
                        error_msg = await message.channel.send(msg)
                        await asyncio.sleep(3)
                        await error_msg.delete()
                    return

            elif message.content.startswith("mc!botlink"):
                send_channel = message.channel
                try:
                    if isinstance(message.channel, discord.abc.GuildChannel):
                        await message.delete()
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        send_channel = message.author.dm_channel
                    msg = "Use the following link to invite this bot to a guild:\n{}".format(
                        discord.utils.oauth_url(
                            client_id=self.discord_bot.user.id,
                            permissions=self.bot_perms))
                    await send_channel.send(msg)
                    return
                except discord.errors.Forbidden:
                    if isinstance(message.author, discord.abc.User):
                        msg = "{}, please allow private messages from this bot.".format(
                            message.author.mention)
                        error_msg = await message.channel.send(msg)
                        await asyncio.sleep(3)
                        await error_msg.delete()
                    return

            elif message.content.startswith("mc!about"):
                send_channel = message.channel
                try:
                    if isinstance(message.channel, discord.abc.GuildChannel):
                        await message.delete()
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        send_channel = message.author.dm_channel
                    msg = "This bot is running minecraft-discord-bridge version {}.\n" \
                          "The source code is available at https://github.com/starcraft66/minecraft-discord-bridge" \
                        .format(minecraft_discord_bridge.__version__)
                    await send_channel.send(msg)
                    return
                except discord.errors.Forbidden:
                    if isinstance(message.author, discord.abc.User):
                        msg = "{}, please allow private messages from this bot.".format(
                            message.author.mention)
                        error_msg = await message.channel.send(msg)
                        await asyncio.sleep(3)
                        await error_msg.delete()
                    return

            elif message.content.startswith("mc!"):
                # Catch-all
                send_channel = message.channel
                try:
                    if isinstance(message.channel, discord.abc.GuildChannel):
                        await message.delete()
                        dm_channel = message.author.dm_channel
                        if not dm_channel:
                            await message.author.create_dm()
                        send_channel = message.author.dm_channel
                    msg = "Unknown command, type `mc!help` for a list of commands."
                    await send_channel.send(msg)
                    return
                except discord.errors.Forbidden:
                    if isinstance(message.author, discord.abc.User):
                        msg = "{}, please allow private messages from this bot.".format(
                            message.author.mention)
                        error_msg = await message.channel.send(msg)
                        await asyncio.sleep(3)
                        await error_msg.delete()
                    return

            elif "https://discord.gg" in message.content.lower():
                await message.delete()  # Deletes the message
                # Add something more if you want to

                msg = f"{message.author.mention} invites aren't allowed!"  # Your message

                await send_channel.send(msg)

            elif not message.author.bot:
                session = self.database_session.get_session()
                channel_should_chat = session.query(DiscordChannel).filter_by(
                    channel_id=this_channel).first()
                if channel_should_chat:
                    await message.delete()
                    discord_user = session.query(DiscordAccount).filter_by(
                        discord_id=message.author.id).first()
                    if discord_user:
                        if discord_user.minecraft_account:
                            minecraft_uuid = discord_user.minecraft_account.minecraft_uuid
                            session.close()
                            del session
                            minecraft_username = self.mc_uuid_to_username(
                                minecraft_uuid)

                            # Max chat message length: 256, bot username does not count towards this
                            # Does not count|Counts
                            # <BOT_USERNAME> minecraft_username: message
                            padding = 2 + len(minecraft_username)

                            message_to_send = self.remove_emoji(
                                message.clean_content.encode('utf-8').decode(
                                    'ascii', 'replace')).strip()
                            message_to_discord = self.escape_markdown(
                                message.clean_content)

                            total_len = padding + len(message_to_send)
                            if total_len > 256:
                                message_to_send = message_to_send[:(256 -
                                                                    padding)]
                                message_to_discord = message_to_discord[:(
                                    256 - padding)]
                            elif not message_to_send:
                                return

                            session = self.database_session.get_session()
                            channels = session.query(DiscordChannel).all()
                            session.close()
                            del session
                            if message_to_send == self.previous_message or \
                                    datetime.now(timezone.utc) < self.next_message_time:
                                send_channel = message.channel
                                try:
                                    if isinstance(message.channel,
                                                  discord.abc.GuildChannel):
                                        dm_channel = message.author.dm_channel
                                        if not dm_channel:
                                            await message.author.create_dm()
                                        send_channel = message.author.dm_channel
                                    msg = "Your message \"{}\" has been rate-limited.".format(
                                        message.clean_content)
                                    await send_channel.send(msg)
                                    return
                                except discord.errors.Forbidden:
                                    if isinstance(message.author,
                                                  discord.abc.User):
                                        msg = "{}, please allow private messages from this bot.".format(
                                            message.author.mention)
                                        error_msg = await message.channel.send(
                                            msg)
                                        await asyncio.sleep(3)
                                        await error_msg.delete()
                                    return

                            self.previous_message = message_to_send
                            self.next_message_time = datetime.now(
                                timezone.utc) + timedelta(
                                    seconds=self.config.message_delay)

                            self.logger.info(
                                "Outgoing message from discord: Username: %s Message: %s",
                                minecraft_username, message_to_send)

                            for channel in channels:
                                discord_channel = self.discord_bot.get_channel(
                                    channel.channel_id)
                                if not discord_channel:
                                    session = self.database_session.get_session(
                                    )
                                    session.query(DiscordChannel).filter_by(
                                        channel_id=channel.channel_id).delete(
                                        )
                                    session.close()
                                    continue
                                webhooks = await discord_channel.webhooks()
                                for webhook in webhooks:
                                    if webhook.name == "_minecraft":
                                        await webhook.send(
                                            username=minecraft_username,
                                            avatar_url=
                                            "https://visage.surgeplay.com/face/160/{}"
                                            .format(minecraft_uuid),
                                            content=message_to_discord)

                            packet = serverbound.play.ChatPacket()
                            packet.message = "{}: {}".format(
                                minecraft_username, message_to_send)
                            self.connection.write_packet(packet)
                    else:
                        send_channel = message.channel
                        try:
                            if isinstance(message.channel,
                                          discord.abc.GuildChannel):
                                dm_channel = message.author.dm_channel
                                if not dm_channel:
                                    await message.author.create_dm()
                                send_channel = message.author.dm_channel
                            msg = "Unable to send chat message: there is no Minecraft account linked to this discord " \
                                "account, please run `mc!register`."
                            await send_channel.send(msg)
                            return
                        except discord.errors.Forbidden:
                            if isinstance(message.author, discord.abc.User):
                                msg = "{}, please allow private messages from this bot.".format(
                                    message.author.mention)
                                error_msg = await message.channel.send(msg)
                                await asyncio.sleep(3)
                                await error_msg.delete()
                            return
                        finally:
                            session.close()
                            del session
                else:
                    session.close()
                    del session

    def run(self):
        self.logger.debug(
            "Checking if the server {} is online before connecting.")

        if not self.config.mc_online:
            self.logger.info("Connecting in offline mode...")
            while not self.is_server_online():
                self.logger.info(
                    'Not connecting to server because it appears to be offline.'
                )
                time.sleep(15)
            self.bot_username = self.config.mc_username
            self.connection = Connection(
                self.config.mc_server,
                self.config.mc_port,
                username=self.config.mc_username,
                handle_exception=self.minecraft_handle_exception)
        else:
            self.auth_token = authentication.AuthenticationToken()
            try:
                self.auth_token.authenticate(self.config.mc_username,
                                             self.config.mc_password)
            except YggdrasilError as ex:
                self.logger.info(ex)
                sys.exit(os.EX_TEMPFAIL)
            self.bot_username = self.auth_token.profile.name
            self.logger.info("Logged in as %s...",
                             self.auth_token.profile.name)
            while not self.is_server_online():
                self.logger.info(
                    'Not connecting to server because it appears to be offline.'
                )
                time.sleep(15)
            self.connection = Connection(
                self.config.mc_server,
                self.config.mc_port,
                auth_token=self.auth_token,
                handle_exception=self.minecraft_handle_exception)

        self.register_handlers(self.connection)
        self.connection_retries += 1
        self.reactor_thread.start()
        self.connection.connect()
        try:
            self.aioloop.run_until_complete(
                self.discord_bot.start(self.config.discord_token))
        except (KeyboardInterrupt, SystemExit):
            # log out of discord
            self.aioloop.run_until_complete(self.discord_bot.logout())
            # log out of minecraft
            self.connection.disconnect()
            # shut down auth server
            from twisted.internet import reactor
            reactor.callFromThread(reactor.stop)
            # clean up auth server thread
            self.reactor_thread.join()
        finally:
            # close the asyncio event loop discord uses
            self.aioloop.close()
        return self.return_code

    def mc_uuid_to_username(self, mc_uuid: str):
        if mc_uuid not in self.uuid_cache:
            try:
                short_uuid = mc_uuid.replace("-", "")
                mojang_response = self.req_future_session.get(
                    "https://api.mojang.com/user/profiles/{}/names".format(
                        short_uuid)).result().json()
                if len(mojang_response) > 1:
                    # Multiple name changes
                    player_username = mojang_response[-1]["name"]
                else:
                    # Only one name
                    player_username = mojang_response[0]["name"]
                self.uuid_cache[mc_uuid] = player_username
                return player_username
            except RequestException as ex:
                self.logger.error(ex, exc_info=True)
                self.logger.error(
                    "Failed to lookup %s's username using the Mojang API.",
                    mc_uuid)
        else:
            return self.uuid_cache[mc_uuid]

    def mc_username_to_uuid(self, username: str):
        if username not in self.uuid_cache.inv:
            try:
                player_uuid = self.req_future_session.get(
                    "https://api.mojang.com/users/profiles/minecraft/{}".
                    format(username)).result().json()["id"]
                long_uuid = uuid.UUID(player_uuid)
                self.uuid_cache.inv[username] = str(long_uuid)
                return player_uuid
            except RequestException:
                self.logger.error(
                    "Failed to lookup %s's username using the Mojang API.",
                    username)
        else:
            return self.uuid_cache.inv[username]

    def get_discord_help_string(self):
        help_str = (
            "Admin commands:\n"
            "`mc!chathere`: Starts outputting server messages in this channel\n"
            "`mc!stopchathere`: Stops outputting server messages in this channel\n"
            "User commands:\n"
            "`mc!tab`: Sends you the content of the server's player/tab list\n"
            "`mc!register`: Starts the minecraft account registration process\n"
            "`mc!botlink`: Sends you the link to invite this bot to a guild\n"
            "`mc!about`: Sends you information about the running bridge\n"
            "To start chatting on the minecraft server, please register your account using `mc!register`."
        )
        return help_str

    # https://stackoverflow.com/questions/33404752/removing-emojis-from-a-string-in-python
    def remove_emoji(self, dirty_string):
        emoji_pattern = re.compile(
            "["
            u"\U0001F600-\U0001F64F"  # emoticons
            u"\U0001F300-\U0001F5FF"  # symbols & pictographs
            u"\U0001F680-\U0001F6FF"  # transport & map symbols
            u"\U0001F1E0-\U0001F1FF"  # flags (iOS)
            u"\U0001F900-\U0001FAFF"  # CJK Compatibility Ideographs
            # u"\U00002702-\U000027B0"
            # u"\U000024C2-\U0001F251"
            "]+",
            flags=re.UNICODE)
        return emoji_pattern.sub(r'', dirty_string)

    def escape_markdown(self, md_string):
        # Don't mess with urls
        url_regex = re.compile(
            r'^(?:http|ftp)s?://'  # http:// or https://
            r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # domain...
            r'localhost|'  # localhost...
            r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|'  # ...or ipv4
            r'\[?[A-F0-9]*:[A-F0-9:]+\]?)'  # ...or ipv6
            r'(?::\d+)?'  # optional port
            r'(?:/?|[/?]\S+)$',
            re.IGNORECASE)
        escaped_string = ""
        # Split the message into pieces, each "word" speparated into a string is a piece
        # Discord ignores formatting characters in urls so we can't just replace the whole
        # string... We need to go through words one by one to find out what is a url (don't)
        # escape) and what isn't (escape).
        for piece in md_string.split(" "):
            if url_regex.match(piece):
                escaped_string += "{} ".format(piece)
                continue
            # Absolutely needs to go first or it will replace our escaping slashes!
            piece = piece.replace("\\", "\\\\")
            piece = piece.replace("_", "\\_")
            piece = piece.replace("*", "\\*")
            escaped_string += "{} ".format(piece)
        if escaped_string.startswith(">"):
            escaped_string = "\\" + escaped_string
        escaped_string.strip()
        return escaped_string

    def strip_colour(self, dirty_string):
        colour_pattern = re.compile(
            u"\U000000A7"  # selection symbol
            ".",
            flags=re.UNICODE)
        return colour_pattern.sub(r'', dirty_string)

    def setup_logging(self, level):
        if level.lower() == "debug":
            log_level = logging.DEBUG
        else:
            log_level = logging.INFO
        log_format = "%(asctime)s:%(name)s:%(levelname)s:%(message)s"
        logging.basicConfig(filename="bridge_log.log",
                            format=log_format,
                            level=log_level)
        stdout_logger = logging.StreamHandler(sys.stdout)
        stdout_logger.setFormatter(logging.Formatter(log_format))
        logging.getLogger().addHandler(stdout_logger)

    def run_auth_server(self, port):
        # We need to import twisted after setting up the logger because twisted hijacks our logging
        from twisted.internet import reactor
        from .auth_server import AuthFactory

        # Create factory
        factory = AuthFactory()

        # Listen
        self.logger.info("Starting authentication server on port %d", port)

        factory.listen("", port)
        reactor.run(installSignalHandlers=False)

    def generate_random_auth_token(self, length):
        letters = string.ascii_lowercase + string.digits + string.ascii_uppercase
        return ''.join(random.choice(letters) for i in range(length))

    def handle_disconnect(self, json_data=""):
        self.logger.info('Disconnected.')
        if json_data:
            self.logger.info("Disconnect json data: %s", json_data)
        if self.connection_retries >= self.config.failsafe_retries:
            self.logger.info(
                "Failed to join the server %s times in a row. Exiting.",
                self.connection_retries)
            self.logger.info(
                "Use a process supervisor if you wish to automatically restart the bridge."
            )
            # This is possibly a huge hack... Since we cannot reliably raise exceptions on this thread
            # for them to be caught on the main thread, we call interrupt_main to raise a KeyboardInterrupt
            # on main and tell it to shut the bridge down.
            self.return_code = os.EX_TEMPFAIL
            _thread.interrupt_main()
            return
        self.previous_player_list = self.player_list.copy()
        self.accept_join_events = False
        self.player_list = bidict()
        if self.connection.connected:
            self.logger.info(
                "Forced a disconnection because the connection is still connected."
            )
            self.connection.disconnect(immediate=True)
        time.sleep(15)
        while not self.is_server_online():
            self.logger.info(
                'Not reconnecting to server because it appears to be offline.')
            time.sleep(15)
        self.logger.info('Reconnecting.')
        self.connection_retries += 1
        self.connection.connect()

    def handle_disconnect_packet(self, disconnect_packet):
        self.handle_disconnect(disconnect_packet.json_data)

    def minecraft_handle_exception(self, exception, exc_info):
        self.logger.error("A minecraft exception occured! %s:",
                          exception,
                          exc_info=exc_info)
        self.handle_disconnect()

    def is_server_online(self):
        server = MinecraftServer.lookup("{}:{}".format(self.config.mc_server,
                                                       self.config.mc_port))
        try:
            status = server.status()
            del status
            return True
        except ConnectionRefusedError:
            return False
        # AttributeError: 'TCPSocketConnection' object has no attribute 'socket'
        # This might not be required as it happens upstream
        except AttributeError:
            return False

    def register_handlers(self, connection):
        connection.register_packet_listener(self.handle_join_game,
                                            clientbound.play.JoinGamePacket)

        connection.register_packet_listener(self.handle_chat,
                                            clientbound.play.ChatMessagePacket)

        connection.register_packet_listener(
            self.handle_health_update, clientbound.play.UpdateHealthPacket)

        connection.register_packet_listener(self.handle_disconnect_packet,
                                            clientbound.play.DisconnectPacket)

        connection.register_packet_listener(
            self.handle_tab_list, clientbound.play.PlayerListItemPacket)

        connection.register_packet_listener(
            self.handle_player_list_header_and_footer_update,
            clientbound.play.PlayerListHeaderAndFooterPacket)

    def handle_player_list_header_and_footer_update(self,
                                                    header_footer_packet):
        self.logger.debug("Got Tablist H/F Update: header=%s",
                          header_footer_packet.header)
        self.logger.debug("Got Tablist H/F Update: footer=%s",
                          header_footer_packet.footer)
        self.tab_header = json.loads(header_footer_packet.header)["text"]
        self.tab_footer = json.loads(header_footer_packet.footer)["text"]

    def handle_tab_list(self, tab_list_packet):
        self.logger.debug("Processing tab list packet")
        for action in tab_list_packet.actions:
            if isinstance(
                    action,
                    clientbound.play.PlayerListItemPacket.AddPlayerAction):
                self.logger.debug(
                    "Processing AddPlayerAction tab list packet, name: %s, uuid: %s",
                    action.name, action.uuid)
                username = action.name
                player_uuid = action.uuid
                if action.name not in self.player_list.inv:
                    self.player_list.inv[action.name] = action.uuid
                else:
                    # Sometimes we get a duplicate add packet on join idk why
                    return
                if action.name not in self.uuid_cache.inv:
                    self.uuid_cache.inv[action.name] = action.uuid
                # Initial tablist backfill
                if self.accept_join_events:
                    webhook_payload = {
                        'username':
                        username,
                        'avatar_url':
                        "https://visage.surgeplay.com/face/160/{}".format(
                            player_uuid),
                        'content':
                        '',
                        'embeds': [{
                            'color': 65280,
                            'title': '**Joined the game**'
                        }]
                    }
                    for webhook in self.webhooks:
                        self.req_future_session.post(webhook,
                                                     json=webhook_payload)
                    if self.config.es_enabled:
                        self.es_logger.log_connection(
                            uuid=action.uuid,
                            reason=ConnectionReason.CONNECTED,
                            count=len(self.player_list))
                    return
                else:
                    # The bot's name is sent last after the initial back-fill
                    if action.name == self.bot_username:
                        self.accept_join_events = True
                        if self.config.es_enabled:
                            diff = set(self.previous_player_list.keys()) - set(
                                self.player_list.keys())
                            for idx, player_uuid in enumerate(diff):
                                self.es_logger.log_connection(
                                    uuid=player_uuid,
                                    reason=ConnectionReason.DISCONNECTED,
                                    count=len(self.previous_player_list) -
                                    (idx + 1))
                        # Don't bother announcing the bot's own join message (who cares) but log it for analytics still
                        if self.config.es_enabled:
                            self.es_logger.log_connection(
                                uuid=action.uuid,
                                reason=ConnectionReason.CONNECTED,
                                count=len(self.player_list))

                if self.config.es_enabled:
                    self.es_logger.log_connection(uuid=action.uuid,
                                                  reason=ConnectionReason.SEEN)
            if isinstance(
                    action,
                    clientbound.play.PlayerListItemPacket.RemovePlayerAction):
                self.logger.debug(
                    "Processing RemovePlayerAction tab list packet, uuid: %s",
                    action.uuid)
                username = self.mc_uuid_to_username(action.uuid)
                player_uuid = action.uuid
                webhook_payload = {
                    'username':
                    username,
                    'avatar_url':
                    "https://visage.surgeplay.com/face/160/{}".format(
                        player_uuid),
                    'content':
                    '',
                    'embeds': [{
                        'color': 16711680,
                        'title': '**Left the game**'
                    }]
                }
                for webhook in self.webhooks:
                    self.req_future_session.post(webhook, json=webhook_payload)
                del self.uuid_cache[action.uuid]
                if action.uuid in self.player_list:
                    del self.player_list[action.uuid]
                if self.config.es_enabled:
                    self.es_logger.log_connection(
                        uuid=action.uuid,
                        reason=ConnectionReason.DISCONNECTED,
                        count=len(self.player_list))

    def handle_join_game(self, join_game_packet):
        self.logger.info('Connected and joined game as entity id %d',
                         join_game_packet.entity_id)
        self.player_list = bidict()
        self.connection_retries = 0

    def handle_chat(self, chat_packet):
        json_data = json.loads(chat_packet.json_data)
        if "extra" not in json_data:
            return
        chat_string = ""
        for chat_component in json_data["extra"]:
            chat_string += chat_component["text"]

        # Handle chat message
        regexp_match = re.match("<(.*?)> (.*)", chat_string, re.M | re.I)
        if regexp_match:
            username = regexp_match.group(1)
            original_message = regexp_match.group(2)
            player_uuid = self.mc_username_to_uuid(username)
            if username.lower() == self.bot_username.lower():
                # Don't relay our own messages
                if self.config.es_enabled:
                    bot_message_match = re.match(
                        "<{}> (.*?): (.*)".format(self.bot_username.lower()),
                        chat_string, re.M | re.I)
                    if bot_message_match:
                        self.es_logger.log_chat_message(
                            uuid=self.mc_username_to_uuid(
                                bot_message_match.group(1)),
                            display_name=bot_message_match.group(1),
                            message=bot_message_match.group(2),
                            message_unformatted=chat_string)
                        self.es_logger.log_raw_message(
                            msg_type=chat_packet.Position.name_from_value(
                                chat_packet.position),
                            message=chat_packet.json_data)
                return
            self.logger.info(
                "Incoming message from minecraft: Username: %s Message: %s",
                username, original_message)
            self.logger.debug("msg: %s", repr(original_message))
            message = self.escape_markdown(
                self.remove_emoji(original_message.strip().replace(
                    "@", "@\N{zero width space}")))
            webhook_payload = {
                'username':
                username,
                'avatar_url':
                "https://visage.surgeplay.com/face/160/{}".format(player_uuid),
                'content':
                '{}'.format(message)
            }
            for webhook in self.webhooks:
                self.req_future_session.post(webhook, json=webhook_payload)
            if self.config.es_enabled:
                self.es_logger.log_chat_message(
                    uuid=player_uuid,
                    display_name=username,
                    message=original_message,
                    message_unformatted=chat_string)
        if self.config.es_enabled:
            self.es_logger.log_raw_message(
                msg_type=chat_packet.Position.name_from_value(
                    chat_packet.position),
                message=chat_packet.json_data)

    def handle_health_update(self, health_update_packet):
        if health_update_packet.health <= 0:
            self.logger.debug("Respawned the player because it died")
            packet = serverbound.play.ClientStatusPacket()
            packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
            self.connection.write_packet(packet)
Пример #33
0
class Player:
    """
    A class built to handle all required actions to maintain:
     - Gaining auth tokens, and connecting to online minecraft servers.
     - Clientbound chat
     - Serverbound chat

    Warnings
    --------
    This class explicitly expects a username & password, then expects to
    be able to connect to a server in online mode.
    If you wish to add different functionality please view the example
    headless client, `start.py`, for how to implement it.
    """

    def __init__(self, username, password, *, admins=None):
        """
        Init handles the following:
         - Client Authentication
         - Setting the current connection state
         - Setting the recognized 'admins' for this instance

        Parameters
        ----------
        username : String
            Used for authentication
        password : String
            Used for authentication
        admins : list, optional
            The minecraft accounts to auto accept tpa's requests from

        Raises
        ------
        YggdrasilError
            Username or Password was incorrect

        """
        self.kickout = False
        self.admins = [] if admins is None else admins

        self.auth_token = authentication.AuthenticationToken()
        self.auth_token.authenticate(username, password)

    def Parser(self, data):
        """
        Converts the chat packet received from the server
        into human readable strings

        Parameters
        ----------
        data : JSON
            The chat data json receive from the server

        Returns
        -------
        message : String
            The text received from the server in human readable form

        """
        message = DefaultParser(data)  # This is where you would call other parsers

        if not message:
            return False

        if "teleport" in message.lower():
            self.HandleTpa(message)

        return message

    def HandleTpa(self, message):
        """
        Using the given message, figure out whether or not to accept the tpa

        Parameters
        ----------
        message : String
            The current chat, where 'tpa' was found in message.lower()

        """
        try:
            found = re.search(
                "(.+?) has requested that you teleport to them.", message
            ).group(1)
            if found in self.admins:
                self.SendChat("/tpyes")
                return
        except AttributeError:
            pass

        try:
            found = re.search("(.+?) has requested to teleport to you.", message).group(
                1
            )
            if found in self.admins:
                self.SendChat("/tpyes")
                return
        except AttributeError:
            pass

    def SendChat(self, msg):
        """
        Send a given message to the server

        Parameters
        ----------
        msg : String
            The message to send to the server

        """
        msg = str(msg)
        if len(msg) > 0:
            packet = serverbound.play.ChatPacket()
            packet.message = msg
            self.connection.write_packet(packet)

    def ReceiveChat(self, chat_packet):
        """
        The listener for ClientboundChatPackets

        Parameters
        ----------
        chat_packet : ClientboundChatPacket
            The incoming chat packet
        chat_packet.json : JSON
            The chat packet to pass of to our Parser for handling

        """
        message = self.Parser(chat_packet.json_data)
        if not message:
            # This means our Parser failed lol
            print("Parser failed")
            return

        print(message)

    def SetServer(self, ip, port=25565, handler=None):
        """
        Sets the server, ready for connection

        Parameters
        ----------
        ip : str
            The server to connect to
        port : int, optional
            The port to connect on
        handler : Function pointer, optional
            Points to the function used to handle Clientbound chat packets

        """
        handler = handler or self.ReceiveChat

        self.ip = ip
        self.port = port
        self.connection = Connection(
            ip, port, auth_token=self.auth_token, handle_exception=print
        )

        self.connection.register_packet_listener(
            handler, clientbound.play.ChatMessagePacket
        )

        self.connection.exception_handler(print)

    def Connect(self):
        """
        Actually connect to the server for this player and maintain said connection

        Notes
        -----
        This is a blocking function and will not return until `Disconnect()` is called on said instance.

        """
        self.connection.connect()

        print(f"Connected to server with: {self.auth_token.username}")

        while True:
            time.sleep(1)
            if self.kickout:
                break

    def Disconnect(self):
        """
        In order to disconnect the client, and break the blocking loop
        this method must be called

        """
        self.kickout = True
        self.connection.disconnect()
Пример #34
0
        raise ValueError("Invalid server address: '%s'." % options.server)
    options.address = match.group("host") or match.group("addr")
    options.port = int(match.group("port") or 25565)
    return options

def useitem():
    global connection
    global packet
    connection.write_packet(packet)



options = get_options()
if options.offline:
    print("Connecting in offline mode...")
    connection = Connection(
        options.address, options.port, username=options.username)
else:
    auth_token = authentication.AuthenticationToken()
    try:
        auth_token.authenticate(options.username, options.password)
    except YggdrasilError as e:
        print(e)
        sys.exit()
    print("Logged in as %s..." % auth_token.username)
    connection = Connection(
        options.address, options.port, auth_token=auth_token)

packet = minecraft.networking.packets.serverbound.play.UseItemPacket()
packet.hand = 0

if options.dump_packets:
Пример #35
0
def main():

    auth_token = authentication.AuthenticationToken()
    try:
        with open('minecraft.auth', 'r') as f:
            auth_token.client_token, auth_token.access_token = f.read().splitlines()

        # Library has issues need to do some hackey stuff to make sure it works.
        # I would use validate, but that would require some rewriting as well.
        auth_token.username = "******"
        auth_token.refresh()
    except (IOError, YggdrasilError):
        # IF there is no authentication file authenticate using username and password
        try:
            options = get_options()
            auth_token.authenticate(options["username"], options["password"])
        except YggdrasilError as e:
            print(e)
            sys.exit()

    with open('minecraft.auth', 'w') as fout:
        fout.write(auth_token.client_token + '\n')
        fout.write(auth_token.access_token)

    print("Logged in as %s..." % auth_token.username)
    connection = Connection(
        "localhost", 25565, auth_token=auth_token)

    def handle_join_game(join_game_packet):
        print('Connected.')

    connection.register_packet_listener(
        handle_join_game, clientbound.play.JoinGamePacket)

    def print_chat(chat_packet):
        print("Message (%s): %s" % (
            chat_packet.field_string('position'), chat_packet.json_data))

    connection.register_packet_listener(
        print_chat, clientbound.play.ChatMessagePacket)

    global connected
    connected = True

    def disconnect(disconnect_packet):
        print("You were disconnected: %s" % disconnect_packet.json_data)
        global connected
        connected = False

    connection.register_packet_listener(disconnect, 
            clientbound.play.DisconnectPacket)
    connection.connect()

    while connected:
        try:
            text = input()
            if text == "/respawn":
                print("respawning...")
                packet = serverbound.play.ClientStatusPacket()
                packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
                connection.write_packet(packet)
            else:
                packet = serverbound.play.ChatPacket()
                packet.message = text
                connection.write_packet(packet)
        except KeyboardInterrupt:
            print("Bye!")
            sys.exit()