def test_presence_listener(): client = MatrixClient("http://example.com") accumulator = [] def dummy_callback(event): accumulator.append(event) presence_events = [ { "content": { "avatar_url": "mxc://*****:*****@example:localhost" }, "event_id": "$WLGTSEFSEF:localhost", "type": "m.presence" }, { "content": { "avatar_url": "mxc://*****:*****@example2:localhost" }, "event_id": "$CIGTXEFREF:localhost", "type": "m.presence" }, { "content": { "avatar_url": "mxc://*****:*****@example3:localhost" }, "event_id": "$ZEGASEDSEF:localhost", "type": "m.presence" }, ] sync_response = deepcopy(response_examples.example_sync) sync_response["presence"]["events"] = presence_events response_body = json.dumps(sync_response) sync_url = HOSTNAME + MATRIX_V2_API_PATH + "/sync" responses.add(responses.GET, sync_url, body=response_body) callback_uid = client.add_presence_listener(dummy_callback) client._sync() assert accumulator == presence_events responses.add(responses.GET, sync_url, body=response_body) client.remove_presence_listener(callback_uid) accumulator = [] client._sync() assert accumulator == []
class MatrixBackend(ErrBot): def __init__(self, config): super().__init__(config) identity = config.BOT_IDENTITY self.token = identity["token"] self.url = identity["url"] self.user = identity["user"] self._client = None def build_identifier(self, text_representation: str) -> None: """Return an object that idenfifies a matrix person or room.""" pass @staticmethod def parse_identfier_pieces(regex: str, text_rep: str): m = re.match(regex, text_rep) if m: data, domain = m.group() return data, domain return None, None @staticmethod def parse_identfier(text_rep): """Parse matrix identifiers into usable types. Expected formats are as follows: !<room>:<domain> #<room>:<domain> @<user>:<domain> """ room, domain, user = None, None, None room, domain = MatrixBackend.parse_identfier_pieces( r"[!#](.*):(.*)", text_rep) if not room or not domain: user, domain = MatrixBackend.parse_identfier_pieces( r"@:(.*):(.*)", text_rep) return room, domain, user def send_msg(self, room_id, msg): room = self._client.join_room(room_id) return room.send_text(msg) def send_file(self, room_id, file_path, filename): with open(file_path, "rb") as f: content = f.read() return self.send_stream_content(room_id, content, filename) def send_stream_content(self, room_id, content, filename): res = self._client.upload(content, 'application/octet-stream', filename) room = self._client.join_room(room_id) room.send_file(res, filename) return res def build_reply(self, msg, text=None, private=False, threaded=False): response = self.build_message(text) response.frm = self.bot_identifier self.send_msg(msg.extras['room_id'], text) if private: response.to = msg.frm else: response.to = msg.frm.room if isinstance(msg.frm, RoomOccupant) else msg.frm return response def change_presence(self): pass def mode(self): pass def query_room(self): pass def rooms(self): pass def invite_callback(self, *args, **kwargs): print(args, kwargs) def ephemeral_callback(self, *args, **kwargs): print(args, kwargs) def leave_callback(self, *args, **kwargs): print(args, kwargs) def presence_callback(self, *args, **kwargs): print(args, kwargs) def callback(self, *events): for event in events: log.debug("Saw event %s.", event) if event["type"] == "m.room.message": content = event["content"] sender = event["sender"] if content["msgtype"] == "m.text": msg = Message(content["body"], extras={'room_id': event["room_id"]}) msg.frm = MatrixPerson(self._client, sender) msg.to = self.bot_identifier self.callback_message(msg) def serve_once(self): self._client = MatrixClient(self.url, token=self.token, user_id=self.user) self._client.add_listener(self.callback) self._client.add_invite_listener(self.invite_callback) self._client.add_ephemeral_listener(self.ephemeral_callback) self._client.add_leave_listener(self.leave_callback) self._client.add_presence_listener(self.presence_callback) self.connect_callback() self.bot_identifier = MatrixPerson(self._client, self.user) self._client.listen_forever()
class Application(QApplication): loggedIn = Signal(str) messageReceived = Signal(object, str, object, float) roomSwitched = Signal(object) roomJoined = Signal(object) roomUpdated = Signal(str, str, str) roomLeft = Signal(object) roomInvited = Signal(object) def __init__(self, *args, **kwargs): super(Application, self).__init__(*args, **kwargs) # setup the application name and icon self.setApplicationName('Qui') self.iconPath = os.path.dirname(__file__) self.iconPath = os.path.join(self.iconPath, 'icons/icon.png') self.setWindowIcon(QIcon(self.iconPath)) # setup the tray icon self.showNotifications = False self.tray = QSystemTrayIcon(QIcon(self.iconPath)) self.tray.show() self.tray.activated.connect(self.showWindow) # setup the tray icon menu self.menu = QMenu() self.menu.addAction('Quit').triggered.connect(self.quit) self.tray.setContextMenu(self.menu) # setup signals self.messageReceived.connect(self.receiveMessage) # show the window self.window = None self.showWindow(None) # try loading the login info self.client = None self.settings = QSettings('Qui', 'Qui') self.url = self.settings.value("url") self.token = self.settings.value("token") self.user = self.settings.value("user") invalid = self.url is None or self.url == "" or self.token is None or self.token == "" or self.user is None or self.user == "" if not invalid: try: self.client = MatrixClient(base_url=self.url, token=self.token, user_id=self.user) self.postLogin() except: invalid = True # show the login form if we can't login if invalid: self.loginForm = LoginForm() self.loginForm.loggedIn.connect(self.login) self.loginForm.show() def showWindow(self, reason): if self.window is None: # make a new window if we don't have one self.window = MainWindow() # setup signals self.loggedIn.connect(self.window.login) self.messageReceived.connect(self.window.receiveMessage) self.roomLeft.connect(self.window.roomLeft) self.roomJoined.connect(self.window.roomJoined) self.roomUpdated.connect(self.window.roomUpdated) self.window.createRoom.connect(self.createRoom) self.window.leaveRoom.connect(self.leaveRoom) self.window.joinRoom.connect(self.joinRoom) # show it self.window.show() else: # show it if it's minimized or something self.window.showNormal() def quit(self): sys.exit(0) def login(self, client, url): self.client = client self.settings.setValue('url', url) self.url = url self.settings.setValue('token', client.token) self.token = client.token self.settings.setValue('user', client.user_id) self.user = client.user_id self.postLogin() def postLogin(self): self.loggedIn.emit(self.user) #self.messages.userId = self.user self.client.add_listener(self.eventCallback) self.client.add_presence_listener(self.presenceCallback) self.client.add_invite_listener(self.inviteCallback) self.client.add_leave_listener(self.leaveCallback) self.client.start_listener_thread() for room, obj in self.client.get_rooms().items(): self.roomJoined.emit(obj) for event in obj.events: self.eventCallback(event) self.showNotifications = True def eventCallback(self, event): if 'type' in event and 'room_id' in event and 'content' in event and event[ 'type'] == 'm.room.message': room = Room(self.client, event['room_id']) self.messageReceived.emit(room, event['sender'], event['content'], time.time() - event['unsigned']['age']) if 'type' in event and 'room_id' in event and 'content' in event and event[ 'type'] == 'm.room.canonical_alias': self.roomUpdated.emit(event['room_id'], 'canonical_alias', event['content']['alias']) def presenceCallback(self, event): return print('presence: {}'.format(event)) def inviteCallback(self, roomId, state): return print('invite: {} {}'.format(roomId, state)) def leaveCallback(self, roomId, room): return print('leave: {} {}'.format(roomId, room)) def receiveMessage(self, room, sender, content, timestamp): if self.showNotifications: if self.window is None or not self.window.isActiveWindow(): self.tray.showMessage(sender, content['body']) def leaveRoom(self, room): self.client.api.leave_room(room.room_id) self.roomLeft.emit(room) def joinRoom(self, roomId): room = self.client.join_room(roomId) self.roomJoined.emit(room) def createRoom(self, roomId): room = self.client.create_room(roomId) self.roomJoined.emit(room)