From 0627c4227057baeec5040cd0024da179e2b7f982 Mon Sep 17 00:00:00 2001 From: "timedout (aka nexy7574)" Date: Mon, 1 Sep 2025 16:01:05 +0100 Subject: [PATCH] client: implement MSC4323 (#407) --- client.go | 28 ++++++++++++++++++++++++++++ requests.go | 10 ++++++++++ responses.go | 28 ++++++++++++++++++++++------ versions.go | 1 + 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/client.go b/client.go index 43fc3783..85b27923 100644 --- a/client.go +++ b/client.go @@ -2562,6 +2562,34 @@ func (cli *Client) ReportRoom(ctx context.Context, roomID id.RoomID, reason stri return err } +// UnstableGetSuspendedStatus uses MSC4323 to check if a user is suspended. +func (cli *Client) UnstableGetSuspendedStatus(ctx context.Context, userID id.UserID) (res *RespSuspended, err error) { + urlPath := cli.BuildClientURL("unstable", "uk.timedout.msc4323", "admin", "suspend", userID) + _, err = cli.MakeRequest(ctx, http.MethodGet, urlPath, nil, res) + return +} + +// UnstableGetLockStatus uses MSC4323 to check if a user is locked. +func (cli *Client) UnstableGetLockStatus(ctx context.Context, userID id.UserID) (res *RespLocked, err error) { + urlPath := cli.BuildClientURL("unstable", "uk.timedout.msc4323", "admin", "lock", userID) + _, err = cli.MakeRequest(ctx, http.MethodGet, urlPath, nil, res) + return +} + +// UnstableSetSuspendedStatus uses MSC4323 to set whether a user account is suspended. +func (cli *Client) UnstableSetSuspendedStatus(ctx context.Context, userID id.UserID, suspended bool) (res *RespSuspended, err error) { + urlPath := cli.BuildClientURL("unstable", "uk.timedout.msc4323", "admin", "suspend", userID) + _, err = cli.MakeRequest(ctx, http.MethodPut, urlPath, &ReqSuspend{Suspended: suspended}, res) + return +} + +// UnstableSetLockStatus uses MSC4323 to set whether a user account is locked. +func (cli *Client) UnstableSetLockStatus(ctx context.Context, userID id.UserID, locked bool) (res *RespLocked, err error) { + urlPath := cli.BuildClientURL("unstable", "uk.timedout.msc4323", "admin", "lock", userID) + _, err = cli.MakeRequest(ctx, http.MethodPut, urlPath, &ReqLocked{Locked: locked}, res) + return +} + func (cli *Client) AppservicePing(ctx context.Context, id, txnID string) (resp *RespAppservicePing, err error) { _, err = cli.MakeFullRequest(ctx, FullRequest{ Method: http.MethodPost, diff --git a/requests.go b/requests.go index 9871f044..4b5ce74b 100644 --- a/requests.go +++ b/requests.go @@ -596,3 +596,13 @@ func (rgr *ReqGetRelations) Query() map[string]string { } return query } + +// ReqSuspend is the request body for https://github.com/matrix-org/matrix-spec-proposals/pull/4323 +type ReqSuspend struct { + Suspended bool `json:"suspended"` +} + +// ReqLocked is the request body for https://github.com/matrix-org/matrix-spec-proposals/pull/4323 +type ReqLocked struct { + Locked bool `json:"locked"` +} diff --git a/responses.go b/responses.go index 5b97b293..8ab78373 100644 --- a/responses.go +++ b/responses.go @@ -494,12 +494,13 @@ type RespBeeperBatchSend struct { // RespCapabilities is the JSON response for https://spec.matrix.org/v1.3/client-server-api/#get_matrixclientv3capabilities type RespCapabilities struct { - RoomVersions *CapRoomVersions `json:"m.room_versions,omitempty"` - ChangePassword *CapBooleanTrue `json:"m.change_password,omitempty"` - SetDisplayname *CapBooleanTrue `json:"m.set_displayname,omitempty"` - SetAvatarURL *CapBooleanTrue `json:"m.set_avatar_url,omitempty"` - ThreePIDChanges *CapBooleanTrue `json:"m.3pid_changes,omitempty"` - GetLoginToken *CapBooleanTrue `json:"m.get_login_token,omitempty"` + RoomVersions *CapRoomVersions `json:"m.room_versions,omitempty"` + ChangePassword *CapBooleanTrue `json:"m.change_password,omitempty"` + SetDisplayname *CapBooleanTrue `json:"m.set_displayname,omitempty"` + SetAvatarURL *CapBooleanTrue `json:"m.set_avatar_url,omitempty"` + ThreePIDChanges *CapBooleanTrue `json:"m.3pid_changes,omitempty"` + GetLoginToken *CapBooleanTrue `json:"m.get_login_token,omitempty"` + UnstableAccountModeration *CapUnstableAccountModeration `json:"uk.timedout.msc4323,omitempty"` Custom map[string]interface{} `json:"-"` } @@ -608,6 +609,11 @@ func (vers *CapRoomVersions) IsAvailable(version string) bool { return available } +type CapUnstableAccountModeration struct { + Suspend bool `json:"suspend"` + Lock bool `json:"lock"` +} + type RespPublicRooms struct { Chunk []*PublicRoomInfo `json:"chunk"` NextBatch string `json:"next_batch,omitempty"` @@ -699,3 +705,13 @@ type RespGetRelations struct { PrevBatch string `json:"prev_batch,omitempty"` RecursionDepth int `json:"recursion_depth,omitempty"` } + +// RespSuspended is the response body for https://github.com/matrix-org/matrix-spec-proposals/pull/4323 +type RespSuspended struct { + Suspended bool `json:"suspended"` +} + +// RespLocked is the response body for https://github.com/matrix-org/matrix-spec-proposals/pull/4323 +type RespLocked struct { + Locked bool `json:"locked"` +} diff --git a/versions.go b/versions.go index f87bddda..c3be86cc 100644 --- a/versions.go +++ b/versions.go @@ -66,6 +66,7 @@ var ( FeatureMutualRooms = UnstableFeature{UnstableFlag: "uk.half-shot.msc2666.query_mutual_rooms"} FeatureUserRedaction = UnstableFeature{UnstableFlag: "org.matrix.msc4194"} FeatureViewRedactedContent = UnstableFeature{UnstableFlag: "fi.mau.msc2815"} + FeatureAccountModeration = UnstableFeature{UnstableFlag: "uk.timedout.msc4323"} BeeperFeatureHungry = UnstableFeature{UnstableFlag: "com.beeper.hungry"} BeeperFeatureBatchSending = UnstableFeature{UnstableFlag: "com.beeper.batch_sending"}