def __init__(self, bot_mxid: UserID, login_shared_secret: str, homeserver_address: str, user_id_prefix: str, user_id_suffix: str, device_name: str, loop: Optional[asyncio.AbstractEventLoop] = None) -> None: self.loop = loop or asyncio.get_event_loop() self.bot_mxid = bot_mxid self.device_name = device_name self._id_prefix = user_id_prefix self._id_suffix = user_id_suffix self.login_shared_secret = login_shared_secret.encode("utf-8") config = AsyncClientConfig(store=NioStore, encryption_enabled=True, pickle_key="mautrix-python", store_sync_tokens=True) device_id = DBAccount.first_device_id(self.bot_mxid) if device_id: self.log.debug(f"Found device ID in database: {device_id}") self.client = AsyncClient(homeserver=homeserver_address, user=bot_mxid, device_id=device_id, config=config, store_path="3:<")
async def main(): # Read config file config = Config("config.yaml") # Configuration options for the AsyncClient nio_client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, ) # Initialize the matrix client nio_client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, config=nio_client_config, store_path="/home/brendan/Documents/matrix-monzo-next/nio_store", ) # Initialise the monzo client monzo_client = Monzo(config.monzo_access_token) await nio_client.login(config.password, "monzo_bot") # Set up event callbacks callbacks = Callbacks(config, nio_client, monzo_client) nio_client.add_event_callback(callbacks.message, (RoomMessageText, )) nio_client.add_event_callback(callbacks.invite, (InviteEvent, )) # First do a sync with full_state = true to retrieve the state of the room. await nio_client.sync(full_state=True) await nio_client.sync_forever(30000)
async def create_client() -> AsyncClient: homeserver = ARGS.server user_id = ARGS.user password = ARGS.userpass if not ARGS.batch: homeserver = input( f"Enter URL of your homeserver: [{homeserver}] ") or homeserver user_id = input(f"Enter your full user ID: [{user_id}] ") or user_id password = getpass.getpass() client = AsyncClient( homeserver=homeserver, user=user_id, config=AsyncClientConfig(store=store.SqliteMemoryStore), ) await client.login(password, DEVICE_NAME) client.load_store() room_keys_path = ARGS.keys room_keys_password = ARGS.keyspass if not ARGS.batch: room_keys_path = input( f"Enter full path to room E2E keys: [{room_keys_path}] " ) or room_keys_path room_keys_password = getpass.getpass("Room keys password: "******"Importing keys. This may take a while...") await client.import_keys(room_keys_path, room_keys_password) return client
async def run(self) -> None: client_config = AsyncClientConfig(store_sync_tokens=True, encryption_enabled=True) self.client = AsyncClient(config.matrix_homeserver, store_path="./store", config=client_config) self.client.restore_login( user_id=config.matrix_user_id, device_id=config.matrix_device_id, access_token=config.matrix_access_token, ) if self.client.should_upload_keys: await self.client.keys_upload() if self.client.should_query_keys: await self.client.keys_query() if self.client.should_claim_keys: await self.client.keys_claim() await self.client.sync(full_state=True) self.client.add_event_callback(self.on_message, RoomMessageText) self.client.add_event_callback(self.on_invite, InviteMemberEvent) await self.client.sync_forever(timeout=30000) await self.client.close()
def make_client(): client_config = AsyncClientConfig(encryption_enabled=True) return AsyncClient(settings.homeserver, settings.mxid, device_id=settings.device_id, config=client_config, store_path=settings.store_dir)
async def async_client_pair(tempdir, loop): ALICE_ID = "@alice:example.org" ALICE_DEVICE = "JLAFKJWSCS" BOB_ID = "@bob:example.org" BOB_DEVICE = "ASDFOEAK" config = AsyncClientConfig(max_timeouts=3) alice = AsyncClient( "https://example.org", ALICE_ID, ALICE_DEVICE, tempdir, config=config, ) bob = AsyncClient( "https://example.org", BOB_ID, BOB_DEVICE, tempdir, config=config, ) await alice.receive_response( LoginResponse(ALICE_ID, ALICE_DEVICE, "alice_1234")) await bob.receive_response(LoginResponse(BOB_ID, BOB_DEVICE, "bob_1234")) yield (alice, bob) await alice.close() await bob.close()
async def init(homeserver: str, username: str, password: str, keyfile: Optional[str], keyphrase: Optional[str]) -> AsyncClient: config = AsyncClientConfig(store=SqliteMemoryStore, store_sync_tokens=True) client = AsyncClient(homeserver, username, config=config) response = await client.login(password) client.add_event_callback(event_cb, RoomMessage) await client.import_keys(keyfile, keyphrase) return client
async def async_client(tempdir, loop): client = AsyncClient( "https://example.org", "ephemeral", "DEVICEID", tempdir, config=AsyncClientConfig(max_timeouts=3), ) yield client await client.close()
async def _parseandpost(): if len(sys.argv) < 4 or len(sys.argv) > 5: logger.error("Usage: {} <room(s)> <file path> <message> [<additional url>]".format(sys.argv[0])) return the_rooms = re.split("[, ;]+", sys.argv[1].strip()) the_picture_filename = sys.argv[2] the_message = sys.argv[3] if len(sys.argv) == 5: the_additional_link = sys.argv[4] else: the_additional_link = None error = _read_config() if error: logger.error(f"Error reading config: {error}") return client = None try: # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=False, ) client = AsyncClient(homeserver=_config_values[_config_string_url], user=_config_values[_config_string_username], config=client_config, ssl=True ) resp = await client.login(password=_config_values[_config_string_password]) if isinstance(resp, LoginError): logger.error(f"Could not login: {resp}") return await client.sync(30000, True) for room_id in the_rooms: resp = await client.join(room_id=room_id) if isinstance(resp, JoinError): logger.warning(f"Failed to join {room_id}: {resp}") continue if isinstance(resp, JoinResponse): internal_room_id = resp.room_id await _send_message(client, internal_room_id, the_picture_filename, the_message, the_additional_link) await client.sync(3000, True) await client.logout() return finally: await client.close()
async def main(): # Read config file config = Config("config.yaml") # Configure the database store = Storage(config.database_filepath) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, config=client_config, ) logger.debug("Connected to Matrix!") # Assign an access token to the bot instead of logging in and creating a new device client.access_token = config.access_token # Set up event callbacks callbacks = Callbacks(client, store, config) client.add_event_callback(callbacks.message, (RoomMessageText, )) client.add_event_callback(callbacks.invite, (InviteEvent, )) # Retrieve the last sync token if it exists token = store.get_sync_token() # Sync loop while True: # Sync with the server sync_response = await client.sync(timeout=30000, full_state=True, since=token) # Check if the sync had an error if type(sync_response) == SyncError: logger.warning("Error in client sync: %s", sync_response.message) continue # Save the latest sync token token = sync_response.next_batch if token: store.save_sync_token(token)
def __init__(self, join_rooms: set): self.STORE_PATH = os.environ['LOGIN_STORE_PATH'] self.CONFIG_FILE = f"{self.STORE_PATH}/credentials.json" self.join_rooms = join_rooms self.client: AsyncClient = None self.client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) self.greeting_sent = False
def __init__(self, config): super().__init__(config) self.has_synced = False self.identity = config.BOT_IDENTITY for key in ('email', 'auth_dict', 'site'): if key not in self.identity: log.fatal( f"You need to supply the key `{key}` for me to use. `{key}` and its value " "can be found in your bot's `matrixniorc` config file.") sys.exit(1) # Store the sync token in order to avoid replay of old messages. config = AsyncClientConfig(store_sync_tokens=True) self.client = nio.AsyncClient(self.identity['site'], self.identity['email'], config=config)
def __init__(self, bot: Bot, home_server: str, username: str, access_token: str, device_id: str, store_filepath: str, web_dir: str, public_url: str, display_name: str, avatar_path: str, debug: bool = False): if not os.path.exists(store_filepath): os.makedirs(store_filepath) self.debug = debug self.public_url = public_url self.web_dir = web_dir self.display_name = display_name self.avatar_path = avatar_path self.username = username self.identifier = f"@{username}:{home_server[home_server.find('//') + 2:]}" self.matrix = AsyncClient(home_server, self.identifier, device_id, store_path=store_filepath, config=AsyncClientConfig( encryption_enabled=True, store=SqliteStore, store_name="matrix.db", store_sync_tokens=True)) self.matrix.access_token = access_token self.matrix.user_id = self.identifier self.matrix.add_event_callback(self.handle_message, RoomMessageText) self.matrix.add_event_callback(self.crypto_event, MegolmEvent) self.matrix.add_event_callback(self.invite_event, InviteMemberEvent) self.matrix.add_event_callback(self.room_event, RoomMemberEvent) self.matrix.restore_login(self.identifier, device_id, access_token) self.bot = bot self.log.level = logging.DEBUG self.log.debug(f"Initialized Matrix Bot: {self.identifier}")
async def create_client() -> AsyncClient: homeserver = "https://matrix-client.matrix.org" homeserver = input( f"Enter URL of your homeserver: [{homeserver}] ") or homeserver user_id = input(f"Enter your full user ID (e.g. @user:matrix.org): ") password = getpass.getpass() client = AsyncClient( homeserver=homeserver, user=user_id, config=AsyncClientConfig(store=store.SqliteMemoryStore), ) await client.login(password, DEVICE_NAME) client.load_store() room_keys_path = input("Enter full path to room E2E keys: ") room_keys_password = getpass.getpass("Room keys password: "******"Importing keys. This may take a while...") await client.import_keys(room_keys_path, room_keys_password) return client
async def main() -> None: matrix_homeserver = "https://matrix.org" matrix_user_id = "@myawesomebot:matrix.org" matrix_password = getpass.getpass(f"Enter password for {matrix_user_id}: ") client = AsyncClient(matrix_homeserver, matrix_user_id, config=AsyncClientConfig(encryption_enabled=True), store_path="./store") resp = await client.login(matrix_password, device_name="glagolitic-bot") if isinstance(resp, LoginResponse): print (f"""Add these parameters to config.py: matrix_homeserver = '{matrix_homeserver}' matrix_user_id = '{resp.user_id}' matrix_device_id = '{resp.device_id}' matrix_access_token = '{resp.access_token}' """) else: print (f"Login failed: {resp}") await client.close()
check_if_user_is_existing, create_new_room, create_new_user, create_new_message, get_number_of_links_to_be_shown, get_salt_value, add_salt_value, check_if_room_is_existing, get_all_domains_original, get_room_ids) from nlp import language_processing from message_evaluation import evaluate_message from response_management import generate_response from config import Config #set filepath of config file config_filepath = "../config.yaml" config = Config(config_filepath) #AsyncClient configuration options client_config = AsyncClientConfig( store_sync_tokens=True, encryption_enabled=True, ) #initialize matrix client client = AsyncClient( config.homeserver_url, config.user_id, config=client_config, ) ''' The main module controls the processing of events via callback functions 1) InviteEvents --> auto-join room 2) MessageEvents --> pass message to other modules The module also sends messages to the matrix homeserver
async def main(): # Read config file # A different config file path can be specified as the first command line argument if len(sys.argv) > 1: config_filepath = sys.argv[1] else: config_filepath = "config.yaml" config = Config(config_filepath) # Configure the database store = Storage(config.database_filepath) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_filepath, config=client_config, ) # Set up event callbacks callbacks = Callbacks(client, store, config) client.add_event_callback(callbacks.message, (RoomMessageText, )) client.add_event_callback(callbacks.invite, (InviteMemberEvent, )) # Keep trying to reconnect on failure (with some time in-between) while True: try: # Try to login with the configured username/password try: login_response = await client.login( password=config.user_password, device_name=config.device_name, ) # Check if login failed if type(login_response) == LoginError: logger.error(f"Failed to login: %s", login_response.message) return False except LocalProtocolError as e: # There's an edge case here where the user hasn't installed the correct C # dependencies. In that case, a LocalProtocolError is raised on login. logger.fatal( "Failed to login. Have you installed the correct dependencies? " "https://github.com/poljar/matrix-nio#installation " "Error: %s", e) return False # Login succeeded! # Sync encryption keys with the server # Required for participating in encrypted rooms if client.should_upload_keys: await client.keys_upload() logger.info(f"Logged in as {config.user_id}") await client.sync_forever(timeout=30000, full_state=True) except (ClientConnectionError, ServerDisconnectedError): logger.warning( "Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) finally: # Make sure to close the client connection on disconnect await client.close()
async def main(): # TODO: this really needs to be replaced # probably using https://docs.python.org/3.8/library/functools.html#functools.partial global client global plugin_loader # Read config file config = Config("config.yaml") # Configure the database store = Storage(config.database_filepath) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=config.enable_encryption, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_filepath, config=client_config, ) # instantiate the pluginLoader plugin_loader = PluginLoader() # Set up event callbacks callbacks = Callbacks(client, store, config, plugin_loader) client.add_event_callback(callbacks.message, (RoomMessageText, )) client.add_event_callback(callbacks.invite, (InviteEvent, )) client.add_event_callback(callbacks.event_unknown, (UnknownEvent, )) client.add_response_callback(run_plugins) # Keep trying to reconnect on failure (with some time in-between) error_retries: int = 0 while True: try: # Try to login with the configured username/password try: login_response = await client.login( password=config.user_password, device_name=config.device_name, ) # Check if login failed if type(login_response) == LoginError: logger.error( f"Failed to login: {login_response.message}, retrying in 15s... ({error_retries})" ) # try logging in a few times to work around temporary login errors during homeserver restarts if error_retries < 3: error_retries += 1 await sleep(15) continue else: return False else: error_retries = 0 except LocalProtocolError as e: # There's an edge case here where the user enables encryption but hasn't installed # the correct C dependencies. In that case, a LocalProtocolError is raised on login. # Warn the user if these conditions are met. if config.enable_encryption: logger.fatal( "Failed to login and encryption is enabled. Have you installed the correct dependencies? " "https://github.com/poljar/matrix-nio#installation") return False else: # We don't know why this was raised. Throw it at the user logger.fatal(f"Error logging in: {e}") # Login succeeded! # Sync encryption keys with the server # Required for participating in encrypted rooms if client.should_upload_keys: await client.keys_upload() logger.info(f"Logged in as {config.user_id}") await client.sync_forever(timeout=30000, full_state=True) except (ClientConnectionError, ServerDisconnectedError, AttributeError, asyncio.TimeoutError) as err: logger.debug(err) logger.warning( f"Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests await sleep(15) finally: # Make sure to close the client connection on disconnect await client.close()
def __init__( self, server_name, pan_store, pan_conf, homeserver, queue=None, user_id="", device_id="", store_path="", config=None, ssl=None, proxy=None, store_class=None, ): config = config or AsyncClientConfig( store=store_class or SqliteStore, store_name="pan.db" ) super().__init__(homeserver, user_id, device_id, store_path, config, ssl, proxy) index_dir = os.path.join(store_path, server_name, user_id) try: os.makedirs(index_dir) except OSError: pass self.server_name = server_name self.pan_store = pan_store self.pan_conf = pan_conf if INDEXING_ENABLED: logger.info("Indexing enabled.") from pantalaimon.index import IndexStore self.index = IndexStore(self.user_id, index_dir) else: logger.info("Indexing disabled.") self.index = None self.task = None self.queue = queue # Those two events are mainly used for testing. self.new_fetch_task = asyncio.Event() self.fetch_loop_event = asyncio.Event() self.room_members_fetched = defaultdict(bool) self.send_semaphores = defaultdict(asyncio.Semaphore) self.send_decision_queues = dict() # type: asyncio.Queue self.last_sync_token = None self.history_fetcher_task = None self.history_fetch_queue = asyncio.Queue() self.add_to_device_callback(self.key_verification_cb, KeyVerificationEvent) self.add_to_device_callback( self.key_request_cb, (RoomKeyRequest, RoomKeyRequestCancellation) ) self.add_event_callback(self.undecrypted_event_cb, MegolmEvent) if INDEXING_ENABLED: self.add_event_callback( self.store_message_cb, ( RoomMessageText, RoomMessageMedia, RoomEncryptedMedia, RoomTopicEvent, RoomNameEvent, ), ) self.add_response_callback(self.keys_query_cb, KeysQueryResponse) self.add_response_callback(self.sync_tasks, SyncResponse)
async def main(): # Read config file # A different config file path can be specified as the first command line arg if len(sys.argv) > 1: config_filepath = sys.argv[1] else: config_filepath = "config.yaml" CONFIG.read_config(config_filepath) # Configure the python job scheduler SCHEDULER.configure({"apscheduler.timezone": CONFIG.timezone}) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # Initialize the matrix client client = AsyncClient( CONFIG.homeserver_url, CONFIG.user_id, device_id=CONFIG.device_id, store_path=CONFIG.store_path, config=client_config, ) # Configure the database store = Storage(client) # Set up event callbacks callbacks = Callbacks(client, store) client.add_event_callback(callbacks.message, (RoomMessageText,)) client.add_event_callback(callbacks.invite, (InviteMemberEvent,)) client.add_event_callback(callbacks.decryption_failure, (MegolmEvent,)) # Keep trying to reconnect on failure (with some time in-between) while True: try: # Try to login with the configured username/password try: login_response = await client.login( password=CONFIG.user_password, device_name=CONFIG.device_name, ) # Check if login failed. Usually incorrect password if type(login_response) == LoginError: logger.error("Failed to login: %s", login_response.message) logger.warning("Trying again in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) continue except LocalProtocolError as e: # There's an edge case here where the user hasn't installed the correct C # dependencies. In that case, a LocalProtocolError is raised on login. logger.fatal( "Failed to login. Have you installed the correct dependencies? " "https://github.com/poljar/matrix-nio#installation " "Error: %s", e, ) return False # Login succeeded! logger.info(f"Logged in as {CONFIG.user_id}") logger.info("Startup complete") # Allow jobs to fire try: SCHEDULER.start() except SchedulerAlreadyRunningError: pass await client.sync_forever(timeout=30000, full_state=True) except (ClientConnectionError, ServerDisconnectedError, TimeoutError): logger.warning("Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) except Exception: logger.exception("Unknown exception occurred:") logger.warning("Restarting in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) finally: # Make sure to close the client connection on disconnect await client.close()
async def login() -> AsyncClient: """Handle login with or without stored credentials.""" # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # If there are no previously-saved credentials, we'll use the password if not os.path.exists(CONFIG_FILE): print("First time use. Did not find credential file. Asking for " "homeserver, user, and password to create credential file.") homeserver = "https://matrix.example.org" homeserver = input(f"Enter your homeserver URL: [{homeserver}] ") if not (homeserver.startswith("https://") or homeserver.startswith("http://")): homeserver = "https://" + homeserver user_id = "@user:example.org" user_id = input(f"Enter your full user ID: [{user_id}] ") device_name = "matrix-nio" device_name = input(f"Choose a name for this device: [{device_name}] ") if not os.path.exists(STORE_PATH): os.makedirs(STORE_PATH) # Initialize the matrix client client = AsyncClient( homeserver, user_id, store_path=STORE_PATH, config=client_config, ) pw = getpass.getpass() resp = await client.login(password=pw, device_name=device_name) # check that we logged in succesfully if (isinstance(resp, LoginResponse)): write_details_to_disk(resp, homeserver) else: print(f"homeserver = \"{homeserver}\"; user = \"{user_id}\"") print(f"Failed to log in: {resp}") sys.exit(1) print("Logged in using a password. Credentials were stored. " "On next execution the stored login credentials will be used.") # Otherwise the config file exists, so we'll use the stored credentials else: # open the file in read-only mode with open(CONFIG_FILE, "r") as f: config = json.load(f) # Initialize the matrix client based on credentials from file client = AsyncClient( config['homeserver'], config['user_id'], device_id=config['device_id'], store_path=STORE_PATH, config=client_config, ) client.restore_login(user_id=config['user_id'], device_id=config['device_id'], access_token=config['access_token']) print("Logged in using stored credentials.") return client
async def main(): """The first function that is run when starting the bot""" # Read user-configured options from a config file. # A different config file path can be specified as the first command line argument if len(sys.argv) > 1: config_path = sys.argv[1] else: config_path = "config.yaml" # Read the parsed config file and create a Config object config = Config(config_path) # Configure the database store = Storage(config.database) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_path, config=client_config, ) if config.user_token: client.access_token = config.user_token client.user_id = config.user_id # Set up event callbacks callbacks = Callbacks(client, store, config) client.add_event_callback(callbacks.invite, (InviteMemberEvent, )) client.add_event_callback(callbacks.decryption_failure, (MegolmEvent, )) client.add_response_callback(callbacks.sync, (SyncResponse, )) client.add_event_callback(callbacks.unknown, (UnknownEvent, )) # Keep trying to reconnect on failure (with some time in-between) while True: try: if config.user_token: # Use token to log in client.load_store() # Sync encryption keys with the server if client.should_upload_keys: await client.keys_upload() else: # Try to login with the configured username/password try: login_response = await client.login( password=config.user_password, device_name=config.device_name, ) # Check if login failed if type(login_response) == LoginError: logger.error("Failed to login: %s", login_response.message) return False except LocalProtocolError as e: # There's an edge case here where the user hasn't installed the correct C # dependencies. In that case, a LocalProtocolError is raised on login. logger.fatal( "Failed to login. Have you installed the correct dependencies? " "https://github.com/poljar/matrix-nio#installation " "Error: %s", e, ) return False # Login succeeded! logger.info(f"Logged in as {config.user_id}") # join the pins room we'll be writing to result = client.join(config.pins_room) if type(result) == JoinError: raise Exception( f"Error joining pins room {config.pins_room}", ) await client.sync_forever(timeout=30000, full_state=True) except Exception as e: logger.error("%s", e) logger.warning( "Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) finally: # Make sure to close the client connection on disconnect try: await client.close() except Exception as e2: logger.error("Also got exception while closing, %s", e2)
async def main(): # Read config file # A different config file path can be specified as the first command line argument if len(sys.argv) > 1: config_path = sys.argv[1] else: config_path = "config.yaml" config = Config(config_path) # Configure the database store = Storage(config.database) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_path, config=client_config, ) if config.user_token: client.access_token = config.user_token client.user_id = config.user_id # Set up event callbacks callbacks = Callbacks(client, store, config) # noinspection PyTypeChecker client.add_event_callback(callbacks.message, (RoomMessageText, )) # noinspection PyTypeChecker client.add_event_callback(callbacks.invite, (InviteMemberEvent, )) # Keep trying to reconnect on failure (with some time in-between) while True: try: if config.user_token: # Use token to log in client.load_store() # Sync encryption keys with the server if client.should_upload_keys: await client.keys_upload() else: # Try to login with the configured username/password try: login_response = await client.login( password=config.user_password, device_name=config.device_name, ) # Check if login failed if type(login_response) == LoginError: logger.error("Failed to login: %s", login_response.message) break except LocalProtocolError as e: # There's an edge case here where the user hasn't installed the correct C # dependencies. In that case, a LocalProtocolError is raised on login. logger.fatal( "Failed to login. Have you installed the correct dependencies? " "https://github.com/poljar/matrix-nio#installation " "Error: %s", e, ) break # Login succeeded! # Join the management room or fail response = await with_ratelimit(client, "join", config.management_room) if type(response) == JoinError: logger.fatal("Could not join the management room, aborting.") break else: logger.info(f"Management room membership is good") # Resolve management room ID if not known if config.management_room.startswith('#'): # Resolve the room ID response = await with_ratelimit(client, "room_resolve_alias", config.management_room) if type(response) == RoomResolveAliasResponse: config.management_room_id = response.room_id else: logger.fatal( "Could not resolve the management room ID from alias, aborting" ) break logger.info(f"Logged in as {config.user_id}") await client.sync_forever(timeout=30000, full_state=True) except (ClientConnectionError, ServerDisconnectedError): logger.warning( "Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) finally: # Make sure to close the client connection on disconnect await client.close()
async def main(): """Entry point.""" # Read config file config = Config("config.yaml") # Configure the database store = Storage(config.database_filepath) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, # store_sync_tokens=True, encryption_enabled=config.enable_encryption, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_filepath, config=client_config, ) # Assign an access token to the bot instead of logging in and creating a new device client.access_token = config.access_token # Set up event callbacks callbacks = Callbacks(client, store, config) client.add_event_callback(callbacks.message, (RoomMessageText,)) client.add_event_callback(callbacks.invite, (InviteMemberEvent,)) client.add_event_callback(callbacks.joined, (RoomMemberEvent,)) # Create a new sync token, attempting to load one from the database if it has one already sync_token = SyncToken(store) # Keep trying to reconnect on failure (with some time in-between) while True: # try: # Try to login with the configured username/password # try: # login_response = await client.login( # password=config.user_password, # device_name=config.device_name, # ) # # Check if login failed # if type(login_response) == LoginError: # logger.error(f"Failed to login: %s", login_response.message) # return False # except LocalProtocolError as e: # # There's an edge case here where the user enables encryption # # but hasn't installed the correct C dependencies. In that case, # # a LocalProtocolError is raised on login. # # Warn the user if these conditions are met. # if config.enable_encryption: # logger.fatal( # "Failed to login and encryption is enabled. " # "Have you installed the correct dependencies? " # "https://github.com/poljar/matrix-nio#installation" # ) # return False # else: # # We don't know why this was raised. Throw it at the user # logger.fatal("Error logging in: %s", e) # return False # Login succeeded! # =============================== # Sync encryption keys with the server # Required for participating in encrypted rooms # if client.should_upload_keys: # await client.keys_upload() # logger.info(f"Logged in as {config.user_id}") # await client.sync_forever(timeout=30000, full_state=True) # =============================== # =============================== logger.debug("Syncing: %s", sync_token.token) sync_response = await client.sync(timeout=30000, since=sync_token.token) # Check if the sync had an errors if type(sync_response) == SyncError: logger.warning("Error in client sync: %s", sync_response.message) continue # Save the latest sync token to the database token = sync_response.next_batch if token: sync_token.update(token)
async def main(): # noqa """Create bot as Matrix client and enter event loop.""" # Read config file # A different config file path can be specified # as the first command line argument if len(sys.argv) > 1: config_filepath = sys.argv[1] else: config_filepath = "config.yaml" config = Config(config_filepath) # Configure the database store = Storage(config.database_filepath) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_filepath, config=client_config, ) # Set up event callbacks callbacks = Callbacks(client, store, config) client.add_event_callback(callbacks.message, (RoomMessageText, )) client.add_event_callback(callbacks.invite, (InviteMemberEvent, )) client.add_to_device_callback(callbacks.accept_all_verify, (KeyVerificationEvent, )) # Keep trying to reconnect on failure (with some time in-between) while True: try: # Try to login with the configured username/password try: if config.access_token: logger.debug("Using access token from config file to log " f"in. access_token={config.access_token}") client.restore_login(user_id=config.user_id, device_id=config.device_id, access_token=config.access_token) else: logger.debug("Using password from config file to log in.") login_response = await client.login( password=config.user_password, device_name=config.device_name, ) # Check if login failed if type(login_response) == LoginError: logger.error("Failed to login: "******"{login_response.message}") return False logger.info((f"access_token of device {config.device_name}" f" is: \"{login_response.access_token}\"")) except LocalProtocolError as e: # There's an edge case here where the user hasn't installed # the correct C dependencies. In that case, a # LocalProtocolError is raised on login. logger.fatal( "Failed to login. " "Have you installed the correct dependencies? " "Error: %s", e) return False # Login succeeded! logger.debug(f"Logged in successfully as user {config.user_id} " f"with device {config.device_id}.") # Sync encryption keys with the server # Required for participating in encrypted rooms if client.should_upload_keys: await client.keys_upload() if config.change_device_name: content = {"display_name": config.device_name} resp = await client.update_device(config.device_id, content) if isinstance(resp, UpdateDeviceError): logger.debug(f"update_device failed with {resp}") else: logger.debug(f"update_device successful with {resp}") await client.sync(timeout=30000, full_state=True) for device_id, olm_device in client.device_store[ config.user_id].items(): logger.info("Setting up trust for my own " f"device {device_id} and session key " f"{olm_device.keys}.") client.verify_device(olm_device) await client.sync_forever(timeout=30000, full_state=True) except (ClientConnectionError, ServerDisconnectedError): logger.warning( "Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) finally: # Make sure to close the client connection on disconnect await client.close()
async def main(): """The first function that is run when starting the bot""" # Read user-configured options from a config file. # A different config file path can be specified as the first command line argument if len(sys.argv) > 1: config_path = sys.argv[1] else: config_path = "config.yaml" # Read the parsed config file and create a Config object config = Config(config_path) # Configure the database store = Storage(config.database) # Configuration options for the AsyncClient client_config = AsyncClientConfig( max_limit_exceeded=0, max_timeouts=0, store_sync_tokens=True, encryption_enabled=True, ) # Initialize the matrix client client = AsyncClient( config.homeserver_url, config.user_id, device_id=config.device_id, store_path=config.store_path, config=client_config, ) if config.user_token: client.access_token = config.user_token client.user_id = config.user_id # Set up event callbacks callbacks = Callbacks(client, store, config) client.add_event_callback(callbacks.message, (RoomMessageText, )) client.add_event_callback(callbacks.invite, (InviteMemberEvent, )) client.add_event_callback(callbacks.decryption_failure, (MegolmEvent, )) client.add_event_callback(callbacks.unknown, (UnknownEvent, )) # Set up a scheduler scheduler = AsyncIOScheduler() # Set up MISPAlert misp_alert = MISPAlert(client, config, store) # Add a job that checks for new taged events every minute trigger = IntervalTrigger( seconds=60, start_date=datetime.now() + timedelta(seconds=2), ) # Add the query job scheduler.add_job(misp_alert.alerter, trigger=trigger) # Keep trying to reconnect on failure (with some time in-between) while True: try: if config.user_token: # Use token to log in client.load_store() # Sync encryption keys with the server if client.should_upload_keys: await client.keys_upload() else: # Try to login with the configured username/password try: login_response = await client.login( password=config.user_password, device_name=config.device_name, ) # Check if login failed if type(login_response) == LoginError: logger.error("Failed to login: %s", login_response.message) return False except LocalProtocolError as e: # There's an edge case here where the user hasn't installed the correct C # dependencies. In that case, a LocalProtocolError is raised on login. logger.fatal( "Failed to login. Have you installed the correct dependencies? " "https://github.com/poljar/matrix-nio#installation " "Error: %s", e, ) return False # Login succeeded! logger.info(f"Logged in as {config.user_id}") # Allow jobs to fire try: scheduler.start() except SchedulerAlreadyRunningError: pass await client.sync_forever(timeout=30000, full_state=True) except (ClientConnectionError, ServerDisconnectedError): logger.warning( "Unable to connect to homeserver, retrying in 15s...") # Sleep so we don't bombard the server with login requests sleep(15) finally: # Make sure to close the client connection on disconnect await client.close()