Ejemplo n.º 1
0
    async def login(self) -> AsyncClient:
        # If there are no previously-saved credentials, we'll use the password
        if not os.path.exists(self.config.state_file):
            self.logger.info(
                "First time use. Did not find credential file. Using environment variables"
            )

            client = AsyncClient(self.config.homeserver,
                                 self.config.account_name)
            resp = await client.login(self.config.account_password,
                                      device_name=self.config.device_name)

            # check that we logged in succesfully
            if (isinstance(resp, LoginResponse)):
                write_details_to_disk(resp, self.config)
            else:
                self.logger.warning(
                    f'homeserver = "{self.config.homeserver}"; user = "******"'
                )
                self.logger.warning(f'Failed to log in: {resp}')
                exit(1)

            self.logger.info(
                'Logged in using a password. Credentials were stored.',
                'Try running the script again to login with credentials')

        # Otherwise the config file exists, so we'll use the stored credentials
        else:
            client = AsyncClient(self.config.homeserver)
            client.access_token = self.access_token
            client.user_id = self.user_id
            client.device_id = self.device_id

        return client
Ejemplo n.º 2
0
async def main() -> None:
    # Otherwise the config file exists, so we'll use the stored credentials
    # open the file in read-only mode
    client = AsyncClient("***HOMESERVER***", "***MATRIX_USER***")  #NOTE
    client.access_token = "***ACCESS_TOKEN***"  #NOTE

    #client.user_id = config['user_id']
    #client.device_id = config['device_id']

    # Now we can send messages as the user
    room_id = "***ROOM_ID***"  #NOTE
    #room_id = input(f"Enter room id for image message: [{room_id}] ")

    #image = "exampledir/samplephoto.jpg"
    #image = input(f"Enter file name of image to send: [{image}] ")

    #await send_image(client, room_id, image)
    await client.room_send(room_id=room_id,
                           message_type="m.room.message",
                           content={
                               "msgtype": "m.text",
                               "body": "Moi"
                           })

    client.login()
    print("Logged in using stored credentials. Sent a test message.")

    # Close the client connection after we are done with it.
    await client.close()
Ejemplo n.º 3
0
async def main() -> None:
    # 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}] ")

        client = AsyncClient(homeserver, user_id)
        pw = getpass.getpass()

        resp = await client.login(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.",
            "Try running the script again to login with credentials."
        )

    # 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)
            client = AsyncClient(config['homeserver'])

            client.access_token = config['access_token']
            client.user_id = config['user_id']
            client.device_id = config['device_id']

        # Now we can send messages as the user
        room_id = "!myfavouriteroomid:example.org"
        room_id = input(f"Enter room id for image message: [{room_id}] ")

        image = "exampledir/samplephoto.jpg"
        image = input(f"Enter file name of image to send: [{image}] ")

        await send_image(client, room_id, image)
        print("Logged in using stored credentials. Sent a test message.")

    # Close the client connection after we are done with it.
    await client.close()
Ejemplo n.º 4
0
async def main() -> None:
    # 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}] ")

        client = AsyncClient(homeserver, user_id)
        pw = getpass.getpass()

        resp = await client.login(pw)

        # 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.",
              "Try running the script again to login with credentials.")

    # 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)
            client = AsyncClient(config['homeserver'])

            client.access_token = config['access_token']
            client.user_id = config['user_id']
            client.device_id = config['device_id']

        # Now we can send messages as the user
        room_id = "!myfavouriteroomid:example.org"
        room_id = input(f"Enter room id for test message: [{room_id}] ")

        await client.room_send(room_id,
                               message_type="m.room.message",
                               content={
                                   "msgtype": "m.text",
                                   "body": "Hello world!"
                               })
        print("Logged in using stored credentials. Sent a test message.")

    # Either way we're logged in here, too
    await client.close()
Ejemplo n.º 5
0
async def post_picture_to_room(matrix_config: MatrixConfig,
                               image: Image) -> None:
    client = AsyncClient(matrix_config.homeserver_url)
    client.access_token = matrix_config.access_token
    client.user_id = matrix_config.mxid
    client.device_id = matrix_config.device_id

    room_id = matrix_config.target_room

    f = io.BytesIO()

    image.save(f, format="JPEG", optimize=True, progressive=True)

    # Get the (post-resize) file size
    f.seek(0, io.SEEK_END)
    image_file_size = f.tell()
    print(f"Image resized down to {image_file_size} bytes")
    f.seek(0)  # rewind to the start

    # First upload the image and get an MXC URI in response
    resp, _maybe_keys = await client.upload(
        lambda _got_429, _got_timeouts:
        f,  # No need to really use aiofiles when we have a BytesIO
        content_type="image/jpeg",
        filesize=image_file_size)

    if not isinstance(resp, UploadResponse):
        raise RuntimeError(f"Failed to send image: {resp}")

    # Then send a (image) message to the room pointing to the uploaded image's MXC URI.
    today_str = str(datetime.date.today())
    content = {
        "body": f"Image of the day {today_str}",
        "info": {
            "size": image_file_size,
            "mimetype": "image/jpeg",
            "w": image.width,
            "h": image.height,
            "thumbnail_info": None,
            "thumbnail_url": None,
        },
        "msgtype": "m.image",
        "url": resp.content_uri,
    }

    await client.room_send(room_id,
                           message_type="m.room.message",
                           content=content)

    f.close()
    await client.close()
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
async def main() -> None:
    bot_info = load_bot_info()

    mongo_client = MongoClient(
        "mongodb+srv://{}:{}@{}/weekling?retryWrites=true&w=majority".format(
            bot_info["db_username"], bot_info["db_password"],
            bot_info["db_hostname"]))
    db = mongo_client.weekling

    # NOTE Hemppa-hack
    jointime = datetime.datetime.now()  # HACKHACKHACK to avoid running old
    # commands after join
    join_hack_time = 5  # Seconds
    """
    Create the client-object with correct info, set callbacks for reacting 
    to events and login. If an access token is not found in config-file,
    ask for password.
    """
    client = AsyncClient(bot_info["homeserver"])

    client.add_event_callback(pass_to_invite_callback(client),
                              InviteMemberEvent)

    client.add_event_callback(
        pass_to_message_callback(client, db, jointime, join_hack_time),
        RoomMessageText)

    # Ask password from command line, press enter to use stored access token
    access_token = bot_info["access_token"]
    user_id = bot_info["user_id"]
    if len(access_token) != 0 and len(user_id) != 0:
        client.access_token = access_token
        # Manually set user id because not calling client.login()
        client.user_id = user_id
    else:
        password = getpass.getpass()
        response = await client.login(password)
        # Save info to file for future use
        bot_info["access_token"] = response.access_token
        try:
            with io.open(LOGIN_FILE, "w", encoding="utf-8") as fp:
                fp.write(json.dumps(bot_info))
        except OSError as e:
            print(f"Writing login-info failed: {e}")

    print(f"Logged in as {client}")

    await client.sync_forever(timeout=30000, full_state=False)  # milliseconds
Ejemplo n.º 8
0
async def do_sendmsg(roomid, message, path, endpoint) -> None:
    full_path = os.path.join(path, CONFIG_FILE)
    if not os.path.exists(full_path):
        print(f"Didn't find {full_path}, perhaps you should run init first")
        return

    # open the file in read-only mode
    with open(full_path, "r") as f:
        config = json.load(f)
        client = AsyncClient(config["homeserver"])
        client.access_token = config["access_token"]
        client.user_id = config["user_id"]
        client.device_id = config["device_id"]

        if not roomid:
            try:
                roomid = config["room_id"]
            except KeyError:
                print("Must either specify roomid or put it config file")
                raise

        if endpoint:
            do_check_health(endpoint, 10)
        else:
            try:
                endpoint = config["endpoint"]
            except KeyError:
                pass
            else:
                do_check_health(endpoint, 10)

        resp = await client.room_send(
            roomid,
            message_type="m.room.message",
            content={
                "msgtype": "m.text",
                "body": message,
            },
        )

    if isinstance(resp, RoomSendResponse):
        print("Logged in using stored credentials. Sent message.")
    else:
        print(f"Bad response: {resp}")
    await client.close()
Ejemplo n.º 9
0
async def login() -> None:
    try:
        with open(CREDS_FILE) as f:
            creds = json.load(f)
            client = AsyncClient(creds["homeserver"])
            client.access_token = creds["access_token"]
            client.user_id = creds["user_id"]
            client.device_id = creds["device_id"]
    except (FileNotFoundError, json.JSONDecodeError, KeyError):
        print(f"Did not find credentials in {CREDS_FILE}. "
              "Asking for login info.")
        matrix_server_str = "matrix.org"
        matrix_server_str = (input("Enter your matrix server URL "
                                   f"(default = {matrix_server_str!r}): ")
                             or matrix_server_str)

        url = urlsplit(matrix_server_str)
        url = (url._replace(scheme=url.scheme or "https")._replace(
            netloc=url.netloc or url.path)._replace(path=""))
        matrix_server = urlunsplit(url)

        user_id = input("Enter your user ID: ")
        user, *server_maybe = user_id.lstrip("@").split(":", 1)
        user_id = f"@{user}:" + (server_maybe[0]
                                 if server_maybe else url.netloc)

        device_name = "diplomatrix_client"
        device_name = (input("Choose a name for this device "
                             f"(default = {device_name!r}): ") or device_name)

        client = AsyncClient(matrix_server, user_id)
        pw = getpass.getpass()
        resp = await client.login(pw, device_name=device_name)

        if isinstance(resp, LoginResponse):
            save_login(resp, matrix_server)
            print(f"Logged in. Credentials saved to {CREDS_FILE!r}")
        else:
            print(f'server = "{matrix_server}"; user = "******"')
            print(f"Failed to log in: {resp}")
            sys.exit(1)

    await client.close()
Ejemplo n.º 10
0
async def main() -> None:
    client = AsyncClient("https://the-apothecary.club",
                         "@bot-sync:the-apothecary.club")

    # imports login data
    with open(CONFIG_FILE, "r") as f:
        config = json.load(f)
        client.access_token = config["access_token"]
        client.user_id = config["user_id"]
        client.device_id = config["device_id"]

    # import room data
    with open(ROOMS_FILE, "r") as f:
        config = json.load(f)
        bot_control_room = config["control_room"]
        bot_template_room = config["template_room"]
        bot_rooms = config["rooms"]

    ## await bot_send_msg(client, "Online", bot_control_room)

    # get room state
    room_state = await client.room_get_state(bot_template_room)

    ## print(room_state)

    # execute in each room
    for room in bot_rooms:

        # logs room cycle
        print("Syncing state in:", room["id"])

        # join rooms if not already joined
        await client.join(room["id"])

        # sends a test message
        ##resp = await bot_send_msg(client, "Syncing...", room["id"])
        ##print(resp)
        # sends a test state event
        resp = await bot_set_emote(client, room["id"])
        print(resp)
        # ends the connection
        await client.close()
Ejemplo n.º 11
0
async def main(sugaroid: Sugaroid) -> None:
    config = Config.from_environment()
    client = AsyncClient(config['homeserver'])
    client.access_token = config['access_token']
    client.user_id = config['user_id']
    client.device_id = config['device_id']

    print("Status: sleeping for 30000")
    await client.sync(30000)
    print("Resuming:")
    cb = Callbacks(client, sugaroid=sugaroid)
    client.add_event_callback(cb.message, RoomMessageText)
    while True:
        try:
            await client.sync_forever(timeout=30000, full_state=True)
        except KeyboardInterrupt:
            break
        except (ClientConnectionError, ServerDisconnectedError):
            print("Unable to connect to homeserver, retrying in 15s")
            time.sleep(15)
        finally:
            await client.close()
Ejemplo n.º 12
0
async def main():
    global client
    access_token = os.getenv('MATRIX_ACCESS_TOKEN')
    join_on_invite = os.getenv('JOIN_ON_INVITE')

    client = AsyncClient(os.environ['MATRIX_SERVER'],
                         os.environ['MATRIX_USER'])
    if access_token:
        client.access_token = access_token
    else:
        await client.login(os.environ['MATRIX_PASSWORD'])
        print("Access token:", client.access_token)
    await client.sync()
    if client.logged_in:
        client.add_event_callback(message_cb, RoomMessageText)
        client.add_event_callback(unknown_cb, RoomMessageUnknown)
        if join_on_invite:
            print('Note: Bot will join rooms if invited')
            client.add_event_callback(invite_cb, (InviteEvent, ))
        print('Bot running')
        await client.sync_forever(timeout=30000)
    else:
        print('Client was not able to log in, check env variables!')
Ejemplo n.º 13
0
async def main() -> None:
    client = AsyncClient("https://matrix.example.org", "@alice:example.org")

    # If there are no previously-saved credentials, we'll use the password
    if not os.path.exists(CONFIG_FILE):
        resp = await client.login("hunter2")
        # check that we logged in succesfully
        if (isinstance(resp, LoginResponse)):
            write_details_to_disk(resp)
        else:
            print(f"Failed to log in: {resp}")
            sys.exit(1)

        print("Logged in using a password.",
              "Try running the script again to login with an access token")

    # 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)
            client.access_token = config['access_token']
            client.user_id = config['user_id']
            client.device_id = config['device_id']

        # Now we can send messages as the user
        await client.room_send(room_id="!myfavouriteroomid:example.org",
                               message_type="m.room.message",
                               content={
                                   "msgtype": "m.text",
                                   "body": "Hello world!"
                               })
        print("Logged in using stored credentials")

    # Either way we're logged in here, too
    await client.close()
Ejemplo n.º 14
0
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, ))
    workflows = Workflow.fetch_workflows(config)
    aiocron.crontab(config.crontab,
                    func=report_last_nightlies,
                    args=(config, client, workflows))

    # 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}")
            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(args):
    cfgparser = configparser.ConfigParser()
    with open(args.config) as fh:
        cfgparser.read_file(fh)
    cfg = cfgparser['DEFAULT']
    room = cfg['room']

    payload = {
        'service': args.service,
        'host': args.host,
        'type': args.type.upper(),
        'state': args.state.upper(),
        'output': args.output,
        'msg': args.message,
    }

    device = {}
    device_state = os.path.join(cfg['state'], 'device.json')
    try:
        with open(device_state) as fh:
            device = json.load(fh)
    except FileNotFoundError:
        pass

    ensure_dir(cfg['state'])
    ensure_dir(os.path.join(cfg['state'], 'nio'))
    ensure_dir(os.path.join(cfg['state'], 'nio', cfg['user_id']))

    client = AsyncClient(cfg['homeserver'],
                         cfg['user_id'],
                         device_id=device.get('device_id'),
                         store_path=os.path.join(cfg['state'], 'nio',
                                                 cfg['user_id']),
                         config=ClientConfig(store_sync_tokens=True))

    if device:
        client.access_token = device['access_token']
        client.user_id = device['user_id']
        client.load_store()
    else:
        resp = await client.login_raw({
            'type': 'org.matrix.login.jwt',
            'token': cfg['token'],
        })
        if (isinstance(resp, LoginResponse)):
            write_state(device_state, resp)
        else:
            print(f"Failed to log in: {resp}", file=sys.stderr)
            sys.exit(1)

    await client.sync(timeout=args.timeout * 1000, full_state=True)

    in_rooms = client.rooms.keys()
    room_id = (await client.room_resolve_alias(room)).room_id
    if not room_id in in_rooms:
        await client.join(room_id)
    for unwanted in [r for r in in_rooms if r != room_id]:
        await client.room_leave(room)

    if client.should_upload_keys:
        await client.keys_upload()
    if client.should_query_keys:
        await client.keys_query()
    if client.should_claim_keys:
        await client.keys_claim(client.get_users_for_key_claiming())

    await client.sync(timeout=args.timeout * 1000, full_state=True)

    ps_l = []
    if payload['msg']:
        ps_l.append(payload['msg'])
    if payload['output']:
        ps_l.append(payload['output'])
    ps = '\n'.join(ps_l)

    await client.room_send(
        room_id,
        'm.room.message', {
            'msgtype':
            'm.text',
            'body':
            '{type}: {service} on {host} is {state}\n{msg}'.format(**payload),
            'format':
            'org.matrix.custom.html',
            'formatted_body':
            '<span style="background-color: #{color};"><span data-mx-bg-color="#{color}"><strong>{type}</strong>:</span></span> <span data-mx-bg-color="#ffffff">Service <strong>{service}</strong> on <strong>{host}</strong> is <strong>{state}</strong>:<br />{ps}</span>'
            .format(**payload,
                    bgcolor=state_colors_back.get(payload['state'].lower(),
                                                  '222288'),
                    ps=ps,
                    color=state_colors.get(payload['state'].lower(),
                                           '1111ff')),
        },
        ignore_unverified_devices=True)

    await client.sync(timeout=args.timeout * 1000, full_state=True)

    await client.close()
Ejemplo n.º 16
0
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()
Ejemplo n.º 17
0
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)