diff options
author | Alexey Rusakov <Kitsune-Ral@users.sf.net> | 2022-06-12 15:04:18 +0200 |
---|---|---|
committer | Alexey Rusakov <Kitsune-Ral@users.sf.net> | 2022-06-12 15:04:18 +0200 |
commit | a831d6f9cd55e33061e748b29cf256ba84ece20d (patch) | |
tree | 35443bf8a5006c6d8498bcd9bad6cb280107eac9 | |
parent | 7d4b46e6daf656a1e97426cb1f2f8c99c68c4dda (diff) | |
parent | 9e594bd1d49dc0e1fdb8b74cef11fe3bfa3fdc1e (diff) | |
download | libquotient-a831d6f9cd55e33061e748b29cf256ba84ece20d.tar.gz libquotient-a831d6f9cd55e33061e748b29cf256ba84ece20d.zip |
Merge branch 'kitsune/more-gtad-fixes' into dev
-rw-r--r-- | .github/workflows/ci.yml | 2 | ||||
-rw-r--r-- | event-schemas/schema/core-event-schema/stripped_state.h | 44 | ||||
m--------- | gtad/gtad | 0 | ||||
-rw-r--r-- | gtad/gtad.yaml | 34 | ||||
-rw-r--r-- | lib/csapi/definitions/public_rooms_chunk.h | 73 | ||||
-rw-r--r-- | lib/csapi/definitions/public_rooms_response.h | 40 | ||||
-rw-r--r-- | lib/csapi/login.cpp | 4 | ||||
-rw-r--r-- | lib/csapi/login.h | 30 | ||||
-rw-r--r-- | lib/csapi/refresh.cpp | 17 | ||||
-rw-r--r-- | lib/csapi/refresh.h | 65 | ||||
-rw-r--r-- | lib/csapi/registration.cpp | 4 | ||||
-rw-r--r-- | lib/csapi/registration.h | 32 | ||||
-rw-r--r-- | lib/csapi/relations.cpp | 111 | ||||
-rw-r--r-- | lib/csapi/relations.h | 277 | ||||
-rw-r--r-- | lib/csapi/space_hierarchy.cpp | 12 | ||||
-rw-r--r-- | lib/csapi/space_hierarchy.h | 17 |
16 files changed, 562 insertions, 200 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99fe7b7b..172c027f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ concurrency: ci-${{ github.ref }} jobs: CI: runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.update-api != '' }} # the current upstream API definitions are expected to fail the test + continue-on-error: false strategy: fail-fast: false max-parallel: 1 diff --git a/event-schemas/schema/core-event-schema/stripped_state.h b/event-schemas/schema/core-event-schema/stripped_state.h deleted file mode 100644 index 742b0a56..00000000 --- a/event-schemas/schema/core-event-schema/stripped_state.h +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN - */ - -#pragma once - -#include "converters.h" - -namespace Quotient { -/// A stripped down state event, with only the `type`, `state_key`, -/// `sender`, and `content` keys. -struct StrippedStateEvent { - /// The `content` for the event. - QJsonObject content; - - /// The `state_key` for the event. - QString stateKey; - - /// The `type` for the event. - QString type; - - /// The `sender` for the event. - QString sender; -}; - -template <> -struct JsonObjectConverter<StrippedStateEvent> { - static void dumpTo(QJsonObject& jo, const StrippedStateEvent& pod) - { - addParam<>(jo, QStringLiteral("content"), pod.content); - addParam<>(jo, QStringLiteral("state_key"), pod.stateKey); - addParam<>(jo, QStringLiteral("type"), pod.type); - addParam<>(jo, QStringLiteral("sender"), pod.sender); - } - static void fillFrom(const QJsonObject& jo, StrippedStateEvent& pod) - { - fromJson(jo.value("content"_ls), pod.content); - fromJson(jo.value("state_key"_ls), pod.stateKey); - fromJson(jo.value("type"_ls), pod.type); - fromJson(jo.value("sender"_ls), pod.sender); - } -}; - -} // namespace Quotient diff --git a/gtad/gtad b/gtad/gtad -Subproject fcc8e0f28367f37890db9cfa5e96d08d599b36f +Subproject 9ea32fb74767a62a3a0d27b3b181e8c18fb0c69 diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 2d004cbc..0bec3b7a 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -29,6 +29,8 @@ analyzer: login>/user: "" login>/medium: "" login>/address: "" + login</home_server: "" + register</home_server: "" # Structure inside `types`: # - swaggerType: <targetTypeSpec> @@ -88,7 +90,8 @@ analyzer: - /(room|client)_event.yaml$/: RoomEventPtr - /event(_without_room_id)?.yaml$/: EventPtr - +set: - # This renderer actually applies to all $ref things + # This renderer applies to everything actually $ref'ed + # (not substituted) _importRenderer: '"{{#segments}}{{_}}{{#_join}}/{{/_join}}{{/segments}}.h"' +on: - '/^(\./)?definitions/request_email_validation.yaml$/': @@ -96,7 +99,20 @@ analyzer: - '/^(\./)?definitions/request_msisdn_validation.yaml$/': title: MsisdnValidationData - /_filter.yaml$/: # Event/RoomEventFilters do NOT need Omittable<> + + # Despite being used in two calls, it's more practical to have those + # fields available as getters right from the respective job classes - /public_rooms_response.yaml$/: { _inline: true } + + # list_public_rooms.yaml (via public_rooms_response.yaml) and + # space_hierarchy.yaml use public_rooms_chunk.yaml as a common base + # structure, adding (space_hiearchy) or overriding + # (public_rooms_response) fields for their purposes. The spec text + # confusingly ends up with having two different structures named + # "PublicRoomsChunk". To make sure the types are distinct in + # libQuotient, this common base is inlined into the actually used + # data structures (that have distinct names) defined + # in space_hierarchy.h and public_rooms_response.h, respectively - /public_rooms_chunk.yaml$/: { _inline: true } - //: *UseOmittable # Also apply "avoidCopy" to all other ref'ed types - schema: @@ -105,6 +121,7 @@ analyzer: # type: Filter # imports: '"csapi/definitions/sync_filter.h"' # - getFilter<: *Filter + - StrippedChildStateEvent: void # only used in an array, see below - RoomFilter: # A structure inside Filter, same story as with *_filter.yaml - OneTimeKeys: type: OneTimeKeys @@ -114,20 +131,21 @@ analyzer: - string: QStringList - +set: { moveOnly: } +on: - - /^Notification|Result$/: - type: "std::vector<{{1}}>" + - /^Notification|Result|ChildRoomsChunk$/: "std::vector<{{1}}>" + - StrippedChildStateEvent: + type: StateEvents imports: '"events/eventloader.h"' - - /state_event.yaml$/: StateEvents - - /(room|client)_event.yaml$/: RoomEvents - - /event(_without_room_id)?.yaml$/: Events + - /state_event.yaml$/: StateEvents # 'imports' already set under $ref + - /(room|client)_event.yaml$/: RoomEvents # ditto + - /event(_without_room_id)?.yaml$/: Events # ditto - //: "QVector<{{1}}>" - map: # `additionalProperties` in OpenAPI - RoomState: type: "UnorderedMap<QString, {{1}}>" moveOnly: - /.+/: "QHash<QString, {{1}}>" - - //: QVariantHash - - variant: # A sequence `type` (multitype) in OpenAPI + - //: QVariantHash # QJsonObject?.. + - variant: # A sequence `type` or a 'oneOf' group in OpenAPI - /^string,null|null,string$/: *QString - //: QVariant diff --git a/lib/csapi/definitions/public_rooms_chunk.h b/lib/csapi/definitions/public_rooms_chunk.h deleted file mode 100644 index eac68213..00000000 --- a/lib/csapi/definitions/public_rooms_chunk.h +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************************** - * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN - */ - -#pragma once - -#include "converters.h" - -namespace Quotient { - -struct PublicRoomsChunk { - /// 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; -}; - -template <> -struct JsonObjectConverter<PublicRoomsChunk> { - static void dumpTo(QJsonObject& jo, const PublicRoomsChunk& pod) - { - addParam<IfNotEmpty>(jo, QStringLiteral("canonical_alias"), - pod.canonicalAlias); - addParam<IfNotEmpty>(jo, QStringLiteral("name"), pod.name); - addParam<>(jo, QStringLiteral("num_joined_members"), - pod.numJoinedMembers); - addParam<>(jo, QStringLiteral("room_id"), pod.roomId); - addParam<IfNotEmpty>(jo, QStringLiteral("topic"), pod.topic); - addParam<>(jo, QStringLiteral("world_readable"), pod.worldReadable); - addParam<>(jo, QStringLiteral("guest_can_join"), pod.guestCanJoin); - addParam<IfNotEmpty>(jo, QStringLiteral("avatar_url"), pod.avatarUrl); - addParam<IfNotEmpty>(jo, QStringLiteral("join_rule"), pod.joinRule); - } - static void fillFrom(const QJsonObject& jo, PublicRoomsChunk& pod) - { - fromJson(jo.value("canonical_alias"_ls), pod.canonicalAlias); - fromJson(jo.value("name"_ls), pod.name); - fromJson(jo.value("num_joined_members"_ls), pod.numJoinedMembers); - fromJson(jo.value("room_id"_ls), pod.roomId); - fromJson(jo.value("topic"_ls), pod.topic); - fromJson(jo.value("world_readable"_ls), pod.worldReadable); - fromJson(jo.value("guest_can_join"_ls), pod.guestCanJoin); - fromJson(jo.value("avatar_url"_ls), pod.avatarUrl); - fromJson(jo.value("join_rule"_ls), pod.joinRule); - } -}; - -} // namespace Quotient diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index da917a98..d0a2595c 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -72,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/login.cpp b/lib/csapi/login.cpp index b2175a05..5e007d8f 100644 --- a/lib/csapi/login.cpp +++ b/lib/csapi/login.cpp @@ -21,7 +21,8 @@ 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/v3", "/login"), false) { @@ -33,5 +34,6 @@ LoginJob::LoginJob(const QString& type, addParam<IfNotEmpty>(_data, QStringLiteral("device_id"), deviceId); addParam<IfNotEmpty>(_data, QStringLiteral("initial_device_display_name"), initialDeviceDisplayName); + addParam<IfNotEmpty>(_data, QStringLiteral("refresh_token"), refreshToken); setRequestData(std::move(_data)); } 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/refresh.cpp b/lib/csapi/refresh.cpp new file mode 100644 index 00000000..8d4a34ae --- /dev/null +++ b/lib/csapi/refresh.cpp @@ -0,0 +1,17 @@ +/****************************************************************************** + * 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 _data; + addParam<IfNotEmpty>(_data, QStringLiteral("refresh_token"), refreshToken); + setRequestData(std::move(_data)); + 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 aa4b4fad..3541724b 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -18,7 +18,8 @@ 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/v3", "/register"), queryToRegister(kind), {}, false) @@ -31,6 +32,7 @@ RegisterJob::RegisterJob(const QString& kind, addParam<IfNotEmpty>(_data, QStringLiteral("initial_device_display_name"), initialDeviceDisplayName); addParam<IfNotEmpty>(_data, QStringLiteral("inhibit_login"), inhibitLogin); + addParam<IfNotEmpty>(_data, QStringLiteral("refresh_token"), refreshToken); setRequestData(std::move(_data)); addExpectedKey("user_id"); } diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h index 39840008..7a20cab8 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 false. + 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 false. + 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 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/space_hierarchy.cpp b/lib/csapi/space_hierarchy.cpp index 7c17ce8a..7b5c7eac 100644 --- a/lib/csapi/space_hierarchy.cpp +++ b/lib/csapi/space_hierarchy.cpp @@ -7,8 +7,8 @@ using namespace Quotient; auto queryToGetSpaceHierarchy(Omittable<bool> suggestedOnly, - Omittable<double> limit, - Omittable<double> maxDepth, const QString& from) + Omittable<int> limit, Omittable<int> maxDepth, + const QString& from) { QUrlQuery _q; addParam<IfNotEmpty>(_q, QStringLiteral("suggested_only"), suggestedOnly); @@ -20,8 +20,8 @@ auto queryToGetSpaceHierarchy(Omittable<bool> suggestedOnly, QUrl GetSpaceHierarchyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, Omittable<bool> suggestedOnly, - Omittable<double> limit, - Omittable<double> maxDepth, + Omittable<int> limit, + Omittable<int> maxDepth, const QString& from) { return BaseJob::makeRequestUrl( @@ -32,8 +32,8 @@ QUrl GetSpaceHierarchyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, GetSpaceHierarchyJob::GetSpaceHierarchyJob(const QString& roomId, Omittable<bool> suggestedOnly, - Omittable<double> limit, - Omittable<double> maxDepth, + Omittable<int> limit, + Omittable<int> maxDepth, const QString& from) : BaseJob(HttpVerb::Get, QStringLiteral("GetSpaceHierarchyJob"), makePath("/_matrix/client/v1", "/rooms/", roomId, "/hierarchy"), diff --git a/lib/csapi/space_hierarchy.h b/lib/csapi/space_hierarchy.h index 5b3c1f80..7a421be8 100644 --- a/lib/csapi/space_hierarchy.h +++ b/lib/csapi/space_hierarchy.h @@ -4,8 +4,7 @@ #pragma once -#include "csapi/../../event-schemas/schema/core-event-schema/stripped_state.h" - +#include "events/eventloader.h" #include "jobs/basejob.h" namespace Quotient { @@ -66,7 +65,7 @@ public: /// added `origin_server_ts` key. /// /// If the room is not a space-room, this should be empty. - QVector<QJsonObject> childrenState; + StateEvents childrenState; }; // Construction/destruction @@ -103,8 +102,8 @@ public: */ explicit GetSpaceHierarchyJob(const QString& roomId, Omittable<bool> suggestedOnly = none, - Omittable<double> limit = none, - Omittable<double> maxDepth = none, + Omittable<int> limit = none, + Omittable<int> maxDepth = none, const QString& from = {}); /*! \brief Construct a URL without creating a full-fledged job object @@ -114,16 +113,16 @@ public: */ static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, Omittable<bool> suggestedOnly = none, - Omittable<double> limit = none, - Omittable<double> maxDepth = none, + Omittable<int> limit = none, + Omittable<int> maxDepth = none, const QString& from = {}); // Result properties /// The rooms for the current page, with the current filters. - QVector<ChildRoomsChunk> rooms() const + std::vector<ChildRoomsChunk> rooms() { - return loadFromJson<QVector<ChildRoomsChunk>>("rooms"_ls); + return takeFromJson<std::vector<ChildRoomsChunk>>("rooms"_ls); } /// A token to supply to `from` to keep paginating the responses. Not |