From eff64fabd6b0ecd5869a19233412accbbf5f56e4 Mon Sep 17 00:00:00 2001 From: miruka Date: Thu, 26 Dec 2019 08:16:04 -0400 Subject: [PATCH] Catch any nio.ErrorResponse to raise MatrixErrors --- TODO.md | 1 + src/backend/backend.py | 23 +++-------- src/backend/errors.py | 5 --- src/backend/matrix_client.py | 77 +++++++++++++++--------------------- src/backend/nio_callbacks.py | 8 ---- 5 files changed, 38 insertions(+), 76 deletions(-) diff --git a/TODO.md b/TODO.md index 1acd4d29..2b6290ab 100644 --- a/TODO.md +++ b/TODO.md @@ -48,6 +48,7 @@ ## Issues +- Room pane can't make thin enough when zoomed - `EventImage`s for `m.image` sometimes appear broken, can be made normal by switching to another room and coming back - First sent message in E2E room is sometimes undecryptable diff --git a/src/backend/backend.py b/src/backend/backend.py index 213af748..829667cf 100644 --- a/src/backend/backend.py +++ b/src/backend/backend.py @@ -220,9 +220,6 @@ class Backend: client = await self.get_any_client() response = await client.get_profile(user_id) - if isinstance(response, nio.ProfileGetError): - raise MatrixError.from_nio(response) - self.profile_cache[user_id] = response return response @@ -232,14 +229,9 @@ class Backend: ) -> nio.ThumbnailResponse: """Return thumbnail for a matrix media.""" - args = (server_name, media_id, width, height) - client = await self.get_any_client() - response = await client.thumbnail(*args) - - if isinstance(response, nio.ThumbnailError): - raise MatrixError.from_nio(response) - - return response + args = (server_name, media_id, width, height) + client = await self.get_any_client() + return await client.thumbnail(*args) async def download( @@ -247,13 +239,8 @@ class Backend: ) -> nio.DownloadResponse: """Return the content of a matrix media.""" - client = await self.get_any_client() - response = await client.download(server_name, media_id) - - if isinstance(response, nio.DownloadError): - raise MatrixError.from_nio(response) - - return response + client = await self.get_any_client() + return await client.download(server_name, media_id) # General functions diff --git a/src/backend/errors.py b/src/backend/errors.py index 105df1d8..15a01cd5 100644 --- a/src/backend/errors.py +++ b/src/backend/errors.py @@ -71,11 +71,6 @@ class MatrixTooLarge(MatrixError): # Client errors -@dataclass -class UserNotFound(Exception): - user_id: str = field() - - @dataclass class InvalidUserId(Exception): user_id: str = field() diff --git a/src/backend/matrix_client.py b/src/backend/matrix_client.py index e5e8c06e..c3b16b20 100644 --- a/src/backend/matrix_client.py +++ b/src/backend/matrix_client.py @@ -28,11 +28,10 @@ import nio from nio.crypto import AsyncDataT as UploadData from nio.crypto import async_generator_from_data -from . import __app_name__, __display_name__ -from . import utils +from . import __app_name__, __display_name__, utils from .errors import ( BadMimeType, InvalidUserId, InvalidUserInContext, MatrixError, - UneededThumbnail, UserNotFound, + MatrixNotFound, UneededThumbnail, ) from .html_markdown import HTML_PROCESSOR as HTML from .models.items import ( @@ -131,6 +130,22 @@ class MatrixClient(nio.AsyncClient): ) + async def _send(self, *args, **kwargs) -> nio.Response: + """Raise a `MatrixError` subclass for any `nio.ErrorResponse`. + + This function is called by `nio.AsyncClient`'s methods to send + requests to the server. Return normal responses, but catch any + `ErrorResponse` to turn them into `MatrixError` exceptions we raise. + """ + + response = await super()._send(*args, **kwargs) + + if isinstance(response, nio.ErrorResponse): + raise MatrixError.from_nio(response) + + return response + + @property def default_device_name(self) -> str: """Device name to set at login if the user hasn't set a custom one.""" @@ -143,13 +158,7 @@ class MatrixClient(nio.AsyncClient): async def login(self, password: str, device_name: str = "") -> None: """Login to the server using the account's password.""" - response = await super().login( - password, device_name or self.default_device_name, - ) - - if isinstance(response, nio.LoginError): - raise MatrixError.from_nio(response) - + await super().login(password, device_name or self.default_device_name) asyncio.ensure_future(self._start()) @@ -221,7 +230,7 @@ class MatrixClient(nio.AsyncClient): break # task cancelled except Exception: trace = traceback.format_exc().rstrip() - log.error("Exception during sync, will restart:\n%s", trace) + log.error("Exception during sync, restart in 2s:\n%s", trace) await asyncio.sleep(2) @@ -520,16 +529,13 @@ class MatrixClient(nio.AsyncClient): """Send a message event with `content` dict to a room.""" async with self.backend.send_locks[room_id]: - response = await self.room_send( + await self.room_send( room_id = room_id, message_type = "m.room.message", content = content, ignore_unverified_devices = True, ) - if isinstance(response, nio.RoomSendError): - raise MatrixError.from_nio(response) - async def load_past_events(self, room_id: str) -> bool: """Ask the server for 100 previous events of the room. @@ -557,9 +563,6 @@ class MatrixClient(nio.AsyncClient): limit = 100 if room_id in self.loaded_once_rooms else 25, ) - if isinstance(response, nio.RoomMessagesError): - raise MatrixError.from_nio(response) - self.loaded_once_rooms.add(room_id) more_to_load = True @@ -620,21 +623,16 @@ class MatrixClient(nio.AsyncClient): if not self.user_id_regex.match(invite): raise InvalidUserId(invite) - if isinstance(await self.get_profile(invite), nio.ProfileGetError): - raise UserNotFound(invite) + # Raise MatrixNotFound if profile doesn't exist + await self.get_profile(invite) - response = await super().room_create( + return await super().room_create( invite = [invite], is_direct = True, visibility = nio.RoomVisibility.private, initial_state = [nio.EnableEncryptionBuilder().as_dict()] if encrypt else [], - ) - - if isinstance(response, nio.RoomCreateError): - raise MatrixError.from_nio(response) - - return response.room_id + ).room_id async def new_group_chat( @@ -647,7 +645,7 @@ class MatrixClient(nio.AsyncClient): ) -> str: """Create a new matrix room with the purpose of being a group chat.""" - response = await super().room_create( + return await super().room_create( name = name or None, topic = topic or None, federate = federate, @@ -656,12 +654,7 @@ class MatrixClient(nio.AsyncClient): nio.RoomVisibility.private, initial_state = [nio.EnableEncryptionBuilder().as_dict()] if encrypt else [], - ) - - if isinstance(response, nio.RoomCreateError): - raise MatrixError.from_nio(response) - - return response.room_id + ).room_id async def room_join(self, alias_or_id_or_url: str) -> str: """Join an existing matrix room.""" @@ -679,12 +672,7 @@ class MatrixClient(nio.AsyncClient): if not self.room_id_or_alias_regex.match(string): raise ValueError("Not an alias or room id") - response = await super().join(string) - - if isinstance(response, nio.JoinError): - raise MatrixError.from_nio(response) - - return response.room_id + return await super().join(string).room_id async def room_forget(self, room_id: str) -> None: @@ -722,8 +710,10 @@ class MatrixClient(nio.AsyncClient): if not self.user_id_regex.match(user): return InvalidUserId(user) - if isinstance(await self.get_profile(user), nio.ProfileGetError): - return UserNotFound(user) + try: + await self.get_profile(user) + except MatrixNotFound as err: + return err return await self.room_invite(room_id, user) @@ -810,9 +800,6 @@ class MatrixClient(nio.AsyncClient): monitor, ) - if isinstance(response, nio.UploadError): - raise MatrixError.from_nio(response) - return UploadReturn(response.content_uri, mime, decryption_dict) diff --git a/src/backend/nio_callbacks.py b/src/backend/nio_callbacks.py index 063e5a47..c50d256c 100644 --- a/src/backend/nio_callbacks.py +++ b/src/backend/nio_callbacks.py @@ -89,14 +89,6 @@ class NioCallbacks: account.first_sync_done = True - async def onErrorResponse(self, resp: nio.ErrorResponse) -> None: - # TODO: show something in the client, must be seen on login screen too - try: - log.warning("%s - %s", resp, json.dumps(vars(resp), indent=4)) - except Exception: - log.warning(repr(resp)) - - # Event callbacks async def onRoomMessageText(self, room, ev) -> None: