diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 1ca54f5b..d626dccd 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -776,7 +776,7 @@ class FakeMatrixApi extends MockClient { 'u.Customers': {} } }, - '/client/r0/events?from=1234&timeout=10&roomId=%211234': (var req) => { + '/client/r0/events?from=1234&timeout=10&room_id=%211234': (var req) => { 'start': 's3456_9_0', 'end': 's3457_9_0', 'chunk': [ diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 838e242e..8cd63c62 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -50,7 +50,6 @@ export 'src/model/events/room_key_request_content.dart'; export 'src/model/events/secret_storage_default_key_content.dart'; export 'src/model/events/secret_storage_key_content.dart'; export 'src/model/events/tombstone_content.dart'; -export 'src/model/events_sync_update.dart'; export 'src/model/matrix_connection_exception.dart'; export 'src/model/matrix_event.dart'; export 'src/model/matrix_exception.dart'; @@ -58,15 +57,10 @@ export 'src/model/matrix_keys.dart'; export 'src/model/message_types.dart'; export 'src/model/presence.dart'; export 'src/model/presence_content.dart'; -export 'src/model/request_token_response.dart'; export 'src/model/room_creation_types.dart'; -export 'src/model/room_keys_keys.dart'; export 'src/model/room_summary.dart'; export 'src/model/stripped_state_event.dart'; -export 'src/model/supported_protocol.dart'; export 'src/model/sync_update.dart'; -export 'src/model/third_party_location.dart'; -export 'src/model/third_party_user.dart'; export 'src/model/upload_key_signatures_response.dart'; export 'src/utils/logs.dart'; export 'src/utils/map_copy_extension.dart'; diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 39408a66..5a28a352 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -212,6 +212,139 @@ class Api { }[json['id_server_unbind_result']]!; } + /// The homeserver must check that the given email address is **not** + /// already associated with an account on this homeserver. This API should + /// be used to request validation tokens when adding an email address to an + /// account. This API's parameters and response are identical to that of + /// the [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registeremailrequesttoken) + /// endpoint. The homeserver should validate + /// the email itself, either by sending a validation email itself or by using + /// a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [email] The email address to validate. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [sendAttempt] The server will only send an email if the `send_attempt` + /// is a number greater than the most recent one which it has seen, + /// scoped to that `email` + `client_secret` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. If they do not, the server + /// should respond with success but not resend the email. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenTo3PIDEmail( + String clientSecret, String email, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/3pid/email/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'email': email, + if (nextLink != null) 'next_link': nextLink, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// The homeserver must check that the given phone number is **not** + /// already associated with an account on this homeserver. This API should + /// be used to request validation tokens when adding a phone number to an + /// account. This API's parameters and response are identical to that of + /// the [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + /// endpoint. The homeserver should validate + /// the phone number itself, either by sending a validation message itself or by using + /// a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the + /// number in `phone_number` should be parsed as if it were dialled from. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [phoneNumber] The phone number to validate. + /// + /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a + /// number greater than the most recent one which it has seen, + /// scoped to that `country` + `phone_number` + `client_secret` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenTo3PIDMSISDN( + String clientSecret, String country, String phoneNumber, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/3pid/msisdn/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'country': country, + if (nextLink != null) 'next_link': nextLink, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + /// Removes a user's third party identifier from the provided identity server /// without removing it from the homeserver. /// @@ -356,6 +489,153 @@ class Api { return ignore(json); } + /// The homeserver must check that the given email address **is + /// associated** with an account on this homeserver. This API should be + /// used to request validation tokens when authenticating for the + /// `/account/password` endpoint. + /// + /// This API's parameters and response are identical to that of the + /// [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registeremailrequesttoken) + /// endpoint, except that + /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the + /// given email address could be found. The server may instead send an + /// email to the given address prompting the user to create an account. + /// `M_THREEPID_IN_USE` may not be returned. + /// + /// The homeserver should validate the email itself, either by sending a + /// validation email itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [email] The email address to validate. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [sendAttempt] The server will only send an email if the `send_attempt` + /// is a number greater than the most recent one which it has seen, + /// scoped to that `email` + `client_secret` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. If they do not, the server + /// should respond with success but not resend the email. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToResetPasswordEmail( + String clientSecret, String email, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/password/email/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'email': email, + if (nextLink != null) 'next_link': nextLink, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// The homeserver must check that the given phone number **is + /// associated** with an account on this homeserver. This API should be + /// used to request validation tokens when authenticating for the + /// `/account/password` endpoint. + /// + /// This API's parameters and response are identical to that of the + /// [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + /// endpoint, except that + /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the + /// given phone number could be found. The server may instead send the SMS + /// to the given phone number prompting the user to create an account. + /// `M_THREEPID_IN_USE` may not be returned. + /// + /// The homeserver should validate the phone number itself, either by sending a + /// validation message itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the + /// number in `phone_number` should be parsed as if it were dialled from. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [phoneNumber] The phone number to validate. + /// + /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a + /// number greater than the most recent one which it has seen, + /// scoped to that `country` + `phone_number` + `client_secret` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToResetPasswordMSISDN( + String clientSecret, String country, String phoneNumber, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/password/msisdn/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'country': country, + if (nextLink != null) 'next_link': nextLink, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + /// Gets information about the owner of a given access token. /// /// Note that, as with the rest of the Client-Server API, @@ -725,6 +1005,61 @@ class Api { return json as Map; } + /// Gets the visibility of a given room on the server's public room directory. + /// + /// [roomId] The room ID. + /// + /// returns `visibility`: + /// The visibility of the room in the directory. + Future getRoomVisibilityOnDirectory(String roomId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? {'public': Visibility.public, 'private': Visibility.private}[v]! + : null)(json['visibility']); + } + + /// Sets the visibility of a given room in the server's public room + /// directory. + /// + /// Servers may choose to implement additional access control checks + /// here, for instance that room visibility can only be changed by + /// the room creator or a server administrator. + /// + /// [roomId] The room ID. + /// + /// [visibility] The new visibility setting for the room. + /// Defaults to 'public'. + Future setRoomVisibilityOnDirectory(String roomId, + {Visibility? visibility}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (visibility != null) + 'visibility': { + Visibility.public: 'public', + Visibility.private: 'private' + }[visibility]!, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + /// Remove a mapping of room alias to room ID. /// /// Servers may choose to implement additional access control checks here, for instance that @@ -795,6 +1130,68 @@ class Api { return ignore(json); } + /// This will listen for new events and return them to the caller. This will + /// block until an event is received, or until the `timeout` is reached. + /// + /// This endpoint was deprecated in r0 of this specification. Clients + /// should instead call the [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) + /// API with a `since` parameter. See + /// the [migration guide](https://matrix.org/docs/guides/migrating-from-client-server-api-v-1#deprecated-endpoints). + /// + /// [from] The token to stream from. This token is either from a previous + /// request to this API or from the initial sync API. + /// + /// [timeout] The maximum time in milliseconds to wait for an event. + @deprecated + Future getEvents({String? from, int? timeout}) async { + final requestUri = Uri(path: '_matrix/client/r0/events', queryParameters: { + if (from != null) 'from': from, + if (timeout != null) 'timeout': timeout.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return EventsSyncUpdate.fromJson(json); + } + + /// This will listen for new events related to a particular room and return + /// them to the caller. This will block until an event is received, or until + /// the `timeout` is reached. + /// + /// This API is the same as the normal `/events` endpoint, but can be + /// called by users who have not joined the room. + /// + /// Note that the normal `/events` endpoint has been deprecated. This + /// API will also be deprecated at some point, but its replacement is not + /// yet known. + /// + /// [from] The token to stream from. This token is either from a previous + /// request to this API or from the initial sync API. + /// + /// [timeout] The maximum time in milliseconds to wait for an event. + /// + /// [roomId] The room ID for which events should be returned. + Future peekEvents( + {String? from, int? timeout, String? roomId}) async { + final requestUri = Uri(path: '_matrix/client/r0/events', queryParameters: { + if (from != null) 'from': from, + if (timeout != null) 'timeout': timeout.toString(), + if (roomId != null) 'room_id': roomId, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return EventsSyncUpdate.fromJson(json); + } + /// Get a single event based on `event_id`. You must have permission to /// retrieve this event e.g. by being a member in the room for this event. /// @@ -948,6 +1345,48 @@ class Api { return ClaimKeysResponse.fromJson(json); } + /// Publishes cross-signing keys for the user. + /// + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). + /// + /// [auth] Additional authentication information for the + /// user-interactive authentication API. + /// + /// [masterKey] Optional. The user\'s master key. + /// + /// [selfSigningKey] Optional. The user\'s self-signing key. Must be signed by + /// the accompanying master key, or by the user\'s most recently + /// uploaded master key if no master key is included in the + /// request. + /// + /// [userSigningKey] Optional. The user\'s user-signing key. Must be signed by + /// the accompanying master key, or by the user\'s most recently + /// uploaded master key if no master key is included in the + /// request. + Future uploadCrossSigningKeys( + {AuthenticationData? auth, + MatrixCrossSigningKey? masterKey, + MatrixCrossSigningKey? selfSigningKey, + MatrixCrossSigningKey? userSigningKey}) async { + final requestUri = + Uri(path: '_matrix/client/unstable/keys/device_signing/upload'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + if (masterKey != null) 'master_key': masterKey.toJson(), + if (selfSigningKey != null) 'self_signing_key': selfSigningKey.toJson(), + if (userSigningKey != null) 'user_signing_key': userSigningKey.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + /// Returns the current devices and identity keys for the given users. /// /// [deviceKeys] The keys to be downloaded. A map from user ID, to a list of @@ -981,6 +1420,36 @@ class Api { return QueryKeysResponse.fromJson(json); } + /// Publishes cross-signing signatures for the user. The request body is a + /// map from user ID to key ID to signed JSON object. + /// + /// [signatures] The signatures to be published. + /// + /// returns `failures`: + /// A map from user ID to key ID to an error for any signatures + /// that failed. If a signature was invalid, the `errcode` will + /// be set to `M_INVALID_SIGNATURE`. + Future>>?> + uploadCrossSigningSignatures( + Map>> signatures) async { + final requestUri = Uri(path: '_matrix/client/r0/keys/signatures/upload'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(signatures)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as Map).map((k, v) => MapEntry( + k, + (v as Map) + .map((k, v) => MapEntry(k, v as Map)))) + : null)(json['failures']); + } + /// *Note that this API takes either a room ID or alias, unlike other membership APIs.* /// /// This API "knocks" on the room to ask for permission to join, if the user @@ -1856,12 +2325,173 @@ class Api { return ((v) => v != null ? v as bool : null)(json['available']); } + /// The homeserver must check that the given email address is **not** + /// already associated with an account on this homeserver. The homeserver + /// should validate the email itself, either by sending a validation email + /// itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [email] The email address to validate. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [sendAttempt] The server will only send an email if the `send_attempt` + /// is a number greater than the most recent one which it has seen, + /// scoped to that `email` + `client_secret` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. If they do not, the server + /// should respond with success but not resend the email. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToRegisterEmail( + String clientSecret, String email, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/register/email/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'email': email, + if (nextLink != null) 'next_link': nextLink, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// The homeserver must check that the given phone number is **not** + /// already associated with an account on this homeserver. The homeserver + /// should validate the phone number itself, either by sending a validation + /// message itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the + /// number in `phone_number` should be parsed as if it were dialled from. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [phoneNumber] The phone number to validate. + /// + /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a + /// number greater than the most recent one which it has seen, + /// scoped to that `country` + `phone_number` + `client_secret` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToRegisterMSISDN( + String clientSecret, String country, String phoneNumber, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/register/msisdn/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'country': country, + if (nextLink != null) 'next_link': nextLink, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// Delete the keys from the backup. + /// + /// [version] The backup from which to delete the key + Future deleteRoomKeys(String version) async { + final requestUri = + Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + 'version': version, + }); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Retrieve the keys from the backup. + /// + /// [version] The backup from which to retrieve the keys. + Future getRoomKeys(String version) async { + final requestUri = + Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + 'version': version, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeys.fromJson(json); + } + /// Store several keys in the backup. /// /// [version] The backup in which to store the keys. Must be the current backup. /// /// [backupData] The backup data. - Future postRoomKeysKey( + Future putRoomKeys( String version, RoomKeys backupData) async { final requestUri = Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { @@ -1876,17 +2506,63 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PostRoomKeysKeyResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json); } - /// Store a key in the backup. + /// Delete the keys from the backup for a given room. + /// + /// [roomId] The ID of the room that the specified key is for. + /// + /// [version] The backup from which to delete the key. + Future deleteRoomKeysByRoomId( + String roomId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + queryParameters: { + 'version': version, + }); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Retrieve the keys from the backup for a given room. + /// + /// [roomId] The ID of the room that the requested key is for. + /// + /// [version] The backup from which to retrieve the key. + Future getRoomKeysByRoomId( + String roomId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + queryParameters: { + 'version': version, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeyBackup.fromJson(json); + } + + /// Store several keys in the backup for a given room. /// /// [roomId] The ID of the room that the keys are for. /// /// [version] The backup in which to store the keys. Must be the current backup. /// /// [backupData] The backup data - Future postRoomKeysKeyRoomId( + Future putRoomKeysByRoomId( String roomId, String version, RoomKeyBackup backupData) async { final requestUri = Uri( path: @@ -1903,7 +2579,57 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PostRoomKeysKeyRoomIdResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Delete a key from the backup. + /// + /// [roomId] The ID of the room that the specified key is for. + /// + /// [sessionId] The ID of the megolm session whose key is to be deleted. + /// + /// [version] The backup from which to delete the key + Future deleteRoomKeysBySessionId( + String roomId, String sessionId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + queryParameters: { + 'version': version, + }); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Retrieve a key from the backup. + /// + /// [roomId] The ID of the room that the requested key is for. + /// + /// [sessionId] The ID of the megolm session whose key is requested. + /// + /// [version] The backup from which to retrieve the key. + Future getRoomKeysBySessionId( + String roomId, String sessionId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + queryParameters: { + 'version': version, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return KeyBackupData.fromJson(json); } /// Store a key in the backup. @@ -1915,11 +2641,8 @@ class Api { /// [version] The backup in which to store the key. Must be the current backup. /// /// [data] The key data. - Future postRoomKeysKeyRoomIdSessionId( - String roomId, - String sessionId, - String version, - KeyBackupData data) async { + Future putRoomKeysBySessionId(String roomId, + String sessionId, String version, KeyBackupData data) async { final requestUri = Uri( path: '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', @@ -1935,7 +2658,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PostRoomKeysKeyRoomIdSessionIdResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json); } /// Get information about the latest backup version. @@ -3036,6 +3759,131 @@ class Api { return SyncUpdate.fromJson(json); } + /// Retrieve an array of third party network locations from a Matrix room + /// alias. + /// + /// [alias] The Matrix room alias to look up. + Future> queryLocationByAlias(String alias) async { + final requestUri = + Uri(path: '_matrix/client/r0/thirdparty/location', queryParameters: { + 'alias': alias, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => Location.fromJson(v)).toList(); + } + + /// Requesting this endpoint with a valid protocol name results in a list + /// of successful mapping results in a JSON array. Each result contains + /// objects to represent the Matrix room or rooms that represent a portal + /// to this third party network. Each has the Matrix room alias string, + /// an identifier for the particular third party network protocol, and an + /// object containing the network-specific fields that comprise this + /// identifier. It should attempt to canonicalise the identifier as much + /// as reasonably possible given the network type. + /// + /// [protocol] The protocol used to communicate to the third party network. + /// + /// [searchFields] One or more custom fields to help identify the third party + /// location. + Future> queryLocationByProtocol(String protocol, + {String? searchFields}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/thirdparty/location/${Uri.encodeComponent(protocol)}', + queryParameters: { + if (searchFields != null) 'searchFields': searchFields, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => Location.fromJson(v)).toList(); + } + + /// Fetches the metadata from the homeserver about a particular third party protocol. + /// + /// [protocol] The name of the protocol. + Future getProtocolMetadata(String protocol) async { + final requestUri = Uri( + path: + '_matrix/client/r0/thirdparty/protocol/${Uri.encodeComponent(protocol)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return Protocol.fromJson(json); + } + + /// Fetches the overall metadata about protocols supported by the + /// homeserver. Includes both the available protocols and all fields + /// required for queries against each protocol. + Future> getProtocols() async { + final requestUri = Uri(path: '_matrix/client/r0/thirdparty/protocols'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as Map) + .map((k, v) => MapEntry(k, Protocol.fromJson(v))); + } + + /// Retrieve an array of third party users from a Matrix User ID. + /// + /// [userid] The Matrix User ID to look up. + Future> queryUserByID(String userid) async { + final requestUri = + Uri(path: '_matrix/client/r0/thirdparty/user', queryParameters: { + 'userid': userid, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); + } + + /// Retrieve a Matrix User ID linked to a user on the third party service, given + /// a set of user parameters. + /// + /// [protocol] The name of the protocol. + /// + /// [fields] One or more custom fields that are passed to the AS to help identify the user. + Future> queryUserByProtocol(String protocol, + {String? fields}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/thirdparty/user/${Uri.encodeComponent(protocol)}', + queryParameters: { + if (fields != null) 'fields...': fields, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); + } + /// Get some account_data for the client. This config is only visible to the user /// that set the account_data. /// @@ -3531,16 +4379,16 @@ class Api { /// uploadContent /// - /// [contentType] The content type of the file being uploaded - /// /// [filename] The name of the file being uploaded /// /// [content] The content to be uploaded. /// + /// [contentType] The content type of the file being uploaded + /// /// returns `content_uri`: /// The [MXC URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the uploaded content. Future uploadContent(Uint8List content, - {String? contentType, String? filename}) async { + {String? filename, String? contentType}) async { final requestUri = Uri(path: '_matrix/media/r0/upload', queryParameters: { if (filename != null) 'filename': filename, }); diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 324c5822..f4f5f2e0 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -165,6 +165,43 @@ class ThreePidCredentials { @_NameSource('generated') enum IdServerUnbindResult { noSupport, success } +@_NameSource('spec') +class RequestTokenResponse { + RequestTokenResponse({ + required this.sid, + this.submitUrl, + }); + + RequestTokenResponse.fromJson(Map json) + : sid = json['sid'] as String, + submitUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['submit_url']); + Map toJson() { + final submitUrl = this.submitUrl; + return { + 'sid': sid, + if (submitUrl != null) 'submit_url': submitUrl.toString(), + }; + } + + /// The session ID. Session IDs are opaque strings that must consist entirely + /// of the characters `[0-9a-zA-Z.=_-]`. Their length must not exceed 255 + /// characters and they must not be empty. + String sid; + + /// An optional field containing a URL where the client must submit the + /// validation token to, with identical parameters to the Identity Service + /// API's `POST /validate/email/submitToken` endpoint (without the requirement + /// for an access token). The homeserver must send this token to the user (if + /// applicable), who should then be prompted to provide it to the client. + /// + /// If this field is not present, the client can assume that verification + /// will happen without the client's involvement provided the homeserver + /// advertises this specification version in the `/versions` response + /// (ie: r0.5.0). + Uri? submitUrl; +} + @_NameSource('rule override generated') class TokenOwnerInfo { TokenOwnerInfo({ @@ -539,6 +576,43 @@ class GetRoomIdByAliasResponse { List? servers; } +@_NameSource('rule override generated') +class EventsSyncUpdate { + EventsSyncUpdate({ + this.chunk, + this.end, + this.start, + }); + + EventsSyncUpdate.fromJson(Map json) + : chunk = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['chunk']), + end = ((v) => v != null ? v as String : null)(json['end']), + start = ((v) => v != null ? v as String : null)(json['start']); + Map toJson() { + final chunk = this.chunk; + final end = this.end; + final start = this.start; + return { + if (chunk != null) 'chunk': chunk.map((v) => v.toJson()).toList(), + if (end != null) 'end': end, + if (start != null) 'start': start, + }; + } + + /// An array of events. + List? chunk; + + /// A token which correlates to the last value in `chunk`. This + /// token should be used in the next request to `/events`. + String? end; + + /// A token which correlates to the first value in `chunk`. This + /// is usually the same token supplied to `from=`. + String? start; +} + /// A signature of an `m.third_party_invite` token to prove that this user /// owns a third party identity which has been invited to the room. @_NameSource('spec') @@ -1522,6 +1596,29 @@ class RegisterResponse { String userId; } +@_NameSource('spec') +class RoomKeysUpdateResponse { + RoomKeysUpdateResponse({ + required this.count, + required this.etag, + }); + + RoomKeysUpdateResponse.fromJson(Map json) + : count = json['count'] as int, + etag = json['etag'] as String; + Map toJson() => { + 'count': count, + 'etag': etag, + }; + + /// The number of keys stored in the backup + int count; + + /// The new etag value representing stored keys in the backup. + /// See `GET /room_keys/version/{version}` for more details. + String etag; +} + /// The key data @_NameSource('spec') class KeyBackupData { @@ -1595,75 +1692,6 @@ class RoomKeys { Map rooms; } -@_NameSource('generated') -class PostRoomKeysKeyResponse { - PostRoomKeysKeyResponse({ - required this.count, - required this.etag, - }); - - PostRoomKeysKeyResponse.fromJson(Map json) - : count = json['count'] as int, - etag = json['etag'] as String; - Map toJson() => { - 'count': count, - 'etag': etag, - }; - - /// The number of keys stored in the backup - int count; - - /// The new etag value representing stored keys in the backup. - /// See `GET /room_keys/version/{version}` for more details. - String etag; -} - -@_NameSource('generated') -class PostRoomKeysKeyRoomIdResponse { - PostRoomKeysKeyRoomIdResponse({ - required this.count, - required this.etag, - }); - - PostRoomKeysKeyRoomIdResponse.fromJson(Map json) - : count = json['count'] as int, - etag = json['etag'] as String; - Map toJson() => { - 'count': count, - 'etag': etag, - }; - - /// The number of keys stored in the backup - int count; - - /// The new etag value representing stored keys in the backup. - /// See `GET /room_keys/version/{version}` for more details. - String etag; -} - -@_NameSource('generated') -class PostRoomKeysKeyRoomIdSessionIdResponse { - PostRoomKeysKeyRoomIdSessionIdResponse({ - required this.count, - required this.etag, - }); - - PostRoomKeysKeyRoomIdSessionIdResponse.fromJson(Map json) - : count = json['count'] as int, - etag = json['etag'] as String; - Map toJson() => { - 'count': count, - 'etag': etag, - }; - - /// The number of keys stored in the backup - int count; - - /// The new etag value representing stored keys in the backup. - /// See `GET /room_keys/version/{version}` for more details. - String etag; -} - @_NameSource('rule override generated') enum BackupAlgorithm { mMegolmBackupV1Curve25519AesSha2 } @@ -2635,6 +2663,182 @@ class SearchResults { ResultCategories searchCategories; } +@_NameSource('spec') +class Location { + Location({ + required this.alias, + required this.fields, + required this.protocol, + }); + + Location.fromJson(Map json) + : alias = json['alias'] as String, + fields = json['fields'] as Map, + protocol = json['protocol'] as String; + Map toJson() => { + 'alias': alias, + 'fields': fields, + 'protocol': protocol, + }; + + /// An alias for a matrix room. + String alias; + + /// Information used to identify this third party location. + Map fields; + + /// The protocol ID that the third party location is a part of. + String protocol; +} + +/// Definition of valid values for a field. +@_NameSource('spec') +class FieldType { + FieldType({ + required this.placeholder, + required this.regexp, + }); + + FieldType.fromJson(Map json) + : placeholder = json['placeholder'] as String, + regexp = json['regexp'] as String; + Map toJson() => { + 'placeholder': placeholder, + 'regexp': regexp, + }; + + /// An placeholder serving as a valid example of the field value. + String placeholder; + + /// A regular expression for validation of a field's value. This may be relatively + /// coarse to verify the value as the application service providing this protocol + /// may apply additional validation or filtering. + String regexp; +} + +@_NameSource('spec') +class ProtocolInstance { + ProtocolInstance({ + required this.desc, + required this.fields, + this.icon, + required this.networkId, + }); + + ProtocolInstance.fromJson(Map json) + : desc = json['desc'] as String, + fields = json['fields'] as Map, + icon = ((v) => v != null ? v as String : null)(json['icon']), + networkId = json['network_id'] as String; + Map toJson() { + final icon = this.icon; + return { + 'desc': desc, + 'fields': fields, + if (icon != null) 'icon': icon, + 'network_id': networkId, + }; + } + + /// A human-readable description for the protocol, such as the name. + String desc; + + /// Preset values for `fields` the client may use to search by. + Map fields; + + /// An optional content URI representing the protocol. Overrides the one provided + /// at the higher level Protocol object. + String? icon; + + /// A unique identifier across all instances. + String networkId; +} + +@_NameSource('spec') +class Protocol { + Protocol({ + required this.fieldTypes, + required this.icon, + required this.instances, + required this.locationFields, + required this.userFields, + }); + + Protocol.fromJson(Map json) + : fieldTypes = (json['field_types'] as Map) + .map((k, v) => MapEntry(k, FieldType.fromJson(v))), + icon = json['icon'] as String, + instances = (json['instances'] as List) + .map((v) => ProtocolInstance.fromJson(v)) + .toList(), + locationFields = + (json['location_fields'] as List).map((v) => v as String).toList(), + userFields = + (json['user_fields'] as List).map((v) => v as String).toList(); + Map toJson() => { + 'field_types': fieldTypes.map((k, v) => MapEntry(k, v.toJson())), + 'icon': icon, + 'instances': instances.map((v) => v.toJson()).toList(), + 'location_fields': locationFields.map((v) => v).toList(), + 'user_fields': userFields.map((v) => v).toList(), + }; + + /// The type definitions for the fields defined in the `user_fields` and + /// `location_fields`. Each entry in those arrays MUST have an entry here. The + /// `string` key for this object is field name itself. + /// + /// May be an empty object if no fields are defined. + Map fieldTypes; + + /// A content URI representing an icon for the third party protocol. + String icon; + + /// A list of objects representing independent instances of configuration. + /// For example, multiple networks on IRC if multiple are provided by the + /// same application service. + List instances; + + /// Fields which may be used to identify a third party location. These should be + /// ordered to suggest the way that entities may be grouped, where higher + /// groupings are ordered first. For example, the name of a network should be + /// searched before the name of a channel. + List locationFields; + + /// Fields which may be used to identify a third party user. These should be + /// ordered to suggest the way that entities may be grouped, where higher + /// groupings are ordered first. For example, the name of a network should be + /// searched before the nickname of a user. + List userFields; +} + +@_NameSource('rule override spec') +class ThirdPartyUser { + ThirdPartyUser({ + required this.fields, + required this.protocol, + required this.userid, + }); + + ThirdPartyUser.fromJson(Map json) + : fields = json['fields'] as Map, + protocol = json['protocol'] as String, + userid = json['userid'] as String; + Map toJson() => { + 'fields': fields, + 'protocol': protocol, + 'userid': userid, + }; + + /// Information used to identify this third party location. + Map fields; + + /// The protocol ID that the third party location is a part of. + String protocol; + + /// A Matrix User ID represting a third party user. + String userid; +} + @_NameSource('generated') enum EventFormat { client, federation } diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 88859870..f64b633c 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -29,27 +29,13 @@ import 'package:http/http.dart' as http; import '../matrix_api_lite.dart'; import 'generated/api.dart'; -import 'model/auth/authentication_data.dart'; -import 'model/events_sync_update.dart'; import 'model/matrix_connection_exception.dart'; import 'model/matrix_exception.dart'; import 'model/matrix_keys.dart'; -import 'model/request_token_response.dart'; -import 'model/room_keys_keys.dart'; -import 'model/supported_protocol.dart'; -import 'model/third_party_location.dart'; -import 'model/third_party_user.dart'; import 'model/upload_key_signatures_response.dart'; enum RequestType { GET, POST, PUT, DELETE } -String describeEnum(Object enumEntry) { - final description = enumEntry.toString(); - final indexOfDot = description.indexOf('.'); - assert(indexOfDot != -1 && indexOfDot < description.length - 1); - return description.substring(indexOfDot + 1); -} - class MatrixApi extends Api { /// The homeserver this client is communicating with. Uri? get homeserver => baseUri; @@ -164,203 +150,6 @@ class MatrixApi extends Api { return jsonResp!; } - /// The homeserver must check that the given email address is not already associated - /// with an account on this homeserver. The homeserver should validate the email - /// itself, either by sending a validation email itself or by using a service it - /// has control over. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-email-requesttoken - Future requestEmailToken( - String email, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/register/email/requestToken', - data: { - 'email': email, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// The homeserver must check that the given phone number is not already associated with an - /// account on this homeserver. The homeserver should validate the phone number itself, - /// either by sending a validation message itself or by using a service it has control over. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-msisdn-requesttoken - Future requestMsisdnToken( - String country, - String phoneNumber, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/register/msisdn/requestToken', - data: { - 'country': country, - 'phone_number': phoneNumber, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// The homeserver must check that the given email address is associated with - /// an account on this homeserver. This API should be used to request - /// validation tokens when authenticating for the /account/password endpoint. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-email-requesttoken - Future resetPasswordUsingEmail( - String email, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/password/email/requestToken', - data: { - 'email': email, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// The homeserver must check that the given phone number is associated with - /// an account on this homeserver. This API should be used to request validation - /// tokens when authenticating for the /account/password endpoint. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-msisdn-requesttoken - Future resetPasswordUsingMsisdn( - String country, - String phoneNumber, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/password/msisdn/requestToken', - data: { - 'country': country, - 'phone_number': phoneNumber, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// This API should be used to request validation tokens when adding an email address to an account. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-email-requesttoken - Future requestEmailValidationToken( - String email, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/3pid/email/requestToken', - data: { - 'email': email, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// This API should be used to request validation tokens when adding a phone number to an account. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-msisdn-requesttoken - Future requestMsisdnValidationToken( - String country, - String phoneNumber, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/3pid/msisdn/requestToken', - data: { - 'country': country, - 'phone_number': phoneNumber, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// Looks up the contents of a state event in a room. If the user is joined to the room then the - /// state is taken from the current state of the room. If the user has left the room then the - /// state is taken from the state of the room when they left. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey - Future> requestStateContent( - String roomId, String eventType, - [String? stateKey]) async { - var url = - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/'; - if (stateKey != null) { - url += Uri.encodeComponent(stateKey); - } - final response = await request( - RequestType.GET, - url, - ); - return response; - } - - /// Gets the visibility of a given room on the server's public room directory. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-list-room-roomid - Future getRoomVisibilityOnDirectory(String roomId) async { - final response = await request( - RequestType.GET, - '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', - ); - return Visibility.values - .firstWhere((v) => describeEnum(v) == response['visibility']); - } - - /// Sets the visibility of a given room in the server's public room directory. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-list-room-roomid - Future setRoomVisibilityOnDirectory( - String roomId, Visibility visibility) async { - await request( - RequestType.PUT, - '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', - data: { - 'visibility': describeEnum(visibility), - }, - ); - return; - } - /// Publishes end-to-end encryption keys for the device. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query Future> uploadKeys( @@ -382,26 +171,6 @@ class MatrixApi extends Api { return Map.from(response['one_time_key_counts']); } - /// Uploads your own cross-signing keys. - /// https://github.com/matrix-org/matrix-doc/pull/2536 - Future uploadDeviceSigningKeys({ - MatrixCrossSigningKey? masterKey, - MatrixCrossSigningKey? selfSigningKey, - MatrixCrossSigningKey? userSigningKey, - AuthenticationData? auth, - }) async { - await request( - RequestType.POST, - '/client/unstable/keys/device_signing/upload', - data: { - if (masterKey != null) 'master_key': masterKey.toJson(), - if (selfSigningKey != null) 'self_signing_key': selfSigningKey.toJson(), - if (userSigningKey != null) 'user_signing_key': userSigningKey.toJson(), - if (auth != null) 'auth': auth.toJson(), - }, - ); - } - /// Uploads new signatures of keys /// https://github.com/matrix-org/matrix-doc/pull/2536 Future uploadKeySignatures( @@ -449,174 +218,4 @@ class MatrixApi extends Api { ); return; } - - /// This will listen for new events related to a particular room and return them to the - /// caller. This will block until an event is received, or until the timeout is reached. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-events - Future getEvents({ - String? from, - int? timeout, - String? roomId, - }) async { - final response = - await request(RequestType.GET, '/client/r0/events', query: { - if (from != null) 'from': from, - if (timeout != null) 'timeout': timeout.toString(), - if (roomId != null) 'roomId': roomId, - }); - return EventsSyncUpdate.fromJson(response); - } - - /// Fetches the overall metadata about protocols supported by the homeserver. Includes - /// both the available protocols and all fields required for queries against each protocol. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocols - Future> requestSupportedProtocols() async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/protocols', - ); - return response.map((k, v) => MapEntry(k, SupportedProtocol.fromJson(v))); - } - - /// Fetches the metadata from the homeserver about a particular third party protocol. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocol-protocol - Future requestSupportedProtocol(String protocol) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/protocol/${Uri.encodeComponent(protocol)}', - ); - return SupportedProtocol.fromJson(response); - } - - /// Requesting this endpoint with a valid protocol name results in a list of successful - /// mapping results in a JSON array. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-location-protocol - Future> requestThirdPartyLocations( - String protocol) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/location/${Uri.encodeComponent(protocol)}', - ); - return (response['chunk'] as List) - .map((i) => ThirdPartyLocation.fromJson(i)) - .toList(); - } - - /// Retrieve a Matrix User ID linked to a user on the third party service, given a set of - /// user parameters. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user-protocol - Future> requestThirdPartyUsers(String protocol) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/user/${Uri.encodeComponent(protocol)}', - ); - return (response['chunk'] as List) - .map((i) => ThirdPartyUser.fromJson(i)) - .toList(); - } - - /// Retrieve an array of third party network locations from a Matrix room alias. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-location - Future> requestThirdPartyLocationsByAlias( - String alias) async { - final response = await request( - RequestType.GET, '/client/r0/thirdparty/location', - query: { - 'alias': alias, - }); - return (response['chunk'] as List) - .map((i) => ThirdPartyLocation.fromJson(i)) - .toList(); - } - - /// Retrieve an array of third party users from a Matrix User ID. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user - Future> requestThirdPartyUsersByUserId( - String userId) async { - final response = - await request(RequestType.GET, '/client/r0/thirdparty/user', query: { - 'userid': userId, - }); - return (response['chunk'] as List) - .map((i) => ThirdPartyUser.fromJson(i)) - .toList(); - } - - /// Deletes a room key backup - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-version-version - Future deleteRoomKeysBackup(String version) async { - await request( - RequestType.DELETE, - '/client/unstable/room_keys/version/${Uri.encodeComponent(version)}', - ); - } - - /// Gets a single room key - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid-sessionid - Future getRoomKeysSingleKey( - String roomId, String sessionId, String version) async { - final ret = await request( - RequestType.GET, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', - query: {'version': version}, - ); - return RoomKeysSingleKey.fromJson(ret); - } - - /// Deletes a single room key - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys-roomid-sessionid - Future deleteRoomKeysSingleKey( - String roomId, String sessionId, String version) async { - final ret = await request( - RequestType.DELETE, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', - query: {'version': version}, - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - - /// Gets room keys for a room - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid - Future getRoomKeysRoom(String roomId, String version) async { - final ret = await request( - RequestType.GET, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', - query: {'version': version}, - ); - return RoomKeysRoom.fromJson(ret); - } - - /// Deletes room keys for a room - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys-roomid - Future deleteRoomKeysRoom( - String roomId, String version) async { - final ret = await request( - RequestType.DELETE, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', - query: {'version': version}, - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - - /// get all room keys - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys - Future getRoomKeys(String version) async { - final ret = await request( - RequestType.GET, - '/client/unstable/room_keys/keys', - query: {'version': version}, - ); - return RoomKeys.fromJson(ret); - } - - /// delete all room keys - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys - Future deleteRoomKeys(String version) async { - final ret = await request( - RequestType.DELETE, - '/client/unstable/room_keys/keys', - query: {'version': version}, - ); - return RoomKeysUpdateResponse.fromJson(ret); - } } diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart deleted file mode 100644 index 2f35ac74..00000000 --- a/lib/src/model/events_sync_update.dart +++ /dev/null @@ -1,53 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -import 'matrix_event.dart'; - -class EventsSyncUpdate { - String? start; - String? end; - List? chunk; - - EventsSyncUpdate.fromJson(Map json) - : start = json['start'], - end = json['end'], - chunk = json['chunk'] != null - ? (json['chunk'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList() - : null; - - Map toJson() { - final data = {}; - if (start != null) { - data['start'] = start; - } - if (end != null) { - data['end'] = end; - } - if (chunk != null) { - data['chunk'] = chunk!.map((i) => i.toJson()).toList(); - } - return data; - } -} diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart deleted file mode 100644 index 4be5d726..00000000 --- a/lib/src/model/request_token_response.dart +++ /dev/null @@ -1,38 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -class RequestTokenResponse { - String sid; - String? submitUrl; - - RequestTokenResponse.fromJson(Map json) - : sid = json['sid'], - submitUrl = json['submit_url']; - - Map toJson() { - final data = {}; - data['sid'] = sid; - data['submit_url'] = submitUrl; - return data; - } -} diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart deleted file mode 100644 index 0f1fcf50..00000000 --- a/lib/src/model/supported_protocol.dart +++ /dev/null @@ -1,91 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -class SupportedProtocol { - List userFields; - List locationFields; - String icon; - Map fieldTypes; - List instances; - - SupportedProtocol.fromJson(Map json) - : userFields = json['user_fields'].cast(), - locationFields = json['location_fields'].cast(), - icon = json['icon'], - fieldTypes = (json['field_types'] as Map) - .map((k, v) => MapEntry(k, ProtocolFieldType.fromJson(v))), - instances = (json['instances'] as List) - .map((v) => ProtocolInstance.fromJson(v)) - .toList(); - - Map toJson() { - final data = {}; - data['user_fields'] = userFields; - data['location_fields'] = locationFields; - data['icon'] = icon; - data['field_types'] = fieldTypes.map((k, v) => MapEntry(k, v.toJson())); - data['instances'] = instances.map((v) => v.toJson()).toList(); - return data; - } -} - -class ProtocolFieldType { - String regexp; - String placeholder; - - ProtocolFieldType.fromJson(Map json) - : regexp = json['regexp'], - placeholder = json['placeholder']; - - Map toJson() { - final data = {}; - data['regexp'] = regexp; - data['placeholder'] = placeholder; - return data; - } -} - -class ProtocolInstance { - String networkId; - String desc; - String? icon; - dynamic fields; - - ProtocolInstance.fromJson(Map json) - : networkId = json['network_id'], - desc = json['desc'], - icon = json['icon'], - fields = json['fields']; - - Map toJson() { - final data = {}; - data['network_id'] = networkId; - data['desc'] = desc; - if (icon != null) { - data['icon'] = icon; - } - data['fields'] = fields; - - return data; - } -} diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart deleted file mode 100644 index a2271f9b..00000000 --- a/lib/src/model/third_party_location.dart +++ /dev/null @@ -1,43 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -import '../utils/map_copy_extension.dart'; - -class ThirdPartyLocation { - String alias; - String protocol; - Map fields; - - ThirdPartyLocation.fromJson(Map json) - : alias = json['alias'], - protocol = json['protocol'], - fields = (json['fields'] as Map).copy(); - - Map toJson() { - final data = {}; - data['alias'] = alias; - data['protocol'] = protocol; - data['fields'] = fields; - return data; - } -} diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart deleted file mode 100644 index a4289b2a..00000000 --- a/lib/src/model/third_party_user.dart +++ /dev/null @@ -1,43 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -import '../utils/map_copy_extension.dart'; - -class ThirdPartyUser { - String userId; - String protocol; - Map fields; - - ThirdPartyUser.fromJson(Map json) - : userId = json['userid'], - protocol = json['protocol'], - fields = (json['fields'] as Map).copy(); - - Map toJson() { - final data = {}; - data['userid'] = userId; - data['protocol'] = protocol; - data['fields'] = fields; - return data; - } -} diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 15050e2c..d5fecb78 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -180,10 +180,10 @@ void main() { registerResponse.toJson()); matrixApi.homeserver = null; }); - test('requestEmailToken', () async { + test('requestTokenToRegisterEmail', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestEmailToken( + final response = await matrixApi.requestTokenToRegisterEmail( 'alice@example.com', '1234', 1, @@ -197,10 +197,10 @@ void main() { response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMsisdnToken', () async { + test('requestTokenToRegisterMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestMsisdnToken( + final response = await matrixApi.requestTokenToRegisterMSISDN( 'en', '1234', '1234', @@ -228,10 +228,10 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('resetPasswordUsingEmail', () async { + test('requestTokenToResetPasswordEmail', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.resetPasswordUsingEmail( + await matrixApi.requestTokenToResetPasswordEmail( 'alice@example.com', '1234', 1, @@ -241,10 +241,10 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('resetPasswordUsingMsisdn', () async { + test('requestTokenToResetPasswordMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.resetPasswordUsingMsisdn( + await matrixApi.requestTokenToResetPasswordMSISDN( 'en', '1234', '1234', @@ -324,10 +324,10 @@ void main() { expect(response, IdServerUnbindResult.success); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestEmailValidationToken', () async { + test('requestTokenTo3PIDEmail', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestEmailValidationToken( + await matrixApi.requestTokenTo3PIDEmail( 'alice@example.com', '1234', 1, @@ -337,10 +337,10 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMsisdnValidationToken', () async { + test('requestTokenTo3PIDMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestMsisdnValidationToken( + await matrixApi.requestTokenTo3PIDMSISDN( 'en', '1234', '1234', @@ -351,7 +351,7 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMsisdnValidationToken', () async { + test('requestTokenTo3PIDMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getTokenOwner(); @@ -511,11 +511,11 @@ void main() { expect(event.eventId, '143273582443PhrSn:example.org'); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestStateContent', () async { + test('getRoomStateWithKey', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestStateContent( + await matrixApi.getRoomStateWithKey( '!localpart:server.abc', 'm.room.member', '@getme:example.com', @@ -811,8 +811,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setRoomVisibilityOnDirectory( - '!localpart:example.com', Visibility.private); + await matrixApi.setRoomVisibilityOnDirectory('!localpart:example.com', + visibility: Visibility.private); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1151,7 +1151,7 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('uploadDeviceSigningKeys', () async { + test('uploadCrossSigningKeys', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1182,7 +1182,7 @@ void main() { }, 'signatures': {}, }); - await matrixApi.uploadDeviceSigningKeys( + await matrixApi.uploadCrossSigningKeys( masterKey: masterKey, selfSigningKey: selfSigningKey, userSigningKey: userSigningKey); @@ -1400,11 +1400,11 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = - await matrixApi.getEvents(from: '1234', roomId: '!1234', timeout: 10); + final response = await matrixApi.peekEvents( + from: '1234', roomId: '!1234', timeout: 10); expect( FakeMatrixApi.api['GET']![ - '/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), + '/client/r0/events?from=1234&timeout=10&room_id=%211234']({}), response.toJson(), ); @@ -1537,11 +1537,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestSupportedProtocols', () async { + test('getProtocols', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestSupportedProtocols(); + final response = await matrixApi.getProtocols(); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocols']({}), response.map((k, v) => MapEntry(k, v.toJson())), @@ -1549,11 +1549,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestSupportedProtocol', () async { + test('getProtocol', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestSupportedProtocol('irc'); + final response = await matrixApi.getProtocolMetadata('irc'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocol/irc']({}), response.toJson(), @@ -1561,11 +1561,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyLocations', () async { + test('queryLocationByProtocol', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyLocations('irc'); + final response = await matrixApi.queryLocationByProtocol('irc'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/location/irc']({}), response.map((i) => i.toJson()).toList(), @@ -1573,11 +1573,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyUsers', () async { + test('queryUserByProtocol', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyUsers('irc'); + final response = await matrixApi.queryUserByProtocol('irc'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user/irc']({}), response.map((i) => i.toJson()).toList(), @@ -1585,12 +1585,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyLocationsByAlias', () async { + test('queryLocationByAlias', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = - await matrixApi.requestThirdPartyLocationsByAlias('1234'); + final response = await matrixApi.queryLocationByAlias('1234'); expect( FakeMatrixApi .api['GET']!['/client/r0/thirdparty/location?alias=1234']({}), @@ -1599,11 +1598,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyUsersByUserId', () async { + test('queryUserByID', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyUsersByUserId('1234'); + final response = await matrixApi.queryUserByID('1234'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user?userid=1234']({}), response.map((i) => i.toJson()).toList(), @@ -1667,13 +1666,13 @@ void main() { }; await matrixApi.putRoomKeysVersion('5', algorithm, authData); }); - test('deleteRoomKeysBackup', () async { + test('deleteRoomKeys', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.deleteRoomKeysBackup('5'); + await matrixApi.deleteRoomKeys('5'); }); - test('postRoomKeysKeyRoomIdSessionId', () async { + test('putRoomKeysBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1690,39 +1689,40 @@ void main() { 'mac': 'QzKV/fgAs4U', }, }); - final ret = await matrixApi.postRoomKeysKeyRoomIdSessionId( + final ret = await matrixApi.putRoomKeysBySessionId( roomId, sessionId, '5', session); expect( FakeMatrixApi.api['PUT']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('getRoomKeysSingleKey', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final ret = await matrixApi.getRoomKeysSingleKey(roomId, sessionId, '5'); - expect( - FakeMatrixApi.api['GET']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), - ret.toJson()); - }); - test('deleteRoomKeysSingleKey', () async { + test('getRoomKeysBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; final ret = - await matrixApi.deleteRoomKeysSingleKey(roomId, sessionId, '5'); + await matrixApi.getRoomKeysBySessionId(roomId, sessionId, '5'); + expect( + FakeMatrixApi.api['GET']![ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + ret.toJson()); + }); + test('deleteRoomKeysBySessionId', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final ret = + await matrixApi.deleteRoomKeysBySessionId(roomId, sessionId, '5'); expect( FakeMatrixApi.api['DELETE']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('postRoomKeysKeyRoomId', () async { + test('putRoomKeysByRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1743,35 +1743,35 @@ void main() { }, }, }); - final ret = await matrixApi.postRoomKeysKeyRoomId(roomId, '5', session); + final ret = await matrixApi.putRoomKeysByRoomId(roomId, '5', session); expect( FakeMatrixApi.api['PUT']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('getRoomKeysRoom', () async { + test('getRoomKeysByRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; - final ret = await matrixApi.getRoomKeysRoom(roomId, '5'); + final ret = await matrixApi.getRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['GET']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('deleteRoomKeysRoom', () async { + test('deleteRoomKeysByRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; - final ret = await matrixApi.deleteRoomKeysRoom(roomId, '5'); + final ret = await matrixApi.deleteRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['DELETE']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('postRoomKeysKey', () async { + test('putRoomKeys', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1796,7 +1796,7 @@ void main() { }, }, }); - final ret = await matrixApi.postRoomKeysKey('5', session); + final ret = await matrixApi.putRoomKeys('5', session); expect( FakeMatrixApi .api['PUT']!['/client/unstable/room_keys/keys?version=5']({}),