diff options
Diffstat (limited to 'lib/csapi')
83 files changed, 1406 insertions, 567 deletions
diff --git a/lib/csapi/account-data.cpp b/lib/csapi/account-data.cpp index 09fc8d40..8c71f6c5 100644 --- a/lib/csapi/account-data.cpp +++ b/lib/csapi/account-data.cpp @@ -9,23 +9,23 @@ using namespace Quotient; SetAccountDataJob::SetAccountDataJob(const QString& userId, const QString& type, const QJsonObject& content) : BaseJob(HttpVerb::Put, QStringLiteral("SetAccountDataJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/account_data/", + makePath("/_matrix/client/v3", "/user/", userId, "/account_data/", type)) { - setRequestData(RequestData(toJson(content))); + setRequestData({ toJson(content) }); } QUrl GetAccountDataJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& type) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/user/", + makePath("/_matrix/client/v3", "/user/", userId, "/account_data/", type)); } GetAccountDataJob::GetAccountDataJob(const QString& userId, const QString& type) : BaseJob(HttpVerb::Get, QStringLiteral("GetAccountDataJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/account_data/", + makePath("/_matrix/client/v3", "/user/", userId, "/account_data/", type)) {} @@ -34,10 +34,10 @@ SetAccountDataPerRoomJob::SetAccountDataPerRoomJob(const QString& userId, const QString& type, const QJsonObject& content) : BaseJob(HttpVerb::Put, QStringLiteral("SetAccountDataPerRoomJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/account_data/", type)) { - setRequestData(RequestData(toJson(content))); + setRequestData({ toJson(content) }); } QUrl GetAccountDataPerRoomJob::makeRequestUrl(QUrl baseUrl, @@ -46,7 +46,7 @@ QUrl GetAccountDataPerRoomJob::makeRequestUrl(QUrl baseUrl, const QString& type) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/user/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/account_data/", type)); } @@ -55,6 +55,6 @@ GetAccountDataPerRoomJob::GetAccountDataPerRoomJob(const QString& userId, const QString& roomId, const QString& type) : BaseJob(HttpVerb::Get, QStringLiteral("GetAccountDataPerRoomJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/account_data/", type)) {} diff --git a/lib/csapi/admin.cpp b/lib/csapi/admin.cpp index 81dd0624..322212db 100644 --- a/lib/csapi/admin.cpp +++ b/lib/csapi/admin.cpp @@ -9,11 +9,11 @@ using namespace Quotient; QUrl GetWhoIsJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/admin/whois/", userId)); } GetWhoIsJob::GetWhoIsJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetWhoIsJob"), - makePath("/_matrix/client/r0", "/admin/whois/", userId)) + makePath("/_matrix/client/v3", "/admin/whois/", userId)) {} diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index 589c9fc1..aa55d934 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -9,59 +9,59 @@ using namespace Quotient; QUrl GetAccount3PIDsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/account/3pid")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/account/3pid")); } GetAccount3PIDsJob::GetAccount3PIDsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetAccount3PIDsJob"), - makePath("/_matrix/client/r0", "/account/3pid")) + makePath("/_matrix/client/v3", "/account/3pid")) {} Post3PIDsJob::Post3PIDsJob(const ThreePidCredentials& threePidCreds) : BaseJob(HttpVerb::Post, QStringLiteral("Post3PIDsJob"), - makePath("/_matrix/client/r0", "/account/3pid")) + makePath("/_matrix/client/v3", "/account/3pid")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("three_pid_creds"), threePidCreds); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("three_pid_creds"), threePidCreds); + setRequestData({ _dataJson }); } Add3PIDJob::Add3PIDJob(const QString& clientSecret, const QString& sid, const Omittable<AuthenticationData>& auth) : BaseJob(HttpVerb::Post, QStringLiteral("Add3PIDJob"), - makePath("/_matrix/client/r0", "/account/3pid/add")) + makePath("/_matrix/client/v3", "/account/3pid/add")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth); - addParam<>(_data, QStringLiteral("client_secret"), clientSecret); - addParam<>(_data, QStringLiteral("sid"), sid); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + addParam<>(_dataJson, QStringLiteral("client_secret"), clientSecret); + addParam<>(_dataJson, QStringLiteral("sid"), sid); + setRequestData({ _dataJson }); } Bind3PIDJob::Bind3PIDJob(const QString& clientSecret, const QString& idServer, const QString& idAccessToken, const QString& sid) : BaseJob(HttpVerb::Post, QStringLiteral("Bind3PIDJob"), - makePath("/_matrix/client/r0", "/account/3pid/bind")) + makePath("/_matrix/client/v3", "/account/3pid/bind")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("client_secret"), clientSecret); - addParam<>(_data, QStringLiteral("id_server"), idServer); - addParam<>(_data, QStringLiteral("id_access_token"), idAccessToken); - addParam<>(_data, QStringLiteral("sid"), sid); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("client_secret"), clientSecret); + addParam<>(_dataJson, QStringLiteral("id_server"), idServer); + addParam<>(_dataJson, QStringLiteral("id_access_token"), idAccessToken); + addParam<>(_dataJson, QStringLiteral("sid"), sid); + setRequestData({ _dataJson }); } Delete3pidFromAccountJob::Delete3pidFromAccountJob(const QString& medium, const QString& address, const QString& idServer) : BaseJob(HttpVerb::Post, QStringLiteral("Delete3pidFromAccountJob"), - makePath("/_matrix/client/r0", "/account/3pid/delete")) + makePath("/_matrix/client/v3", "/account/3pid/delete")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("id_server"), idServer); - addParam<>(_data, QStringLiteral("medium"), medium); - addParam<>(_data, QStringLiteral("address"), address); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("id_server"), idServer); + addParam<>(_dataJson, QStringLiteral("medium"), medium); + addParam<>(_dataJson, QStringLiteral("address"), address); + setRequestData({ _dataJson }); addExpectedKey("id_server_unbind_result"); } @@ -69,32 +69,32 @@ Unbind3pidFromAccountJob::Unbind3pidFromAccountJob(const QString& medium, const QString& address, const QString& idServer) : BaseJob(HttpVerb::Post, QStringLiteral("Unbind3pidFromAccountJob"), - makePath("/_matrix/client/r0", "/account/3pid/unbind")) + makePath("/_matrix/client/v3", "/account/3pid/unbind")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("id_server"), idServer); - addParam<>(_data, QStringLiteral("medium"), medium); - addParam<>(_data, QStringLiteral("address"), address); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("id_server"), idServer); + addParam<>(_dataJson, QStringLiteral("medium"), medium); + addParam<>(_dataJson, QStringLiteral("address"), address); + setRequestData({ _dataJson }); addExpectedKey("id_server_unbind_result"); } RequestTokenTo3PIDEmailJob::RequestTokenTo3PIDEmailJob( const EmailValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenTo3PIDEmailJob"), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/account/3pid/email/requestToken"), false) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } RequestTokenTo3PIDMSISDNJob::RequestTokenTo3PIDMSISDNJob( const MsisdnValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenTo3PIDMSISDNJob"), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/account/3pid/msisdn/requestToken"), false) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } diff --git a/lib/csapi/administrative_contact.h b/lib/csapi/administrative_contact.h index e636b12a..27334850 100644 --- a/lib/csapi/administrative_contact.h +++ b/lib/csapi/administrative_contact.h @@ -128,6 +128,22 @@ public: * The third party credentials to associate with the account. */ explicit Post3PIDsJob(const ThreePidCredentials& threePidCreds); + + // Result properties + + /// 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). + QUrl submitUrl() const { return loadFromJson<QUrl>("submit_url"_ls); } }; template <> @@ -235,7 +251,7 @@ public: /// An indicator as to whether or not the homeserver was able to unbind /// the 3PID from the identity server. `success` indicates that the - /// indentity server has unbound the identifier whereas `no-support` + /// identity server has unbound the identifier whereas `no-support` /// indicates that the identity server refuses to support the request /// or the homeserver was not able to determine an identity server to /// unbind from. @@ -295,7 +311,7 @@ public: * 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`](/client-server-api/#post_matrixclientr0registeremailrequesttoken) + * [`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken) * endpoint. The homeserver should validate * the email itself, either by sending a validation email itself or by using * a service it has control over. @@ -311,7 +327,7 @@ public: * 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`](/client-server-api/#post_matrixclientr0registeremailrequesttoken) + * [`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken) * endpoint. The homeserver should validate * the email itself, either by sending a validation email itself or by * using a service it has control over. @@ -337,7 +353,7 @@ public: * 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`](/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + * [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) * 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. @@ -353,7 +369,7 @@ public: * 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`](/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + * [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) * 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. diff --git a/lib/csapi/appservice_room_directory.cpp b/lib/csapi/appservice_room_directory.cpp index 40d784c6..dff7e032 100644 --- a/lib/csapi/appservice_room_directory.cpp +++ b/lib/csapi/appservice_room_directory.cpp @@ -6,14 +6,16 @@ using namespace Quotient; -UpdateAppserviceRoomDirectoryVisibilityJob::UpdateAppserviceRoomDirectoryVisibilityJob( - const QString& networkId, const QString& roomId, const QString& visibility) +UpdateAppserviceRoomDirectoryVisibilityJob:: + UpdateAppserviceRoomDirectoryVisibilityJob(const QString& networkId, + const QString& roomId, + const QString& visibility) : BaseJob(HttpVerb::Put, QStringLiteral("UpdateAppserviceRoomDirectoryVisibilityJob"), - makePath("/_matrix/client/r0", "/directory/list/appservice/", + makePath("/_matrix/client/v3", "/directory/list/appservice/", networkId, "/", roomId)) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("visibility"), visibility); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("visibility"), visibility); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/appservice_room_directory.h b/lib/csapi/appservice_room_directory.h index 6b2801ca..d6268979 100644 --- a/lib/csapi/appservice_room_directory.h +++ b/lib/csapi/appservice_room_directory.h @@ -21,8 +21,7 @@ namespace Quotient { * instead of a typical client's access_token. This API cannot be invoked by * users who are not identified as application services. */ -class QUOTIENT_API UpdateAppserviceRoomDirectoryVisibilityJob - : public BaseJob { +class QUOTIENT_API UpdateAppserviceRoomDirectoryVisibilityJob : public BaseJob { public: /*! \brief Updates a room's visibility in the application service's room * directory. diff --git a/lib/csapi/banning.cpp b/lib/csapi/banning.cpp index 472128bb..e04075b7 100644 --- a/lib/csapi/banning.cpp +++ b/lib/csapi/banning.cpp @@ -9,21 +9,21 @@ using namespace Quotient; BanJob::BanJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("BanJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/ban")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/ban")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("user_id"), userId); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("user_id"), userId); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } UnbanJob::UnbanJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("UnbanJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/unban")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/unban")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("user_id"), userId); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("user_id"), userId); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/capabilities.cpp b/lib/csapi/capabilities.cpp index bc21e462..ca2a543f 100644 --- a/lib/csapi/capabilities.cpp +++ b/lib/csapi/capabilities.cpp @@ -9,12 +9,12 @@ using namespace Quotient; QUrl GetCapabilitiesJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/capabilities")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/capabilities")); } GetCapabilitiesJob::GetCapabilitiesJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetCapabilitiesJob"), - makePath("/_matrix/client/r0", "/capabilities")) + makePath("/_matrix/client/v3", "/capabilities")) { addExpectedKey("capabilities"); } diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index 6d1e38b6..6f6738af 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -16,11 +16,11 @@ auto queryToUploadContent(const QString& filename) UploadContentJob::UploadContentJob(QIODevice* content, const QString& filename, const QString& contentType) : BaseJob(HttpVerb::Post, QStringLiteral("UploadContentJob"), - makePath("/_matrix/media/r0", "/upload"), + makePath("/_matrix/media/v3", "/upload"), queryToUploadContent(filename)) { setRequestHeader("Content-Type", contentType.toLatin1()); - setRequestData(RequestData(content)); + setRequestData({ content }); addExpectedKey("content_uri"); } @@ -35,7 +35,7 @@ QUrl GetContentJob::makeRequestUrl(QUrl baseUrl, const QString& serverName, const QString& mediaId, bool allowRemote) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/media/r0", "/download/", + makePath("/_matrix/media/v3", "/download/", serverName, "/", mediaId), queryToGetContent(allowRemote)); } @@ -43,7 +43,7 @@ QUrl GetContentJob::makeRequestUrl(QUrl baseUrl, const QString& serverName, GetContentJob::GetContentJob(const QString& serverName, const QString& mediaId, bool allowRemote) : BaseJob(HttpVerb::Get, QStringLiteral("GetContentJob"), - makePath("/_matrix/media/r0", "/download/", serverName, "/", + makePath("/_matrix/media/v3", "/download/", serverName, "/", mediaId), queryToGetContent(allowRemote), {}, false) { @@ -64,7 +64,7 @@ QUrl GetContentOverrideNameJob::makeRequestUrl(QUrl baseUrl, bool allowRemote) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/media/r0", "/download/", + makePath("/_matrix/media/v3", "/download/", serverName, "/", mediaId, "/", fileName), queryToGetContentOverrideName(allowRemote)); @@ -75,7 +75,7 @@ GetContentOverrideNameJob::GetContentOverrideNameJob(const QString& serverName, const QString& fileName, bool allowRemote) : BaseJob(HttpVerb::Get, QStringLiteral("GetContentOverrideNameJob"), - makePath("/_matrix/media/r0", "/download/", serverName, "/", + makePath("/_matrix/media/v3", "/download/", serverName, "/", mediaId, "/", fileName), queryToGetContentOverrideName(allowRemote), {}, false) { @@ -101,16 +101,17 @@ QUrl GetContentThumbnailJob::makeRequestUrl(QUrl baseUrl, { return BaseJob::makeRequestUrl( std::move(baseUrl), - makePath("/_matrix/media/r0", "/thumbnail/", serverName, "/", mediaId), + makePath("/_matrix/media/v3", "/thumbnail/", serverName, "/", mediaId), queryToGetContentThumbnail(width, height, method, allowRemote)); } GetContentThumbnailJob::GetContentThumbnailJob(const QString& serverName, - const QString& mediaId, int width, - int height, const QString& method, + const QString& mediaId, + int width, int height, + const QString& method, bool allowRemote) : BaseJob(HttpVerb::Get, QStringLiteral("GetContentThumbnailJob"), - makePath("/_matrix/media/r0", "/thumbnail/", serverName, "/", + makePath("/_matrix/media/v3", "/thumbnail/", serverName, "/", mediaId), queryToGetContentThumbnail(width, height, method, allowRemote), {}, false) @@ -130,24 +131,24 @@ QUrl GetUrlPreviewJob::makeRequestUrl(QUrl baseUrl, const QUrl& url, Omittable<qint64> ts) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/media/r0", + makePath("/_matrix/media/v3", "/preview_url"), queryToGetUrlPreview(url, ts)); } GetUrlPreviewJob::GetUrlPreviewJob(const QUrl& url, Omittable<qint64> ts) : BaseJob(HttpVerb::Get, QStringLiteral("GetUrlPreviewJob"), - makePath("/_matrix/media/r0", "/preview_url"), + makePath("/_matrix/media/v3", "/preview_url"), queryToGetUrlPreview(url, ts)) {} QUrl GetConfigJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/media/r0", "/config")); + makePath("/_matrix/media/v3", "/config")); } GetConfigJob::GetConfigJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetConfigJob"), - makePath("/_matrix/media/r0", "/config")) + makePath("/_matrix/media/v3", "/config")) {} diff --git a/lib/csapi/content-repo.h b/lib/csapi/content-repo.h index 511db985..2ba66a35 100644 --- a/lib/csapi/content-repo.h +++ b/lib/csapi/content-repo.h @@ -162,7 +162,8 @@ public: * * \param method * The desired resizing method. See the - * [Thumbnails](/client-server-api/#thumbnails) section for more information. + * [Thumbnails](/client-server-api/#thumbnails) section for more + * information. * * \param allowRemote * Indicates to the server that it should not attempt to fetch diff --git a/lib/csapi/create_room.cpp b/lib/csapi/create_room.cpp index 9aaef87f..afae80af 100644 --- a/lib/csapi/create_room.cpp +++ b/lib/csapi/create_room.cpp @@ -16,24 +16,26 @@ CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& preset, Omittable<bool> isDirect, const QJsonObject& powerLevelContentOverride) : BaseJob(HttpVerb::Post, QStringLiteral("CreateRoomJob"), - makePath("/_matrix/client/r0", "/createRoom")) + makePath("/_matrix/client/v3", "/createRoom")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("visibility"), visibility); - addParam<IfNotEmpty>(_data, QStringLiteral("room_alias_name"), + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("visibility"), visibility); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("room_alias_name"), roomAliasName); - addParam<IfNotEmpty>(_data, QStringLiteral("name"), name); - addParam<IfNotEmpty>(_data, QStringLiteral("topic"), topic); - addParam<IfNotEmpty>(_data, QStringLiteral("invite"), invite); - addParam<IfNotEmpty>(_data, QStringLiteral("invite_3pid"), invite3pid); - addParam<IfNotEmpty>(_data, QStringLiteral("room_version"), roomVersion); - addParam<IfNotEmpty>(_data, QStringLiteral("creation_content"), + addParam<IfNotEmpty>(_dataJson, QStringLiteral("name"), name); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("topic"), topic); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("invite"), invite); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("invite_3pid"), invite3pid); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("room_version"), roomVersion); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("creation_content"), creationContent); - addParam<IfNotEmpty>(_data, QStringLiteral("initial_state"), initialState); - addParam<IfNotEmpty>(_data, QStringLiteral("preset"), preset); - addParam<IfNotEmpty>(_data, QStringLiteral("is_direct"), isDirect); - addParam<IfNotEmpty>(_data, QStringLiteral("power_level_content_override"), + addParam<IfNotEmpty>(_dataJson, QStringLiteral("initial_state"), + initialState); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("preset"), preset); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("is_direct"), isDirect); + addParam<IfNotEmpty>(_dataJson, + QStringLiteral("power_level_content_override"), powerLevelContentOverride); - setRequestData(std::move(_data)); + setRequestData({ _dataJson }); addExpectedKey("room_id"); } diff --git a/lib/csapi/create_room.h b/lib/csapi/create_room.h index 7d566057..336b9767 100644 --- a/lib/csapi/create_room.h +++ b/lib/csapi/create_room.h @@ -26,16 +26,18 @@ namespace Quotient { * (and not other members) permission to send state events. Overridden * by the `power_level_content_override` parameter. * - * 4. Events set by the `preset`. Currently these are the `m.room.join_rules`, + * 4. An `m.room.canonical_alias` event if `room_alias_name` is given. + * + * 5. Events set by the `preset`. Currently these are the `m.room.join_rules`, * `m.room.history_visibility`, and `m.room.guest_access` state events. * - * 5. Events listed in `initial_state`, in the order that they are + * 6. Events listed in `initial_state`, in the order that they are * listed. * - * 6. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` + * 7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` * state events). * - * 7. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with + * 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with * `membership: invite` and `m.room.third_party_invite`). * * The available presets do the following with respect to room state: @@ -73,17 +75,20 @@ public: /// (and not other members) permission to send state events. Overridden /// by the `power_level_content_override` parameter. /// - /// 4. Events set by the `preset`. Currently these are the + /// 4. An `m.room.canonical_alias` event if `room_alias_name` is given. + /// + /// 5. Events set by the `preset`. Currently these are the /// `m.room.join_rules`, /// `m.room.history_visibility`, and `m.room.guest_access` state events. /// - /// 5. Events listed in `initial_state`, in the order that they are + /// 6. Events listed in `initial_state`, in the order that they are /// listed. /// - /// 6. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` + /// 7. Events implied by `name` and `topic` (`m.room.name` and + /// `m.room.topic` /// state events). /// - /// 7. Invite events implied by `invite` and `invite_3pid` (`m.room.member` + /// 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` /// with /// `membership: invite` and `m.room.third_party_invite`). /// @@ -132,17 +137,20 @@ public: /// (and not other members) permission to send state events. Overridden /// by the `power_level_content_override` parameter. /// - /// 4. Events set by the `preset`. Currently these are the + /// 4. An `m.room.canonical_alias` event if `room_alias_name` is given. + /// + /// 5. Events set by the `preset`. Currently these are the /// `m.room.join_rules`, /// `m.room.history_visibility`, and `m.room.guest_access` state events. /// - /// 5. Events listed in `initial_state`, in the order that they are + /// 6. Events listed in `initial_state`, in the order that they are /// listed. /// - /// 6. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` + /// 7. Events implied by `name` and `topic` (`m.room.name` and + /// `m.room.topic` /// state events). /// - /// 7. Invite events implied by `invite` and `invite_3pid` (`m.room.member` + /// 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` /// with /// `membership: invite` and `m.room.third_party_invite`). /// @@ -190,7 +198,8 @@ public: * would be `#foo:example.com`. * * The complete room alias will become the canonical alias for - * the room. + * the room and an `m.room.canonical_alias` event will be sent + * into the room. * * \param name * If this is included, an `m.room.name` event will be sent @@ -218,9 +227,10 @@ public: * * \param creationContent * Extra keys, such as `m.federate`, to be added to the content - * of the [`m.room.create`](client-server-api/#mroomcreate) event. The - * server will clobber the following keys: `creator`, `room_version`. Future - * versions of the specification may allow the server to clobber other keys. + * of the [`m.room.create`](/client-server-api/#mroomcreate) event. The + * server will overwrite the following keys: `creator`, `room_version`. + * Future versions of the specification may allow the server to overwrite + * other keys. * * \param initialState * A list of state events to set in the new room. This allows @@ -229,7 +239,7 @@ public: * with type, state_key and content keys set. * * Takes precedence over events set by `preset`, but gets - * overriden by `name` and `topic` keys. + * overridden by `name` and `topic` keys. * * \param preset * Convenience parameter for setting various default state events @@ -249,7 +259,7 @@ public: * \param powerLevelContentOverride * The power level content to override in the default power level * event. This object is applied on top of the generated - * [`m.room.power_levels`](client-server-api/#mroompower_levels) + * [`m.room.power_levels`](/client-server-api/#mroompower_levels) * event content prior to it being sent to the room. Defaults to * overriding nothing. */ diff --git a/lib/csapi/cross_signing.cpp b/lib/csapi/cross_signing.cpp index 1fa0e949..83136d71 100644 --- a/lib/csapi/cross_signing.cpp +++ b/lib/csapi/cross_signing.cpp @@ -9,23 +9,25 @@ using namespace Quotient; UploadCrossSigningKeysJob::UploadCrossSigningKeysJob( const Omittable<CrossSigningKey>& masterKey, const Omittable<CrossSigningKey>& selfSigningKey, - const Omittable<CrossSigningKey>& userSigningKey) + const Omittable<CrossSigningKey>& userSigningKey, + const Omittable<AuthenticationData>& auth) : BaseJob(HttpVerb::Post, QStringLiteral("UploadCrossSigningKeysJob"), - makePath("/_matrix/client/r0", "/keys/device_signing/upload")) + makePath("/_matrix/client/v3", "/keys/device_signing/upload")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("master_key"), masterKey); - addParam<IfNotEmpty>(_data, QStringLiteral("self_signing_key"), + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("master_key"), masterKey); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("self_signing_key"), selfSigningKey); - addParam<IfNotEmpty>(_data, QStringLiteral("user_signing_key"), + addParam<IfNotEmpty>(_dataJson, QStringLiteral("user_signing_key"), userSigningKey); - setRequestData(std::move(_data)); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + setRequestData({ _dataJson }); } UploadCrossSigningSignaturesJob::UploadCrossSigningSignaturesJob( const QHash<QString, QHash<QString, QJsonObject>>& signatures) : BaseJob(HttpVerb::Post, QStringLiteral("UploadCrossSigningSignaturesJob"), - makePath("/_matrix/client/r0", "/keys/signatures/upload")) + makePath("/_matrix/client/v3", "/keys/signatures/upload")) { - setRequestData(RequestData(toJson(signatures))); + setRequestData({ toJson(signatures) }); } diff --git a/lib/csapi/cross_signing.h b/lib/csapi/cross_signing.h index 617b61d1..6cea73e6 100644 --- a/lib/csapi/cross_signing.h +++ b/lib/csapi/cross_signing.h @@ -4,6 +4,7 @@ #pragma once +#include "csapi/definitions/auth_data.h" #include "csapi/definitions/cross_signing_key.h" #include "jobs/basejob.h" @@ -35,11 +36,16 @@ public: * the accompanying master key, or by the user\'s most recently * uploaded master key if no master key is included in the * request. + * + * \param auth + * Additional authentication information for the + * user-interactive authentication API. */ explicit UploadCrossSigningKeysJob( const Omittable<CrossSigningKey>& masterKey = none, const Omittable<CrossSigningKey>& selfSigningKey = none, - const Omittable<CrossSigningKey>& userSigningKey = none); + const Omittable<CrossSigningKey>& userSigningKey = none, + const Omittable<AuthenticationData>& auth = none); }; /*! \brief Upload cross-signing signatures. @@ -55,7 +61,7 @@ public: * The signatures to be published. */ explicit UploadCrossSigningSignaturesJob( - const QHash<QString, QHash<QString, QJsonObject>>& signatures = {}); + const QHash<QString, QHash<QString, QJsonObject>>& signatures); // Result properties diff --git a/lib/csapi/definitions/auth_data.h b/lib/csapi/definitions/auth_data.h index e92596d0..a9972323 100644 --- a/lib/csapi/definitions/auth_data.h +++ b/lib/csapi/definitions/auth_data.h @@ -10,7 +10,10 @@ namespace Quotient { /// Used by clients to submit authentication information to the /// interactive-authentication API struct AuthenticationData { - /// The login type that the client is attempting to complete. + /// The authentication type that the client is attempting to complete. + /// May be omitted if `session` is given, and the client is reissuing a + /// request which it believes has been completed out-of-band (for example, + /// via the [fallback mechanism](#fallback)). QString type; /// The value of the session key given by the homeserver. @@ -25,7 +28,7 @@ struct JsonObjectConverter<AuthenticationData> { static void dumpTo(QJsonObject& jo, const AuthenticationData& pod) { fillJson(jo, pod.authInfo); - addParam<>(jo, QStringLiteral("type"), pod.type); + addParam<IfNotEmpty>(jo, QStringLiteral("type"), pod.type); addParam<IfNotEmpty>(jo, QStringLiteral("session"), pod.session); } static void fillFrom(QJsonObject jo, AuthenticationData& pod) diff --git a/lib/csapi/definitions/openid_token.h b/lib/csapi/definitions/openid_token.h index 3c447321..9b026dea 100644 --- a/lib/csapi/definitions/openid_token.h +++ b/lib/csapi/definitions/openid_token.h @@ -8,7 +8,7 @@ namespace Quotient { -struct OpenidToken { +struct OpenIdCredentials { /// An access token the consumer may use to verify the identity of /// the person who generated the token. This is given to the federation /// API `GET /openid/userinfo` to verify the user's identity. @@ -27,8 +27,8 @@ struct OpenidToken { }; template <> -struct JsonObjectConverter<OpenidToken> { - static void dumpTo(QJsonObject& jo, const OpenidToken& pod) +struct JsonObjectConverter<OpenIdCredentials> { + static void dumpTo(QJsonObject& jo, const OpenIdCredentials& pod) { addParam<>(jo, QStringLiteral("access_token"), pod.accessToken); addParam<>(jo, QStringLiteral("token_type"), pod.tokenType); @@ -36,7 +36,7 @@ struct JsonObjectConverter<OpenidToken> { pod.matrixServerName); addParam<>(jo, QStringLiteral("expires_in"), pod.expiresIn); } - static void fillFrom(const QJsonObject& jo, OpenidToken& pod) + static void fillFrom(const QJsonObject& jo, OpenIdCredentials& pod) { fromJson(jo.value("access_token"_ls), pod.accessToken); fromJson(jo.value("token_type"_ls), pod.tokenType); diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index 2938b4ec..d0a2595c 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -9,9 +9,6 @@ namespace Quotient { struct PublicRoomsChunk { - /// Aliases of the room. May be empty. - QStringList aliases; - /// The canonical alias of the room, if any. QString canonicalAlias; @@ -49,7 +46,6 @@ template <> struct JsonObjectConverter<PublicRoomsChunk> { static void dumpTo(QJsonObject& jo, const PublicRoomsChunk& pod) { - addParam<IfNotEmpty>(jo, QStringLiteral("aliases"), pod.aliases); addParam<IfNotEmpty>(jo, QStringLiteral("canonical_alias"), pod.canonicalAlias); addParam<IfNotEmpty>(jo, QStringLiteral("name"), pod.name); @@ -64,7 +60,6 @@ struct JsonObjectConverter<PublicRoomsChunk> { } static void fillFrom(const QJsonObject& jo, PublicRoomsChunk& pod) { - fromJson(jo.value("aliases"_ls), pod.aliases); fromJson(jo.value("canonical_alias"_ls), pod.canonicalAlias); fromJson(jo.value("name"_ls), pod.name); fromJson(jo.value("num_joined_members"_ls), pod.numJoinedMembers); @@ -77,44 +72,4 @@ struct JsonObjectConverter<PublicRoomsChunk> { } }; -/// A list of the rooms on the server. -struct PublicRoomsResponse { - /// A paginated chunk of public rooms. - QVector<PublicRoomsChunk> chunk; - - /// A pagination token for the response. The absence of this token - /// means there are no more results to fetch and the client should - /// stop paginating. - QString nextBatch; - - /// A pagination token that allows fetching previous results. The - /// absence of this token means there are no results before this - /// batch, i.e. this is the first batch. - QString prevBatch; - - /// An estimate on the total number of public rooms, if the - /// server has an estimate. - Omittable<int> totalRoomCountEstimate; -}; - -template <> -struct JsonObjectConverter<PublicRoomsResponse> { - static void dumpTo(QJsonObject& jo, const PublicRoomsResponse& pod) - { - addParam<>(jo, QStringLiteral("chunk"), pod.chunk); - addParam<IfNotEmpty>(jo, QStringLiteral("next_batch"), pod.nextBatch); - addParam<IfNotEmpty>(jo, QStringLiteral("prev_batch"), pod.prevBatch); - addParam<IfNotEmpty>(jo, QStringLiteral("total_room_count_estimate"), - pod.totalRoomCountEstimate); - } - static void fillFrom(const QJsonObject& jo, PublicRoomsResponse& pod) - { - fromJson(jo.value("chunk"_ls), pod.chunk); - fromJson(jo.value("next_batch"_ls), pod.nextBatch); - fromJson(jo.value("prev_batch"_ls), pod.prevBatch); - fromJson(jo.value("total_room_count_estimate"_ls), - pod.totalRoomCountEstimate); - } -}; - } // namespace Quotient diff --git a/lib/csapi/definitions/push_condition.h b/lib/csapi/definitions/push_condition.h index ce66d075..6a048ba8 100644 --- a/lib/csapi/definitions/push_condition.h +++ b/lib/csapi/definitions/push_condition.h @@ -24,9 +24,7 @@ struct PushCondition { QString key; /// Required for `event_match` conditions. The glob-style pattern to - /// match against. Patterns with no special glob characters should be - /// treated as having asterisks prepended and appended when testing the - /// condition. + /// match against. QString pattern; /// Required for `room_member_count` conditions. A decimal integer diff --git a/lib/csapi/device_management.cpp b/lib/csapi/device_management.cpp index da6dbc76..6f2badee 100644 --- a/lib/csapi/device_management.cpp +++ b/lib/csapi/device_management.cpp @@ -9,53 +9,53 @@ using namespace Quotient; QUrl GetDevicesJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/devices")); + makePath("/_matrix/client/v3", "/devices")); } GetDevicesJob::GetDevicesJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetDevicesJob"), - makePath("/_matrix/client/r0", "/devices")) + makePath("/_matrix/client/v3", "/devices")) {} QUrl GetDeviceJob::makeRequestUrl(QUrl baseUrl, const QString& deviceId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/devices/", + makePath("/_matrix/client/v3", "/devices/", deviceId)); } GetDeviceJob::GetDeviceJob(const QString& deviceId) : BaseJob(HttpVerb::Get, QStringLiteral("GetDeviceJob"), - makePath("/_matrix/client/r0", "/devices/", deviceId)) + makePath("/_matrix/client/v3", "/devices/", deviceId)) {} UpdateDeviceJob::UpdateDeviceJob(const QString& deviceId, const QString& displayName) : BaseJob(HttpVerb::Put, QStringLiteral("UpdateDeviceJob"), - makePath("/_matrix/client/r0", "/devices/", deviceId)) + makePath("/_matrix/client/v3", "/devices/", deviceId)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("display_name"), displayName); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("display_name"), displayName); + setRequestData({ _dataJson }); } DeleteDeviceJob::DeleteDeviceJob(const QString& deviceId, const Omittable<AuthenticationData>& auth) : BaseJob(HttpVerb::Delete, QStringLiteral("DeleteDeviceJob"), - makePath("/_matrix/client/r0", "/devices/", deviceId)) + makePath("/_matrix/client/v3", "/devices/", deviceId)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + setRequestData({ _dataJson }); } DeleteDevicesJob::DeleteDevicesJob(const QStringList& devices, const Omittable<AuthenticationData>& auth) : BaseJob(HttpVerb::Post, QStringLiteral("DeleteDevicesJob"), - makePath("/_matrix/client/r0", "/delete_devices")) + makePath("/_matrix/client/v3", "/delete_devices")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("devices"), devices); - addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("devices"), devices); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/device_management.h b/lib/csapi/device_management.h index 430d2132..c10389b3 100644 --- a/lib/csapi/device_management.h +++ b/lib/csapi/device_management.h @@ -86,7 +86,8 @@ public: * This API endpoint uses the [User-Interactive Authentication * API](/client-server-api/#user-interactive-authentication-api). * - * Deletes the given device, and invalidates any access token associated with it. + * Deletes the given device, and invalidates any access token associated with + * it. */ class QUOTIENT_API DeleteDeviceJob : public BaseJob { public: diff --git a/lib/csapi/directory.cpp b/lib/csapi/directory.cpp index b351b4ef..c1255bb1 100644 --- a/lib/csapi/directory.cpp +++ b/lib/csapi/directory.cpp @@ -8,48 +8,48 @@ using namespace Quotient; SetRoomAliasJob::SetRoomAliasJob(const QString& roomAlias, const QString& roomId) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomAliasJob"), - makePath("/_matrix/client/r0", "/directory/room/", roomAlias)) + makePath("/_matrix/client/v3", "/directory/room/", roomAlias)) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("room_id"), roomId); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("room_id"), roomId); + setRequestData({ _dataJson }); } QUrl GetRoomIdByAliasJob::makeRequestUrl(QUrl baseUrl, const QString& roomAlias) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/directory/room/", roomAlias)); } GetRoomIdByAliasJob::GetRoomIdByAliasJob(const QString& roomAlias) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomIdByAliasJob"), - makePath("/_matrix/client/r0", "/directory/room/", roomAlias), + makePath("/_matrix/client/v3", "/directory/room/", roomAlias), false) {} QUrl DeleteRoomAliasJob::makeRequestUrl(QUrl baseUrl, const QString& roomAlias) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/directory/room/", roomAlias)); } DeleteRoomAliasJob::DeleteRoomAliasJob(const QString& roomAlias) : BaseJob(HttpVerb::Delete, QStringLiteral("DeleteRoomAliasJob"), - makePath("/_matrix/client/r0", "/directory/room/", roomAlias)) + makePath("/_matrix/client/v3", "/directory/room/", roomAlias)) {} QUrl GetLocalAliasesJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/aliases")); } GetLocalAliasesJob::GetLocalAliasesJob(const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetLocalAliasesJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/aliases")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/aliases")) { addExpectedKey("aliases"); } diff --git a/lib/csapi/event_context.cpp b/lib/csapi/event_context.cpp index 877838e2..4ebbbf98 100644 --- a/lib/csapi/event_context.cpp +++ b/lib/csapi/event_context.cpp @@ -20,7 +20,7 @@ QUrl GetEventContextJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& filter) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/context/", eventId), queryToGetEventContext(limit, filter)); } @@ -30,7 +30,7 @@ GetEventContextJob::GetEventContextJob(const QString& roomId, Omittable<int> limit, const QString& filter) : BaseJob(HttpVerb::Get, QStringLiteral("GetEventContextJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/context/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/context/", eventId), queryToGetEventContext(limit, filter)) {} diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index 38c68be7..2469fbd1 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -8,9 +8,9 @@ using namespace Quotient; DefineFilterJob::DefineFilterJob(const QString& userId, const Filter& filter) : BaseJob(HttpVerb::Post, QStringLiteral("DefineFilterJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/filter")) + makePath("/_matrix/client/v3", "/user/", userId, "/filter")) { - setRequestData(RequestData(toJson(filter))); + setRequestData({ toJson(filter) }); addExpectedKey("filter_id"); } @@ -18,12 +18,12 @@ QUrl GetFilterJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& filterId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/user/", + makePath("/_matrix/client/v3", "/user/", userId, "/filter/", filterId)); } GetFilterJob::GetFilterJob(const QString& userId, const QString& filterId) : BaseJob(HttpVerb::Get, QStringLiteral("GetFilterJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/filter/", + makePath("/_matrix/client/v3", "/user/", userId, "/filter/", filterId)) {} diff --git a/lib/csapi/inviting.cpp b/lib/csapi/inviting.cpp index 39d24611..41a8b5be 100644 --- a/lib/csapi/inviting.cpp +++ b/lib/csapi/inviting.cpp @@ -9,10 +9,10 @@ using namespace Quotient; InviteUserJob::InviteUserJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("InviteUserJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/invite")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/invite")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("user_id"), userId); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("user_id"), userId); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/inviting.h b/lib/csapi/inviting.h index 21e6cb74..cb9d052b 100644 --- a/lib/csapi/inviting.h +++ b/lib/csapi/inviting.h @@ -14,7 +14,7 @@ namespace Quotient { * This version of the API requires that the inviter knows the Matrix * identifier of the invitee. The other is documented in the* * [third party invites - * section](/client-server-api/#post_matrixclientr0roomsroomidinvite-1). + * section](/client-server-api/#post_matrixclientv3roomsroomidinvite-1). * * This API invites a user to participate in a particular room. * They do not start participating in the room until they actually join the diff --git a/lib/csapi/joining.cpp b/lib/csapi/joining.cpp index 373c1c6a..cdba95e9 100644 --- a/lib/csapi/joining.cpp +++ b/lib/csapi/joining.cpp @@ -10,13 +10,13 @@ JoinRoomByIdJob::JoinRoomByIdJob( const QString& roomId, const Omittable<ThirdPartySigned>& thirdPartySigned, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("JoinRoomByIdJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/join")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/join")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("third_party_signed"), + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("third_party_signed"), thirdPartySigned); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); addExpectedKey("room_id"); } @@ -32,13 +32,13 @@ JoinRoomJob::JoinRoomJob(const QString& roomIdOrAlias, const Omittable<ThirdPartySigned>& thirdPartySigned, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("JoinRoomJob"), - makePath("/_matrix/client/r0", "/join/", roomIdOrAlias), + makePath("/_matrix/client/v3", "/join/", roomIdOrAlias), queryToJoinRoom(serverName)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("third_party_signed"), + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("third_party_signed"), thirdPartySigned); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); addExpectedKey("room_id"); } diff --git a/lib/csapi/joining.h b/lib/csapi/joining.h index f64152f7..233537bb 100644 --- a/lib/csapi/joining.h +++ b/lib/csapi/joining.h @@ -22,8 +22,8 @@ namespace Quotient { * * After a user has joined a room, the room will appear as an entry in the * response of the - * [`/initialSync`](/client-server-api/#get_matrixclientr0initialsync) and - * [`/sync`](/client-server-api/#get_matrixclientr0sync) APIs. + * [`/initialSync`](/client-server-api/#get_matrixclientv3initialsync) and + * [`/sync`](/client-server-api/#get_matrixclientv3sync) APIs. */ class QUOTIENT_API JoinRoomByIdJob : public BaseJob { public: @@ -64,8 +64,8 @@ public: * * After a user has joined a room, the room will appear as an entry in the * response of the - * [`/initialSync`](/client-server-api/#get_matrixclientr0initialsync) and - * [`/sync`](/client-server-api/#get_matrixclientr0sync) APIs. + * [`/initialSync`](/client-server-api/#get_matrixclientv3initialsync) and + * [`/sync`](/client-server-api/#get_matrixclientv3sync) APIs. */ class QUOTIENT_API JoinRoomJob : public BaseJob { public: diff --git a/lib/csapi/keys.cpp b/lib/csapi/keys.cpp index d6bd2fab..2e4978f2 100644 --- a/lib/csapi/keys.cpp +++ b/lib/csapi/keys.cpp @@ -7,39 +7,43 @@ using namespace Quotient; UploadKeysJob::UploadKeysJob(const Omittable<DeviceKeys>& deviceKeys, - const QHash<QString, QVariant>& oneTimeKeys) + const OneTimeKeys& oneTimeKeys, + const OneTimeKeys& fallbackKeys) : BaseJob(HttpVerb::Post, QStringLiteral("UploadKeysJob"), - makePath("/_matrix/client/r0", "/keys/upload")) + makePath("/_matrix/client/v3", "/keys/upload")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("device_keys"), deviceKeys); - addParam<IfNotEmpty>(_data, QStringLiteral("one_time_keys"), oneTimeKeys); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("device_keys"), deviceKeys); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("one_time_keys"), + oneTimeKeys); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("fallback_keys"), + fallbackKeys); + setRequestData({ _dataJson }); addExpectedKey("one_time_key_counts"); } QueryKeysJob::QueryKeysJob(const QHash<QString, QStringList>& deviceKeys, Omittable<int> timeout, const QString& token) : BaseJob(HttpVerb::Post, QStringLiteral("QueryKeysJob"), - makePath("/_matrix/client/r0", "/keys/query")) + makePath("/_matrix/client/v3", "/keys/query")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("timeout"), timeout); - addParam<>(_data, QStringLiteral("device_keys"), deviceKeys); - addParam<IfNotEmpty>(_data, QStringLiteral("token"), token); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("timeout"), timeout); + addParam<>(_dataJson, QStringLiteral("device_keys"), deviceKeys); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("token"), token); + setRequestData({ _dataJson }); } ClaimKeysJob::ClaimKeysJob( const QHash<QString, QHash<QString, QString>>& oneTimeKeys, Omittable<int> timeout) : BaseJob(HttpVerb::Post, QStringLiteral("ClaimKeysJob"), - makePath("/_matrix/client/r0", "/keys/claim")) + makePath("/_matrix/client/v3", "/keys/claim")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("timeout"), timeout); - addParam<>(_data, QStringLiteral("one_time_keys"), oneTimeKeys); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("timeout"), timeout); + addParam<>(_dataJson, QStringLiteral("one_time_keys"), oneTimeKeys); + setRequestData({ _dataJson }); addExpectedKey("one_time_keys"); } @@ -55,13 +59,13 @@ QUrl GetKeysChangesJob::makeRequestUrl(QUrl baseUrl, const QString& from, const QString& to) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/keys/changes"), queryToGetKeysChanges(from, to)); } GetKeysChangesJob::GetKeysChangesJob(const QString& from, const QString& to) : BaseJob(HttpVerb::Get, QStringLiteral("GetKeysChangesJob"), - makePath("/_matrix/client/r0", "/keys/changes"), + makePath("/_matrix/client/v3", "/keys/changes"), queryToGetKeysChanges(from, to)) {} diff --git a/lib/csapi/keys.h b/lib/csapi/keys.h index ce1ca9ed..2f2ebc6d 100644 --- a/lib/csapi/keys.h +++ b/lib/csapi/keys.h @@ -4,6 +4,8 @@ #pragma once +#include "e2ee/e2ee.h" + #include "csapi/definitions/cross_signing_key.h" #include "csapi/definitions/device_keys.h" @@ -30,14 +32,32 @@ public: * by the [key algorithm](/client-server-api/#key-algorithms). * * May be absent if no new one-time keys are required. + * + * \param fallbackKeys + * The public key which should be used if the device's one-time keys + * are exhausted. The fallback key is not deleted once used, but should + * be replaced when additional one-time keys are being uploaded. The + * server will notify the client of the fallback key being used through + * `/sync`. + * + * There can only be at most one key per algorithm uploaded, and the + * server will only persist one key per algorithm. + * + * When uploading a signed key, an additional `fallback: true` key should + * be included to denote that the key is a fallback key. + * + * May be absent if a new fallback key is not required. */ explicit UploadKeysJob(const Omittable<DeviceKeys>& deviceKeys = none, - const QHash<QString, QVariant>& oneTimeKeys = {}); + const OneTimeKeys& oneTimeKeys = {}, + const OneTimeKeys& fallbackKeys = {}); // Result properties /// For each key algorithm, the number of unclaimed one-time keys /// of that type currently held on the server for this device. + /// If an algorithm is not listed, the count for that algorithm + /// is to be assumed zero. QHash<QString, int> oneTimeKeyCounts() const { return loadFromJson<QHash<QString, int>>("one_time_key_counts"_ls); @@ -207,9 +227,12 @@ public: /// /// See the [key algorithms](/client-server-api/#key-algorithms) section for /// information on the Key Object format. - QHash<QString, QHash<QString, QVariant>> oneTimeKeys() const + /// + /// If necessary, the claimed key might be a fallback key. Fallback + /// keys are re-used by the server until replaced by the device. + QHash<QString, QHash<QString, OneTimeKeys>> oneTimeKeys() const { - return loadFromJson<QHash<QString, QHash<QString, QVariant>>>( + return loadFromJson<QHash<QString, QHash<QString, OneTimeKeys>>>( "one_time_keys"_ls); } }; @@ -233,7 +256,7 @@ public: * \param from * The desired start point of the list. Should be the `next_batch` field * from a response to an earlier call to - * [`/sync`](/client-server-api/#get_matrixclientr0sync). Users who have not + * [`/sync`](/client-server-api/#get_matrixclientv3sync). Users who have not * uploaded new device identity keys since this point, nor deleted * existing devices with identity keys since then, will be excluded * from the results. @@ -241,7 +264,7 @@ public: * \param to * The desired end point of the list. Should be the `next_batch` * field from a recent call to - * [`/sync`](/client-server-api/#get_matrixclientr0sync) - typically the + * [`/sync`](/client-server-api/#get_matrixclientv3sync) - typically the * most recent such call. This may be used by the server as a hint to check * its caches are up to date. */ diff --git a/lib/csapi/kicking.cpp b/lib/csapi/kicking.cpp index 433e592c..4ca39c4c 100644 --- a/lib/csapi/kicking.cpp +++ b/lib/csapi/kicking.cpp @@ -9,10 +9,10 @@ using namespace Quotient; KickJob::KickJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("KickJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/kick")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/kick")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("user_id"), userId); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("user_id"), userId); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/knocking.cpp b/lib/csapi/knocking.cpp index 73e13e6e..b9da4b9b 100644 --- a/lib/csapi/knocking.cpp +++ b/lib/csapi/knocking.cpp @@ -16,11 +16,11 @@ auto queryToKnockRoom(const QStringList& serverName) KnockRoomJob::KnockRoomJob(const QString& roomIdOrAlias, const QStringList& serverName, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("KnockRoomJob"), - makePath("/_matrix/client/r0", "/knock/", roomIdOrAlias), + makePath("/_matrix/client/v3", "/knock/", roomIdOrAlias), queryToKnockRoom(serverName)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); addExpectedKey("room_id"); } diff --git a/lib/csapi/knocking.h b/lib/csapi/knocking.h index e3645b59..f43033a8 100644 --- a/lib/csapi/knocking.h +++ b/lib/csapi/knocking.h @@ -25,7 +25,7 @@ namespace Quotient { * history visibility to the user. * * The knock will appear as an entry in the response of the - * [`/sync`](/client-server-api/#get_matrixclientr0sync) API. + * [`/sync`](/client-server-api/#get_matrixclientv3sync) API. */ class QUOTIENT_API KnockRoomJob : public BaseJob { public: diff --git a/lib/csapi/leaving.cpp b/lib/csapi/leaving.cpp index 0e5386be..ba91f26a 100644 --- a/lib/csapi/leaving.cpp +++ b/lib/csapi/leaving.cpp @@ -8,21 +8,21 @@ using namespace Quotient; LeaveRoomJob::LeaveRoomJob(const QString& roomId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("LeaveRoomJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/leave")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/leave")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } QUrl ForgetRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/forget")); } ForgetRoomJob::ForgetRoomJob(const QString& roomId) : BaseJob(HttpVerb::Post, QStringLiteral("ForgetRoomJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/forget")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/forget")) {} diff --git a/lib/csapi/list_joined_rooms.cpp b/lib/csapi/list_joined_rooms.cpp index 22ba04da..cdcf3eb2 100644 --- a/lib/csapi/list_joined_rooms.cpp +++ b/lib/csapi/list_joined_rooms.cpp @@ -9,12 +9,12 @@ using namespace Quotient; QUrl GetJoinedRoomsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/joined_rooms")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/joined_rooms")); } GetJoinedRoomsJob::GetJoinedRoomsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetJoinedRoomsJob"), - makePath("/_matrix/client/r0", "/joined_rooms")) + makePath("/_matrix/client/v3", "/joined_rooms")) { addExpectedKey("joined_rooms"); } diff --git a/lib/csapi/list_public_rooms.cpp b/lib/csapi/list_public_rooms.cpp index 25f8da5c..4deecfc2 100644 --- a/lib/csapi/list_public_rooms.cpp +++ b/lib/csapi/list_public_rooms.cpp @@ -10,25 +10,25 @@ QUrl GetRoomVisibilityOnDirectoryJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/directory/list/room/", roomId)); } GetRoomVisibilityOnDirectoryJob::GetRoomVisibilityOnDirectoryJob( const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomVisibilityOnDirectoryJob"), - makePath("/_matrix/client/r0", "/directory/list/room/", roomId), + makePath("/_matrix/client/v3", "/directory/list/room/", roomId), false) {} SetRoomVisibilityOnDirectoryJob::SetRoomVisibilityOnDirectoryJob( const QString& roomId, const QString& visibility) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomVisibilityOnDirectoryJob"), - makePath("/_matrix/client/r0", "/directory/list/room/", roomId)) + makePath("/_matrix/client/v3", "/directory/list/room/", roomId)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("visibility"), visibility); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("visibility"), visibility); + setRequestData({ _dataJson }); } auto queryToGetPublicRooms(Omittable<int> limit, const QString& since, @@ -46,7 +46,7 @@ QUrl GetPublicRoomsJob::makeRequestUrl(QUrl baseUrl, Omittable<int> limit, const QString& server) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/publicRooms"), queryToGetPublicRooms(limit, since, server)); } @@ -54,7 +54,7 @@ QUrl GetPublicRoomsJob::makeRequestUrl(QUrl baseUrl, Omittable<int> limit, GetPublicRoomsJob::GetPublicRoomsJob(Omittable<int> limit, const QString& since, const QString& server) : BaseJob(HttpVerb::Get, QStringLiteral("GetPublicRoomsJob"), - makePath("/_matrix/client/r0", "/publicRooms"), + makePath("/_matrix/client/v3", "/publicRooms"), queryToGetPublicRooms(limit, since, server), {}, false) { addExpectedKey("chunk"); @@ -74,17 +74,17 @@ QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable<bool> includeAllNetworks, const QString& thirdPartyInstanceId) : BaseJob(HttpVerb::Post, QStringLiteral("QueryPublicRoomsJob"), - makePath("/_matrix/client/r0", "/publicRooms"), + makePath("/_matrix/client/v3", "/publicRooms"), queryToQueryPublicRooms(server)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("limit"), limit); - addParam<IfNotEmpty>(_data, QStringLiteral("since"), since); - addParam<IfNotEmpty>(_data, QStringLiteral("filter"), filter); - addParam<IfNotEmpty>(_data, QStringLiteral("include_all_networks"), + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("limit"), limit); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("since"), since); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("filter"), filter); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("include_all_networks"), includeAllNetworks); - addParam<IfNotEmpty>(_data, QStringLiteral("third_party_instance_id"), + addParam<IfNotEmpty>(_dataJson, QStringLiteral("third_party_instance_id"), thirdPartyInstanceId); - setRequestData(std::move(_data)); + setRequestData({ _dataJson }); addExpectedKey("chunk"); } diff --git a/lib/csapi/login.cpp b/lib/csapi/login.cpp index 71fd93c5..81e603b5 100644 --- a/lib/csapi/login.cpp +++ b/lib/csapi/login.cpp @@ -9,29 +9,33 @@ using namespace Quotient; QUrl GetLoginFlowsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/login")); + makePath("/_matrix/client/v3", "/login")); } GetLoginFlowsJob::GetLoginFlowsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetLoginFlowsJob"), - makePath("/_matrix/client/r0", "/login"), false) + makePath("/_matrix/client/v3", "/login"), false) {} LoginJob::LoginJob(const QString& type, const Omittable<UserIdentifier>& identifier, const QString& password, const QString& token, const QString& deviceId, - const QString& initialDeviceDisplayName) + const QString& initialDeviceDisplayName, + Omittable<bool> refreshToken) : BaseJob(HttpVerb::Post, QStringLiteral("LoginJob"), - makePath("/_matrix/client/r0", "/login"), false) + makePath("/_matrix/client/v3", "/login"), false) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("type"), type); - addParam<IfNotEmpty>(_data, QStringLiteral("identifier"), identifier); - addParam<IfNotEmpty>(_data, QStringLiteral("password"), password); - addParam<IfNotEmpty>(_data, QStringLiteral("token"), token); - addParam<IfNotEmpty>(_data, QStringLiteral("device_id"), deviceId); - addParam<IfNotEmpty>(_data, QStringLiteral("initial_device_display_name"), + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("type"), type); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("identifier"), identifier); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("password"), password); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("token"), token); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("device_id"), deviceId); + addParam<IfNotEmpty>(_dataJson, + QStringLiteral("initial_device_display_name"), initialDeviceDisplayName); - setRequestData(std::move(_data)); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("refresh_token"), + refreshToken); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/login.h b/lib/csapi/login.h index ce6951eb..b9f14266 100644 --- a/lib/csapi/login.h +++ b/lib/csapi/login.h @@ -111,12 +111,16 @@ public: * \param initialDeviceDisplayName * A display name to assign to the newly-created device. Ignored * if `device_id` corresponds to a known device. + * + * \param refreshToken + * If true, the client supports refresh tokens. */ explicit LoginJob(const QString& type, const Omittable<UserIdentifier>& identifier = none, const QString& password = {}, const QString& token = {}, const QString& deviceId = {}, - const QString& initialDeviceDisplayName = {}); + const QString& initialDeviceDisplayName = {}, + Omittable<bool> refreshToken = none); // Result properties @@ -130,15 +134,23 @@ public: return loadFromJson<QString>("access_token"_ls); } - /// The server_name of the homeserver on which the account has - /// been registered. - /// - /// **Deprecated**. Clients should extract the server_name from - /// `user_id` (by splitting at the first colon) if they require - /// it. Note also that `homeserver` is not spelt this way. - QString homeServer() const + /// A refresh token for the account. This token can be used to + /// obtain a new access token when it expires by calling the + /// `/refresh` endpoint. + QString refreshToken() const + { + return loadFromJson<QString>("refresh_token"_ls); + } + + /// The lifetime of the access token, in milliseconds. Once + /// the access token has expired a new access token can be + /// obtained by using the provided refresh token. If no + /// refresh token is provided, the client will need to re-log in + /// to obtain a new access token. If not given, the client can + /// assume that the access token will not expire. + Omittable<int> expiresInMs() const { - return loadFromJson<QString>("home_server"_ls); + return loadFromJson<Omittable<int>>("expires_in_ms"_ls); } /// ID of the logged-in device. Will be the same as the diff --git a/lib/csapi/logout.cpp b/lib/csapi/logout.cpp index e8083e31..9ec54c71 100644 --- a/lib/csapi/logout.cpp +++ b/lib/csapi/logout.cpp @@ -9,21 +9,21 @@ using namespace Quotient; QUrl LogoutJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/logout")); + makePath("/_matrix/client/v3", "/logout")); } LogoutJob::LogoutJob() : BaseJob(HttpVerb::Post, QStringLiteral("LogoutJob"), - makePath("/_matrix/client/r0", "/logout")) + makePath("/_matrix/client/v3", "/logout")) {} QUrl LogoutAllJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/logout/all")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/logout/all")); } LogoutAllJob::LogoutAllJob() : BaseJob(HttpVerb::Post, QStringLiteral("LogoutAllJob"), - makePath("/_matrix/client/r0", "/logout/all")) + makePath("/_matrix/client/v3", "/logout/all")) {} diff --git a/lib/csapi/message_pagination.cpp b/lib/csapi/message_pagination.cpp index 1a93b75b..0b2c99ce 100644 --- a/lib/csapi/message_pagination.cpp +++ b/lib/csapi/message_pagination.cpp @@ -11,7 +11,7 @@ auto queryToGetRoomEvents(const QString& from, const QString& to, const QString& filter) { QUrlQuery _q; - addParam<>(_q, QStringLiteral("from"), from); + addParam<IfNotEmpty>(_q, QStringLiteral("from"), from); addParam<IfNotEmpty>(_q, QStringLiteral("to"), to); addParam<>(_q, QStringLiteral("dir"), dir); addParam<IfNotEmpty>(_q, QStringLiteral("limit"), limit); @@ -20,20 +20,23 @@ auto queryToGetRoomEvents(const QString& from, const QString& to, } QUrl GetRoomEventsJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, - const QString& from, const QString& dir, + const QString& dir, const QString& from, const QString& to, Omittable<int> limit, const QString& filter) { return BaseJob::makeRequestUrl( std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/messages"), + makePath("/_matrix/client/v3", "/rooms/", roomId, "/messages"), queryToGetRoomEvents(from, to, dir, limit, filter)); } -GetRoomEventsJob::GetRoomEventsJob(const QString& roomId, const QString& from, - const QString& dir, const QString& to, +GetRoomEventsJob::GetRoomEventsJob(const QString& roomId, const QString& dir, + const QString& from, const QString& to, Omittable<int> limit, const QString& filter) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomEventsJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/messages"), + makePath("/_matrix/client/v3", "/rooms/", roomId, "/messages"), queryToGetRoomEvents(from, to, dir, limit, filter)) -{} +{ + addExpectedKey("start"); + addExpectedKey("chunk"); +} diff --git a/lib/csapi/message_pagination.h b/lib/csapi/message_pagination.h index 8c18f104..9831ae2d 100644 --- a/lib/csapi/message_pagination.h +++ b/lib/csapi/message_pagination.h @@ -25,20 +25,30 @@ public: * \param roomId * The room to get events from. * + * \param dir + * The direction to return events from. If this is set to `f`, events + * will be returned in chronological order starting at `from`. If it + * is set to `b`, events will be returned in *reverse* chronological + * order, again starting at `from`. + * * \param from * The token to start returning events from. This token can be obtained - * from a `prev_batch` token returned for each room by the sync API, - * or from a `start` or `end` token returned by a previous request - * to this endpoint. + * from a `prev_batch` or `next_batch` token returned by the `/sync` + * endpoint, or from an `end` token returned by a previous request to this + * endpoint. * - * \param dir - * The direction to return events from. + * This endpoint can also accept a value returned as a `start` token + * by a previous request to this endpoint, though servers are not + * required to support this. Clients should not rely on the behaviour. + * + * If it is not provided, the homeserver shall return a list of messages + * from the first or last (per the value of the `dir` parameter) visible + * event in the room history for the requesting user. * * \param to * The token to stop returning events at. This token can be obtained from - * a `prev_batch` token returned for each room by the sync endpoint, - * or from a `start` or `end` token returned by a previous request to - * this endpoint. + * a `prev_batch` or `next_batch` token returned by the `/sync` endpoint, + * or from an `end` token returned by a previous request to this endpoint. * * \param limit * The maximum number of events to return. Default: 10. @@ -46,8 +56,8 @@ public: * \param filter * A JSON RoomEventFilter to filter returned events with. */ - explicit GetRoomEventsJob(const QString& roomId, const QString& from, - const QString& dir, const QString& to = {}, + explicit GetRoomEventsJob(const QString& roomId, const QString& dir, + const QString& from = {}, const QString& to = {}, Omittable<int> limit = none, const QString& filter = {}); @@ -57,25 +67,34 @@ public: * is necessary but the job itself isn't. */ static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, - const QString& from, const QString& dir, + const QString& dir, const QString& from = {}, const QString& to = {}, Omittable<int> limit = none, const QString& filter = {}); // Result properties - /// The token the pagination starts from. If `dir=b` this will be - /// the token supplied in `from`. + /// A token corresponding to the start of `chunk`. This will be the same as + /// the value given in `from`. QString begin() const { return loadFromJson<QString>("start"_ls); } - /// The token the pagination ends at. If `dir=b` this token should - /// be used again to request even earlier events. + /// A token corresponding to the end of `chunk`. This token can be passed + /// back to this endpoint to request further events. + /// + /// If no further events are available (either because we have + /// reached the start of the timeline, or because the user does + /// not have permission to see any more events), this property + /// is omitted from the response. QString end() const { return loadFromJson<QString>("end"_ls); } /// A list of room events. The order depends on the `dir` parameter. /// For `dir=b` events will be in reverse-chronological order, - /// for `dir=f` in chronological order, so that events start - /// at the `from` point. + /// for `dir=f` in chronological order. (The exact definition of + /// `chronological` is dependent on the server implementation.) + /// + /// Note that an empty `chunk` does not *necessarily* imply that no more + /// events are available. Clients should continue to paginate until no `end` + /// property is returned. RoomEvents chunk() { return takeFromJson<RoomEvents>("chunk"_ls); } /// A list of state events relevant to showing the `chunk`. For example, if @@ -86,7 +105,7 @@ public: /// may remove membership events which would have already been /// sent to the client in prior calls to this endpoint, assuming /// the membership of those members has not changed. - StateEvents state() { return takeFromJson<StateEvents>("state"_ls); } + RoomEvents state() { return takeFromJson<RoomEvents>("state"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/notifications.cpp b/lib/csapi/notifications.cpp index 1e523c6f..38aed174 100644 --- a/lib/csapi/notifications.cpp +++ b/lib/csapi/notifications.cpp @@ -21,7 +21,7 @@ QUrl GetNotificationsJob::makeRequestUrl(QUrl baseUrl, const QString& from, const QString& only) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/notifications"), queryToGetNotifications(from, limit, only)); } @@ -30,7 +30,7 @@ GetNotificationsJob::GetNotificationsJob(const QString& from, Omittable<int> limit, const QString& only) : BaseJob(HttpVerb::Get, QStringLiteral("GetNotificationsJob"), - makePath("/_matrix/client/r0", "/notifications"), + makePath("/_matrix/client/v3", "/notifications"), queryToGetNotifications(from, limit, only)) { addExpectedKey("notifications"); diff --git a/lib/csapi/notifications.h b/lib/csapi/notifications.h index 23211758..48167877 100644 --- a/lib/csapi/notifications.h +++ b/lib/csapi/notifications.h @@ -43,7 +43,8 @@ public: /*! \brief Gets a list of events that the user has been notified about * * \param from - * Pagination token given to retrieve the next set of events. + * Pagination token to continue from. This should be the `next_token` + * returned from an earlier call to this endpoint. * * \param limit * Limit on the number of events to return in this request. diff --git a/lib/csapi/openid.cpp b/lib/csapi/openid.cpp index 5c93a2d7..7e89b8a6 100644 --- a/lib/csapi/openid.cpp +++ b/lib/csapi/openid.cpp @@ -9,8 +9,8 @@ using namespace Quotient; RequestOpenIdTokenJob::RequestOpenIdTokenJob(const QString& userId, const QJsonObject& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestOpenIdTokenJob"), - makePath("/_matrix/client/r0", "/user/", userId, + makePath("/_matrix/client/v3", "/user/", userId, "/openid/request_token")) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } diff --git a/lib/csapi/openid.h b/lib/csapi/openid.h index 773b6011..b3f72a25 100644 --- a/lib/csapi/openid.h +++ b/lib/csapi/openid.h @@ -43,7 +43,10 @@ public: /// Specification](http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse) /// with the only difference being the lack of an `id_token`. Instead, /// the Matrix homeserver's name is provided. - OpenidToken tokenData() const { return fromJson<OpenidToken>(jsonData()); } + OpenIdCredentials tokenData() const + { + return fromJson<OpenIdCredentials>(jsonData()); + } }; } // namespace Quotient diff --git a/lib/csapi/peeking_events.cpp b/lib/csapi/peeking_events.cpp index eb5d22fa..9dd1445e 100644 --- a/lib/csapi/peeking_events.cpp +++ b/lib/csapi/peeking_events.cpp @@ -20,13 +20,13 @@ QUrl PeekEventsJob::makeRequestUrl(QUrl baseUrl, const QString& from, Omittable<int> timeout, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/events"), + makePath("/_matrix/client/v3", "/events"), queryToPeekEvents(from, timeout, roomId)); } PeekEventsJob::PeekEventsJob(const QString& from, Omittable<int> timeout, const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("PeekEventsJob"), - makePath("/_matrix/client/r0", "/events"), + makePath("/_matrix/client/v3", "/events"), queryToPeekEvents(from, timeout, roomId)) {} diff --git a/lib/csapi/peeking_events.h b/lib/csapi/peeking_events.h index 14cb6f0b..ff688c49 100644 --- a/lib/csapi/peeking_events.h +++ b/lib/csapi/peeking_events.h @@ -9,7 +9,7 @@ namespace Quotient { -/*! \brief Listen on the event stream. +/*! \brief Listen on the event stream of a particular room. * * 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 @@ -24,7 +24,7 @@ namespace Quotient { */ class QUOTIENT_API PeekEventsJob : public BaseJob { public: - /*! \brief Listen on the event stream. + /*! \brief Listen on the event stream of a particular room. * * \param from * The token to stream from. This token is either from a previous diff --git a/lib/csapi/presence.cpp b/lib/csapi/presence.cpp index 4f77c466..828ccfb7 100644 --- a/lib/csapi/presence.cpp +++ b/lib/csapi/presence.cpp @@ -9,24 +9,24 @@ using namespace Quotient; SetPresenceJob::SetPresenceJob(const QString& userId, const QString& presence, const QString& statusMsg) : BaseJob(HttpVerb::Put, QStringLiteral("SetPresenceJob"), - makePath("/_matrix/client/r0", "/presence/", userId, "/status")) + makePath("/_matrix/client/v3", "/presence/", userId, "/status")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("presence"), presence); - addParam<IfNotEmpty>(_data, QStringLiteral("status_msg"), statusMsg); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("presence"), presence); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("status_msg"), statusMsg); + setRequestData({ _dataJson }); } QUrl GetPresenceJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/presence/", + makePath("/_matrix/client/v3", "/presence/", userId, "/status")); } GetPresenceJob::GetPresenceJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetPresenceJob"), - makePath("/_matrix/client/r0", "/presence/", userId, "/status")) + makePath("/_matrix/client/v3", "/presence/", userId, "/status")) { addExpectedKey("presence"); } diff --git a/lib/csapi/profile.cpp b/lib/csapi/profile.cpp index 64ac84ca..f024ed82 100644 --- a/lib/csapi/profile.cpp +++ b/lib/csapi/profile.cpp @@ -9,56 +9,58 @@ using namespace Quotient; SetDisplayNameJob::SetDisplayNameJob(const QString& userId, const QString& displayname) : BaseJob(HttpVerb::Put, QStringLiteral("SetDisplayNameJob"), - makePath("/_matrix/client/r0", "/profile/", userId, "/displayname")) + makePath("/_matrix/client/v3", "/profile/", userId, + "/displayname")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("displayname"), displayname); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("displayname"), displayname); + setRequestData({ _dataJson }); } QUrl GetDisplayNameJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/profile/", + makePath("/_matrix/client/v3", "/profile/", userId, "/displayname")); } GetDisplayNameJob::GetDisplayNameJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetDisplayNameJob"), - makePath("/_matrix/client/r0", "/profile/", userId, "/displayname"), + makePath("/_matrix/client/v3", "/profile/", userId, + "/displayname"), false) {} SetAvatarUrlJob::SetAvatarUrlJob(const QString& userId, const QUrl& avatarUrl) : BaseJob(HttpVerb::Put, QStringLiteral("SetAvatarUrlJob"), - makePath("/_matrix/client/r0", "/profile/", userId, "/avatar_url")) + makePath("/_matrix/client/v3", "/profile/", userId, "/avatar_url")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("avatar_url"), avatarUrl); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("avatar_url"), avatarUrl); + setRequestData({ _dataJson }); } QUrl GetAvatarUrlJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/profile/", + makePath("/_matrix/client/v3", "/profile/", userId, "/avatar_url")); } GetAvatarUrlJob::GetAvatarUrlJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetAvatarUrlJob"), - makePath("/_matrix/client/r0", "/profile/", userId, "/avatar_url"), + makePath("/_matrix/client/v3", "/profile/", userId, "/avatar_url"), false) {} QUrl GetUserProfileJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/profile/", + makePath("/_matrix/client/v3", "/profile/", userId)); } GetUserProfileJob::GetUserProfileJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetUserProfileJob"), - makePath("/_matrix/client/r0", "/profile/", userId), false) + makePath("/_matrix/client/v3", "/profile/", userId), false) {} diff --git a/lib/csapi/pusher.cpp b/lib/csapi/pusher.cpp index ef4b3767..fb6595fc 100644 --- a/lib/csapi/pusher.cpp +++ b/lib/csapi/pusher.cpp @@ -9,12 +9,12 @@ using namespace Quotient; QUrl GetPushersJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/pushers")); + makePath("/_matrix/client/v3", "/pushers")); } GetPushersJob::GetPushersJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetPushersJob"), - makePath("/_matrix/client/r0", "/pushers")) + makePath("/_matrix/client/v3", "/pushers")) {} PostPusherJob::PostPusherJob(const QString& pushkey, const QString& kind, @@ -23,17 +23,18 @@ PostPusherJob::PostPusherJob(const QString& pushkey, const QString& kind, const QString& lang, const PusherData& data, const QString& profileTag, Omittable<bool> append) : BaseJob(HttpVerb::Post, QStringLiteral("PostPusherJob"), - makePath("/_matrix/client/r0", "/pushers/set")) + makePath("/_matrix/client/v3", "/pushers/set")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("pushkey"), pushkey); - addParam<>(_data, QStringLiteral("kind"), kind); - addParam<>(_data, QStringLiteral("app_id"), appId); - addParam<>(_data, QStringLiteral("app_display_name"), appDisplayName); - addParam<>(_data, QStringLiteral("device_display_name"), deviceDisplayName); - addParam<IfNotEmpty>(_data, QStringLiteral("profile_tag"), profileTag); - addParam<>(_data, QStringLiteral("lang"), lang); - addParam<>(_data, QStringLiteral("data"), data); - addParam<IfNotEmpty>(_data, QStringLiteral("append"), append); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("pushkey"), pushkey); + addParam<>(_dataJson, QStringLiteral("kind"), kind); + addParam<>(_dataJson, QStringLiteral("app_id"), appId); + addParam<>(_dataJson, QStringLiteral("app_display_name"), appDisplayName); + addParam<>(_dataJson, QStringLiteral("device_display_name"), + deviceDisplayName); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("profile_tag"), profileTag); + addParam<>(_dataJson, QStringLiteral("lang"), lang); + addParam<>(_dataJson, QStringLiteral("data"), data); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("append"), append); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/pushrules.cpp b/lib/csapi/pushrules.cpp index 0d840788..2376654a 100644 --- a/lib/csapi/pushrules.cpp +++ b/lib/csapi/pushrules.cpp @@ -9,12 +9,12 @@ using namespace Quotient; QUrl GetPushRulesJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/pushrules")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/pushrules")); } GetPushRulesJob::GetPushRulesJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetPushRulesJob"), - makePath("/_matrix/client/r0", "/pushrules")) + makePath("/_matrix/client/v3", "/pushrules")) { addExpectedKey("global"); } @@ -23,14 +23,14 @@ QUrl GetPushRuleJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& kind, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/pushrules/", + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId)); } GetPushRuleJob::GetPushRuleJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Get, QStringLiteral("GetPushRuleJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId)) {} @@ -39,14 +39,14 @@ QUrl DeletePushRuleJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/pushrules/", + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId)); } DeletePushRuleJob::DeletePushRuleJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Delete, QStringLiteral("DeletePushRuleJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId)) {} @@ -65,15 +65,15 @@ SetPushRuleJob::SetPushRuleJob(const QString& scope, const QString& kind, const QVector<PushCondition>& conditions, const QString& pattern) : BaseJob(HttpVerb::Put, QStringLiteral("SetPushRuleJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId), queryToSetPushRule(before, after)) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("actions"), actions); - addParam<IfNotEmpty>(_data, QStringLiteral("conditions"), conditions); - addParam<IfNotEmpty>(_data, QStringLiteral("pattern"), pattern); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("actions"), actions); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("conditions"), conditions); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("pattern"), pattern); + setRequestData({ _dataJson }); } QUrl IsPushRuleEnabledJob::makeRequestUrl(QUrl baseUrl, const QString& scope, @@ -81,7 +81,7 @@ QUrl IsPushRuleEnabledJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/pushrules/", + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId, "/enabled")); } @@ -90,7 +90,7 @@ IsPushRuleEnabledJob::IsPushRuleEnabledJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Get, QStringLiteral("IsPushRuleEnabledJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId, "/enabled")) { addExpectedKey("enabled"); @@ -100,12 +100,12 @@ SetPushRuleEnabledJob::SetPushRuleEnabledJob(const QString& scope, const QString& kind, const QString& ruleId, bool enabled) : BaseJob(HttpVerb::Put, QStringLiteral("SetPushRuleEnabledJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId, "/enabled")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("enabled"), enabled); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("enabled"), enabled); + setRequestData({ _dataJson }); } QUrl GetPushRuleActionsJob::makeRequestUrl(QUrl baseUrl, const QString& scope, @@ -113,7 +113,7 @@ QUrl GetPushRuleActionsJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/pushrules/", + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId, "/actions")); } @@ -122,7 +122,7 @@ GetPushRuleActionsJob::GetPushRuleActionsJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Get, QStringLiteral("GetPushRuleActionsJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId, "/actions")) { addExpectedKey("actions"); @@ -133,10 +133,10 @@ SetPushRuleActionsJob::SetPushRuleActionsJob(const QString& scope, const QString& ruleId, const QVector<QVariant>& actions) : BaseJob(HttpVerb::Put, QStringLiteral("SetPushRuleActionsJob"), - makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + makePath("/_matrix/client/v3", "/pushrules/", scope, "/", kind, "/", ruleId, "/actions")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("actions"), actions); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("actions"), actions); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/read_markers.cpp b/lib/csapi/read_markers.cpp index f2edb71e..de5f4a9a 100644 --- a/lib/csapi/read_markers.cpp +++ b/lib/csapi/read_markers.cpp @@ -10,10 +10,10 @@ SetReadMarkerJob::SetReadMarkerJob(const QString& roomId, const QString& mFullyRead, const QString& mRead) : BaseJob(HttpVerb::Post, QStringLiteral("SetReadMarkerJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/read_markers")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/read_markers")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("m.fully_read"), mFullyRead); - addParam<IfNotEmpty>(_data, QStringLiteral("m.read"), mRead); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("m.fully_read"), mFullyRead); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("m.read"), mRead); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/receipts.cpp b/lib/csapi/receipts.cpp index 401c3bfe..0194603d 100644 --- a/lib/csapi/receipts.cpp +++ b/lib/csapi/receipts.cpp @@ -10,8 +10,8 @@ PostReceiptJob::PostReceiptJob(const QString& roomId, const QString& receiptType const QString& eventId, const QJsonObject& receipt) : BaseJob(HttpVerb::Post, QStringLiteral("PostReceiptJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/receipt/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/receipt/", receiptType, "/", eventId)) { - setRequestData(RequestData(toJson(receipt))); + setRequestData({ toJson(receipt) }); } diff --git a/lib/csapi/redaction.cpp b/lib/csapi/redaction.cpp index acf1b0e4..154abd9b 100644 --- a/lib/csapi/redaction.cpp +++ b/lib/csapi/redaction.cpp @@ -9,10 +9,10 @@ using namespace Quotient; RedactEventJob::RedactEventJob(const QString& roomId, const QString& eventId, const QString& txnId, const QString& reason) : BaseJob(HttpVerb::Put, QStringLiteral("RedactEventJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/redact/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/redact/", eventId, "/", txnId)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/refresh.cpp b/lib/csapi/refresh.cpp new file mode 100644 index 00000000..284ae4ff --- /dev/null +++ b/lib/csapi/refresh.cpp @@ -0,0 +1,18 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "refresh.h" + +using namespace Quotient; + +RefreshJob::RefreshJob(const QString& refreshToken) + : BaseJob(HttpVerb::Post, QStringLiteral("RefreshJob"), + makePath("/_matrix/client/v3", "/refresh"), false) +{ + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("refresh_token"), + refreshToken); + setRequestData({ _dataJson }); + addExpectedKey("access_token"); +} diff --git a/lib/csapi/refresh.h b/lib/csapi/refresh.h new file mode 100644 index 00000000..d432802c --- /dev/null +++ b/lib/csapi/refresh.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + +namespace Quotient { + +/*! \brief Refresh an access token + * + * Refresh an access token. Clients should use the returned access token + * when making subsequent API calls, and store the returned refresh token + * (if given) in order to refresh the new access token when necessary. + * + * After an access token has been refreshed, a server can choose to + * invalidate the old access token immediately, or can choose not to, for + * example if the access token would expire soon anyways. Clients should + * not make any assumptions about the old access token still being valid, + * and should use the newly provided access token instead. + * + * The old refresh token remains valid until the new access token or refresh + * token is used, at which point the old refresh token is revoked. + * + * Note that this endpoint does not require authentication via an + * access token. Authentication is provided via the refresh token. + * + * Application Service identity assertion is disabled for this endpoint. + */ +class QUOTIENT_API RefreshJob : public BaseJob { +public: + /*! \brief Refresh an access token + * + * \param refreshToken + * The refresh token + */ + explicit RefreshJob(const QString& refreshToken = {}); + + // Result properties + + /// The new access token to use. + QString accessToken() const + { + return loadFromJson<QString>("access_token"_ls); + } + + /// The new refresh token to use when the access token needs to + /// be refreshed again. If not given, the old refresh token can + /// be re-used. + QString refreshToken() const + { + return loadFromJson<QString>("refresh_token"_ls); + } + + /// The lifetime of the access token, in milliseconds. If not + /// given, the client can assume that the access token will not + /// expire. + Omittable<int> expiresInMs() const + { + return loadFromJson<Omittable<int>>("expires_in_ms"_ls); + } +}; + +} // namespace Quotient diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index 153abcee..04c0fe12 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -18,85 +18,91 @@ RegisterJob::RegisterJob(const QString& kind, const QString& username, const QString& password, const QString& deviceId, const QString& initialDeviceDisplayName, - Omittable<bool> inhibitLogin) + Omittable<bool> inhibitLogin, + Omittable<bool> refreshToken) : BaseJob(HttpVerb::Post, QStringLiteral("RegisterJob"), - makePath("/_matrix/client/r0", "/register"), + makePath("/_matrix/client/v3", "/register"), queryToRegister(kind), {}, false) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth); - addParam<IfNotEmpty>(_data, QStringLiteral("username"), username); - addParam<IfNotEmpty>(_data, QStringLiteral("password"), password); - addParam<IfNotEmpty>(_data, QStringLiteral("device_id"), deviceId); - addParam<IfNotEmpty>(_data, QStringLiteral("initial_device_display_name"), + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("username"), username); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("password"), password); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("device_id"), deviceId); + addParam<IfNotEmpty>(_dataJson, + QStringLiteral("initial_device_display_name"), initialDeviceDisplayName); - addParam<IfNotEmpty>(_data, QStringLiteral("inhibit_login"), inhibitLogin); - setRequestData(std::move(_data)); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("inhibit_login"), + inhibitLogin); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("refresh_token"), + refreshToken); + setRequestData({ _dataJson }); addExpectedKey("user_id"); } RequestTokenToRegisterEmailJob::RequestTokenToRegisterEmailJob( const EmailValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToRegisterEmailJob"), - makePath("/_matrix/client/r0", "/register/email/requestToken"), + makePath("/_matrix/client/v3", "/register/email/requestToken"), false) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } RequestTokenToRegisterMSISDNJob::RequestTokenToRegisterMSISDNJob( const MsisdnValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToRegisterMSISDNJob"), - makePath("/_matrix/client/r0", "/register/msisdn/requestToken"), + makePath("/_matrix/client/v3", "/register/msisdn/requestToken"), false) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } ChangePasswordJob::ChangePasswordJob(const QString& newPassword, bool logoutDevices, const Omittable<AuthenticationData>& auth) : BaseJob(HttpVerb::Post, QStringLiteral("ChangePasswordJob"), - makePath("/_matrix/client/r0", "/account/password")) + makePath("/_matrix/client/v3", "/account/password")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("new_password"), newPassword); - addParam<IfNotEmpty>(_data, QStringLiteral("logout_devices"), logoutDevices); - addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("new_password"), newPassword); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("logout_devices"), + logoutDevices); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + setRequestData({ _dataJson }); } RequestTokenToResetPasswordEmailJob::RequestTokenToResetPasswordEmailJob( const EmailValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToResetPasswordEmailJob"), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/account/password/email/requestToken"), false) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob( const MsisdnValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToResetPasswordMSISDNJob"), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/account/password/msisdn/requestToken"), false) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); } DeactivateAccountJob::DeactivateAccountJob( const Omittable<AuthenticationData>& auth, const QString& idServer) : BaseJob(HttpVerb::Post, QStringLiteral("DeactivateAccountJob"), - makePath("/_matrix/client/r0", "/account/deactivate")) + makePath("/_matrix/client/v3", "/account/deactivate")) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth); - addParam<IfNotEmpty>(_data, QStringLiteral("id_server"), idServer); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("auth"), auth); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("id_server"), idServer); + setRequestData({ _dataJson }); addExpectedKey("id_server_unbind_result"); } @@ -111,13 +117,14 @@ QUrl CheckUsernameAvailabilityJob::makeRequestUrl(QUrl baseUrl, const QString& username) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/register/available"), queryToCheckUsernameAvailability(username)); } -CheckUsernameAvailabilityJob::CheckUsernameAvailabilityJob(const QString& username) +CheckUsernameAvailabilityJob::CheckUsernameAvailabilityJob( + const QString& username) : BaseJob(HttpVerb::Get, QStringLiteral("CheckUsernameAvailabilityJob"), - makePath("/_matrix/client/r0", "/register/available"), + makePath("/_matrix/client/v3", "/register/available"), queryToCheckUsernameAvailability(username), {}, false) {} diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h index 10375971..21d7f9d7 100644 --- a/lib/csapi/registration.h +++ b/lib/csapi/registration.h @@ -93,6 +93,9 @@ public: * If true, an `access_token` and `device_id` should not be * returned from this call, therefore preventing an automatic * login. Defaults to false. + * + * \param refreshToken + * If true, the client supports refresh tokens. */ explicit RegisterJob(const QString& kind = QStringLiteral("user"), const Omittable<AuthenticationData>& auth = none, @@ -100,7 +103,8 @@ public: const QString& password = {}, const QString& deviceId = {}, const QString& initialDeviceDisplayName = {}, - Omittable<bool> inhibitLogin = none); + Omittable<bool> inhibitLogin = none, + Omittable<bool> refreshToken = none); // Result properties @@ -118,15 +122,27 @@ public: return loadFromJson<QString>("access_token"_ls); } - /// The server_name of the homeserver on which the account has - /// been registered. + /// A refresh token for the account. This token can be used to + /// obtain a new access token when it expires by calling the + /// `/refresh` endpoint. + /// + /// Omitted if the `inhibit_login` option is true. + QString refreshToken() const + { + return loadFromJson<QString>("refresh_token"_ls); + } + + /// The lifetime of the access token, in milliseconds. Once + /// the access token has expired a new access token can be + /// obtained by using the provided refresh token. If no + /// refresh token is provided, the client will need to re-log in + /// to obtain a new access token. If not given, the client can + /// assume that the access token will not expire. /// - /// **Deprecated**. Clients should extract the server_name from - /// `user_id` (by splitting at the first colon) if they require - /// it. Note also that `homeserver` is not spelt this way. - QString homeServer() const + /// Omitted if the `inhibit_login` option is true. + Omittable<int> expiresInMs() const { - return loadFromJson<QString>("home_server"_ls); + return loadFromJson<Omittable<int>>("expires_in_ms"_ls); } /// ID of the registered device. Will be the same as the @@ -227,7 +243,8 @@ public: * should be revoked if the request succeeds. * * When `false`, the server can still take advantage of the [soft logout - * method](/client-server-api/#soft-logout) for the user's remaining devices. + * method](/client-server-api/#soft-logout) for the user's remaining + * devices. * * \param auth * Additional authentication information for the user-interactive @@ -247,7 +264,7 @@ public: * `/account/password` endpoint. * * This API's parameters and response are identical to that of the - * [`/register/email/requestToken`](/client-server-api/#post_matrixclientr0registeremailrequesttoken) + * [`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken) * 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 @@ -269,7 +286,7 @@ public: * `/account/password` endpoint. * * This API's parameters and response are identical to that of the - * [`/register/email/requestToken`](/client-server-api/#post_matrixclientr0registeremailrequesttoken) + * [`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken) * 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 @@ -299,7 +316,7 @@ public: * `/account/password` endpoint. * * This API's parameters and response are identical to that of the - * [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + * [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) * 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 @@ -321,15 +338,16 @@ public: * `/account/password` endpoint. * * This API's parameters and response are identical to that of the - * [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + * [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) * 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. + * The homeserver should validate the phone number itself, either by + * sending a validation message itself or by using a service it has control + * over. */ explicit RequestTokenToResetPasswordMSISDNJob( const MsisdnValidationData& body); @@ -377,8 +395,9 @@ public: * it must return an `id_server_unbind_result` of * `no-support`. */ - explicit DeactivateAccountJob(const Omittable<AuthenticationData>& auth = none, - const QString& idServer = {}); + explicit DeactivateAccountJob( + const Omittable<AuthenticationData>& auth = none, + const QString& idServer = {}); // Result properties diff --git a/lib/csapi/registration_tokens.cpp b/lib/csapi/registration_tokens.cpp new file mode 100644 index 00000000..9c1f0587 --- /dev/null +++ b/lib/csapi/registration_tokens.cpp @@ -0,0 +1,33 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "registration_tokens.h" + +using namespace Quotient; + +auto queryToRegistrationTokenValidity(const QString& token) +{ + QUrlQuery _q; + addParam<>(_q, QStringLiteral("token"), token); + return _q; +} + +QUrl RegistrationTokenValidityJob::makeRequestUrl(QUrl baseUrl, + const QString& token) +{ + return BaseJob::makeRequestUrl( + std::move(baseUrl), + makePath("/_matrix/client/v1", + "/register/m.login.registration_token/validity"), + queryToRegistrationTokenValidity(token)); +} + +RegistrationTokenValidityJob::RegistrationTokenValidityJob(const QString& token) + : BaseJob(HttpVerb::Get, QStringLiteral("RegistrationTokenValidityJob"), + makePath("/_matrix/client/v1", + "/register/m.login.registration_token/validity"), + queryToRegistrationTokenValidity(token), {}, false) +{ + addExpectedKey("valid"); +} diff --git a/lib/csapi/registration_tokens.h b/lib/csapi/registration_tokens.h new file mode 100644 index 00000000..e3008dd4 --- /dev/null +++ b/lib/csapi/registration_tokens.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + +namespace Quotient { + +/*! \brief Query if a given registration token is still valid. + * + * Queries the server to determine if a given registration token is still + * valid at the time of request. This is a point-in-time check where the + * token might still expire by the time it is used. + * + * Servers should be sure to rate limit this endpoint to avoid brute force + * attacks. + */ +class QUOTIENT_API RegistrationTokenValidityJob : public BaseJob { +public: + /*! \brief Query if a given registration token is still valid. + * + * \param token + * The token to check validity of. + */ + explicit RegistrationTokenValidityJob(const QString& token); + + /*! \brief Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for RegistrationTokenValidityJob + * is necessary but the job itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& token); + + // Result properties + + /// True if the token is still valid, false otherwise. This should + /// additionally be false if the token is not a recognised token by + /// the server. + bool valid() const { return loadFromJson<bool>("valid"_ls); } +}; + +} // namespace Quotient diff --git a/lib/csapi/relations.cpp b/lib/csapi/relations.cpp new file mode 100644 index 00000000..8bcecee4 --- /dev/null +++ b/lib/csapi/relations.cpp @@ -0,0 +1,111 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "relations.h" + +using namespace Quotient; + +auto queryToGetRelatingEvents(const QString& from, const QString& to, + Omittable<int> limit) +{ + QUrlQuery _q; + addParam<IfNotEmpty>(_q, QStringLiteral("from"), from); + addParam<IfNotEmpty>(_q, QStringLiteral("to"), to); + addParam<IfNotEmpty>(_q, QStringLiteral("limit"), limit); + return _q; +} + +QUrl GetRelatingEventsJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, + const QString& eventId, + const QString& from, const QString& to, + Omittable<int> limit) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + makePath("/_matrix/client/v1", "/rooms/", + roomId, "/relations/", eventId), + queryToGetRelatingEvents(from, to, limit)); +} + +GetRelatingEventsJob::GetRelatingEventsJob(const QString& roomId, + const QString& eventId, + const QString& from, + const QString& to, + Omittable<int> limit) + : BaseJob(HttpVerb::Get, QStringLiteral("GetRelatingEventsJob"), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/relations/", + eventId), + queryToGetRelatingEvents(from, to, limit)) +{ + addExpectedKey("chunk"); +} + +auto queryToGetRelatingEventsWithRelType(const QString& from, const QString& to, + Omittable<int> limit) +{ + QUrlQuery _q; + addParam<IfNotEmpty>(_q, QStringLiteral("from"), from); + addParam<IfNotEmpty>(_q, QStringLiteral("to"), to); + addParam<IfNotEmpty>(_q, QStringLiteral("limit"), limit); + return _q; +} + +QUrl GetRelatingEventsWithRelTypeJob::makeRequestUrl( + QUrl baseUrl, const QString& roomId, const QString& eventId, + const QString& relType, const QString& from, const QString& to, + Omittable<int> limit) +{ + return BaseJob::makeRequestUrl( + std::move(baseUrl), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/relations/", + eventId, "/", relType), + queryToGetRelatingEventsWithRelType(from, to, limit)); +} + +GetRelatingEventsWithRelTypeJob::GetRelatingEventsWithRelTypeJob( + const QString& roomId, const QString& eventId, const QString& relType, + const QString& from, const QString& to, Omittable<int> limit) + : BaseJob(HttpVerb::Get, QStringLiteral("GetRelatingEventsWithRelTypeJob"), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/relations/", + eventId, "/", relType), + queryToGetRelatingEventsWithRelType(from, to, limit)) +{ + addExpectedKey("chunk"); +} + +auto queryToGetRelatingEventsWithRelTypeAndEventType(const QString& from, + const QString& to, + Omittable<int> limit) +{ + QUrlQuery _q; + addParam<IfNotEmpty>(_q, QStringLiteral("from"), from); + addParam<IfNotEmpty>(_q, QStringLiteral("to"), to); + addParam<IfNotEmpty>(_q, QStringLiteral("limit"), limit); + return _q; +} + +QUrl GetRelatingEventsWithRelTypeAndEventTypeJob::makeRequestUrl( + QUrl baseUrl, const QString& roomId, const QString& eventId, + const QString& relType, const QString& eventType, const QString& from, + const QString& to, Omittable<int> limit) +{ + return BaseJob::makeRequestUrl( + std::move(baseUrl), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/relations/", + eventId, "/", relType, "/", eventType), + queryToGetRelatingEventsWithRelTypeAndEventType(from, to, limit)); +} + +GetRelatingEventsWithRelTypeAndEventTypeJob:: + GetRelatingEventsWithRelTypeAndEventTypeJob( + const QString& roomId, const QString& eventId, const QString& relType, + const QString& eventType, const QString& from, const QString& to, + Omittable<int> limit) + : BaseJob(HttpVerb::Get, + QStringLiteral("GetRelatingEventsWithRelTypeAndEventTypeJob"), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/relations/", + eventId, "/", relType, "/", eventType), + queryToGetRelatingEventsWithRelTypeAndEventType(from, to, limit)) +{ + addExpectedKey("chunk"); +} diff --git a/lib/csapi/relations.h b/lib/csapi/relations.h new file mode 100644 index 00000000..985a43b5 --- /dev/null +++ b/lib/csapi/relations.h @@ -0,0 +1,277 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "events/eventloader.h" +#include "jobs/basejob.h" + +namespace Quotient { + +/*! \brief Get the child events for a given parent event. + * + * Retrieve all of the child events for a given parent event. + * + * Note that when paginating the `from` token should be "after" the `to` token + * in terms of topological ordering, because it is only possible to paginate + * "backwards" through events, starting at `from`. + * + * For example, passing a `from` token from page 2 of the results, and a `to` + * token from page 1, would return the empty set. The caller can use a `from` + * token from page 1 and a `to` token from page 2 to paginate over the same + * range, however. + */ +class QUOTIENT_API GetRelatingEventsJob : public BaseJob { +public: + /*! \brief Get the child events for a given parent event. + * + * \param roomId + * The ID of the room containing the parent event. + * + * \param eventId + * The ID of the parent event whose child events are to be returned. + * + * \param from + * The pagination token to start returning results from. If not supplied, + * results start at the most recent topological event known to the server. + * + * Can be a `next_batch` token from a previous call, or a returned + * `start` token from + * [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages), + * or a `next_batch` token from + * [`/sync`](/client-server-api/#get_matrixclientv3sync). + * + * \param to + * The pagination token to stop returning results at. If not supplied, + * results continue up to `limit` or until there are no more events. + * + * Like `from`, this can be a previous token from a prior call to this + * endpoint or from `/messages` or `/sync`. + * + * \param limit + * The maximum number of results to return in a single `chunk`. The server + * can and should apply a maximum value to this parameter to avoid large + * responses. + * + * Similarly, the server should apply a default value when not supplied. + */ + explicit GetRelatingEventsJob(const QString& roomId, const QString& eventId, + const QString& from = {}, + const QString& to = {}, + Omittable<int> limit = none); + + /*! \brief Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for GetRelatingEventsJob + * is necessary but the job itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, + const QString& eventId, const QString& from = {}, + const QString& to = {}, + Omittable<int> limit = none); + + // Result properties + + /// The child events of the requested event, ordered topologically + /// most-recent first. + RoomEvents chunk() { return takeFromJson<RoomEvents>("chunk"_ls); } + + /// An opaque string representing a pagination token. The absence of this + /// token means there are no more results to fetch and the client should + /// stop paginating. + QString nextBatch() const { return loadFromJson<QString>("next_batch"_ls); } + + /// An opaque string representing a pagination token. The absence of this + /// token means this is the start of the result set, i.e. this is the first + /// batch/page. + QString prevBatch() const { return loadFromJson<QString>("prev_batch"_ls); } +}; + +/*! \brief Get the child events for a given parent event, with a given + * `relType`. + * + * Retrieve all of the child events for a given parent event which relate to the + * parent using the given `relType`. + * + * Note that when paginating the `from` token should be "after" the `to` token + * in terms of topological ordering, because it is only possible to paginate + * "backwards" through events, starting at `from`. + * + * For example, passing a `from` token from page 2 of the results, and a `to` + * token from page 1, would return the empty set. The caller can use a `from` + * token from page 1 and a `to` token from page 2 to paginate over the same + * range, however. + */ +class QUOTIENT_API GetRelatingEventsWithRelTypeJob : public BaseJob { +public: + /*! \brief Get the child events for a given parent event, with a given + * `relType`. + * + * \param roomId + * The ID of the room containing the parent event. + * + * \param eventId + * The ID of the parent event whose child events are to be returned. + * + * \param relType + * The [relationship type](/client-server-api/#relationship-types) to + * search for. + * + * \param from + * The pagination token to start returning results from. If not supplied, + * results start at the most recent topological event known to the server. + * + * Can be a `next_batch` token from a previous call, or a returned + * `start` token from + * [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages), + * or a `next_batch` token from + * [`/sync`](/client-server-api/#get_matrixclientv3sync). + * + * \param to + * The pagination token to stop returning results at. If not supplied, + * results continue up to `limit` or until there are no more events. + * + * Like `from`, this can be a previous token from a prior call to this + * endpoint or from `/messages` or `/sync`. + * + * \param limit + * The maximum number of results to return in a single `chunk`. The server + * can and should apply a maximum value to this parameter to avoid large + * responses. + * + * Similarly, the server should apply a default value when not supplied. + */ + explicit GetRelatingEventsWithRelTypeJob(const QString& roomId, + const QString& eventId, + const QString& relType, + const QString& from = {}, + const QString& to = {}, + Omittable<int> limit = none); + + /*! \brief Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for GetRelatingEventsWithRelTypeJob + * is necessary but the job itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, + const QString& eventId, const QString& relType, + const QString& from = {}, const QString& to = {}, + Omittable<int> limit = none); + + // Result properties + + /// The child events of the requested event, ordered topologically + /// most-recent first. The events returned will match the `relType` + /// supplied in the URL. + RoomEvents chunk() { return takeFromJson<RoomEvents>("chunk"_ls); } + + /// An opaque string representing a pagination token. The absence of this + /// token means there are no more results to fetch and the client should + /// stop paginating. + QString nextBatch() const { return loadFromJson<QString>("next_batch"_ls); } + + /// An opaque string representing a pagination token. The absence of this + /// token means this is the start of the result set, i.e. this is the first + /// batch/page. + QString prevBatch() const { return loadFromJson<QString>("prev_batch"_ls); } +}; + +/*! \brief Get the child events for a given parent event, with a given `relType` + * and `eventType`. + * + * Retrieve all of the child events for a given parent event which relate to the + * parent using the given `relType` and have the given `eventType`. + * + * Note that when paginating the `from` token should be "after" the `to` token + * in terms of topological ordering, because it is only possible to paginate + * "backwards" through events, starting at `from`. + * + * For example, passing a `from` token from page 2 of the results, and a `to` + * token from page 1, would return the empty set. The caller can use a `from` + * token from page 1 and a `to` token from page 2 to paginate over the same + * range, however. + */ +class QUOTIENT_API GetRelatingEventsWithRelTypeAndEventTypeJob + : public BaseJob { +public: + /*! \brief Get the child events for a given parent event, with a given + * `relType` and `eventType`. + * + * \param roomId + * The ID of the room containing the parent event. + * + * \param eventId + * The ID of the parent event whose child events are to be returned. + * + * \param relType + * The [relationship type](/client-server-api/#relationship-types) to + * search for. + * + * \param eventType + * The event type of child events to search for. + * + * Note that in encrypted rooms this will typically always be + * `m.room.encrypted` regardless of the event type contained within the + * encrypted payload. + * + * \param from + * The pagination token to start returning results from. If not supplied, + * results start at the most recent topological event known to the server. + * + * Can be a `next_batch` token from a previous call, or a returned + * `start` token from + * [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages), + * or a `next_batch` token from + * [`/sync`](/client-server-api/#get_matrixclientv3sync). + * + * \param to + * The pagination token to stop returning results at. If not supplied, + * results continue up to `limit` or until there are no more events. + * + * Like `from`, this can be a previous token from a prior call to this + * endpoint or from `/messages` or `/sync`. + * + * \param limit + * The maximum number of results to return in a single `chunk`. The server + * can and should apply a maximum value to this parameter to avoid large + * responses. + * + * Similarly, the server should apply a default value when not supplied. + */ + explicit GetRelatingEventsWithRelTypeAndEventTypeJob( + const QString& roomId, const QString& eventId, const QString& relType, + const QString& eventType, const QString& from = {}, + const QString& to = {}, Omittable<int> limit = none); + + /*! \brief Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for + * GetRelatingEventsWithRelTypeAndEventTypeJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, + const QString& eventId, const QString& relType, + const QString& eventType, + const QString& from = {}, const QString& to = {}, + Omittable<int> limit = none); + + // Result properties + + /// The child events of the requested event, ordered topologically + /// most-recent first. The events returned will match the `relType` and + /// `eventType` supplied in the URL. + RoomEvents chunk() { return takeFromJson<RoomEvents>("chunk"_ls); } + + /// An opaque string representing a pagination token. The absence of this + /// token means there are no more results to fetch and the client should + /// stop paginating. + QString nextBatch() const { return loadFromJson<QString>("next_batch"_ls); } + + /// An opaque string representing a pagination token. The absence of this + /// token means this is the start of the result set, i.e. this is the first + /// batch/page. + QString prevBatch() const { return loadFromJson<QString>("prev_batch"_ls); } +}; + +} // namespace Quotient diff --git a/lib/csapi/report_content.cpp b/lib/csapi/report_content.cpp index 0a76d5b8..bc52208f 100644 --- a/lib/csapi/report_content.cpp +++ b/lib/csapi/report_content.cpp @@ -9,11 +9,11 @@ using namespace Quotient; ReportContentJob::ReportContentJob(const QString& roomId, const QString& eventId, Omittable<int> score, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("ReportContentJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/report/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/report/", eventId)) { - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("score"), score); - addParam<IfNotEmpty>(_data, QStringLiteral("reason"), reason); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<IfNotEmpty>(_dataJson, QStringLiteral("score"), score); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("reason"), reason); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/room_send.cpp b/lib/csapi/room_send.cpp index f80f9300..2319496f 100644 --- a/lib/csapi/room_send.cpp +++ b/lib/csapi/room_send.cpp @@ -9,9 +9,9 @@ using namespace Quotient; SendMessageJob::SendMessageJob(const QString& roomId, const QString& eventType, const QString& txnId, const QJsonObject& body) : BaseJob(HttpVerb::Put, QStringLiteral("SendMessageJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/send/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/send/", eventType, "/", txnId)) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); addExpectedKey("event_id"); } diff --git a/lib/csapi/room_send.h b/lib/csapi/room_send.h index fea3d59d..fcb6b24f 100644 --- a/lib/csapi/room_send.h +++ b/lib/csapi/room_send.h @@ -16,7 +16,8 @@ namespace Quotient { * * The body of the request should be the content object of the event; the * fields in this object will vary depending on the type of event. See - * [Room Events](/client-server-api/#room-events) for the m. event specification. + * [Room Events](/client-server-api/#room-events) for the m. event + * specification. */ class QUOTIENT_API SendMessageJob : public BaseJob { public: diff --git a/lib/csapi/room_state.cpp b/lib/csapi/room_state.cpp index f6d2e6ec..b4adb739 100644 --- a/lib/csapi/room_state.cpp +++ b/lib/csapi/room_state.cpp @@ -11,9 +11,9 @@ SetRoomStateWithKeyJob::SetRoomStateWithKeyJob(const QString& roomId, const QString& stateKey, const QJsonObject& body) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomStateWithKeyJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/state/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/state/", eventType, "/", stateKey)) { - setRequestData(RequestData(toJson(body))); + setRequestData({ toJson(body) }); addExpectedKey("event_id"); } diff --git a/lib/csapi/room_upgrades.cpp b/lib/csapi/room_upgrades.cpp index d4129cfb..b03fb6e8 100644 --- a/lib/csapi/room_upgrades.cpp +++ b/lib/csapi/room_upgrades.cpp @@ -8,10 +8,10 @@ using namespace Quotient; UpgradeRoomJob::UpgradeRoomJob(const QString& roomId, const QString& newVersion) : BaseJob(HttpVerb::Post, QStringLiteral("UpgradeRoomJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/upgrade")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/upgrade")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("new_version"), newVersion); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("new_version"), newVersion); + setRequestData({ _dataJson }); addExpectedKey("replacement_room"); } diff --git a/lib/csapi/rooms.cpp b/lib/csapi/rooms.cpp index 5310aa32..563f4fa5 100644 --- a/lib/csapi/rooms.cpp +++ b/lib/csapi/rooms.cpp @@ -10,14 +10,14 @@ QUrl GetOneRoomEventJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& eventId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/event/", eventId)); } GetOneRoomEventJob::GetOneRoomEventJob(const QString& roomId, const QString& eventId) : BaseJob(HttpVerb::Get, QStringLiteral("GetOneRoomEventJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/event/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/event/", eventId)) {} @@ -26,7 +26,7 @@ QUrl GetRoomStateWithKeyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& stateKey) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/state/", eventType, "/", stateKey)); } @@ -35,20 +35,20 @@ GetRoomStateWithKeyJob::GetRoomStateWithKeyJob(const QString& roomId, const QString& eventType, const QString& stateKey) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomStateWithKeyJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/state/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/state/", eventType, "/", stateKey)) {} QUrl GetRoomStateJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/state")); } GetRoomStateJob::GetRoomStateJob(const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomStateJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/state")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/state")) {} auto queryToGetMembersByRoom(const QString& at, const QString& membership, @@ -68,7 +68,7 @@ QUrl GetMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, { return BaseJob::makeRequestUrl( std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/members"), + makePath("/_matrix/client/v3", "/rooms/", roomId, "/members"), queryToGetMembersByRoom(at, membership, notMembership)); } @@ -77,7 +77,7 @@ GetMembersByRoomJob::GetMembersByRoomJob(const QString& roomId, const QString& membership, const QString& notMembership) : BaseJob(HttpVerb::Get, QStringLiteral("GetMembersByRoomJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/members"), + makePath("/_matrix/client/v3", "/rooms/", roomId, "/members"), queryToGetMembersByRoom(at, membership, notMembership)) {} @@ -85,12 +85,12 @@ QUrl GetJoinedMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/rooms/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/joined_members")); } GetJoinedMembersByRoomJob::GetJoinedMembersByRoomJob(const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetJoinedMembersByRoomJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, + makePath("/_matrix/client/v3", "/rooms/", roomId, "/joined_members")) {} diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h index f0815109..247fb13f 100644 --- a/lib/csapi/rooms.h +++ b/lib/csapi/rooms.h @@ -5,7 +5,6 @@ #pragma once #include "events/eventloader.h" -#include "events/roommemberevent.h" #include "jobs/basejob.h" namespace Quotient { @@ -38,7 +37,7 @@ public: // Result properties /// The full event. - EventPtr event() { return fromJson<EventPtr>(jsonData()); } + RoomEventPtr event() { return fromJson<RoomEventPtr>(jsonData()); } }; /*! \brief Get the state identified by the type and key. @@ -146,10 +145,7 @@ public: // Result properties /// Get the list of members for this room. - EventsArray<RoomMemberEvent> chunk() - { - return takeFromJson<EventsArray<RoomMemberEvent>>("chunk"_ls); - } + StateEvents chunk() { return takeFromJson<StateEvents>("chunk"_ls); } }; /*! \brief Gets the list of currently joined users and their profile data. @@ -157,9 +153,8 @@ public: * This API returns a map of MXIDs to member info objects for members of the * room. The current user must be in the room for it to work, unless it is an * Application Service in which case any of the AS's users must be in the room. - * This API is primarily for Application Services and should be faster to - * respond than `/members` as it can be implemented more efficiently on the - * server. + * This API is primarily for Application Services and should be faster to respond + * than `/members` as it can be implemented more efficiently on the server. */ class QUOTIENT_API GetJoinedMembersByRoomJob : public BaseJob { public: diff --git a/lib/csapi/search.cpp b/lib/csapi/search.cpp index 295dd1cc..4e2c9e92 100644 --- a/lib/csapi/search.cpp +++ b/lib/csapi/search.cpp @@ -16,11 +16,11 @@ auto queryToSearch(const QString& nextBatch) SearchJob::SearchJob(const Categories& searchCategories, const QString& nextBatch) : BaseJob(HttpVerb::Post, QStringLiteral("SearchJob"), - makePath("/_matrix/client/r0", "/search"), + makePath("/_matrix/client/v3", "/search"), queryToSearch(nextBatch)) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("search_categories"), searchCategories); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("search_categories"), searchCategories); + setRequestData({ _dataJson }); addExpectedKey("search_categories"); } diff --git a/lib/csapi/space_hierarchy.cpp b/lib/csapi/space_hierarchy.cpp new file mode 100644 index 00000000..7b5c7eac --- /dev/null +++ b/lib/csapi/space_hierarchy.cpp @@ -0,0 +1,43 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "space_hierarchy.h" + +using namespace Quotient; + +auto queryToGetSpaceHierarchy(Omittable<bool> suggestedOnly, + Omittable<int> limit, Omittable<int> maxDepth, + const QString& from) +{ + QUrlQuery _q; + addParam<IfNotEmpty>(_q, QStringLiteral("suggested_only"), suggestedOnly); + addParam<IfNotEmpty>(_q, QStringLiteral("limit"), limit); + addParam<IfNotEmpty>(_q, QStringLiteral("max_depth"), maxDepth); + addParam<IfNotEmpty>(_q, QStringLiteral("from"), from); + return _q; +} + +QUrl GetSpaceHierarchyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, + Omittable<bool> suggestedOnly, + Omittable<int> limit, + Omittable<int> maxDepth, + const QString& from) +{ + return BaseJob::makeRequestUrl( + std::move(baseUrl), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/hierarchy"), + queryToGetSpaceHierarchy(suggestedOnly, limit, maxDepth, from)); +} + +GetSpaceHierarchyJob::GetSpaceHierarchyJob(const QString& roomId, + Omittable<bool> suggestedOnly, + Omittable<int> limit, + Omittable<int> maxDepth, + const QString& from) + : BaseJob(HttpVerb::Get, QStringLiteral("GetSpaceHierarchyJob"), + makePath("/_matrix/client/v1", "/rooms/", roomId, "/hierarchy"), + queryToGetSpaceHierarchy(suggestedOnly, limit, maxDepth, from)) +{ + addExpectedKey("rooms"); +} diff --git a/lib/csapi/space_hierarchy.h b/lib/csapi/space_hierarchy.h new file mode 100644 index 00000000..7a421be8 --- /dev/null +++ b/lib/csapi/space_hierarchy.h @@ -0,0 +1,152 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "events/eventloader.h" +#include "jobs/basejob.h" + +namespace Quotient { + +/*! \brief Retrieve a portion of a space tree. + * + * Paginates over the space tree in a depth-first manner to locate child rooms + * of a given space. + * + * Where a child room is unknown to the local server, federation is used to fill + * in the details. The servers listed in the `via` array should be contacted to + * attempt to fill in missing rooms. + * + * Only [`m.space.child`](#mspacechild) state events of the room are considered. + * Invalid child rooms and parent events are not covered by this endpoint. + */ +class QUOTIENT_API GetSpaceHierarchyJob : public BaseJob { +public: + // Inner data structures + + /// Paginates over the space tree in a depth-first manner to locate child + /// rooms of a given space. + /// + /// Where a child room is unknown to the local server, federation is used to + /// fill in the details. The servers listed in the `via` array should be + /// contacted to attempt to fill in missing rooms. + /// + /// Only [`m.space.child`](#mspacechild) state events of the room are + /// considered. Invalid child rooms and parent events are not covered by + /// this endpoint. + struct ChildRoomsChunk { + /// The canonical alias of the room, if any. + QString canonicalAlias; + /// The name of the room, if any. + QString name; + /// The number of members joined to the room. + int numJoinedMembers; + /// The ID of the room. + QString roomId; + /// The topic of the room, if any. + QString topic; + /// Whether the room may be viewed by guest users without joining. + bool worldReadable; + /// Whether guest users may join the room and participate in it. + /// If they can, they will be subject to ordinary power level + /// rules like any other user. + bool guestCanJoin; + /// The URL for the room's avatar, if one is set. + QUrl avatarUrl; + /// The room's join rule. When not present, the room is assumed to + /// be `public`. + QString joinRule; + /// The `type` of room (from + /// [`m.room.create`](/client-server-api/#mroomcreate)), if any. + QString roomType; + /// The [`m.space.child`](#mspacechild) events of the space-room, + /// represented as [Stripped State Events](#stripped-state) with an + /// added `origin_server_ts` key. + /// + /// If the room is not a space-room, this should be empty. + StateEvents childrenState; + }; + + // Construction/destruction + + /*! \brief Retrieve a portion of a space tree. + * + * \param roomId + * The room ID of the space to get a hierarchy for. + * + * \param suggestedOnly + * Optional (default `false`) flag to indicate whether or not the server + * should only consider suggested rooms. Suggested rooms are annotated in + * their [`m.space.child`](#mspacechild) event contents. + * + * \param limit + * Optional limit for the maximum number of rooms to include per response. + * Must be an integer greater than zero. + * + * Servers should apply a default value, and impose a maximum value to + * avoid resource exhaustion. + * + * \param maxDepth + * Optional limit for how far to go into the space. Must be a non-negative + * integer. + * + * When reached, no further child rooms will be returned. + * + * Servers should apply a default value, and impose a maximum value to + * avoid resource exhaustion. + * + * \param from + * A pagination token from a previous result. If specified, `max_depth` + * and `suggested_only` cannot be changed from the first request. + */ + explicit GetSpaceHierarchyJob(const QString& roomId, + Omittable<bool> suggestedOnly = none, + Omittable<int> limit = none, + Omittable<int> maxDepth = none, + const QString& from = {}); + + /*! \brief Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for GetSpaceHierarchyJob + * is necessary but the job itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, + Omittable<bool> suggestedOnly = none, + Omittable<int> limit = none, + Omittable<int> maxDepth = none, + const QString& from = {}); + + // Result properties + + /// The rooms for the current page, with the current filters. + std::vector<ChildRoomsChunk> rooms() + { + return takeFromJson<std::vector<ChildRoomsChunk>>("rooms"_ls); + } + + /// A token to supply to `from` to keep paginating the responses. Not + /// present when there are no further results. + QString nextBatch() const { return loadFromJson<QString>("next_batch"_ls); } +}; + +template <> +struct JsonObjectConverter<GetSpaceHierarchyJob::ChildRoomsChunk> { + static void fillFrom(const QJsonObject& jo, + GetSpaceHierarchyJob::ChildRoomsChunk& result) + { + fromJson(jo.value("canonical_alias"_ls), result.canonicalAlias); + fromJson(jo.value("name"_ls), result.name); + fromJson(jo.value("num_joined_members"_ls), result.numJoinedMembers); + fromJson(jo.value("room_id"_ls), result.roomId); + fromJson(jo.value("topic"_ls), result.topic); + fromJson(jo.value("world_readable"_ls), result.worldReadable); + fromJson(jo.value("guest_can_join"_ls), result.guestCanJoin); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); + fromJson(jo.value("join_rule"_ls), result.joinRule); + fromJson(jo.value("room_type"_ls), result.roomType); + fromJson(jo.value("children_state"_ls), result.childrenState); + } +}; + +} // namespace Quotient diff --git a/lib/csapi/sso_login_redirect.cpp b/lib/csapi/sso_login_redirect.cpp index 871d6ff6..71f8147c 100644 --- a/lib/csapi/sso_login_redirect.cpp +++ b/lib/csapi/sso_login_redirect.cpp @@ -16,14 +16,14 @@ auto queryToRedirectToSSO(const QString& redirectUrl) QUrl RedirectToSSOJob::makeRequestUrl(QUrl baseUrl, const QString& redirectUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/login/sso/redirect"), queryToRedirectToSSO(redirectUrl)); } RedirectToSSOJob::RedirectToSSOJob(const QString& redirectUrl) : BaseJob(HttpVerb::Get, QStringLiteral("RedirectToSSOJob"), - makePath("/_matrix/client/r0", "/login/sso/redirect"), + makePath("/_matrix/client/v3", "/login/sso/redirect"), queryToRedirectToSSO(redirectUrl), {}, false) {} @@ -38,7 +38,7 @@ QUrl RedirectToIdPJob::makeRequestUrl(QUrl baseUrl, const QString& idpId, const QString& redirectUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/login/sso/redirect/", idpId), queryToRedirectToIdP(redirectUrl)); } @@ -46,6 +46,6 @@ QUrl RedirectToIdPJob::makeRequestUrl(QUrl baseUrl, const QString& idpId, RedirectToIdPJob::RedirectToIdPJob(const QString& idpId, const QString& redirectUrl) : BaseJob(HttpVerb::Get, QStringLiteral("RedirectToIdPJob"), - makePath("/_matrix/client/r0", "/login/sso/redirect/", idpId), + makePath("/_matrix/client/v3", "/login/sso/redirect/", idpId), queryToRedirectToIdP(redirectUrl), {}, false) {} diff --git a/lib/csapi/tags.cpp b/lib/csapi/tags.cpp index f717de6e..2c85842d 100644 --- a/lib/csapi/tags.cpp +++ b/lib/csapi/tags.cpp @@ -10,13 +10,13 @@ QUrl GetRoomTagsJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/user/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/tags")); } GetRoomTagsJob::GetRoomTagsJob(const QString& userId, const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomTagsJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/tags")) {} @@ -24,20 +24,20 @@ SetRoomTagJob::SetRoomTagJob(const QString& userId, const QString& roomId, const QString& tag, Omittable<float> order, const QVariantHash& additionalProperties) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomTagJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/tags/", tag)) { - QJsonObject _data; - fillJson(_data, additionalProperties); - addParam<IfNotEmpty>(_data, QStringLiteral("order"), order); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + fillJson(_dataJson, additionalProperties); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("order"), order); + setRequestData({ _dataJson }); } QUrl DeleteRoomTagJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId, const QString& tag) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", "/user/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/tags/", tag)); } @@ -45,6 +45,6 @@ QUrl DeleteRoomTagJob::makeRequestUrl(QUrl baseUrl, const QString& userId, DeleteRoomTagJob::DeleteRoomTagJob(const QString& userId, const QString& roomId, const QString& tag) : BaseJob(HttpVerb::Delete, QStringLiteral("DeleteRoomTagJob"), - makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + makePath("/_matrix/client/v3", "/user/", userId, "/rooms/", roomId, "/tags/", tag)) {} diff --git a/lib/csapi/third_party_lookup.cpp b/lib/csapi/third_party_lookup.cpp index 4c930668..1e5870ce 100644 --- a/lib/csapi/third_party_lookup.cpp +++ b/lib/csapi/third_party_lookup.cpp @@ -9,26 +9,26 @@ using namespace Quotient; QUrl GetProtocolsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/thirdparty/protocols")); } GetProtocolsJob::GetProtocolsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetProtocolsJob"), - makePath("/_matrix/client/r0", "/thirdparty/protocols")) + makePath("/_matrix/client/v3", "/thirdparty/protocols")) {} QUrl GetProtocolMetadataJob::makeRequestUrl(QUrl baseUrl, const QString& protocol) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/thirdparty/protocol/", protocol)); } GetProtocolMetadataJob::GetProtocolMetadataJob(const QString& protocol) : BaseJob(HttpVerb::Get, QStringLiteral("GetProtocolMetadataJob"), - makePath("/_matrix/client/r0", "/thirdparty/protocol/", protocol)) + makePath("/_matrix/client/v3", "/thirdparty/protocol/", protocol)) {} auto queryToQueryLocationByProtocol(const QString& searchFields) @@ -43,7 +43,7 @@ QUrl QueryLocationByProtocolJob::makeRequestUrl(QUrl baseUrl, const QString& searchFields) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/thirdparty/location/", protocol), queryToQueryLocationByProtocol(searchFields)); } @@ -51,7 +51,7 @@ QUrl QueryLocationByProtocolJob::makeRequestUrl(QUrl baseUrl, QueryLocationByProtocolJob::QueryLocationByProtocolJob( const QString& protocol, const QString& searchFields) : BaseJob(HttpVerb::Get, QStringLiteral("QueryLocationByProtocolJob"), - makePath("/_matrix/client/r0", "/thirdparty/location/", protocol), + makePath("/_matrix/client/v3", "/thirdparty/location/", protocol), queryToQueryLocationByProtocol(searchFields)) {} @@ -67,7 +67,7 @@ QUrl QueryUserByProtocolJob::makeRequestUrl(QUrl baseUrl, const QString& fields) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/thirdparty/user/", protocol), queryToQueryUserByProtocol(fields)); } @@ -75,7 +75,7 @@ QUrl QueryUserByProtocolJob::makeRequestUrl(QUrl baseUrl, QueryUserByProtocolJob::QueryUserByProtocolJob(const QString& protocol, const QString& fields) : BaseJob(HttpVerb::Get, QStringLiteral("QueryUserByProtocolJob"), - makePath("/_matrix/client/r0", "/thirdparty/user/", protocol), + makePath("/_matrix/client/v3", "/thirdparty/user/", protocol), queryToQueryUserByProtocol(fields)) {} @@ -89,14 +89,14 @@ auto queryToQueryLocationByAlias(const QString& alias) QUrl QueryLocationByAliasJob::makeRequestUrl(QUrl baseUrl, const QString& alias) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/thirdparty/location"), queryToQueryLocationByAlias(alias)); } QueryLocationByAliasJob::QueryLocationByAliasJob(const QString& alias) : BaseJob(HttpVerb::Get, QStringLiteral("QueryLocationByAliasJob"), - makePath("/_matrix/client/r0", "/thirdparty/location"), + makePath("/_matrix/client/v3", "/thirdparty/location"), queryToQueryLocationByAlias(alias)) {} @@ -110,13 +110,13 @@ auto queryToQueryUserByID(const QString& userid) QUrl QueryUserByIDJob::makeRequestUrl(QUrl baseUrl, const QString& userid) { return BaseJob::makeRequestUrl(std::move(baseUrl), - makePath("/_matrix/client/r0", + makePath("/_matrix/client/v3", "/thirdparty/user"), queryToQueryUserByID(userid)); } QueryUserByIDJob::QueryUserByIDJob(const QString& userid) : BaseJob(HttpVerb::Get, QStringLiteral("QueryUserByIDJob"), - makePath("/_matrix/client/r0", "/thirdparty/user"), + makePath("/_matrix/client/v3", "/thirdparty/user"), queryToQueryUserByID(userid)) {} diff --git a/lib/csapi/third_party_membership.cpp b/lib/csapi/third_party_membership.cpp index 59275e41..3ca986c7 100644 --- a/lib/csapi/third_party_membership.cpp +++ b/lib/csapi/third_party_membership.cpp @@ -10,12 +10,12 @@ InviteBy3PIDJob::InviteBy3PIDJob(const QString& roomId, const QString& idServer, const QString& idAccessToken, const QString& medium, const QString& address) : BaseJob(HttpVerb::Post, QStringLiteral("InviteBy3PIDJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/invite")) + makePath("/_matrix/client/v3", "/rooms/", roomId, "/invite")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("id_server"), idServer); - addParam<>(_data, QStringLiteral("id_access_token"), idAccessToken); - addParam<>(_data, QStringLiteral("medium"), medium); - addParam<>(_data, QStringLiteral("address"), address); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("id_server"), idServer); + addParam<>(_dataJson, QStringLiteral("id_access_token"), idAccessToken); + addParam<>(_dataJson, QStringLiteral("medium"), medium); + addParam<>(_dataJson, QStringLiteral("address"), address); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/third_party_membership.h b/lib/csapi/third_party_membership.h index 1edb969e..1129a9a8 100644 --- a/lib/csapi/third_party_membership.h +++ b/lib/csapi/third_party_membership.h @@ -16,7 +16,7 @@ namespace Quotient { * The homeserver uses an identity server to perform the mapping from * third party identifier to a Matrix identifier. The other is documented in * the* [joining rooms - * section](/client-server-api/#post_matrixclientr0roomsroomidinvite). + * section](/client-server-api/#post_matrixclientv3roomsroomidinvite). * * This API invites a user to participate in a particular room. * They do not start participating in the room until they actually join the diff --git a/lib/csapi/to_device.cpp b/lib/csapi/to_device.cpp index 628e8314..e10fac69 100644 --- a/lib/csapi/to_device.cpp +++ b/lib/csapi/to_device.cpp @@ -10,10 +10,10 @@ SendToDeviceJob::SendToDeviceJob( const QString& eventType, const QString& txnId, const QHash<QString, QHash<QString, QJsonObject>>& messages) : BaseJob(HttpVerb::Put, QStringLiteral("SendToDeviceJob"), - makePath("/_matrix/client/r0", "/sendToDevice/", eventType, "/", + makePath("/_matrix/client/v3", "/sendToDevice/", eventType, "/", txnId)) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("messages"), messages); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("messages"), messages); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/typing.cpp b/lib/csapi/typing.cpp index c9673118..21bd45ae 100644 --- a/lib/csapi/typing.cpp +++ b/lib/csapi/typing.cpp @@ -9,11 +9,11 @@ using namespace Quotient; SetTypingJob::SetTypingJob(const QString& userId, const QString& roomId, bool typing, Omittable<int> timeout) : BaseJob(HttpVerb::Put, QStringLiteral("SetTypingJob"), - makePath("/_matrix/client/r0", "/rooms/", roomId, "/typing/", + makePath("/_matrix/client/v3", "/rooms/", roomId, "/typing/", userId)) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("typing"), typing); - addParam<IfNotEmpty>(_data, QStringLiteral("timeout"), timeout); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("typing"), typing); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("timeout"), timeout); + setRequestData({ _dataJson }); } diff --git a/lib/csapi/users.cpp b/lib/csapi/users.cpp index 48b727f0..c65280ee 100644 --- a/lib/csapi/users.cpp +++ b/lib/csapi/users.cpp @@ -9,12 +9,12 @@ using namespace Quotient; SearchUserDirectoryJob::SearchUserDirectoryJob(const QString& searchTerm, Omittable<int> limit) : BaseJob(HttpVerb::Post, QStringLiteral("SearchUserDirectoryJob"), - makePath("/_matrix/client/r0", "/user_directory/search")) + makePath("/_matrix/client/v3", "/user_directory/search")) { - QJsonObject _data; - addParam<>(_data, QStringLiteral("search_term"), searchTerm); - addParam<IfNotEmpty>(_data, QStringLiteral("limit"), limit); - setRequestData(std::move(_data)); + QJsonObject _dataJson; + addParam<>(_dataJson, QStringLiteral("search_term"), searchTerm); + addParam<IfNotEmpty>(_dataJson, QStringLiteral("limit"), limit); + setRequestData({ _dataJson }); addExpectedKey("results"); addExpectedKey("limited"); } diff --git a/lib/csapi/versions.h b/lib/csapi/versions.h index 4445dbd2..9f799cb0 100644 --- a/lib/csapi/versions.h +++ b/lib/csapi/versions.h @@ -12,11 +12,9 @@ namespace Quotient { * * Gets the versions of the specification supported by the server. * - * Values will take the form `rX.Y.Z`. - * - * Only the latest `Z` value will be reported for each supported `X.Y` value. - * i.e. if the server implements `r0.0.0`, `r0.0.1`, and `r1.2.0`, it will - * report `r0.0.1` and `r1.2.0`. + * Values will take the form `vX.Y` or `rX.Y.Z` in historical cases. See + * [the Specification Versioning](../#specification-versions) for more + * information. * * The server may additionally advertise experimental features it supports * through `unstable_features`. These features should be namespaced and diff --git a/lib/csapi/voip.cpp b/lib/csapi/voip.cpp index c748ad94..1e1f2441 100644 --- a/lib/csapi/voip.cpp +++ b/lib/csapi/voip.cpp @@ -9,10 +9,10 @@ using namespace Quotient; QUrl GetTurnServerJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/voip/turnServer")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/voip/turnServer")); } GetTurnServerJob::GetTurnServerJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetTurnServerJob"), - makePath("/_matrix/client/r0", "/voip/turnServer")) + makePath("/_matrix/client/v3", "/voip/turnServer")) {} diff --git a/lib/csapi/whoami.cpp b/lib/csapi/whoami.cpp index ed8a9817..af0c5d31 100644 --- a/lib/csapi/whoami.cpp +++ b/lib/csapi/whoami.cpp @@ -9,12 +9,12 @@ using namespace Quotient; QUrl GetTokenOwnerJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl( - std::move(baseUrl), makePath("/_matrix/client/r0", "/account/whoami")); + std::move(baseUrl), makePath("/_matrix/client/v3", "/account/whoami")); } GetTokenOwnerJob::GetTokenOwnerJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetTokenOwnerJob"), - makePath("/_matrix/client/r0", "/account/whoami")) + makePath("/_matrix/client/v3", "/account/whoami")) { addExpectedKey("user_id"); } diff --git a/lib/csapi/whoami.h b/lib/csapi/whoami.h index fba099f6..3451dbc3 100644 --- a/lib/csapi/whoami.h +++ b/lib/csapi/whoami.h @@ -41,6 +41,14 @@ public: /// of application services) then this field can be omitted. /// Otherwise this is required. QString deviceId() const { return loadFromJson<QString>("device_id"_ls); } + + /// When `true`, the user is a [Guest User](#guest-access). When + /// not present or `false`, the user is presumed to be a non-guest + /// user. + Omittable<bool> isGuest() const + { + return loadFromJson<Omittable<bool>>("is_guest"_ls); + } }; } // namespace Quotient |