LCOV - code coverage report
Current view: top level - lib/matrix_api_lite/generated - api.dart (source / functions) Coverage Total Hit
Test: merged.info Lines: 30.7 % 2129 653
Test Date: 2025-10-13 02:23:18 Functions: - 0 0

            Line data    Source code
       1              : import 'dart:convert';
       2              : import 'dart:typed_data';
       3              : 
       4              : import 'package:http/http.dart';
       5              : 
       6              : import 'package:matrix/matrix_api_lite/generated/fixed_model.dart';
       7              : import 'package:matrix/matrix_api_lite/generated/internal.dart';
       8              : import 'package:matrix/matrix_api_lite/generated/model.dart';
       9              : import 'package:matrix/matrix_api_lite/model/auth/authentication_data.dart';
      10              : import 'package:matrix/matrix_api_lite/model/auth/authentication_identifier.dart';
      11              : import 'package:matrix/matrix_api_lite/model/matrix_event.dart';
      12              : import 'package:matrix/matrix_api_lite/model/matrix_keys.dart';
      13              : import 'package:matrix/matrix_api_lite/model/sync_update.dart';
      14              : 
      15              : // ignore_for_file: provide_deprecation_message
      16              : 
      17              : class Api {
      18              :   Client httpClient;
      19              :   Uri? baseUri;
      20              :   String? bearerToken;
      21           48 :   Api({Client? httpClient, this.baseUri, this.bearerToken})
      22            0 :       : httpClient = httpClient ?? Client();
      23            1 :   Never unexpectedResponse(BaseResponse response, Uint8List body) {
      24            1 :     throw Exception('http error response');
      25              :   }
      26              : 
      27            0 :   Never bodySizeExceeded(int expected, int actual) {
      28            0 :     throw Exception('body size $actual exceeded $expected');
      29              :   }
      30              : 
      31              :   /// Gets discovery information about the domain. The file may include
      32              :   /// additional keys, which MUST follow the Java package naming convention,
      33              :   /// e.g. `com.example.myapp.property`. This ensures property names are
      34              :   /// suitably namespaced for each application and reduces the risk of
      35              :   /// clashes.
      36              :   ///
      37              :   /// **NOTE:**
      38              :   /// This endpoint should be accessed with the hostname of the homeserver's
      39              :   /// [server name](https://spec.matrix.org/unstable/appendices/#server-name) by making a
      40              :   /// GET request to `https://hostname/.well-known/matrix/client`.
      41              :   ///
      42              :   ///
      43              :   /// Note that this endpoint is not necessarily handled by the homeserver,
      44              :   /// but by another webserver, to be used for discovering the homeserver URL.
      45            0 :   Future<DiscoveryInformation> getWellknown() async {
      46            0 :     final requestUri = Uri(path: '.well-known/matrix/client');
      47            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
      48            0 :     final response = await httpClient.send(request);
      49            0 :     final responseBody = await response.stream.toBytes();
      50            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
      51            0 :     final responseString = utf8.decode(responseBody);
      52            0 :     final json = jsonDecode(responseString);
      53            0 :     return DiscoveryInformation.fromJson(json as Map<String, Object?>);
      54              :   }
      55              : 
      56              :   /// Gets server admin contact and support page of the domain.
      57              :   ///
      58              :   /// **NOTE:**
      59              :   /// Like the [well-known discovery URI](https://spec.matrix.org/unstable/client-server-api/#well-known-uris),
      60              :   /// this endpoint should be accessed with the hostname of the homeserver's
      61              :   /// [server name](https://spec.matrix.org/unstable/appendices/#server-name) by making a
      62              :   /// GET request to `https://hostname/.well-known/matrix/support`.
      63              :   ///
      64              :   ///
      65              :   /// Note that this endpoint is not necessarily handled by the homeserver.
      66              :   /// It may be served by another webserver, used for discovering support
      67              :   /// information for the homeserver.
      68            0 :   Future<GetWellknownSupportResponse> getWellknownSupport() async {
      69            0 :     final requestUri = Uri(path: '.well-known/matrix/support');
      70            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
      71            0 :     final response = await httpClient.send(request);
      72            0 :     final responseBody = await response.stream.toBytes();
      73            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
      74            0 :     final responseString = utf8.decode(responseBody);
      75            0 :     final json = jsonDecode(responseString);
      76            0 :     return GetWellknownSupportResponse.fromJson(json as Map<String, Object?>);
      77              :   }
      78              : 
      79              :   /// This API asks the homeserver to call the
      80              :   /// [`/_matrix/app/v1/ping`](https://spec.matrix.org/unstable/application-service-api/#post_matrixappv1ping) endpoint on the
      81              :   /// application service to ensure that the homeserver can communicate
      82              :   /// with the application service.
      83              :   ///
      84              :   /// This API requires the use of an application service access token (`as_token`)
      85              :   /// instead of a typical client's access token. This API cannot be invoked by
      86              :   /// users who are not identified as application services. Additionally, the
      87              :   /// appservice ID in the path must be the same as the appservice whose `as_token`
      88              :   /// is being used.
      89              :   ///
      90              :   /// [appserviceId] The appservice ID of the appservice to ping. This must be the same
      91              :   /// as the appservice whose `as_token` is being used to authenticate the
      92              :   /// request.
      93              :   ///
      94              :   /// [transactionId] An optional transaction ID that is passed through to the `/_matrix/app/v1/ping` call.
      95              :   ///
      96              :   /// returns `duration_ms`:
      97              :   /// The duration in milliseconds that the
      98              :   /// [`/_matrix/app/v1/ping`](https://spec.matrix.org/unstable/application-service-api/#post_matrixappv1ping)
      99              :   /// request took from the homeserver's point of view.
     100            0 :   Future<int> pingAppservice(
     101              :     String appserviceId, {
     102              :     String? transactionId,
     103              :   }) async {
     104            0 :     final requestUri = Uri(
     105              :       path:
     106            0 :           '_matrix/client/v1/appservice/${Uri.encodeComponent(appserviceId)}/ping',
     107              :     );
     108            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
     109            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     110            0 :     request.headers['content-type'] = 'application/json';
     111            0 :     request.bodyBytes = utf8.encode(
     112            0 :       jsonEncode({
     113            0 :         if (transactionId != null) 'transaction_id': transactionId,
     114              :       }),
     115              :     );
     116            0 :     final response = await httpClient.send(request);
     117            0 :     final responseBody = await response.stream.toBytes();
     118            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     119            0 :     final responseString = utf8.decode(responseBody);
     120            0 :     final json = jsonDecode(responseString);
     121            0 :     return json['duration_ms'] as int;
     122              :   }
     123              : 
     124              :   /// Gets the OAuth 2.0 authorization server metadata, as defined in
     125              :   /// [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414), including the
     126              :   /// endpoint URLs and the supported parameters that can be used by the
     127              :   /// clients.
     128              :   ///
     129              :   /// This endpoint definition includes only the fields that are meaningful in
     130              :   /// the context of the Matrix specification. The full list of possible
     131              :   /// fields is available in the [OAuth Authorization Server Metadata
     132              :   /// registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata),
     133              :   /// and normative definitions of them are available in their respective
     134              :   /// RFCs.
     135              :   ///
     136              :   /// **NOTE:**
     137              :   /// The authorization server metadata is relatively large and may change
     138              :   /// over time. Clients should:
     139              :   ///
     140              :   /// - Cache the metadata appropriately based on HTTP caching headers
     141              :   /// - Refetch the metadata if it is stale
     142              :   ///
     143            0 :   Future<GetAuthMetadataResponse> getAuthMetadata() async {
     144            0 :     final requestUri = Uri(path: '_matrix/client/v1/auth_metadata');
     145            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     146            0 :     final response = await httpClient.send(request);
     147            0 :     final responseBody = await response.stream.toBytes();
     148            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     149            0 :     final responseString = utf8.decode(responseBody);
     150            0 :     final json = jsonDecode(responseString);
     151            0 :     return GetAuthMetadataResponse.fromJson(json as Map<String, Object?>);
     152              :   }
     153              : 
     154              :   /// Optional endpoint - the server is not required to implement this endpoint if it does not
     155              :   /// intend to use or support this functionality.
     156              :   ///
     157              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api).
     158              :   ///
     159              :   /// An already-authenticated client can call this endpoint to generate a single-use, time-limited,
     160              :   /// token for an unauthenticated client to log in with, becoming logged in as the same user which
     161              :   /// called this endpoint. The unauthenticated client uses the generated token in a `m.login.token`
     162              :   /// login flow with the homeserver.
     163              :   ///
     164              :   /// Clients, both authenticated and unauthenticated, might wish to hide user interface which exposes
     165              :   /// this feature if the server is not offering it. Authenticated clients can check for support on
     166              :   /// a per-user basis with the [`m.get_login_token`](https://spec.matrix.org/unstable/client-server-api/#mget_login_token-capability) capability,
     167              :   /// while unauthenticated clients can detect server support by looking for an `m.login.token` login
     168              :   /// flow with `get_login_token: true` on [`GET /login`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3login).
     169              :   ///
     170              :   /// In v1.7 of the specification, transmission of the generated token to an unauthenticated client is
     171              :   /// left as an implementation detail. Future MSCs such as [MSC3906](https://github.com/matrix-org/matrix-spec-proposals/pull/3906)
     172              :   /// might standardise a way to transmit the token between clients.
     173              :   ///
     174              :   /// The generated token MUST only be valid for a single login, enforced by the server. Clients which
     175              :   /// intend to log in multiple devices must generate a token for each.
     176              :   ///
     177              :   /// With other User-Interactive Authentication (UIA)-supporting endpoints, servers sometimes do not re-prompt
     178              :   /// for verification if the session recently passed UIA. For this endpoint, servers MUST always re-prompt
     179              :   /// the user for verification to ensure explicit consent is gained for each additional client.
     180              :   ///
     181              :   /// Servers are encouraged to apply stricter than normal rate limiting to this endpoint, such as maximum
     182              :   /// of 1 request per minute.
     183              :   ///
     184              :   /// [auth] Additional authentication information for the user-interactive authentication API.
     185            0 :   Future<GenerateLoginTokenResponse> generateLoginToken({
     186              :     AuthenticationData? auth,
     187              :   }) async {
     188            0 :     final requestUri = Uri(path: '_matrix/client/v1/login/get_token');
     189            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
     190            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     191            0 :     request.headers['content-type'] = 'application/json';
     192            0 :     request.bodyBytes = utf8.encode(
     193            0 :       jsonEncode({
     194            0 :         if (auth != null) 'auth': auth.toJson(),
     195              :       }),
     196              :     );
     197            0 :     final response = await httpClient.send(request);
     198            0 :     final responseBody = await response.stream.toBytes();
     199            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     200            0 :     final responseString = utf8.decode(responseBody);
     201            0 :     final json = jsonDecode(responseString);
     202            0 :     return GenerateLoginTokenResponse.fromJson(json as Map<String, Object?>);
     203              :   }
     204              : 
     205              :   /// This endpoint allows clients to retrieve the configuration of the content
     206              :   /// repository, such as upload limitations.
     207              :   /// Clients SHOULD use this as a guide when using content repository endpoints.
     208              :   /// All values are intentionally left optional. Clients SHOULD follow
     209              :   /// the advice given in the field description when the field is not available.
     210              :   ///
     211              :   /// **NOTE:**
     212              :   /// Both clients and server administrators should be aware that proxies
     213              :   /// between the client and the server may affect the apparent behaviour of content
     214              :   /// repository APIs, for example, proxies may enforce a lower upload size limit
     215              :   /// than is advertised by the server on this endpoint.
     216              :   ///
     217            4 :   Future<MediaConfig> getConfigAuthed() async {
     218            4 :     final requestUri = Uri(path: '_matrix/client/v1/media/config');
     219           12 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     220           16 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     221            8 :     final response = await httpClient.send(request);
     222            8 :     final responseBody = await response.stream.toBytes();
     223            8 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     224            4 :     final responseString = utf8.decode(responseBody);
     225            4 :     final json = jsonDecode(responseString);
     226            4 :     return MediaConfig.fromJson(json as Map<String, Object?>);
     227              :   }
     228              : 
     229              :   /// **NOTE:**
     230              :   /// Clients SHOULD NOT generate or use URLs which supply the access token in
     231              :   /// the query string. These URLs may be copied by users verbatim and provided
     232              :   /// in a chat message to another user, disclosing the sender's access token.
     233              :   ///
     234              :   ///
     235              :   /// Clients MAY be redirected using the 307/308 responses below to download
     236              :   /// the request object. This is typical when the homeserver uses a Content
     237              :   /// Delivery Network (CDN).
     238              :   ///
     239              :   /// [serverName] The server name from the `mxc://` URI (the authority component).
     240              :   ///
     241              :   ///
     242              :   /// [mediaId] The media ID from the `mxc://` URI (the path component).
     243              :   ///
     244              :   ///
     245              :   /// [timeoutMs] The maximum number of milliseconds that the client is willing to wait to
     246              :   /// start receiving data, in the case that the content has not yet been
     247              :   /// uploaded. The default value is 20000 (20 seconds). The content
     248              :   /// repository SHOULD impose a maximum value for this parameter. The
     249              :   /// content repository MAY respond before the timeout.
     250              :   ///
     251            0 :   Future<FileResponse> getContentAuthed(
     252              :     String serverName,
     253              :     String mediaId, {
     254              :     int? timeoutMs,
     255              :   }) async {
     256            0 :     final requestUri = Uri(
     257              :       path:
     258            0 :           '_matrix/client/v1/media/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}',
     259            0 :       queryParameters: {
     260            0 :         if (timeoutMs != null) 'timeout_ms': timeoutMs.toString(),
     261              :       },
     262              :     );
     263            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     264            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     265            0 :     final response = await httpClient.send(request);
     266            0 :     final responseBody = await response.stream.toBytes();
     267            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     268            0 :     return FileResponse(
     269            0 :       contentType: response.headers['content-type'],
     270              :       data: responseBody,
     271              :     );
     272              :   }
     273              : 
     274              :   /// This will download content from the content repository (same as
     275              :   /// the previous endpoint) but replaces the target file name with the one
     276              :   /// provided by the caller.
     277              :   ///
     278              :   /// **NOTE:**
     279              :   /// Clients SHOULD NOT generate or use URLs which supply the access token in
     280              :   /// the query string. These URLs may be copied by users verbatim and provided
     281              :   /// in a chat message to another user, disclosing the sender's access token.
     282              :   ///
     283              :   ///
     284              :   /// Clients MAY be redirected using the 307/308 responses below to download
     285              :   /// the request object. This is typical when the homeserver uses a Content
     286              :   /// Delivery Network (CDN).
     287              :   ///
     288              :   /// [serverName] The server name from the `mxc://` URI (the authority component).
     289              :   ///
     290              :   ///
     291              :   /// [mediaId] The media ID from the `mxc://` URI (the path component).
     292              :   ///
     293              :   ///
     294              :   /// [fileName] A filename to give in the `Content-Disposition` header.
     295              :   ///
     296              :   /// [timeoutMs] The maximum number of milliseconds that the client is willing to wait to
     297              :   /// start receiving data, in the case that the content has not yet been
     298              :   /// uploaded. The default value is 20000 (20 seconds). The content
     299              :   /// repository SHOULD impose a maximum value for this parameter. The
     300              :   /// content repository MAY respond before the timeout.
     301              :   ///
     302            0 :   Future<FileResponse> getContentOverrideNameAuthed(
     303              :     String serverName,
     304              :     String mediaId,
     305              :     String fileName, {
     306              :     int? timeoutMs,
     307              :   }) async {
     308            0 :     final requestUri = Uri(
     309              :       path:
     310            0 :           '_matrix/client/v1/media/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}/${Uri.encodeComponent(fileName)}',
     311            0 :       queryParameters: {
     312            0 :         if (timeoutMs != null) 'timeout_ms': timeoutMs.toString(),
     313              :       },
     314              :     );
     315            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     316            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     317            0 :     final response = await httpClient.send(request);
     318            0 :     final responseBody = await response.stream.toBytes();
     319            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     320            0 :     return FileResponse(
     321            0 :       contentType: response.headers['content-type'],
     322              :       data: responseBody,
     323              :     );
     324              :   }
     325              : 
     326              :   /// Get information about a URL for the client. Typically this is called when a
     327              :   /// client sees a URL in a message and wants to render a preview for the user.
     328              :   ///
     329              :   /// **NOTE:**
     330              :   /// Clients should consider avoiding this endpoint for URLs posted in encrypted
     331              :   /// rooms. Encrypted rooms often contain more sensitive information the users
     332              :   /// do not want to share with the homeserver, and this can mean that the URLs
     333              :   /// being shared should also not be shared with the homeserver.
     334              :   ///
     335              :   ///
     336              :   /// [url] The URL to get a preview of.
     337              :   ///
     338              :   /// [ts] The preferred point in time to return a preview for. The server may
     339              :   /// return a newer version if it does not have the requested version
     340              :   /// available.
     341            0 :   Future<PreviewForUrl> getUrlPreviewAuthed(Uri url, {int? ts}) async {
     342            0 :     final requestUri = Uri(
     343              :       path: '_matrix/client/v1/media/preview_url',
     344            0 :       queryParameters: {
     345            0 :         'url': url.toString(),
     346            0 :         if (ts != null) 'ts': ts.toString(),
     347              :       },
     348              :     );
     349            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     350            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     351            0 :     final response = await httpClient.send(request);
     352            0 :     final responseBody = await response.stream.toBytes();
     353            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     354            0 :     final responseString = utf8.decode(responseBody);
     355            0 :     final json = jsonDecode(responseString);
     356            0 :     return PreviewForUrl.fromJson(json as Map<String, Object?>);
     357              :   }
     358              : 
     359              :   /// Download a thumbnail of content from the content repository.
     360              :   /// See the [Thumbnails](https://spec.matrix.org/unstable/client-server-api/#thumbnails) section for more information.
     361              :   ///
     362              :   /// **NOTE:**
     363              :   /// Clients SHOULD NOT generate or use URLs which supply the access token in
     364              :   /// the query string. These URLs may be copied by users verbatim and provided
     365              :   /// in a chat message to another user, disclosing the sender's access token.
     366              :   ///
     367              :   ///
     368              :   /// Clients MAY be redirected using the 307/308 responses below to download
     369              :   /// the request object. This is typical when the homeserver uses a Content
     370              :   /// Delivery Network (CDN).
     371              :   ///
     372              :   /// [serverName] The server name from the `mxc://` URI (the authority component).
     373              :   ///
     374              :   ///
     375              :   /// [mediaId] The media ID from the `mxc://` URI (the path component).
     376              :   ///
     377              :   ///
     378              :   /// [width] The *desired* width of the thumbnail. The actual thumbnail may be
     379              :   /// larger than the size specified.
     380              :   ///
     381              :   /// [height] The *desired* height of the thumbnail. The actual thumbnail may be
     382              :   /// larger than the size specified.
     383              :   ///
     384              :   /// [method] The desired resizing method. See the [Thumbnails](https://spec.matrix.org/unstable/client-server-api/#thumbnails)
     385              :   /// section for more information.
     386              :   ///
     387              :   /// [timeoutMs] The maximum number of milliseconds that the client is willing to wait to
     388              :   /// start receiving data, in the case that the content has not yet been
     389              :   /// uploaded. The default value is 20000 (20 seconds). The content
     390              :   /// repository SHOULD impose a maximum value for this parameter. The
     391              :   /// content repository MAY respond before the timeout.
     392              :   ///
     393              :   ///
     394              :   /// [animated] Indicates preference for an animated thumbnail from the server, if possible. Animated
     395              :   /// thumbnails typically use the content types `image/gif`, `image/png` (with APNG format),
     396              :   /// `image/apng`, and `image/webp` instead of the common static `image/png` or `image/jpeg`
     397              :   /// content types.
     398              :   ///
     399              :   /// When `true`, the server SHOULD return an animated thumbnail if possible and supported.
     400              :   /// When `false`, the server MUST NOT return an animated thumbnail. For example, returning a
     401              :   /// static `image/png` or `image/jpeg` thumbnail. When not provided, the server SHOULD NOT
     402              :   /// return an animated thumbnail.
     403              :   ///
     404              :   /// Servers SHOULD prefer to return `image/webp` thumbnails when supporting animation.
     405              :   ///
     406              :   /// When `true` and the media cannot be animated, such as in the case of a JPEG or PDF, the
     407              :   /// server SHOULD behave as though `animated` is `false`.
     408              :   ///
     409            0 :   Future<FileResponse> getContentThumbnailAuthed(
     410              :     String serverName,
     411              :     String mediaId,
     412              :     int width,
     413              :     int height, {
     414              :     Method? method,
     415              :     int? timeoutMs,
     416              :     bool? animated,
     417              :   }) async {
     418            0 :     final requestUri = Uri(
     419              :       path:
     420            0 :           '_matrix/client/v1/media/thumbnail/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}',
     421            0 :       queryParameters: {
     422            0 :         'width': width.toString(),
     423            0 :         'height': height.toString(),
     424            0 :         if (method != null) 'method': method.name,
     425            0 :         if (timeoutMs != null) 'timeout_ms': timeoutMs.toString(),
     426            0 :         if (animated != null) 'animated': animated.toString(),
     427              :       },
     428              :     );
     429            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     430            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     431            0 :     final response = await httpClient.send(request);
     432            0 :     final responseBody = await response.stream.toBytes();
     433            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     434            0 :     return FileResponse(
     435            0 :       contentType: response.headers['content-type'],
     436              :       data: responseBody,
     437              :     );
     438              :   }
     439              : 
     440              :   /// Queries the server to determine if a given registration token is still
     441              :   /// valid at the time of request. This is a point-in-time check where the
     442              :   /// token might still expire by the time it is used.
     443              :   ///
     444              :   /// Servers should be sure to rate limit this endpoint to avoid brute force
     445              :   /// attacks.
     446              :   ///
     447              :   /// [token] The token to check validity of.
     448              :   ///
     449              :   /// returns `valid`:
     450              :   /// True if the token is still valid, false otherwise. This should
     451              :   /// additionally be false if the token is not a recognised token by
     452              :   /// the server.
     453            0 :   Future<bool> registrationTokenValidity(String token) async {
     454            0 :     final requestUri = Uri(
     455              :       path: '_matrix/client/v1/register/m.login.registration_token/validity',
     456            0 :       queryParameters: {
     457              :         'token': token,
     458              :       },
     459              :     );
     460            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     461            0 :     final response = await httpClient.send(request);
     462            0 :     final responseBody = await response.stream.toBytes();
     463            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     464            0 :     final responseString = utf8.decode(responseBody);
     465            0 :     final json = jsonDecode(responseString);
     466            0 :     return json['valid'] as bool;
     467              :   }
     468              : 
     469              :   /// Retrieves a summary for a room.
     470              :   ///
     471              :   /// Clients should note that requests for rooms where the user's membership
     472              :   /// is `invite` or `knock` might yield outdated, partial or even no data
     473              :   /// since the server may not have access to the current state of the room.
     474              :   ///
     475              :   /// Servers MAY allow unauthenticated access to this API if at least one of
     476              :   /// the following conditions holds true:
     477              :   ///
     478              :   /// - The room has a [join rule](#mroomjoin_rules) of `public`, `knock` or
     479              :   ///   `knock_restricted`.
     480              :   /// - The room has a `world_readable` [history visibility](#room-history-visibility).
     481              :   ///
     482              :   /// Servers should consider rate limiting requests that require a federation
     483              :   /// request more heavily if the client is unauthenticated.
     484              :   ///
     485              :   /// [roomIdOrAlias] The room identifier or alias to summarise.
     486              :   ///
     487              :   /// [via] The servers to attempt to request the summary from when
     488              :   /// the local server cannot generate it (for instance, because
     489              :   /// it has no local user in the room).
     490            0 :   Future<GetRoomSummaryResponse$3> getRoomSummary(
     491              :     String roomIdOrAlias, {
     492              :     List<String>? via,
     493              :   }) async {
     494            0 :     final requestUri = Uri(
     495              :       path:
     496            0 :           '_matrix/client/v1/room_summary/${Uri.encodeComponent(roomIdOrAlias)}',
     497            0 :       queryParameters: {
     498            0 :         if (via != null) 'via': via,
     499              :       },
     500              :     );
     501            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     502            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     503            0 :     final response = await httpClient.send(request);
     504            0 :     final responseBody = await response.stream.toBytes();
     505            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     506            0 :     final responseString = utf8.decode(responseBody);
     507            0 :     final json = jsonDecode(responseString);
     508            0 :     return GetRoomSummaryResponse$3.fromJson(json as Map<String, Object?>);
     509              :   }
     510              : 
     511              :   /// Paginates over the space tree in a depth-first manner to locate child rooms of a given space.
     512              :   ///
     513              :   /// Where a child room is unknown to the local server, federation is used to fill in the details.
     514              :   /// The servers listed in the `via` array should be contacted to attempt to fill in missing rooms.
     515              :   ///
     516              :   /// Only [`m.space.child`](https://spec.matrix.org/unstable/client-server-api/#mspacechild) state events of the room are considered.
     517              :   /// Invalid child rooms and parent events are not covered by this endpoint.
     518              :   ///
     519              :   /// [roomId] The room ID of the space to get a hierarchy for.
     520              :   ///
     521              :   /// [suggestedOnly] Optional (default `false`) flag to indicate whether or not the server should only consider
     522              :   /// suggested rooms. Suggested rooms are annotated in their [`m.space.child`](https://spec.matrix.org/unstable/client-server-api/#mspacechild)
     523              :   /// event contents.
     524              :   ///
     525              :   /// [limit] Optional limit for the maximum number of rooms to include per response. Must be an integer
     526              :   /// greater than zero.
     527              :   ///
     528              :   /// Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
     529              :   ///
     530              :   /// [maxDepth] Optional limit for how far to go into the space. Must be a non-negative integer.
     531              :   ///
     532              :   /// When reached, no further child rooms will be returned.
     533              :   ///
     534              :   /// Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
     535              :   ///
     536              :   /// [from] A pagination token from a previous result. If specified, `max_depth` and `suggested_only` cannot
     537              :   /// be changed from the first request.
     538            0 :   Future<GetSpaceHierarchyResponse> getSpaceHierarchy(
     539              :     String roomId, {
     540              :     bool? suggestedOnly,
     541              :     int? limit,
     542              :     int? maxDepth,
     543              :     String? from,
     544              :   }) async {
     545            0 :     final requestUri = Uri(
     546            0 :       path: '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/hierarchy',
     547            0 :       queryParameters: {
     548            0 :         if (suggestedOnly != null) 'suggested_only': suggestedOnly.toString(),
     549            0 :         if (limit != null) 'limit': limit.toString(),
     550            0 :         if (maxDepth != null) 'max_depth': maxDepth.toString(),
     551            0 :         if (from != null) 'from': from,
     552              :       },
     553              :     );
     554            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     555            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     556            0 :     final response = await httpClient.send(request);
     557            0 :     final responseBody = await response.stream.toBytes();
     558            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     559            0 :     final responseString = utf8.decode(responseBody);
     560            0 :     final json = jsonDecode(responseString);
     561            0 :     return GetSpaceHierarchyResponse.fromJson(json as Map<String, Object?>);
     562              :   }
     563              : 
     564              :   /// Retrieve all of the child events for a given parent event.
     565              :   ///
     566              :   /// Note that when paginating the `from` token should be "after" the `to` token in
     567              :   /// terms of topological ordering, because it is only possible to paginate "backwards"
     568              :   /// through events, starting at `from`.
     569              :   ///
     570              :   /// For example, passing a `from` token from page 2 of the results, and a `to` token
     571              :   /// from page 1, would return the empty set. The caller can use a `from` token from
     572              :   /// page 1 and a `to` token from page 2 to paginate over the same range, however.
     573              :   ///
     574              :   /// [roomId] The ID of the room containing the parent event.
     575              :   ///
     576              :   /// [eventId] The ID of the parent event whose child events are to be returned.
     577              :   ///
     578              :   /// [from] The pagination token to start returning results from. If not supplied, results
     579              :   /// start at the most recent topological event known to the server.
     580              :   ///
     581              :   /// Can be a `next_batch` or `prev_batch` token from a previous call, or a returned
     582              :   /// `start` token from [`/messages`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidmessages),
     583              :   /// or a `next_batch` token from [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync).
     584              :   ///
     585              :   /// [to] The pagination token to stop returning results at. If not supplied, results
     586              :   /// continue up to `limit` or until there are no more events.
     587              :   ///
     588              :   /// Like `from`, this can be a previous token from a prior call to this endpoint
     589              :   /// or from `/messages` or `/sync`.
     590              :   ///
     591              :   /// [limit] The maximum number of results to return in a single `chunk`. The server can
     592              :   /// and should apply a maximum value to this parameter to avoid large responses.
     593              :   ///
     594              :   /// Similarly, the server should apply a default value when not supplied.
     595              :   ///
     596              :   /// [dir] Optional (default `b`) direction to return events from. If this is set to `f`, events
     597              :   /// will be returned in chronological order starting at `from`. If it
     598              :   /// is set to `b`, events will be returned in *reverse* chronological
     599              :   /// order, again starting at `from`.
     600              :   ///
     601              :   /// [recurse] Whether to additionally include events which only relate indirectly to the
     602              :   /// given event, i.e. events related to the given event via two or more direct relationships.
     603              :   ///
     604              :   /// If set to `false`, only events which have a direct relation with the given
     605              :   /// event will be included.
     606              :   ///
     607              :   /// If set to `true`, events which have an indirect relation with the given event
     608              :   /// will be included additionally up to a certain depth level. Homeservers SHOULD traverse
     609              :   /// at least 3 levels of relationships. Implementations MAY perform more but MUST be careful
     610              :   /// to not infinitely recurse.
     611              :   ///
     612              :   /// The default value is `false`.
     613            0 :   Future<GetRelatingEventsResponse> getRelatingEvents(
     614              :     String roomId,
     615              :     String eventId, {
     616              :     String? from,
     617              :     String? to,
     618              :     int? limit,
     619              :     Direction? dir,
     620              :     bool? recurse,
     621              :   }) async {
     622            0 :     final requestUri = Uri(
     623              :       path:
     624            0 :           '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/relations/${Uri.encodeComponent(eventId)}',
     625            0 :       queryParameters: {
     626            0 :         if (from != null) 'from': from,
     627            0 :         if (to != null) 'to': to,
     628            0 :         if (limit != null) 'limit': limit.toString(),
     629            0 :         if (dir != null) 'dir': dir.name,
     630            0 :         if (recurse != null) 'recurse': recurse.toString(),
     631              :       },
     632              :     );
     633            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     634            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     635            0 :     final response = await httpClient.send(request);
     636            0 :     final responseBody = await response.stream.toBytes();
     637            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     638            0 :     final responseString = utf8.decode(responseBody);
     639            0 :     final json = jsonDecode(responseString);
     640            0 :     return GetRelatingEventsResponse.fromJson(json as Map<String, Object?>);
     641              :   }
     642              : 
     643              :   /// Retrieve all of the child events for a given parent event which relate to the parent
     644              :   /// using the given `relType`.
     645              :   ///
     646              :   /// Note that when paginating the `from` token should be "after" the `to` token in
     647              :   /// terms of topological ordering, because it is only possible to paginate "backwards"
     648              :   /// through events, starting at `from`.
     649              :   ///
     650              :   /// For example, passing a `from` token from page 2 of the results, and a `to` token
     651              :   /// from page 1, would return the empty set. The caller can use a `from` token from
     652              :   /// page 1 and a `to` token from page 2 to paginate over the same range, however.
     653              :   ///
     654              :   /// [roomId] The ID of the room containing the parent event.
     655              :   ///
     656              :   /// [eventId] The ID of the parent event whose child events are to be returned.
     657              :   ///
     658              :   /// [relType] The [relationship type](https://spec.matrix.org/unstable/client-server-api/#relationship-types) to search for.
     659              :   ///
     660              :   /// [from] The pagination token to start returning results from. If not supplied, results
     661              :   /// start at the most recent topological event known to the server.
     662              :   ///
     663              :   /// Can be a `next_batch` or `prev_batch` token from a previous call, or a returned
     664              :   /// `start` token from [`/messages`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidmessages),
     665              :   /// or a `next_batch` token from [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync).
     666              :   ///
     667              :   /// [to] The pagination token to stop returning results at. If not supplied, results
     668              :   /// continue up to `limit` or until there are no more events.
     669              :   ///
     670              :   /// Like `from`, this can be a previous token from a prior call to this endpoint
     671              :   /// or from `/messages` or `/sync`.
     672              :   ///
     673              :   /// [limit] The maximum number of results to return in a single `chunk`. The server can
     674              :   /// and should apply a maximum value to this parameter to avoid large responses.
     675              :   ///
     676              :   /// Similarly, the server should apply a default value when not supplied.
     677              :   ///
     678              :   /// [dir] Optional (default `b`) direction to return events from. If this is set to `f`, events
     679              :   /// will be returned in chronological order starting at `from`. If it
     680              :   /// is set to `b`, events will be returned in *reverse* chronological
     681              :   /// order, again starting at `from`.
     682              :   ///
     683              :   /// [recurse] Whether to additionally include events which only relate indirectly to the
     684              :   /// given event, i.e. events related to the given event via two or more direct relationships.
     685              :   ///
     686              :   /// If set to `false`, only events which have a direct relation with the given
     687              :   /// event will be included.
     688              :   ///
     689              :   /// If set to `true`, events which have an indirect relation with the given event
     690              :   /// will be included additionally up to a certain depth level. Homeservers SHOULD traverse
     691              :   /// at least 3 levels of relationships. Implementations MAY perform more but MUST be careful
     692              :   /// to not infinitely recurse.
     693              :   ///
     694              :   /// The default value is `false`.
     695            0 :   Future<GetRelatingEventsWithRelTypeResponse> getRelatingEventsWithRelType(
     696              :     String roomId,
     697              :     String eventId,
     698              :     String relType, {
     699              :     String? from,
     700              :     String? to,
     701              :     int? limit,
     702              :     Direction? dir,
     703              :     bool? recurse,
     704              :   }) async {
     705            0 :     final requestUri = Uri(
     706              :       path:
     707            0 :           '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/relations/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(relType)}',
     708            0 :       queryParameters: {
     709            0 :         if (from != null) 'from': from,
     710            0 :         if (to != null) 'to': to,
     711            0 :         if (limit != null) 'limit': limit.toString(),
     712            0 :         if (dir != null) 'dir': dir.name,
     713            0 :         if (recurse != null) 'recurse': recurse.toString(),
     714              :       },
     715              :     );
     716            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     717            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     718            0 :     final response = await httpClient.send(request);
     719            0 :     final responseBody = await response.stream.toBytes();
     720            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     721            0 :     final responseString = utf8.decode(responseBody);
     722            0 :     final json = jsonDecode(responseString);
     723            0 :     return GetRelatingEventsWithRelTypeResponse.fromJson(
     724              :       json as Map<String, Object?>,
     725              :     );
     726              :   }
     727              : 
     728              :   /// Retrieve all of the child events for a given parent event which relate to the parent
     729              :   /// using the given `relType` and have the given `eventType`.
     730              :   ///
     731              :   /// Note that when paginating the `from` token should be "after" the `to` token in
     732              :   /// terms of topological ordering, because it is only possible to paginate "backwards"
     733              :   /// through events, starting at `from`.
     734              :   ///
     735              :   /// For example, passing a `from` token from page 2 of the results, and a `to` token
     736              :   /// from page 1, would return the empty set. The caller can use a `from` token from
     737              :   /// page 1 and a `to` token from page 2 to paginate over the same range, however.
     738              :   ///
     739              :   /// [roomId] The ID of the room containing the parent event.
     740              :   ///
     741              :   /// [eventId] The ID of the parent event whose child events are to be returned.
     742              :   ///
     743              :   /// [relType] The [relationship type](https://spec.matrix.org/unstable/client-server-api/#relationship-types) to search for.
     744              :   ///
     745              :   /// [eventType] The event type of child events to search for.
     746              :   ///
     747              :   /// Note that in encrypted rooms this will typically always be `m.room.encrypted`
     748              :   /// regardless of the event type contained within the encrypted payload.
     749              :   ///
     750              :   /// [from] The pagination token to start returning results from. If not supplied, results
     751              :   /// start at the most recent topological event known to the server.
     752              :   ///
     753              :   /// Can be a `next_batch` or `prev_batch` token from a previous call, or a returned
     754              :   /// `start` token from [`/messages`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidmessages),
     755              :   /// or a `next_batch` token from [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync).
     756              :   ///
     757              :   /// [to] The pagination token to stop returning results at. If not supplied, results
     758              :   /// continue up to `limit` or until there are no more events.
     759              :   ///
     760              :   /// Like `from`, this can be a previous token from a prior call to this endpoint
     761              :   /// or from `/messages` or `/sync`.
     762              :   ///
     763              :   /// [limit] The maximum number of results to return in a single `chunk`. The server can
     764              :   /// and should apply a maximum value to this parameter to avoid large responses.
     765              :   ///
     766              :   /// Similarly, the server should apply a default value when not supplied.
     767              :   ///
     768              :   /// [dir] Optional (default `b`) direction to return events from. If this is set to `f`, events
     769              :   /// will be returned in chronological order starting at `from`. If it
     770              :   /// is set to `b`, events will be returned in *reverse* chronological
     771              :   /// order, again starting at `from`.
     772              :   ///
     773              :   /// [recurse] Whether to additionally include events which only relate indirectly to the
     774              :   /// given event, i.e. events related to the given event via two or more direct relationships.
     775              :   ///
     776              :   /// If set to `false`, only events which have a direct relation with the given
     777              :   /// event will be included.
     778              :   ///
     779              :   /// If set to `true`, events which have an indirect relation with the given event
     780              :   /// will be included additionally up to a certain depth level. Homeservers SHOULD traverse
     781              :   /// at least 3 levels of relationships. Implementations MAY perform more but MUST be careful
     782              :   /// to not infinitely recurse.
     783              :   ///
     784              :   /// The default value is `false`.
     785            4 :   Future<GetRelatingEventsWithRelTypeAndEventTypeResponse>
     786              :       getRelatingEventsWithRelTypeAndEventType(
     787              :     String roomId,
     788              :     String eventId,
     789              :     String relType,
     790              :     String eventType, {
     791              :     String? from,
     792              :     String? to,
     793              :     int? limit,
     794              :     Direction? dir,
     795              :     bool? recurse,
     796              :   }) async {
     797            4 :     final requestUri = Uri(
     798              :       path:
     799           20 :           '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/relations/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(relType)}/${Uri.encodeComponent(eventType)}',
     800            4 :       queryParameters: {
     801            0 :         if (from != null) 'from': from,
     802            0 :         if (to != null) 'to': to,
     803            8 :         if (limit != null) 'limit': limit.toString(),
     804            0 :         if (dir != null) 'dir': dir.name,
     805            8 :         if (recurse != null) 'recurse': recurse.toString(),
     806              :       },
     807              :     );
     808           12 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     809           16 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     810            8 :     final response = await httpClient.send(request);
     811            8 :     final responseBody = await response.stream.toBytes();
     812            8 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     813            4 :     final responseString = utf8.decode(responseBody);
     814            4 :     final json = jsonDecode(responseString);
     815            4 :     return GetRelatingEventsWithRelTypeAndEventTypeResponse.fromJson(
     816              :       json as Map<String, Object?>,
     817              :     );
     818              :   }
     819              : 
     820              :   /// This API is used to paginate through the list of the thread roots in a given room.
     821              :   ///
     822              :   /// Optionally, the returned list may be filtered according to whether the requesting
     823              :   /// user has participated in the thread.
     824              :   ///
     825              :   /// [roomId] The room ID where the thread roots are located.
     826              :   ///
     827              :   /// [include] Optional (default `all`) flag to denote which thread roots are of interest to the caller.
     828              :   /// When `all`, all thread roots found in the room are returned. When `participated`, only
     829              :   /// thread roots for threads the user has [participated in](https://spec.matrix.org/unstable/client-server-api/#server-side-aggregation-of-mthread-relationships)
     830              :   /// will be returned.
     831              :   ///
     832              :   /// [limit] Optional limit for the maximum number of thread roots to include per response. Must be an integer
     833              :   /// greater than zero.
     834              :   ///
     835              :   /// Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
     836              :   ///
     837              :   /// [from] A pagination token from a previous result. When not provided, the server starts paginating from
     838              :   /// the most recent event visible to the user (as per history visibility rules; topologically).
     839            0 :   Future<GetThreadRootsResponse> getThreadRoots(
     840              :     String roomId, {
     841              :     Include? include,
     842              :     int? limit,
     843              :     String? from,
     844              :   }) async {
     845            0 :     final requestUri = Uri(
     846            0 :       path: '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/threads',
     847            0 :       queryParameters: {
     848            0 :         if (include != null) 'include': include.name,
     849            0 :         if (limit != null) 'limit': limit.toString(),
     850            0 :         if (from != null) 'from': from,
     851              :       },
     852              :     );
     853            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     854            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     855            0 :     final response = await httpClient.send(request);
     856            0 :     final responseBody = await response.stream.toBytes();
     857            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     858            0 :     final responseString = utf8.decode(responseBody);
     859            0 :     final json = jsonDecode(responseString);
     860            0 :     return GetThreadRootsResponse.fromJson(json as Map<String, Object?>);
     861              :   }
     862              : 
     863              :   /// Get the ID of the event closest to the given timestamp, in the
     864              :   /// direction specified by the `dir` parameter.
     865              :   ///
     866              :   /// If the server does not have all of the room history and does not have
     867              :   /// an event suitably close to the requested timestamp, it can use the
     868              :   /// corresponding [federation endpoint](https://spec.matrix.org/unstable/server-server-api/#get_matrixfederationv1timestamp_to_eventroomid)
     869              :   /// to ask other servers for a suitable event.
     870              :   ///
     871              :   /// After calling this endpoint, clients can call
     872              :   /// [`/rooms/{roomId}/context/{eventId}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidcontexteventid)
     873              :   /// to obtain a pagination token to retrieve the events around the returned event.
     874              :   ///
     875              :   /// The event returned by this endpoint could be an event that the client
     876              :   /// cannot render, and so may need to paginate in order to locate an event
     877              :   /// that it can display, which may end up being outside of the client's
     878              :   /// suitable range.  Clients can employ different strategies to display
     879              :   /// something reasonable to the user.  For example, the client could try
     880              :   /// paginating in one direction for a while, while looking at the
     881              :   /// timestamps of the events that it is paginating through, and if it
     882              :   /// exceeds a certain difference from the target timestamp, it can try
     883              :   /// paginating in the opposite direction.  The client could also simply
     884              :   /// paginate in one direction and inform the user that the closest event
     885              :   /// found in that direction is outside of the expected range.
     886              :   ///
     887              :   /// [roomId] The ID of the room to search
     888              :   ///
     889              :   /// [ts] The timestamp to search from, as given in milliseconds
     890              :   /// since the Unix epoch.
     891              :   ///
     892              :   /// [dir] The direction in which to search.  `f` for forwards, `b` for backwards.
     893            0 :   Future<GetEventByTimestampResponse> getEventByTimestamp(
     894              :     String roomId,
     895              :     int ts,
     896              :     Direction dir,
     897              :   ) async {
     898            0 :     final requestUri = Uri(
     899              :       path:
     900            0 :           '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/timestamp_to_event',
     901            0 :       queryParameters: {
     902            0 :         'ts': ts.toString(),
     903            0 :         'dir': dir.name,
     904              :       },
     905              :     );
     906            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     907            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     908            0 :     final response = await httpClient.send(request);
     909            0 :     final responseBody = await response.stream.toBytes();
     910            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     911            0 :     final responseString = utf8.decode(responseBody);
     912            0 :     final json = jsonDecode(responseString);
     913            0 :     return GetEventByTimestampResponse.fromJson(json as Map<String, Object?>);
     914              :   }
     915              : 
     916              :   /// Gets a list of the third-party identifiers that the homeserver has
     917              :   /// associated with the user's account.
     918              :   ///
     919              :   /// This is *not* the same as the list of third-party identifiers bound to
     920              :   /// the user's Matrix ID in identity servers.
     921              :   ///
     922              :   /// Identifiers in this list may be used by the homeserver as, for example,
     923              :   /// identifiers that it will accept to reset the user's account password.
     924              :   ///
     925              :   /// returns `threepids`:
     926              :   ///
     927            0 :   Future<List<ThirdPartyIdentifier>?> getAccount3PIDs() async {
     928            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/3pid');
     929            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
     930            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     931            0 :     final response = await httpClient.send(request);
     932            0 :     final responseBody = await response.stream.toBytes();
     933            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     934            0 :     final responseString = utf8.decode(responseBody);
     935            0 :     final json = jsonDecode(responseString);
     936            0 :     return ((v) => v != null
     937              :         ? (v as List)
     938            0 :             .map(
     939            0 :               (v) => ThirdPartyIdentifier.fromJson(v as Map<String, Object?>),
     940              :             )
     941            0 :             .toList()
     942            0 :         : null)(json['threepids']);
     943              :   }
     944              : 
     945              :   /// Adds contact information to the user's account.
     946              :   ///
     947              :   /// This endpoint is deprecated in favour of the more specific `/3pid/add`
     948              :   /// and `/3pid/bind` endpoints.
     949              :   ///
     950              :   /// **Note:**
     951              :   /// Previously this endpoint supported a `bind` parameter. This parameter
     952              :   /// has been removed, making this endpoint behave as though it was `false`.
     953              :   /// This results in this endpoint being an equivalent to `/3pid/bind` rather
     954              :   /// than dual-purpose.
     955              :   ///
     956              :   /// [threePidCreds] The third-party credentials to associate with the account.
     957              :   ///
     958              :   /// returns `submit_url`:
     959              :   /// An optional field containing a URL where the client must
     960              :   /// submit the validation token to, with identical parameters
     961              :   /// to the Identity Service API's `POST
     962              :   /// /validate/email/submitToken` endpoint (without the requirement
     963              :   /// for an access token). The homeserver must send this token to the
     964              :   /// user (if applicable), who should then be prompted to provide it
     965              :   /// to the client.
     966              :   ///
     967              :   /// If this field is not present, the client can assume that
     968              :   /// verification will happen without the client's involvement
     969              :   /// provided the homeserver advertises this specification version
     970              :   /// in the `/versions` response (ie: r0.5.0).
     971            0 :   @deprecated
     972              :   Future<Uri?> post3PIDs(ThreePidCredentials threePidCreds) async {
     973            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/3pid');
     974            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
     975            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
     976            0 :     request.headers['content-type'] = 'application/json';
     977            0 :     request.bodyBytes = utf8.encode(
     978            0 :       jsonEncode({
     979            0 :         'three_pid_creds': threePidCreds.toJson(),
     980              :       }),
     981              :     );
     982            0 :     final response = await httpClient.send(request);
     983            0 :     final responseBody = await response.stream.toBytes();
     984            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
     985            0 :     final responseString = utf8.decode(responseBody);
     986            0 :     final json = jsonDecode(responseString);
     987            0 :     return ((v) =>
     988            0 :         v != null ? Uri.parse(v as String) : null)(json['submit_url']);
     989              :   }
     990              : 
     991              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api).
     992              :   ///
     993              :   /// Adds contact information to the user's account. Homeservers should use 3PIDs added
     994              :   /// through this endpoint for password resets instead of relying on the identity server.
     995              :   ///
     996              :   /// Homeservers should prevent the caller from adding a 3PID to their account if it has
     997              :   /// already been added to another user's account on the homeserver.
     998              :   ///
     999              :   /// **WARNING:**
    1000              :   /// Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained
    1001              :   /// via the [OAuth 2.0 API](https://spec.matrix.org/unstable/client-server-api/#oauth-20-api).
    1002              :   ///
    1003              :   ///
    1004              :   /// [auth] Additional authentication information for the
    1005              :   /// user-interactive authentication API.
    1006              :   ///
    1007              :   /// [clientSecret] The client secret used in the session with the homeserver.
    1008              :   ///
    1009              :   /// [sid] The session identifier given by the homeserver.
    1010            0 :   Future<void> add3PID(
    1011              :     String clientSecret,
    1012              :     String sid, {
    1013              :     AuthenticationData? auth,
    1014              :   }) async {
    1015            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/3pid/add');
    1016            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1017            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1018            0 :     request.headers['content-type'] = 'application/json';
    1019            0 :     request.bodyBytes = utf8.encode(
    1020            0 :       jsonEncode({
    1021            0 :         if (auth != null) 'auth': auth.toJson(),
    1022            0 :         'client_secret': clientSecret,
    1023            0 :         'sid': sid,
    1024              :       }),
    1025              :     );
    1026            0 :     final response = await httpClient.send(request);
    1027            0 :     final responseBody = await response.stream.toBytes();
    1028            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1029            0 :     final responseString = utf8.decode(responseBody);
    1030            0 :     final json = jsonDecode(responseString);
    1031            0 :     return ignore(json);
    1032              :   }
    1033              : 
    1034              :   /// Binds a 3PID to the user's account through the specified identity server.
    1035              :   ///
    1036              :   /// Homeservers should not prevent this request from succeeding if another user
    1037              :   /// has bound the 3PID. Homeservers should simply proxy any errors received by
    1038              :   /// the identity server to the caller.
    1039              :   ///
    1040              :   /// Homeservers should track successful binds so they can be unbound later.
    1041              :   ///
    1042              :   /// [clientSecret] The client secret used in the session with the identity server.
    1043              :   ///
    1044              :   /// [idAccessToken] An access token previously registered with the identity server.
    1045              :   ///
    1046              :   /// [idServer] The identity server to use.
    1047              :   ///
    1048              :   /// [sid] The session identifier given by the identity server.
    1049            0 :   Future<void> bind3PID(
    1050              :     String clientSecret,
    1051              :     String idAccessToken,
    1052              :     String idServer,
    1053              :     String sid,
    1054              :   ) async {
    1055            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/3pid/bind');
    1056            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1057            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1058            0 :     request.headers['content-type'] = 'application/json';
    1059            0 :     request.bodyBytes = utf8.encode(
    1060            0 :       jsonEncode({
    1061              :         'client_secret': clientSecret,
    1062              :         'id_access_token': idAccessToken,
    1063              :         'id_server': idServer,
    1064              :         'sid': sid,
    1065              :       }),
    1066              :     );
    1067            0 :     final response = await httpClient.send(request);
    1068            0 :     final responseBody = await response.stream.toBytes();
    1069            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1070            0 :     final responseString = utf8.decode(responseBody);
    1071            0 :     final json = jsonDecode(responseString);
    1072            0 :     return ignore(json);
    1073              :   }
    1074              : 
    1075              :   /// Removes a third-party identifier from the user's account. This might not
    1076              :   /// cause an unbind of the identifier from the identity server.
    1077              :   ///
    1078              :   /// Unlike other endpoints, this endpoint does not take an `id_access_token`
    1079              :   /// parameter because the homeserver is expected to sign the request to the
    1080              :   /// identity server instead.
    1081              :   ///
    1082              :   /// [address] The third-party address being removed.
    1083              :   ///
    1084              :   /// [idServer] The identity server to unbind from. If not provided, the homeserver
    1085              :   /// MUST use the `id_server` the identifier was added through. If the
    1086              :   /// homeserver does not know the original `id_server`, it MUST return
    1087              :   /// a `id_server_unbind_result` of `no-support`.
    1088              :   ///
    1089              :   /// [medium] The medium of the third-party identifier being removed.
    1090              :   ///
    1091              :   /// returns `id_server_unbind_result`:
    1092              :   /// An indicator as to whether or not the homeserver was able to unbind
    1093              :   /// the 3PID from the identity server. `success` indicates that the
    1094              :   /// identity server has unbound the identifier whereas `no-support`
    1095              :   /// indicates that the identity server refuses to support the request
    1096              :   /// or the homeserver was not able to determine an identity server to
    1097              :   /// unbind from.
    1098            0 :   Future<IdServerUnbindResult> delete3pidFromAccount(
    1099              :     String address,
    1100              :     ThirdPartyIdentifierMedium medium, {
    1101              :     String? idServer,
    1102              :   }) async {
    1103            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/3pid/delete');
    1104            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1105            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1106            0 :     request.headers['content-type'] = 'application/json';
    1107            0 :     request.bodyBytes = utf8.encode(
    1108            0 :       jsonEncode({
    1109            0 :         'address': address,
    1110            0 :         if (idServer != null) 'id_server': idServer,
    1111            0 :         'medium': medium.name,
    1112              :       }),
    1113              :     );
    1114            0 :     final response = await httpClient.send(request);
    1115            0 :     final responseBody = await response.stream.toBytes();
    1116            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1117            0 :     final responseString = utf8.decode(responseBody);
    1118            0 :     final json = jsonDecode(responseString);
    1119              :     return IdServerUnbindResult.values
    1120            0 :         .fromString(json['id_server_unbind_result'] as String)!;
    1121              :   }
    1122              : 
    1123              :   /// The homeserver must check that the given email address is **not**
    1124              :   /// already associated with an account on this homeserver. This API should
    1125              :   /// be used to request validation tokens when adding an email address to an
    1126              :   /// account. This API's parameters and response are identical to that of
    1127              :   /// the [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registeremailrequesttoken)
    1128              :   /// endpoint. The homeserver should validate
    1129              :   /// the email itself, either by sending a validation email itself or by using
    1130              :   /// a service it has control over.
    1131              :   ///
    1132              :   /// [clientSecret] A unique string generated by the client, and used to identify the
    1133              :   /// validation attempt. It must be a string consisting of the characters
    1134              :   /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it
    1135              :   /// must not be empty.
    1136              :   ///
    1137              :   ///
    1138              :   /// [email] The email address to validate.
    1139              :   ///
    1140              :   /// [nextLink] Optional. When the validation is completed, the identity server will
    1141              :   /// redirect the user to this URL. This option is ignored when submitting
    1142              :   /// 3PID validation information through a POST request.
    1143              :   ///
    1144              :   /// [sendAttempt] The server will only send an email if the `send_attempt`
    1145              :   /// is a number greater than the most recent one which it has seen,
    1146              :   /// scoped to that `email` + `client_secret` pair. This is to
    1147              :   /// avoid repeatedly sending the same email in the case of request
    1148              :   /// retries between the POSTing user and the identity server.
    1149              :   /// The client should increment this value if they desire a new
    1150              :   /// email (e.g. a reminder) to be sent. If they do not, the server
    1151              :   /// should respond with success but not resend the email.
    1152              :   ///
    1153              :   /// [idAccessToken] An access token previously registered with the identity server. Servers
    1154              :   /// can treat this as optional to distinguish between r0.5-compatible clients
    1155              :   /// and this specification version.
    1156              :   ///
    1157              :   /// Required if an `id_server` is supplied.
    1158              :   ///
    1159              :   /// [idServer] The hostname of the identity server to communicate with. May optionally
    1160              :   /// include a port. This parameter is ignored when the homeserver handles
    1161              :   /// 3PID verification.
    1162              :   ///
    1163              :   /// This parameter is deprecated with a plan to be removed in a future specification
    1164              :   /// version for `/account/password` and `/register` requests.
    1165            0 :   Future<RequestTokenResponse> requestTokenTo3PIDEmail(
    1166              :     String clientSecret,
    1167              :     String email,
    1168              :     int sendAttempt, {
    1169              :     Uri? nextLink,
    1170              :     String? idAccessToken,
    1171              :     String? idServer,
    1172              :   }) async {
    1173              :     final requestUri =
    1174            0 :         Uri(path: '_matrix/client/v3/account/3pid/email/requestToken');
    1175            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1176            0 :     request.headers['content-type'] = 'application/json';
    1177            0 :     request.bodyBytes = utf8.encode(
    1178            0 :       jsonEncode({
    1179            0 :         'client_secret': clientSecret,
    1180            0 :         'email': email,
    1181            0 :         if (nextLink != null) 'next_link': nextLink.toString(),
    1182            0 :         'send_attempt': sendAttempt,
    1183            0 :         if (idAccessToken != null) 'id_access_token': idAccessToken,
    1184            0 :         if (idServer != null) 'id_server': idServer,
    1185              :       }),
    1186              :     );
    1187            0 :     final response = await httpClient.send(request);
    1188            0 :     final responseBody = await response.stream.toBytes();
    1189            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1190            0 :     final responseString = utf8.decode(responseBody);
    1191            0 :     final json = jsonDecode(responseString);
    1192            0 :     return RequestTokenResponse.fromJson(json as Map<String, Object?>);
    1193              :   }
    1194              : 
    1195              :   /// The homeserver must check that the given phone number is **not**
    1196              :   /// already associated with an account on this homeserver. This API should
    1197              :   /// be used to request validation tokens when adding a phone number to an
    1198              :   /// account. This API's parameters and response are identical to that of
    1199              :   /// the [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registermsisdnrequesttoken)
    1200              :   /// endpoint. The homeserver should validate
    1201              :   /// the phone number itself, either by sending a validation message itself or by using
    1202              :   /// a service it has control over.
    1203              :   ///
    1204              :   /// [clientSecret] A unique string generated by the client, and used to identify the
    1205              :   /// validation attempt. It must be a string consisting of the characters
    1206              :   /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it
    1207              :   /// must not be empty.
    1208              :   ///
    1209              :   ///
    1210              :   /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the
    1211              :   /// number in `phone_number` should be parsed as if it were dialled from.
    1212              :   ///
    1213              :   /// [nextLink] Optional. When the validation is completed, the identity server will
    1214              :   /// redirect the user to this URL. This option is ignored when submitting
    1215              :   /// 3PID validation information through a POST request.
    1216              :   ///
    1217              :   /// [phoneNumber] The phone number to validate.
    1218              :   ///
    1219              :   /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a
    1220              :   /// number greater than the most recent one which it has seen,
    1221              :   /// scoped to that `country` + `phone_number` + `client_secret`
    1222              :   /// triple. This is to avoid repeatedly sending the same SMS in
    1223              :   /// the case of request retries between the POSTing user and the
    1224              :   /// identity server. The client should increment this value if
    1225              :   /// they desire a new SMS (e.g. a reminder) to be sent.
    1226              :   ///
    1227              :   /// [idAccessToken] An access token previously registered with the identity server. Servers
    1228              :   /// can treat this as optional to distinguish between r0.5-compatible clients
    1229              :   /// and this specification version.
    1230              :   ///
    1231              :   /// Required if an `id_server` is supplied.
    1232              :   ///
    1233              :   /// [idServer] The hostname of the identity server to communicate with. May optionally
    1234              :   /// include a port. This parameter is ignored when the homeserver handles
    1235              :   /// 3PID verification.
    1236              :   ///
    1237              :   /// This parameter is deprecated with a plan to be removed in a future specification
    1238              :   /// version for `/account/password` and `/register` requests.
    1239            0 :   Future<RequestTokenResponse> requestTokenTo3PIDMSISDN(
    1240              :     String clientSecret,
    1241              :     String country,
    1242              :     String phoneNumber,
    1243              :     int sendAttempt, {
    1244              :     Uri? nextLink,
    1245              :     String? idAccessToken,
    1246              :     String? idServer,
    1247              :   }) async {
    1248              :     final requestUri =
    1249            0 :         Uri(path: '_matrix/client/v3/account/3pid/msisdn/requestToken');
    1250            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1251            0 :     request.headers['content-type'] = 'application/json';
    1252            0 :     request.bodyBytes = utf8.encode(
    1253            0 :       jsonEncode({
    1254            0 :         'client_secret': clientSecret,
    1255            0 :         'country': country,
    1256            0 :         if (nextLink != null) 'next_link': nextLink.toString(),
    1257            0 :         'phone_number': phoneNumber,
    1258            0 :         'send_attempt': sendAttempt,
    1259            0 :         if (idAccessToken != null) 'id_access_token': idAccessToken,
    1260            0 :         if (idServer != null) 'id_server': idServer,
    1261              :       }),
    1262              :     );
    1263            0 :     final response = await httpClient.send(request);
    1264            0 :     final responseBody = await response.stream.toBytes();
    1265            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1266            0 :     final responseString = utf8.decode(responseBody);
    1267            0 :     final json = jsonDecode(responseString);
    1268            0 :     return RequestTokenResponse.fromJson(json as Map<String, Object?>);
    1269              :   }
    1270              : 
    1271              :   /// Removes a user's third-party identifier from the provided identity server
    1272              :   /// without removing it from the homeserver.
    1273              :   ///
    1274              :   /// Unlike other endpoints, this endpoint does not take an `id_access_token`
    1275              :   /// parameter because the homeserver is expected to sign the request to the
    1276              :   /// identity server instead.
    1277              :   ///
    1278              :   /// [address] The third-party address being removed.
    1279              :   ///
    1280              :   /// [idServer] The identity server to unbind from. If not provided, the homeserver
    1281              :   /// MUST use the `id_server` the identifier was added through. If the
    1282              :   /// homeserver does not know the original `id_server`, it MUST return
    1283              :   /// a `id_server_unbind_result` of `no-support`.
    1284              :   ///
    1285              :   /// [medium] The medium of the third-party identifier being removed.
    1286              :   ///
    1287              :   /// returns `id_server_unbind_result`:
    1288              :   /// An indicator as to whether or not the identity server was able to unbind
    1289              :   /// the 3PID. `success` indicates that the identity server has unbound the
    1290              :   /// identifier whereas `no-support` indicates that the identity server
    1291              :   /// refuses to support the request or the homeserver was not able to determine
    1292              :   /// an identity server to unbind from.
    1293            0 :   Future<IdServerUnbindResult> unbind3pidFromAccount(
    1294              :     String address,
    1295              :     ThirdPartyIdentifierMedium medium, {
    1296              :     String? idServer,
    1297              :   }) async {
    1298            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/3pid/unbind');
    1299            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1300            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1301            0 :     request.headers['content-type'] = 'application/json';
    1302            0 :     request.bodyBytes = utf8.encode(
    1303            0 :       jsonEncode({
    1304            0 :         'address': address,
    1305            0 :         if (idServer != null) 'id_server': idServer,
    1306            0 :         'medium': medium.name,
    1307              :       }),
    1308              :     );
    1309            0 :     final response = await httpClient.send(request);
    1310            0 :     final responseBody = await response.stream.toBytes();
    1311            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1312            0 :     final responseString = utf8.decode(responseBody);
    1313            0 :     final json = jsonDecode(responseString);
    1314              :     return IdServerUnbindResult.values
    1315            0 :         .fromString(json['id_server_unbind_result'] as String)!;
    1316              :   }
    1317              : 
    1318              :   /// Deactivate the user's account, removing all ability for the user to
    1319              :   /// login again.
    1320              :   ///
    1321              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api).
    1322              :   ///
    1323              :   /// An access token should be submitted to this endpoint if the client has
    1324              :   /// an active session.
    1325              :   ///
    1326              :   /// The homeserver may change the flows available depending on whether a
    1327              :   /// valid access token is provided.
    1328              :   ///
    1329              :   /// Unlike other endpoints, this endpoint does not take an `id_access_token`
    1330              :   /// parameter because the homeserver is expected to sign the request to the
    1331              :   /// identity server instead.
    1332              :   ///
    1333              :   /// [auth] Additional authentication information for the user-interactive authentication API.
    1334              :   ///
    1335              :   /// [erase] Whether the user would like their content to be erased as
    1336              :   /// much as possible from the server.
    1337              :   ///
    1338              :   /// Erasure means that any users (or servers) which join the
    1339              :   /// room after the erasure request are served redacted copies of
    1340              :   /// the events sent by this account. Users which had visibility
    1341              :   /// on those events prior to the erasure are still able to see
    1342              :   /// unredacted copies. No redactions are sent and the erasure
    1343              :   /// request is not shared over federation, so other servers
    1344              :   /// might still serve unredacted copies.
    1345              :   ///
    1346              :   /// The server should additionally erase any non-event data
    1347              :   /// associated with the user, such as [account data](https://spec.matrix.org/unstable/client-server-api/#client-config)
    1348              :   /// and [contact 3PIDs](https://spec.matrix.org/unstable/client-server-api/#adding-account-administrative-contact-information).
    1349              :   ///
    1350              :   /// Defaults to `false` if not present.
    1351              :   ///
    1352              :   /// [idServer] The identity server to unbind all of the user's 3PIDs from.
    1353              :   /// If not provided, the homeserver MUST use the `id_server`
    1354              :   /// that was originally use to bind each identifier. If the
    1355              :   /// homeserver does not know which `id_server` that was,
    1356              :   /// it must return an `id_server_unbind_result` of
    1357              :   /// `no-support`.
    1358              :   ///
    1359              :   /// returns `id_server_unbind_result`:
    1360              :   /// An indicator as to whether or not the homeserver was able to unbind
    1361              :   /// the user's 3PIDs from the identity server(s). `success` indicates
    1362              :   /// that all identifiers have been unbound from the identity server while
    1363              :   /// `no-support` indicates that one or more identifiers failed to unbind
    1364              :   /// due to the identity server refusing the request or the homeserver
    1365              :   /// being unable to determine an identity server to unbind from. This
    1366              :   /// must be `success` if the homeserver has no identifiers to unbind
    1367              :   /// for the user.
    1368            0 :   Future<IdServerUnbindResult> deactivateAccount({
    1369              :     AuthenticationData? auth,
    1370              :     bool? erase,
    1371              :     String? idServer,
    1372              :   }) async {
    1373            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/deactivate');
    1374            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1375            0 :     if (bearerToken != null) {
    1376            0 :       request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1377              :     }
    1378            0 :     request.headers['content-type'] = 'application/json';
    1379            0 :     request.bodyBytes = utf8.encode(
    1380            0 :       jsonEncode({
    1381            0 :         if (auth != null) 'auth': auth.toJson(),
    1382            0 :         if (erase != null) 'erase': erase,
    1383            0 :         if (idServer != null) 'id_server': idServer,
    1384              :       }),
    1385              :     );
    1386            0 :     final response = await httpClient.send(request);
    1387            0 :     final responseBody = await response.stream.toBytes();
    1388            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1389            0 :     final responseString = utf8.decode(responseBody);
    1390            0 :     final json = jsonDecode(responseString);
    1391              :     return IdServerUnbindResult.values
    1392            0 :         .fromString(json['id_server_unbind_result'] as String)!;
    1393              :   }
    1394              : 
    1395              :   /// Changes the password for an account on this homeserver.
    1396              :   ///
    1397              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api) to
    1398              :   /// ensure the user changing the password is actually the owner of the
    1399              :   /// account.
    1400              :   ///
    1401              :   /// An access token should be submitted to this endpoint if the client has
    1402              :   /// an active session.
    1403              :   ///
    1404              :   /// The homeserver may change the flows available depending on whether a
    1405              :   /// valid access token is provided. The homeserver SHOULD NOT revoke the
    1406              :   /// access token provided in the request. Whether other access tokens for
    1407              :   /// the user are revoked depends on the request parameters.
    1408              :   ///
    1409              :   /// [auth] Additional authentication information for the user-interactive authentication API.
    1410              :   ///
    1411              :   /// [logoutDevices] Whether the user's other access tokens, and their associated devices, should be
    1412              :   /// revoked if the request succeeds. Defaults to true.
    1413              :   ///
    1414              :   /// When `false`, the server can still take advantage of the [soft logout method](https://spec.matrix.org/unstable/client-server-api/#soft-logout)
    1415              :   /// for the user's remaining devices.
    1416              :   ///
    1417              :   /// [newPassword] The new password for the account.
    1418            1 :   Future<void> changePassword(
    1419              :     String newPassword, {
    1420              :     AuthenticationData? auth,
    1421              :     bool? logoutDevices,
    1422              :   }) async {
    1423            1 :     final requestUri = Uri(path: '_matrix/client/v3/account/password');
    1424            3 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1425            1 :     if (bearerToken != null) {
    1426            4 :       request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1427              :     }
    1428            2 :     request.headers['content-type'] = 'application/json';
    1429            2 :     request.bodyBytes = utf8.encode(
    1430            2 :       jsonEncode({
    1431            2 :         if (auth != null) 'auth': auth.toJson(),
    1432            0 :         if (logoutDevices != null) 'logout_devices': logoutDevices,
    1433            1 :         'new_password': newPassword,
    1434              :       }),
    1435              :     );
    1436            2 :     final response = await httpClient.send(request);
    1437            2 :     final responseBody = await response.stream.toBytes();
    1438            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1439            1 :     final responseString = utf8.decode(responseBody);
    1440            1 :     final json = jsonDecode(responseString);
    1441            1 :     return ignore(json);
    1442              :   }
    1443              : 
    1444              :   /// The homeserver must check that the given email address **is
    1445              :   /// associated** with an account on this homeserver. This API should be
    1446              :   /// used to request validation tokens when authenticating for the
    1447              :   /// `/account/password` endpoint.
    1448              :   ///
    1449              :   /// This API's parameters and response are identical to that of the
    1450              :   /// [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registeremailrequesttoken)
    1451              :   /// endpoint, except that
    1452              :   /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the
    1453              :   /// given email address could be found. The server may instead send an
    1454              :   /// email to the given address prompting the user to create an account.
    1455              :   /// `M_THREEPID_IN_USE` may not be returned.
    1456              :   ///
    1457              :   /// The homeserver should validate the email itself, either by sending a
    1458              :   /// validation email itself or by using a service it has control over.
    1459              :   ///
    1460              :   /// [clientSecret] A unique string generated by the client, and used to identify the
    1461              :   /// validation attempt. It must be a string consisting of the characters
    1462              :   /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it
    1463              :   /// must not be empty.
    1464              :   ///
    1465              :   ///
    1466              :   /// [email] The email address to validate.
    1467              :   ///
    1468              :   /// [nextLink] Optional. When the validation is completed, the identity server will
    1469              :   /// redirect the user to this URL. This option is ignored when submitting
    1470              :   /// 3PID validation information through a POST request.
    1471              :   ///
    1472              :   /// [sendAttempt] The server will only send an email if the `send_attempt`
    1473              :   /// is a number greater than the most recent one which it has seen,
    1474              :   /// scoped to that `email` + `client_secret` pair. This is to
    1475              :   /// avoid repeatedly sending the same email in the case of request
    1476              :   /// retries between the POSTing user and the identity server.
    1477              :   /// The client should increment this value if they desire a new
    1478              :   /// email (e.g. a reminder) to be sent. If they do not, the server
    1479              :   /// should respond with success but not resend the email.
    1480              :   ///
    1481              :   /// [idAccessToken] An access token previously registered with the identity server. Servers
    1482              :   /// can treat this as optional to distinguish between r0.5-compatible clients
    1483              :   /// and this specification version.
    1484              :   ///
    1485              :   /// Required if an `id_server` is supplied.
    1486              :   ///
    1487              :   /// [idServer] The hostname of the identity server to communicate with. May optionally
    1488              :   /// include a port. This parameter is ignored when the homeserver handles
    1489              :   /// 3PID verification.
    1490              :   ///
    1491              :   /// This parameter is deprecated with a plan to be removed in a future specification
    1492              :   /// version for `/account/password` and `/register` requests.
    1493            0 :   Future<RequestTokenResponse> requestTokenToResetPasswordEmail(
    1494              :     String clientSecret,
    1495              :     String email,
    1496              :     int sendAttempt, {
    1497              :     Uri? nextLink,
    1498              :     String? idAccessToken,
    1499              :     String? idServer,
    1500              :   }) async {
    1501              :     final requestUri =
    1502            0 :         Uri(path: '_matrix/client/v3/account/password/email/requestToken');
    1503            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1504            0 :     request.headers['content-type'] = 'application/json';
    1505            0 :     request.bodyBytes = utf8.encode(
    1506            0 :       jsonEncode({
    1507            0 :         'client_secret': clientSecret,
    1508            0 :         'email': email,
    1509            0 :         if (nextLink != null) 'next_link': nextLink.toString(),
    1510            0 :         'send_attempt': sendAttempt,
    1511            0 :         if (idAccessToken != null) 'id_access_token': idAccessToken,
    1512            0 :         if (idServer != null) 'id_server': idServer,
    1513              :       }),
    1514              :     );
    1515            0 :     final response = await httpClient.send(request);
    1516            0 :     final responseBody = await response.stream.toBytes();
    1517            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1518            0 :     final responseString = utf8.decode(responseBody);
    1519            0 :     final json = jsonDecode(responseString);
    1520            0 :     return RequestTokenResponse.fromJson(json as Map<String, Object?>);
    1521              :   }
    1522              : 
    1523              :   /// The homeserver must check that the given phone number **is
    1524              :   /// associated** with an account on this homeserver. This API should be
    1525              :   /// used to request validation tokens when authenticating for the
    1526              :   /// `/account/password` endpoint.
    1527              :   ///
    1528              :   /// This API's parameters and response are identical to that of the
    1529              :   /// [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registermsisdnrequesttoken)
    1530              :   /// endpoint, except that
    1531              :   /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the
    1532              :   /// given phone number could be found. The server may instead send the SMS
    1533              :   /// to the given phone number prompting the user to create an account.
    1534              :   /// `M_THREEPID_IN_USE` may not be returned.
    1535              :   ///
    1536              :   /// The homeserver should validate the phone number itself, either by sending a
    1537              :   /// validation message itself or by using a service it has control over.
    1538              :   ///
    1539              :   /// [clientSecret] A unique string generated by the client, and used to identify the
    1540              :   /// validation attempt. It must be a string consisting of the characters
    1541              :   /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it
    1542              :   /// must not be empty.
    1543              :   ///
    1544              :   ///
    1545              :   /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the
    1546              :   /// number in `phone_number` should be parsed as if it were dialled from.
    1547              :   ///
    1548              :   /// [nextLink] Optional. When the validation is completed, the identity server will
    1549              :   /// redirect the user to this URL. This option is ignored when submitting
    1550              :   /// 3PID validation information through a POST request.
    1551              :   ///
    1552              :   /// [phoneNumber] The phone number to validate.
    1553              :   ///
    1554              :   /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a
    1555              :   /// number greater than the most recent one which it has seen,
    1556              :   /// scoped to that `country` + `phone_number` + `client_secret`
    1557              :   /// triple. This is to avoid repeatedly sending the same SMS in
    1558              :   /// the case of request retries between the POSTing user and the
    1559              :   /// identity server. The client should increment this value if
    1560              :   /// they desire a new SMS (e.g. a reminder) to be sent.
    1561              :   ///
    1562              :   /// [idAccessToken] An access token previously registered with the identity server. Servers
    1563              :   /// can treat this as optional to distinguish between r0.5-compatible clients
    1564              :   /// and this specification version.
    1565              :   ///
    1566              :   /// Required if an `id_server` is supplied.
    1567              :   ///
    1568              :   /// [idServer] The hostname of the identity server to communicate with. May optionally
    1569              :   /// include a port. This parameter is ignored when the homeserver handles
    1570              :   /// 3PID verification.
    1571              :   ///
    1572              :   /// This parameter is deprecated with a plan to be removed in a future specification
    1573              :   /// version for `/account/password` and `/register` requests.
    1574            0 :   Future<RequestTokenResponse> requestTokenToResetPasswordMSISDN(
    1575              :     String clientSecret,
    1576              :     String country,
    1577              :     String phoneNumber,
    1578              :     int sendAttempt, {
    1579              :     Uri? nextLink,
    1580              :     String? idAccessToken,
    1581              :     String? idServer,
    1582              :   }) async {
    1583              :     final requestUri =
    1584            0 :         Uri(path: '_matrix/client/v3/account/password/msisdn/requestToken');
    1585            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1586            0 :     request.headers['content-type'] = 'application/json';
    1587            0 :     request.bodyBytes = utf8.encode(
    1588            0 :       jsonEncode({
    1589            0 :         'client_secret': clientSecret,
    1590            0 :         'country': country,
    1591            0 :         if (nextLink != null) 'next_link': nextLink.toString(),
    1592            0 :         'phone_number': phoneNumber,
    1593            0 :         'send_attempt': sendAttempt,
    1594            0 :         if (idAccessToken != null) 'id_access_token': idAccessToken,
    1595            0 :         if (idServer != null) 'id_server': idServer,
    1596              :       }),
    1597              :     );
    1598            0 :     final response = await httpClient.send(request);
    1599            0 :     final responseBody = await response.stream.toBytes();
    1600            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1601            0 :     final responseString = utf8.decode(responseBody);
    1602            0 :     final json = jsonDecode(responseString);
    1603            0 :     return RequestTokenResponse.fromJson(json as Map<String, Object?>);
    1604              :   }
    1605              : 
    1606              :   /// Gets information about the owner of a given access token.
    1607              :   ///
    1608              :   /// Note that, as with the rest of the Client-Server API,
    1609              :   /// Application Services may masquerade as users within their
    1610              :   /// namespace by giving a `user_id` query parameter. In this
    1611              :   /// situation, the server should verify that the given `user_id`
    1612              :   /// is registered by the appservice, and return it in the response
    1613              :   /// body.
    1614            0 :   Future<TokenOwnerInfo> getTokenOwner() async {
    1615            0 :     final requestUri = Uri(path: '_matrix/client/v3/account/whoami');
    1616            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    1617            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1618            0 :     final response = await httpClient.send(request);
    1619            0 :     final responseBody = await response.stream.toBytes();
    1620            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1621            0 :     final responseString = utf8.decode(responseBody);
    1622            0 :     final json = jsonDecode(responseString);
    1623            0 :     return TokenOwnerInfo.fromJson(json as Map<String, Object?>);
    1624              :   }
    1625              : 
    1626              :   /// Gets information about a particular user.
    1627              :   ///
    1628              :   /// This API may be restricted to only be called by the user being looked
    1629              :   /// up, or by a server admin. Server-local administrator privileges are not
    1630              :   /// specified in this document.
    1631              :   ///
    1632              :   /// [userId] The user to look up.
    1633            0 :   Future<WhoIsInfo> getWhoIs(String userId) async {
    1634            0 :     final requestUri = Uri(
    1635            0 :       path: '_matrix/client/v3/admin/whois/${Uri.encodeComponent(userId)}',
    1636              :     );
    1637            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    1638            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1639            0 :     final response = await httpClient.send(request);
    1640            0 :     final responseBody = await response.stream.toBytes();
    1641            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1642            0 :     final responseString = utf8.decode(responseBody);
    1643            0 :     final json = jsonDecode(responseString);
    1644            0 :     return WhoIsInfo.fromJson(json as Map<String, Object?>);
    1645              :   }
    1646              : 
    1647              :   /// Gets information about the server's supported feature set
    1648              :   /// and other relevant capabilities.
    1649              :   ///
    1650              :   /// returns `capabilities`:
    1651              :   /// The custom capabilities the server supports, using the
    1652              :   /// Java package naming convention.
    1653            0 :   Future<Capabilities> getCapabilities() async {
    1654            0 :     final requestUri = Uri(path: '_matrix/client/v3/capabilities');
    1655            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    1656            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1657            0 :     final response = await httpClient.send(request);
    1658            0 :     final responseBody = await response.stream.toBytes();
    1659            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1660            0 :     final responseString = utf8.decode(responseBody);
    1661            0 :     final json = jsonDecode(responseString);
    1662            0 :     return Capabilities.fromJson(json['capabilities'] as Map<String, Object?>);
    1663              :   }
    1664              : 
    1665              :   /// Create a new room with various configuration options.
    1666              :   ///
    1667              :   /// The server MUST apply the normal state resolution rules when creating
    1668              :   /// the new room, including checking power levels for each event. It MUST
    1669              :   /// apply the events implied by the request in the following order:
    1670              :   ///
    1671              :   /// 1. The `m.room.create` event itself. Must be the first event in the
    1672              :   ///    room.
    1673              :   ///
    1674              :   /// 2. An `m.room.member` event for the creator to join the room. This is
    1675              :   ///    needed so the remaining events can be sent.
    1676              :   ///
    1677              :   /// 3. A default `m.room.power_levels` event. Overridden by the
    1678              :   ///    `power_level_content_override` parameter.
    1679              :   ///
    1680              :   ///    In [room versions](https://spec.matrix.org/unstable/rooms) 1 through 11, the room creator (and not
    1681              :   ///    other members) will be given permission to send state events.
    1682              :   ///
    1683              :   ///    In room versions 12 and later, the room creator is given infinite
    1684              :   ///    power level and cannot be specified in the `users` field of
    1685              :   ///    `m.room.power_levels`, so is not listed explicitly.
    1686              :   ///
    1687              :   ///    **Note**: For `trusted_private_chat`, the users specified in the
    1688              :   ///    `invite` parameter SHOULD also be appended to `additional_creators`
    1689              :   ///    by the server, per the `creation_content` parameter.
    1690              :   ///
    1691              :   ///    If the room's version is 12 or higher, the power level for sending
    1692              :   ///    `m.room.tombstone` events MUST explicitly be higher than `state_default`.
    1693              :   ///    For example, set to 150 instead of 100.
    1694              :   ///
    1695              :   /// 4. An `m.room.canonical_alias` event if `room_alias_name` is given.
    1696              :   ///
    1697              :   /// 5. Events set by the `preset`. Currently these are the `m.room.join_rules`,
    1698              :   ///    `m.room.history_visibility`, and `m.room.guest_access` state events.
    1699              :   ///
    1700              :   /// 6. Events listed in `initial_state`, in the order that they are
    1701              :   ///    listed.
    1702              :   ///
    1703              :   /// 7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`
    1704              :   ///    state events).
    1705              :   ///
    1706              :   /// 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with
    1707              :   ///    `membership: invite` and `m.room.third_party_invite`).
    1708              :   ///
    1709              :   /// The available presets do the following with respect to room state:
    1710              :   ///
    1711              :   /// | Preset                 | `join_rules` | `history_visibility` | `guest_access` | Other |
    1712              :   /// |------------------------|--------------|----------------------|----------------|-------|
    1713              :   /// | `private_chat`         | `invite`     | `shared`             | `can_join`     |       |
    1714              :   /// | `trusted_private_chat` | `invite`     | `shared`             | `can_join`     | All invitees are given the same power level as the room creator. |
    1715              :   /// | `public_chat`          | `public`     | `shared`             | `forbidden`    |       |
    1716              :   ///
    1717              :   /// The server will create a `m.room.create` event in the room with the
    1718              :   /// requesting user as the creator, alongside other keys provided in the
    1719              :   /// `creation_content` or implied by behaviour of `creation_content`.
    1720              :   ///
    1721              :   /// [creationContent] Extra keys, such as `m.federate`, to be added to the content
    1722              :   /// of the [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate) event.
    1723              :   ///
    1724              :   /// The server will overwrite the following
    1725              :   /// keys: `creator`, `room_version`. Future versions of the specification
    1726              :   /// may allow the server to overwrite other keys.
    1727              :   ///
    1728              :   /// When using the `trusted_private_chat` preset, the server SHOULD combine
    1729              :   /// `additional_creators` specified here and the `invite` array into the
    1730              :   /// eventual `m.room.create` event's `additional_creators`, deduplicating
    1731              :   /// between the two parameters.
    1732              :   ///
    1733              :   /// [initialState] A list of state events to set in the new room. This allows
    1734              :   /// the user to override the default state events set in the new
    1735              :   /// room. The expected format of the state events are an object
    1736              :   /// with type, state_key and content keys set.
    1737              :   ///
    1738              :   /// Takes precedence over events set by `preset`, but gets
    1739              :   /// overridden by `name` and `topic` keys.
    1740              :   ///
    1741              :   /// [invite] A list of user IDs to invite to the room. This will tell the
    1742              :   /// server to invite everyone in the list to the newly created room.
    1743              :   ///
    1744              :   /// [invite3pid] A list of objects representing third-party IDs to invite into
    1745              :   /// the room.
    1746              :   ///
    1747              :   /// [isDirect] This flag makes the server set the `is_direct` flag on the
    1748              :   /// `m.room.member` events sent to the users in `invite` and
    1749              :   /// `invite_3pid`. See [Direct Messaging](https://spec.matrix.org/unstable/client-server-api/#direct-messaging) for more information.
    1750              :   ///
    1751              :   /// [name] If this is included, an [`m.room.name`](https://spec.matrix.org/unstable/client-server-api/#mroomname) event
    1752              :   /// will be sent into the room to indicate the name for the room.
    1753              :   /// This overwrites any [`m.room.name`](https://spec.matrix.org/unstable/client-server-api/#mroomname)
    1754              :   /// event in `initial_state`.
    1755              :   ///
    1756              :   /// [powerLevelContentOverride] The power level content to override in the default power level
    1757              :   /// event. This object is applied on top of the generated
    1758              :   /// [`m.room.power_levels`](https://spec.matrix.org/unstable/client-server-api/#mroompower_levels)
    1759              :   /// event content prior to it being sent to the room. Defaults to
    1760              :   /// overriding nothing.
    1761              :   ///
    1762              :   /// [preset] Convenience parameter for setting various default state events
    1763              :   /// based on a preset.
    1764              :   ///
    1765              :   /// If unspecified, the server should use the `visibility` to determine
    1766              :   /// which preset to use. A visibility of `public` equates to a preset of
    1767              :   /// `public_chat` and `private` visibility equates to a preset of
    1768              :   /// `private_chat`.
    1769              :   ///
    1770              :   /// [roomAliasName] The desired room alias **local part**. If this is included, a
    1771              :   /// room alias will be created and mapped to the newly created
    1772              :   /// room. The alias will belong on the *same* homeserver which
    1773              :   /// created the room. For example, if this was set to "foo" and
    1774              :   /// sent to the homeserver "example.com" the complete room alias
    1775              :   /// would be `#foo:example.com`.
    1776              :   ///
    1777              :   /// The complete room alias will become the canonical alias for
    1778              :   /// the room and an `m.room.canonical_alias` event will be sent
    1779              :   /// into the room.
    1780              :   ///
    1781              :   /// [roomVersion] The room version to set for the room. If not provided, the homeserver is
    1782              :   /// to use its configured default. If provided, the homeserver will return a
    1783              :   /// 400 error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not
    1784              :   /// support the room version.
    1785              :   ///
    1786              :   /// [topic] If this is included, an [`m.room.topic`](https://spec.matrix.org/unstable/client-server-api/#mroomtopic)
    1787              :   /// event with a `text/plain` mimetype will be sent into the room
    1788              :   /// to indicate the topic for the room. This overwrites any
    1789              :   /// [`m.room.topic`](https://spec.matrix.org/unstable/client-server-api/#mroomtopic) event in `initial_state`.
    1790              :   ///
    1791              :   /// [visibility] The room's visibility in the server's
    1792              :   /// [published room directory](https://spec.matrix.org/unstable/client-server-api#published-room-directory).
    1793              :   /// Defaults to `private`.
    1794              :   ///
    1795              :   /// returns `room_id`:
    1796              :   /// The created room's ID.
    1797            6 :   Future<String> createRoom({
    1798              :     Map<String, Object?>? creationContent,
    1799              :     List<StateEvent>? initialState,
    1800              :     List<String>? invite,
    1801              :     List<Invite3pid>? invite3pid,
    1802              :     bool? isDirect,
    1803              :     String? name,
    1804              :     Map<String, Object?>? powerLevelContentOverride,
    1805              :     CreateRoomPreset? preset,
    1806              :     String? roomAliasName,
    1807              :     String? roomVersion,
    1808              :     String? topic,
    1809              :     Visibility? visibility,
    1810              :   }) async {
    1811            6 :     final requestUri = Uri(path: '_matrix/client/v3/createRoom');
    1812           18 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1813           24 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1814           12 :     request.headers['content-type'] = 'application/json';
    1815           12 :     request.bodyBytes = utf8.encode(
    1816           12 :       jsonEncode({
    1817            1 :         if (creationContent != null) 'creation_content': creationContent,
    1818              :         if (initialState != null)
    1819           10 :           'initial_state': initialState.map((v) => v.toJson()).toList(),
    1820           24 :         if (invite != null) 'invite': invite.map((v) => v).toList(),
    1821              :         if (invite3pid != null)
    1822            0 :           'invite_3pid': invite3pid.map((v) => v.toJson()).toList(),
    1823            6 :         if (isDirect != null) 'is_direct': isDirect,
    1824            2 :         if (name != null) 'name': name,
    1825              :         if (powerLevelContentOverride != null)
    1826            1 :           'power_level_content_override': powerLevelContentOverride,
    1827           12 :         if (preset != null) 'preset': preset.name,
    1828            1 :         if (roomAliasName != null) 'room_alias_name': roomAliasName,
    1829            1 :         if (roomVersion != null) 'room_version': roomVersion,
    1830            1 :         if (topic != null) 'topic': topic,
    1831            2 :         if (visibility != null) 'visibility': visibility.name,
    1832              :       }),
    1833              :     );
    1834           12 :     final response = await httpClient.send(request);
    1835           12 :     final responseBody = await response.stream.toBytes();
    1836           12 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1837            6 :     final responseString = utf8.decode(responseBody);
    1838            6 :     final json = jsonDecode(responseString);
    1839            6 :     return json['room_id'] as String;
    1840              :   }
    1841              : 
    1842              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api).
    1843              :   ///
    1844              :   /// Deletes the given devices, and invalidates any access token associated with them.
    1845              :   ///
    1846              :   /// **WARNING:**
    1847              :   /// Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained
    1848              :   /// via the [OAuth 2.0 API](https://spec.matrix.org/unstable/client-server-api/#oauth-20-api).
    1849              :   ///
    1850              :   ///
    1851              :   /// [auth] Additional authentication information for the
    1852              :   /// user-interactive authentication API.
    1853              :   ///
    1854              :   /// [devices] The list of device IDs to delete.
    1855            0 :   Future<void> deleteDevices(
    1856              :     List<String> devices, {
    1857              :     AuthenticationData? auth,
    1858              :   }) async {
    1859            0 :     final requestUri = Uri(path: '_matrix/client/v3/delete_devices');
    1860            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    1861            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1862            0 :     request.headers['content-type'] = 'application/json';
    1863            0 :     request.bodyBytes = utf8.encode(
    1864            0 :       jsonEncode({
    1865            0 :         if (auth != null) 'auth': auth.toJson(),
    1866            0 :         'devices': devices.map((v) => v).toList(),
    1867              :       }),
    1868              :     );
    1869            0 :     final response = await httpClient.send(request);
    1870            0 :     final responseBody = await response.stream.toBytes();
    1871            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1872            0 :     final responseString = utf8.decode(responseBody);
    1873            0 :     final json = jsonDecode(responseString);
    1874            0 :     return ignore(json);
    1875              :   }
    1876              : 
    1877              :   /// Gets information about all devices for the current user.
    1878              :   ///
    1879              :   /// returns `devices`:
    1880              :   /// A list of all registered devices for this user.
    1881            0 :   Future<List<Device>?> getDevices() async {
    1882            0 :     final requestUri = Uri(path: '_matrix/client/v3/devices');
    1883            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    1884            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1885            0 :     final response = await httpClient.send(request);
    1886            0 :     final responseBody = await response.stream.toBytes();
    1887            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1888            0 :     final responseString = utf8.decode(responseBody);
    1889            0 :     final json = jsonDecode(responseString);
    1890            0 :     return ((v) => v != null
    1891              :         ? (v as List)
    1892            0 :             .map((v) => Device.fromJson(v as Map<String, Object?>))
    1893            0 :             .toList()
    1894            0 :         : null)(json['devices']);
    1895              :   }
    1896              : 
    1897              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api).
    1898              :   ///
    1899              :   /// Deletes the given device, and invalidates any access token associated with it.
    1900              :   ///
    1901              :   /// **WARNING:**
    1902              :   /// Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained
    1903              :   /// via the [OAuth 2.0 API](https://spec.matrix.org/unstable/client-server-api/#oauth-20-api).
    1904              :   ///
    1905              :   ///
    1906              :   /// [deviceId] The device to delete.
    1907              :   ///
    1908              :   /// [auth] Additional authentication information for the
    1909              :   /// user-interactive authentication API.
    1910            0 :   Future<void> deleteDevice(String deviceId, {AuthenticationData? auth}) async {
    1911              :     final requestUri =
    1912            0 :         Uri(path: '_matrix/client/v3/devices/${Uri.encodeComponent(deviceId)}');
    1913            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    1914            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1915            0 :     request.headers['content-type'] = 'application/json';
    1916            0 :     request.bodyBytes = utf8.encode(
    1917            0 :       jsonEncode({
    1918            0 :         if (auth != null) 'auth': auth.toJson(),
    1919              :       }),
    1920              :     );
    1921            0 :     final response = await httpClient.send(request);
    1922            0 :     final responseBody = await response.stream.toBytes();
    1923            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1924            0 :     final responseString = utf8.decode(responseBody);
    1925            0 :     final json = jsonDecode(responseString);
    1926            0 :     return ignore(json);
    1927              :   }
    1928              : 
    1929              :   /// Gets information on a single device, by device id.
    1930              :   ///
    1931              :   /// [deviceId] The device to retrieve.
    1932            0 :   Future<Device> getDevice(String deviceId) async {
    1933              :     final requestUri =
    1934            0 :         Uri(path: '_matrix/client/v3/devices/${Uri.encodeComponent(deviceId)}');
    1935            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    1936            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1937            0 :     final response = await httpClient.send(request);
    1938            0 :     final responseBody = await response.stream.toBytes();
    1939            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1940            0 :     final responseString = utf8.decode(responseBody);
    1941            0 :     final json = jsonDecode(responseString);
    1942            0 :     return Device.fromJson(json as Map<String, Object?>);
    1943              :   }
    1944              : 
    1945              :   /// Updates the metadata on the given device.
    1946              :   ///
    1947              :   /// [deviceId] The device to update.
    1948              :   ///
    1949              :   /// [displayName] The new display name for this device. If not given, the
    1950              :   /// display name is unchanged.
    1951            0 :   Future<void> updateDevice(String deviceId, {String? displayName}) async {
    1952              :     final requestUri =
    1953            0 :         Uri(path: '_matrix/client/v3/devices/${Uri.encodeComponent(deviceId)}');
    1954            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    1955            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    1956            0 :     request.headers['content-type'] = 'application/json';
    1957            0 :     request.bodyBytes = utf8.encode(
    1958            0 :       jsonEncode({
    1959            0 :         if (displayName != null) 'display_name': displayName,
    1960              :       }),
    1961              :     );
    1962            0 :     final response = await httpClient.send(request);
    1963            0 :     final responseBody = await response.stream.toBytes();
    1964            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    1965            0 :     final responseString = utf8.decode(responseBody);
    1966            0 :     final json = jsonDecode(responseString);
    1967            0 :     return ignore(json);
    1968              :   }
    1969              : 
    1970              :   /// Updates the visibility of a given room in the application service's
    1971              :   /// published room directory.
    1972              :   ///
    1973              :   /// This API is similar to the
    1974              :   /// [visibility API](https://spec.matrix.org/unstable/client-server-api#put_matrixclientv3directorylistroomroomid)
    1975              :   /// used by clients to update the homeserver's more general published room directory.
    1976              :   ///
    1977              :   /// This API requires the use of an application service access token (`as_token`)
    1978              :   /// instead of a typical client's access_token. This API cannot be invoked by
    1979              :   /// users who are not identified as application services.
    1980              :   ///
    1981              :   /// [networkId] The protocol (network) ID to update the room list for. This would
    1982              :   /// have been provided by the application service as being listed as
    1983              :   /// a supported protocol.
    1984              :   ///
    1985              :   /// [roomId] The room ID to add to the directory.
    1986              :   ///
    1987              :   /// [visibility] Whether the room should be visible (public) in the directory
    1988              :   /// or not (private).
    1989            0 :   Future<Map<String, Object?>> updateAppserviceRoomDirectoryVisibility(
    1990              :     String networkId,
    1991              :     String roomId,
    1992              :     Visibility visibility,
    1993              :   ) async {
    1994            0 :     final requestUri = Uri(
    1995              :       path:
    1996            0 :           '_matrix/client/v3/directory/list/appservice/${Uri.encodeComponent(networkId)}/${Uri.encodeComponent(roomId)}',
    1997              :     );
    1998            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    1999            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2000            0 :     request.headers['content-type'] = 'application/json';
    2001            0 :     request.bodyBytes = utf8.encode(
    2002            0 :       jsonEncode({
    2003            0 :         'visibility': visibility.name,
    2004              :       }),
    2005              :     );
    2006            0 :     final response = await httpClient.send(request);
    2007            0 :     final responseBody = await response.stream.toBytes();
    2008            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2009            0 :     final responseString = utf8.decode(responseBody);
    2010            0 :     final json = jsonDecode(responseString);
    2011              :     return json as Map<String, Object?>;
    2012              :   }
    2013              : 
    2014              :   /// Gets the visibility of a given room in the server's
    2015              :   /// published room directory.
    2016              :   ///
    2017              :   /// [roomId] The room ID.
    2018              :   ///
    2019              :   /// returns `visibility`:
    2020              :   /// The visibility of the room in the directory.
    2021            0 :   Future<Visibility?> getRoomVisibilityOnDirectory(String roomId) async {
    2022            0 :     final requestUri = Uri(
    2023              :       path:
    2024            0 :           '_matrix/client/v3/directory/list/room/${Uri.encodeComponent(roomId)}',
    2025              :     );
    2026            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2027            0 :     final response = await httpClient.send(request);
    2028            0 :     final responseBody = await response.stream.toBytes();
    2029            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2030            0 :     final responseString = utf8.decode(responseBody);
    2031            0 :     final json = jsonDecode(responseString);
    2032            0 :     return ((v) => v != null
    2033            0 :         ? Visibility.values.fromString(v as String)!
    2034            0 :         : null)(json['visibility']);
    2035              :   }
    2036              : 
    2037              :   /// Sets the visibility of a given room in the server's published room directory.
    2038              :   ///
    2039              :   /// Servers MAY implement additional access control checks, for instance,
    2040              :   /// to ensure that a room's visibility can only be changed by the room creator
    2041              :   /// or a server administrator.
    2042              :   ///
    2043              :   /// [roomId] The room ID.
    2044              :   ///
    2045              :   /// [visibility] The new visibility setting for the room.
    2046              :   /// Defaults to `public`.
    2047            0 :   Future<void> setRoomVisibilityOnDirectory(
    2048              :     String roomId, {
    2049              :     Visibility? visibility,
    2050              :   }) async {
    2051            0 :     final requestUri = Uri(
    2052              :       path:
    2053            0 :           '_matrix/client/v3/directory/list/room/${Uri.encodeComponent(roomId)}',
    2054              :     );
    2055            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    2056            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2057            0 :     request.headers['content-type'] = 'application/json';
    2058            0 :     request.bodyBytes = utf8.encode(
    2059            0 :       jsonEncode({
    2060            0 :         if (visibility != null) 'visibility': visibility.name,
    2061              :       }),
    2062              :     );
    2063            0 :     final response = await httpClient.send(request);
    2064            0 :     final responseBody = await response.stream.toBytes();
    2065            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2066            0 :     final responseString = utf8.decode(responseBody);
    2067            0 :     final json = jsonDecode(responseString);
    2068            0 :     return ignore(json);
    2069              :   }
    2070              : 
    2071              :   /// Remove a mapping of room alias to room ID.
    2072              :   ///
    2073              :   /// Servers may choose to implement additional access control checks here, for instance that
    2074              :   /// room aliases can only be deleted by their creator or a server administrator.
    2075              :   ///
    2076              :   /// **Note:**
    2077              :   /// Servers may choose to update the `alt_aliases` for the `m.room.canonical_alias`
    2078              :   /// state event in the room when an alias is removed. Servers which choose to update the
    2079              :   /// canonical alias event are recommended to, in addition to their other relevant permission
    2080              :   /// checks, delete the alias and return a successful response even if the user does not
    2081              :   /// have permission to update the `m.room.canonical_alias` event.
    2082              :   ///
    2083              :   /// [roomAlias] The room alias to remove. Its format is defined
    2084              :   /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases).
    2085              :   ///
    2086            0 :   Future<void> deleteRoomAlias(String roomAlias) async {
    2087            0 :     final requestUri = Uri(
    2088              :       path:
    2089            0 :           '_matrix/client/v3/directory/room/${Uri.encodeComponent(roomAlias)}',
    2090              :     );
    2091            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    2092            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2093            0 :     final response = await httpClient.send(request);
    2094            0 :     final responseBody = await response.stream.toBytes();
    2095            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2096            0 :     final responseString = utf8.decode(responseBody);
    2097            0 :     final json = jsonDecode(responseString);
    2098            0 :     return ignore(json);
    2099              :   }
    2100              : 
    2101              :   /// Requests that the server resolve a room alias to a room ID.
    2102              :   ///
    2103              :   /// The server will use the federation API to resolve the alias if the
    2104              :   /// domain part of the alias does not correspond to the server's own
    2105              :   /// domain.
    2106              :   ///
    2107              :   /// [roomAlias] The room alias. Its format is defined
    2108              :   /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases).
    2109              :   ///
    2110            0 :   Future<GetRoomIdByAliasResponse> getRoomIdByAlias(String roomAlias) async {
    2111            0 :     final requestUri = Uri(
    2112              :       path:
    2113            0 :           '_matrix/client/v3/directory/room/${Uri.encodeComponent(roomAlias)}',
    2114              :     );
    2115            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2116            0 :     final response = await httpClient.send(request);
    2117            0 :     final responseBody = await response.stream.toBytes();
    2118            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2119            0 :     final responseString = utf8.decode(responseBody);
    2120            0 :     final json = jsonDecode(responseString);
    2121            0 :     return GetRoomIdByAliasResponse.fromJson(json as Map<String, Object?>);
    2122              :   }
    2123              : 
    2124              :   ///
    2125              :   ///
    2126              :   /// [roomAlias] The room alias to set. Its format is defined
    2127              :   /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases).
    2128              :   ///
    2129              :   ///
    2130              :   /// [roomId] The room ID to set.
    2131            0 :   Future<void> setRoomAlias(String roomAlias, String roomId) async {
    2132            0 :     final requestUri = Uri(
    2133              :       path:
    2134            0 :           '_matrix/client/v3/directory/room/${Uri.encodeComponent(roomAlias)}',
    2135              :     );
    2136            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    2137            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2138            0 :     request.headers['content-type'] = 'application/json';
    2139            0 :     request.bodyBytes = utf8.encode(
    2140            0 :       jsonEncode({
    2141              :         'room_id': roomId,
    2142              :       }),
    2143              :     );
    2144            0 :     final response = await httpClient.send(request);
    2145            0 :     final responseBody = await response.stream.toBytes();
    2146            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2147            0 :     final responseString = utf8.decode(responseBody);
    2148            0 :     final json = jsonDecode(responseString);
    2149            0 :     return ignore(json);
    2150              :   }
    2151              : 
    2152              :   /// This will listen for new events and return them to the caller. This will
    2153              :   /// block until an event is received, or until the `timeout` is reached.
    2154              :   ///
    2155              :   /// This endpoint was deprecated in r0 of this specification. Clients
    2156              :   /// should instead call the [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync)
    2157              :   /// endpoint with a `since` parameter. See
    2158              :   /// the [migration guide](https://matrix.org/docs/guides/migrating-from-client-server-api-v-1#deprecated-endpoints).
    2159              :   ///
    2160              :   /// [from] The token to stream from. This token is either from a previous
    2161              :   /// request to this API or from the initial sync API.
    2162              :   ///
    2163              :   /// [timeout] The maximum time in milliseconds to wait for an event.
    2164            0 :   @deprecated
    2165              :   Future<GetEventsResponse> getEvents({String? from, int? timeout}) async {
    2166            0 :     final requestUri = Uri(
    2167              :       path: '_matrix/client/v3/events',
    2168            0 :       queryParameters: {
    2169            0 :         if (from != null) 'from': from,
    2170            0 :         if (timeout != null) 'timeout': timeout.toString(),
    2171              :       },
    2172              :     );
    2173            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2174            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2175            0 :     final response = await httpClient.send(request);
    2176            0 :     final responseBody = await response.stream.toBytes();
    2177            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2178            0 :     final responseString = utf8.decode(responseBody);
    2179            0 :     final json = jsonDecode(responseString);
    2180            0 :     return GetEventsResponse.fromJson(json as Map<String, Object?>);
    2181              :   }
    2182              : 
    2183              :   /// This will listen for new events related to a particular room and return
    2184              :   /// them to the caller. This will block until an event is received, or until
    2185              :   /// the `timeout` is reached.
    2186              :   ///
    2187              :   /// This API is the same as the normal `/events` endpoint, but can be
    2188              :   /// called by users who have not joined the room.
    2189              :   ///
    2190              :   /// Note that the normal `/events` endpoint has been deprecated. This
    2191              :   /// API will also be deprecated at some point, but its replacement is not
    2192              :   /// yet known.
    2193              :   ///
    2194              :   /// [from] The token to stream from. This token is either from a previous
    2195              :   /// request to this API or from the initial sync API.
    2196              :   ///
    2197              :   /// [timeout] The maximum time in milliseconds to wait for an event.
    2198              :   ///
    2199              :   /// [roomId] The room ID for which events should be returned.
    2200            0 :   Future<PeekEventsResponse> peekEvents({
    2201              :     String? from,
    2202              :     int? timeout,
    2203              :     String? roomId,
    2204              :   }) async {
    2205            0 :     final requestUri = Uri(
    2206              :       path: '_matrix/client/v3/events',
    2207            0 :       queryParameters: {
    2208            0 :         if (from != null) 'from': from,
    2209            0 :         if (timeout != null) 'timeout': timeout.toString(),
    2210            0 :         if (roomId != null) 'room_id': roomId,
    2211              :       },
    2212              :     );
    2213            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2214            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2215            0 :     final response = await httpClient.send(request);
    2216            0 :     final responseBody = await response.stream.toBytes();
    2217            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2218            0 :     final responseString = utf8.decode(responseBody);
    2219            0 :     final json = jsonDecode(responseString);
    2220            0 :     return PeekEventsResponse.fromJson(json as Map<String, Object?>);
    2221              :   }
    2222              : 
    2223              :   /// Get a single event based on `event_id`. You must have permission to
    2224              :   /// retrieve this event e.g. by being a member in the room for this event.
    2225              :   ///
    2226              :   /// This endpoint was deprecated in r0 of this specification. Clients
    2227              :   /// should instead call the
    2228              :   /// [/rooms/{roomId}/event/{eventId}](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomideventeventid) API
    2229              :   /// or the [/rooms/{roomId}/context/{eventId](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidcontexteventid) API.
    2230              :   ///
    2231              :   /// [eventId] The event ID to get.
    2232            0 :   @deprecated
    2233              :   Future<MatrixEvent> getOneEvent(String eventId) async {
    2234              :     final requestUri =
    2235            0 :         Uri(path: '_matrix/client/v3/events/${Uri.encodeComponent(eventId)}');
    2236            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2237            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2238            0 :     final response = await httpClient.send(request);
    2239            0 :     final responseBody = await response.stream.toBytes();
    2240            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2241            0 :     final responseString = utf8.decode(responseBody);
    2242            0 :     final json = jsonDecode(responseString);
    2243            0 :     return MatrixEvent.fromJson(json as Map<String, Object?>);
    2244              :   }
    2245              : 
    2246              :   /// *Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.
    2247              :   ///
    2248              :   /// This API starts a user's participation in a particular room, if that user
    2249              :   /// is allowed to participate in that room. After this call, the client is
    2250              :   /// allowed to see all current state events in the room, and all subsequent
    2251              :   /// events associated with the room until the user leaves the room.
    2252              :   ///
    2253              :   /// After a user has joined a room, the room will appear as an entry in the
    2254              :   /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3initialsync)
    2255              :   /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) APIs.
    2256              :   ///
    2257              :   /// [roomIdOrAlias] The room identifier or alias to join.
    2258              :   ///
    2259              :   /// [via] The servers to attempt to join the room through. One of the servers
    2260              :   /// must be participating in the room.
    2261              :   ///
    2262              :   /// [reason] Optional reason to be included as the `reason` on the subsequent
    2263              :   /// membership event.
    2264              :   ///
    2265              :   /// [thirdPartySigned] If a `third_party_signed` was supplied, the homeserver must verify
    2266              :   /// that it matches a pending `m.room.third_party_invite` event in the
    2267              :   /// room, and perform key validity checking if required by the event.
    2268              :   ///
    2269              :   /// returns `room_id`:
    2270              :   /// The joined room ID.
    2271            1 :   Future<String> joinRoom(
    2272              :     String roomIdOrAlias, {
    2273              :     List<String>? via,
    2274              :     String? reason,
    2275              :     ThirdPartySigned? thirdPartySigned,
    2276              :   }) async {
    2277            1 :     final requestUri = Uri(
    2278            2 :       path: '_matrix/client/v3/join/${Uri.encodeComponent(roomIdOrAlias)}',
    2279            1 :       queryParameters: {
    2280            0 :         if (via != null) 'via': via,
    2281              :       },
    2282              :     );
    2283            3 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2284            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2285            2 :     request.headers['content-type'] = 'application/json';
    2286            2 :     request.bodyBytes = utf8.encode(
    2287            2 :       jsonEncode({
    2288            0 :         if (reason != null) 'reason': reason,
    2289              :         if (thirdPartySigned != null)
    2290            0 :           'third_party_signed': thirdPartySigned.toJson(),
    2291              :       }),
    2292              :     );
    2293            2 :     final response = await httpClient.send(request);
    2294            2 :     final responseBody = await response.stream.toBytes();
    2295            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2296            1 :     final responseString = utf8.decode(responseBody);
    2297            1 :     final json = jsonDecode(responseString);
    2298            1 :     return json['room_id'] as String;
    2299              :   }
    2300              : 
    2301              :   /// This API returns a list of the user's current rooms.
    2302              :   ///
    2303              :   /// returns `joined_rooms`:
    2304              :   /// The ID of each room in which the user has `joined` membership.
    2305            0 :   Future<List<String>> getJoinedRooms() async {
    2306            0 :     final requestUri = Uri(path: '_matrix/client/v3/joined_rooms');
    2307            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2308            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2309            0 :     final response = await httpClient.send(request);
    2310            0 :     final responseBody = await response.stream.toBytes();
    2311            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2312            0 :     final responseString = utf8.decode(responseBody);
    2313            0 :     final json = jsonDecode(responseString);
    2314            0 :     return (json['joined_rooms'] as List).map((v) => v as String).toList();
    2315              :   }
    2316              : 
    2317              :   /// Gets a list of users who have updated their device identity keys since a
    2318              :   /// previous sync token.
    2319              :   ///
    2320              :   /// The server should include in the results any users who:
    2321              :   ///
    2322              :   /// * currently share a room with the calling user (ie, both users have
    2323              :   ///   membership state `join`); *and*
    2324              :   /// * added new device identity keys or removed an existing device with
    2325              :   ///   identity keys, between `from` and `to`.
    2326              :   ///
    2327              :   /// [from] The desired start point of the list. Should be the `next_batch` field
    2328              :   /// from a response to an earlier call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync). Users who have not
    2329              :   /// uploaded new device identity keys since this point, nor deleted
    2330              :   /// existing devices with identity keys since then, will be excluded
    2331              :   /// from the results.
    2332              :   ///
    2333              :   /// [to] The desired end point of the list. Should be the `next_batch`
    2334              :   /// field from a recent call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) - typically the most recent
    2335              :   /// such call. This may be used by the server as a hint to check its
    2336              :   /// caches are up to date.
    2337            0 :   Future<GetKeysChangesResponse> getKeysChanges(String from, String to) async {
    2338            0 :     final requestUri = Uri(
    2339              :       path: '_matrix/client/v3/keys/changes',
    2340            0 :       queryParameters: {
    2341              :         'from': from,
    2342              :         'to': to,
    2343              :       },
    2344              :     );
    2345            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2346            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2347            0 :     final response = await httpClient.send(request);
    2348            0 :     final responseBody = await response.stream.toBytes();
    2349            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2350            0 :     final responseString = utf8.decode(responseBody);
    2351            0 :     final json = jsonDecode(responseString);
    2352            0 :     return GetKeysChangesResponse.fromJson(json as Map<String, Object?>);
    2353              :   }
    2354              : 
    2355              :   /// Claims one-time keys for use in pre-key messages.
    2356              :   ///
    2357              :   /// The request contains the user ID, device ID and algorithm name of the
    2358              :   /// keys that are required. If a key matching these requirements can be
    2359              :   /// found, the response contains it. The returned key is a one-time key
    2360              :   /// if one is available, and otherwise a fallback key.
    2361              :   ///
    2362              :   /// One-time keys are given out in the order that they were uploaded via
    2363              :   /// [/keys/upload](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysupload). (All
    2364              :   /// keys uploaded within a given call to `/keys/upload` are considered
    2365              :   /// equivalent in this regard; no ordering is specified within them.)
    2366              :   ///
    2367              :   /// Servers must ensure that each one-time key is returned at most once,
    2368              :   /// so when a key has been returned, no other request will ever return
    2369              :   /// the same key.
    2370              :   ///
    2371              :   /// [oneTimeKeys] The keys to be claimed. A map from user ID, to a map from
    2372              :   /// device ID to algorithm name.
    2373              :   ///
    2374              :   /// [timeout] The time (in milliseconds) to wait when downloading keys from
    2375              :   /// remote servers. 10 seconds is the recommended default.
    2376           28 :   Future<ClaimKeysResponse> claimKeys(
    2377              :     Map<String, Map<String, String>> oneTimeKeys, {
    2378              :     int? timeout,
    2379              :   }) async {
    2380           28 :     final requestUri = Uri(path: '_matrix/client/v3/keys/claim');
    2381           84 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2382          112 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2383           56 :     request.headers['content-type'] = 'application/json';
    2384           56 :     request.bodyBytes = utf8.encode(
    2385           56 :       jsonEncode({
    2386           28 :         'one_time_keys': oneTimeKeys
    2387          168 :             .map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))),
    2388           28 :         if (timeout != null) 'timeout': timeout,
    2389              :       }),
    2390              :     );
    2391           56 :     final response = await httpClient.send(request);
    2392           56 :     final responseBody = await response.stream.toBytes();
    2393           56 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2394           28 :     final responseString = utf8.decode(responseBody);
    2395           28 :     final json = jsonDecode(responseString);
    2396           28 :     return ClaimKeysResponse.fromJson(json as Map<String, Object?>);
    2397              :   }
    2398              : 
    2399              :   /// Publishes cross-signing keys for the user.
    2400              :   ///
    2401              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api).
    2402              :   ///
    2403              :   /// User-Interactive Authentication MUST be performed, except in these cases:
    2404              :   /// - there is no existing cross-signing master key uploaded to the homeserver, OR
    2405              :   /// - there is an existing cross-signing master key and it exactly matches the
    2406              :   ///   cross-signing master key provided in the request body. If there are any additional
    2407              :   ///   keys provided in the request (self-signing key, user-signing key) they MUST also
    2408              :   ///   match the existing keys stored on the server. In other words, the request contains
    2409              :   ///   no new keys.
    2410              :   ///
    2411              :   /// This allows clients to freely upload one set of keys, but not modify/overwrite keys if
    2412              :   /// they already exist. Allowing clients to upload the same set of keys more than once
    2413              :   /// makes this endpoint idempotent in the case where the response is lost over the network,
    2414              :   /// which would otherwise cause a UIA challenge upon retry.
    2415              :   ///
    2416              :   /// **WARNING:**
    2417              :   /// When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained
    2418              :   /// via the [OAuth 2.0 API](https://spec.matrix.org/unstable/client-server-api/#oauth-20-api).
    2419              :   ///
    2420              :   ///
    2421              :   /// [auth] Additional authentication information for the
    2422              :   /// user-interactive authentication API.
    2423              :   ///
    2424              :   /// [masterKey] Optional. The user\'s master key.
    2425              :   ///
    2426              :   /// [selfSigningKey] Optional. The user\'s self-signing key. Must be signed by
    2427              :   /// the accompanying master key, or by the user\'s most recently
    2428              :   /// uploaded master key if no master key is included in the
    2429              :   /// request.
    2430              :   ///
    2431              :   /// [userSigningKey] Optional. The user\'s user-signing key. Must be signed by
    2432              :   /// the accompanying master key, or by the user\'s most recently
    2433              :   /// uploaded master key if no master key is included in the
    2434              :   /// request.
    2435            1 :   Future<void> uploadCrossSigningKeys({
    2436              :     AuthenticationData? auth,
    2437              :     MatrixCrossSigningKey? masterKey,
    2438              :     MatrixCrossSigningKey? selfSigningKey,
    2439              :     MatrixCrossSigningKey? userSigningKey,
    2440              :   }) async {
    2441              :     final requestUri =
    2442            1 :         Uri(path: '_matrix/client/v3/keys/device_signing/upload');
    2443            3 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2444            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2445            2 :     request.headers['content-type'] = 'application/json';
    2446            2 :     request.bodyBytes = utf8.encode(
    2447            2 :       jsonEncode({
    2448            0 :         if (auth != null) 'auth': auth.toJson(),
    2449            2 :         if (masterKey != null) 'master_key': masterKey.toJson(),
    2450            2 :         if (selfSigningKey != null) 'self_signing_key': selfSigningKey.toJson(),
    2451            2 :         if (userSigningKey != null) 'user_signing_key': userSigningKey.toJson(),
    2452              :       }),
    2453              :     );
    2454            2 :     final response = await httpClient.send(request);
    2455            2 :     final responseBody = await response.stream.toBytes();
    2456            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2457            1 :     final responseString = utf8.decode(responseBody);
    2458            1 :     final json = jsonDecode(responseString);
    2459            1 :     return ignore(json);
    2460              :   }
    2461              : 
    2462              :   /// Returns the current devices and identity keys for the given users.
    2463              :   ///
    2464              :   /// [deviceKeys] The keys to be downloaded. A map from user ID, to a list of
    2465              :   /// device IDs, or to an empty list to indicate all devices for the
    2466              :   /// corresponding user.
    2467              :   ///
    2468              :   /// [timeout] The time (in milliseconds) to wait when downloading keys from
    2469              :   /// remote servers. 10 seconds is the recommended default.
    2470           40 :   Future<QueryKeysResponse> queryKeys(
    2471              :     Map<String, List<String>> deviceKeys, {
    2472              :     int? timeout,
    2473              :   }) async {
    2474           40 :     final requestUri = Uri(path: '_matrix/client/v3/keys/query');
    2475          120 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2476          160 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2477           80 :     request.headers['content-type'] = 'application/json';
    2478           80 :     request.bodyBytes = utf8.encode(
    2479           80 :       jsonEncode({
    2480           40 :         'device_keys':
    2481          200 :             deviceKeys.map((k, v) => MapEntry(k, v.map((v) => v).toList())),
    2482           40 :         if (timeout != null) 'timeout': timeout,
    2483              :       }),
    2484              :     );
    2485           80 :     final response = await httpClient.send(request);
    2486           80 :     final responseBody = await response.stream.toBytes();
    2487           80 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2488           40 :     final responseString = utf8.decode(responseBody);
    2489           40 :     final json = jsonDecode(responseString);
    2490           40 :     return QueryKeysResponse.fromJson(json as Map<String, Object?>);
    2491              :   }
    2492              : 
    2493              :   /// Publishes cross-signing signatures for the user.
    2494              :   ///
    2495              :   /// The signed JSON object must match the key previously uploaded or
    2496              :   /// retrieved for the given key ID, with the exception of the `signatures`
    2497              :   /// property, which contains the new signature(s) to add.
    2498              :   ///
    2499              :   /// [body] A map from user ID to key ID to signed JSON objects containing the
    2500              :   /// signatures to be published.
    2501              :   ///
    2502              :   /// returns `failures`:
    2503              :   /// A map from user ID to key ID to an error for any signatures
    2504              :   /// that failed.  If a signature was invalid, the `errcode` will
    2505              :   /// be set to `M_INVALID_SIGNATURE`.
    2506            7 :   Future<Map<String, Map<String, Map<String, Object?>>>?>
    2507              :       uploadCrossSigningSignatures(
    2508              :     Map<String, Map<String, Map<String, Object?>>> body,
    2509              :   ) async {
    2510            7 :     final requestUri = Uri(path: '_matrix/client/v3/keys/signatures/upload');
    2511           21 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2512           28 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2513           14 :     request.headers['content-type'] = 'application/json';
    2514           14 :     request.bodyBytes = utf8.encode(
    2515            7 :       jsonEncode(
    2516           42 :         body.map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))),
    2517              :       ),
    2518              :     );
    2519           14 :     final response = await httpClient.send(request);
    2520           14 :     final responseBody = await response.stream.toBytes();
    2521           14 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2522            7 :     final responseString = utf8.decode(responseBody);
    2523            7 :     final json = jsonDecode(responseString);
    2524            7 :     return ((v) => v != null
    2525            7 :         ? (v as Map<String, Object?>).map(
    2526            0 :             (k, v) => MapEntry(
    2527              :               k,
    2528              :               (v as Map<String, Object?>)
    2529            0 :                   .map((k, v) => MapEntry(k, v as Map<String, Object?>)),
    2530              :             ),
    2531              :           )
    2532           14 :         : null)(json['failures']);
    2533              :   }
    2534              : 
    2535              :   /// Publishes end-to-end encryption keys for the device.
    2536              :   ///
    2537              :   /// [deviceKeys] Identity keys for the device. May be absent if no new
    2538              :   /// identity keys are required.
    2539              :   ///
    2540              :   /// [fallbackKeys] The public key which should be used if the device's one-time keys
    2541              :   /// are exhausted. The fallback key is not deleted once used, but should
    2542              :   /// be replaced when additional one-time keys are being uploaded. The
    2543              :   /// server will notify the client of the fallback key being used through
    2544              :   /// `/sync`.
    2545              :   ///
    2546              :   /// There can only be at most one key per algorithm uploaded, and the server
    2547              :   /// will only persist one key per algorithm.
    2548              :   ///
    2549              :   /// When uploading a signed key, an additional `fallback: true` key should
    2550              :   /// be included to denote that the key is a fallback key.
    2551              :   ///
    2552              :   /// May be absent if a new fallback key is not required.
    2553              :   ///
    2554              :   /// [oneTimeKeys] One-time public keys for "pre-key" messages.  The names of
    2555              :   /// the properties should be in the format
    2556              :   /// `<algorithm>:<key_id>`. The format of the key is determined
    2557              :   /// by the [key algorithm](https://spec.matrix.org/unstable/client-server-api/#key-algorithms).
    2558              :   ///
    2559              :   /// May be absent if no new one-time keys are required.
    2560              :   ///
    2561              :   /// returns `one_time_key_counts`:
    2562              :   /// For each key algorithm, the number of unclaimed one-time keys
    2563              :   /// of that type currently held on the server for this device.
    2564              :   /// If an algorithm is not listed, the count for that algorithm
    2565              :   /// is to be assumed zero.
    2566            6 :   Future<Map<String, int>> uploadKeys({
    2567              :     MatrixDeviceKeys? deviceKeys,
    2568              :     Map<String, Object?>? fallbackKeys,
    2569              :     Map<String, Object?>? oneTimeKeys,
    2570              :   }) async {
    2571            6 :     final requestUri = Uri(path: '_matrix/client/v3/keys/upload');
    2572           18 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2573           24 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2574           12 :     request.headers['content-type'] = 'application/json';
    2575           12 :     request.bodyBytes = utf8.encode(
    2576           12 :       jsonEncode({
    2577           12 :         if (deviceKeys != null) 'device_keys': deviceKeys.toJson(),
    2578            6 :         if (fallbackKeys != null) 'fallback_keys': fallbackKeys,
    2579            6 :         if (oneTimeKeys != null) 'one_time_keys': oneTimeKeys,
    2580              :       }),
    2581              :     );
    2582           12 :     final response = await httpClient.send(request);
    2583           12 :     final responseBody = await response.stream.toBytes();
    2584           12 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2585            6 :     final responseString = utf8.decode(responseBody);
    2586            6 :     final json = jsonDecode(responseString);
    2587            6 :     return (json['one_time_key_counts'] as Map<String, Object?>)
    2588           18 :         .map((k, v) => MapEntry(k, v as int));
    2589              :   }
    2590              : 
    2591              :   /// *Note that this API takes either a room ID or alias, unlike other membership APIs.*
    2592              :   ///
    2593              :   /// This API "knocks" on the room to ask for permission to join, if the user
    2594              :   /// is allowed to knock on the room. Acceptance of the knock happens out of
    2595              :   /// band from this API, meaning that the client will have to watch for updates
    2596              :   /// regarding the acceptance/rejection of the knock.
    2597              :   ///
    2598              :   /// If the room history settings allow, the user will still be able to see
    2599              :   /// history of the room while being in the "knock" state. The user will have
    2600              :   /// to accept the invitation to join the room (acceptance of knock) to see
    2601              :   /// messages reliably. See the `/join` endpoints for more information about
    2602              :   /// history visibility to the user.
    2603              :   ///
    2604              :   /// The knock will appear as an entry in the response of the
    2605              :   /// [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) API.
    2606              :   ///
    2607              :   /// [roomIdOrAlias] The room identifier or alias to knock upon.
    2608              :   ///
    2609              :   /// [via] The servers to attempt to knock on the room through. One of the servers
    2610              :   /// must be participating in the room.
    2611              :   ///
    2612              :   /// [reason] Optional reason to be included as the `reason` on the subsequent
    2613              :   /// membership event.
    2614              :   ///
    2615              :   /// returns `room_id`:
    2616              :   /// The knocked room ID.
    2617            0 :   Future<String> knockRoom(
    2618              :     String roomIdOrAlias, {
    2619              :     List<String>? via,
    2620              :     String? reason,
    2621              :   }) async {
    2622            0 :     final requestUri = Uri(
    2623            0 :       path: '_matrix/client/v3/knock/${Uri.encodeComponent(roomIdOrAlias)}',
    2624            0 :       queryParameters: {
    2625            0 :         if (via != null) 'via': via,
    2626              :       },
    2627              :     );
    2628            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2629            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2630            0 :     request.headers['content-type'] = 'application/json';
    2631            0 :     request.bodyBytes = utf8.encode(
    2632            0 :       jsonEncode({
    2633            0 :         if (reason != null) 'reason': reason,
    2634              :       }),
    2635              :     );
    2636            0 :     final response = await httpClient.send(request);
    2637            0 :     final responseBody = await response.stream.toBytes();
    2638            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2639            0 :     final responseString = utf8.decode(responseBody);
    2640            0 :     final json = jsonDecode(responseString);
    2641            0 :     return json['room_id'] as String;
    2642              :   }
    2643              : 
    2644              :   /// Gets the homeserver's supported login types to authenticate users. Clients
    2645              :   /// should pick one of these and supply it as the `type` when logging in.
    2646              :   ///
    2647              :   /// returns `flows`:
    2648              :   /// The homeserver's supported login types
    2649           42 :   Future<List<LoginFlow>?> getLoginFlows() async {
    2650           42 :     final requestUri = Uri(path: '_matrix/client/v3/login');
    2651          126 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2652           84 :     final response = await httpClient.send(request);
    2653           84 :     final responseBody = await response.stream.toBytes();
    2654           84 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2655           42 :     final responseString = utf8.decode(responseBody);
    2656           42 :     final json = jsonDecode(responseString);
    2657           42 :     return ((v) => v != null
    2658              :         ? (v as List)
    2659          126 :             .map((v) => LoginFlow.fromJson(v as Map<String, Object?>))
    2660           42 :             .toList()
    2661           84 :         : null)(json['flows']);
    2662              :   }
    2663              : 
    2664              :   /// Authenticates the user, and issues an access token they can
    2665              :   /// use to authorize themself in subsequent requests.
    2666              :   ///
    2667              :   /// If the client does not supply a `device_id`, the server must
    2668              :   /// auto-generate one.
    2669              :   ///
    2670              :   /// The returned access token must be associated with the `device_id`
    2671              :   /// supplied by the client or generated by the server. The server may
    2672              :   /// invalidate any access token previously associated with that device. See
    2673              :   /// [Relationship between access tokens and devices](https://spec.matrix.org/unstable/client-server-api/#relationship-between-access-tokens-and-devices).
    2674              :   ///
    2675              :   /// [address] Third-party identifier for the user.  Deprecated in favour of `identifier`.
    2676              :   ///
    2677              :   /// [deviceId] ID of the client device. If this does not correspond to a
    2678              :   /// known client device, a new device will be created. The given
    2679              :   /// device ID must not be the same as a
    2680              :   /// [cross-signing](https://spec.matrix.org/unstable/client-server-api/#cross-signing) key ID.
    2681              :   /// The server will auto-generate a device_id
    2682              :   /// if this is not specified.
    2683              :   ///
    2684              :   /// [identifier] Identification information for a user
    2685              :   ///
    2686              :   /// [initialDeviceDisplayName] A display name to assign to the newly-created device. Ignored
    2687              :   /// if `device_id` corresponds to a known device.
    2688              :   ///
    2689              :   /// [medium] When logging in using a third-party identifier, the medium of the identifier. Must be 'email'.  Deprecated in favour of `identifier`.
    2690              :   ///
    2691              :   /// [password] Required when `type` is `m.login.password`. The user's
    2692              :   /// password.
    2693              :   ///
    2694              :   /// [refreshToken] If true, the client supports refresh tokens.
    2695              :   ///
    2696              :   /// [token] Required when `type` is `m.login.token`. Part of Token-based login.
    2697              :   ///
    2698              :   /// [type] The login type being used.
    2699              :   ///
    2700              :   /// This must be a type returned in one of the flows of the
    2701              :   /// response of the [`GET /login`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3login)
    2702              :   /// endpoint, like `m.login.password` or `m.login.token`.
    2703              :   ///
    2704              :   /// [user] The fully qualified user ID or just local part of the user ID, to log in.  Deprecated in favour of `identifier`.
    2705            5 :   Future<LoginResponse> login(
    2706              :     String type, {
    2707              :     String? address,
    2708              :     String? deviceId,
    2709              :     AuthenticationIdentifier? identifier,
    2710              :     String? initialDeviceDisplayName,
    2711              :     String? medium,
    2712              :     String? password,
    2713              :     bool? refreshToken,
    2714              :     String? token,
    2715              :     String? user,
    2716              :   }) async {
    2717            5 :     final requestUri = Uri(path: '_matrix/client/v3/login');
    2718           15 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2719           10 :     request.headers['content-type'] = 'application/json';
    2720           10 :     request.bodyBytes = utf8.encode(
    2721           10 :       jsonEncode({
    2722            0 :         if (address != null) 'address': address,
    2723            1 :         if (deviceId != null) 'device_id': deviceId,
    2724           10 :         if (identifier != null) 'identifier': identifier.toJson(),
    2725              :         if (initialDeviceDisplayName != null)
    2726            0 :           'initial_device_display_name': initialDeviceDisplayName,
    2727            0 :         if (medium != null) 'medium': medium,
    2728            5 :         if (password != null) 'password': password,
    2729            5 :         if (refreshToken != null) 'refresh_token': refreshToken,
    2730            1 :         if (token != null) 'token': token,
    2731            5 :         'type': type,
    2732            0 :         if (user != null) 'user': user,
    2733              :       }),
    2734              :     );
    2735           10 :     final response = await httpClient.send(request);
    2736           10 :     final responseBody = await response.stream.toBytes();
    2737           10 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2738            5 :     final responseString = utf8.decode(responseBody);
    2739            5 :     final json = jsonDecode(responseString);
    2740            5 :     return LoginResponse.fromJson(json as Map<String, Object?>);
    2741              :   }
    2742              : 
    2743              :   /// Invalidates an existing access token, so that it can no longer be used for
    2744              :   /// authorization. The device associated with the access token is also deleted.
    2745              :   /// [Device keys](https://spec.matrix.org/unstable/client-server-api/#device-keys) for the device are deleted alongside the device.
    2746           12 :   Future<void> logout() async {
    2747           12 :     final requestUri = Uri(path: '_matrix/client/v3/logout');
    2748           36 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2749           48 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2750           24 :     final response = await httpClient.send(request);
    2751           24 :     final responseBody = await response.stream.toBytes();
    2752           25 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2753           12 :     final responseString = utf8.decode(responseBody);
    2754           12 :     final json = jsonDecode(responseString);
    2755           12 :     return ignore(json);
    2756              :   }
    2757              : 
    2758              :   /// Invalidates all access tokens for a user, so that they can no longer be used for
    2759              :   /// authorization. This includes the access token that made this request. All devices
    2760              :   /// for the user are also deleted. [Device keys](https://spec.matrix.org/unstable/client-server-api/#device-keys) for the device are
    2761              :   /// deleted alongside the device.
    2762              :   ///
    2763              :   /// This endpoint does not use the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api) because
    2764              :   /// User-Interactive Authentication is designed to protect against attacks where
    2765              :   /// someone gets hold of a single access token then takes over the account. This
    2766              :   /// endpoint invalidates all access tokens for the user, including the token used in
    2767              :   /// the request, and therefore the attacker is unable to take over the account in
    2768              :   /// this way.
    2769            0 :   Future<void> logoutAll() async {
    2770            0 :     final requestUri = Uri(path: '_matrix/client/v3/logout/all');
    2771            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    2772            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2773            0 :     final response = await httpClient.send(request);
    2774            0 :     final responseBody = await response.stream.toBytes();
    2775            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2776            0 :     final responseString = utf8.decode(responseBody);
    2777            0 :     final json = jsonDecode(responseString);
    2778            0 :     return ignore(json);
    2779              :   }
    2780              : 
    2781              :   /// This API is used to paginate through the list of events that the
    2782              :   /// user has been, or would have been notified about.
    2783              :   ///
    2784              :   /// [from] Pagination token to continue from. This should be the `next_token`
    2785              :   /// returned from an earlier call to this endpoint.
    2786              :   ///
    2787              :   /// [limit] Limit on the number of events to return in this request.
    2788              :   ///
    2789              :   /// [only] Allows basic filtering of events returned. Supply `highlight`
    2790              :   /// to return only events where the notification had the highlight
    2791              :   /// tweak set.
    2792            0 :   Future<GetNotificationsResponse> getNotifications({
    2793              :     String? from,
    2794              :     int? limit,
    2795              :     String? only,
    2796              :   }) async {
    2797            0 :     final requestUri = Uri(
    2798              :       path: '_matrix/client/v3/notifications',
    2799            0 :       queryParameters: {
    2800            0 :         if (from != null) 'from': from,
    2801            0 :         if (limit != null) 'limit': limit.toString(),
    2802            0 :         if (only != null) 'only': only,
    2803              :       },
    2804              :     );
    2805            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2806            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2807            0 :     final response = await httpClient.send(request);
    2808            0 :     final responseBody = await response.stream.toBytes();
    2809            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2810            0 :     final responseString = utf8.decode(responseBody);
    2811            0 :     final json = jsonDecode(responseString);
    2812            0 :     return GetNotificationsResponse.fromJson(json as Map<String, Object?>);
    2813              :   }
    2814              : 
    2815              :   /// Get the given user's presence state.
    2816              :   ///
    2817              :   /// [userId] The user whose presence state to get.
    2818            0 :   Future<GetPresenceResponse> getPresence(String userId) async {
    2819            0 :     final requestUri = Uri(
    2820            0 :       path: '_matrix/client/v3/presence/${Uri.encodeComponent(userId)}/status',
    2821              :     );
    2822            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2823            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2824            0 :     final response = await httpClient.send(request);
    2825            0 :     final responseBody = await response.stream.toBytes();
    2826            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2827            0 :     final responseString = utf8.decode(responseBody);
    2828            0 :     final json = jsonDecode(responseString);
    2829            0 :     return GetPresenceResponse.fromJson(json as Map<String, Object?>);
    2830              :   }
    2831              : 
    2832              :   /// This API sets the given user's presence state. When setting the status,
    2833              :   /// the activity time is updated to reflect that activity; the client does
    2834              :   /// not need to specify the `last_active_ago` field. You cannot set the
    2835              :   /// presence state of another user.
    2836              :   ///
    2837              :   /// [userId] The user whose presence state to update.
    2838              :   ///
    2839              :   /// [presence] The new presence state.
    2840              :   ///
    2841              :   /// [statusMsg] The status message to attach to this state.
    2842            0 :   Future<void> setPresence(
    2843              :     String userId,
    2844              :     PresenceType presence, {
    2845              :     String? statusMsg,
    2846              :   }) async {
    2847            0 :     final requestUri = Uri(
    2848            0 :       path: '_matrix/client/v3/presence/${Uri.encodeComponent(userId)}/status',
    2849              :     );
    2850            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    2851            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2852            0 :     request.headers['content-type'] = 'application/json';
    2853            0 :     request.bodyBytes = utf8.encode(
    2854            0 :       jsonEncode({
    2855            0 :         'presence': presence.name,
    2856            0 :         if (statusMsg != null) 'status_msg': statusMsg,
    2857              :       }),
    2858              :     );
    2859            0 :     final response = await httpClient.send(request);
    2860            0 :     final responseBody = await response.stream.toBytes();
    2861            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2862            0 :     final responseString = utf8.decode(responseBody);
    2863            0 :     final json = jsonDecode(responseString);
    2864            0 :     return ignore(json);
    2865              :   }
    2866              : 
    2867              :   /// Get the complete profile for a user.
    2868              :   ///
    2869              :   /// [userId] The user whose profile information to get.
    2870            5 :   Future<ProfileInformation> getUserProfile(String userId) async {
    2871              :     final requestUri =
    2872           15 :         Uri(path: '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}');
    2873           11 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2874            3 :     if (bearerToken != null) {
    2875           12 :       request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2876              :     }
    2877            6 :     final response = await httpClient.send(request);
    2878            6 :     final responseBody = await response.stream.toBytes();
    2879            7 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2880            3 :     final responseString = utf8.decode(responseBody);
    2881            3 :     final json = jsonDecode(responseString);
    2882            3 :     return ProfileInformation.fromJson(json as Map<String, Object?>);
    2883              :   }
    2884              : 
    2885              :   /// Remove a specific field from a user's profile.
    2886              :   ///
    2887              :   /// [userId] The user whose profile field should be deleted.
    2888              :   ///
    2889              :   /// [keyName] The name of the profile field to delete.
    2890            0 :   Future<Map<String, Object?>> deleteProfileField(
    2891              :     String userId,
    2892              :     String keyName,
    2893              :   ) async {
    2894            0 :     final requestUri = Uri(
    2895              :       path:
    2896            0 :           '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/${Uri.encodeComponent(keyName)}',
    2897              :     );
    2898            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    2899            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2900            0 :     final response = await httpClient.send(request);
    2901            0 :     final responseBody = await response.stream.toBytes();
    2902            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2903            0 :     final responseString = utf8.decode(responseBody);
    2904            0 :     final json = jsonDecode(responseString);
    2905              :     return json as Map<String, Object?>;
    2906              :   }
    2907              : 
    2908              :   /// Get the value of a profile field for a user.
    2909              :   ///
    2910              :   /// [userId] The user whose profile field should be returned.
    2911              :   ///
    2912              :   /// [keyName] The name of the profile field to retrieve.
    2913            0 :   Future<Map<String, Object?>> getProfileField(
    2914              :     String userId,
    2915              :     String keyName,
    2916              :   ) async {
    2917            0 :     final requestUri = Uri(
    2918              :       path:
    2919            0 :           '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/${Uri.encodeComponent(keyName)}',
    2920              :     );
    2921            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2922            0 :     if (bearerToken != null) {
    2923            0 :       request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2924              :     }
    2925            0 :     final response = await httpClient.send(request);
    2926            0 :     final responseBody = await response.stream.toBytes();
    2927            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2928            0 :     final responseString = utf8.decode(responseBody);
    2929            0 :     final json = jsonDecode(responseString);
    2930              :     return json as Map<String, Object?>;
    2931              :   }
    2932              : 
    2933              :   /// Set or update a profile field for a user. Must be authenticated with an
    2934              :   /// access token authorised to make changes. Servers MAY impose size limits
    2935              :   /// on individual fields, and the total profile MUST be under 64 KiB.
    2936              :   ///
    2937              :   /// Servers MAY reject `null` values. Servers that accept `null` values SHOULD store
    2938              :   /// them rather than treating `null` as a deletion request. Clients that want to delete a
    2939              :   /// field, including its key and value, SHOULD use the `DELETE` endpoint instead.
    2940              :   ///
    2941              :   /// [userId] The user whose profile field should be set.
    2942              :   ///
    2943              :   /// [keyName] The name of the profile field to set. This MUST be either `avatar_url`, `displayname`, `m.tz`, or a custom field following the [Common Namespaced Identifier Grammar](https://spec.matrix.org/unstable/appendices/#common-namespaced-identifier-grammar).
    2944              :   ///
    2945              :   /// [body] A JSON object containing the property whose name matches the `keyName` specified in the URL. See `additionalProperties` for further details.
    2946            1 :   Future<Map<String, Object?>> setProfileField(
    2947              :     String userId,
    2948              :     String keyName,
    2949              :     Map<String, Object?> body,
    2950              :   ) async {
    2951            1 :     final requestUri = Uri(
    2952              :       path:
    2953            3 :           '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/${Uri.encodeComponent(keyName)}',
    2954              :     );
    2955            3 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    2956            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    2957            2 :     request.headers['content-type'] = 'application/json';
    2958            3 :     request.bodyBytes = utf8.encode(jsonEncode(body));
    2959            2 :     final response = await httpClient.send(request);
    2960            2 :     final responseBody = await response.stream.toBytes();
    2961            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2962            1 :     final responseString = utf8.decode(responseBody);
    2963            1 :     final json = jsonDecode(responseString);
    2964              :     return json as Map<String, Object?>;
    2965              :   }
    2966              : 
    2967              :   /// Lists a server's published room directory.
    2968              :   ///
    2969              :   /// This API returns paginated responses. The rooms are ordered by the number
    2970              :   /// of joined members, with the largest rooms first.
    2971              :   ///
    2972              :   /// [limit] Limit the number of results returned.
    2973              :   ///
    2974              :   /// [since] A pagination token from a previous request, allowing clients to
    2975              :   /// get the next (or previous) batch of rooms.
    2976              :   /// The direction of pagination is specified solely by which token
    2977              :   /// is supplied, rather than via an explicit flag.
    2978              :   ///
    2979              :   /// [server] The server to fetch the published room directory from. Defaults
    2980              :   /// to the local server. Case sensitive.
    2981            0 :   Future<GetPublicRoomsResponse> getPublicRooms({
    2982              :     int? limit,
    2983              :     String? since,
    2984              :     String? server,
    2985              :   }) async {
    2986            0 :     final requestUri = Uri(
    2987              :       path: '_matrix/client/v3/publicRooms',
    2988            0 :       queryParameters: {
    2989            0 :         if (limit != null) 'limit': limit.toString(),
    2990            0 :         if (since != null) 'since': since,
    2991            0 :         if (server != null) 'server': server,
    2992              :       },
    2993              :     );
    2994            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    2995            0 :     final response = await httpClient.send(request);
    2996            0 :     final responseBody = await response.stream.toBytes();
    2997            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    2998            0 :     final responseString = utf8.decode(responseBody);
    2999            0 :     final json = jsonDecode(responseString);
    3000            0 :     return GetPublicRoomsResponse.fromJson(json as Map<String, Object?>);
    3001              :   }
    3002              : 
    3003              :   /// Lists a server's published room directory with an optional filter.
    3004              :   ///
    3005              :   /// This API returns paginated responses. The rooms are ordered by the number
    3006              :   /// of joined members, with the largest rooms first.
    3007              :   ///
    3008              :   /// [server] The server to fetch the published room directory from. Defaults
    3009              :   /// to the local server. Case sensitive.
    3010              :   ///
    3011              :   /// [filter] Filter to apply to the results.
    3012              :   ///
    3013              :   /// [includeAllNetworks] Whether or not to include all known networks/protocols from
    3014              :   /// application services on the homeserver. Defaults to false.
    3015              :   ///
    3016              :   /// [limit] Limit the number of results returned.
    3017              :   ///
    3018              :   /// [since] A pagination token from a previous request, allowing clients
    3019              :   /// to get the next (or previous) batch of rooms.  The direction
    3020              :   /// of pagination is specified solely by which token is supplied,
    3021              :   /// rather than via an explicit flag.
    3022              :   ///
    3023              :   /// [thirdPartyInstanceId] The specific third-party network/protocol to request from the
    3024              :   /// homeserver. Can only be used if `include_all_networks` is false.
    3025              :   ///
    3026              :   /// This is the `instance_id` of a `Protocol Instance` returned by
    3027              :   /// [`GET /_matrix/client/v3/thirdparty/protocols`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3thirdpartyprotocols).
    3028            0 :   Future<QueryPublicRoomsResponse> queryPublicRooms({
    3029              :     String? server,
    3030              :     PublicRoomQueryFilter? filter,
    3031              :     bool? includeAllNetworks,
    3032              :     int? limit,
    3033              :     String? since,
    3034              :     String? thirdPartyInstanceId,
    3035              :   }) async {
    3036            0 :     final requestUri = Uri(
    3037              :       path: '_matrix/client/v3/publicRooms',
    3038            0 :       queryParameters: {
    3039            0 :         if (server != null) 'server': server,
    3040              :       },
    3041              :     );
    3042            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    3043            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3044            0 :     request.headers['content-type'] = 'application/json';
    3045            0 :     request.bodyBytes = utf8.encode(
    3046            0 :       jsonEncode({
    3047            0 :         if (filter != null) 'filter': filter.toJson(),
    3048              :         if (includeAllNetworks != null)
    3049            0 :           'include_all_networks': includeAllNetworks,
    3050            0 :         if (limit != null) 'limit': limit,
    3051            0 :         if (since != null) 'since': since,
    3052              :         if (thirdPartyInstanceId != null)
    3053            0 :           'third_party_instance_id': thirdPartyInstanceId,
    3054              :       }),
    3055              :     );
    3056            0 :     final response = await httpClient.send(request);
    3057            0 :     final responseBody = await response.stream.toBytes();
    3058            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3059            0 :     final responseString = utf8.decode(responseBody);
    3060            0 :     final json = jsonDecode(responseString);
    3061            0 :     return QueryPublicRoomsResponse.fromJson(json as Map<String, Object?>);
    3062              :   }
    3063              : 
    3064              :   /// Gets all currently active pushers for the authenticated user.
    3065              :   ///
    3066              :   /// returns `pushers`:
    3067              :   /// An array containing the current pushers for the user
    3068            0 :   Future<List<Pusher>?> getPushers() async {
    3069            0 :     final requestUri = Uri(path: '_matrix/client/v3/pushers');
    3070            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3071            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3072            0 :     final response = await httpClient.send(request);
    3073            0 :     final responseBody = await response.stream.toBytes();
    3074            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3075            0 :     final responseString = utf8.decode(responseBody);
    3076            0 :     final json = jsonDecode(responseString);
    3077            0 :     return ((v) => v != null
    3078              :         ? (v as List)
    3079            0 :             .map((v) => Pusher.fromJson(v as Map<String, Object?>))
    3080            0 :             .toList()
    3081            0 :         : null)(json['pushers']);
    3082              :   }
    3083              : 
    3084              :   /// Retrieve all push rulesets for this user. Currently the only push ruleset
    3085              :   /// defined is `global`.
    3086              :   ///
    3087              :   /// returns `global`:
    3088              :   /// The global ruleset.
    3089            0 :   Future<PushRuleSet> getPushRules() async {
    3090            0 :     final requestUri = Uri(path: '_matrix/client/v3/pushrules/');
    3091            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3092            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3093            0 :     final response = await httpClient.send(request);
    3094            0 :     final responseBody = await response.stream.toBytes();
    3095            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3096            0 :     final responseString = utf8.decode(responseBody);
    3097            0 :     final json = jsonDecode(responseString);
    3098            0 :     return PushRuleSet.fromJson(json['global'] as Map<String, Object?>);
    3099              :   }
    3100              : 
    3101              :   /// Retrieve all push rules for this user.
    3102            0 :   Future<GetPushRulesGlobalResponse> getPushRulesGlobal() async {
    3103            0 :     final requestUri = Uri(path: '_matrix/client/v3/pushrules/global/');
    3104            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3105            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3106            0 :     final response = await httpClient.send(request);
    3107            0 :     final responseBody = await response.stream.toBytes();
    3108            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3109            0 :     final responseString = utf8.decode(responseBody);
    3110            0 :     final json = jsonDecode(responseString);
    3111            0 :     return GetPushRulesGlobalResponse.fromJson(json as Map<String, Object?>);
    3112              :   }
    3113              : 
    3114              :   /// This endpoint removes the push rule defined in the path.
    3115              :   ///
    3116              :   /// [kind] The kind of rule
    3117              :   ///
    3118              :   ///
    3119              :   /// [ruleId] The identifier for the rule.
    3120              :   ///
    3121            2 :   Future<void> deletePushRule(PushRuleKind kind, String ruleId) async {
    3122            2 :     final requestUri = Uri(
    3123              :       path:
    3124            8 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}',
    3125              :     );
    3126            6 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    3127            8 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3128            4 :     final response = await httpClient.send(request);
    3129            4 :     final responseBody = await response.stream.toBytes();
    3130            4 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3131            2 :     final responseString = utf8.decode(responseBody);
    3132            2 :     final json = jsonDecode(responseString);
    3133            2 :     return ignore(json);
    3134              :   }
    3135              : 
    3136              :   /// Retrieve a single specified push rule.
    3137              :   ///
    3138              :   /// [kind] The kind of rule
    3139              :   ///
    3140              :   ///
    3141              :   /// [ruleId] The identifier for the rule.
    3142              :   ///
    3143            0 :   Future<PushRule> getPushRule(PushRuleKind kind, String ruleId) async {
    3144            0 :     final requestUri = Uri(
    3145              :       path:
    3146            0 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}',
    3147              :     );
    3148            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3149            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3150            0 :     final response = await httpClient.send(request);
    3151            0 :     final responseBody = await response.stream.toBytes();
    3152            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3153            0 :     final responseString = utf8.decode(responseBody);
    3154            0 :     final json = jsonDecode(responseString);
    3155            0 :     return PushRule.fromJson(json as Map<String, Object?>);
    3156              :   }
    3157              : 
    3158              :   /// This endpoint allows the creation and modification of user defined push
    3159              :   /// rules.
    3160              :   ///
    3161              :   /// If a rule with the same `rule_id` already exists among rules of the same
    3162              :   /// kind, it is updated with the new parameters, otherwise a new rule is
    3163              :   /// created.
    3164              :   ///
    3165              :   /// If both `after` and `before` are provided, the new or updated rule must
    3166              :   /// be the next most important rule with respect to the rule identified by
    3167              :   /// `before`.
    3168              :   ///
    3169              :   /// If neither `after` nor `before` are provided and the rule is created, it
    3170              :   /// should be added as the most important user defined rule among rules of
    3171              :   /// the same kind.
    3172              :   ///
    3173              :   /// When creating push rules, they MUST be enabled by default.
    3174              :   ///
    3175              :   /// [kind] The kind of rule
    3176              :   ///
    3177              :   ///
    3178              :   /// [ruleId] The identifier for the rule. If the string starts with a dot ("."),
    3179              :   /// the request MUST be rejected as this is reserved for server-default
    3180              :   /// rules. Slashes ("/") and backslashes ("\\") are also not allowed.
    3181              :   ///
    3182              :   ///
    3183              :   /// [before] Use 'before' with a `rule_id` as its value to make the new rule the
    3184              :   /// next-most important rule with respect to the given user defined rule.
    3185              :   /// It is not possible to add a rule relative to a predefined server rule.
    3186              :   ///
    3187              :   /// [after] This makes the new rule the next-less important rule relative to the
    3188              :   /// given user defined rule. It is not possible to add a rule relative
    3189              :   /// to a predefined server rule.
    3190              :   ///
    3191              :   /// [actions] The action(s) to perform when the conditions for this rule are met.
    3192              :   ///
    3193              :   /// [conditions] The conditions that must hold true for an event in order for a
    3194              :   /// rule to be applied to an event. A rule with no conditions
    3195              :   /// always matches. Only applicable to `underride` and `override` rules.
    3196              :   ///
    3197              :   /// [pattern] Only applicable to `content` rules. The glob-style pattern to match against.
    3198            2 :   Future<void> setPushRule(
    3199              :     PushRuleKind kind,
    3200              :     String ruleId,
    3201              :     List<Object?> actions, {
    3202              :     String? before,
    3203              :     String? after,
    3204              :     List<PushCondition>? conditions,
    3205              :     String? pattern,
    3206              :   }) async {
    3207            2 :     final requestUri = Uri(
    3208              :       path:
    3209            8 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}',
    3210            2 :       queryParameters: {
    3211            0 :         if (before != null) 'before': before,
    3212            0 :         if (after != null) 'after': after,
    3213              :       },
    3214              :     );
    3215            6 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    3216            8 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3217            4 :     request.headers['content-type'] = 'application/json';
    3218            4 :     request.bodyBytes = utf8.encode(
    3219            4 :       jsonEncode({
    3220            6 :         'actions': actions.map((v) => v).toList(),
    3221              :         if (conditions != null)
    3222            0 :           'conditions': conditions.map((v) => v.toJson()).toList(),
    3223            0 :         if (pattern != null) 'pattern': pattern,
    3224              :       }),
    3225              :     );
    3226            4 :     final response = await httpClient.send(request);
    3227            4 :     final responseBody = await response.stream.toBytes();
    3228            4 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3229            2 :     final responseString = utf8.decode(responseBody);
    3230            2 :     final json = jsonDecode(responseString);
    3231            2 :     return ignore(json);
    3232              :   }
    3233              : 
    3234              :   /// This endpoint get the actions for the specified push rule.
    3235              :   ///
    3236              :   /// [kind] The kind of rule
    3237              :   ///
    3238              :   ///
    3239              :   /// [ruleId] The identifier for the rule.
    3240              :   ///
    3241              :   ///
    3242              :   /// returns `actions`:
    3243              :   /// The action(s) to perform for this rule.
    3244            0 :   Future<List<Object?>> getPushRuleActions(
    3245              :     PushRuleKind kind,
    3246              :     String ruleId,
    3247              :   ) async {
    3248            0 :     final requestUri = Uri(
    3249              :       path:
    3250            0 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/actions',
    3251              :     );
    3252            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3253            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3254            0 :     final response = await httpClient.send(request);
    3255            0 :     final responseBody = await response.stream.toBytes();
    3256            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3257            0 :     final responseString = utf8.decode(responseBody);
    3258            0 :     final json = jsonDecode(responseString);
    3259            0 :     return (json['actions'] as List).map((v) => v as Object?).toList();
    3260              :   }
    3261              : 
    3262              :   /// This endpoint allows clients to change the actions of a push rule.
    3263              :   /// This can be used to change the actions of builtin rules.
    3264              :   ///
    3265              :   /// [kind] The kind of rule
    3266              :   ///
    3267              :   ///
    3268              :   /// [ruleId] The identifier for the rule.
    3269              :   ///
    3270              :   ///
    3271              :   /// [actions] The action(s) to perform for this rule.
    3272            0 :   Future<void> setPushRuleActions(
    3273              :     PushRuleKind kind,
    3274              :     String ruleId,
    3275              :     List<Object?> actions,
    3276              :   ) async {
    3277            0 :     final requestUri = Uri(
    3278              :       path:
    3279            0 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/actions',
    3280              :     );
    3281            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    3282            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3283            0 :     request.headers['content-type'] = 'application/json';
    3284            0 :     request.bodyBytes = utf8.encode(
    3285            0 :       jsonEncode({
    3286            0 :         'actions': actions.map((v) => v).toList(),
    3287              :       }),
    3288              :     );
    3289            0 :     final response = await httpClient.send(request);
    3290            0 :     final responseBody = await response.stream.toBytes();
    3291            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3292            0 :     final responseString = utf8.decode(responseBody);
    3293            0 :     final json = jsonDecode(responseString);
    3294            0 :     return ignore(json);
    3295              :   }
    3296              : 
    3297              :   /// This endpoint gets whether the specified push rule is enabled.
    3298              :   ///
    3299              :   /// [kind] The kind of rule
    3300              :   ///
    3301              :   ///
    3302              :   /// [ruleId] The identifier for the rule.
    3303              :   ///
    3304              :   ///
    3305              :   /// returns `enabled`:
    3306              :   /// Whether the push rule is enabled or not.
    3307            0 :   Future<bool> isPushRuleEnabled(PushRuleKind kind, String ruleId) async {
    3308            0 :     final requestUri = Uri(
    3309              :       path:
    3310            0 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/enabled',
    3311              :     );
    3312            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3313            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3314            0 :     final response = await httpClient.send(request);
    3315            0 :     final responseBody = await response.stream.toBytes();
    3316            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3317            0 :     final responseString = utf8.decode(responseBody);
    3318            0 :     final json = jsonDecode(responseString);
    3319            0 :     return json['enabled'] as bool;
    3320              :   }
    3321              : 
    3322              :   /// This endpoint allows clients to enable or disable the specified push rule.
    3323              :   ///
    3324              :   /// [kind] The kind of rule
    3325              :   ///
    3326              :   ///
    3327              :   /// [ruleId] The identifier for the rule.
    3328              :   ///
    3329              :   ///
    3330              :   /// [enabled] Whether the push rule is enabled or not.
    3331            1 :   Future<void> setPushRuleEnabled(
    3332              :     PushRuleKind kind,
    3333              :     String ruleId,
    3334              :     bool enabled,
    3335              :   ) async {
    3336            1 :     final requestUri = Uri(
    3337              :       path:
    3338            4 :           '_matrix/client/v3/pushrules/global/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/enabled',
    3339              :     );
    3340            3 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    3341            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3342            2 :     request.headers['content-type'] = 'application/json';
    3343            2 :     request.bodyBytes = utf8.encode(
    3344            2 :       jsonEncode({
    3345              :         'enabled': enabled,
    3346              :       }),
    3347              :     );
    3348            2 :     final response = await httpClient.send(request);
    3349            2 :     final responseBody = await response.stream.toBytes();
    3350            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3351            1 :     final responseString = utf8.decode(responseBody);
    3352            1 :     final json = jsonDecode(responseString);
    3353            1 :     return ignore(json);
    3354              :   }
    3355              : 
    3356              :   /// Refresh an access token. Clients should use the returned access token
    3357              :   /// when making subsequent API calls, and store the returned refresh token
    3358              :   /// (if given) in order to refresh the new access token when necessary.
    3359              :   ///
    3360              :   /// After an access token has been refreshed, a server can choose to
    3361              :   /// invalidate the old access token immediately, or can choose not to, for
    3362              :   /// example if the access token would expire soon anyways. Clients should
    3363              :   /// not make any assumptions about the old access token still being valid,
    3364              :   /// and should use the newly provided access token instead.
    3365              :   ///
    3366              :   /// The old refresh token remains valid until the new access token or refresh token
    3367              :   /// is used, at which point the old refresh token is revoked.
    3368              :   ///
    3369              :   /// Note that this endpoint does not require authentication via an
    3370              :   /// access token. Authentication is provided via the refresh token.
    3371              :   ///
    3372              :   /// Application Service identity assertion is disabled for this endpoint.
    3373              :   ///
    3374              :   /// [refreshToken] The refresh token
    3375            0 :   Future<RefreshResponse> refresh(String refreshToken) async {
    3376            0 :     final requestUri = Uri(path: '_matrix/client/v3/refresh');
    3377            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    3378            0 :     request.headers['content-type'] = 'application/json';
    3379            0 :     request.bodyBytes = utf8.encode(
    3380            0 :       jsonEncode({
    3381              :         'refresh_token': refreshToken,
    3382              :       }),
    3383              :     );
    3384            0 :     final response = await httpClient.send(request);
    3385            0 :     final responseBody = await response.stream.toBytes();
    3386            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3387            0 :     final responseString = utf8.decode(responseBody);
    3388            0 :     final json = jsonDecode(responseString);
    3389            0 :     return RefreshResponse.fromJson(json as Map<String, Object?>);
    3390              :   }
    3391              : 
    3392              :   /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api), except in
    3393              :   /// the cases where a guest account is being registered.
    3394              :   ///
    3395              :   /// Register for an account on this homeserver.
    3396              :   ///
    3397              :   /// There are two kinds of user account:
    3398              :   ///
    3399              :   /// - `user` accounts. These accounts may use the full API described in this specification.
    3400              :   ///
    3401              :   /// - `guest` accounts. These accounts may have limited permissions and may not be supported by all servers.
    3402              :   ///
    3403              :   /// If registration is successful, this endpoint will issue an access token
    3404              :   /// the client can use to authorize itself in subsequent requests.
    3405              :   ///
    3406              :   /// If the client does not supply a `device_id`, the server must
    3407              :   /// auto-generate one.
    3408              :   ///
    3409              :   /// The server SHOULD register an account with a User ID based on the
    3410              :   /// `username` provided, if any. Note that the grammar of Matrix User ID
    3411              :   /// localparts is restricted, so the server MUST either map the provided
    3412              :   /// `username` onto a `user_id` in a logical manner, or reject any
    3413              :   /// `username` which does not comply to the grammar with
    3414              :   /// `M_INVALID_USERNAME`.
    3415              :   ///
    3416              :   /// Matrix clients MUST NOT assume that localpart of the registered
    3417              :   /// `user_id` matches the provided `username`.
    3418              :   ///
    3419              :   /// The returned access token must be associated with the `device_id`
    3420              :   /// supplied by the client or generated by the server. The server may
    3421              :   /// invalidate any access token previously associated with that device. See
    3422              :   /// [Relationship between access tokens and devices](https://spec.matrix.org/unstable/client-server-api/#relationship-between-access-tokens-and-devices).
    3423              :   ///
    3424              :   /// When registering a guest account, all parameters in the request body
    3425              :   /// with the exception of `initial_device_display_name` MUST BE ignored
    3426              :   /// by the server. The server MUST pick a `device_id` for the account
    3427              :   /// regardless of input.
    3428              :   ///
    3429              :   /// Any user ID returned by this API must conform to the grammar given in the
    3430              :   /// [Matrix specification](https://spec.matrix.org/unstable/appendices/#user-identifiers).
    3431              :   ///
    3432              :   /// [kind] The kind of account to register. Defaults to `user`.
    3433              :   ///
    3434              :   /// [auth] Additional authentication information for the
    3435              :   /// user-interactive authentication API. Note that this
    3436              :   /// information is *not* used to define how the registered user
    3437              :   /// should be authenticated, but is instead used to
    3438              :   /// authenticate the `register` call itself.
    3439              :   ///
    3440              :   /// [deviceId] ID of the client device. If this does not correspond to a
    3441              :   /// known client device, a new device will be created. The server
    3442              :   /// will auto-generate a device_id if this is not specified.
    3443              :   ///
    3444              :   /// [inhibitLogin] If true, an `access_token` and `device_id` should not be
    3445              :   /// returned from this call, therefore preventing an automatic
    3446              :   /// login. Defaults to false.
    3447              :   ///
    3448              :   /// [initialDeviceDisplayName] A display name to assign to the newly-created device. Ignored
    3449              :   /// if `device_id` corresponds to a known device.
    3450              :   ///
    3451              :   /// [password] The desired password for the account.
    3452              :   ///
    3453              :   /// [refreshToken] If true, the client supports refresh tokens.
    3454              :   ///
    3455              :   /// [username] The basis for the localpart of the desired Matrix ID. If omitted,
    3456              :   /// the homeserver MUST generate a Matrix ID local part.
    3457            0 :   Future<RegisterResponse> register({
    3458              :     AccountKind? kind,
    3459              :     AuthenticationData? auth,
    3460              :     String? deviceId,
    3461              :     bool? inhibitLogin,
    3462              :     String? initialDeviceDisplayName,
    3463              :     String? password,
    3464              :     bool? refreshToken,
    3465              :     String? username,
    3466              :   }) async {
    3467            0 :     final requestUri = Uri(
    3468              :       path: '_matrix/client/v3/register',
    3469            0 :       queryParameters: {
    3470            0 :         if (kind != null) 'kind': kind.name,
    3471              :       },
    3472              :     );
    3473            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    3474            0 :     request.headers['content-type'] = 'application/json';
    3475            0 :     request.bodyBytes = utf8.encode(
    3476            0 :       jsonEncode({
    3477            0 :         if (auth != null) 'auth': auth.toJson(),
    3478            0 :         if (deviceId != null) 'device_id': deviceId,
    3479            0 :         if (inhibitLogin != null) 'inhibit_login': inhibitLogin,
    3480              :         if (initialDeviceDisplayName != null)
    3481            0 :           'initial_device_display_name': initialDeviceDisplayName,
    3482            0 :         if (password != null) 'password': password,
    3483            0 :         if (refreshToken != null) 'refresh_token': refreshToken,
    3484            0 :         if (username != null) 'username': username,
    3485              :       }),
    3486              :     );
    3487            0 :     final response = await httpClient.send(request);
    3488            0 :     final responseBody = await response.stream.toBytes();
    3489            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3490            0 :     final responseString = utf8.decode(responseBody);
    3491            0 :     final json = jsonDecode(responseString);
    3492            0 :     return RegisterResponse.fromJson(json as Map<String, Object?>);
    3493              :   }
    3494              : 
    3495              :   /// Checks to see if a username is available, and valid, for the server.
    3496              :   ///
    3497              :   /// The server should check to ensure that, at the time of the request, the
    3498              :   /// username requested is available for use. This includes verifying that an
    3499              :   /// application service has not claimed the username and that the username
    3500              :   /// fits the server's desired requirements (for example, a server could dictate
    3501              :   /// that it does not permit usernames with underscores).
    3502              :   ///
    3503              :   /// Matrix clients may wish to use this API prior to attempting registration,
    3504              :   /// however the clients must also be aware that using this API does not normally
    3505              :   /// reserve the username. This can mean that the username becomes unavailable
    3506              :   /// between checking its availability and attempting to register it.
    3507              :   ///
    3508              :   /// [username] The username to check the availability of.
    3509              :   ///
    3510              :   /// returns `available`:
    3511              :   /// A flag to indicate that the username is available. This should always
    3512              :   /// be `true` when the server replies with 200 OK.
    3513            1 :   Future<bool?> checkUsernameAvailability(String username) async {
    3514            1 :     final requestUri = Uri(
    3515              :       path: '_matrix/client/v3/register/available',
    3516            1 :       queryParameters: {
    3517              :         'username': username,
    3518              :       },
    3519              :     );
    3520            3 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3521            2 :     final response = await httpClient.send(request);
    3522            2 :     final responseBody = await response.stream.toBytes();
    3523            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3524            1 :     final responseString = utf8.decode(responseBody);
    3525            1 :     final json = jsonDecode(responseString);
    3526            3 :     return ((v) => v != null ? v as bool : null)(json['available']);
    3527              :   }
    3528              : 
    3529              :   /// The homeserver must check that the given email address is **not**
    3530              :   /// already associated with an account on this homeserver. The homeserver
    3531              :   /// should validate the email itself, either by sending a validation email
    3532              :   /// itself or by using a service it has control over.
    3533              :   ///
    3534              :   /// [clientSecret] A unique string generated by the client, and used to identify the
    3535              :   /// validation attempt. It must be a string consisting of the characters
    3536              :   /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it
    3537              :   /// must not be empty.
    3538              :   ///
    3539              :   ///
    3540              :   /// [email] The email address to validate.
    3541              :   ///
    3542              :   /// [nextLink] Optional. When the validation is completed, the identity server will
    3543              :   /// redirect the user to this URL. This option is ignored when submitting
    3544              :   /// 3PID validation information through a POST request.
    3545              :   ///
    3546              :   /// [sendAttempt] The server will only send an email if the `send_attempt`
    3547              :   /// is a number greater than the most recent one which it has seen,
    3548              :   /// scoped to that `email` + `client_secret` pair. This is to
    3549              :   /// avoid repeatedly sending the same email in the case of request
    3550              :   /// retries between the POSTing user and the identity server.
    3551              :   /// The client should increment this value if they desire a new
    3552              :   /// email (e.g. a reminder) to be sent. If they do not, the server
    3553              :   /// should respond with success but not resend the email.
    3554              :   ///
    3555              :   /// [idAccessToken] An access token previously registered with the identity server. Servers
    3556              :   /// can treat this as optional to distinguish between r0.5-compatible clients
    3557              :   /// and this specification version.
    3558              :   ///
    3559              :   /// Required if an `id_server` is supplied.
    3560              :   ///
    3561              :   /// [idServer] The hostname of the identity server to communicate with. May optionally
    3562              :   /// include a port. This parameter is ignored when the homeserver handles
    3563              :   /// 3PID verification.
    3564              :   ///
    3565              :   /// This parameter is deprecated with a plan to be removed in a future specification
    3566              :   /// version for `/account/password` and `/register` requests.
    3567            0 :   Future<RequestTokenResponse> requestTokenToRegisterEmail(
    3568              :     String clientSecret,
    3569              :     String email,
    3570              :     int sendAttempt, {
    3571              :     Uri? nextLink,
    3572              :     String? idAccessToken,
    3573              :     String? idServer,
    3574              :   }) async {
    3575              :     final requestUri =
    3576            0 :         Uri(path: '_matrix/client/v3/register/email/requestToken');
    3577            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    3578            0 :     request.headers['content-type'] = 'application/json';
    3579            0 :     request.bodyBytes = utf8.encode(
    3580            0 :       jsonEncode({
    3581            0 :         'client_secret': clientSecret,
    3582            0 :         'email': email,
    3583            0 :         if (nextLink != null) 'next_link': nextLink.toString(),
    3584            0 :         'send_attempt': sendAttempt,
    3585            0 :         if (idAccessToken != null) 'id_access_token': idAccessToken,
    3586            0 :         if (idServer != null) 'id_server': idServer,
    3587              :       }),
    3588              :     );
    3589            0 :     final response = await httpClient.send(request);
    3590            0 :     final responseBody = await response.stream.toBytes();
    3591            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3592            0 :     final responseString = utf8.decode(responseBody);
    3593            0 :     final json = jsonDecode(responseString);
    3594            0 :     return RequestTokenResponse.fromJson(json as Map<String, Object?>);
    3595              :   }
    3596              : 
    3597              :   /// The homeserver must check that the given phone number is **not**
    3598              :   /// already associated with an account on this homeserver. The homeserver
    3599              :   /// should validate the phone number itself, either by sending a validation
    3600              :   /// message itself or by using a service it has control over.
    3601              :   ///
    3602              :   /// [clientSecret] A unique string generated by the client, and used to identify the
    3603              :   /// validation attempt. It must be a string consisting of the characters
    3604              :   /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it
    3605              :   /// must not be empty.
    3606              :   ///
    3607              :   ///
    3608              :   /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the
    3609              :   /// number in `phone_number` should be parsed as if it were dialled from.
    3610              :   ///
    3611              :   /// [nextLink] Optional. When the validation is completed, the identity server will
    3612              :   /// redirect the user to this URL. This option is ignored when submitting
    3613              :   /// 3PID validation information through a POST request.
    3614              :   ///
    3615              :   /// [phoneNumber] The phone number to validate.
    3616              :   ///
    3617              :   /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a
    3618              :   /// number greater than the most recent one which it has seen,
    3619              :   /// scoped to that `country` + `phone_number` + `client_secret`
    3620              :   /// triple. This is to avoid repeatedly sending the same SMS in
    3621              :   /// the case of request retries between the POSTing user and the
    3622              :   /// identity server. The client should increment this value if
    3623              :   /// they desire a new SMS (e.g. a reminder) to be sent.
    3624              :   ///
    3625              :   /// [idAccessToken] An access token previously registered with the identity server. Servers
    3626              :   /// can treat this as optional to distinguish between r0.5-compatible clients
    3627              :   /// and this specification version.
    3628              :   ///
    3629              :   /// Required if an `id_server` is supplied.
    3630              :   ///
    3631              :   /// [idServer] The hostname of the identity server to communicate with. May optionally
    3632              :   /// include a port. This parameter is ignored when the homeserver handles
    3633              :   /// 3PID verification.
    3634              :   ///
    3635              :   /// This parameter is deprecated with a plan to be removed in a future specification
    3636              :   /// version for `/account/password` and `/register` requests.
    3637            0 :   Future<RequestTokenResponse> requestTokenToRegisterMSISDN(
    3638              :     String clientSecret,
    3639              :     String country,
    3640              :     String phoneNumber,
    3641              :     int sendAttempt, {
    3642              :     Uri? nextLink,
    3643              :     String? idAccessToken,
    3644              :     String? idServer,
    3645              :   }) async {
    3646              :     final requestUri =
    3647            0 :         Uri(path: '_matrix/client/v3/register/msisdn/requestToken');
    3648            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    3649            0 :     request.headers['content-type'] = 'application/json';
    3650            0 :     request.bodyBytes = utf8.encode(
    3651            0 :       jsonEncode({
    3652            0 :         'client_secret': clientSecret,
    3653            0 :         'country': country,
    3654            0 :         if (nextLink != null) 'next_link': nextLink.toString(),
    3655            0 :         'phone_number': phoneNumber,
    3656            0 :         'send_attempt': sendAttempt,
    3657            0 :         if (idAccessToken != null) 'id_access_token': idAccessToken,
    3658            0 :         if (idServer != null) 'id_server': idServer,
    3659              :       }),
    3660              :     );
    3661            0 :     final response = await httpClient.send(request);
    3662            0 :     final responseBody = await response.stream.toBytes();
    3663            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3664            0 :     final responseString = utf8.decode(responseBody);
    3665            0 :     final json = jsonDecode(responseString);
    3666            0 :     return RequestTokenResponse.fromJson(json as Map<String, Object?>);
    3667              :   }
    3668              : 
    3669              :   /// Delete the keys from the backup.
    3670              :   ///
    3671              :   /// [version] The backup from which to delete the key
    3672            0 :   Future<RoomKeysUpdateResponse> deleteRoomKeys(String version) async {
    3673            0 :     final requestUri = Uri(
    3674              :       path: '_matrix/client/v3/room_keys/keys',
    3675            0 :       queryParameters: {
    3676              :         'version': version,
    3677              :       },
    3678              :     );
    3679            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    3680            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3681            0 :     final response = await httpClient.send(request);
    3682            0 :     final responseBody = await response.stream.toBytes();
    3683            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3684            0 :     final responseString = utf8.decode(responseBody);
    3685            0 :     final json = jsonDecode(responseString);
    3686            0 :     return RoomKeysUpdateResponse.fromJson(json as Map<String, Object?>);
    3687              :   }
    3688              : 
    3689              :   /// Retrieve the keys from the backup.
    3690              :   ///
    3691              :   /// [version] The backup from which to retrieve the keys.
    3692            1 :   Future<RoomKeys> getRoomKeys(String version) async {
    3693            1 :     final requestUri = Uri(
    3694              :       path: '_matrix/client/v3/room_keys/keys',
    3695            1 :       queryParameters: {
    3696              :         'version': version,
    3697              :       },
    3698              :     );
    3699            3 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3700            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3701            2 :     final response = await httpClient.send(request);
    3702            2 :     final responseBody = await response.stream.toBytes();
    3703            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3704            1 :     final responseString = utf8.decode(responseBody);
    3705            1 :     final json = jsonDecode(responseString);
    3706            1 :     return RoomKeys.fromJson(json as Map<String, Object?>);
    3707              :   }
    3708              : 
    3709              :   /// Store several keys in the backup.
    3710              :   ///
    3711              :   /// [version] The backup in which to store the keys. Must be the current backup.
    3712              :   ///
    3713              :   /// [body] The backup data.
    3714            4 :   Future<RoomKeysUpdateResponse> putRoomKeys(
    3715              :     String version,
    3716              :     RoomKeys body,
    3717              :   ) async {
    3718            4 :     final requestUri = Uri(
    3719              :       path: '_matrix/client/v3/room_keys/keys',
    3720            4 :       queryParameters: {
    3721              :         'version': version,
    3722              :       },
    3723              :     );
    3724           12 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    3725           16 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3726            8 :     request.headers['content-type'] = 'application/json';
    3727           16 :     request.bodyBytes = utf8.encode(jsonEncode(body.toJson()));
    3728            8 :     final response = await httpClient.send(request);
    3729            8 :     final responseBody = await response.stream.toBytes();
    3730            8 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3731            4 :     final responseString = utf8.decode(responseBody);
    3732            4 :     final json = jsonDecode(responseString);
    3733            4 :     return RoomKeysUpdateResponse.fromJson(json as Map<String, Object?>);
    3734              :   }
    3735              : 
    3736              :   /// Delete the keys from the backup for a given room.
    3737              :   ///
    3738              :   /// [roomId] The ID of the room that the specified key is for.
    3739              :   ///
    3740              :   /// [version] The backup from which to delete the key.
    3741            0 :   Future<RoomKeysUpdateResponse> deleteRoomKeysByRoomId(
    3742              :     String roomId,
    3743              :     String version,
    3744              :   ) async {
    3745            0 :     final requestUri = Uri(
    3746            0 :       path: '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}',
    3747            0 :       queryParameters: {
    3748              :         'version': version,
    3749              :       },
    3750              :     );
    3751            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    3752            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3753            0 :     final response = await httpClient.send(request);
    3754            0 :     final responseBody = await response.stream.toBytes();
    3755            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3756            0 :     final responseString = utf8.decode(responseBody);
    3757            0 :     final json = jsonDecode(responseString);
    3758            0 :     return RoomKeysUpdateResponse.fromJson(json as Map<String, Object?>);
    3759              :   }
    3760              : 
    3761              :   /// Retrieve the keys from the backup for a given room.
    3762              :   ///
    3763              :   /// [roomId] The ID of the room that the requested key is for.
    3764              :   ///
    3765              :   /// [version] The backup from which to retrieve the key.
    3766            1 :   Future<RoomKeyBackup> getRoomKeysByRoomId(
    3767              :     String roomId,
    3768              :     String version,
    3769              :   ) async {
    3770            1 :     final requestUri = Uri(
    3771            2 :       path: '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}',
    3772            1 :       queryParameters: {
    3773              :         'version': version,
    3774              :       },
    3775              :     );
    3776            3 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3777            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3778            2 :     final response = await httpClient.send(request);
    3779            2 :     final responseBody = await response.stream.toBytes();
    3780            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3781            1 :     final responseString = utf8.decode(responseBody);
    3782            1 :     final json = jsonDecode(responseString);
    3783            1 :     return RoomKeyBackup.fromJson(json as Map<String, Object?>);
    3784              :   }
    3785              : 
    3786              :   /// Store several keys in the backup for a given room.
    3787              :   ///
    3788              :   /// [roomId] The ID of the room that the keys are for.
    3789              :   ///
    3790              :   /// [version] The backup in which to store the keys. Must be the current backup.
    3791              :   ///
    3792              :   /// [body] The backup data
    3793            0 :   Future<RoomKeysUpdateResponse> putRoomKeysByRoomId(
    3794              :     String roomId,
    3795              :     String version,
    3796              :     RoomKeyBackup body,
    3797              :   ) async {
    3798            0 :     final requestUri = Uri(
    3799            0 :       path: '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}',
    3800            0 :       queryParameters: {
    3801              :         'version': version,
    3802              :       },
    3803              :     );
    3804            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    3805            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3806            0 :     request.headers['content-type'] = 'application/json';
    3807            0 :     request.bodyBytes = utf8.encode(jsonEncode(body.toJson()));
    3808            0 :     final response = await httpClient.send(request);
    3809            0 :     final responseBody = await response.stream.toBytes();
    3810            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3811            0 :     final responseString = utf8.decode(responseBody);
    3812            0 :     final json = jsonDecode(responseString);
    3813            0 :     return RoomKeysUpdateResponse.fromJson(json as Map<String, Object?>);
    3814              :   }
    3815              : 
    3816              :   /// Delete a key from the backup.
    3817              :   ///
    3818              :   /// [roomId] The ID of the room that the specified key is for.
    3819              :   ///
    3820              :   /// [sessionId] The ID of the megolm session whose key is to be deleted.
    3821              :   ///
    3822              :   /// [version] The backup from which to delete the key
    3823            0 :   Future<RoomKeysUpdateResponse> deleteRoomKeyBySessionId(
    3824              :     String roomId,
    3825              :     String sessionId,
    3826              :     String version,
    3827              :   ) async {
    3828            0 :     final requestUri = Uri(
    3829              :       path:
    3830            0 :           '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}',
    3831            0 :       queryParameters: {
    3832              :         'version': version,
    3833              :       },
    3834              :     );
    3835            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    3836            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3837            0 :     final response = await httpClient.send(request);
    3838            0 :     final responseBody = await response.stream.toBytes();
    3839            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3840            0 :     final responseString = utf8.decode(responseBody);
    3841            0 :     final json = jsonDecode(responseString);
    3842            0 :     return RoomKeysUpdateResponse.fromJson(json as Map<String, Object?>);
    3843              :   }
    3844              : 
    3845              :   /// Retrieve a key from the backup.
    3846              :   ///
    3847              :   /// [roomId] The ID of the room that the requested key is for.
    3848              :   ///
    3849              :   /// [sessionId] The ID of the megolm session whose key is requested.
    3850              :   ///
    3851              :   /// [version] The backup from which to retrieve the key.
    3852            1 :   Future<KeyBackupData> getRoomKeyBySessionId(
    3853              :     String roomId,
    3854              :     String sessionId,
    3855              :     String version,
    3856              :   ) async {
    3857            1 :     final requestUri = Uri(
    3858              :       path:
    3859            3 :           '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}',
    3860            1 :       queryParameters: {
    3861              :         'version': version,
    3862              :       },
    3863              :     );
    3864            3 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3865            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3866            2 :     final response = await httpClient.send(request);
    3867            2 :     final responseBody = await response.stream.toBytes();
    3868            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3869            1 :     final responseString = utf8.decode(responseBody);
    3870            1 :     final json = jsonDecode(responseString);
    3871            1 :     return KeyBackupData.fromJson(json as Map<String, Object?>);
    3872              :   }
    3873              : 
    3874              :   /// Store a key in the backup.
    3875              :   ///
    3876              :   /// [roomId] The ID of the room that the key is for.
    3877              :   ///
    3878              :   /// [sessionId] The ID of the megolm session that the key is for.
    3879              :   ///
    3880              :   /// [version] The backup in which to store the key. Must be the current backup.
    3881              :   ///
    3882              :   /// [body] The key data.
    3883            0 :   Future<RoomKeysUpdateResponse> putRoomKeyBySessionId(
    3884              :     String roomId,
    3885              :     String sessionId,
    3886              :     String version,
    3887              :     KeyBackupData body,
    3888              :   ) async {
    3889            0 :     final requestUri = Uri(
    3890              :       path:
    3891            0 :           '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}',
    3892            0 :       queryParameters: {
    3893              :         'version': version,
    3894              :       },
    3895              :     );
    3896            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    3897            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3898            0 :     request.headers['content-type'] = 'application/json';
    3899            0 :     request.bodyBytes = utf8.encode(jsonEncode(body.toJson()));
    3900            0 :     final response = await httpClient.send(request);
    3901            0 :     final responseBody = await response.stream.toBytes();
    3902            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3903            0 :     final responseString = utf8.decode(responseBody);
    3904            0 :     final json = jsonDecode(responseString);
    3905            0 :     return RoomKeysUpdateResponse.fromJson(json as Map<String, Object?>);
    3906              :   }
    3907              : 
    3908              :   /// Get information about the latest backup version.
    3909            5 :   Future<GetRoomKeysVersionCurrentResponse> getRoomKeysVersionCurrent() async {
    3910            5 :     final requestUri = Uri(path: '_matrix/client/v3/room_keys/version');
    3911           15 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3912           20 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3913           10 :     final response = await httpClient.send(request);
    3914           10 :     final responseBody = await response.stream.toBytes();
    3915           10 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3916            5 :     final responseString = utf8.decode(responseBody);
    3917            5 :     final json = jsonDecode(responseString);
    3918            5 :     return GetRoomKeysVersionCurrentResponse.fromJson(
    3919              :       json as Map<String, Object?>,
    3920              :     );
    3921              :   }
    3922              : 
    3923              :   /// Creates a new backup.
    3924              :   ///
    3925              :   /// [algorithm] The algorithm used for storing backups.
    3926              :   ///
    3927              :   /// [authData] Algorithm-dependent data. See the documentation for the backup
    3928              :   /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the
    3929              :   /// expected format of the data.
    3930              :   ///
    3931              :   /// returns `version`:
    3932              :   /// The backup version. This is an opaque string.
    3933            1 :   Future<String> postRoomKeysVersion(
    3934              :     BackupAlgorithm algorithm,
    3935              :     Map<String, Object?> authData,
    3936              :   ) async {
    3937            1 :     final requestUri = Uri(path: '_matrix/client/v3/room_keys/version');
    3938            3 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    3939            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3940            2 :     request.headers['content-type'] = 'application/json';
    3941            2 :     request.bodyBytes = utf8.encode(
    3942            2 :       jsonEncode({
    3943            1 :         'algorithm': algorithm.name,
    3944              :         'auth_data': authData,
    3945              :       }),
    3946              :     );
    3947            2 :     final response = await httpClient.send(request);
    3948            2 :     final responseBody = await response.stream.toBytes();
    3949            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3950            1 :     final responseString = utf8.decode(responseBody);
    3951            1 :     final json = jsonDecode(responseString);
    3952            1 :     return json['version'] as String;
    3953              :   }
    3954              : 
    3955              :   /// Delete an existing key backup. Both the information about the backup,
    3956              :   /// as well as all key data related to the backup will be deleted.
    3957              :   ///
    3958              :   /// [version] The backup version to delete, as returned in the `version`
    3959              :   /// parameter in the response of
    3960              :   /// [`POST /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3room_keysversion)
    3961              :   /// or [`GET /_matrix/client/v3/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3room_keysversionversion).
    3962            0 :   Future<void> deleteRoomKeysVersion(String version) async {
    3963            0 :     final requestUri = Uri(
    3964              :       path:
    3965            0 :           '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}',
    3966              :     );
    3967            0 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    3968            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3969            0 :     final response = await httpClient.send(request);
    3970            0 :     final responseBody = await response.stream.toBytes();
    3971            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3972            0 :     final responseString = utf8.decode(responseBody);
    3973            0 :     final json = jsonDecode(responseString);
    3974            0 :     return ignore(json);
    3975              :   }
    3976              : 
    3977              :   /// Get information about an existing backup.
    3978              :   ///
    3979              :   /// [version] The backup version to get, as returned in the `version` parameter
    3980              :   /// of the response in
    3981              :   /// [`POST /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3room_keysversion)
    3982              :   /// or this endpoint.
    3983            0 :   Future<GetRoomKeysVersionResponse> getRoomKeysVersion(String version) async {
    3984            0 :     final requestUri = Uri(
    3985              :       path:
    3986            0 :           '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}',
    3987              :     );
    3988            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    3989            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    3990            0 :     final response = await httpClient.send(request);
    3991            0 :     final responseBody = await response.stream.toBytes();
    3992            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    3993            0 :     final responseString = utf8.decode(responseBody);
    3994            0 :     final json = jsonDecode(responseString);
    3995            0 :     return GetRoomKeysVersionResponse.fromJson(json as Map<String, Object?>);
    3996              :   }
    3997              : 
    3998              :   /// Update information about an existing backup.  Only `auth_data` can be modified.
    3999              :   ///
    4000              :   /// [version] The backup version to update, as returned in the `version`
    4001              :   /// parameter in the response of
    4002              :   /// [`POST /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3room_keysversion)
    4003              :   /// or [`GET /_matrix/client/v3/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3room_keysversionversion).
    4004              :   ///
    4005              :   /// [algorithm] The algorithm used for storing backups.  Must be the same as
    4006              :   /// the algorithm currently used by the backup.
    4007              :   ///
    4008              :   /// [authData] Algorithm-dependent data. See the documentation for the backup
    4009              :   /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the
    4010              :   /// expected format of the data.
    4011            0 :   Future<Map<String, Object?>> putRoomKeysVersion(
    4012              :     String version,
    4013              :     BackupAlgorithm algorithm,
    4014              :     Map<String, Object?> authData,
    4015              :   ) async {
    4016            0 :     final requestUri = Uri(
    4017              :       path:
    4018            0 :           '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}',
    4019              :     );
    4020            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    4021            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4022            0 :     request.headers['content-type'] = 'application/json';
    4023            0 :     request.bodyBytes = utf8.encode(
    4024            0 :       jsonEncode({
    4025            0 :         'algorithm': algorithm.name,
    4026              :         'auth_data': authData,
    4027              :       }),
    4028              :     );
    4029            0 :     final response = await httpClient.send(request);
    4030            0 :     final responseBody = await response.stream.toBytes();
    4031            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4032            0 :     final responseString = utf8.decode(responseBody);
    4033            0 :     final json = jsonDecode(responseString);
    4034              :     return json as Map<String, Object?>;
    4035              :   }
    4036              : 
    4037              :   /// Get a list of aliases maintained by the local server for the
    4038              :   /// given room.
    4039              :   ///
    4040              :   /// This endpoint can be called by users who are in the room (external
    4041              :   /// users receive an `M_FORBIDDEN` error response). If the room's
    4042              :   /// `m.room.history_visibility` maps to `world_readable`, any
    4043              :   /// user can call this endpoint.
    4044              :   ///
    4045              :   /// Servers may choose to implement additional access control checks here,
    4046              :   /// such as allowing server administrators to view aliases regardless of
    4047              :   /// membership.
    4048              :   ///
    4049              :   /// **Note:**
    4050              :   /// Clients are recommended not to display this list of aliases prominently
    4051              :   /// as they are not curated, unlike those listed in the `m.room.canonical_alias`
    4052              :   /// state event.
    4053              :   ///
    4054              :   /// [roomId] The room ID to find local aliases of.
    4055              :   ///
    4056              :   /// returns `aliases`:
    4057              :   /// The server's local aliases on the room. Can be empty.
    4058            0 :   Future<List<String>> getLocalAliases(String roomId) async {
    4059            0 :     final requestUri = Uri(
    4060            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/aliases',
    4061              :     );
    4062            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4063            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4064            0 :     final response = await httpClient.send(request);
    4065            0 :     final responseBody = await response.stream.toBytes();
    4066            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4067            0 :     final responseString = utf8.decode(responseBody);
    4068            0 :     final json = jsonDecode(responseString);
    4069            0 :     return (json['aliases'] as List).map((v) => v as String).toList();
    4070              :   }
    4071              : 
    4072              :   /// Ban a user in the room. If the user is currently in the room, also kick them.
    4073              :   ///
    4074              :   /// When a user is banned from a room, they may not join it or be invited to it until they are unbanned.
    4075              :   ///
    4076              :   /// The caller must have the required power level in order to perform this operation.
    4077              :   ///
    4078              :   /// [roomId] The room identifier (not alias) from which the user should be banned.
    4079              :   ///
    4080              :   /// [reason] The reason the user has been banned. This will be supplied as the `reason` on the target's updated [`m.room.member`](https://spec.matrix.org/unstable/client-server-api/#mroommember) event.
    4081              :   ///
    4082              :   /// [userId] The fully qualified user ID of the user being banned.
    4083            5 :   Future<void> ban(String roomId, String userId, {String? reason}) async {
    4084              :     final requestUri =
    4085           15 :         Uri(path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/ban');
    4086           15 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4087           20 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4088           10 :     request.headers['content-type'] = 'application/json';
    4089           10 :     request.bodyBytes = utf8.encode(
    4090           10 :       jsonEncode({
    4091            0 :         if (reason != null) 'reason': reason,
    4092            5 :         'user_id': userId,
    4093              :       }),
    4094              :     );
    4095           10 :     final response = await httpClient.send(request);
    4096           10 :     final responseBody = await response.stream.toBytes();
    4097           10 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4098            5 :     final responseString = utf8.decode(responseBody);
    4099            5 :     final json = jsonDecode(responseString);
    4100            5 :     return ignore(json);
    4101              :   }
    4102              : 
    4103              :   /// This API returns a number of events that happened just before and
    4104              :   /// after the specified event. This allows clients to get the context
    4105              :   /// surrounding an event.
    4106              :   ///
    4107              :   /// *Note*: This endpoint supports lazy-loading of room member events. See
    4108              :   /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) for more information.
    4109              :   ///
    4110              :   /// [roomId] The room to get events from.
    4111              :   ///
    4112              :   /// [eventId] The event to get context around.
    4113              :   ///
    4114              :   /// [limit] The maximum number of context events to return. The limit applies
    4115              :   /// to the sum of the `events_before` and `events_after` arrays. The
    4116              :   /// requested event ID is always returned in `event` even if `limit` is
    4117              :   /// 0. Defaults to 10.
    4118              :   ///
    4119              :   /// [filter] A JSON `RoomEventFilter` to filter the returned events with. The
    4120              :   /// filter is only applied to `events_before`, `events_after`, and
    4121              :   /// `state`. It is not applied to the `event` itself. The filter may
    4122              :   /// be applied before or/and after the `limit` parameter - whichever the
    4123              :   /// homeserver prefers.
    4124              :   ///
    4125              :   /// See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering) for more information.
    4126            0 :   Future<EventContext> getEventContext(
    4127              :     String roomId,
    4128              :     String eventId, {
    4129              :     int? limit,
    4130              :     String? filter,
    4131              :   }) async {
    4132            0 :     final requestUri = Uri(
    4133              :       path:
    4134            0 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/context/${Uri.encodeComponent(eventId)}',
    4135            0 :       queryParameters: {
    4136            0 :         if (limit != null) 'limit': limit.toString(),
    4137            0 :         if (filter != null) 'filter': filter,
    4138              :       },
    4139              :     );
    4140            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4141            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4142            0 :     final response = await httpClient.send(request);
    4143            0 :     final responseBody = await response.stream.toBytes();
    4144            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4145            0 :     final responseString = utf8.decode(responseBody);
    4146            0 :     final json = jsonDecode(responseString);
    4147            0 :     return EventContext.fromJson(json as Map<String, Object?>);
    4148              :   }
    4149              : 
    4150              :   /// Get a single event based on `roomId/eventId`. You must have permission to
    4151              :   /// retrieve this event e.g. by being a member in the room for this event.
    4152              :   ///
    4153              :   /// [roomId] The ID of the room the event is in.
    4154              :   ///
    4155              :   /// [eventId] The event ID to get.
    4156            5 :   Future<MatrixEvent> getOneRoomEvent(String roomId, String eventId) async {
    4157            5 :     final requestUri = Uri(
    4158              :       path:
    4159           15 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}',
    4160              :     );
    4161           15 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4162           20 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4163           10 :     final response = await httpClient.send(request);
    4164           10 :     final responseBody = await response.stream.toBytes();
    4165           12 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4166            5 :     final responseString = utf8.decode(responseBody);
    4167            5 :     final json = jsonDecode(responseString);
    4168            5 :     return MatrixEvent.fromJson(json as Map<String, Object?>);
    4169              :   }
    4170              : 
    4171              :   /// This API stops a user remembering about a particular room.
    4172              :   ///
    4173              :   /// In general, history is a first class citizen in Matrix. After this API
    4174              :   /// is called, however, a user will no longer be able to retrieve history
    4175              :   /// for this room. If all users on a homeserver forget a room, the room is
    4176              :   /// eligible for deletion from that homeserver.
    4177              :   ///
    4178              :   /// If the user is currently joined to the room, they must leave the room
    4179              :   /// before calling this API.
    4180              :   ///
    4181              :   /// [roomId] The room identifier to forget.
    4182            0 :   Future<void> forgetRoom(String roomId) async {
    4183            0 :     final requestUri = Uri(
    4184            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/forget',
    4185              :     );
    4186            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4187            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4188            0 :     final response = await httpClient.send(request);
    4189            0 :     final responseBody = await response.stream.toBytes();
    4190            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4191            0 :     final responseString = utf8.decode(responseBody);
    4192            0 :     final json = jsonDecode(responseString);
    4193            0 :     return ignore(json);
    4194              :   }
    4195              : 
    4196              :   /// *Note that there are two forms of this API, which are documented separately.
    4197              :   /// This version of the API does not require that the inviter know the Matrix
    4198              :   /// identifier of the invitee, and instead relies on third-party identifiers.
    4199              :   /// The homeserver uses an identity server to perform the mapping from
    4200              :   /// third-party identifier to a Matrix identifier. The other is documented in the*
    4201              :   /// [joining rooms section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3roomsroomidinvite).
    4202              :   ///
    4203              :   /// This API invites a user to participate in a particular room.
    4204              :   /// They do not start participating in the room until they actually join the
    4205              :   /// room.
    4206              :   ///
    4207              :   /// Only users currently in a particular room can invite other users to
    4208              :   /// join that room.
    4209              :   ///
    4210              :   /// If the identity server did know the Matrix user identifier for the
    4211              :   /// third-party identifier, the homeserver will append a `m.room.member`
    4212              :   /// event to the room.
    4213              :   ///
    4214              :   /// If the identity server does not know a Matrix user identifier for the
    4215              :   /// passed third-party identifier, the homeserver will issue an invitation
    4216              :   /// which can be accepted upon providing proof of ownership of the third-
    4217              :   /// party identifier. This is achieved by the identity server generating a
    4218              :   /// token, which it gives to the inviting homeserver. The homeserver will
    4219              :   /// add an `m.room.third_party_invite` event into the graph for the room,
    4220              :   /// containing that token.
    4221              :   ///
    4222              :   /// When the invitee binds the invited third-party identifier to a Matrix
    4223              :   /// user ID, the identity server will give the user a list of pending
    4224              :   /// invitations, each containing:
    4225              :   ///
    4226              :   /// - The room ID to which they were invited
    4227              :   ///
    4228              :   /// - The token given to the homeserver
    4229              :   ///
    4230              :   /// - A signature of the token, signed with the identity server's private key
    4231              :   ///
    4232              :   /// - The matrix user ID who invited them to the room
    4233              :   ///
    4234              :   /// [roomId] The room identifier (not alias) to which to invite the user.
    4235              :   ///
    4236              :   /// [body]
    4237            0 :   Future<void> inviteBy3PID(String roomId, Invite3pid body) async {
    4238            0 :     final requestUri = Uri(
    4239            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/invite',
    4240              :     );
    4241            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4242            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4243            0 :     request.headers['content-type'] = 'application/json';
    4244            0 :     request.bodyBytes = utf8.encode(jsonEncode(body.toJson()));
    4245            0 :     final response = await httpClient.send(request);
    4246            0 :     final responseBody = await response.stream.toBytes();
    4247            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4248            0 :     final responseString = utf8.decode(responseBody);
    4249            0 :     final json = jsonDecode(responseString);
    4250            0 :     return ignore(json);
    4251              :   }
    4252              : 
    4253              :   /// *Note that there are two forms of this API, which are documented separately.
    4254              :   /// This version of the API requires that the inviter knows the Matrix
    4255              :   /// identifier of the invitee. The other is documented in the
    4256              :   /// [third-party invites](https://spec.matrix.org/unstable/client-server-api/#third-party-invites) section.*
    4257              :   ///
    4258              :   /// This API invites a user to participate in a particular room.
    4259              :   /// They do not start participating in the room until they actually join the
    4260              :   /// room.
    4261              :   ///
    4262              :   /// Only users currently in a particular room can invite other users to
    4263              :   /// join that room.
    4264              :   ///
    4265              :   /// If the user was invited to the room, the homeserver will append a
    4266              :   /// `m.room.member` event to the room.
    4267              :   ///
    4268              :   /// [roomId] The room identifier (not alias) to which to invite the user.
    4269              :   ///
    4270              :   /// [reason] Optional reason to be included as the `reason` on the subsequent
    4271              :   /// membership event.
    4272              :   ///
    4273              :   /// [userId] The fully qualified user ID of the invitee.
    4274            3 :   Future<void> inviteUser(
    4275              :     String roomId,
    4276              :     String userId, {
    4277              :     String? reason,
    4278              :   }) async {
    4279            3 :     final requestUri = Uri(
    4280            6 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/invite',
    4281              :     );
    4282            9 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4283           12 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4284            6 :     request.headers['content-type'] = 'application/json';
    4285            6 :     request.bodyBytes = utf8.encode(
    4286            6 :       jsonEncode({
    4287            0 :         if (reason != null) 'reason': reason,
    4288            3 :         'user_id': userId,
    4289              :       }),
    4290              :     );
    4291            6 :     final response = await httpClient.send(request);
    4292            6 :     final responseBody = await response.stream.toBytes();
    4293            6 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4294            3 :     final responseString = utf8.decode(responseBody);
    4295            3 :     final json = jsonDecode(responseString);
    4296            3 :     return ignore(json);
    4297              :   }
    4298              : 
    4299              :   /// *Note that this API requires a room ID, not alias.*
    4300              :   /// `/join/{roomIdOrAlias}` *exists if you have a room alias.*
    4301              :   ///
    4302              :   /// This API starts a user's participation in a particular room, if that user
    4303              :   /// is allowed to participate in that room. After this call, the client is
    4304              :   /// allowed to see all current state events in the room, and all subsequent
    4305              :   /// events associated with the room until the user leaves the room.
    4306              :   ///
    4307              :   /// After a user has joined a room, the room will appear as an entry in the
    4308              :   /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3initialsync)
    4309              :   /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) APIs.
    4310              :   ///
    4311              :   /// [roomId] The room identifier (not alias) to join.
    4312              :   ///
    4313              :   /// [reason] Optional reason to be included as the `reason` on the subsequent
    4314              :   /// membership event.
    4315              :   ///
    4316              :   /// [thirdPartySigned] If supplied, the homeserver must verify that it matches a pending
    4317              :   /// `m.room.third_party_invite` event in the room, and perform
    4318              :   /// key validity checking if required by the event.
    4319              :   ///
    4320              :   /// returns `room_id`:
    4321              :   /// The joined room ID.
    4322            0 :   Future<String> joinRoomById(
    4323              :     String roomId, {
    4324              :     String? reason,
    4325              :     ThirdPartySigned? thirdPartySigned,
    4326              :   }) async {
    4327            0 :     final requestUri = Uri(
    4328            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/join',
    4329              :     );
    4330            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4331            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4332            0 :     request.headers['content-type'] = 'application/json';
    4333            0 :     request.bodyBytes = utf8.encode(
    4334            0 :       jsonEncode({
    4335            0 :         if (reason != null) 'reason': reason,
    4336              :         if (thirdPartySigned != null)
    4337            0 :           'third_party_signed': thirdPartySigned.toJson(),
    4338              :       }),
    4339              :     );
    4340            0 :     final response = await httpClient.send(request);
    4341            0 :     final responseBody = await response.stream.toBytes();
    4342            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4343            0 :     final responseString = utf8.decode(responseBody);
    4344            0 :     final json = jsonDecode(responseString);
    4345            0 :     return json['room_id'] as String;
    4346              :   }
    4347              : 
    4348              :   /// This API returns a map of MXIDs to member info objects for members of the room. The current user must be in the room for it to work, unless it is an Application Service in which case any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than `/members` as it can be implemented more efficiently on the server.
    4349              :   ///
    4350              :   /// [roomId] The room to get the members of.
    4351              :   ///
    4352              :   /// returns `joined`:
    4353              :   /// A map from user ID to a RoomMember object.
    4354            0 :   Future<Map<String, RoomMember>?> getJoinedMembersByRoom(String roomId) async {
    4355            0 :     final requestUri = Uri(
    4356              :       path:
    4357            0 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/joined_members',
    4358              :     );
    4359            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4360            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4361            0 :     final response = await httpClient.send(request);
    4362            0 :     final responseBody = await response.stream.toBytes();
    4363            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4364            0 :     final responseString = utf8.decode(responseBody);
    4365            0 :     final json = jsonDecode(responseString);
    4366            0 :     return ((v) => v != null
    4367            0 :         ? (v as Map<String, Object?>).map(
    4368            0 :             (k, v) =>
    4369            0 :                 MapEntry(k, RoomMember.fromJson(v as Map<String, Object?>)),
    4370              :           )
    4371            0 :         : null)(json['joined']);
    4372              :   }
    4373              : 
    4374              :   /// Kick a user from the room.
    4375              :   ///
    4376              :   /// The caller must have the required power level in order to perform this operation.
    4377              :   ///
    4378              :   /// Kicking a user adjusts the target member's membership state to be `leave` with an
    4379              :   /// optional `reason`. Like with other membership changes, a user can directly adjust
    4380              :   /// the target member's state by making a request to `/rooms/<room id>/state/m.room.member/<user id>`.
    4381              :   ///
    4382              :   /// [roomId] The room identifier (not alias) from which the user should be kicked.
    4383              :   ///
    4384              :   /// [reason] The reason the user has been kicked. This will be supplied as the
    4385              :   /// `reason` on the target's updated [`m.room.member`](https://spec.matrix.org/unstable/client-server-api/#mroommember) event.
    4386              :   ///
    4387              :   /// [userId] The fully qualified user ID of the user being kicked.
    4388            5 :   Future<void> kick(String roomId, String userId, {String? reason}) async {
    4389            5 :     final requestUri = Uri(
    4390           10 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/kick',
    4391              :     );
    4392           15 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4393           20 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4394           10 :     request.headers['content-type'] = 'application/json';
    4395           10 :     request.bodyBytes = utf8.encode(
    4396           10 :       jsonEncode({
    4397            0 :         if (reason != null) 'reason': reason,
    4398            5 :         'user_id': userId,
    4399              :       }),
    4400              :     );
    4401           10 :     final response = await httpClient.send(request);
    4402           10 :     final responseBody = await response.stream.toBytes();
    4403           10 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4404            5 :     final responseString = utf8.decode(responseBody);
    4405            5 :     final json = jsonDecode(responseString);
    4406            5 :     return ignore(json);
    4407              :   }
    4408              : 
    4409              :   /// This API stops a user participating in a particular room.
    4410              :   ///
    4411              :   /// If the user was already in the room, they will no longer be able to see
    4412              :   /// new events in the room. If the room requires an invite to join, they
    4413              :   /// will need to be re-invited before they can re-join.
    4414              :   ///
    4415              :   /// If the user was invited to the room, but had not joined, this call
    4416              :   /// serves to reject the invite.
    4417              :   ///
    4418              :   /// The user will still be allowed to retrieve history from the room which
    4419              :   /// they were previously allowed to see.
    4420              :   ///
    4421              :   /// [roomId] The room identifier to leave.
    4422              :   ///
    4423              :   /// [reason] Optional reason to be included as the `reason` on the subsequent
    4424              :   /// membership event.
    4425            1 :   Future<void> leaveRoom(String roomId, {String? reason}) async {
    4426            1 :     final requestUri = Uri(
    4427            2 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/leave',
    4428              :     );
    4429            3 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4430            4 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4431            2 :     request.headers['content-type'] = 'application/json';
    4432            2 :     request.bodyBytes = utf8.encode(
    4433            2 :       jsonEncode({
    4434            0 :         if (reason != null) 'reason': reason,
    4435              :       }),
    4436              :     );
    4437            2 :     final response = await httpClient.send(request);
    4438            2 :     final responseBody = await response.stream.toBytes();
    4439            2 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4440            1 :     final responseString = utf8.decode(responseBody);
    4441            1 :     final json = jsonDecode(responseString);
    4442            1 :     return ignore(json);
    4443              :   }
    4444              : 
    4445              :   /// Get the list of members for this room.
    4446              :   ///
    4447              :   /// [roomId] The room to get the member events for.
    4448              :   ///
    4449              :   /// [at] The point in time (pagination token) to return members for in the room.
    4450              :   /// This token can be obtained from a `prev_batch` token returned for
    4451              :   /// each room by the sync API. Defaults to the current state of the room,
    4452              :   /// as determined by the server.
    4453              :   ///
    4454              :   /// [membership] The kind of membership to filter for. Defaults to no filtering if
    4455              :   /// unspecified. When specified alongside `not_membership`, the two
    4456              :   /// parameters create an 'or' condition: either the membership *is*
    4457              :   /// the same as `membership` **or** *is not* the same as `not_membership`.
    4458              :   ///
    4459              :   /// [notMembership] The kind of membership to exclude from the results. Defaults to no
    4460              :   /// filtering if unspecified.
    4461              :   ///
    4462              :   /// returns `chunk`:
    4463              :   ///
    4464            2 :   Future<List<MatrixEvent>?> getMembersByRoom(
    4465              :     String roomId, {
    4466              :     String? at,
    4467              :     Membership? membership,
    4468              :     Membership? notMembership,
    4469              :   }) async {
    4470            2 :     final requestUri = Uri(
    4471            4 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/members',
    4472            2 :       queryParameters: {
    4473            0 :         if (at != null) 'at': at,
    4474            0 :         if (membership != null) 'membership': membership.name,
    4475            0 :         if (notMembership != null) 'not_membership': notMembership.name,
    4476              :       },
    4477              :     );
    4478            6 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4479            8 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4480            4 :     final response = await httpClient.send(request);
    4481            4 :     final responseBody = await response.stream.toBytes();
    4482            4 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4483            2 :     final responseString = utf8.decode(responseBody);
    4484            2 :     final json = jsonDecode(responseString);
    4485            2 :     return ((v) => v != null
    4486              :         ? (v as List)
    4487            6 :             .map((v) => MatrixEvent.fromJson(v as Map<String, Object?>))
    4488            2 :             .toList()
    4489            4 :         : null)(json['chunk']);
    4490              :   }
    4491              : 
    4492              :   /// This API returns a list of message and state events for a room. It uses
    4493              :   /// pagination query parameters to paginate history in the room.
    4494              :   ///
    4495              :   /// *Note*: This endpoint supports lazy-loading of room member events. See
    4496              :   /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) for more information.
    4497              :   ///
    4498              :   /// [roomId] The room to get events from.
    4499              :   ///
    4500              :   /// [from] The token to start returning events from. This token can be obtained
    4501              :   /// from a `prev_batch` or `next_batch` token returned by the `/sync` endpoint,
    4502              :   /// or from an `end` token returned by a previous request to this endpoint.
    4503              :   ///
    4504              :   /// This endpoint can also accept a value returned as a `start` token
    4505              :   /// by a previous request to this endpoint, though servers are not
    4506              :   /// required to support this. Clients should not rely on the behaviour.
    4507              :   ///
    4508              :   /// If it is not provided, the homeserver shall return a list of messages
    4509              :   /// from the first or last (per the value of the `dir` parameter) visible
    4510              :   /// event in the room history for the requesting user.
    4511              :   ///
    4512              :   /// [to] The token to stop returning events at. This token can be obtained from
    4513              :   /// a `prev_batch` or `next_batch` token returned by the `/sync` endpoint,
    4514              :   /// or from an `end` token returned by a previous request to this endpoint.
    4515              :   ///
    4516              :   /// [dir] The direction to return events from. If this is set to `f`, events
    4517              :   /// will be returned in chronological order starting at `from`. If it
    4518              :   /// is set to `b`, events will be returned in *reverse* chronological
    4519              :   /// order, again starting at `from`.
    4520              :   ///
    4521              :   /// [limit] The maximum number of events to return. Default: 10.
    4522              :   ///
    4523              :   /// [filter] A JSON RoomEventFilter to filter returned events with.
    4524            7 :   Future<GetRoomEventsResponse> getRoomEvents(
    4525              :     String roomId,
    4526              :     Direction dir, {
    4527              :     String? from,
    4528              :     String? to,
    4529              :     int? limit,
    4530              :     String? filter,
    4531              :   }) async {
    4532            7 :     final requestUri = Uri(
    4533           14 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/messages',
    4534            7 :       queryParameters: {
    4535            5 :         if (from != null) 'from': from,
    4536            0 :         if (to != null) 'to': to,
    4537           14 :         'dir': dir.name,
    4538           14 :         if (limit != null) 'limit': limit.toString(),
    4539            7 :         if (filter != null) 'filter': filter,
    4540              :       },
    4541              :     );
    4542           21 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4543           28 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4544           14 :     final response = await httpClient.send(request);
    4545           14 :     final responseBody = await response.stream.toBytes();
    4546           16 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4547            7 :     final responseString = utf8.decode(responseBody);
    4548            7 :     final json = jsonDecode(responseString);
    4549            7 :     return GetRoomEventsResponse.fromJson(json as Map<String, Object?>);
    4550              :   }
    4551              : 
    4552              :   /// Sets the position of the read marker for a given room, and optionally
    4553              :   /// the read receipt's location.
    4554              :   ///
    4555              :   /// [roomId] The room ID to set the read marker in for the user.
    4556              :   ///
    4557              :   /// [mFullyRead] The event ID the read marker should be located at. The
    4558              :   /// event MUST belong to the room.
    4559              :   ///
    4560              :   /// [mRead] The event ID to set the read receipt location at. This is
    4561              :   /// equivalent to calling `/receipt/m.read/$elsewhere:example.org`
    4562              :   /// and is provided here to save that extra call.
    4563              :   ///
    4564              :   /// [mReadPrivate] The event ID to set the *private* read receipt location at. This
    4565              :   /// equivalent to calling `/receipt/m.read.private/$elsewhere:example.org`
    4566              :   /// and is provided here to save that extra call.
    4567            4 :   Future<void> setReadMarker(
    4568              :     String roomId, {
    4569              :     String? mFullyRead,
    4570              :     String? mRead,
    4571              :     String? mReadPrivate,
    4572              :   }) async {
    4573            4 :     final requestUri = Uri(
    4574              :       path:
    4575            8 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/read_markers',
    4576              :     );
    4577           12 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4578           16 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4579            8 :     request.headers['content-type'] = 'application/json';
    4580            8 :     request.bodyBytes = utf8.encode(
    4581            8 :       jsonEncode({
    4582            4 :         if (mFullyRead != null) 'm.fully_read': mFullyRead,
    4583            2 :         if (mRead != null) 'm.read': mRead,
    4584            2 :         if (mReadPrivate != null) 'm.read.private': mReadPrivate,
    4585              :       }),
    4586              :     );
    4587            8 :     final response = await httpClient.send(request);
    4588            8 :     final responseBody = await response.stream.toBytes();
    4589            8 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4590            4 :     final responseString = utf8.decode(responseBody);
    4591            4 :     final json = jsonDecode(responseString);
    4592            4 :     return ignore(json);
    4593              :   }
    4594              : 
    4595              :   /// This API updates the marker for the given receipt type to the event ID
    4596              :   /// specified.
    4597              :   ///
    4598              :   /// [roomId] The room in which to send the event.
    4599              :   ///
    4600              :   /// [receiptType] The type of receipt to send. This can also be `m.fully_read` as an
    4601              :   /// alternative to [`/read_markers`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3roomsroomidread_markers).
    4602              :   ///
    4603              :   /// Note that `m.fully_read` does not appear under `m.receipt`: this endpoint
    4604              :   /// effectively calls `/read_markers` internally when presented with a receipt
    4605              :   /// type of `m.fully_read`.
    4606              :   ///
    4607              :   /// [eventId] The event ID to acknowledge up to.
    4608              :   ///
    4609              :   /// [threadId] The root thread event's ID (or `main`) for which
    4610              :   /// thread this receipt is intended to be under. If
    4611              :   /// not specified, the read receipt is *unthreaded*
    4612              :   /// (default).
    4613            0 :   Future<void> postReceipt(
    4614              :     String roomId,
    4615              :     ReceiptType receiptType,
    4616              :     String eventId, {
    4617              :     String? threadId,
    4618              :   }) async {
    4619            0 :     final requestUri = Uri(
    4620              :       path:
    4621            0 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/receipt/${Uri.encodeComponent(receiptType.name)}/${Uri.encodeComponent(eventId)}',
    4622              :     );
    4623            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4624            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4625            0 :     request.headers['content-type'] = 'application/json';
    4626            0 :     request.bodyBytes = utf8.encode(
    4627            0 :       jsonEncode({
    4628            0 :         if (threadId != null) 'thread_id': threadId,
    4629              :       }),
    4630              :     );
    4631            0 :     final response = await httpClient.send(request);
    4632            0 :     final responseBody = await response.stream.toBytes();
    4633            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4634            0 :     final responseString = utf8.decode(responseBody);
    4635            0 :     final json = jsonDecode(responseString);
    4636            0 :     return ignore(json);
    4637              :   }
    4638              : 
    4639              :   /// Strips all information out of an event which isn't critical to the
    4640              :   /// integrity of the server-side representation of the room.
    4641              :   ///
    4642              :   /// This cannot be undone.
    4643              :   ///
    4644              :   /// Any user with a power level greater than or equal to the `m.room.redaction`
    4645              :   /// event power level may send redaction events in the room. If the user's power
    4646              :   /// level is also greater than or equal to the `redact` power level of the room,
    4647              :   /// the user may redact events sent by other users.
    4648              :   ///
    4649              :   /// Server administrators may redact events sent by users on their server.
    4650              :   ///
    4651              :   /// [roomId] The room from which to redact the event.
    4652              :   ///
    4653              :   /// [eventId] The ID of the event to redact
    4654              :   ///
    4655              :   /// [txnId] The [transaction ID](https://spec.matrix.org/unstable/client-server-api/#transaction-identifiers) for this event. Clients should generate a
    4656              :   /// unique ID; it will be used by the server to ensure idempotency of requests.
    4657              :   ///
    4658              :   /// [reason] The reason for the event being redacted.
    4659              :   ///
    4660              :   /// returns `event_id`:
    4661              :   /// A unique identifier for the event.
    4662            3 :   Future<String?> redactEvent(
    4663              :     String roomId,
    4664              :     String eventId,
    4665              :     String txnId, {
    4666              :     String? reason,
    4667              :   }) async {
    4668            3 :     final requestUri = Uri(
    4669              :       path:
    4670           12 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/redact/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(txnId)}',
    4671              :     );
    4672            9 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    4673           12 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4674            6 :     request.headers['content-type'] = 'application/json';
    4675            6 :     request.bodyBytes = utf8.encode(
    4676            6 :       jsonEncode({
    4677            1 :         if (reason != null) 'reason': reason,
    4678              :       }),
    4679              :     );
    4680            6 :     final response = await httpClient.send(request);
    4681            6 :     final responseBody = await response.stream.toBytes();
    4682            6 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4683            3 :     final responseString = utf8.decode(responseBody);
    4684            3 :     final json = jsonDecode(responseString);
    4685            9 :     return ((v) => v != null ? v as String : null)(json['event_id']);
    4686              :   }
    4687              : 
    4688              :   /// Reports a room as inappropriate to the server, which may then notify
    4689              :   /// the appropriate people. How such information is delivered is left up to
    4690              :   /// implementations. The caller is not required to be joined to the room to
    4691              :   /// report it.
    4692              :   ///
    4693              :   /// [roomId] The room being reported.
    4694              :   ///
    4695              :   /// [reason] The reason the room is being reported. May be blank.
    4696            0 :   Future<void> reportRoom(String roomId, String reason) async {
    4697            0 :     final requestUri = Uri(
    4698            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/report',
    4699              :     );
    4700            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4701            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4702            0 :     request.headers['content-type'] = 'application/json';
    4703            0 :     request.bodyBytes = utf8.encode(
    4704            0 :       jsonEncode({
    4705              :         'reason': reason,
    4706              :       }),
    4707              :     );
    4708            0 :     final response = await httpClient.send(request);
    4709            0 :     final responseBody = await response.stream.toBytes();
    4710            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4711            0 :     final responseString = utf8.decode(responseBody);
    4712            0 :     final json = jsonDecode(responseString);
    4713            0 :     return ignore(json);
    4714              :   }
    4715              : 
    4716              :   /// Reports an event as inappropriate to the server, which may then notify
    4717              :   /// the appropriate people. The caller must be joined to the room to report
    4718              :   /// it.
    4719              :   ///
    4720              :   /// Furthermore, it might be possible for clients to deduce whether a reported
    4721              :   /// event exists by timing the response. This is because only a report for an
    4722              :   /// existing event will require the homeserver to do further processing. To
    4723              :   /// combat this, homeservers MAY add a random delay when generating a response.
    4724              :   ///
    4725              :   /// [roomId] The room in which the event being reported is located.
    4726              :   ///
    4727              :   /// [eventId] The event to report.
    4728              :   ///
    4729              :   /// [reason] The reason the content is being reported.
    4730              :   ///
    4731              :   /// [score] The score to rate this content as where -100 is most offensive
    4732              :   /// and 0 is inoffensive.
    4733            0 :   Future<void> reportEvent(
    4734              :     String roomId,
    4735              :     String eventId, {
    4736              :     String? reason,
    4737              :     int? score,
    4738              :   }) async {
    4739            0 :     final requestUri = Uri(
    4740              :       path:
    4741            0 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/report/${Uri.encodeComponent(eventId)}',
    4742              :     );
    4743            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4744            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4745            0 :     request.headers['content-type'] = 'application/json';
    4746            0 :     request.bodyBytes = utf8.encode(
    4747            0 :       jsonEncode({
    4748            0 :         if (reason != null) 'reason': reason,
    4749            0 :         if (score != null) 'score': score,
    4750              :       }),
    4751              :     );
    4752            0 :     final response = await httpClient.send(request);
    4753            0 :     final responseBody = await response.stream.toBytes();
    4754            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4755            0 :     final responseString = utf8.decode(responseBody);
    4756            0 :     final json = jsonDecode(responseString);
    4757            0 :     return ignore(json);
    4758              :   }
    4759              : 
    4760              :   /// This endpoint is used to send a message event to a room. Message events
    4761              :   /// allow access to historical events and pagination, making them suited
    4762              :   /// for "once-off" activity in a room.
    4763              :   ///
    4764              :   /// The body of the request should be the content object of the event; the
    4765              :   /// fields in this object will vary depending on the type of event. See
    4766              :   /// [Room Events](https://spec.matrix.org/unstable/client-server-api/#room-events) for the m. event specification.
    4767              :   ///
    4768              :   /// [roomId] The room to send the event to.
    4769              :   ///
    4770              :   /// [eventType] The type of event to send.
    4771              :   ///
    4772              :   /// [txnId] The [transaction ID](https://spec.matrix.org/unstable/client-server-api/#transaction-identifiers) for this event. Clients should generate an
    4773              :   /// ID unique across requests with the same access token; it will be
    4774              :   /// used by the server to ensure idempotency of requests.
    4775              :   ///
    4776              :   /// [body]
    4777              :   ///
    4778              :   /// returns `event_id`:
    4779              :   /// A unique identifier for the event.
    4780           15 :   Future<String> sendMessage(
    4781              :     String roomId,
    4782              :     String eventType,
    4783              :     String txnId,
    4784              :     Map<String, Object?> body,
    4785              :   ) async {
    4786           15 :     final requestUri = Uri(
    4787              :       path:
    4788           60 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}',
    4789              :     );
    4790           45 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    4791           60 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4792           30 :     request.headers['content-type'] = 'application/json';
    4793           45 :     request.bodyBytes = utf8.encode(jsonEncode(body));
    4794              :     const maxBodySize = 60000;
    4795           45 :     if (request.bodyBytes.length > maxBodySize) {
    4796            6 :       bodySizeExceeded(maxBodySize, request.bodyBytes.length);
    4797              :     }
    4798           30 :     final response = await httpClient.send(request);
    4799           30 :     final responseBody = await response.stream.toBytes();
    4800           34 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4801           15 :     final responseString = utf8.decode(responseBody);
    4802           15 :     final json = jsonDecode(responseString);
    4803           15 :     return json['event_id'] as String;
    4804              :   }
    4805              : 
    4806              :   /// Get the state events for the current state of a room.
    4807              :   ///
    4808              :   /// [roomId] The room to look up the state for.
    4809            0 :   Future<List<MatrixEvent>> getRoomState(String roomId) async {
    4810            0 :     final requestUri = Uri(
    4811            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state',
    4812              :     );
    4813            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4814            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4815            0 :     final response = await httpClient.send(request);
    4816            0 :     final responseBody = await response.stream.toBytes();
    4817            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4818            0 :     final responseString = utf8.decode(responseBody);
    4819            0 :     final json = jsonDecode(responseString);
    4820              :     return (json as List)
    4821            0 :         .map((v) => MatrixEvent.fromJson(v as Map<String, Object?>))
    4822            0 :         .toList();
    4823              :   }
    4824              : 
    4825              :   /// Looks up the contents of a state event in a room. If the user is
    4826              :   /// joined to the room then the state is taken from the current
    4827              :   /// state of the room. If the user has left the room then the state is
    4828              :   /// taken from the state of the room when they left.
    4829              :   ///
    4830              :   /// [roomId] The room to look up the state in.
    4831              :   ///
    4832              :   /// [eventType] The type of state to look up.
    4833              :   ///
    4834              :   /// [stateKey] The key of the state to look up. Defaults to an empty string. When
    4835              :   /// an empty string, the trailing slash on this endpoint is optional.
    4836              :   ///
    4837              :   /// [format] The format to use for the returned data. `content` (the default) will
    4838              :   /// return only the content of the state event. `event` will return the entire
    4839              :   /// event in the usual format suitable for clients, including fields like event
    4840              :   /// ID, sender and timestamp.
    4841            8 :   Future<Map<String, Object?>> getRoomStateWithKey(
    4842              :     String roomId,
    4843              :     String eventType,
    4844              :     String stateKey, {
    4845              :     Format? format,
    4846              :   }) async {
    4847            8 :     final requestUri = Uri(
    4848              :       path:
    4849           32 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}',
    4850            8 :       queryParameters: {
    4851            0 :         if (format != null) 'format': format.name,
    4852              :       },
    4853              :     );
    4854           22 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    4855           28 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4856           14 :     final response = await httpClient.send(request);
    4857           14 :     final responseBody = await response.stream.toBytes();
    4858           17 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4859            7 :     final responseString = utf8.decode(responseBody);
    4860            7 :     final json = jsonDecode(responseString);
    4861              :     return json as Map<String, Object?>;
    4862              :   }
    4863              : 
    4864              :   /// State events can be sent using this endpoint.  These events will be
    4865              :   /// overwritten if `<room id>`, `<event type>` and `<state key>` all
    4866              :   /// match.
    4867              :   ///
    4868              :   /// Requests to this endpoint **cannot use transaction IDs**
    4869              :   /// like other `PUT` paths because they cannot be differentiated from the
    4870              :   /// `state_key`. Furthermore, `POST` is unsupported on state paths.
    4871              :   ///
    4872              :   /// The body of the request should be the content object of the event; the
    4873              :   /// fields in this object will vary depending on the type of event. See
    4874              :   /// [Room Events](https://spec.matrix.org/unstable/client-server-api/#room-events) for the `m.` event specification.
    4875              :   ///
    4876              :   /// If the event type being sent is `m.room.canonical_alias` servers
    4877              :   /// SHOULD ensure that any new aliases being listed in the event are valid
    4878              :   /// per their grammar/syntax and that they point to the room ID where the
    4879              :   /// state event is to be sent. Servers do not validate aliases which are
    4880              :   /// being removed or are already present in the state event.
    4881              :   ///
    4882              :   ///
    4883              :   /// [roomId] The room to set the state in
    4884              :   ///
    4885              :   /// [eventType] The type of event to send.
    4886              :   ///
    4887              :   /// [stateKey] The state_key for the state to send. Defaults to the empty string. When
    4888              :   /// an empty string, the trailing slash on this endpoint is optional.
    4889              :   ///
    4890              :   /// [body]
    4891              :   ///
    4892              :   /// returns `event_id`:
    4893              :   /// A unique identifier for the event.
    4894           11 :   Future<String> setRoomStateWithKey(
    4895              :     String roomId,
    4896              :     String eventType,
    4897              :     String stateKey,
    4898              :     Map<String, Object?> body,
    4899              :   ) async {
    4900           11 :     final requestUri = Uri(
    4901              :       path:
    4902           44 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}',
    4903              :     );
    4904           33 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    4905           44 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4906           22 :     request.headers['content-type'] = 'application/json';
    4907           33 :     request.bodyBytes = utf8.encode(jsonEncode(body));
    4908           22 :     final response = await httpClient.send(request);
    4909           22 :     final responseBody = await response.stream.toBytes();
    4910           22 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4911           11 :     final responseString = utf8.decode(responseBody);
    4912           11 :     final json = jsonDecode(responseString);
    4913           11 :     return json['event_id'] as String;
    4914              :   }
    4915              : 
    4916              :   /// This tells the server that the user is typing for the next N
    4917              :   /// milliseconds where N is the value specified in the `timeout` key.
    4918              :   /// Alternatively, if `typing` is `false`, it tells the server that the
    4919              :   /// user has stopped typing.
    4920              :   ///
    4921              :   /// [userId] The user who has started to type.
    4922              :   ///
    4923              :   /// [roomId] The room in which the user is typing.
    4924              :   ///
    4925              :   /// [timeout] The length of time in milliseconds to mark this user as typing.
    4926              :   ///
    4927              :   /// [typing] Whether the user is typing or not. If `false`, the `timeout`
    4928              :   /// key can be omitted.
    4929            0 :   Future<void> setTyping(
    4930              :     String userId,
    4931              :     String roomId,
    4932              :     bool typing, {
    4933              :     int? timeout,
    4934              :   }) async {
    4935            0 :     final requestUri = Uri(
    4936              :       path:
    4937            0 :           '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/typing/${Uri.encodeComponent(userId)}',
    4938              :     );
    4939            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    4940            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4941            0 :     request.headers['content-type'] = 'application/json';
    4942            0 :     request.bodyBytes = utf8.encode(
    4943            0 :       jsonEncode({
    4944            0 :         if (timeout != null) 'timeout': timeout,
    4945            0 :         'typing': typing,
    4946              :       }),
    4947              :     );
    4948            0 :     final response = await httpClient.send(request);
    4949            0 :     final responseBody = await response.stream.toBytes();
    4950            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4951            0 :     final responseString = utf8.decode(responseBody);
    4952            0 :     final json = jsonDecode(responseString);
    4953            0 :     return ignore(json);
    4954              :   }
    4955              : 
    4956              :   /// Unban a user from the room. This allows them to be invited to the room,
    4957              :   /// and join if they would otherwise be allowed to join according to its join rules.
    4958              :   ///
    4959              :   /// The caller must have the required power level in order to perform this operation.
    4960              :   ///
    4961              :   /// [roomId] The room identifier (not alias) from which the user should be unbanned.
    4962              :   ///
    4963              :   /// [reason] Optional reason to be included as the `reason` on the subsequent
    4964              :   /// membership event.
    4965              :   ///
    4966              :   /// [userId] The fully qualified user ID of the user being unbanned.
    4967            5 :   Future<void> unban(String roomId, String userId, {String? reason}) async {
    4968            5 :     final requestUri = Uri(
    4969           10 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/unban',
    4970              :     );
    4971           15 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    4972           20 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    4973           10 :     request.headers['content-type'] = 'application/json';
    4974           10 :     request.bodyBytes = utf8.encode(
    4975           10 :       jsonEncode({
    4976            0 :         if (reason != null) 'reason': reason,
    4977            5 :         'user_id': userId,
    4978              :       }),
    4979              :     );
    4980           10 :     final response = await httpClient.send(request);
    4981           10 :     final responseBody = await response.stream.toBytes();
    4982           10 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    4983            5 :     final responseString = utf8.decode(responseBody);
    4984            5 :     final json = jsonDecode(responseString);
    4985            5 :     return ignore(json);
    4986              :   }
    4987              : 
    4988              :   /// Upgrades the given room to a particular room version.
    4989              :   ///
    4990              :   /// [roomId] The ID of the room to upgrade.
    4991              :   ///
    4992              :   /// [additionalCreators] When upgrading to a [room version](https://spec.matrix.org/unstable/rooms) which supports additional creators,
    4993              :   /// the [user IDs](https://spec.matrix.org/unstable/appendices#user-identifiers) which should be considered room
    4994              :   /// creators in addition to the user performing the upgrade.
    4995              :   ///
    4996              :   /// If the room being upgraded has additional creators, they are *not* automatically
    4997              :   /// copied to the new room. The full set of additional creators needs to be set to
    4998              :   /// retain (or add/remove) more room creators.
    4999              :   ///
    5000              :   /// When upgrading to a room version which doesn't support additional creators, this
    5001              :   /// field is ignored and has no effect during the upgrade process.
    5002              :   ///
    5003              :   /// [newVersion] The new version for the room.
    5004              :   ///
    5005              :   /// returns `replacement_room`:
    5006              :   /// The ID of the new room.
    5007            0 :   Future<String> upgradeRoom(
    5008              :     String roomId,
    5009              :     String newVersion, {
    5010              :     List<String>? additionalCreators,
    5011              :   }) async {
    5012            0 :     final requestUri = Uri(
    5013            0 :       path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/upgrade',
    5014              :     );
    5015            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5016            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5017            0 :     request.headers['content-type'] = 'application/json';
    5018            0 :     request.bodyBytes = utf8.encode(
    5019            0 :       jsonEncode({
    5020              :         if (additionalCreators != null)
    5021            0 :           'additional_creators': additionalCreators.map((v) => v).toList(),
    5022            0 :         'new_version': newVersion,
    5023              :       }),
    5024              :     );
    5025            0 :     final response = await httpClient.send(request);
    5026            0 :     final responseBody = await response.stream.toBytes();
    5027            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5028            0 :     final responseString = utf8.decode(responseBody);
    5029            0 :     final json = jsonDecode(responseString);
    5030            0 :     return json['replacement_room'] as String;
    5031              :   }
    5032              : 
    5033              :   /// Performs a full text search across different categories.
    5034              :   ///
    5035              :   /// [nextBatch] The point to return events from. If given, this should be a
    5036              :   /// `next_batch` result from a previous call to this endpoint.
    5037              :   ///
    5038              :   /// [searchCategories] Describes which categories to search in and their criteria.
    5039            0 :   Future<SearchResults> search(
    5040              :     Categories searchCategories, {
    5041              :     String? nextBatch,
    5042              :   }) async {
    5043            0 :     final requestUri = Uri(
    5044              :       path: '_matrix/client/v3/search',
    5045            0 :       queryParameters: {
    5046            0 :         if (nextBatch != null) 'next_batch': nextBatch,
    5047              :       },
    5048              :     );
    5049            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5050            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5051            0 :     request.headers['content-type'] = 'application/json';
    5052            0 :     request.bodyBytes = utf8.encode(
    5053            0 :       jsonEncode({
    5054            0 :         'search_categories': searchCategories.toJson(),
    5055              :       }),
    5056              :     );
    5057            0 :     final response = await httpClient.send(request);
    5058            0 :     final responseBody = await response.stream.toBytes();
    5059            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5060            0 :     final responseString = utf8.decode(responseBody);
    5061            0 :     final json = jsonDecode(responseString);
    5062            0 :     return SearchResults.fromJson(json as Map<String, Object?>);
    5063              :   }
    5064              : 
    5065              :   /// This endpoint is used to send send-to-device events to a set of
    5066              :   /// client devices.
    5067              :   ///
    5068              :   /// [eventType] The type of event to send.
    5069              :   ///
    5070              :   /// [txnId] The [transaction ID](https://spec.matrix.org/unstable/client-server-api/#transaction-identifiers) for this event. Clients should generate an
    5071              :   /// ID unique across requests with the same access token; it will be
    5072              :   /// used by the server to ensure idempotency of requests.
    5073              :   ///
    5074              :   /// [messages] The messages to send. A map from user ID, to a map from
    5075              :   /// device ID to message body. The device ID may also be `*`,
    5076              :   /// meaning all known devices for the user.
    5077           12 :   Future<void> sendToDevice(
    5078              :     String eventType,
    5079              :     String txnId,
    5080              :     Map<String, Map<String, Map<String, Object?>>> messages,
    5081              :   ) async {
    5082           12 :     final requestUri = Uri(
    5083              :       path:
    5084           36 :           '_matrix/client/v3/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}',
    5085              :     );
    5086           36 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    5087           48 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5088           24 :     request.headers['content-type'] = 'application/json';
    5089           24 :     request.bodyBytes = utf8.encode(
    5090           24 :       jsonEncode({
    5091              :         'messages': messages
    5092           63 :             .map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))),
    5093              :       }),
    5094              :     );
    5095           24 :     final response = await httpClient.send(request);
    5096           24 :     final responseBody = await response.stream.toBytes();
    5097           25 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5098           12 :     final responseString = utf8.decode(responseBody);
    5099           12 :     final json = jsonDecode(responseString);
    5100           12 :     return ignore(json);
    5101              :   }
    5102              : 
    5103              :   /// Synchronise the client's state with the latest state on the server.
    5104              :   /// Clients use this API when they first log in to get an initial snapshot
    5105              :   /// of the state on the server, and then continue to call this API to get
    5106              :   /// incremental deltas to the state, and to receive new messages.
    5107              :   ///
    5108              :   /// *Note*: This endpoint supports lazy-loading. See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering)
    5109              :   /// for more information. Lazy-loading members is only supported on the `state` part of a
    5110              :   /// [`RoomFilter`](#post_matrixclientv3useruseridfilter_request_roomfilter)
    5111              :   /// for this endpoint. When lazy-loading is enabled, servers MUST include the
    5112              :   /// syncing user's own membership event when they join a room, or when the
    5113              :   /// full state of rooms is requested, to aid discovering the user's avatar &
    5114              :   /// displayname.
    5115              :   ///
    5116              :   /// Further, like other members, the user's own membership event is eligible
    5117              :   /// for being considered redundant by the server. When a sync is `limited`,
    5118              :   /// the server MUST return membership events for events in the gap
    5119              :   /// (between `since` and the start of the returned timeline), regardless
    5120              :   /// as to whether or not they are redundant. This ensures that joins/leaves
    5121              :   /// and profile changes which occur during the gap are not lost.
    5122              :   ///
    5123              :   /// Note that the default behaviour of `state` is to include all membership
    5124              :   /// events, alongside other state, when lazy-loading is not enabled.
    5125              :   ///
    5126              :   /// [filter] The ID of a filter created using the filter API or a filter JSON
    5127              :   /// object encoded as a string. The server will detect whether it is
    5128              :   /// an ID or a JSON object by whether the first character is a `"{"`
    5129              :   /// open brace. Passing the JSON inline is best suited to one off
    5130              :   /// requests. Creating a filter using the filter API is recommended for
    5131              :   /// clients that reuse the same filter multiple times, for example in
    5132              :   /// long poll requests.
    5133              :   ///
    5134              :   /// See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering) for more information.
    5135              :   ///
    5136              :   /// [since] A point in time to continue a sync from. This should be the
    5137              :   /// `next_batch` token returned by an earlier call to this endpoint.
    5138              :   ///
    5139              :   /// [fullState] Controls whether to include the full state for all rooms the user
    5140              :   /// is a member of.
    5141              :   ///
    5142              :   /// If this is set to `true`, then all state events will be returned,
    5143              :   /// even if `since` is non-empty. The timeline will still be limited
    5144              :   /// by the `since` parameter. In this case, the `timeout` parameter
    5145              :   /// will be ignored and the query will return immediately, possibly with
    5146              :   /// an empty timeline.
    5147              :   ///
    5148              :   /// If `false`, and `since` is non-empty, only state which has
    5149              :   /// changed since the point indicated by `since` will be returned.
    5150              :   ///
    5151              :   /// By default, this is `false`.
    5152              :   ///
    5153              :   /// [setPresence] Controls whether the client is automatically marked as online by
    5154              :   /// polling this API. If this parameter is omitted then the client is
    5155              :   /// automatically marked as online when it uses this API. Otherwise if
    5156              :   /// the parameter is set to "offline" then the client is not marked as
    5157              :   /// being online when it uses this API. When set to "unavailable", the
    5158              :   /// client is marked as being idle.
    5159              :   ///
    5160              :   /// [timeout] The maximum time to wait, in milliseconds, before returning this
    5161              :   /// request. If no events (or other data) become available before this
    5162              :   /// time elapses, the server will return a response with empty fields.
    5163              :   ///
    5164              :   /// By default, this is `0`, so the server will return immediately
    5165              :   /// even if the response is empty.
    5166              :   ///
    5167              :   /// [useStateAfter] Controls whether to receive state changes between the previous sync
    5168              :   /// and the **start** of the timeline, or between the previous sync and
    5169              :   /// the **end** of the timeline.
    5170              :   ///
    5171              :   /// If this is set to `true`, servers MUST respond with the state
    5172              :   /// between the previous sync and the **end** of the timeline in
    5173              :   /// `state_after` and MUST omit `state`.
    5174              :   ///
    5175              :   /// If `false`, servers MUST respond with the state between the previous
    5176              :   /// sync and the **start** of the timeline in `state` and MUST omit
    5177              :   /// `state_after`.
    5178              :   ///
    5179              :   /// Even if this is set to `true`, clients MUST update their local state
    5180              :   /// with events in `state` and `timeline` if `state_after` is missing in
    5181              :   /// the response, for compatibility with servers that don't support this
    5182              :   /// parameter.
    5183              :   ///
    5184              :   /// By default, this is `false`.
    5185           40 :   Future<SyncUpdate> sync({
    5186              :     String? filter,
    5187              :     String? since,
    5188              :     bool? fullState,
    5189              :     PresenceType? setPresence,
    5190              :     int? timeout,
    5191              :     bool? useStateAfter,
    5192              :   }) async {
    5193           40 :     final requestUri = Uri(
    5194              :       path: '_matrix/client/v3/sync',
    5195           40 :       queryParameters: {
    5196           40 :         if (filter != null) 'filter': filter,
    5197           38 :         if (since != null) 'since': since,
    5198            0 :         if (fullState != null) 'full_state': fullState.toString(),
    5199            0 :         if (setPresence != null) 'set_presence': setPresence.name,
    5200           80 :         if (timeout != null) 'timeout': timeout.toString(),
    5201            0 :         if (useStateAfter != null) 'use_state_after': useStateAfter.toString(),
    5202              :       },
    5203              :     );
    5204          120 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5205          160 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5206           80 :     final response = await httpClient.send(request);
    5207           80 :     final responseBody = await response.stream.toBytes();
    5208           81 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5209           40 :     final responseString = utf8.decode(responseBody);
    5210           40 :     final json = jsonDecode(responseString);
    5211           40 :     return SyncUpdate.fromJson(json as Map<String, Object?>);
    5212              :   }
    5213              : 
    5214              :   /// Retrieve an array of third-party network locations from a Matrix room
    5215              :   /// alias.
    5216              :   ///
    5217              :   /// [alias] The Matrix room alias to look up.
    5218            0 :   Future<List<Location>> queryLocationByAlias(String alias) async {
    5219            0 :     final requestUri = Uri(
    5220              :       path: '_matrix/client/v3/thirdparty/location',
    5221            0 :       queryParameters: {
    5222              :         'alias': alias,
    5223              :       },
    5224              :     );
    5225            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5226            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5227            0 :     final response = await httpClient.send(request);
    5228            0 :     final responseBody = await response.stream.toBytes();
    5229            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5230            0 :     final responseString = utf8.decode(responseBody);
    5231            0 :     final json = jsonDecode(responseString);
    5232              :     return (json as List)
    5233            0 :         .map((v) => Location.fromJson(v as Map<String, Object?>))
    5234            0 :         .toList();
    5235              :   }
    5236              : 
    5237              :   /// Requesting this endpoint with a valid protocol name results in a list
    5238              :   /// of successful mapping results in a JSON array. Each result contains
    5239              :   /// objects to represent the Matrix room or rooms that represent a portal
    5240              :   /// to this third-party network. Each has the Matrix room alias string,
    5241              :   /// an identifier for the particular third-party network protocol, and an
    5242              :   /// object containing the network-specific fields that comprise this
    5243              :   /// identifier. It should attempt to canonicalise the identifier as much
    5244              :   /// as reasonably possible given the network type.
    5245              :   ///
    5246              :   /// [protocol] The protocol used to communicate to the third-party network.
    5247              :   ///
    5248              :   /// [fields] One or more custom fields to help identify the third-party
    5249              :   /// location.
    5250            0 :   Future<List<Location>> queryLocationByProtocol(
    5251              :     String protocol, {
    5252              :     Map<String, String>? fields,
    5253              :   }) async {
    5254            0 :     final requestUri = Uri(
    5255              :       path:
    5256            0 :           '_matrix/client/v3/thirdparty/location/${Uri.encodeComponent(protocol)}',
    5257            0 :       queryParameters: {
    5258            0 :         if (fields != null) ...fields,
    5259              :       },
    5260              :     );
    5261            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5262            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5263            0 :     final response = await httpClient.send(request);
    5264            0 :     final responseBody = await response.stream.toBytes();
    5265            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5266            0 :     final responseString = utf8.decode(responseBody);
    5267            0 :     final json = jsonDecode(responseString);
    5268              :     return (json as List)
    5269            0 :         .map((v) => Location.fromJson(v as Map<String, Object?>))
    5270            0 :         .toList();
    5271              :   }
    5272              : 
    5273              :   /// Fetches the metadata from the homeserver about a particular third-party protocol.
    5274              :   ///
    5275              :   /// [protocol] The name of the protocol.
    5276            0 :   Future<GetProtocolMetadataResponse$2> getProtocolMetadata(
    5277              :     String protocol,
    5278              :   ) async {
    5279            0 :     final requestUri = Uri(
    5280              :       path:
    5281            0 :           '_matrix/client/v3/thirdparty/protocol/${Uri.encodeComponent(protocol)}',
    5282              :     );
    5283            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5284            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5285            0 :     final response = await httpClient.send(request);
    5286            0 :     final responseBody = await response.stream.toBytes();
    5287            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5288            0 :     final responseString = utf8.decode(responseBody);
    5289            0 :     final json = jsonDecode(responseString);
    5290            0 :     return GetProtocolMetadataResponse$2.fromJson(json as Map<String, Object?>);
    5291              :   }
    5292              : 
    5293              :   /// Fetches the overall metadata about protocols supported by the
    5294              :   /// homeserver. Includes both the available protocols and all fields
    5295              :   /// required for queries against each protocol.
    5296            0 :   Future<Map<String, GetProtocolsResponse$2>> getProtocols() async {
    5297            0 :     final requestUri = Uri(path: '_matrix/client/v3/thirdparty/protocols');
    5298            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5299            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5300            0 :     final response = await httpClient.send(request);
    5301            0 :     final responseBody = await response.stream.toBytes();
    5302            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5303            0 :     final responseString = utf8.decode(responseBody);
    5304            0 :     final json = jsonDecode(responseString);
    5305            0 :     return (json as Map<String, Object?>).map(
    5306            0 :       (k, v) => MapEntry(
    5307              :         k,
    5308            0 :         GetProtocolsResponse$2.fromJson(v as Map<String, Object?>),
    5309              :       ),
    5310              :     );
    5311              :   }
    5312              : 
    5313              :   /// Retrieve an array of third-party users from a Matrix User ID.
    5314              :   ///
    5315              :   /// [userid] The Matrix User ID to look up.
    5316            0 :   Future<List<ThirdPartyUser>> queryUserByID(String userid) async {
    5317            0 :     final requestUri = Uri(
    5318              :       path: '_matrix/client/v3/thirdparty/user',
    5319            0 :       queryParameters: {
    5320              :         'userid': userid,
    5321              :       },
    5322              :     );
    5323            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5324            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5325            0 :     final response = await httpClient.send(request);
    5326            0 :     final responseBody = await response.stream.toBytes();
    5327            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5328            0 :     final responseString = utf8.decode(responseBody);
    5329            0 :     final json = jsonDecode(responseString);
    5330              :     return (json as List)
    5331            0 :         .map((v) => ThirdPartyUser.fromJson(v as Map<String, Object?>))
    5332            0 :         .toList();
    5333              :   }
    5334              : 
    5335              :   /// Retrieve a Matrix User ID linked to a user on the third-party service, given
    5336              :   /// a set of user parameters.
    5337              :   ///
    5338              :   /// [protocol] The name of the protocol.
    5339              :   ///
    5340              :   /// [fields] One or more custom fields that are passed to the AS to help identify the user.
    5341            0 :   Future<List<ThirdPartyUser>> queryUserByProtocol(
    5342              :     String protocol, {
    5343              :     Map<String, String>? fields,
    5344              :   }) async {
    5345            0 :     final requestUri = Uri(
    5346              :       path:
    5347            0 :           '_matrix/client/v3/thirdparty/user/${Uri.encodeComponent(protocol)}',
    5348            0 :       queryParameters: {
    5349            0 :         if (fields != null) ...fields,
    5350              :       },
    5351              :     );
    5352            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5353            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5354            0 :     final response = await httpClient.send(request);
    5355            0 :     final responseBody = await response.stream.toBytes();
    5356            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5357            0 :     final responseString = utf8.decode(responseBody);
    5358            0 :     final json = jsonDecode(responseString);
    5359              :     return (json as List)
    5360            0 :         .map((v) => ThirdPartyUser.fromJson(v as Map<String, Object?>))
    5361            0 :         .toList();
    5362              :   }
    5363              : 
    5364              :   /// Get some account data for the client. This config is only visible to the user
    5365              :   /// that set the account data.
    5366              :   ///
    5367              :   /// [userId] The ID of the user to get account data for. The access token must be
    5368              :   /// authorized to make requests for this user ID.
    5369              :   ///
    5370              :   /// [type] The event type of the account data to get. Custom types should be
    5371              :   /// namespaced to avoid clashes.
    5372            0 :   Future<Map<String, Object?>> getAccountData(
    5373              :     String userId,
    5374              :     String type,
    5375              :   ) async {
    5376            0 :     final requestUri = Uri(
    5377              :       path:
    5378            0 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}',
    5379              :     );
    5380            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5381            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5382            0 :     final response = await httpClient.send(request);
    5383            0 :     final responseBody = await response.stream.toBytes();
    5384            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5385            0 :     final responseString = utf8.decode(responseBody);
    5386            0 :     final json = jsonDecode(responseString);
    5387              :     return json as Map<String, Object?>;
    5388              :   }
    5389              : 
    5390              :   /// Set some account data for the client. This config is only visible to the user
    5391              :   /// that set the account data. The config will be available to clients through the
    5392              :   /// top-level `account_data` field in the homeserver response to
    5393              :   /// [/sync](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync).
    5394              :   ///
    5395              :   /// [userId] The ID of the user to set account data for. The access token must be
    5396              :   /// authorized to make requests for this user ID.
    5397              :   ///
    5398              :   /// [type] The event type of the account data to set. Custom types should be
    5399              :   /// namespaced to avoid clashes.
    5400              :   ///
    5401              :   /// [body] The content of the account data.
    5402           10 :   Future<void> setAccountData(
    5403              :     String userId,
    5404              :     String type,
    5405              :     Map<String, Object?> body,
    5406              :   ) async {
    5407           10 :     final requestUri = Uri(
    5408              :       path:
    5409           30 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}',
    5410              :     );
    5411           30 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    5412           40 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5413           20 :     request.headers['content-type'] = 'application/json';
    5414           30 :     request.bodyBytes = utf8.encode(jsonEncode(body));
    5415           20 :     final response = await httpClient.send(request);
    5416           20 :     final responseBody = await response.stream.toBytes();
    5417           20 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5418           10 :     final responseString = utf8.decode(responseBody);
    5419           10 :     final json = jsonDecode(responseString);
    5420           10 :     return ignore(json);
    5421              :   }
    5422              : 
    5423              :   /// Uploads a new filter definition to the homeserver.
    5424              :   /// Returns a filter ID that may be used in future requests to
    5425              :   /// restrict which events are returned to the client.
    5426              :   ///
    5427              :   /// [userId] The id of the user uploading the filter. The access token must be authorized to make requests for this user id.
    5428              :   ///
    5429              :   /// [body] The filter to upload.
    5430              :   ///
    5431              :   /// returns `filter_id`:
    5432              :   /// The ID of the filter that was created. Cannot start
    5433              :   /// with a `{` as this character is used to determine
    5434              :   /// if the filter provided is inline JSON or a previously
    5435              :   /// declared filter by homeservers on some APIs.
    5436           40 :   Future<String> defineFilter(String userId, Filter body) async {
    5437           40 :     final requestUri = Uri(
    5438           80 :       path: '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/filter',
    5439              :     );
    5440          120 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5441          160 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5442           80 :     request.headers['content-type'] = 'application/json';
    5443          160 :     request.bodyBytes = utf8.encode(jsonEncode(body.toJson()));
    5444           80 :     final response = await httpClient.send(request);
    5445           80 :     final responseBody = await response.stream.toBytes();
    5446           80 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5447           40 :     final responseString = utf8.decode(responseBody);
    5448           40 :     final json = jsonDecode(responseString);
    5449           40 :     return json['filter_id'] as String;
    5450              :   }
    5451              : 
    5452              :   ///
    5453              :   ///
    5454              :   /// [userId] The user ID to download a filter for.
    5455              :   ///
    5456              :   /// [filterId] The filter ID to download.
    5457            0 :   Future<Filter> getFilter(String userId, String filterId) async {
    5458            0 :     final requestUri = Uri(
    5459              :       path:
    5460            0 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}',
    5461              :     );
    5462            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5463            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5464            0 :     final response = await httpClient.send(request);
    5465            0 :     final responseBody = await response.stream.toBytes();
    5466            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5467            0 :     final responseString = utf8.decode(responseBody);
    5468            0 :     final json = jsonDecode(responseString);
    5469            0 :     return Filter.fromJson(json as Map<String, Object?>);
    5470              :   }
    5471              : 
    5472              :   /// Gets an OpenID token object that the requester may supply to another
    5473              :   /// service to verify their identity in Matrix. The generated token is only
    5474              :   /// valid for exchanging for user information from the federation API for
    5475              :   /// OpenID.
    5476              :   ///
    5477              :   /// The access token generated is only valid for the OpenID API. It cannot
    5478              :   /// be used to request another OpenID access token or call `/sync`, for
    5479              :   /// example.
    5480              :   ///
    5481              :   /// [userId] The user to request an OpenID token for. Should be the user who
    5482              :   /// is authenticated for the request.
    5483              :   ///
    5484              :   /// [body] An empty object. Reserved for future expansion.
    5485            0 :   Future<OpenIdCredentials> requestOpenIdToken(
    5486              :     String userId,
    5487              :     Map<String, Object?> body,
    5488              :   ) async {
    5489            0 :     final requestUri = Uri(
    5490              :       path:
    5491            0 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/openid/request_token',
    5492              :     );
    5493            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5494            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5495            0 :     request.headers['content-type'] = 'application/json';
    5496            0 :     request.bodyBytes = utf8.encode(jsonEncode(body));
    5497            0 :     final response = await httpClient.send(request);
    5498            0 :     final responseBody = await response.stream.toBytes();
    5499            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5500            0 :     final responseString = utf8.decode(responseBody);
    5501            0 :     final json = jsonDecode(responseString);
    5502            0 :     return OpenIdCredentials.fromJson(json as Map<String, Object?>);
    5503              :   }
    5504              : 
    5505              :   /// Get some account data for the client on a given room. This config is only
    5506              :   /// visible to the user that set the account data.
    5507              :   ///
    5508              :   /// [userId] The ID of the user to get account data for. The access token must be
    5509              :   /// authorized to make requests for this user ID.
    5510              :   ///
    5511              :   /// [roomId] The ID of the room to get account data for.
    5512              :   ///
    5513              :   /// [type] The event type of the account data to get. Custom types should be
    5514              :   /// namespaced to avoid clashes.
    5515            0 :   Future<Map<String, Object?>> getAccountDataPerRoom(
    5516              :     String userId,
    5517              :     String roomId,
    5518              :     String type,
    5519              :   ) async {
    5520            0 :     final requestUri = Uri(
    5521              :       path:
    5522            0 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}',
    5523              :     );
    5524            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5525            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5526            0 :     final response = await httpClient.send(request);
    5527            0 :     final responseBody = await response.stream.toBytes();
    5528            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5529            0 :     final responseString = utf8.decode(responseBody);
    5530            0 :     final json = jsonDecode(responseString);
    5531              :     return json as Map<String, Object?>;
    5532              :   }
    5533              : 
    5534              :   /// Set some account data for the client on a given room. This config is only
    5535              :   /// visible to the user that set the account data. The config will be delivered to
    5536              :   /// clients in the per-room entries via [/sync](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync).
    5537              :   ///
    5538              :   /// [userId] The ID of the user to set account data for. The access token must be
    5539              :   /// authorized to make requests for this user ID.
    5540              :   ///
    5541              :   /// [roomId] The ID of the room to set account data on.
    5542              :   ///
    5543              :   /// [type] The event type of the account data to set. Custom types should be
    5544              :   /// namespaced to avoid clashes.
    5545              :   ///
    5546              :   /// [body] The content of the account data.
    5547            3 :   Future<void> setAccountDataPerRoom(
    5548              :     String userId,
    5549              :     String roomId,
    5550              :     String type,
    5551              :     Map<String, Object?> body,
    5552              :   ) async {
    5553            3 :     final requestUri = Uri(
    5554              :       path:
    5555           12 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}',
    5556              :     );
    5557            9 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    5558           12 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5559            6 :     request.headers['content-type'] = 'application/json';
    5560            9 :     request.bodyBytes = utf8.encode(jsonEncode(body));
    5561            6 :     final response = await httpClient.send(request);
    5562            6 :     final responseBody = await response.stream.toBytes();
    5563            6 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5564            3 :     final responseString = utf8.decode(responseBody);
    5565            3 :     final json = jsonDecode(responseString);
    5566            3 :     return ignore(json);
    5567              :   }
    5568              : 
    5569              :   /// List the tags set by a user on a room.
    5570              :   ///
    5571              :   /// [userId] The id of the user to get tags for. The access token must be
    5572              :   /// authorized to make requests for this user ID.
    5573              :   ///
    5574              :   /// [roomId] The ID of the room to get tags for.
    5575              :   ///
    5576              :   /// returns `tags`:
    5577              :   ///
    5578            0 :   Future<Map<String, Tag>?> getRoomTags(String userId, String roomId) async {
    5579            0 :     final requestUri = Uri(
    5580              :       path:
    5581            0 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags',
    5582              :     );
    5583            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5584            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5585            0 :     final response = await httpClient.send(request);
    5586            0 :     final responseBody = await response.stream.toBytes();
    5587            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5588            0 :     final responseString = utf8.decode(responseBody);
    5589            0 :     final json = jsonDecode(responseString);
    5590            0 :     return ((v) => v != null
    5591              :         ? (v as Map<String, Object?>)
    5592            0 :             .map((k, v) => MapEntry(k, Tag.fromJson(v as Map<String, Object?>)))
    5593            0 :         : null)(json['tags']);
    5594              :   }
    5595              : 
    5596              :   /// Remove a tag from the room.
    5597              :   ///
    5598              :   /// [userId] The id of the user to remove a tag for. The access token must be
    5599              :   /// authorized to make requests for this user ID.
    5600              :   ///
    5601              :   /// [roomId] The ID of the room to remove a tag from.
    5602              :   ///
    5603              :   /// [tag] The tag to remove.
    5604            2 :   Future<void> deleteRoomTag(String userId, String roomId, String tag) async {
    5605            2 :     final requestUri = Uri(
    5606              :       path:
    5607            8 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}',
    5608              :     );
    5609            6 :     final request = Request('DELETE', baseUri!.resolveUri(requestUri));
    5610            8 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5611            4 :     final response = await httpClient.send(request);
    5612            4 :     final responseBody = await response.stream.toBytes();
    5613            4 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5614            2 :     final responseString = utf8.decode(responseBody);
    5615            2 :     final json = jsonDecode(responseString);
    5616            2 :     return ignore(json);
    5617              :   }
    5618              : 
    5619              :   /// Add a tag to the room.
    5620              :   ///
    5621              :   /// [userId] The id of the user to add a tag for. The access token must be
    5622              :   /// authorized to make requests for this user ID.
    5623              :   ///
    5624              :   /// [roomId] The ID of the room to add a tag to.
    5625              :   ///
    5626              :   /// [tag] The tag to add.
    5627              :   ///
    5628              :   /// [body] Extra data for the tag, e.g. ordering.
    5629            2 :   Future<void> setRoomTag(
    5630              :     String userId,
    5631              :     String roomId,
    5632              :     String tag,
    5633              :     Tag body,
    5634              :   ) async {
    5635            2 :     final requestUri = Uri(
    5636              :       path:
    5637            8 :           '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}',
    5638              :     );
    5639            6 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    5640            8 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5641            4 :     request.headers['content-type'] = 'application/json';
    5642            8 :     request.bodyBytes = utf8.encode(jsonEncode(body.toJson()));
    5643            4 :     final response = await httpClient.send(request);
    5644            4 :     final responseBody = await response.stream.toBytes();
    5645            4 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5646            2 :     final responseString = utf8.decode(responseBody);
    5647            2 :     final json = jsonDecode(responseString);
    5648            2 :     return ignore(json);
    5649              :   }
    5650              : 
    5651              :   /// Performs a search for users. The homeserver may determine which
    5652              :   /// subset of users are searched. However, the homeserver MUST at a
    5653              :   /// minimum consider users who are visible to the requester based
    5654              :   /// on their membership in rooms known to the homeserver. This means:
    5655              :   ///
    5656              :   /// -   users that share a room with the requesting user
    5657              :   /// -   users who are joined to rooms known to the homeserver that have a
    5658              :   ///     `public` [join rule](#mroomjoin_rules)
    5659              :   /// -   users who are joined to rooms known to the homeserver that have a
    5660              :   ///     `world_readable` [history visibility](#room-history-visibility)
    5661              :   ///
    5662              :   /// The search MUST consider local users to the homeserver, and SHOULD
    5663              :   /// query remote users as part of the search.
    5664              :   ///
    5665              :   /// The search is performed case-insensitively on user IDs and display
    5666              :   /// names preferably using a collation determined based upon the
    5667              :   /// `Accept-Language` header provided in the request, if present.
    5668              :   ///
    5669              :   /// [limit] The maximum number of results to return. Defaults to 10.
    5670              :   ///
    5671              :   /// [searchTerm] The term to search for
    5672            0 :   Future<SearchUserDirectoryResponse> searchUserDirectory(
    5673              :     String searchTerm, {
    5674              :     int? limit,
    5675              :   }) async {
    5676            0 :     final requestUri = Uri(path: '_matrix/client/v3/user_directory/search');
    5677            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5678            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5679            0 :     request.headers['content-type'] = 'application/json';
    5680            0 :     request.bodyBytes = utf8.encode(
    5681            0 :       jsonEncode({
    5682            0 :         if (limit != null) 'limit': limit,
    5683            0 :         'search_term': searchTerm,
    5684              :       }),
    5685              :     );
    5686            0 :     final response = await httpClient.send(request);
    5687            0 :     final responseBody = await response.stream.toBytes();
    5688            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5689            0 :     final responseString = utf8.decode(responseBody);
    5690            0 :     final json = jsonDecode(responseString);
    5691            0 :     return SearchUserDirectoryResponse.fromJson(json as Map<String, Object?>);
    5692              :   }
    5693              : 
    5694              :   /// Reports a user as inappropriate to the server, which may then notify
    5695              :   /// the appropriate people. How such information is delivered is left up to
    5696              :   /// implementations. The caller is not required to be joined to any rooms
    5697              :   /// that the reported user is joined to.
    5698              :   ///
    5699              :   /// Clients may wish to [ignore](#ignoring-users) users after reporting them.
    5700              :   ///
    5701              :   /// Clients could infer whether a reported user exists based on the 404 response.
    5702              :   /// Homeservers that wish to conceal this information MAY return 200 responses
    5703              :   /// regardless of the existence of the reported user.
    5704              :   ///
    5705              :   /// Furthermore, it might be possible for clients to deduce whether a reported
    5706              :   /// user exists by timing the response. This is because only a report for an
    5707              :   /// existing user will require the homeserver to do further processing. To
    5708              :   /// combat this, homeservers MAY add a random delay when generating a response.
    5709              :   ///
    5710              :   /// [userId] The user being reported.
    5711              :   ///
    5712              :   /// [reason] The reason the room is being reported. May be blank.
    5713            0 :   Future<Map<String, Object?>> reportUser(String userId, String reason) async {
    5714            0 :     final requestUri = Uri(
    5715            0 :       path: '_matrix/client/v3/users/${Uri.encodeComponent(userId)}/report',
    5716              :     );
    5717            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5718            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5719            0 :     request.headers['content-type'] = 'application/json';
    5720            0 :     request.bodyBytes = utf8.encode(
    5721            0 :       jsonEncode({
    5722              :         'reason': reason,
    5723              :       }),
    5724              :     );
    5725            0 :     final response = await httpClient.send(request);
    5726            0 :     final responseBody = await response.stream.toBytes();
    5727            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5728            0 :     final responseString = utf8.decode(responseBody);
    5729            0 :     final json = jsonDecode(responseString);
    5730              :     return json as Map<String, Object?>;
    5731              :   }
    5732              : 
    5733              :   /// This API provides credentials for the client to use when initiating
    5734              :   /// calls.
    5735            0 :   Future<TurnServerCredentials> getTurnServer() async {
    5736            0 :     final requestUri = Uri(path: '_matrix/client/v3/voip/turnServer');
    5737            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5738            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5739            0 :     final response = await httpClient.send(request);
    5740            0 :     final responseBody = await response.stream.toBytes();
    5741            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5742            0 :     final responseString = utf8.decode(responseBody);
    5743            0 :     final json = jsonDecode(responseString);
    5744            0 :     return TurnServerCredentials.fromJson(json as Map<String, Object?>);
    5745              :   }
    5746              : 
    5747              :   /// Gets the versions of the specification supported by the server.
    5748              :   ///
    5749              :   /// Values will take the form `vX.Y` or `rX.Y.Z` in historical cases. See
    5750              :   /// [the Specification Versioning](../#specification-versions) for more
    5751              :   /// information.
    5752              :   ///
    5753              :   /// The server may additionally advertise experimental features it supports
    5754              :   /// through `unstable_features`. These features should be namespaced and
    5755              :   /// may optionally include version information within their name if desired.
    5756              :   /// Features listed here are not for optionally toggling parts of the Matrix
    5757              :   /// specification and should only be used to advertise support for a feature
    5758              :   /// which has not yet landed in the spec. For example, a feature currently
    5759              :   /// undergoing the proposal process may appear here and eventually be taken
    5760              :   /// off this list once the feature lands in the spec and the server deems it
    5761              :   /// reasonable to do so. Servers can choose to enable some features only for
    5762              :   /// some users, so clients should include authentication in the request to
    5763              :   /// get all the features available for the logged-in user. If no
    5764              :   /// authentication is provided, the server should only return the features
    5765              :   /// available to all users. Servers may wish to keep advertising features
    5766              :   /// here after they've been released into the spec to give clients a chance
    5767              :   /// to upgrade appropriately. Additionally, clients should avoid using
    5768              :   /// unstable features in their stable releases.
    5769           42 :   Future<GetVersionsResponse> getVersions() async {
    5770           42 :     final requestUri = Uri(path: '_matrix/client/versions');
    5771          126 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5772           42 :     if (bearerToken != null) {
    5773           44 :       request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5774              :     }
    5775           84 :     final response = await httpClient.send(request);
    5776           84 :     final responseBody = await response.stream.toBytes();
    5777           85 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5778           42 :     final responseString = utf8.decode(responseBody);
    5779           42 :     final json = jsonDecode(responseString);
    5780           42 :     return GetVersionsResponse.fromJson(json as Map<String, Object?>);
    5781              :   }
    5782              : 
    5783              :   /// Creates a new `mxc://` URI, independently of the content being uploaded. The content must be provided later
    5784              :   /// via [`PUT /_matrix/media/v3/upload/{serverName}/{mediaId}`](https://spec.matrix.org/unstable/client-server-api/#put_matrixmediav3uploadservernamemediaid).
    5785              :   ///
    5786              :   /// The server may optionally enforce a maximum age for unused IDs,
    5787              :   /// and delete media IDs when the client doesn't start the upload in time,
    5788              :   /// or when the upload was interrupted and not resumed in time. The server
    5789              :   /// should include the maximum POSIX millisecond timestamp to complete the
    5790              :   /// upload in the `unused_expires_at` field in the response JSON. The
    5791              :   /// recommended default expiration is 24 hours which should be enough time
    5792              :   /// to accommodate users on poor connection who find a better connection to
    5793              :   /// complete the upload.
    5794              :   ///
    5795              :   /// As well as limiting the rate of requests to create `mxc://` URIs, the server
    5796              :   /// should limit the number of concurrent *pending media uploads* a given
    5797              :   /// user can have. A pending media upload is a created `mxc://` URI where (a)
    5798              :   /// the media has not yet been uploaded, and (b) has not yet expired (the
    5799              :   /// `unused_expires_at` timestamp has not yet passed). In both cases, the
    5800              :   /// server should respond with an HTTP 429 error with an errcode of
    5801              :   /// `M_LIMIT_EXCEEDED`.
    5802            0 :   Future<CreateContentResponse> createContent() async {
    5803            0 :     final requestUri = Uri(path: '_matrix/media/v1/create');
    5804            0 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    5805            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5806            0 :     final response = await httpClient.send(request);
    5807            0 :     final responseBody = await response.stream.toBytes();
    5808            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5809            0 :     final responseString = utf8.decode(responseBody);
    5810            0 :     final json = jsonDecode(responseString);
    5811            0 :     return CreateContentResponse.fromJson(json as Map<String, Object?>);
    5812              :   }
    5813              : 
    5814              :   /// **NOTE:**
    5815              :   /// Replaced by [`GET /_matrix/client/v1/media/config`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv1mediaconfig).
    5816              :   ///
    5817              :   ///
    5818              :   /// This endpoint allows clients to retrieve the configuration of the content
    5819              :   /// repository, such as upload limitations.
    5820              :   /// Clients SHOULD use this as a guide when using content repository endpoints.
    5821              :   /// All values are intentionally left optional. Clients SHOULD follow
    5822              :   /// the advice given in the field description when the field is not available.
    5823              :   ///
    5824              :   /// **NOTE:** Both clients and server administrators should be aware that proxies
    5825              :   /// between the client and the server may affect the apparent behaviour of content
    5826              :   /// repository APIs, for example, proxies may enforce a lower upload size limit
    5827              :   /// than is advertised by the server on this endpoint.
    5828            0 :   @deprecated
    5829              :   Future<MediaConfig> getConfig() async {
    5830            0 :     final requestUri = Uri(path: '_matrix/media/v3/config');
    5831            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5832            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    5833            0 :     final response = await httpClient.send(request);
    5834            0 :     final responseBody = await response.stream.toBytes();
    5835            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5836            0 :     final responseString = utf8.decode(responseBody);
    5837            0 :     final json = jsonDecode(responseString);
    5838            0 :     return MediaConfig.fromJson(json as Map<String, Object?>);
    5839              :   }
    5840              : 
    5841              :   /// **NOTE:**
    5842              :   /// Replaced by [`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv1mediadownloadservernamemediaid)
    5843              :   /// (requires authentication).
    5844              :   ///
    5845              :   ///
    5846              :   /// **WARNING:**
    5847              :   /// **[Changed in `v1.11`]**  This endpoint MAY return `404 M_NOT_FOUND`
    5848              :   /// for media which exists, but is after the server froze unauthenticated
    5849              :   /// media access. See [Client Behaviour](https://spec.matrix.org/unstable/client-server-api/#content-repo-client-behaviour) for more
    5850              :   /// information.
    5851              :   ///
    5852              :   ///
    5853              :   /// [serverName] The server name from the `mxc://` URI (the authority component).
    5854              :   ///
    5855              :   ///
    5856              :   /// [mediaId] The media ID from the `mxc://` URI (the path component).
    5857              :   ///
    5858              :   ///
    5859              :   /// [allowRemote] Indicates to the server that it should not attempt to fetch the media if
    5860              :   /// it is deemed remote. This is to prevent routing loops where the server
    5861              :   /// contacts itself.
    5862              :   ///
    5863              :   /// Defaults to `true` if not provided.
    5864              :   ///
    5865              :   /// [timeoutMs] The maximum number of milliseconds that the client is willing to wait to
    5866              :   /// start receiving data, in the case that the content has not yet been
    5867              :   /// uploaded. The default value is 20000 (20 seconds). The content
    5868              :   /// repository SHOULD impose a maximum value for this parameter. The
    5869              :   /// content repository MAY respond before the timeout.
    5870              :   ///
    5871              :   ///
    5872              :   /// [allowRedirect] Indicates to the server that it may return a 307 or 308 redirect
    5873              :   /// response that points at the relevant media content. When not explicitly
    5874              :   /// set to `true` the server must return the media content itself.
    5875              :   ///
    5876            0 :   @deprecated
    5877              :   Future<FileResponse> getContent(
    5878              :     String serverName,
    5879              :     String mediaId, {
    5880              :     bool? allowRemote,
    5881              :     int? timeoutMs,
    5882              :     bool? allowRedirect,
    5883              :   }) async {
    5884            0 :     final requestUri = Uri(
    5885              :       path:
    5886            0 :           '_matrix/media/v3/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}',
    5887            0 :       queryParameters: {
    5888            0 :         if (allowRemote != null) 'allow_remote': allowRemote.toString(),
    5889            0 :         if (timeoutMs != null) 'timeout_ms': timeoutMs.toString(),
    5890            0 :         if (allowRedirect != null) 'allow_redirect': allowRedirect.toString(),
    5891              :       },
    5892              :     );
    5893            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5894            0 :     final response = await httpClient.send(request);
    5895            0 :     final responseBody = await response.stream.toBytes();
    5896            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5897            0 :     return FileResponse(
    5898            0 :       contentType: response.headers['content-type'],
    5899              :       data: responseBody,
    5900              :     );
    5901              :   }
    5902              : 
    5903              :   /// **NOTE:**
    5904              :   /// Replaced by [`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}/{fileName}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv1mediadownloadservernamemediaidfilename)
    5905              :   /// (requires authentication).
    5906              :   ///
    5907              :   ///
    5908              :   /// This will download content from the content repository (same as
    5909              :   /// the previous endpoint) but replace the target file name with the one
    5910              :   /// provided by the caller.
    5911              :   ///
    5912              :   /// **WARNING:**
    5913              :   /// **[Changed in `v1.11`]**  This endpoint MAY return `404 M_NOT_FOUND`
    5914              :   /// for media which exists, but is after the server froze unauthenticated
    5915              :   /// media access. See [Client Behaviour](https://spec.matrix.org/unstable/client-server-api/#content-repo-client-behaviour) for more
    5916              :   /// information.
    5917              :   ///
    5918              :   ///
    5919              :   /// [serverName] The server name from the `mxc://` URI (the authority component).
    5920              :   ///
    5921              :   ///
    5922              :   /// [mediaId] The media ID from the `mxc://` URI (the path component).
    5923              :   ///
    5924              :   ///
    5925              :   /// [fileName] A filename to give in the `Content-Disposition` header.
    5926              :   ///
    5927              :   /// [allowRemote] Indicates to the server that it should not attempt to fetch the media if
    5928              :   /// it is deemed remote. This is to prevent routing loops where the server
    5929              :   /// contacts itself.
    5930              :   ///
    5931              :   /// Defaults to `true` if not provided.
    5932              :   ///
    5933              :   /// [timeoutMs] The maximum number of milliseconds that the client is willing to wait to
    5934              :   /// start receiving data, in the case that the content has not yet been
    5935              :   /// uploaded. The default value is 20000 (20 seconds). The content
    5936              :   /// repository SHOULD impose a maximum value for this parameter. The
    5937              :   /// content repository MAY respond before the timeout.
    5938              :   ///
    5939              :   ///
    5940              :   /// [allowRedirect] Indicates to the server that it may return a 307 or 308 redirect
    5941              :   /// response that points at the relevant media content. When not explicitly
    5942              :   /// set to `true` the server must return the media content itself.
    5943              :   ///
    5944            0 :   @deprecated
    5945              :   Future<FileResponse> getContentOverrideName(
    5946              :     String serverName,
    5947              :     String mediaId,
    5948              :     String fileName, {
    5949              :     bool? allowRemote,
    5950              :     int? timeoutMs,
    5951              :     bool? allowRedirect,
    5952              :   }) async {
    5953            0 :     final requestUri = Uri(
    5954              :       path:
    5955            0 :           '_matrix/media/v3/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}/${Uri.encodeComponent(fileName)}',
    5956            0 :       queryParameters: {
    5957            0 :         if (allowRemote != null) 'allow_remote': allowRemote.toString(),
    5958            0 :         if (timeoutMs != null) 'timeout_ms': timeoutMs.toString(),
    5959            0 :         if (allowRedirect != null) 'allow_redirect': allowRedirect.toString(),
    5960              :       },
    5961              :     );
    5962            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    5963            0 :     final response = await httpClient.send(request);
    5964            0 :     final responseBody = await response.stream.toBytes();
    5965            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    5966            0 :     return FileResponse(
    5967            0 :       contentType: response.headers['content-type'],
    5968              :       data: responseBody,
    5969              :     );
    5970              :   }
    5971              : 
    5972              :   /// **NOTE:**
    5973              :   /// Replaced by [`GET /_matrix/client/v1/media/preview_url`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv1mediapreview_url).
    5974              :   ///
    5975              :   ///
    5976              :   /// Get information about a URL for the client. Typically this is called when a
    5977              :   /// client sees a URL in a message and wants to render a preview for the user.
    5978              :   ///
    5979              :   /// **Note:**
    5980              :   /// Clients should consider avoiding this endpoint for URLs posted in encrypted
    5981              :   /// rooms. Encrypted rooms often contain more sensitive information the users
    5982              :   /// do not want to share with the homeserver, and this can mean that the URLs
    5983              :   /// being shared should also not be shared with the homeserver.
    5984              :   ///
    5985              :   /// [url] The URL to get a preview of.
    5986              :   ///
    5987              :   /// [ts] The preferred point in time to return a preview for. The server may
    5988              :   /// return a newer version if it does not have the requested version
    5989              :   /// available.
    5990            0 :   @deprecated
    5991              :   Future<PreviewForUrl> getUrlPreview(Uri url, {int? ts}) async {
    5992            0 :     final requestUri = Uri(
    5993              :       path: '_matrix/media/v3/preview_url',
    5994            0 :       queryParameters: {
    5995            0 :         'url': url.toString(),
    5996            0 :         if (ts != null) 'ts': ts.toString(),
    5997              :       },
    5998              :     );
    5999            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    6000            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    6001            0 :     final response = await httpClient.send(request);
    6002            0 :     final responseBody = await response.stream.toBytes();
    6003            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    6004            0 :     final responseString = utf8.decode(responseBody);
    6005            0 :     final json = jsonDecode(responseString);
    6006            0 :     return PreviewForUrl.fromJson(json as Map<String, Object?>);
    6007              :   }
    6008              : 
    6009              :   /// **NOTE:**
    6010              :   /// Replaced by [`GET /_matrix/client/v1/media/thumbnail/{serverName}/{mediaId}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv1mediathumbnailservernamemediaid)
    6011              :   /// (requires authentication).
    6012              :   ///
    6013              :   ///
    6014              :   /// Download a thumbnail of content from the content repository.
    6015              :   /// See the [Thumbnails](https://spec.matrix.org/unstable/client-server-api/#thumbnails) section for more information.
    6016              :   ///
    6017              :   /// **WARNING:**
    6018              :   /// **[Changed in `v1.11`]**  This endpoint MAY return `404 M_NOT_FOUND`
    6019              :   /// for media which exists, but is after the server froze unauthenticated
    6020              :   /// media access. See [Client Behaviour](https://spec.matrix.org/unstable/client-server-api/#content-repo-client-behaviour) for more
    6021              :   /// information.
    6022              :   ///
    6023              :   ///
    6024              :   /// [serverName] The server name from the `mxc://` URI (the authority component).
    6025              :   ///
    6026              :   ///
    6027              :   /// [mediaId] The media ID from the `mxc://` URI (the path component).
    6028              :   ///
    6029              :   ///
    6030              :   /// [width] The *desired* width of the thumbnail. The actual thumbnail may be
    6031              :   /// larger than the size specified.
    6032              :   ///
    6033              :   /// [height] The *desired* height of the thumbnail. The actual thumbnail may be
    6034              :   /// larger than the size specified.
    6035              :   ///
    6036              :   /// [method] The desired resizing method. See the [Thumbnails](https://spec.matrix.org/unstable/client-server-api/#thumbnails)
    6037              :   /// section for more information.
    6038              :   ///
    6039              :   /// [allowRemote] Indicates to the server that it should not attempt to fetch the media if
    6040              :   /// it is deemed remote. This is to prevent routing loops where the server
    6041              :   /// contacts itself.
    6042              :   ///
    6043              :   /// Defaults to `true` if not provided.
    6044              :   ///
    6045              :   /// [timeoutMs] The maximum number of milliseconds that the client is willing to wait to
    6046              :   /// start receiving data, in the case that the content has not yet been
    6047              :   /// uploaded. The default value is 20000 (20 seconds). The content
    6048              :   /// repository SHOULD impose a maximum value for this parameter. The
    6049              :   /// content repository MAY respond before the timeout.
    6050              :   ///
    6051              :   ///
    6052              :   /// [allowRedirect] Indicates to the server that it may return a 307 or 308 redirect
    6053              :   /// response that points at the relevant media content. When not explicitly
    6054              :   /// set to `true` the server must return the media content itself.
    6055              :   ///
    6056              :   ///
    6057              :   /// [animated] Indicates preference for an animated thumbnail from the server, if possible. Animated
    6058              :   /// thumbnails typically use the content types `image/gif`, `image/png` (with APNG format),
    6059              :   /// `image/apng`, and `image/webp` instead of the common static `image/png` or `image/jpeg`
    6060              :   /// content types.
    6061              :   ///
    6062              :   /// When `true`, the server SHOULD return an animated thumbnail if possible and supported.
    6063              :   /// When `false`, the server MUST NOT return an animated thumbnail. For example, returning a
    6064              :   /// static `image/png` or `image/jpeg` thumbnail. When not provided, the server SHOULD NOT
    6065              :   /// return an animated thumbnail.
    6066              :   ///
    6067              :   /// Servers SHOULD prefer to return `image/webp` thumbnails when supporting animation.
    6068              :   ///
    6069              :   /// When `true` and the media cannot be animated, such as in the case of a JPEG or PDF, the
    6070              :   /// server SHOULD behave as though `animated` is `false`.
    6071              :   ///
    6072            0 :   @deprecated
    6073              :   Future<FileResponse> getContentThumbnail(
    6074              :     String serverName,
    6075              :     String mediaId,
    6076              :     int width,
    6077              :     int height, {
    6078              :     Method? method,
    6079              :     bool? allowRemote,
    6080              :     int? timeoutMs,
    6081              :     bool? allowRedirect,
    6082              :     bool? animated,
    6083              :   }) async {
    6084            0 :     final requestUri = Uri(
    6085              :       path:
    6086            0 :           '_matrix/media/v3/thumbnail/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}',
    6087            0 :       queryParameters: {
    6088            0 :         'width': width.toString(),
    6089            0 :         'height': height.toString(),
    6090            0 :         if (method != null) 'method': method.name,
    6091            0 :         if (allowRemote != null) 'allow_remote': allowRemote.toString(),
    6092            0 :         if (timeoutMs != null) 'timeout_ms': timeoutMs.toString(),
    6093            0 :         if (allowRedirect != null) 'allow_redirect': allowRedirect.toString(),
    6094            0 :         if (animated != null) 'animated': animated.toString(),
    6095              :       },
    6096              :     );
    6097            0 :     final request = Request('GET', baseUri!.resolveUri(requestUri));
    6098            0 :     final response = await httpClient.send(request);
    6099            0 :     final responseBody = await response.stream.toBytes();
    6100            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    6101            0 :     return FileResponse(
    6102            0 :       contentType: response.headers['content-type'],
    6103              :       data: responseBody,
    6104              :     );
    6105              :   }
    6106              : 
    6107              :   ///
    6108              :   ///
    6109              :   /// [filename] The name of the file being uploaded
    6110              :   ///
    6111              :   /// [body]
    6112              :   ///
    6113              :   /// [contentType] **Optional.** The content type of the file being uploaded.
    6114              :   ///
    6115              :   /// Clients SHOULD always supply this header.
    6116              :   ///
    6117              :   /// Defaults to `application/octet-stream` if it is not set.
    6118              :   ///
    6119              :   ///
    6120              :   /// returns `content_uri`:
    6121              :   /// The [`mxc://` URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the uploaded content.
    6122            4 :   Future<Uri> uploadContent(
    6123              :     Uint8List body, {
    6124              :     String? filename,
    6125              :     String? contentType,
    6126              :   }) async {
    6127            4 :     final requestUri = Uri(
    6128              :       path: '_matrix/media/v3/upload',
    6129            4 :       queryParameters: {
    6130            4 :         if (filename != null) 'filename': filename,
    6131              :       },
    6132              :     );
    6133           12 :     final request = Request('POST', baseUri!.resolveUri(requestUri));
    6134           16 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    6135            8 :     if (contentType != null) request.headers['content-type'] = contentType;
    6136            4 :     request.bodyBytes = body;
    6137            8 :     final response = await httpClient.send(request);
    6138            8 :     final responseBody = await response.stream.toBytes();
    6139            8 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    6140            4 :     final responseString = utf8.decode(responseBody);
    6141            4 :     final json = jsonDecode(responseString);
    6142            8 :     return ((json['content_uri'] as String).startsWith('mxc://')
    6143            8 :         ? Uri.parse(json['content_uri'] as String)
    6144            0 :         : throw Exception('Uri not an mxc URI'));
    6145              :   }
    6146              : 
    6147              :   /// This endpoint permits uploading content to an `mxc://` URI that was created
    6148              :   /// earlier via [POST /_matrix/media/v1/create](https://spec.matrix.org/unstable/client-server-api/#post_matrixmediav1create).
    6149              :   ///
    6150              :   /// [serverName] The server name from the `mxc://` URI returned by `POST /_matrix/media/v1/create` (the authority component).
    6151              :   ///
    6152              :   ///
    6153              :   /// [mediaId] The media ID from the `mxc://` URI returned by `POST /_matrix/media/v1/create` (the path component).
    6154              :   ///
    6155              :   ///
    6156              :   /// [filename] The name of the file being uploaded
    6157              :   ///
    6158              :   /// [body]
    6159              :   ///
    6160              :   /// [contentType] **Optional.** The content type of the file being uploaded.
    6161              :   ///
    6162              :   /// Clients SHOULD always supply this header.
    6163              :   ///
    6164              :   /// Defaults to `application/octet-stream` if it is not set.
    6165              :   ///
    6166            0 :   Future<Map<String, Object?>> uploadContentToMXC(
    6167              :     String serverName,
    6168              :     String mediaId,
    6169              :     Uint8List body, {
    6170              :     String? filename,
    6171              :     String? contentType,
    6172              :   }) async {
    6173            0 :     final requestUri = Uri(
    6174              :       path:
    6175            0 :           '_matrix/media/v3/upload/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}',
    6176            0 :       queryParameters: {
    6177            0 :         if (filename != null) 'filename': filename,
    6178              :       },
    6179              :     );
    6180            0 :     final request = Request('PUT', baseUri!.resolveUri(requestUri));
    6181            0 :     request.headers['authorization'] = 'Bearer ${bearerToken!}';
    6182            0 :     if (contentType != null) request.headers['content-type'] = contentType;
    6183            0 :     request.bodyBytes = body;
    6184            0 :     final response = await httpClient.send(request);
    6185            0 :     final responseBody = await response.stream.toBytes();
    6186            0 :     if (response.statusCode != 200) unexpectedResponse(response, responseBody);
    6187            0 :     final responseString = utf8.decode(responseBody);
    6188            0 :     final json = jsonDecode(responseString);
    6189              :     return json as Map<String, Object?>;
    6190              :   }
    6191              : }
        

Generated by: LCOV version 2.0-1