def announce(text, token, room=None): from matrix_client.api import MatrixHttpApi matrix = MatrixHttpApi("https://matrix.org", token=token) matrix.sync() roomid = matrix.get_room_id(room) matrix.join_room(roomid) matrix.send_message(roomid, text)
def announce(text, cred): matrix = MatrixHttpApi(cred.get("url", "https://matrix.org"), token=cred['access_token']) for room in cred['rooms']: roomid = matrix.get_room_id(room) matrix.join_room(roomid) if not cred.get('mock', False): matrix.send_message(roomid, text)
def _get_messages(request, sync_token, direction): storage = get_messages(request) for message in storage: user_name = message print("MESSAGE : ", message) print("_get_message username: "******" : ", direction) messages.add_message(request, messages.INFO, user_name) sys.stdout.flush() session = Session.objects.get(matrix_user_name=user_name.message) api = MatrixHttpApi(session.matrix_server, token=session.matrix_token) synced = api.get_room_messages(api.get_room_id(session.matrix_room_name), session.matrix_sync_token, direction, limit=session.message_count) session.matrix_sync_token = synced[sync_token] session.save() room_topic = api.get_room_topic(api.get_room_id( session.matrix_room_name))['topic'] synced['chunk'] = _parse_messages(synced['chunk']) return synced
def matrix_sender(homeserver: str, token: str, room: str): """ Matrix sender wrapper: execute func, send a Matrix message with the end status (sucessfully finished or crashed) at the end. Also send a Matrix message before executing func. `homeserver`: str The homeserver address which was used to register the BOT. It is e.g. 'https://matrix-client.matrix.org'. It can be also looked up in Riot by looking in the riot settings, "Help & About" at the bottom. Specifying the schema (`http` or `https`) is required. `token`: str The access TOKEN of the user that will send the messages. It can be obtained in Riot by looking in the riot settings, "Help & About" , down the bottom is: Access Token:<click to reveal> `room`: str The alias of the room to which messages will be send by the BOT. After creating a room, an alias can be set. In Riot, this can be done by opening the room settings under 'Room Addresses'. """ matrix = MatrixHttpApi(homeserver, token=token) room_id = matrix.get_room_id(room) def decorator_sender(func): def send_message(text, room_id=room_id): matrix.send_message(room_id, text) @functools.wraps(func) def wrapper_sender(*args, **kwargs): start_time = datetime.datetime.now() host_name = socket.gethostname() func_name = func.__name__ text = "" if include_details: text += f'{func_name} called on {host_name} at {start_time.strftime(DATE_FORMAT)}' if message: text += f'{func_name}: {message}' if not include_details else f'\nMessage: {message}' if notify_end: text += '\nWe\'ll let you know when it\'s done.' send_message(text=text) try: value = func(*args, **kwargs) if notify_end: end_time = datetime.datetime.now() elapsed_time = end_time - start_time text = "" text += f'✅ {func_name} finished on {host_name} at {end_time.strftime(DATE_FORMAT)}' text += f'\nDuration: {elapsed_time}' try: str_value = str(value) text += f'\nReturned value: {str_value}' except: text += f'\nReturned value: ERROR - Couldn\'t parse the returned value.' send_message(text=text) return value except Exception as ex: end_time = datetime.datetime.now() elapsed_time = end_time - start_time contents = [f"☠️ {func_name} has crashed on {host_name} at {end_time.strftime(DATE_FORMAT)}", "Here's the error:", '%s\n\n' % ex, "Traceback:", '%s' % traceback.format_exc()] text = '\n'.join(contents) send_message(text=text) raise ex return wrapper_sender return decorator_sender
class MatrixBot(): def __init__(self, settings): self.sync_token = None self.logger = utils.get_logger() self.cache = utils.create_cache(settings) self.cache_timeout = int(settings["memcached"]["timeout"]) self.settings = settings self.period = settings["DEFAULT"]["period"] self.uri = settings["matrix"]["uri"] self.username = settings["matrix"]["username"].lower() self.password = settings["matrix"]["password"] self.room_ids = settings["matrix"]["rooms"] self.domain = self.settings["matrix"]["domain"] self.only_local_domain = self.settings["matrix"]["only_local_domain"] self.subscriptions_room_ids = settings["subscriptions"].keys() self.revokations_rooms_ids = settings["revokations"].keys() self.allowed_join_rooms_ids = filter(lambda x: x != 'default', settings["allowed-join"].keys()) self.default_allowed_join_rooms = settings["allowed-join"]["default"] self.client = MatrixClient(self.uri) self.token = self.client.login_with_password(username=self.username, password=self.password) self.api = MatrixHttpApi(self.uri, token=self.token) self.rooms = [] self.room_aliases = {} self.plugins = [] for plugin in settings['plugins'].itervalues(): mod = __import__(plugin['module'], fromlist=[plugin['class']]) klass = getattr(mod, plugin['class']) self.plugins.append(klass(self, plugin['settings'])) def _get_selected_users(self, groups_users_list): def _add_or_remove_user(users, username, append): username = self.normalize_user_id(username) if append and username not in users["in"]: users["in"].append(username) if not append and username not in users["out"]: users["out"].append(username) ldap_settings = self.settings["ldap"] append = True users = {"in": [], "out": []} for item in groups_users_list: if item == ("but"): append = False elif item.startswith("+"): group_name = item[1:] groups_members = bot_ldap.get_ldap_groups_members( ldap_settings) if group_name in groups_members.keys(): map(lambda x: _add_or_remove_user(users, x, append), groups_members[group_name]) else: _add_or_remove_user(users, item, append) selected_users = filter(lambda x: x not in users["out"], users["in"]) return selected_users def normalize_user_id(self, user_id): if not user_id.startswith("@"): user_id = "@" + user_id self.logger.debug("Adding missing '@' to the username: %s" % user_id) if user_id.count(":") == 0: user_id = "%s:%s" % (user_id, self.domain) return user_id def get_user_id(self, username=None, normalized=True): if not username: username = self.username normalized_username = self.normalize_user_id(username) if normalized: return normalized_username else: return normalized_username[1:].split(':')[0] def is_local_user_id(self, username): normalized_username = self.get_user_id(username, normalized=True) if normalized_username.split(':')[1] == self.domain: return True return False def get_real_room_id(self, room_id): if room_id.startswith("#"): room_id = self.api.get_room_id(room_id) return room_id def get_room_members(self, room_id): key = "get_room_members-%s" % room_id res = self.cache.get(key) if res: self.logger.debug("get_room_members (cached): %s" % (key)) return res res = self.call_api("get_room_members", 2, room_id) self.cache.set(key, res, self.cache_timeout) self.logger.debug("get_room_members (non cached): %s" % (key)) return res def is_room_member(self, room_id, user_id): try: r = Room(self.client, room_id) return user_id in r.get_joined_members().keys() except Exception, e: return False return False
def matrix_sender(homeserver: str, token: str, room: str): """ Matrix sender wrapper: execute func, send a Matrix message with the end status (sucessfully finished or crashed) at the end. Also send a Matrix message before executing func. `homeserver`: str The homeserver address which was used to register the BOT. It is e.g. 'https://matrix-client.matrix.org'. It can be also looked up in Riot by looking in the riot settings, "Help & About" at the bottom. Specifying the schema (`http` or `https`) is required. `token`: str The access TOKEN of the user that will send the messages. It can be obtained in Riot by looking in the riot settings, "Help & About" , down the bottom is: Access Token:<click to reveal> `room`: str The alias of the room to which messages will be send by the BOT. After creating a room, an alias can be set. In Riot, this can be done by opening the room settings under 'Room Addresses'. """ matrix = MatrixHttpApi(homeserver, token=token) room_id = matrix.get_room_id(room) def decorator_sender(func): @functools.wraps(func) def wrapper_sender(*args, **kwargs): start_time = datetime.datetime.now() host_name = socket.gethostname() func_name = func.__name__ # Handling distributed training edge case. # In PyTorch, the launch of `torch.distributed.launch` sets up a RANK environment variable for each process. # This can be used to detect the master process. # See https://github.com/pytorch/pytorch/blob/master/torch/distributed/launch.py#L211 # Except for errors, only the master process will send notifications. if 'RANK' in os.environ: master_process = (int(os.environ['RANK']) == 0) host_name += ' - RANK: %s' % os.environ['RANK'] else: master_process = True if master_process: contents = [ 'Your training has started 🎬', 'Machine name: %s' % host_name, 'Main call: %s' % func_name, 'Starting date: %s' % start_time.strftime(DATE_FORMAT) ] text = '\n'.join(contents) matrix.send_message(room_id, text) try: value = func(*args, **kwargs) if master_process: end_time = datetime.datetime.now() elapsed_time = end_time - start_time contents = [ "Your training is complete 🎉", 'Machine name: %s' % host_name, 'Main call: %s' % func_name, 'Starting date: %s' % start_time.strftime(DATE_FORMAT), 'End date: %s' % end_time.strftime(DATE_FORMAT), 'Training duration: %s' % str(elapsed_time) ] try: str_value = str(value) contents.append('Main call returned value: %s' % str_value) except: contents.append( 'Main call returned value: %s' % "ERROR - Couldn't str the returned value.") text = '\n'.join(contents) matrix.send_message(room_id, text) return value except Exception as ex: end_time = datetime.datetime.now() elapsed_time = end_time - start_time contents = [ "Your training has crashed ☠️", 'Machine name: %s' % host_name, 'Main call: %s' % func_name, 'Starting date: %s' % start_time.strftime(DATE_FORMAT), 'Crash date: %s' % end_time.strftime(DATE_FORMAT), 'Crashed training duration: %s\n\n' % str(elapsed_time), "Here's the error:", '%s\n\n' % ex, "Traceback:", '%s' % traceback.format_exc() ] text = '\n'.join(contents) matrix.send_message(room_id, text) raise ex return wrapper_sender return decorator_sender
class MatrixBot: """The main bot, connecting to the server and handling plugins""" def __init__(self, config): self.username = config['bot']['username'] server = config['bot']['host'] self.fullname = "@" + str( self.username).lower() + ':' + urlparse(server).hostname self.plugins = [] self.api = None self.current_room = "" self.members = [] self.all_rooms = None self.config = config # Connect to server BOT_LOG.debug("creating matrix client for server %s", server) self.client = MatrixClient(server) def connect(self): ''' log in to the server and get connected rooms''' password = self.config['bot']['password'] username = self.username server = self.config['bot']['host'] room_id = self.config['bot']['room'] try: BOT_LOG.debug("Trying to log in as %s pw: %s", self.username, "".join(['*' for p in password])) token = self.client.login(username, password) BOT_LOG.debug("Got Token %s..%s", token[0:3], token[-3:-1]) except MatrixRequestError as error: BOT_LOG.error("Login Failed: Code: %s, Content: %s", error.code, error.content) #this is a second connection with different interface BOT_LOG.debug("Creating matrix API endpoint") self.api = MatrixHttpApi(server, token) if str(room_id).startswith('!'): self.current_room = room_id else: self.current_room = self.get_room_id_by_name(room_id) BOT_LOG.debug("Joining room with id %s", self.current_room) self.api.join_room(self.current_room) BOT_LOG.debug("Getting member info") self.members = self.api.get_room_members(self.current_room) BOT_LOG.debug( "Members in room: %s", ",".join([ a['sender'] if 'sender' in a.keys() else "" for a in self.members['chunk'] ])) rooms = [] for _, room in self.client.get_rooms().items(): rooms.append(room) self.all_rooms = VirtualRoom(rooms) def init_scheduler(self): ''' initialize a thread that handles the event loop for the scheduler for all plugins''' BOT_LOG.debug("Spinning up scheduler thread") self.schedule = schedule self.killswitch = Event() self.killswitch.clear() self.thread = Thread(target=self.schedule_loop, args=(self.killswitch, )) #self.thread.daemon = True self.thread.start() def stop_scheduler(self): ''' wind down the scheduler thread gracefully before exit''' BOT_LOG.debug("Trying to end scheduler thread ..") self.killswitch.set() self.thread.join() BOT_LOG.debug("..successful") def schedule_loop(self, stop_event): ''' this event loop is run inside the scheduler thread''' BOT_LOG.debug("Scheduler thread started successfully") while not stop_event.is_set(): #BOT_LOG.debug("Scheduler loop runs") self.schedule.run_pending() sleep(10) def add_plugin(self, plugin): """Puts a plugin in the internal list where it will be registered as a listener""" self.plugins.append(plugin) def get_room_id_by_name(self, name): """Translate human-readable room name into internal room id""" BOT_LOG.debug("Getting room ID for name '%s'", name) if str(name).startswith('#'): rid = self.api.get_room_id(name) else: rid = self.api.get_room_id('#' + name) if rid is None: BOT_LOG.warning("Room name '%s' not found", name) rid = "" return rid def send(self, text): """Sending initial message to room to announce startup""" BOT_LOG.debug("Sending sample text to room") self.api.send_message(self.current_room, text) def start_polling(self): """Starts syncing and polling for new messages in a new thread""" # Starts polling for messages self.client.start_listener_thread() return self.client.sync_thread def register_listeners(self): ''' register the added plugins as listeners into the rooms the bot si connected to''' rooms = [] for room_id, room in self.client.get_rooms().items(): BOT_LOG.debug("Registering plugins in room %s (%s)", room.name, room_id) rooms.append(room) for plugin in self.plugins: room.add_listener(plugin.handle_message)
def chat(request, update=""): user_name = None storage = get_messages(request) for message in storage: user_name = message print("MESSAGE : ", message) if user_name != None: print("username: "******"LOGIN VARS") print("session.matrix_user_name ", session.matrix_user_name) print("session.matrix_room_name ", session.matrix_room_name) print("session.matrix_server ", session.matrix_server) print("session.message_count ", session.message_count) print("session.show_images ", session.show_images) sys.stdout.flush() api = MatrixHttpApi(session.matrix_server, token=session.matrix_token) print("GET_MEMBERSHIP") api.join_room(api.get_room_id(session.matrix_room_name)) else: return HttpResponseRedirect('/') if request.method == 'POST': #If the user hit send button try: print("Posting chat") sys.stdout.flush() chat_form = ChatForm(request.POST) if chat_form.is_valid(): response = api.send_message( api.get_room_id(session.matrix_room_name), chat_form.cleaned_data['text_entered']) chat_form = ChatForm() room_topic = api.get_room_topic( api.get_room_id(session.matrix_room_name))['topic'] messages.add_message(request, messages.INFO, session.matrix_user_name) synced = _get_messages(request, sync_token="end", direction='f') session.messages = json.dumps(synced['chunk'] + jsonDec.decode(session.messages)) session.save() return render( request, 'client_app/chat.html', { 'chat_form': chat_form, 'name': session.matrix_user_name, 'messages': jsonDec.decode(session.messages), 'room': session.matrix_room_name, 'topic': room_topic, 'show_images': session.show_images }) except MatrixRequestError as e: print(str(e)) sys.stdout.flush() form = NameForm(request.POST) return render(request, 'client_app/login.html', { 'form': form, 'login_error': True, 'error_text': str(e) }) else: return render( request, 'client_app/chat.html', { 'chat_form': chat_form, 'name': session.matrix_user_name, 'messages': jsonDec.decode(session.messages), 'room': session.matrix_room_name, 'topic': room_topic, 'show_images': session.show_images }) if update == "": #If not asking for an update, get first sync to server try: chat_form = ChatForm() synced = api.sync() room_topic = api.get_room_topic( api.get_room_id(session.matrix_room_name))['topic'] session.matrix_sync_token = synced["next_batch"] messages.add_message(request, messages.INFO, session.matrix_user_name) synced = _get_messages(request, sync_token="start", direction='b') session.messages = json.dumps(synced['chunk']) session.save() except MatrixRequestError as e: print(str(e)) sys.stdout.flush() form = NameForm(request.POST) return render(request, 'client_app/login.html', { 'form': form, 'login_error': True }) else: return render( request, 'client_app/chat.html', { 'chat_form': chat_form, 'name': session.matrix_user_name, 'messages': jsonDec.decode(session.messages), 'room': session.matrix_room_name, 'topic': room_topic, 'show_images': session.show_images }) else: # update is requested so return next messages using sync token from initial sync chat_form = ChatForm() room_topic = api.get_room_topic( api.get_room_id(session.matrix_room_name))['topic'] messages.add_message(request, messages.INFO, session.matrix_user_name) synced = _get_messages(request, sync_token="end", direction='f') session.messages = json.dumps(synced['chunk'] + jsonDec.decode(session.messages)) session.save() return render( request, 'client_app/chat.html', { 'chat_form': chat_form, 'name': session.matrix_user_name, 'messages': jsonDec.decode(session.messages), 'room': session.matrix_room_name, 'topic': room_topic, 'show_images': session.show_images })