Exemple #1
0
def test_get_user():
    client = MatrixClient("http://example.com")

    assert isinstance(client.get_user("@foobar:matrix.org"), User)

    with pytest.raises(ValueError):
        client.get_user("badfoobar:matrix.org")
        client.get_user("@badfoobarmatrix.org")
        client.get_user("@badfoobar:::matrix.org")
def test_get_user():
    client = MatrixClient("http://example.com")

    assert isinstance(client.get_user("@foobar:matrix.org"), User)

    with pytest.raises(ValueError):
        client.get_user("badfoobar:matrix.org")
        client.get_user("@badfoobarmatrix.org")
        client.get_user("@badfoobar:::matrix.org")
Exemple #3
0
    def __init__(self, server, username, password, rooms, nick=None):
        client = MatrixClient(server)
        self.viewer_url = server.strip('/') + "/_matrix/media/v1/download/"

        try:
            client.login_with_password(username, password)
        except MatrixRequestError as e:
            if e.code == 403:
                logger.error("403 Bad username or password.")
                sys.exit(4)
            else:
                logger.error("{} Check your server details are correct.".format(e))
                sys.exit(2)
        except MissingSchema as e:
            logger.error("{} Bad URL format.".format(e))
            sys.exit(3)

        self.username = client.user_id
        logger.info("logged in as: {}".format(self.username))

        if nick is not None:
            u = client.get_user(client.user_id)
            logger.info("Setting display name to {}".format(nick))
            try:
                u.set_display_name(nick)
            except MatrixRequestError as e:
                logger.error("Fail to set display name: error = {}".format(e))

        self.joined_rooms = {}
        self.room_id_to_alias = {}
        self.displaynames = {}

        for room_id_alias in rooms:
            try:
                room = client.join_room(room_id_alias)
            except MatrixRequestError as e:
                if e.code == 400:
                    logger.error("400 Room ID/Alias in the wrong format")
                    sys.exit(11)
                else:
                    logger.error("{} Couldn't find room {}".format(e, room_id_alias))
                    sys.exit(12)
            logger.info("Joined room {}".format(room_id_alias))
            self.joined_rooms[room_id_alias] = room
            self.room_id_to_alias[room.room_id] = room_id_alias
            room.add_listener(self.on_message)

        self.client = client
        self.bot_msg_pattern = config['matrix'].get('bot_msg_pattern', None)
except MatrixRequestError as e:
    print(e)
    if e.code == 403:
        print("Bad username or password.")
        sys.exit(4)
    else:
        print("Check your sever details are correct.")
        sys.exit(2)
except MissingSchema as e:
    print("Bad URL format.")
    print(e)
    sys.exit(3)

if len(sys.argv) > 4:
    userid = sys.argv[4]
else:
    userid = samples_common.get_input("UserID: ")

try:
    user = client.get_user(userid)
    print("Display Name: %s" % user.get_display_name())
    print("Avatar %s" % user.get_avatar_url())
except MatrixRequestError as e:
    print(e)
    if e.code == 400:
        print("User ID/Alias in the wrong format")
        sys.exit(11)
    else:
        print("Couldn't find room.")
        sys.exit(12)
Exemple #5
0
class JokeBot:
    bot_startcmd = '!joke'
    bot_display_name = 'JokeBot'
    auto_join_invited_rooms = True
    mcl = None
    init_done = False
    admin_ids = set()

    def __init__(self, filename=CONFIG_FILENAME):
        logging.debug('load config')
        config_dic = load_yaml_config(filename)
        matrix_server = config_dic['matrix_server']
        login_with_token = False
        if matrix_server.get('token', ''):
            if not matrix_server.get('user_id', ''):
                matrix_server['user_id'] = config_dic['matrix_user'][
                    'username']
            login_with_token = True
        else:
            matrix_user = config_dic['matrix_user']

        bot_startcmd = config_dic.get('bot_startcmd')
        if bot_startcmd:
            self.bot_startcmd = bot_startcmd
        bot_display_name = config_dic.get('bot_display_name')
        if bot_display_name:
            self.bot_display_name = bot_display_name
        self.auto_join_invited_rooms = config_dic.get(
            'auto_join_invited_rooms', True)
        self.admin_ids = set(config_dic.get('admin_ids', []))

        logging.debug('init bot')

        if login_with_token:
            logging.debug('init bot with token')
            self.mcl = MatrixClient(**matrix_server)
        else:
            logging.debug('init bot with password')
            self.mcl = MatrixClient(**matrix_server)
            self.mcl.login_with_password_no_sync(**matrix_user)

        m_user = self.mcl.get_user(self.mcl.user_id)
        if m_user.get_display_name() != self.bot_display_name:
            m_user.set_display_name(self.bot_display_name)

        self.mcl.add_invite_listener(self.process_invite)
        self.mcl.add_listener(self.process_message, 'm.room.message')

        self.init_done = True
        logging.info('bot initialization successful')

    def run(self):
        if self.init_done:
            logging.debug('run listen_forever')
            self.mcl.listen_forever()
        else:
            logging.warning('bot not initialized successful')

    def join_room(self, room_id):
        self.ignore_room_temporary(
            room_id
        )  # necessary while joining room because otherwise old messages would be processed
        try:
            logging.info('joining new room {}'.format(room_id))
            room = self.mcl.join_room(room_id)
            room.send_text(
                "Welcome! I'm a joke bot. Type '{}' and I will tell you a joke."
                .format(self.bot_startcmd))
            return True
        except:
            logging.exception(
                'Exception while joining room {}'.format(room_id))
            return False

    temp_ignored_rooms = set()

    def temp_ignore_room_thread(self, room_id):
        logging.debug('temporary ignoring room {}'.format(room_id))
        self.temp_ignored_rooms.add(room_id)
        time.sleep(10)
        self.temp_ignored_rooms.remove(room_id)
        logging.debug('not ignoring room {} any more'.format(room_id))

    def ignore_room_temporary(self, room_id):
        threading.Thread(target=self.temp_ignore_room_thread,
                         args=[room_id],
                         daemon=True).start()

    def leave_room(self, room_id):
        logging.debug('trying to leave room with id {}'.format(room_id))
        leave_room = self.mcl.get_rooms().get(room_id, '')
        if not leave_room:
            logging.debug('bot not in room with id {}'.format(room_id))
            return False
        if leave_room.leave():
            logging.debug('leaving room {} was successful'.format(room_id))
            return True
        else:
            logging.debug('failed to leave known room with id {}'.format(
                leave_room.room_id))
        return False

    def process_invite(self, room_id, state=None):
        logging.debug('received invitation of {}'.format(room_id))
        if self.auto_join_invited_rooms:
            self.join_room(room_id)

    def evaluate_bot_message(self, room, sender, msg):
        if msg.startswith('ctl'):
            logging.debug("received control message '{}' in room '{}'".format(
                msg, room.room_id))
            if sender not in self.admin_ids:
                logging.debug(
                    '{} has no permissions to send a ctl-message'.format(
                        sender))
                room.send_notice(
                    '{} has no permissions to send a ctl-message'.format(
                        sender))
                return
            data = msg.split(' ')[1:]
            if len(data) == 2:
                if data[0] == 'join':
                    if not self.join_room(data[1]):
                        room.send_notice(
                            'something went wrong while joining room')
                elif data[0] == 'leave':
                    if data[1] == 'this':
                        data[1] = room.room_id
                    if not self.leave_room(data[1]):
                        room.send_notice('room could not be left')
            return

        logging.info('sending joke to room {}'.format(room.room_id))
        answer = '...'
        data = msg.split(' ')[1:]  # remove first empty string
        if len(data) == 0:
            answer = get_joke()
        elif len(data) == 1:
            answer = get_joke(data[0])
        elif len(data) == 2:
            answer = get_joke(data[0], data[1])
        logging.debug('starting room send text')
        room.send_text(answer)
        logging.debug('done room send text')

    def process_message(self, roomchunk):
        if roomchunk['sender'] == self.mcl.user_id:
            return

        if roomchunk['room_id'] in self.temp_ignored_rooms:
            logging.debug('ignoring room {} temporary'.format(
                roomchunk['room_id']))
            return

        content = roomchunk['content']
        if content['msgtype'] == 'm.text':
            msg = content['body']
            if msg.startswith(self.bot_startcmd):
                room = self.mcl.get_rooms()[roomchunk['room_id']]
                msg = msg[len(self.bot_startcmd):]
                self.evaluate_bot_message(room, roomchunk['sender'], msg)
Exemple #6
0
class TinyMatrixtBot():
    def __init__(self, hostname, username, password, displayname):
        signal.signal(signal.SIGTERM, self.on_signal)
        signal.signal(signal.SIGHUP, self.on_signal)

        self.current_path = os.path.dirname(os.path.realpath(__file__))
        self.scripts_path = os.path.join(self.current_path, "scripts")
        self.sockets_path = os.path.join(self.current_path, "sockets")

        if not os.access(self.sockets_path, os.W_OK):
            self.sockets_path = None

        os.chdir(self.scripts_path)
        self.scripts = self.load_scripts(self.scripts_path)

        self.client = MatrixClient(hostname)
        self.client.login_with_password(username=username, password=password)

        self.user = self.client.get_user(self.client.user_id)
        self.user.set_display_name(displayname)

        for room_id in self.client.get_rooms():
            self.join_room(room_id)

        self.client.start_listener_thread()
        self.client.add_invite_listener(self.on_invite)
        self.client.add_leave_listener(self.on_leave)

        while True:
            sleep(10)

    def on_signal(self, signal, frame):
        if signal == 1:
            self.scripts = self.load_scripts(self.scripts_path)
        if signal == 15:
            sys.exit()

    def load_scripts(self, path):
        scripts = {}
        for script in os.listdir(path):
            script = os.path.join(path, script)
            if not stat.S_IXUSR & os.stat(script)[stat.ST_MODE]:
                continue
            output = subprocess.Popen(
                [script],
                env={
                    "CONFIG": "1"
                },
                stdout=subprocess.PIPE,
                universal_newlines=True).communicate()[0].strip()
            if not output:
                continue
            scripts[output] = script
            print("script {} {}".format(output, script))
        return scripts

    def on_invite(self, room_id, state):
        print("invite {}".format(room_id))
        self.join_room(room_id)

    def join_room(self, room_id):
        room = self.client.join_room(room_id)
        room.add_listener(self.on_room_event)
        print("join {}".format(room_id))
        if self.sockets_path is not None:
            thread = Thread(target=self.create_socket, args=(room, ))
            thread.daemon = True
            thread.start()

    def create_socket(self, room):
        socket_name = re.search("^\!([a-z]+):", room.room_id,
                                re.IGNORECASE).group(1)
        socket_path = os.path.join(self.sockets_path, socket_name)
        try:
            os.remove(socket_path)
        except OSError:
            pass
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.bind(socket_path)
        sock.listen(1)
        print("bind {}".format(socket_path))
        while True:
            conn, addr = sock.accept()
            recv = conn.recv(4096).decode('utf-8').strip()
            print("recv {} {}".format(socket_path, recv))
            room.send_text(recv)

    def on_leave(self, room_id, state):
        print("leave {}".format(room_id))

    def on_room_event(self, room, event):
        if event["sender"] == self.client.user_id:
            return
        if event["type"] == "m.room.message":
            if event["content"]["msgtype"] == "m.text":
                body = event["content"]["body"].strip()
                for regex, script in self.scripts.items():
                    if re.search(regex, body, re.IGNORECASE):
                        self.run_script(room, script, body)

    def run_script(self, room, script, args):
        print("run {} {}".format(script, args))
        output = subprocess.Popen(
            [script, args], stdout=subprocess.PIPE,
            universal_newlines=True).communicate()[0].strip()
        for line in output.split("\n\n"):
            sleep(1)
            print(line)
            room.send_text(line)
Exemple #7
0
class MpyBot:
	def __init__(self, configfile, run=True):
		logger.debug('load config')
		config_dic = load_yaml_config(configfile)
		self.bot_startcmd = config_dic.get('bot_startcmd', STARTCMD)

		self._full_cmds = {}
		self._local_cmds = {}
		self._module_calls = {}
		for moduledic in config_dic.get('modules', []):
			self.add_module(moduledic)

		matrix_server = config_dic['matrix_server']

		logger.debug('init bot')
		self.mcl = MatrixClient(**matrix_server)

		self.auto_join_invited_rooms = config_dic.get('auto_join_invited_rooms', True)
		self.auto_join_servers = set(config_dic.get('auto_join_servers', []))

		self.admin_ids = set(config_dic.get('admin_ids', []))

		disp_name = config_dic.get('bot_display_name', '')
		if disp_name:
			user = self.mcl.get_user(self.mcl.user_id)
			if user.get_display_name() != disp_name:
				user.set_display_name(disp_name)

		self.mcl.add_invite_listener(self._process_invite)
		self.mcl.add_listener(self._process_message, 'm.room.message')

		logger.info('bot initialized')

		if run:
			self._run()

	def _run(self):
		logger.debug('run listen_forever')
		self.mcl.listen_forever()


	def join_room(self, room_id):
		try:
			logger.info('joining new room {}'.format(room_id))
			room = self.mcl.join_room(room_id)
			room.send_text("Welcome! Type {} to control me.".format(self.bot_startcmd))
			return True
		except MatrixError as e:
			logger.exception('{} while joining room {}'.format(repr(e), room_id))
			return False

	def leave_room(self, room_id):
		logger.info('trying to leave room with id {}'.format(room_id))
		leave_room = self.mcl.get_rooms().get(room_id, '')
		if not leave_room:
			logger.debug('bot not in room {}'.format(room_id))
			return False
		if leave_room.leave():
			logger.debug('left room {}'.format(room_id))
			return True
		else:
			logger.debug('failed to leave known room with id {}'.format(leave_room.room_id))
		return False


	def _process_invite(self, room_id, state=None):
		logger.debug('received invitation to {}, state: {}'.format(room_id, state))
		if self.auto_join_invited_rooms:
			if self.auto_join_servers and \
					room_id.split(':')[-1] not in self.auto_join_servers:
				return
			self.join_room(room_id)

	def _process_message(self, roomchunk):
		if roomchunk['sender'] == self.mcl.user_id:
			return

		age = roomchunk.get('unsigned', {}).get('age')
		if age is None:
			# fallback
			age = abs(time.time() - roomchunk['origin_server_ts']/1000)
		else:
			age /= 1000

		if age > 60:
			logger.debug('received old message in {}, event_id: {}'.format(roomchunk['room_id'], roomchunk['event_id']))
			return

		content = roomchunk['content']
		if content['msgtype'] == 'm.text':
			msg = content['body'].lstrip()
			if msg.startswith(self.bot_startcmd):
				room = self.mcl.get_rooms()[roomchunk['room_id']]
				msg = msg[len(self.bot_startcmd):].lstrip()
				self._evaluate_bot_message(room, roomchunk['sender'], msg)
			else:
				s_msg = msg.split(' ', 1)
				cmd = s_msg[0]
				msg = s_msg[1] if len(s_msg) > 1 else ''
				modulename = self._full_cmds.get(cmd)
				if modulename:
					room = self.mcl.get_rooms()[roomchunk['room_id']]
					self._call_module(modulename, room, roomchunk['sender'], msg)

	def _evaluate_bot_message(self, room, sender, msg):
		if msg.startswith('ctl'):
			logger.debug("received control message '{}' in room '{}'".format(msg, room.room_id))
			if sender not in self.admin_ids:
				logger.debug('{} has no permissions to send a ctl-message'.format(sender))
				room.send_notice('{} has no permissions to send a ctl-message'.format(sender))
				return
			data = msg.split()[1:]
			if len(data) == 2:
				if data[0] == 'join':
					if not self.join_room(data[1]):
						room.send_notice('something went wrong while joining room')
				elif data[0] == 'leave':
					if data[1] == 'this':
						data[1] = room.room_id
					if not self.leave_room(data[1]):
						room.send_notice('room could not be left')
			return

		elif msg.startswith('-'):
			msg = msg[1:].strip()
			if msg.startswith('help'):
				text = 'Available local commands:\n'
				for k in self._local_cmds:
					text += ' - ' + k + '\n'
				text += 'Available full commands:\n'
				for k in self._full_cmds:
					text += ' - ' + k + '\n'
				room.send_text(text)
			elif msg.startswith('time'):
				room.send_text('UTC: {:.0f}'.format(time.time()))

		s_msg = msg.split(' ', 1)
		cmd = s_msg[0]
		msg = s_msg[1] if len(s_msg) > 1 else ''

		modulename = self._local_cmds.get(cmd)
		if modulename:
			self._call_module(modulename, room, sender, msg)


	def add_module(self, moduledic):
		try:
			name = moduledic['name']
			module = importlib.import_module('modules.' + name)
			opt = moduledic.get('options')
			logging.debug('here')
			if opt:
				module.set_options(opt)

			self._module_calls[name] = module.msg_call

			cmd = moduledic.get('local_cmd')
			if cmd:
				self._local_cmds[cmd] = name
			cmd = moduledic.get('full_cmd')
			if cmd:
				self._full_cmds[cmd] = name

			logger.info('module {} added'.format(moduledic))
		except Exception as e:
			logger.exception('not possible to add module {}: {}'.format(moduledic, repr(e)))

	def _call_module(self, modulename, room, sender, msg):
		logger.debug("modulecall {} for message '{}' in room {}".format(modulename, msg, room.room_id))
		try:
			res = self._module_calls[modulename](room=room, sender=sender, msg=msg)
			if res and isinstance(res, str):
				room.send_text(res)
		except Exception as e:
			logger.exception('Failed to call module {}'.format(modulename))
Exemple #8
0
class TinyMatrixtBot():
    def __init__(self, path_config):
        signal.signal(signal.SIGHUP, self.on_signal)
        signal.signal(signal.SIGINT, self.on_signal)
        signal.signal(signal.SIGTERM, self.on_signal)

        self.config = configparser.ConfigParser()
        self.config.read(path_config)

        path_current = os.path.dirname(os.path.realpath(__file__))

        self.path_lib = self.config.get("tiny-matrix-bot",
                                        "lib",
                                        fallback=os.path.join(
                                            path_current, "scripts")).strip()
        print("SCRIPTS {}".format(self.path_lib))
        if os.access(self.path_lib, os.R_OK):
            self.scripts = self.load_scripts(self.path_lib)
        else:
            print("ERROR {} is not readable".format(self.path_lib))
            sys.exit(0)

        self.path_var = self.config.get("tiny-matrix-bot",
                                        "var",
                                        fallback=os.path.join(
                                            path_current, "data")).strip()
        print("DATA {}".format(self.path_var))
        if os.access(self.path_var, os.W_OK):
            os.chdir(self.path_var)
        else:
            print("ERROR {} is not writeable".format(self.path_var))
            sys.exit(0)

        self.path_run = self.config.get("tiny-matrix-bot",
                                        "run",
                                        fallback=os.path.join(
                                            path_current, "sockets")).strip()
        if os.access(self.path_run, os.W_OK):
            print("SOCKETS {}".format(self.path_run))
        else:
            print("SOCKETS {} (not writeable, disabling sockets)".format(
                self.path_run))
            self.path_run = False

        self.client = MatrixClient(self.config.get("tiny-matrix-bot", "host"))
        self.client.login_with_password(
            username=self.config.get("tiny-matrix-bot", "user"),
            password=self.config.get("tiny-matrix-bot", "pass"))

        self.user = self.client.get_user(self.client.user_id)
        self.user.set_display_name(self.config.get("tiny-matrix-bot", "name"))

        for room_id in self.client.get_rooms():
            self.join_room(room_id)

        self.client.start_listener_thread()
        self.client.add_invite_listener(self.on_invite)
        self.client.add_leave_listener(self.on_leave)

        while True:
            sleep(1)

    def on_signal(self, signal, frame):
        if signal == 1:
            self.scripts = self.load_scripts(self.path_lib)
        elif signal in [2, 15]:
            sys.exit(0)

    def load_scripts(self, path):
        scripts = {}
        for script in os.listdir(path):
            script_path = os.path.join(path, script)
            if not os.access(script_path, os.R_OK) \
                or not os.access(script_path, os.X_OK):
                continue
            output = subprocess.Popen(
                [script_path],
                env={
                    "CONFIG": "1"
                },
                stdout=subprocess.PIPE,
                universal_newlines=True).communicate()[0].strip()
            if not output:
                continue
            scripts[output] = script_path
            print("LOAD {} {}".format(script, output))
        return scripts

    def on_invite(self, room_id, state):
        print("INVITE {}".format(room_id))
        self.join_room(room_id)

    def join_room(self, room_id):
        room = self.client.join_room(room_id)
        room.add_listener(self.on_room_event)
        print("JOIN {}".format(room_id))
        if self.path_run is not False:
            thread = Thread(target=self.create_socket, args=(room, ))
            thread.daemon = True
            thread.start()

    def create_socket(self, room):
        socket_name = re.search("^\!([a-z]+):", room.room_id,
                                re.IGNORECASE).group(1)
        socket_path = os.path.join(self.path_run, socket_name)
        try:
            os.remove(socket_path)
        except OSError:
            pass
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.bind(socket_path)
        sock.listen(1)
        print("SOCKET {}".format(socket_path))
        while True:
            conn, addr = sock.accept()
            recv = conn.recv(4096).decode('utf-8').strip()
            print("RECV {} {}".format(socket_path, recv))
            room.send_text(recv)

    def on_leave(self, room_id, state):
        print("LEAVE {}".format(room_id))

    def on_room_event(self, room, event):
        if event["sender"] == self.client.user_id:
            return
        if event["type"] == "m.room.message":
            if event["content"]["msgtype"] == "m.text":
                body = event["content"]["body"].strip()
                for regex, script in self.scripts.items():
                    if re.search(regex, body, re.IGNORECASE):
                        self.run_script(room, event, [script, body])

    def run_script(self, room, event, args):
        print("ROOM {}".format(event["room_id"]))
        print("SENDER {}".format(event["sender"]))
        print("RUN {}".format(args))
        output = subprocess.Popen(
            args,
            env={
                "MXROOMID": event["room_id"],
                "MXSENDER": event["sender"]
            },
            stdout=subprocess.PIPE,
            universal_newlines=True).communicate()[0].strip()
        sleep(0.5)
        for p in output.split("\n\n"):
            for l in p.split("\n"):
                print("OUTPUT {}".format(l))
            room.send_text(p)
            sleep(1)
Exemple #9
0
class MatrigramClient(object):
    def __init__(self, server, tb, username):
        self.client = MatrixClient(server)
        self.tb = tb
        self.token = None
        self.server = server
        self.username = username
        self.focus_room_id = None
        self.msg_type_router = {
            'm.image': self.forward_image_to_tb,
            'm.audio': self.forward_voice_to_tb,
            'm.video': self.forward_video_to_tb,
            'm.emote': self.forward_emote_to_tb,
        }
        self.room_listener_uid = None
        self.ephemeral_listener_uid = None

    def login(self, username, password):
        try:
            self.token = self.client.login_with_password(username, password)
            logger.info('token = %s', self.token)
            rooms = self.get_rooms_aliases()
            if rooms:
                # set focus room to "first" room
                self.set_focus_room(rooms.keys()[0])

            self.client.add_invite_listener(self.on_invite_event)
            self.client.add_leave_listener(self.on_leave_event)
            self.client.start_listener_thread()
            return True, "OK"
        except MatrixRequestError:
            return False, "Failed to login"
        except ConnectionError:
            return False, "Server is offline"

    def logout(self):
        self.client.logout()

    def on_event(self, _, event):
        logger.debug('entered with message %s', pprint_json(event))
        sender = event['sender'].split(':')[0].encode('utf-8')

        # Prevent messages loopback
        if sender.startswith(u'@{}'.format(self.username)):
            return

        if event['type'] == "m.room.message":
            msgtype = event['content']['msgtype']

            if msgtype != 'm.text':
                callback = self.msg_type_router.get(msgtype)
                if callback:
                    callback(event)
                return

            content = event['content']['body'].encode('utf-8')
            self.tb.send_message(sender, content, self)

        elif event['type'] == "m.room.topic":
            topic = event['content']['topic'].encode('utf-8')
            self.tb.send_topic(sender, topic, self)

    def on_ephemeral_event(self, _, ee):
        logger.debug(pprint_json(ee))

        if ee['type'] == 'm.typing':
            if ee['content']['user_ids']:
                self.tb.start_typing_thread(self)
            else:
                self.tb.stop_typing_thread(self)

    def on_leave_event(self, room_id, le):
        logger.debug(pprint_json(le))

        if le['timeline']['events'][0]['sender'] != le['timeline']['events'][
                0]['state_key']:
            self.tb.send_kick(self._room_id_to_alias(room_id), self)

    def on_invite_event(self, _, ie):
        logger.debug('invite event %s', pprint_json(ie))
        room_name = None
        for event in ie['events']:
            if event['type'] == 'm.room.name':
                room_name = event['content']['name']

        if room_name:
            self.tb.send_invite(self, self._room_id_to_alias(room_name))

    def join_room(self, room_id_or_alias):
        try:
            self.client.join_room(room_id_or_alias)
            self.set_focus_room(room_id_or_alias)
            return True
        except MatrixRequestError:
            return False

    def leave_room(self, room_id_or_alias):
        room = self.get_room_obj(room_id_or_alias)
        if not room:
            logger.error('cant find room')
            return False

        if self.focus_room_id == room.room_id:
            rooms = self.get_rooms_aliases()
            room_id = self._room_alias_to_id(room_id_or_alias)

            del rooms[room_id]
            new_focus_room = rooms.keys()[0] if rooms else None
            self.set_focus_room(new_focus_room)

        return room.leave()

    def set_focus_room(self, room_id_or_alias):
        if self._room_alias_to_id(room_id_or_alias) == self.focus_room_id:
            return

        # remove current focus room listeners
        if self.focus_room_id is not None:
            room_obj = self.get_room_obj(self.focus_room_id)
            room_obj.remove_listener(self.room_listener_uid)
            self.room_listener_uid = None
            room_obj.remove_ephemeral_listener(self.ephemeral_listener_uid)
            self.ephemeral_listener_uid = None
            logger.info("remove focus room %s", self.focus_room_id)
            self.focus_room_id = None

        # set new room on focus
        if room_id_or_alias is not None:
            self.focus_room_id = self._room_alias_to_id(room_id_or_alias)
            room_obj = self.get_room_obj(self.focus_room_id)
            self.room_listener_uid = room_obj.add_listener(self.on_event)
            self.ephemeral_listener_uid = room_obj.add_ephemeral_listener(
                self.on_ephemeral_event)
            logger.info("set focus room to %s", self.focus_room_id)

    def get_focus_room_alias(self):
        return self._room_id_to_alias(self.focus_room_id)

    def have_focus_room(self):
        return self.focus_room_id is not None

    def get_members(self):
        room_obj = self.get_room_obj(self.focus_room_id)
        rtn = room_obj.get_joined_members()

        return [
            member['displayname'] for _, member in rtn.items()
            if member.get('displayname')
        ]

    def set_name(self, name):
        user = self.client.get_user(self.client.user_id)
        user.set_display_name(name)

    def emote(self, body):
        room_obj = self.get_room_obj(self.focus_room_id)
        room_obj.send_emote(body)

    def create_room(self, alias, is_public=False, invitees=()):
        try:
            room_obj = self.client.create_room(alias, is_public, invitees)
            room_obj.update_aliases()
            logger.debug('room_id %s', room_obj.room_id)
            logger.debug('room_alias %s', room_obj.aliases[0])
            return (room_obj.room_id, room_obj.aliases[0])
        except MatrixRequestError:
            logger.error('error creating room')
            return None, None

    def backfill_previous_messages(self, limit=10):
        room_obj = self.get_room_obj(self.focus_room_id)
        room_obj.backfill_previous_messages(limit=limit)

    def get_rooms_aliases(self):
        # returns a dict with id: room obj
        rooms = self._get_rooms_updated()
        if not rooms:
            return rooms

        logger.debug("rooms got from server are %s", rooms)

        # return dict with id: list of aliases or id (if no alias exists)
        return {
            key: val.aliases if val.aliases else [key]
            for (key, val) in rooms.items()
        }

    def get_room_obj(self, room_id_or_alias):
        """Get room object of specific id or alias.

        Args:
            room_id_or_alias (str): Room's id or alias.

        Returns (Room): Room object corresponding to room_id_or_alias.

        """
        rooms = self._get_rooms_updated()
        room_id = self._room_alias_to_id(room_id_or_alias)

        return rooms.get(room_id)

    def send_message(self, msg):
        room_obj = self.get_room_obj(self.focus_room_id)

        if not room_obj:
            logger.error('cant find room')
        else:
            room_obj.send_text(msg)

    def send_photo(self, path):
        with open(path, 'rb') as f:
            mxcurl = self.client.upload(f.read(),
                                        mimetypes.guess_type(path)[0])

            room_obj = self.get_room_obj(self.focus_room_id)

            if not room_obj:
                logger.error('cant find room')
            else:
                room_obj.send_image(mxcurl, os.path.split(path)[1])

    def send_voice(self, path):
        with open(path, 'rb') as f:
            mxcurl = self.client.upload(f.read(),
                                        mimetypes.guess_type(path)[0])
            room_obj = self.get_room_obj(self.focus_room_id)
            room_obj.send_audio(mxcurl, os.path.split(path)[1])

    def send_video(self, path):
        with open(path, 'rb') as f:
            mxcurl = self.client.upload(f.read(),
                                        mimetypes.guess_type(path)[0])
            room_obj = self.get_room_obj(self.focus_room_id)
            room_obj.send_video(mxcurl, os.path.split(path)[1])

    def discover_rooms(self):
        res = requests.get('{}/_matrix/client/r0/publicRooms?limit=20'.format(
            self.server))
        res_json = res.json()

        room_objs = res_json['chunk']
        return [
            room['aliases'][0] for room in room_objs if room.get('aliases')
        ]

    def download_from_event(self, event):
        mxcurl = event['content']['url']
        link = self.client.api.get_download_url(mxcurl)
        media_id = mxcurl.split('/')[3]
        media_type = event['content']['info']['mimetype'].split('/')[1]
        path = os.path.join(self.tb.config['media_dir'],
                            '{}.{}'.format(media_id, media_type))
        download_file(link, path)

        return path

    def forward_image_to_tb(self, event):
        sender = event['sender'].split(':')[0].encode('utf-8')
        path = self.download_from_event(event)
        self.tb.send_photo(sender, path, self)

    def forward_voice_to_tb(self, event):
        sender = event['sender'].split(':')[0].encode('utf-8')
        path = self.download_from_event(event)
        self.tb.send_voice(sender, path, self)

    def forward_video_to_tb(self, event):
        sender = event['sender'].split(':')[0].encode('utf-8')
        path = self.download_from_event(event)
        self.tb.send_video(sender, path, self)

    def forward_emote_to_tb(self, event):
        sender = event['sender'].split(':')[0].encode('utf-8')
        content = event['content']['body'].encode('utf-8')
        self.tb.send_emote(sender, content, self)

    def _room_id_to_alias(self, id):
        """Convert room id to alias.

        Args:
            id (str): Room id.

        Returns (str): Room alias.

        """
        if id is None:
            return None
        if id.startswith('#'):
            return id
        rooms = self.get_rooms_aliases()
        if id in rooms:
            return rooms[id][0]
        else:
            return None

    def _room_alias_to_id(self, alias):
        """Convert room alias to id.

        Args:
            alias (str): Room alias.

        Returns (str): Room id.

        """
        if alias is None:
            return None

        if not alias.startswith('#'):
            return alias

        return self.client.api.get_room_id(alias)

    def _get_rooms_updated(self):
        """Return rooms dictionary with updated aliases.

        Returns (dict): Return rooms dictionary with updated aliases.

        """
        rooms = self.client.get_rooms()
        for room in rooms.values():
            room.update_aliases()

        return rooms
except MatrixRequestError as e:
    print(e)
    if e.code == 403:
        print("Bad username or password.")
        sys.exit(4)
    else:
        print("Check your server details are correct.")
        sys.exit(2)
except MissingSchema as e:
    print("Bad URL format.")
    print(e)
    sys.exit(3)

if len(sys.argv) > 4:
    userid = sys.argv[4]
else:
    userid = samples_common.get_input("UserID: ")

try:
    user = client.get_user(userid)
    print("Display Name: %s" % user.get_display_name())
    print("Avatar %s" % user.get_avatar_url())
except MatrixRequestError as e:
    print(e)
    if e.code == 400:
        print("User ID/Alias in the wrong format")
        sys.exit(11)
    else:
        print("Couldn't find room.")
        sys.exit(12)
Exemple #11
0
try:
    client.login(username, password)
except MatrixRequestError as e:
    print(e)
    if e.code == 403:
        print("Bad username or password.")
        sys.exit(4)
    else:
        print("Check your server details are correct.")
        sys.exit(2)
except MissingSchema as e:
    print("Bad URL format.")
    print(e)
    sys.exit(3)

user = client.get_user(client.user_id)

if len(sys.argv) < 5:
    print("Current Display Name: %s" % user.get_display_name())

    displayname = input("New Display Name: ")
else:
    displayname = sys.argv[4]

try:
    user.set_display_name(displayname)
except MatrixRequestError as e:
    print(e)
    sys.exit(11)
try:
    client.login_with_password(username, password)
except MatrixRequestError as e:
    print(e)
    if e.code == 403:
        print("Bad username or password.")
        sys.exit(4)
    else:
        print("Check your sever details are correct.")
        sys.exit(3)
except MissingSchema as e:
    print("Bad URL format.")
    print(e)
    sys.exit(2)

user = client.get_user(client.user_id)

if len(sys.argv) < 5:
    print("Current Display Name: %s" % user.get_display_name())

    displayname = input("New Display Name: ")
else:
    displayname = sys.argv[4]

try:
    user.set_display_name(displayname)
except MatrixRequestError as e:
    print(e)
    sys.exit(11)