Skip to content

Commit d71b149

Browse files
committed
Implement new error codes from MSC3848
Also includes `M_NOT_JOINED` which is not yet written in the MSC matrix-org/matrix-spec-proposals#3848
1 parent aacc831 commit d71b149

File tree

5 files changed

+52
-5
lines changed

5 files changed

+52
-5
lines changed

mautrix/api.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,18 +245,20 @@ async def _send(
245245
)
246246
async with request as response:
247247
if response.status < 200 or response.status >= 300:
248-
errcode = message = None
248+
errcode = unstable_errcode = message = None
249249
try:
250250
response_data = await response.json()
251251
errcode = response_data["errcode"]
252252
message = response_data["error"]
253+
unstable_errcode = response_data.get("org.matrix.unstable.errcode")
253254
except (JSONDecodeError, ContentTypeError, KeyError):
254255
pass
255256
raise make_request_error(
256257
http_status=response.status,
257258
text=await response.text(),
258259
errcode=errcode,
259260
message=message,
261+
unstable_errcode=unstable_errcode,
260262
)
261263
return await response.json(), response
262264

mautrix/appservice/api/intent.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from mautrix.client import ClientAPI, StoreUpdatingAPI
1313
from mautrix.errors import (
1414
IntentError,
15+
MAlreadyJoined,
1516
MatrixRequestError,
1617
MBadState,
1718
MForbidden,
@@ -243,7 +244,10 @@ async def invite_user(
243244
room_id, user_id, reason=reason, extra_content=extra_content
244245
)
245246
await self.state_store.invited(room_id, user_id)
247+
except MAlreadyJoined as e:
248+
await self.state_store.joined(room_id, user_id)
246249
except MatrixRequestError as e:
250+
# TODO remove this once MSC3848 is released and minimum spec version is bumped
247251
if e.errcode == "M_FORBIDDEN" and "is already in the room" in e.message:
248252
await self.state_store.joined(room_id, user_id)
249253
else:

mautrix/client/api/rooms.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
from multidict import CIMultiDict
1212

1313
from mautrix.api import Method, Path
14-
from mautrix.errors import MatrixRequestError, MatrixResponseError, MNotFound, MRoomInUse
14+
from mautrix.errors import (
15+
MatrixRequestError,
16+
MatrixResponseError,
17+
MNotFound,
18+
MNotJoined,
19+
MRoomInUse,
20+
)
1521
from mautrix.types import (
1622
JSON,
1723
DirectoryPaginationToken,
@@ -478,7 +484,11 @@ async def leave_room(
478484
if reason:
479485
data["reason"] = reason
480486
await self.api.request(Method.POST, Path.v3.rooms[room_id].leave, content=data)
487+
except MNotJoined:
488+
if raise_not_in_room:
489+
raise
481490
except MatrixRequestError as e:
491+
# TODO remove this once MSC3848 is released and minimum spec version is bumped
482492
if "not in room" not in e.message or raise_not_in_room:
483493
raise
484494

mautrix/errors/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
VerificationError,
1414
)
1515
from .request import (
16+
MAlreadyJoined,
1617
MatrixBadContent,
1718
MatrixBadRequest,
1819
MatrixInvalidToken,
@@ -27,13 +28,15 @@
2728
MForbidden,
2829
MGuestAccessForbidden,
2930
MIncompatibleRoomVersion,
31+
MInsufficientPower,
3032
MInvalidParam,
3133
MInvalidRoomState,
3234
MInvalidUsername,
3335
MLimitExceeded,
3436
MMissingParam,
3537
MMissingToken,
3638
MNotFound,
39+
MNotJoined,
3740
MNotJSON,
3841
MRoomInUse,
3942
MTooLarge,
@@ -73,6 +76,7 @@
7376
"SessionNotFound",
7477
"SessionShareError",
7578
"VerificationError",
79+
"MAlreadyJoined",
7680
"MatrixBadContent",
7781
"MatrixBadRequest",
7882
"MatrixInvalidToken",
@@ -87,13 +91,15 @@
8791
"MForbidden",
8892
"MGuestAccessForbidden",
8993
"MIncompatibleRoomVersion",
94+
"MInsufficientPower",
9095
"MInvalidParam",
9196
"MInvalidRoomState",
9297
"MInvalidUsername",
9398
"MLimitExceeded",
9499
"MMissingParam",
95100
"MMissingToken",
96101
"MNotFound",
102+
"MNotJoined",
97103
"MNotJSON",
98104
"MRoomInUse",
99105
"MTooLarge",

mautrix/errors/request.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,23 @@ def __init__(self, http_status: int, message: str = "") -> None:
4646

4747
MxSRE = Type[MatrixStandardRequestError]
4848
ec_map: Dict[str, MxSRE] = {}
49+
uec_map: Dict[str, MxSRE] = {}
4950

5051

51-
def standard_error(code: str) -> Callable[[MxSRE], MxSRE]:
52+
def standard_error(code: str, unstable: Optional[str] = None) -> Callable[[MxSRE], MxSRE]:
5253
def decorator(cls: MxSRE) -> MxSRE:
5354
cls.errcode = code
5455
ec_map[code] = cls
56+
if unstable:
57+
cls.unstable_errcode = unstable
58+
uec_map[unstable] = cls
5559
return cls
5660

5761
return decorator
5862

5963

6064
def make_request_error(
61-
http_status: int, text: str, errcode: str, message: str
65+
http_status: int, text: str, errcode: str, message: str, unstable_errcode: Optional[str] = None
6266
) -> MatrixRequestError:
6367
"""
6468
Determine the correct exception class for the error code and create an instance of that class
@@ -70,14 +74,20 @@ def make_request_error(
7074
errcode: The errcode field in the response JSON.
7175
message: The error field in the response JSON.
7276
"""
77+
if unstable_errcode:
78+
try:
79+
ec_class = uec_map[unstable_errcode]
80+
return ec_class(http_status, message)
81+
except KeyError:
82+
pass
7383
try:
7484
ec_class = ec_map[errcode]
7585
return ec_class(http_status, message)
7686
except KeyError:
7787
return MatrixUnknownRequestError(http_status, text, errcode, message)
7888

7989

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

8393

@@ -86,6 +96,21 @@ class MForbidden(MatrixStandardRequestError):
8696
pass
8797

8898

99+
@standard_error("M_ALREADY_JOINED", unstable="ORG.MATRIX.MSC3848.ALREADY_JOINED")
100+
class MAlreadyJoined(MForbidden):
101+
pass
102+
103+
104+
@standard_error("M_NOT_JOINED", unstable="ORG.MATRIX.MSC3848.NOT_JOINED")
105+
class MNotJoined(MForbidden):
106+
pass
107+
108+
109+
@standard_error("M_INSUFFICIENT_POWER", unstable="ORG.MATRIX.MSC3848.INSUFFICIENT_POWER")
110+
class MInsufficientPower(MForbidden):
111+
pass
112+
113+
89114
@standard_error("M_USER_DEACTIVATED")
90115
class MUserDeactivated(MForbidden):
91116
pass

0 commit comments

Comments
 (0)