diff --git a/client.go b/client.go index 85b27923..034b1bc3 100644 --- a/client.go +++ b/client.go @@ -2562,6 +2562,15 @@ func (cli *Client) ReportRoom(ctx context.Context, roomID id.RoomID, reason stri return err } +// AdminWhoIs fetches session information belonging to a specific user. Typically requires being a server admin. +// +// https://spec.matrix.org/v1.15/client-server-api/#get_matrixclientv3adminwhoisuserid +func (cli *Client) AdminWhoIs(ctx context.Context, userID id.UserID) (resp RespWhoIs, err error) { + urlPath := cli.BuildClientURL("v3", "admin", "whois", userID) + _, err = cli.MakeRequest(ctx, http.MethodGet, urlPath, nil, &resp) + return +} + // 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) diff --git a/responses.go b/responses.go index 8ab78373..ae41084e 100644 --- a/responses.go +++ b/responses.go @@ -715,3 +715,23 @@ type RespSuspended struct { type RespLocked struct { Locked bool `json:"locked"` } + +type ConnectionInfo struct { + IP string `json:"ip,omitempty"` + LastSeen jsontime.UnixMilli `json:"last_seen,omitempty"` + UserAgent string `json:"user_agent,omitempty"` +} + +type SessionInfo struct { + Connections []ConnectionInfo `json:"connections,omitempty"` +} + +type DeviceInfo struct { + Sessions []SessionInfo `json:"sessions,omitempty"` +} + +// RespWhoIs is the response body for https://spec.matrix.org/v1.15/client-server-api/#get_matrixclientv3adminwhoisuserid +type RespWhoIs struct { + UserID id.UserID `json:"user_id,omitempty"` + Devices map[id.Device]DeviceInfo `json:"devices,omitempty"` +}