def test_remove_listener(): def dummy_listener(): pass client = MatrixClient("http://example.com") handler = client.add_listener(dummy_listener) found_listener = False for listener in client.listeners: if listener["uid"] == handler: found_listener = True break assert found_listener, "listener was not added properly" client.remove_listener(handler) found_listener = False for listener in client.listeners: if listener["uid"] == handler: found_listener = True break assert not found_listener, "listener was not removed properly"
class matrix_utils_ext(object): __MODULE_NAME__ = "Matrix Bot" __VERSION__ = "v0.0.1a" __MAX_SERVICE__ = 32 # Number of services that can be simultaneously installed. room_tuple = namedtuple("room_tuple", "room_addr listener") def __init__(self, config_path="config.json"): self.room_dic = {} self.services_sensitive_on_clock = set() self.is_timer_on = False self.is_on = False self.nb_current_service = 0 self.service_list = {} # self.logger.setLevel(logging.DEBUG) ; try: with open(config_path) as f: self.config = json.loads(f.read()) except IOError as e: print(e) self.login = self.config["login"] self.password = self.config["password"] module.config = self.config.copy() try: self.client = MatrixClient(self.config["host"]) self.client.login(self.login, self.password) except MatrixRequestError as e: print(e) sys.exit() def add_service_to_room(self, room, service, message_on_start=None): ret = False if self.nb_current_service < matrix_utils_ext.__MAX_SERVICE__: if service.add_room( room): # if room has been added to the service correctly if service in self.service_list: self.service_list[service] += 1 else: self.service_list[service] = 1 ret = True else: #raise Exception("Maximum number of services ({}) reached".format(str(matrix_utils.__MAX_SERVICE__))) ; pass return ret def remove_service_from_room(self, room, service): ret = False if service.remove_room(room): ret = True # if service is not linked to any room, remove from service_list self.service_list[service] -= 1 if self.service_list[service] == 0: del self.service_list[service] else: #raise Exception("Service {} does not exist in room {}.".format(service, room)) ; pass return ret # TODO ; eventuellement vérifier si une room avec une même adresse n'existe pas ? def add_room(self, room_addr, message_on_start=""): room = self.client.join_room(room_addr) listener = room.add_listener(self.callback) self.room_dic[room] = matrix_utils_ext.room_tuple( room_addr, listener ) # (room object address, room_name (room address), listener object) if message_on_start: # Conversion to HTML format message_on_start = message_on_start.replace("\n", "<br>") message_on_start = message_on_start.replace("\t", " ") room.send_html(message_on_start, msgtype="m.notice") return room def remove_room(self, room): if not (room in self.room_dic): return False for service in service_list.keys(): if (room in service.get_room_list()): # there are still some services linked to room. return False listener = self.room_dic[room].listener self.client.remove_listener(listener) room.leave() del self.room_dic[room] return True def callback(self, room, event): if event["type"] == "m.room.message": login = re.search("@[aA-zZ]+[0-9]*", event["sender"]).group(0) login = login[1:] tmp_log = "Event from " + bcolors.OKGREEN + self.room_dic[ room].room_addr + bcolors.ENDC + " at " + str( datetime.datetime.now()) + " by " + login print(tmp_log) text = str(event["content"]["body"]) ## Stop Service Management if text == self.config["bot_down_cmd"]: self.exit() ## Otherwise, run services for service in self.service_list.keys(): if (room in service.get_room_list()): ret = service.run(text, login, room) if ret: for msg in ret: # Conversion to HTML format msg = msg.replace("\n", "<br>") msg = msg.replace("\t", " ") room.send_html(msg, msgtype="m.notice") def spawn(self): self.client.start_listener_thread(exception_handler=self.error_handle) self.is_on = True print(bcolors.OKGREEN + "\n---------------------------------------------------\n" + "---- Matrix Bot v0.0.1 ----------------------------\n" + "---------------------------------------------------\n" + bcolors.ENDC) while (self.is_on): time.sleep(0.5) def timer_callback(self, t): while (self.is_timer_on): if self.is_on: for service in self.service_list: if service.is_clock_sensitive(): service.clock_update() ret = service.run_on_clock() if ret: # Conversion to HTML format ret = ret.replace("\n", "<br>") ret = ret.replace("\t", " ") for room in service.get_room_list(): room.send_html(ret, msgtype="m.notice") time.sleep(t) def start_timer(self, t=1): if not (self.is_timer_on): self.is_timer_on = True t1 = threading.Thread(target=self.timer_callback, args=(t, )) t1.start() def stop_timer(self): self.is_timer_on = False def exit(self): self.is_timer_on = False self.is_on = False for service in self.service_list: print("Module {} {} {} is shutting down.".format( bcolors.OKGREEN, service.module_name, bcolors.ENDC)) tmp_msg = service.exit() if tmp_msg: for room in service.get_room_list(): room.send_text(tmp_msg) # for room in self.room_dic: # room.send_text(self.config["bot_stop_txt"]); sys.exit() def error_handle(self, err): print("Server is not {} responding {} ({}). Restarting ...".format( bcolors.FAIL, bcolors.ENDC, err)) self.exit()
class matrix_utils(object): __MAX_SERVICE__ = 32 # Number of services that can be simultaneously installed. def __init__(self, config_path="config.json"): self.rooms = {} self.room_name_to_room = {} self.services = {} self.services_sensitive_on_clock = set() self.is_timer_on = False self.is_on = False self.nb_current_service = 0 # self.logger.setLevel(logging.DEBUG) ; try: with open(config_path) as f: self.config = json.loads(f.read()) except IOError as e: print(e) self.login = self.config["login"] self.password = self.config["password"] try: self.client = MatrixClient(self.config["host"]) self.client.login(self.login, self.password) except MatrixRequestError as e: print(e) sys.exit() def add_service_to_room(self, room, service, message_on_start=None): if self.nb_current_service < matrix_utils.__MAX_SERVICE__: tmp_set_service = self.rooms[room][1] tmp_set_service_name = self.rooms[room][2] service_name = service.keywords[0] if not (service in tmp_set_service) and not ( service_name in tmp_set_service_name): self.rooms[room][1].add(service) self.rooms[room][2].add(service_name) self.nb_current_service += 1 if not (service in self.services): self.services[service] = set() self.services[service].add(room) if message_on_start: room.send_text(message_on_start) return True else: raise Exception("Service already does already exist.") else: # raise Exception("Maximum number of services ({}) reached".format(str(matrix_utils.__MAX_SERVICE__))) ; return False def remove_service_from_room(self, room, service): tmp_set_service = self.rooms[room][1] tmp_set_service_name = self.rooms[room][2] tmp_services = self.services[service] if service in tmp_set_service: tmp_set_service.remove(service) tmp_set_service_name.remove(service.keywords[0]) tmp_services.remove(room) self.nb_current_service -= 1 # if service is not linked to any room, remove it from the ; if not (tmp_services ) and service in self.services_sensitive_on_clock: self.services_sensitive_on_clock.remove(service) else: raise Exception("Service {} does not exist.".format(service)) def add_room(self, room_name, message_on_start=False): new_room = self.client.join_room(room_name) listener = new_room.add_listener(self.callback) self.rooms[new_room] = (room_name, set(), set(), listener) self.room_name_to_room[room_name] = new_room if message_on_start: new_room.send_text(self.config["bot_start_txt"]) return new_room def remove_room(self, room): if room in self.room_timer and self.is_timer_on: raise Exception("Can not leave rooms while timer is on.") if room in self.rooms: uuid = self.rooms[room][3] self.client.remove_listener(uuid) room_name = self.rooms[room][0] del self.room_name_to_room[room_name] del self.rooms[room] room.leave() else: raise Exception("Room {} does not exist.".format(str(room))) def callback(self, room, event): if event["type"] == "m.room.message": login = re.search("@[aA-zZ]+[0-9]*", event["sender"]).group(0) login = login[1:] tmp_log = "Event from " + str(self.rooms[room][0]) + " at " + str( datetime.datetime.now()) + " by " + login print(tmp_log) text = str(event["content"]["body"]) if self.rooms: for service in self.rooms[room][1].copy(): service.admin(self) ret = service.run(text, login, room) if ret: room.send_text(ret) def spawn(self): self.client.start_listener_thread() self.is_on = True print("Ready ...") while (self.is_on): time.sleep(0.5) def timer_callback(self, t): while (self.is_timer_on): if self.is_on: for service in self.services_sensitive_on_clock.copy(): service.clock_update() service.admin(self) ret = service.run_on_clock() for room in self.services.copy()[service]: if ret: room.send_text(ret) time.sleep(t) def start_timer(self, t=1): if not (self.is_timer_on): self.is_timer_on = True t1 = threading.Thread(target=self.timer_callback, args=(t, )) t1.start() def stop_timer(self): self.is_timer_on = False def exit(self): self.is_timer_on = False self.is_on = False for room_key, room in self.rooms.items(): for service in room[1].copy(): print(service) tmp_msg = service.exit() if tmp_msg: room[1].send_text(tmp_msg) # self.remove_service_from_room(room_key, service) ; # room_key.leave() ; sys.exit() def add_timer_to_service(self, service): if not (service in self.services): raise BaseException( "Service {} should belong to (at least) one room.".format( service)) if not (service in self.services_sensitive_on_clock): self.services_sensitive_on_clock.add(service) def remove_timer_from_service(self, service): if service in self.services_sensitive_on_clock: self.services_sensitive_on_clock.remove(service) else: raise BaseException( "Service {} is not clock sensitive.".format(service))