Skip to content

Commit

Permalink
Implement new error codes from MSC3848
Browse files Browse the repository at this point in the history
Also includes `M_NOT_JOINED` which is not yet written in the MSC

matrix-org/matrix-spec-proposals#3848
  • Loading branch information
tulir committed Jul 21, 2022
1 parent aacc831 commit d71b149
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
4 changes: 3 additions & 1 deletion mautrix/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,18 +245,20 @@ async def _send(
)
async with request as response:
if response.status < 200 or response.status >= 300:
errcode = message = None
errcode = unstable_errcode = message = None
try:
response_data = await response.json()
errcode = response_data["errcode"]
message = response_data["error"]
unstable_errcode = response_data.get("org.matrix.unstable.errcode")
except (JSONDecodeError, ContentTypeError, KeyError):
pass
raise make_request_error(
http_status=response.status,
text=await response.text(),
errcode=errcode,
message=message,
unstable_errcode=unstable_errcode,
)
return await response.json(), response

Expand Down
4 changes: 4 additions & 0 deletions mautrix/appservice/api/intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from mautrix.client import ClientAPI, StoreUpdatingAPI
from mautrix.errors import (
IntentError,
MAlreadyJoined,
MatrixRequestError,
MBadState,
MForbidden,
Expand Down Expand Up @@ -243,7 +244,10 @@ async def invite_user(
room_id, user_id, reason=reason, extra_content=extra_content
)
await self.state_store.invited(room_id, user_id)
except MAlreadyJoined as e:
await self.state_store.joined(room_id, user_id)
except MatrixRequestError as e:
# TODO remove this once MSC3848 is released and minimum spec version is bumped
if e.errcode == "M_FORBIDDEN" and "is already in the room" in e.message:
await self.state_store.joined(room_id, user_id)
else:
Expand Down
12 changes: 11 additions & 1 deletion mautrix/client/api/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
from multidict import CIMultiDict

from mautrix.api import Method, Path
from mautrix.errors import MatrixRequestError, MatrixResponseError, MNotFound, MRoomInUse
from mautrix.errors import (
MatrixRequestError,
MatrixResponseError,
MNotFound,
MNotJoined,
MRoomInUse,
)
from mautrix.types import (
JSON,
DirectoryPaginationToken,
Expand Down Expand Up @@ -478,7 +484,11 @@ async def leave_room(
if reason:
data["reason"] = reason
await self.api.request(Method.POST, Path.v3.rooms[room_id].leave, content=data)
except MNotJoined:
if raise_not_in_room:
raise
except MatrixRequestError as e:
# TODO remove this once MSC3848 is released and minimum spec version is bumped
if "not in room" not in e.message or raise_not_in_room:
raise

Expand Down
6 changes: 6 additions & 0 deletions mautrix/errors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
VerificationError,
)
from .request import (
MAlreadyJoined,
MatrixBadContent,
MatrixBadRequest,
MatrixInvalidToken,
Expand All @@ -27,13 +28,15 @@
MForbidden,
MGuestAccessForbidden,
MIncompatibleRoomVersion,
MInsufficientPower,
MInvalidParam,
MInvalidRoomState,
MInvalidUsername,
MLimitExceeded,
MMissingParam,
MMissingToken,
MNotFound,
MNotJoined,
MNotJSON,
MRoomInUse,
MTooLarge,
Expand Down Expand Up @@ -73,6 +76,7 @@
"SessionNotFound",
"SessionShareError",
"VerificationError",
"MAlreadyJoined",
"MatrixBadContent",
"MatrixBadRequest",
"MatrixInvalidToken",
Expand All @@ -87,13 +91,15 @@
"MForbidden",
"MGuestAccessForbidden",
"MIncompatibleRoomVersion",
"MInsufficientPower",
"MInvalidParam",
"MInvalidRoomState",
"MInvalidUsername",
"MLimitExceeded",
"MMissingParam",
"MMissingToken",
"MNotFound",
"MNotJoined",
"MNotJSON",
"MRoomInUse",
"MTooLarge",
Expand Down
31 changes: 28 additions & 3 deletions mautrix/errors/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,23 @@ def __init__(self, http_status: int, message: str = "") -> None:

MxSRE = Type[MatrixStandardRequestError]
ec_map: Dict[str, MxSRE] = {}
uec_map: Dict[str, MxSRE] = {}


def standard_error(code: str) -> Callable[[MxSRE], MxSRE]:
def standard_error(code: str, unstable: Optional[str] = None) -> Callable[[MxSRE], MxSRE]:
def decorator(cls: MxSRE) -> MxSRE:
cls.errcode = code
ec_map[code] = cls
if unstable:
cls.unstable_errcode = unstable
uec_map[unstable] = cls
return cls

return decorator


def make_request_error(
http_status: int, text: str, errcode: str, message: str
http_status: int, text: str, errcode: str, message: str, unstable_errcode: Optional[str] = None
) -> MatrixRequestError:
"""
Determine the correct exception class for the error code and create an instance of that class
Expand All @@ -70,14 +74,20 @@ def make_request_error(
errcode: The errcode field in the response JSON.
message: The error field in the response JSON.
"""
if unstable_errcode:
try:
ec_class = uec_map[unstable_errcode]
return ec_class(http_status, message)
except KeyError:
pass
try:
ec_class = ec_map[errcode]
return ec_class(http_status, message)
except KeyError:
return MatrixUnknownRequestError(http_status, text, errcode, message)


# Standard error codes from https://matrix.org/docs/spec/client_server/r0.4.0.html#api-standards
# Standard error codes from https://spec.matrix.org/v1.3/client-server-api/#api-standards
# Additionally some combining superclasses for some of the error codes


Expand All @@ -86,6 +96,21 @@ class MForbidden(MatrixStandardRequestError):
pass


@standard_error("M_ALREADY_JOINED", unstable="ORG.MATRIX.MSC3848.ALREADY_JOINED")
class MAlreadyJoined(MForbidden):
pass


@standard_error("M_NOT_JOINED", unstable="ORG.MATRIX.MSC3848.NOT_JOINED")
class MNotJoined(MForbidden):
pass


@standard_error("M_INSUFFICIENT_POWER", unstable="ORG.MATRIX.MSC3848.INSUFFICIENT_POWER")
class MInsufficientPower(MForbidden):
pass


@standard_error("M_USER_DEACTIVATED")
class MUserDeactivated(MForbidden):
pass
Expand Down

0 comments on commit d71b149

Please sign in to comment.