diff options
Diffstat (limited to 'lib/csapi')
87 files changed, 1149 insertions, 965 deletions
diff --git a/lib/csapi/account-data.cpp b/lib/csapi/account-data.cpp index 5021c73a..96b32a92 100644 --- a/lib/csapi/account-data.cpp +++ b/lib/csapi/account-data.cpp @@ -21,6 +21,20 @@ SetAccountDataJob::SetAccountDataJob(const QString& userId, const QString& type, setRequestData(Data(toJson(content))); } +QUrl GetAccountDataJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& type) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + basePath % "/user/" % userId % "/account_data/" % type); +} + +static const auto GetAccountDataJobName = QStringLiteral("GetAccountDataJob"); + +GetAccountDataJob::GetAccountDataJob(const QString& userId, const QString& type) + : BaseJob(HttpVerb::Get, GetAccountDataJobName, + basePath % "/user/" % userId % "/account_data/" % type) +{ +} + static const auto SetAccountDataPerRoomJobName = QStringLiteral("SetAccountDataPerRoomJob"); SetAccountDataPerRoomJob::SetAccountDataPerRoomJob(const QString& userId, const QString& roomId, const QString& type, const QJsonObject& content) @@ -30,3 +44,17 @@ SetAccountDataPerRoomJob::SetAccountDataPerRoomJob(const QString& userId, const setRequestData(Data(toJson(content))); } +QUrl GetAccountDataPerRoomJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId, const QString& type) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + basePath % "/user/" % userId % "/rooms/" % roomId % "/account_data/" % type); +} + +static const auto GetAccountDataPerRoomJobName = QStringLiteral("GetAccountDataPerRoomJob"); + +GetAccountDataPerRoomJob::GetAccountDataPerRoomJob(const QString& userId, const QString& roomId, const QString& type) + : BaseJob(HttpVerb::Get, GetAccountDataPerRoomJobName, + basePath % "/user/" % userId % "/rooms/" % roomId % "/account_data/" % type) +{ +} + diff --git a/lib/csapi/account-data.h b/lib/csapi/account-data.h index f3656a14..b067618f 100644 --- a/lib/csapi/account-data.h +++ b/lib/csapi/account-data.h @@ -22,8 +22,8 @@ namespace QMatrixClient public: /*! Set some account_data for the user. * \param userId - * The id of the user to set account_data for. The access token must be - * authorized to make requests for this user id. + * The ID of the user to set account_data for. The access token must be + * authorized to make requests for this user ID. * \param type * The event type of the account_data to set. Custom types should be * namespaced to avoid clashes. @@ -33,6 +33,33 @@ namespace QMatrixClient explicit SetAccountDataJob(const QString& userId, const QString& type, const QJsonObject& content = {}); }; + /// Get some account_data for the user. + /// + /// Get some account_data for the client. This config is only visible to the user + /// that set the account_data. + class GetAccountDataJob : public BaseJob + { + public: + /*! Get some account_data for the user. + * \param userId + * The ID of the user to get account_data for. The access token must be + * authorized to make requests for this user ID. + * \param type + * The event type of the account_data to get. Custom types should be + * namespaced to avoid clashes. + */ + explicit GetAccountDataJob(const QString& userId, const QString& type); + + /*! Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for + * GetAccountDataJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& type); + + }; + /// Set some account_data for the user. /// /// Set some account_data for the client on a given room. This config is only @@ -43,10 +70,10 @@ namespace QMatrixClient public: /*! Set some account_data for the user. * \param userId - * The id of the user to set account_data for. The access token must be - * authorized to make requests for this user id. + * The ID of the user to set account_data for. The access token must be + * authorized to make requests for this user ID. * \param roomId - * The id of the room to set account_data on. + * The ID of the room to set account_data on. * \param type * The event type of the account_data to set. Custom types should be * namespaced to avoid clashes. @@ -55,4 +82,33 @@ namespace QMatrixClient */ explicit SetAccountDataPerRoomJob(const QString& userId, const QString& roomId, const QString& type, const QJsonObject& content = {}); }; + + /// Get some account_data for the user. + /// + /// Get some account_data for the client on a given room. This config is only + /// visible to the user that set the account_data. + class GetAccountDataPerRoomJob : public BaseJob + { + public: + /*! Get some account_data for the user. + * \param userId + * The ID of the user to set account_data for. The access token must be + * authorized to make requests for this user ID. + * \param roomId + * The ID of the room to get account_data for. + * \param type + * The event type of the account_data to get. Custom types should be + * namespaced to avoid clashes. + */ + explicit GetAccountDataPerRoomJob(const QString& userId, const QString& roomId, const QString& type); + + /*! Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for + * GetAccountDataPerRoomJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId, const QString& type); + + }; } // namespace QMatrixClient diff --git a/lib/csapi/admin.cpp b/lib/csapi/admin.cpp index 6066d4d9..ce06a56d 100644 --- a/lib/csapi/admin.cpp +++ b/lib/csapi/admin.cpp @@ -16,43 +16,29 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetWhoIsJob::ConnectionInfo> + template <> struct JsonObjectConverter<GetWhoIsJob::ConnectionInfo> { - GetWhoIsJob::ConnectionInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetWhoIsJob::ConnectionInfo& result) { - GetWhoIsJob::ConnectionInfo result; - result.ip = - fromJson<QString>(jo.value("ip"_ls)); - result.lastSeen = - fromJson<qint64>(jo.value("last_seen"_ls)); - result.userAgent = - fromJson<QString>(jo.value("user_agent"_ls)); - - return result; + fromJson(jo.value("ip"_ls), result.ip); + fromJson(jo.value("last_seen"_ls), result.lastSeen); + fromJson(jo.value("user_agent"_ls), result.userAgent); } }; - template <> struct FromJsonObject<GetWhoIsJob::SessionInfo> + template <> struct JsonObjectConverter<GetWhoIsJob::SessionInfo> { - GetWhoIsJob::SessionInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetWhoIsJob::SessionInfo& result) { - GetWhoIsJob::SessionInfo result; - result.connections = - fromJson<QVector<GetWhoIsJob::ConnectionInfo>>(jo.value("connections"_ls)); - - return result; + fromJson(jo.value("connections"_ls), result.connections); } }; - template <> struct FromJsonObject<GetWhoIsJob::DeviceInfo> + template <> struct JsonObjectConverter<GetWhoIsJob::DeviceInfo> { - GetWhoIsJob::DeviceInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetWhoIsJob::DeviceInfo& result) { - GetWhoIsJob::DeviceInfo result; - result.sessions = - fromJson<QVector<GetWhoIsJob::SessionInfo>>(jo.value("sessions"_ls)); - - return result; + fromJson(jo.value("sessions"_ls), result.sessions); } }; } // namespace QMatrixClient @@ -94,8 +80,8 @@ const QHash<QString, GetWhoIsJob::DeviceInfo>& GetWhoIsJob::devices() const BaseJob::Status GetWhoIsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->userId = fromJson<QString>(json.value("user_id"_ls)); - d->devices = fromJson<QHash<QString, DeviceInfo>>(json.value("devices"_ls)); + fromJson(json.value("user_id"_ls), d->userId); + fromJson(json.value("devices"_ls), d->devices); return Success; } diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index f62002a6..11385dff 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -16,21 +16,14 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetAccount3PIDsJob::ThirdPartyIdentifier> + template <> struct JsonObjectConverter<GetAccount3PIDsJob::ThirdPartyIdentifier> { - GetAccount3PIDsJob::ThirdPartyIdentifier operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetAccount3PIDsJob::ThirdPartyIdentifier& result) { - GetAccount3PIDsJob::ThirdPartyIdentifier result; - result.medium = - fromJson<QString>(jo.value("medium"_ls)); - result.address = - fromJson<QString>(jo.value("address"_ls)); - result.validatedAt = - fromJson<qint64>(jo.value("validated_at"_ls)); - result.addedAt = - fromJson<qint64>(jo.value("added_at"_ls)); - - return result; + fromJson(jo.value("medium"_ls), result.medium); + fromJson(jo.value("address"_ls), result.address); + fromJson(jo.value("validated_at"_ls), result.validatedAt); + fromJson(jo.value("added_at"_ls), result.addedAt); } }; } // namespace QMatrixClient @@ -66,7 +59,7 @@ const QVector<GetAccount3PIDsJob::ThirdPartyIdentifier>& GetAccount3PIDsJob::thr BaseJob::Status GetAccount3PIDsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->threepids = fromJson<QVector<ThirdPartyIdentifier>>(json.value("threepids"_ls)); + fromJson(json.value("threepids"_ls), d->threepids); return Success; } @@ -74,19 +67,20 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const Post3PIDsJob::ThreePidCredentials& pod) + template <> struct JsonObjectConverter<Post3PIDsJob::ThreePidCredentials> { - QJsonObject jo; - addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); - addParam<>(jo, QStringLiteral("id_server"), pod.idServer); - addParam<>(jo, QStringLiteral("sid"), pod.sid); - return jo; - } + static void dumpTo(QJsonObject& jo, const Post3PIDsJob::ThreePidCredentials& pod) + { + addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); + addParam<>(jo, QStringLiteral("id_server"), pod.idServer); + addParam<>(jo, QStringLiteral("sid"), pod.sid); + } + }; } // namespace QMatrixClient static const auto Post3PIDsJobName = QStringLiteral("Post3PIDsJob"); -Post3PIDsJob::Post3PIDsJob(const ThreePidCredentials& threePidCreds, bool bind) +Post3PIDsJob::Post3PIDsJob(const ThreePidCredentials& threePidCreds, Omittable<bool> bind) : BaseJob(HttpVerb::Post, Post3PIDsJobName, basePath % "/account/3pid") { @@ -139,7 +133,7 @@ const Sid& RequestTokenTo3PIDEmailJob::data() const BaseJob::Status RequestTokenTo3PIDEmailJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Sid>(data); + fromJson(data, d->data); return Success; } @@ -175,7 +169,7 @@ const Sid& RequestTokenTo3PIDMSISDNJob::data() const BaseJob::Status RequestTokenTo3PIDMSISDNJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Sid>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/administrative_contact.h b/lib/csapi/administrative_contact.h index 3fb3d44c..02aeee4d 100644 --- a/lib/csapi/administrative_contact.h +++ b/lib/csapi/administrative_contact.h @@ -113,7 +113,7 @@ namespace QMatrixClient * identifier to the account's Matrix ID with the passed identity * server. Default: ``false``. */ - explicit Post3PIDsJob(const ThreePidCredentials& threePidCreds, bool bind = false); + explicit Post3PIDsJob(const ThreePidCredentials& threePidCreds, Omittable<bool> bind = none); }; /// Deletes a third party identifier from the user's account diff --git a/lib/csapi/capabilities.cpp b/lib/csapi/capabilities.cpp new file mode 100644 index 00000000..210423f5 --- /dev/null +++ b/lib/csapi/capabilities.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "capabilities.h" + +#include "converters.h" + +#include <QtCore/QStringBuilder> + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +namespace QMatrixClient +{ + // Converters + + template <> struct JsonObjectConverter<GetCapabilitiesJob::ChangePasswordCapability> + { + static void fillFrom(const QJsonObject& jo, GetCapabilitiesJob::ChangePasswordCapability& result) + { + fromJson(jo.value("enabled"_ls), result.enabled); + } + }; + + template <> struct JsonObjectConverter<GetCapabilitiesJob::RoomVersionsCapability> + { + static void fillFrom(const QJsonObject& jo, GetCapabilitiesJob::RoomVersionsCapability& result) + { + fromJson(jo.value("default"_ls), result.defaultVersion); + fromJson(jo.value("available"_ls), result.available); + } + }; + + template <> struct JsonObjectConverter<GetCapabilitiesJob::Capabilities> + { + static void fillFrom(QJsonObject jo, GetCapabilitiesJob::Capabilities& result) + { + fromJson(jo.take("m.change_password"_ls), result.changePassword); + fromJson(jo.take("m.room_versions"_ls), result.roomVersions); + fromJson(jo, result.additionalProperties); + } + }; +} // namespace QMatrixClient + +class GetCapabilitiesJob::Private +{ + public: + Capabilities capabilities; +}; + +QUrl GetCapabilitiesJob::makeRequestUrl(QUrl baseUrl) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + basePath % "/capabilities"); +} + +static const auto GetCapabilitiesJobName = QStringLiteral("GetCapabilitiesJob"); + +GetCapabilitiesJob::GetCapabilitiesJob() + : BaseJob(HttpVerb::Get, GetCapabilitiesJobName, + basePath % "/capabilities") + , d(new Private) +{ +} + +GetCapabilitiesJob::~GetCapabilitiesJob() = default; + +const GetCapabilitiesJob::Capabilities& GetCapabilitiesJob::capabilities() const +{ + return d->capabilities; +} + +BaseJob::Status GetCapabilitiesJob::parseJson(const QJsonDocument& data) +{ + auto json = data.object(); + if (!json.contains("capabilities"_ls)) + return { JsonParseError, + "The key 'capabilities' not found in the response" }; + fromJson(json.value("capabilities"_ls), d->capabilities); + return Success; +} + diff --git a/lib/csapi/capabilities.h b/lib/csapi/capabilities.h new file mode 100644 index 00000000..06a8bf0d --- /dev/null +++ b/lib/csapi/capabilities.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + +#include <QtCore/QJsonObject> +#include "converters.h" +#include <QtCore/QHash> + +namespace QMatrixClient +{ + // Operations + + /// Gets information about the server's capabilities. + /// + /// Gets information about the server's supported feature set + /// and other relevant capabilities. + class GetCapabilitiesJob : public BaseJob + { + public: + // Inner data structures + + /// Capability to indicate if the user can change their password. + struct ChangePasswordCapability + { + /// True if the user can change their password, false otherwise. + bool enabled; + }; + + /// The room versions the server supports. + struct RoomVersionsCapability + { + /// The default room version the server is using for new rooms. + QString defaultVersion; + /// A detailed description of the room versions the server supports. + QHash<QString, QString> available; + }; + + /// The custom capabilities the server supports, using the + /// Java package naming convention. + struct Capabilities + { + /// Capability to indicate if the user can change their password. + Omittable<ChangePasswordCapability> changePassword; + /// The room versions the server supports. + Omittable<RoomVersionsCapability> roomVersions; + /// The custom capabilities the server supports, using the + /// Java package naming convention. + QHash<QString, QJsonObject> additionalProperties; + }; + + // Construction/destruction + + explicit GetCapabilitiesJob(); + + /*! Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for + * GetCapabilitiesJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl); + + ~GetCapabilitiesJob() override; + + // Result properties + + /// The custom capabilities the server supports, using the + /// Java package naming convention. + const Capabilities& capabilities() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; + }; +} // namespace QMatrixClient diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index 9b590e42..22223985 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -52,7 +52,7 @@ BaseJob::Status UploadContentJob::parseJson(const QJsonDocument& data) if (!json.contains("content_uri"_ls)) return { JsonParseError, "The key 'content_uri' not found in the response" }; - d->contentUri = fromJson<QString>(json.value("content_uri"_ls)); + fromJson(json.value("content_uri"_ls), d->contentUri); return Success; } @@ -276,8 +276,8 @@ const QString& GetUrlPreviewJob::ogImage() const BaseJob::Status GetUrlPreviewJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->matrixImageSize = fromJson<qint64>(json.value("matrix:image:size"_ls)); - d->ogImage = fromJson<QString>(json.value("og:image"_ls)); + fromJson(json.value("matrix:image:size"_ls), d->matrixImageSize); + fromJson(json.value("og:image"_ls), d->ogImage); return Success; } @@ -312,7 +312,7 @@ Omittable<qint64> GetConfigJob::uploadSize() const BaseJob::Status GetConfigJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->uploadSize = fromJson<qint64>(json.value("m.upload.size"_ls)); + fromJson(json.value("m.upload.size"_ls), d->uploadSize); return Success; } diff --git a/lib/csapi/create_room.cpp b/lib/csapi/create_room.cpp index 36f83727..448547ae 100644 --- a/lib/csapi/create_room.cpp +++ b/lib/csapi/create_room.cpp @@ -16,23 +16,25 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const CreateRoomJob::Invite3pid& pod) + template <> struct JsonObjectConverter<CreateRoomJob::Invite3pid> { - QJsonObject jo; - addParam<>(jo, QStringLiteral("id_server"), pod.idServer); - addParam<>(jo, QStringLiteral("medium"), pod.medium); - addParam<>(jo, QStringLiteral("address"), pod.address); - return jo; - } + static void dumpTo(QJsonObject& jo, const CreateRoomJob::Invite3pid& pod) + { + addParam<>(jo, QStringLiteral("id_server"), pod.idServer); + addParam<>(jo, QStringLiteral("medium"), pod.medium); + addParam<>(jo, QStringLiteral("address"), pod.address); + } + }; - QJsonObject toJson(const CreateRoomJob::StateEvent& pod) + template <> struct JsonObjectConverter<CreateRoomJob::StateEvent> { - QJsonObject jo; - addParam<>(jo, QStringLiteral("type"), pod.type); - addParam<IfNotEmpty>(jo, QStringLiteral("state_key"), pod.stateKey); - addParam<>(jo, QStringLiteral("content"), pod.content); - return jo; - } + static void dumpTo(QJsonObject& jo, const CreateRoomJob::StateEvent& pod) + { + addParam<>(jo, QStringLiteral("type"), pod.type); + addParam<IfNotEmpty>(jo, QStringLiteral("state_key"), pod.stateKey); + addParam<>(jo, QStringLiteral("content"), pod.content); + } + }; } // namespace QMatrixClient class CreateRoomJob::Private @@ -43,7 +45,7 @@ class CreateRoomJob::Private static const auto CreateRoomJobName = QStringLiteral("CreateRoomJob"); -CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& roomAliasName, const QString& name, const QString& topic, const QStringList& invite, const QVector<Invite3pid>& invite3pid, const QString& roomVersion, const QJsonObject& creationContent, const QVector<StateEvent>& initialState, const QString& preset, bool isDirect, const QJsonObject& powerLevelContentOverride) +CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& roomAliasName, const QString& name, const QString& topic, const QStringList& invite, const QVector<Invite3pid>& invite3pid, const QString& roomVersion, const QJsonObject& creationContent, const QVector<StateEvent>& initialState, const QString& preset, Omittable<bool> isDirect, const QJsonObject& powerLevelContentOverride) : BaseJob(HttpVerb::Post, CreateRoomJobName, basePath % "/createRoom") , d(new Private) @@ -77,7 +79,7 @@ BaseJob::Status CreateRoomJob::parseJson(const QJsonDocument& data) if (!json.contains("room_id"_ls)) return { JsonParseError, "The key 'room_id' not found in the response" }; - d->roomId = fromJson<QString>(json.value("room_id"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); return Success; } diff --git a/lib/csapi/create_room.h b/lib/csapi/create_room.h index a0a64df0..d7c01d00 100644 --- a/lib/csapi/create_room.h +++ b/lib/csapi/create_room.h @@ -216,7 +216,7 @@ namespace QMatrixClient * event content prior to it being sent to the room. Defaults to * overriding nothing. */ - explicit CreateRoomJob(const QString& visibility = {}, const QString& roomAliasName = {}, const QString& name = {}, const QString& topic = {}, const QStringList& invite = {}, const QVector<Invite3pid>& invite3pid = {}, const QString& roomVersion = {}, const QJsonObject& creationContent = {}, const QVector<StateEvent>& initialState = {}, const QString& preset = {}, bool isDirect = false, const QJsonObject& powerLevelContentOverride = {}); + explicit CreateRoomJob(const QString& visibility = {}, const QString& roomAliasName = {}, const QString& name = {}, const QString& topic = {}, const QStringList& invite = {}, const QVector<Invite3pid>& invite3pid = {}, const QString& roomVersion = {}, const QJsonObject& creationContent = {}, const QVector<StateEvent>& initialState = {}, const QString& preset = {}, Omittable<bool> isDirect = none, const QJsonObject& powerLevelContentOverride = {}); ~CreateRoomJob() override; // Result properties diff --git a/lib/csapi/definitions/auth_data.cpp b/lib/csapi/definitions/auth_data.cpp index f8639432..006b8c7e 100644 --- a/lib/csapi/definitions/auth_data.cpp +++ b/lib/csapi/definitions/auth_data.cpp @@ -6,23 +6,20 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const AuthenticationData& pod) +void JsonObjectConverter<AuthenticationData>::dumpTo( + QJsonObject& jo, const AuthenticationData& pod) { - QJsonObject jo = toJson(pod.authInfo); + fillJson(jo, pod.authInfo); addParam<>(jo, QStringLiteral("type"), pod.type); addParam<IfNotEmpty>(jo, QStringLiteral("session"), pod.session); - return jo; } -AuthenticationData FromJsonObject<AuthenticationData>::operator()(QJsonObject jo) const +void JsonObjectConverter<AuthenticationData>::fillFrom( + QJsonObject jo, AuthenticationData& result) { - AuthenticationData result; - result.type = - fromJson<QString>(jo.take("type"_ls)); - result.session = - fromJson<QString>(jo.take("session"_ls)); + fromJson(jo.take("type"_ls), result.type); + fromJson(jo.take("session"_ls), result.session); - result.authInfo = fromJson<QHash<QString, QJsonObject>>(jo); - return result; + fromJson(jo, result.authInfo); } diff --git a/lib/csapi/definitions/auth_data.h b/lib/csapi/definitions/auth_data.h index 661d3e5f..26eb205c 100644 --- a/lib/csapi/definitions/auth_data.h +++ b/lib/csapi/definitions/auth_data.h @@ -23,12 +23,10 @@ namespace QMatrixClient /// Keys dependent on the login type QHash<QString, QJsonObject> authInfo; }; - - QJsonObject toJson(const AuthenticationData& pod); - - template <> struct FromJsonObject<AuthenticationData> + template <> struct JsonObjectConverter<AuthenticationData> { - AuthenticationData operator()(QJsonObject jo) const; + static void dumpTo(QJsonObject& jo, const AuthenticationData& pod); + static void fillFrom(QJsonObject jo, AuthenticationData& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/client_device.cpp b/lib/csapi/definitions/client_device.cpp index 4a192f85..752b806a 100644 --- a/lib/csapi/definitions/client_device.cpp +++ b/lib/csapi/definitions/client_device.cpp @@ -6,28 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const Device& pod) +void JsonObjectConverter<Device>::dumpTo( + QJsonObject& jo, const Device& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("device_id"), pod.deviceId); addParam<IfNotEmpty>(jo, QStringLiteral("display_name"), pod.displayName); addParam<IfNotEmpty>(jo, QStringLiteral("last_seen_ip"), pod.lastSeenIp); addParam<IfNotEmpty>(jo, QStringLiteral("last_seen_ts"), pod.lastSeenTs); - return jo; } -Device FromJsonObject<Device>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<Device>::fillFrom( + const QJsonObject& jo, Device& result) { - Device result; - result.deviceId = - fromJson<QString>(jo.value("device_id"_ls)); - result.displayName = - fromJson<QString>(jo.value("display_name"_ls)); - result.lastSeenIp = - fromJson<QString>(jo.value("last_seen_ip"_ls)); - result.lastSeenTs = - fromJson<qint64>(jo.value("last_seen_ts"_ls)); - - return result; + fromJson(jo.value("device_id"_ls), result.deviceId); + fromJson(jo.value("display_name"_ls), result.displayName); + fromJson(jo.value("last_seen_ip"_ls), result.lastSeenIp); + fromJson(jo.value("last_seen_ts"_ls), result.lastSeenTs); } diff --git a/lib/csapi/definitions/client_device.h b/lib/csapi/definitions/client_device.h index 9f10888a..a6224f71 100644 --- a/lib/csapi/definitions/client_device.h +++ b/lib/csapi/definitions/client_device.h @@ -28,12 +28,10 @@ namespace QMatrixClient /// reasons). Omittable<qint64> lastSeenTs; }; - - QJsonObject toJson(const Device& pod); - - template <> struct FromJsonObject<Device> + template <> struct JsonObjectConverter<Device> { - Device operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const Device& pod); + static void fillFrom(const QJsonObject& jo, Device& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/device_keys.cpp b/lib/csapi/definitions/device_keys.cpp index a0e0ca42..1e79499f 100644 --- a/lib/csapi/definitions/device_keys.cpp +++ b/lib/csapi/definitions/device_keys.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const DeviceKeys& pod) +void JsonObjectConverter<DeviceKeys>::dumpTo( + QJsonObject& jo, const DeviceKeys& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("user_id"), pod.userId); addParam<>(jo, QStringLiteral("device_id"), pod.deviceId); addParam<>(jo, QStringLiteral("algorithms"), pod.algorithms); addParam<>(jo, QStringLiteral("keys"), pod.keys); addParam<>(jo, QStringLiteral("signatures"), pod.signatures); - return jo; } -DeviceKeys FromJsonObject<DeviceKeys>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<DeviceKeys>::fillFrom( + const QJsonObject& jo, DeviceKeys& result) { - DeviceKeys result; - result.userId = - fromJson<QString>(jo.value("user_id"_ls)); - result.deviceId = - fromJson<QString>(jo.value("device_id"_ls)); - result.algorithms = - fromJson<QStringList>(jo.value("algorithms"_ls)); - result.keys = - fromJson<QHash<QString, QString>>(jo.value("keys"_ls)); - result.signatures = - fromJson<QHash<QString, QHash<QString, QString>>>(jo.value("signatures"_ls)); - - return result; + fromJson(jo.value("user_id"_ls), result.userId); + fromJson(jo.value("device_id"_ls), result.deviceId); + fromJson(jo.value("algorithms"_ls), result.algorithms); + fromJson(jo.value("keys"_ls), result.keys); + fromJson(jo.value("signatures"_ls), result.signatures); } diff --git a/lib/csapi/definitions/device_keys.h b/lib/csapi/definitions/device_keys.h index 6023e7e8..8ebe1125 100644 --- a/lib/csapi/definitions/device_keys.h +++ b/lib/csapi/definitions/device_keys.h @@ -34,12 +34,10 @@ namespace QMatrixClient /// JSON`_. QHash<QString, QHash<QString, QString>> signatures; }; - - QJsonObject toJson(const DeviceKeys& pod); - - template <> struct FromJsonObject<DeviceKeys> + template <> struct JsonObjectConverter<DeviceKeys> { - DeviceKeys operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const DeviceKeys& pod); + static void fillFrom(const QJsonObject& jo, DeviceKeys& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/event_filter.cpp b/lib/csapi/definitions/event_filter.cpp index cc444db0..b20d7807 100644 --- a/lib/csapi/definitions/event_filter.cpp +++ b/lib/csapi/definitions/event_filter.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const EventFilter& pod) +void JsonObjectConverter<EventFilter>::dumpTo( + QJsonObject& jo, const EventFilter& pod) { - QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("limit"), pod.limit); addParam<IfNotEmpty>(jo, QStringLiteral("not_senders"), pod.notSenders); addParam<IfNotEmpty>(jo, QStringLiteral("not_types"), pod.notTypes); addParam<IfNotEmpty>(jo, QStringLiteral("senders"), pod.senders); addParam<IfNotEmpty>(jo, QStringLiteral("types"), pod.types); - return jo; } -EventFilter FromJsonObject<EventFilter>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<EventFilter>::fillFrom( + const QJsonObject& jo, EventFilter& result) { - EventFilter result; - result.limit = - fromJson<int>(jo.value("limit"_ls)); - result.notSenders = - fromJson<QStringList>(jo.value("not_senders"_ls)); - result.notTypes = - fromJson<QStringList>(jo.value("not_types"_ls)); - result.senders = - fromJson<QStringList>(jo.value("senders"_ls)); - result.types = - fromJson<QStringList>(jo.value("types"_ls)); - - return result; + fromJson(jo.value("limit"_ls), result.limit); + fromJson(jo.value("not_senders"_ls), result.notSenders); + fromJson(jo.value("not_types"_ls), result.notTypes); + fromJson(jo.value("senders"_ls), result.senders); + fromJson(jo.value("types"_ls), result.types); } diff --git a/lib/csapi/definitions/event_filter.h b/lib/csapi/definitions/event_filter.h index 5c6a5b27..6de1fe79 100644 --- a/lib/csapi/definitions/event_filter.h +++ b/lib/csapi/definitions/event_filter.h @@ -25,12 +25,10 @@ namespace QMatrixClient /// A list of event types to include. If this list is absent then all event types are included. A ``'*'`` can be used as a wildcard to match any sequence of characters. QStringList types; }; - - QJsonObject toJson(const EventFilter& pod); - - template <> struct FromJsonObject<EventFilter> + template <> struct JsonObjectConverter<EventFilter> { - EventFilter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const EventFilter& pod); + static void fillFrom(const QJsonObject& jo, EventFilter& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/public_rooms_response.cpp b/lib/csapi/definitions/public_rooms_response.cpp index 2f52501d..0d26662c 100644 --- a/lib/csapi/definitions/public_rooms_response.cpp +++ b/lib/csapi/definitions/public_rooms_response.cpp @@ -6,9 +6,9 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PublicRoomsChunk& pod) +void JsonObjectConverter<PublicRoomsChunk>::dumpTo( + QJsonObject& jo, const PublicRoomsChunk& pod) { - QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("aliases"), pod.aliases); addParam<IfNotEmpty>(jo, QStringLiteral("canonical_alias"), pod.canonicalAlias); addParam<IfNotEmpty>(jo, QStringLiteral("name"), pod.name); @@ -18,56 +18,37 @@ QJsonObject QMatrixClient::toJson(const PublicRoomsChunk& pod) addParam<>(jo, QStringLiteral("world_readable"), pod.worldReadable); addParam<>(jo, QStringLiteral("guest_can_join"), pod.guestCanJoin); addParam<IfNotEmpty>(jo, QStringLiteral("avatar_url"), pod.avatarUrl); - return jo; } -PublicRoomsChunk FromJsonObject<PublicRoomsChunk>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<PublicRoomsChunk>::fillFrom( + const QJsonObject& jo, PublicRoomsChunk& result) { - PublicRoomsChunk result; - result.aliases = - fromJson<QStringList>(jo.value("aliases"_ls)); - result.canonicalAlias = - fromJson<QString>(jo.value("canonical_alias"_ls)); - result.name = - fromJson<QString>(jo.value("name"_ls)); - result.numJoinedMembers = - fromJson<int>(jo.value("num_joined_members"_ls)); - result.roomId = - fromJson<QString>(jo.value("room_id"_ls)); - result.topic = - fromJson<QString>(jo.value("topic"_ls)); - result.worldReadable = - fromJson<bool>(jo.value("world_readable"_ls)); - result.guestCanJoin = - fromJson<bool>(jo.value("guest_can_join"_ls)); - result.avatarUrl = - fromJson<QString>(jo.value("avatar_url"_ls)); - - return result; + fromJson(jo.value("aliases"_ls), result.aliases); + 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); } -QJsonObject QMatrixClient::toJson(const PublicRoomsResponse& pod) +void JsonObjectConverter<PublicRoomsResponse>::dumpTo( + QJsonObject& jo, const PublicRoomsResponse& pod) { - QJsonObject jo; 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); - return jo; } -PublicRoomsResponse FromJsonObject<PublicRoomsResponse>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<PublicRoomsResponse>::fillFrom( + const QJsonObject& jo, PublicRoomsResponse& result) { - PublicRoomsResponse result; - result.chunk = - fromJson<QVector<PublicRoomsChunk>>(jo.value("chunk"_ls)); - result.nextBatch = - fromJson<QString>(jo.value("next_batch"_ls)); - result.prevBatch = - fromJson<QString>(jo.value("prev_batch"_ls)); - result.totalRoomCountEstimate = - fromJson<int>(jo.value("total_room_count_estimate"_ls)); - - return result; + fromJson(jo.value("chunk"_ls), result.chunk); + fromJson(jo.value("next_batch"_ls), result.nextBatch); + fromJson(jo.value("prev_batch"_ls), result.prevBatch); + fromJson(jo.value("total_room_count_estimate"_ls), result.totalRoomCountEstimate); } diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index 88c805ba..4c54ac25 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -36,12 +36,10 @@ namespace QMatrixClient /// The URL for the room's avatar, if one is set. QString avatarUrl; }; - - QJsonObject toJson(const PublicRoomsChunk& pod); - - template <> struct FromJsonObject<PublicRoomsChunk> + template <> struct JsonObjectConverter<PublicRoomsChunk> { - PublicRoomsChunk operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PublicRoomsChunk& pod); + static void fillFrom(const QJsonObject& jo, PublicRoomsChunk& pod); }; /// A list of the rooms on the server. @@ -61,12 +59,10 @@ namespace QMatrixClient /// server has an estimate. Omittable<int> totalRoomCountEstimate; }; - - QJsonObject toJson(const PublicRoomsResponse& pod); - - template <> struct FromJsonObject<PublicRoomsResponse> + template <> struct JsonObjectConverter<PublicRoomsResponse> { - PublicRoomsResponse operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PublicRoomsResponse& pod); + static void fillFrom(const QJsonObject& jo, PublicRoomsResponse& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/push_condition.cpp b/lib/csapi/definitions/push_condition.cpp index 045094bc..ace02755 100644 --- a/lib/csapi/definitions/push_condition.cpp +++ b/lib/csapi/definitions/push_condition.cpp @@ -6,28 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PushCondition& pod) +void JsonObjectConverter<PushCondition>::dumpTo( + QJsonObject& jo, const PushCondition& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("kind"), pod.kind); addParam<IfNotEmpty>(jo, QStringLiteral("key"), pod.key); addParam<IfNotEmpty>(jo, QStringLiteral("pattern"), pod.pattern); addParam<IfNotEmpty>(jo, QStringLiteral("is"), pod.is); - return jo; } -PushCondition FromJsonObject<PushCondition>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<PushCondition>::fillFrom( + const QJsonObject& jo, PushCondition& result) { - PushCondition result; - result.kind = - fromJson<QString>(jo.value("kind"_ls)); - result.key = - fromJson<QString>(jo.value("key"_ls)); - result.pattern = - fromJson<QString>(jo.value("pattern"_ls)); - result.is = - fromJson<QString>(jo.value("is"_ls)); - - return result; + fromJson(jo.value("kind"_ls), result.kind); + fromJson(jo.value("key"_ls), result.key); + fromJson(jo.value("pattern"_ls), result.pattern); + fromJson(jo.value("is"_ls), result.is); } diff --git a/lib/csapi/definitions/push_condition.h b/lib/csapi/definitions/push_condition.h index defcebb3..e45526d2 100644 --- a/lib/csapi/definitions/push_condition.h +++ b/lib/csapi/definitions/push_condition.h @@ -28,12 +28,10 @@ namespace QMatrixClient /// so forth. If no prefix is present, this parameter defaults to ==. QString is; }; - - QJsonObject toJson(const PushCondition& pod); - - template <> struct FromJsonObject<PushCondition> + template <> struct JsonObjectConverter<PushCondition> { - PushCondition operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PushCondition& pod); + static void fillFrom(const QJsonObject& jo, PushCondition& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/push_rule.cpp b/lib/csapi/definitions/push_rule.cpp index baddd187..abbb04b5 100644 --- a/lib/csapi/definitions/push_rule.cpp +++ b/lib/csapi/definitions/push_rule.cpp @@ -6,34 +6,25 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PushRule& pod) +void JsonObjectConverter<PushRule>::dumpTo( + QJsonObject& jo, const PushRule& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("actions"), pod.actions); addParam<>(jo, QStringLiteral("default"), pod.isDefault); addParam<>(jo, QStringLiteral("enabled"), pod.enabled); addParam<>(jo, QStringLiteral("rule_id"), pod.ruleId); addParam<IfNotEmpty>(jo, QStringLiteral("conditions"), pod.conditions); addParam<IfNotEmpty>(jo, QStringLiteral("pattern"), pod.pattern); - return jo; } -PushRule FromJsonObject<PushRule>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<PushRule>::fillFrom( + const QJsonObject& jo, PushRule& result) { - PushRule result; - result.actions = - fromJson<QVector<QVariant>>(jo.value("actions"_ls)); - result.isDefault = - fromJson<bool>(jo.value("default"_ls)); - result.enabled = - fromJson<bool>(jo.value("enabled"_ls)); - result.ruleId = - fromJson<QString>(jo.value("rule_id"_ls)); - result.conditions = - fromJson<QVector<PushCondition>>(jo.value("conditions"_ls)); - result.pattern = - fromJson<QString>(jo.value("pattern"_ls)); - - return result; + fromJson(jo.value("actions"_ls), result.actions); + fromJson(jo.value("default"_ls), result.isDefault); + fromJson(jo.value("enabled"_ls), result.enabled); + fromJson(jo.value("rule_id"_ls), result.ruleId); + fromJson(jo.value("conditions"_ls), result.conditions); + fromJson(jo.value("pattern"_ls), result.pattern); } diff --git a/lib/csapi/definitions/push_rule.h b/lib/csapi/definitions/push_rule.h index 5f52876d..bea13e96 100644 --- a/lib/csapi/definitions/push_rule.h +++ b/lib/csapi/definitions/push_rule.h @@ -7,10 +7,10 @@ #include "converters.h" #include "csapi/definitions/push_condition.h" -#include "converters.h" +#include <QtCore/QJsonObject> #include <QtCore/QVector> #include <QtCore/QVariant> -#include <QtCore/QJsonObject> +#include "converters.h" namespace QMatrixClient { @@ -34,12 +34,10 @@ namespace QMatrixClient /// rules. QString pattern; }; - - QJsonObject toJson(const PushRule& pod); - - template <> struct FromJsonObject<PushRule> + template <> struct JsonObjectConverter<PushRule> { - PushRule operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PushRule& pod); + static void fillFrom(const QJsonObject& jo, PushRule& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/push_ruleset.cpp b/lib/csapi/definitions/push_ruleset.cpp index 14b7a4b6..f1bad882 100644 --- a/lib/csapi/definitions/push_ruleset.cpp +++ b/lib/csapi/definitions/push_ruleset.cpp @@ -6,31 +6,23 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const PushRuleset& pod) +void JsonObjectConverter<PushRuleset>::dumpTo( + QJsonObject& jo, const PushRuleset& pod) { - QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("content"), pod.content); addParam<IfNotEmpty>(jo, QStringLiteral("override"), pod.override); addParam<IfNotEmpty>(jo, QStringLiteral("room"), pod.room); addParam<IfNotEmpty>(jo, QStringLiteral("sender"), pod.sender); addParam<IfNotEmpty>(jo, QStringLiteral("underride"), pod.underride); - return jo; } -PushRuleset FromJsonObject<PushRuleset>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<PushRuleset>::fillFrom( + const QJsonObject& jo, PushRuleset& result) { - PushRuleset result; - result.content = - fromJson<QVector<PushRule>>(jo.value("content"_ls)); - result.override = - fromJson<QVector<PushRule>>(jo.value("override"_ls)); - result.room = - fromJson<QVector<PushRule>>(jo.value("room"_ls)); - result.sender = - fromJson<QVector<PushRule>>(jo.value("sender"_ls)); - result.underride = - fromJson<QVector<PushRule>>(jo.value("underride"_ls)); - - return result; + fromJson(jo.value("content"_ls), result.content); + fromJson(jo.value("override"_ls), result.override); + fromJson(jo.value("room"_ls), result.room); + fromJson(jo.value("sender"_ls), result.sender); + fromJson(jo.value("underride"_ls), result.underride); } diff --git a/lib/csapi/definitions/push_ruleset.h b/lib/csapi/definitions/push_ruleset.h index a274b72a..f2d937c0 100644 --- a/lib/csapi/definitions/push_ruleset.h +++ b/lib/csapi/definitions/push_ruleset.h @@ -22,12 +22,10 @@ namespace QMatrixClient QVector<PushRule> sender; QVector<PushRule> underride; }; - - QJsonObject toJson(const PushRuleset& pod); - - template <> struct FromJsonObject<PushRuleset> + template <> struct JsonObjectConverter<PushRuleset> { - PushRuleset operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const PushRuleset& pod); + static void fillFrom(const QJsonObject& jo, PushRuleset& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/room_event_filter.cpp b/lib/csapi/definitions/room_event_filter.cpp index f6f1e5cb..df92e684 100644 --- a/lib/csapi/definitions/room_event_filter.cpp +++ b/lib/csapi/definitions/room_event_filter.cpp @@ -6,25 +6,21 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const RoomEventFilter& pod) +void JsonObjectConverter<RoomEventFilter>::dumpTo( + QJsonObject& jo, const RoomEventFilter& pod) { - QJsonObject jo; + fillJson<EventFilter>(jo, pod); addParam<IfNotEmpty>(jo, QStringLiteral("not_rooms"), pod.notRooms); addParam<IfNotEmpty>(jo, QStringLiteral("rooms"), pod.rooms); addParam<IfNotEmpty>(jo, QStringLiteral("contains_url"), pod.containsUrl); - return jo; } -RoomEventFilter FromJsonObject<RoomEventFilter>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<RoomEventFilter>::fillFrom( + const QJsonObject& jo, RoomEventFilter& result) { - RoomEventFilter result; - result.notRooms = - fromJson<QStringList>(jo.value("not_rooms"_ls)); - result.rooms = - fromJson<QStringList>(jo.value("rooms"_ls)); - result.containsUrl = - fromJson<bool>(jo.value("contains_url"_ls)); - - return result; + fillFromJson<EventFilter>(jo, result); + fromJson(jo.value("not_rooms"_ls), result.notRooms); + fromJson(jo.value("rooms"_ls), result.rooms); + fromJson(jo.value("contains_url"_ls), result.containsUrl); } diff --git a/lib/csapi/definitions/room_event_filter.h b/lib/csapi/definitions/room_event_filter.h index 697fe661..6eb9a390 100644 --- a/lib/csapi/definitions/room_event_filter.h +++ b/lib/csapi/definitions/room_event_filter.h @@ -19,15 +19,13 @@ namespace QMatrixClient QStringList notRooms; /// A list of room IDs to include. If this list is absent then all rooms are included. QStringList rooms; - /// If ``true``, includes only events with a ``url`` key in their content. If ``false``, excludes those events. Defaults to ``false``. - bool containsUrl; + /// If ``true``, includes only events with a ``url`` key in their content. If ``false``, excludes those events. If omitted, ``url`` key is not considered for filtering. + Omittable<bool> containsUrl; }; - - QJsonObject toJson(const RoomEventFilter& pod); - - template <> struct FromJsonObject<RoomEventFilter> + template <> struct JsonObjectConverter<RoomEventFilter> { - RoomEventFilter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const RoomEventFilter& pod); + static void fillFrom(const QJsonObject& jo, RoomEventFilter& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/sync_filter.cpp b/lib/csapi/definitions/sync_filter.cpp index bd87804c..32752d1f 100644 --- a/lib/csapi/definitions/sync_filter.cpp +++ b/lib/csapi/definitions/sync_filter.cpp @@ -6,9 +6,25 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const RoomFilter& pod) +void JsonObjectConverter<StateFilter>::dumpTo( + QJsonObject& jo, const StateFilter& pod) +{ + fillJson<RoomEventFilter>(jo, pod); + addParam<IfNotEmpty>(jo, QStringLiteral("lazy_load_members"), pod.lazyLoadMembers); + addParam<IfNotEmpty>(jo, QStringLiteral("include_redundant_members"), pod.includeRedundantMembers); +} + +void JsonObjectConverter<StateFilter>::fillFrom( + const QJsonObject& jo, StateFilter& result) +{ + fillFromJson<RoomEventFilter>(jo, result); + fromJson(jo.value("lazy_load_members"_ls), result.lazyLoadMembers); + fromJson(jo.value("include_redundant_members"_ls), result.includeRedundantMembers); +} + +void JsonObjectConverter<RoomFilter>::dumpTo( + QJsonObject& jo, const RoomFilter& pod) { - QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("not_rooms"), pod.notRooms); addParam<IfNotEmpty>(jo, QStringLiteral("rooms"), pod.rooms); addParam<IfNotEmpty>(jo, QStringLiteral("ephemeral"), pod.ephemeral); @@ -16,55 +32,37 @@ QJsonObject QMatrixClient::toJson(const RoomFilter& pod) addParam<IfNotEmpty>(jo, QStringLiteral("state"), pod.state); addParam<IfNotEmpty>(jo, QStringLiteral("timeline"), pod.timeline); addParam<IfNotEmpty>(jo, QStringLiteral("account_data"), pod.accountData); - return jo; } -RoomFilter FromJsonObject<RoomFilter>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<RoomFilter>::fillFrom( + const QJsonObject& jo, RoomFilter& result) { - RoomFilter result; - result.notRooms = - fromJson<QStringList>(jo.value("not_rooms"_ls)); - result.rooms = - fromJson<QStringList>(jo.value("rooms"_ls)); - result.ephemeral = - fromJson<RoomEventFilter>(jo.value("ephemeral"_ls)); - result.includeLeave = - fromJson<bool>(jo.value("include_leave"_ls)); - result.state = - fromJson<RoomEventFilter>(jo.value("state"_ls)); - result.timeline = - fromJson<RoomEventFilter>(jo.value("timeline"_ls)); - result.accountData = - fromJson<RoomEventFilter>(jo.value("account_data"_ls)); - - return result; + fromJson(jo.value("not_rooms"_ls), result.notRooms); + fromJson(jo.value("rooms"_ls), result.rooms); + fromJson(jo.value("ephemeral"_ls), result.ephemeral); + fromJson(jo.value("include_leave"_ls), result.includeLeave); + fromJson(jo.value("state"_ls), result.state); + fromJson(jo.value("timeline"_ls), result.timeline); + fromJson(jo.value("account_data"_ls), result.accountData); } -QJsonObject QMatrixClient::toJson(const Filter& pod) +void JsonObjectConverter<Filter>::dumpTo( + QJsonObject& jo, const Filter& pod) { - QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("event_fields"), pod.eventFields); addParam<IfNotEmpty>(jo, QStringLiteral("event_format"), pod.eventFormat); addParam<IfNotEmpty>(jo, QStringLiteral("presence"), pod.presence); addParam<IfNotEmpty>(jo, QStringLiteral("account_data"), pod.accountData); addParam<IfNotEmpty>(jo, QStringLiteral("room"), pod.room); - return jo; } -Filter FromJsonObject<Filter>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<Filter>::fillFrom( + const QJsonObject& jo, Filter& result) { - Filter result; - result.eventFields = - fromJson<QStringList>(jo.value("event_fields"_ls)); - result.eventFormat = - fromJson<QString>(jo.value("event_format"_ls)); - result.presence = - fromJson<EventFilter>(jo.value("presence"_ls)); - result.accountData = - fromJson<EventFilter>(jo.value("account_data"_ls)); - result.room = - fromJson<RoomFilter>(jo.value("room"_ls)); - - return result; + fromJson(jo.value("event_fields"_ls), result.eventFields); + fromJson(jo.value("event_format"_ls), result.eventFormat); + fromJson(jo.value("presence"_ls), result.presence); + fromJson(jo.value("account_data"_ls), result.accountData); + fromJson(jo.value("room"_ls), result.room); } diff --git a/lib/csapi/definitions/sync_filter.h b/lib/csapi/definitions/sync_filter.h index ca275a9a..d94c74d7 100644 --- a/lib/csapi/definitions/sync_filter.h +++ b/lib/csapi/definitions/sync_filter.h @@ -14,6 +14,37 @@ namespace QMatrixClient { // Data structures + /// The state events to include for rooms. + struct StateFilter : RoomEventFilter + { + /// If ``true``, the only ``m.room.member`` events returned in + /// the ``state`` section of the ``/sync`` response are those + /// which are definitely necessary for a client to display + /// the ``sender`` of the timeline events in that response. + /// If ``false``, ``m.room.member`` events are not filtered. + /// By default, servers should suppress duplicate redundant + /// lazy-loaded ``m.room.member`` events from being sent to a given + /// client across multiple calls to ``/sync``, given that most clients + /// cache membership events (see ``include_redundant_members`` + /// to change this behaviour). + Omittable<bool> lazyLoadMembers; + /// If ``true``, the ``state`` section of the ``/sync`` response will + /// always contain the ``m.room.member`` events required to display + /// the ``sender`` of the timeline events in that response, assuming + /// ``lazy_load_members`` is enabled. This means that redundant + /// duplicate member events may be returned across multiple calls to + /// ``/sync``. This is useful for naive clients who never track + /// membership data. If ``false``, duplicate ``m.room.member`` events + /// may be suppressed by the server across multiple calls to ``/sync``. + /// If ``lazy_load_members`` is ``false`` this field is ignored. + Omittable<bool> includeRedundantMembers; + }; + template <> struct JsonObjectConverter<StateFilter> + { + static void dumpTo(QJsonObject& jo, const StateFilter& pod); + static void fillFrom(const QJsonObject& jo, StateFilter& pod); + }; + /// Filters to be applied to room data. struct RoomFilter { @@ -24,20 +55,18 @@ namespace QMatrixClient /// The events that aren't recorded in the room history, e.g. typing and receipts, to include for rooms. Omittable<RoomEventFilter> ephemeral; /// Include rooms that the user has left in the sync, default false - bool includeLeave; + Omittable<bool> includeLeave; /// The state events to include for rooms. - Omittable<RoomEventFilter> state; + Omittable<StateFilter> state; /// The message and state update events to include for rooms. Omittable<RoomEventFilter> timeline; /// The per user account data to include for rooms. Omittable<RoomEventFilter> accountData; }; - - QJsonObject toJson(const RoomFilter& pod); - - template <> struct FromJsonObject<RoomFilter> + template <> struct JsonObjectConverter<RoomFilter> { - RoomFilter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const RoomFilter& pod); + static void fillFrom(const QJsonObject& jo, RoomFilter& pod); }; struct Filter @@ -53,12 +82,10 @@ namespace QMatrixClient /// Filters to be applied to room data. Omittable<RoomFilter> room; }; - - QJsonObject toJson(const Filter& pod); - - template <> struct FromJsonObject<Filter> + template <> struct JsonObjectConverter<Filter> { - Filter operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const Filter& pod); + static void fillFrom(const QJsonObject& jo, Filter& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/user_identifier.cpp b/lib/csapi/definitions/user_identifier.cpp index 80a6d450..05a27c1c 100644 --- a/lib/csapi/definitions/user_identifier.cpp +++ b/lib/csapi/definitions/user_identifier.cpp @@ -6,20 +6,18 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const UserIdentifier& pod) +void JsonObjectConverter<UserIdentifier>::dumpTo( + QJsonObject& jo, const UserIdentifier& pod) { - QJsonObject jo = toJson(pod.additionalProperties); + fillJson(jo, pod.additionalProperties); addParam<>(jo, QStringLiteral("type"), pod.type); - return jo; } -UserIdentifier FromJsonObject<UserIdentifier>::operator()(QJsonObject jo) const +void JsonObjectConverter<UserIdentifier>::fillFrom( + QJsonObject jo, UserIdentifier& result) { - UserIdentifier result; - result.type = - fromJson<QString>(jo.take("type"_ls)); + fromJson(jo.take("type"_ls), result.type); - result.additionalProperties = fromJson<QVariantHash>(jo); - return result; + fromJson(jo, result.additionalProperties); } diff --git a/lib/csapi/definitions/user_identifier.h b/lib/csapi/definitions/user_identifier.h index 42614436..cbb1550f 100644 --- a/lib/csapi/definitions/user_identifier.h +++ b/lib/csapi/definitions/user_identifier.h @@ -20,12 +20,10 @@ namespace QMatrixClient /// Identification information for a user QVariantHash additionalProperties; }; - - QJsonObject toJson(const UserIdentifier& pod); - - template <> struct FromJsonObject<UserIdentifier> + template <> struct JsonObjectConverter<UserIdentifier> { - UserIdentifier operator()(QJsonObject jo) const; + static void dumpTo(QJsonObject& jo, const UserIdentifier& pod); + static void fillFrom(QJsonObject jo, UserIdentifier& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/full.cpp b/lib/csapi/definitions/wellknown/full.cpp new file mode 100644 index 00000000..5ecef34f --- /dev/null +++ b/lib/csapi/definitions/wellknown/full.cpp @@ -0,0 +1,25 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "full.h" + +using namespace QMatrixClient; + +void JsonObjectConverter<DiscoveryInformation>::dumpTo( + QJsonObject& jo, const DiscoveryInformation& pod) +{ + fillJson(jo, pod.additionalProperties); + addParam<>(jo, QStringLiteral("m.homeserver"), pod.homeserver); + addParam<IfNotEmpty>(jo, QStringLiteral("m.identity_server"), pod.identityServer); +} + +void JsonObjectConverter<DiscoveryInformation>::fillFrom( + QJsonObject jo, DiscoveryInformation& result) +{ + fromJson(jo.take("m.homeserver"_ls), result.homeserver); + fromJson(jo.take("m.identity_server"_ls), result.identityServer); + + fromJson(jo, result.additionalProperties); +} + diff --git a/lib/csapi/definitions/wellknown/full.h b/lib/csapi/definitions/wellknown/full.h new file mode 100644 index 00000000..d9346acb --- /dev/null +++ b/lib/csapi/definitions/wellknown/full.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "converters.h" + +#include <QtCore/QJsonObject> +#include "converters.h" +#include "csapi/definitions/wellknown/homeserver.h" +#include "csapi/definitions/wellknown/identity_server.h" +#include <QtCore/QHash> + +namespace QMatrixClient +{ + // Data structures + + /// Used by clients to determine the homeserver, identity server, and other + /// optional components they should be interacting with. + struct DiscoveryInformation + { + /// Used by clients to determine the homeserver, identity server, and other + /// optional components they should be interacting with. + HomeserverInformation homeserver; + /// Used by clients to determine the homeserver, identity server, and other + /// optional components they should be interacting with. + Omittable<IdentityServerInformation> identityServer; + /// Application-dependent keys using Java package naming convention. + QHash<QString, QJsonObject> additionalProperties; + }; + template <> struct JsonObjectConverter<DiscoveryInformation> + { + static void dumpTo(QJsonObject& jo, const DiscoveryInformation& pod); + static void fillFrom(QJsonObject jo, DiscoveryInformation& pod); + }; + +} // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/homeserver.cpp b/lib/csapi/definitions/wellknown/homeserver.cpp index f1482ee4..0783f11b 100644 --- a/lib/csapi/definitions/wellknown/homeserver.cpp +++ b/lib/csapi/definitions/wellknown/homeserver.cpp @@ -6,19 +6,15 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const HomeserverInformation& pod) +void JsonObjectConverter<HomeserverInformation>::dumpTo( + QJsonObject& jo, const HomeserverInformation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("base_url"), pod.baseUrl); - return jo; } -HomeserverInformation FromJsonObject<HomeserverInformation>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<HomeserverInformation>::fillFrom( + const QJsonObject& jo, HomeserverInformation& result) { - HomeserverInformation result; - result.baseUrl = - fromJson<QString>(jo.value("base_url"_ls)); - - return result; + fromJson(jo.value("base_url"_ls), result.baseUrl); } diff --git a/lib/csapi/definitions/wellknown/homeserver.h b/lib/csapi/definitions/wellknown/homeserver.h index 09d6ba63..f6761c30 100644 --- a/lib/csapi/definitions/wellknown/homeserver.h +++ b/lib/csapi/definitions/wellknown/homeserver.h @@ -17,12 +17,10 @@ namespace QMatrixClient /// The base URL for the homeserver for client-server connections. QString baseUrl; }; - - QJsonObject toJson(const HomeserverInformation& pod); - - template <> struct FromJsonObject<HomeserverInformation> + template <> struct JsonObjectConverter<HomeserverInformation> { - HomeserverInformation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const HomeserverInformation& pod); + static void fillFrom(const QJsonObject& jo, HomeserverInformation& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/identity_server.cpp b/lib/csapi/definitions/wellknown/identity_server.cpp index f9d7bc37..99f36641 100644 --- a/lib/csapi/definitions/wellknown/identity_server.cpp +++ b/lib/csapi/definitions/wellknown/identity_server.cpp @@ -6,19 +6,15 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const IdentityServerInformation& pod) +void JsonObjectConverter<IdentityServerInformation>::dumpTo( + QJsonObject& jo, const IdentityServerInformation& pod) { - QJsonObject jo; addParam<>(jo, QStringLiteral("base_url"), pod.baseUrl); - return jo; } -IdentityServerInformation FromJsonObject<IdentityServerInformation>::operator()(const QJsonObject& jo) const +void JsonObjectConverter<IdentityServerInformation>::fillFrom( + const QJsonObject& jo, IdentityServerInformation& result) { - IdentityServerInformation result; - result.baseUrl = - fromJson<QString>(jo.value("base_url"_ls)); - - return result; + fromJson(jo.value("base_url"_ls), result.baseUrl); } diff --git a/lib/csapi/definitions/wellknown/identity_server.h b/lib/csapi/definitions/wellknown/identity_server.h index cb8ffcee..67d8b08d 100644 --- a/lib/csapi/definitions/wellknown/identity_server.h +++ b/lib/csapi/definitions/wellknown/identity_server.h @@ -17,12 +17,10 @@ namespace QMatrixClient /// The base URL for the identity server for client-server connections. QString baseUrl; }; - - QJsonObject toJson(const IdentityServerInformation& pod); - - template <> struct FromJsonObject<IdentityServerInformation> + template <> struct JsonObjectConverter<IdentityServerInformation> { - IdentityServerInformation operator()(const QJsonObject& jo) const; + static void dumpTo(QJsonObject& jo, const IdentityServerInformation& pod); + static void fillFrom(const QJsonObject& jo, IdentityServerInformation& pod); }; } // namespace QMatrixClient diff --git a/lib/csapi/device_management.cpp b/lib/csapi/device_management.cpp index 861e1994..9c31db5d 100644 --- a/lib/csapi/device_management.cpp +++ b/lib/csapi/device_management.cpp @@ -43,7 +43,7 @@ const QVector<Device>& GetDevicesJob::devices() const BaseJob::Status GetDevicesJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->devices = fromJson<QVector<Device>>(json.value("devices"_ls)); + fromJson(json.value("devices"_ls), d->devices); return Success; } @@ -77,7 +77,7 @@ const Device& GetDeviceJob::data() const BaseJob::Status GetDeviceJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Device>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/directory.cpp b/lib/csapi/directory.cpp index 5353f3bc..4af86f7b 100644 --- a/lib/csapi/directory.cpp +++ b/lib/csapi/directory.cpp @@ -60,8 +60,8 @@ const QStringList& GetRoomIdByAliasJob::servers() const BaseJob::Status GetRoomIdByAliasJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->roomId = fromJson<QString>(json.value("room_id"_ls)); - d->servers = fromJson<QStringList>(json.value("servers"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); + fromJson(json.value("servers"_ls), d->servers); return Success; } diff --git a/lib/csapi/event_context.cpp b/lib/csapi/event_context.cpp index 806c1613..bb1f5301 100644 --- a/lib/csapi/event_context.cpp +++ b/lib/csapi/event_context.cpp @@ -82,12 +82,12 @@ StateEvents&& GetEventContextJob::state() BaseJob::Status GetEventContextJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->begin = fromJson<QString>(json.value("start"_ls)); - d->end = fromJson<QString>(json.value("end"_ls)); - d->eventsBefore = fromJson<RoomEvents>(json.value("events_before"_ls)); - d->event = fromJson<RoomEventPtr>(json.value("event"_ls)); - d->eventsAfter = fromJson<RoomEvents>(json.value("events_after"_ls)); - d->state = fromJson<StateEvents>(json.value("state"_ls)); + fromJson(json.value("start"_ls), d->begin); + fromJson(json.value("end"_ls), d->end); + fromJson(json.value("events_before"_ls), d->eventsBefore); + fromJson(json.value("event"_ls), d->event); + fromJson(json.value("events_after"_ls), d->eventsAfter); + fromJson(json.value("state"_ls), d->state); return Success; } diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index 77dc9b92..982e60b5 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -41,7 +41,7 @@ BaseJob::Status DefineFilterJob::parseJson(const QJsonDocument& data) if (!json.contains("filter_id"_ls)) return { JsonParseError, "The key 'filter_id' not found in the response" }; - d->filterId = fromJson<QString>(json.value("filter_id"_ls)); + fromJson(json.value("filter_id"_ls), d->filterId); return Success; } @@ -75,7 +75,7 @@ const Filter& GetFilterJob::data() const BaseJob::Status GetFilterJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Filter>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/gtad.yaml b/lib/csapi/gtad.yaml index cb5e553c..a44f803a 100644 --- a/lib/csapi/gtad.yaml +++ b/lib/csapi/gtad.yaml @@ -5,12 +5,15 @@ analyzer: identifiers: signed: signedData unsigned: unsignedData - default: isDefault + PushRule/default: isDefault + default: defaultVersion # getCapabilities/RoomVersionsCapability origin_server_ts: originServerTimestamp # Instead of originServerTs start: begin # Because start() is a method in BaseJob m.upload.size: uploadSize m.homeserver: homeserver m.identity_server: identityServer + m.change_password: changePassword + m.room_versions: roomVersions AuthenticationData/additionalProperties: authInfo # Structure inside `types`: @@ -38,7 +41,7 @@ analyzer: - number: - float: float - //: double - - boolean: { type: bool, omittedValue: 'false' } + - boolean: bool - string: - byte: &ByteStream type: QIODevice* @@ -86,12 +89,9 @@ analyzer: - /m\.room\.member$/: type: "EventsArray<RoomMemberEvent>" imports: '"events/roommemberevent.h"' - - /state_event.yaml$/: - type: StateEvents - - /room_event.yaml$/: - type: RoomEvents - - /event.yaml$/: - type: Events + - /state_event.yaml$/: StateEvents + - /room_event.yaml$/: RoomEvents + - /event.yaml$/: Events - //: { type: "QVector<{{1}}>", imports: <QtCore/QVector> } - map: # `additionalProperties` in OpenAPI - RoomState: diff --git a/lib/csapi/joining.cpp b/lib/csapi/joining.cpp index 71781154..00d930fa 100644 --- a/lib/csapi/joining.cpp +++ b/lib/csapi/joining.cpp @@ -16,15 +16,16 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const JoinRoomByIdJob::ThirdPartySigned& pod) + template <> struct JsonObjectConverter<JoinRoomByIdJob::ThirdPartySigned> { - QJsonObject jo; - addParam<>(jo, QStringLiteral("sender"), pod.sender); - addParam<>(jo, QStringLiteral("mxid"), pod.mxid); - addParam<>(jo, QStringLiteral("token"), pod.token); - addParam<>(jo, QStringLiteral("signatures"), pod.signatures); - return jo; - } + static void dumpTo(QJsonObject& jo, const JoinRoomByIdJob::ThirdPartySigned& pod) + { + addParam<>(jo, QStringLiteral("sender"), pod.sender); + addParam<>(jo, QStringLiteral("mxid"), pod.mxid); + addParam<>(jo, QStringLiteral("token"), pod.token); + addParam<>(jo, QStringLiteral("signatures"), pod.signatures); + } + }; } // namespace QMatrixClient class JoinRoomByIdJob::Private @@ -58,7 +59,7 @@ BaseJob::Status JoinRoomByIdJob::parseJson(const QJsonDocument& data) if (!json.contains("room_id"_ls)) return { JsonParseError, "The key 'room_id' not found in the response" }; - d->roomId = fromJson<QString>(json.value("room_id"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); return Success; } @@ -66,22 +67,24 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const JoinRoomJob::Signed& pod) + template <> struct JsonObjectConverter<JoinRoomJob::Signed> { - QJsonObject jo; - addParam<>(jo, QStringLiteral("sender"), pod.sender); - addParam<>(jo, QStringLiteral("mxid"), pod.mxid); - addParam<>(jo, QStringLiteral("token"), pod.token); - addParam<>(jo, QStringLiteral("signatures"), pod.signatures); - return jo; - } - - QJsonObject toJson(const JoinRoomJob::ThirdPartySigned& pod) + static void dumpTo(QJsonObject& jo, const JoinRoomJob::Signed& pod) + { + addParam<>(jo, QStringLiteral("sender"), pod.sender); + addParam<>(jo, QStringLiteral("mxid"), pod.mxid); + addParam<>(jo, QStringLiteral("token"), pod.token); + addParam<>(jo, QStringLiteral("signatures"), pod.signatures); + } + }; + + template <> struct JsonObjectConverter<JoinRoomJob::ThirdPartySigned> { - QJsonObject jo; - addParam<>(jo, QStringLiteral("signed"), pod.signedData); - return jo; - } + static void dumpTo(QJsonObject& jo, const JoinRoomJob::ThirdPartySigned& pod) + { + addParam<>(jo, QStringLiteral("signed"), pod.signedData); + } + }; } // namespace QMatrixClient class JoinRoomJob::Private @@ -123,7 +126,7 @@ BaseJob::Status JoinRoomJob::parseJson(const QJsonDocument& data) if (!json.contains("room_id"_ls)) return { JsonParseError, "The key 'room_id' not found in the response" }; - d->roomId = fromJson<QString>(json.value("room_id"_ls)); + fromJson(json.value("room_id"_ls), d->roomId); return Success; } diff --git a/lib/csapi/joining.h b/lib/csapi/joining.h index 137afbfc..52c8ea42 100644 --- a/lib/csapi/joining.h +++ b/lib/csapi/joining.h @@ -59,7 +59,7 @@ namespace QMatrixClient // Result properties - /// The joined room id + /// The joined room ID. const QString& roomId() const; protected: @@ -138,7 +138,7 @@ namespace QMatrixClient // Result properties - /// The joined room id + /// The joined room ID. const QString& roomId() const; protected: diff --git a/lib/csapi/keys.cpp b/lib/csapi/keys.cpp index c7492411..6c16a8a3 100644 --- a/lib/csapi/keys.cpp +++ b/lib/csapi/keys.cpp @@ -44,7 +44,7 @@ BaseJob::Status UploadKeysJob::parseJson(const QJsonDocument& data) if (!json.contains("one_time_key_counts"_ls)) return { JsonParseError, "The key 'one_time_key_counts' not found in the response" }; - d->oneTimeKeyCounts = fromJson<QHash<QString, int>>(json.value("one_time_key_counts"_ls)); + fromJson(json.value("one_time_key_counts"_ls), d->oneTimeKeyCounts); return Success; } @@ -52,27 +52,20 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<QueryKeysJob::UnsignedDeviceInfo> + template <> struct JsonObjectConverter<QueryKeysJob::UnsignedDeviceInfo> { - QueryKeysJob::UnsignedDeviceInfo operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, QueryKeysJob::UnsignedDeviceInfo& result) { - QueryKeysJob::UnsignedDeviceInfo result; - result.deviceDisplayName = - fromJson<QString>(jo.value("device_display_name"_ls)); - - return result; + fromJson(jo.value("device_display_name"_ls), result.deviceDisplayName); } }; - template <> struct FromJsonObject<QueryKeysJob::DeviceInformation> + template <> struct JsonObjectConverter<QueryKeysJob::DeviceInformation> { - QueryKeysJob::DeviceInformation operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, QueryKeysJob::DeviceInformation& result) { - QueryKeysJob::DeviceInformation result; - result.unsignedData = - fromJson<QueryKeysJob::UnsignedDeviceInfo>(jo.value("unsigned"_ls)); - - return result; + fillFromJson<DeviceKeys>(jo, result); + fromJson(jo.value("unsigned"_ls), result.unsignedData); } }; } // namespace QMatrixClient @@ -113,8 +106,8 @@ const QHash<QString, QHash<QString, QueryKeysJob::DeviceInformation>>& QueryKeys BaseJob::Status QueryKeysJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->failures = fromJson<QHash<QString, QJsonObject>>(json.value("failures"_ls)); - d->deviceKeys = fromJson<QHash<QString, QHash<QString, DeviceInformation>>>(json.value("device_keys"_ls)); + fromJson(json.value("failures"_ls), d->failures); + fromJson(json.value("device_keys"_ls), d->deviceKeys); return Success; } @@ -153,8 +146,8 @@ const QHash<QString, QHash<QString, QVariant>>& ClaimKeysJob::oneTimeKeys() cons BaseJob::Status ClaimKeysJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->failures = fromJson<QHash<QString, QJsonObject>>(json.value("failures"_ls)); - d->oneTimeKeys = fromJson<QHash<QString, QHash<QString, QVariant>>>(json.value("one_time_keys"_ls)); + fromJson(json.value("failures"_ls), d->failures); + fromJson(json.value("one_time_keys"_ls), d->oneTimeKeys); return Success; } @@ -205,8 +198,8 @@ const QStringList& GetKeysChangesJob::left() const BaseJob::Status GetKeysChangesJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->changed = fromJson<QStringList>(json.value("changed"_ls)); - d->left = fromJson<QStringList>(json.value("left"_ls)); + fromJson(json.value("changed"_ls), d->changed); + fromJson(json.value("left"_ls), d->left); return Success; } diff --git a/lib/csapi/kicking.h b/lib/csapi/kicking.h index 5968187e..714079cf 100644 --- a/lib/csapi/kicking.h +++ b/lib/csapi/kicking.h @@ -29,7 +29,7 @@ namespace QMatrixClient * \param userId * The fully qualified user ID of the user being kicked. * \param reason - * The reason the user has been kicked. This will be supplied as the + * The reason the user has been kicked. This will be supplied as the * ``reason`` on the target's updated `m.room.member`_ event. */ explicit KickJob(const QString& roomId, const QString& userId, const QString& reason = {}); diff --git a/lib/csapi/list_joined_rooms.cpp b/lib/csapi/list_joined_rooms.cpp index a745dba1..85a9cae4 100644 --- a/lib/csapi/list_joined_rooms.cpp +++ b/lib/csapi/list_joined_rooms.cpp @@ -46,7 +46,7 @@ BaseJob::Status GetJoinedRoomsJob::parseJson(const QJsonDocument& data) if (!json.contains("joined_rooms"_ls)) return { JsonParseError, "The key 'joined_rooms' not found in the response" }; - d->joinedRooms = fromJson<QStringList>(json.value("joined_rooms"_ls)); + fromJson(json.value("joined_rooms"_ls), d->joinedRooms); return Success; } diff --git a/lib/csapi/list_public_rooms.cpp b/lib/csapi/list_public_rooms.cpp index 2fdb2005..71b3c541 100644 --- a/lib/csapi/list_public_rooms.cpp +++ b/lib/csapi/list_public_rooms.cpp @@ -43,7 +43,7 @@ const QString& GetRoomVisibilityOnDirectoryJob::visibility() const BaseJob::Status GetRoomVisibilityOnDirectoryJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->visibility = fromJson<QString>(json.value("visibility"_ls)); + fromJson(json.value("visibility"_ls), d->visibility); return Success; } @@ -100,7 +100,7 @@ const PublicRoomsResponse& GetPublicRoomsJob::data() const BaseJob::Status GetPublicRoomsJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<PublicRoomsResponse>(data); + fromJson(data, d->data); return Success; } @@ -108,12 +108,13 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const QueryPublicRoomsJob::Filter& pod) + template <> struct JsonObjectConverter<QueryPublicRoomsJob::Filter> { - QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("generic_search_term"), pod.genericSearchTerm); - return jo; - } + static void dumpTo(QJsonObject& jo, const QueryPublicRoomsJob::Filter& pod) + { + addParam<IfNotEmpty>(jo, QStringLiteral("generic_search_term"), pod.genericSearchTerm); + } + }; } // namespace QMatrixClient class QueryPublicRoomsJob::Private @@ -131,7 +132,7 @@ BaseJob::Query queryToQueryPublicRooms(const QString& server) static const auto QueryPublicRoomsJobName = QStringLiteral("QueryPublicRoomsJob"); -QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable<int> limit, const QString& since, const Omittable<Filter>& filter, bool includeAllNetworks, const QString& thirdPartyInstanceId) +QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable<int> limit, const QString& since, const Omittable<Filter>& filter, Omittable<bool> includeAllNetworks, const QString& thirdPartyInstanceId) : BaseJob(HttpVerb::Post, QueryPublicRoomsJobName, basePath % "/publicRooms", queryToQueryPublicRooms(server)) @@ -155,7 +156,7 @@ const PublicRoomsResponse& QueryPublicRoomsJob::data() const BaseJob::Status QueryPublicRoomsJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<PublicRoomsResponse>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/list_public_rooms.h b/lib/csapi/list_public_rooms.h index 8401c134..a6498745 100644 --- a/lib/csapi/list_public_rooms.h +++ b/lib/csapi/list_public_rooms.h @@ -156,7 +156,7 @@ namespace QMatrixClient * The specific third party network/protocol to request from the * homeserver. Can only be used if ``include_all_networks`` is false. */ - explicit QueryPublicRoomsJob(const QString& server = {}, Omittable<int> limit = none, const QString& since = {}, const Omittable<Filter>& filter = none, bool includeAllNetworks = false, const QString& thirdPartyInstanceId = {}); + explicit QueryPublicRoomsJob(const QString& server = {}, Omittable<int> limit = none, const QString& since = {}, const Omittable<Filter>& filter = none, Omittable<bool> includeAllNetworks = none, const QString& thirdPartyInstanceId = {}); ~QueryPublicRoomsJob() override; // Result properties diff --git a/lib/csapi/login.cpp b/lib/csapi/login.cpp index 4d15a30b..5e369b9a 100644 --- a/lib/csapi/login.cpp +++ b/lib/csapi/login.cpp @@ -16,15 +16,11 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetLoginFlowsJob::LoginFlow> + template <> struct JsonObjectConverter<GetLoginFlowsJob::LoginFlow> { - GetLoginFlowsJob::LoginFlow operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetLoginFlowsJob::LoginFlow& result) { - GetLoginFlowsJob::LoginFlow result; - result.type = - fromJson<QString>(jo.value("type"_ls)); - - return result; + fromJson(jo.value("type"_ls), result.type); } }; } // namespace QMatrixClient @@ -60,7 +56,7 @@ const QVector<GetLoginFlowsJob::LoginFlow>& GetLoginFlowsJob::flows() const BaseJob::Status GetLoginFlowsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->flows = fromJson<QVector<LoginFlow>>(json.value("flows"_ls)); + fromJson(json.value("flows"_ls), d->flows); return Success; } @@ -71,6 +67,7 @@ class LoginJob::Private QString accessToken; QString homeServer; QString deviceId; + Omittable<DiscoveryInformation> wellKnown; }; static const auto LoginJobName = QStringLiteral("LoginJob"); @@ -115,13 +112,19 @@ const QString& LoginJob::deviceId() const return d->deviceId; } +const Omittable<DiscoveryInformation>& LoginJob::wellKnown() const +{ + return d->wellKnown; +} + BaseJob::Status LoginJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->userId = fromJson<QString>(json.value("user_id"_ls)); - d->accessToken = fromJson<QString>(json.value("access_token"_ls)); - d->homeServer = fromJson<QString>(json.value("home_server"_ls)); - d->deviceId = fromJson<QString>(json.value("device_id"_ls)); + fromJson(json.value("user_id"_ls), d->userId); + fromJson(json.value("access_token"_ls), d->accessToken); + fromJson(json.value("home_server"_ls), d->homeServer); + fromJson(json.value("device_id"_ls), d->deviceId); + fromJson(json.value("well_known"_ls), d->wellKnown); return Success; } diff --git a/lib/csapi/login.h b/lib/csapi/login.h index 957d8881..648316df 100644 --- a/lib/csapi/login.h +++ b/lib/csapi/login.h @@ -7,6 +7,7 @@ #include "jobs/basejob.h" #include <QtCore/QVector> +#include "csapi/definitions/wellknown/full.h" #include "csapi/definitions/user_identifier.h" #include "converters.h" @@ -118,6 +119,11 @@ namespace QMatrixClient /// ID of the logged-in device. Will be the same as the /// corresponding parameter in the request, if one was specified. const QString& deviceId() const; + /// Optional client configuration provided by the server. If present, + /// clients SHOULD use the provided object to reconfigure themselves, + /// optionally validating the URLs within. This object takes the same + /// form as the one returned from .well-known autodiscovery. + const Omittable<DiscoveryInformation>& wellKnown() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/message_pagination.cpp b/lib/csapi/message_pagination.cpp index c59a51ab..9aca7ec9 100644 --- a/lib/csapi/message_pagination.cpp +++ b/lib/csapi/message_pagination.cpp @@ -68,9 +68,9 @@ RoomEvents&& GetRoomEventsJob::chunk() BaseJob::Status GetRoomEventsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->begin = fromJson<QString>(json.value("start"_ls)); - d->end = fromJson<QString>(json.value("end"_ls)); - d->chunk = fromJson<RoomEvents>(json.value("chunk"_ls)); + fromJson(json.value("start"_ls), d->begin); + fromJson(json.value("end"_ls), d->end); + fromJson(json.value("chunk"_ls), d->chunk); return Success; } diff --git a/lib/csapi/notifications.cpp b/lib/csapi/notifications.cpp index 785a0a8a..c00b7cb0 100644 --- a/lib/csapi/notifications.cpp +++ b/lib/csapi/notifications.cpp @@ -16,25 +16,16 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetNotificationsJob::Notification> + template <> struct JsonObjectConverter<GetNotificationsJob::Notification> { - GetNotificationsJob::Notification operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetNotificationsJob::Notification& result) { - GetNotificationsJob::Notification result; - result.actions = - fromJson<QVector<QVariant>>(jo.value("actions"_ls)); - result.event = - fromJson<EventPtr>(jo.value("event"_ls)); - result.profileTag = - fromJson<QString>(jo.value("profile_tag"_ls)); - result.read = - fromJson<bool>(jo.value("read"_ls)); - result.roomId = - fromJson<QString>(jo.value("room_id"_ls)); - result.ts = - fromJson<int>(jo.value("ts"_ls)); - - return result; + fromJson(jo.value("actions"_ls), result.actions); + fromJson(jo.value("event"_ls), result.event); + fromJson(jo.value("profile_tag"_ls), result.profileTag); + fromJson(jo.value("read"_ls), result.read); + fromJson(jo.value("room_id"_ls), result.roomId); + fromJson(jo.value("ts"_ls), result.ts); } }; } // namespace QMatrixClient @@ -87,11 +78,11 @@ std::vector<GetNotificationsJob::Notification>&& GetNotificationsJob::notificati BaseJob::Status GetNotificationsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->nextToken = fromJson<QString>(json.value("next_token"_ls)); + fromJson(json.value("next_token"_ls), d->nextToken); if (!json.contains("notifications"_ls)) return { JsonParseError, "The key 'notifications' not found in the response" }; - d->notifications = fromJson<std::vector<Notification>>(json.value("notifications"_ls)); + fromJson(json.value("notifications"_ls), d->notifications); return Success; } diff --git a/lib/csapi/openid.cpp b/lib/csapi/openid.cpp index 2547f0c8..b27fe0b8 100644 --- a/lib/csapi/openid.cpp +++ b/lib/csapi/openid.cpp @@ -59,19 +59,19 @@ BaseJob::Status RequestOpenIdTokenJob::parseJson(const QJsonDocument& data) if (!json.contains("access_token"_ls)) return { JsonParseError, "The key 'access_token' not found in the response" }; - d->accessToken = fromJson<QString>(json.value("access_token"_ls)); + fromJson(json.value("access_token"_ls), d->accessToken); if (!json.contains("token_type"_ls)) return { JsonParseError, "The key 'token_type' not found in the response" }; - d->tokenType = fromJson<QString>(json.value("token_type"_ls)); + fromJson(json.value("token_type"_ls), d->tokenType); if (!json.contains("matrix_server_name"_ls)) return { JsonParseError, "The key 'matrix_server_name' not found in the response" }; - d->matrixServerName = fromJson<QString>(json.value("matrix_server_name"_ls)); + fromJson(json.value("matrix_server_name"_ls), d->matrixServerName); if (!json.contains("expires_in"_ls)) return { JsonParseError, "The key 'expires_in' not found in the response" }; - d->expiresIn = fromJson<int>(json.value("expires_in"_ls)); + fromJson(json.value("expires_in"_ls), d->expiresIn); return Success; } diff --git a/lib/csapi/peeking_events.cpp b/lib/csapi/peeking_events.cpp index e046a62e..3208d48d 100644 --- a/lib/csapi/peeking_events.cpp +++ b/lib/csapi/peeking_events.cpp @@ -66,9 +66,9 @@ RoomEvents&& PeekEventsJob::chunk() BaseJob::Status PeekEventsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->begin = fromJson<QString>(json.value("start"_ls)); - d->end = fromJson<QString>(json.value("end"_ls)); - d->chunk = fromJson<RoomEvents>(json.value("chunk"_ls)); + fromJson(json.value("start"_ls), d->begin); + fromJson(json.value("end"_ls), d->end); + fromJson(json.value("chunk"_ls), d->chunk); return Success; } diff --git a/lib/csapi/presence.cpp b/lib/csapi/presence.cpp index 7aba8b61..024d7a34 100644 --- a/lib/csapi/presence.cpp +++ b/lib/csapi/presence.cpp @@ -30,7 +30,7 @@ class GetPresenceJob::Private QString presence; Omittable<int> lastActiveAgo; QString statusMsg; - bool currentlyActive; + Omittable<bool> currentlyActive; }; QUrl GetPresenceJob::makeRequestUrl(QUrl baseUrl, const QString& userId) @@ -65,7 +65,7 @@ const QString& GetPresenceJob::statusMsg() const return d->statusMsg; } -bool GetPresenceJob::currentlyActive() const +Omittable<bool> GetPresenceJob::currentlyActive() const { return d->currentlyActive; } @@ -76,56 +76,10 @@ BaseJob::Status GetPresenceJob::parseJson(const QJsonDocument& data) if (!json.contains("presence"_ls)) return { JsonParseError, "The key 'presence' not found in the response" }; - d->presence = fromJson<QString>(json.value("presence"_ls)); - d->lastActiveAgo = fromJson<int>(json.value("last_active_ago"_ls)); - d->statusMsg = fromJson<QString>(json.value("status_msg"_ls)); - d->currentlyActive = fromJson<bool>(json.value("currently_active"_ls)); - return Success; -} - -static const auto ModifyPresenceListJobName = QStringLiteral("ModifyPresenceListJob"); - -ModifyPresenceListJob::ModifyPresenceListJob(const QString& userId, const QStringList& invite, const QStringList& drop) - : BaseJob(HttpVerb::Post, ModifyPresenceListJobName, - basePath % "/presence/list/" % userId) -{ - QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("invite"), invite); - addParam<IfNotEmpty>(_data, QStringLiteral("drop"), drop); - setRequestData(_data); -} - -class GetPresenceForListJob::Private -{ - public: - Events data; -}; - -QUrl GetPresenceForListJob::makeRequestUrl(QUrl baseUrl, const QString& userId) -{ - return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/presence/list/" % userId); -} - -static const auto GetPresenceForListJobName = QStringLiteral("GetPresenceForListJob"); - -GetPresenceForListJob::GetPresenceForListJob(const QString& userId) - : BaseJob(HttpVerb::Get, GetPresenceForListJobName, - basePath % "/presence/list/" % userId, false) - , d(new Private) -{ -} - -GetPresenceForListJob::~GetPresenceForListJob() = default; - -Events&& GetPresenceForListJob::data() -{ - return std::move(d->data); -} - -BaseJob::Status GetPresenceForListJob::parseJson(const QJsonDocument& data) -{ - d->data = fromJson<Events>(data); + fromJson(json.value("presence"_ls), d->presence); + fromJson(json.value("last_active_ago"_ls), d->lastActiveAgo); + fromJson(json.value("status_msg"_ls), d->statusMsg); + fromJson(json.value("currently_active"_ls), d->currentlyActive); return Success; } diff --git a/lib/csapi/presence.h b/lib/csapi/presence.h index 86b9d395..5e132d24 100644 --- a/lib/csapi/presence.h +++ b/lib/csapi/presence.h @@ -6,7 +6,6 @@ #include "jobs/basejob.h" -#include "events/eventloader.h" #include "converters.h" namespace QMatrixClient @@ -65,59 +64,7 @@ namespace QMatrixClient /// The state message for this user if one was set. const QString& statusMsg() const; /// Whether the user is currently active - bool currentlyActive() const; - - protected: - Status parseJson(const QJsonDocument& data) override; - - private: - class Private; - QScopedPointer<Private> d; - }; - - /// Add or remove users from this presence list. - /// - /// Adds or removes users from this presence list. - class ModifyPresenceListJob : public BaseJob - { - public: - /*! Add or remove users from this presence list. - * \param userId - * The user whose presence list is being modified. - * \param invite - * A list of user IDs to add to the list. - * \param drop - * A list of user IDs to remove from the list. - */ - explicit ModifyPresenceListJob(const QString& userId, const QStringList& invite = {}, const QStringList& drop = {}); - }; - - /// Get presence events for this presence list. - /// - /// Retrieve a list of presence events for every user on this list. - class GetPresenceForListJob : public BaseJob - { - public: - /*! Get presence events for this presence list. - * \param userId - * The user whose presence list should be retrieved. - */ - explicit GetPresenceForListJob(const QString& userId); - - /*! Construct a URL without creating a full-fledged job object - * - * This function can be used when a URL for - * GetPresenceForListJob is necessary but the job - * itself isn't. - */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& userId); - - ~GetPresenceForListJob() override; - - // Result properties - - /// A list of presence events for this list. - Events&& data(); + Omittable<bool> currentlyActive() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/profile.cpp b/lib/csapi/profile.cpp index bb053062..4ed3ad9b 100644 --- a/lib/csapi/profile.cpp +++ b/lib/csapi/profile.cpp @@ -54,7 +54,7 @@ const QString& GetDisplayNameJob::displayname() const BaseJob::Status GetDisplayNameJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->displayname = fromJson<QString>(json.value("displayname"_ls)); + fromJson(json.value("displayname"_ls), d->displayname); return Success; } @@ -100,7 +100,7 @@ const QString& GetAvatarUrlJob::avatarUrl() const BaseJob::Status GetAvatarUrlJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->avatarUrl = fromJson<QString>(json.value("avatar_url"_ls)); + fromJson(json.value("avatar_url"_ls), d->avatarUrl); return Success; } @@ -141,8 +141,8 @@ const QString& GetUserProfileJob::displayname() const BaseJob::Status GetUserProfileJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->avatarUrl = fromJson<QString>(json.value("avatar_url"_ls)); - d->displayname = fromJson<QString>(json.value("displayname"_ls)); + fromJson(json.value("avatar_url"_ls), d->avatarUrl); + fromJson(json.value("displayname"_ls), d->displayname); return Success; } diff --git a/lib/csapi/pusher.cpp b/lib/csapi/pusher.cpp index d20db88a..664959f4 100644 --- a/lib/csapi/pusher.cpp +++ b/lib/csapi/pusher.cpp @@ -16,43 +16,27 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetPushersJob::PusherData> + template <> struct JsonObjectConverter<GetPushersJob::PusherData> { - GetPushersJob::PusherData operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetPushersJob::PusherData& result) { - GetPushersJob::PusherData result; - result.url = - fromJson<QString>(jo.value("url"_ls)); - result.format = - fromJson<QString>(jo.value("format"_ls)); - - return result; + fromJson(jo.value("url"_ls), result.url); + fromJson(jo.value("format"_ls), result.format); } }; - template <> struct FromJsonObject<GetPushersJob::Pusher> + template <> struct JsonObjectConverter<GetPushersJob::Pusher> { - GetPushersJob::Pusher operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetPushersJob::Pusher& result) { - GetPushersJob::Pusher result; - result.pushkey = - fromJson<QString>(jo.value("pushkey"_ls)); - result.kind = - fromJson<QString>(jo.value("kind"_ls)); - result.appId = - fromJson<QString>(jo.value("app_id"_ls)); - result.appDisplayName = - fromJson<QString>(jo.value("app_display_name"_ls)); - result.deviceDisplayName = - fromJson<QString>(jo.value("device_display_name"_ls)); - result.profileTag = - fromJson<QString>(jo.value("profile_tag"_ls)); - result.lang = - fromJson<QString>(jo.value("lang"_ls)); - result.data = - fromJson<GetPushersJob::PusherData>(jo.value("data"_ls)); - - return result; + fromJson(jo.value("pushkey"_ls), result.pushkey); + fromJson(jo.value("kind"_ls), result.kind); + fromJson(jo.value("app_id"_ls), result.appId); + fromJson(jo.value("app_display_name"_ls), result.appDisplayName); + fromJson(jo.value("device_display_name"_ls), result.deviceDisplayName); + fromJson(jo.value("profile_tag"_ls), result.profileTag); + fromJson(jo.value("lang"_ls), result.lang); + fromJson(jo.value("data"_ls), result.data); } }; } // namespace QMatrixClient @@ -88,7 +72,7 @@ const QVector<GetPushersJob::Pusher>& GetPushersJob::pushers() const BaseJob::Status GetPushersJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->pushers = fromJson<QVector<Pusher>>(json.value("pushers"_ls)); + fromJson(json.value("pushers"_ls), d->pushers); return Success; } @@ -96,18 +80,19 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const PostPusherJob::PusherData& pod) + template <> struct JsonObjectConverter<PostPusherJob::PusherData> { - QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("url"), pod.url); - addParam<IfNotEmpty>(jo, QStringLiteral("format"), pod.format); - return jo; - } + static void dumpTo(QJsonObject& jo, const PostPusherJob::PusherData& pod) + { + addParam<IfNotEmpty>(jo, QStringLiteral("url"), pod.url); + addParam<IfNotEmpty>(jo, QStringLiteral("format"), pod.format); + } + }; } // namespace QMatrixClient static const auto PostPusherJobName = QStringLiteral("PostPusherJob"); -PostPusherJob::PostPusherJob(const QString& pushkey, const QString& kind, const QString& appId, const QString& appDisplayName, const QString& deviceDisplayName, const QString& lang, const PusherData& data, const QString& profileTag, bool append) +PostPusherJob::PostPusherJob(const QString& pushkey, const QString& kind, const QString& appId, const QString& appDisplayName, const QString& deviceDisplayName, const QString& lang, const PusherData& data, const QString& profileTag, Omittable<bool> append) : BaseJob(HttpVerb::Post, PostPusherJobName, basePath % "/pushers/set") { diff --git a/lib/csapi/pusher.h b/lib/csapi/pusher.h index 2b506183..da3303fe 100644 --- a/lib/csapi/pusher.h +++ b/lib/csapi/pusher.h @@ -164,6 +164,6 @@ namespace QMatrixClient * other pushers with the same App ID and pushkey for different * users. The default is ``false``. */ - explicit PostPusherJob(const QString& pushkey, const QString& kind, const QString& appId, const QString& appDisplayName, const QString& deviceDisplayName, const QString& lang, const PusherData& data, const QString& profileTag = {}, bool append = false); + explicit PostPusherJob(const QString& pushkey, const QString& kind, const QString& appId, const QString& appDisplayName, const QString& deviceDisplayName, const QString& lang, const PusherData& data, const QString& profileTag = {}, Omittable<bool> append = none); }; } // namespace QMatrixClient diff --git a/lib/csapi/pushrules.cpp b/lib/csapi/pushrules.cpp index ea8ad02a..b91d18f7 100644 --- a/lib/csapi/pushrules.cpp +++ b/lib/csapi/pushrules.cpp @@ -46,7 +46,7 @@ BaseJob::Status GetPushRulesJob::parseJson(const QJsonDocument& data) if (!json.contains("global"_ls)) return { JsonParseError, "The key 'global' not found in the response" }; - d->global = fromJson<PushRuleset>(json.value("global"_ls)); + fromJson(json.value("global"_ls), d->global); return Success; } @@ -80,7 +80,7 @@ const PushRule& GetPushRuleJob::data() const BaseJob::Status GetPushRuleJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<PushRule>(data); + fromJson(data, d->data); return Success; } @@ -154,7 +154,7 @@ BaseJob::Status IsPushRuleEnabledJob::parseJson(const QJsonDocument& data) if (!json.contains("enabled"_ls)) return { JsonParseError, "The key 'enabled' not found in the response" }; - d->enabled = fromJson<bool>(json.value("enabled"_ls)); + fromJson(json.value("enabled"_ls), d->enabled); return Success; } @@ -203,7 +203,7 @@ BaseJob::Status GetPushRuleActionsJob::parseJson(const QJsonDocument& data) if (!json.contains("actions"_ls)) return { JsonParseError, "The key 'actions' not found in the response" }; - d->actions = fromJson<QStringList>(json.value("actions"_ls)); + fromJson(json.value("actions"_ls), d->actions); return Success; } diff --git a/lib/csapi/read_markers.h b/lib/csapi/read_markers.h index f19f46b0..d982b477 100644 --- a/lib/csapi/read_markers.h +++ b/lib/csapi/read_markers.h @@ -26,7 +26,7 @@ namespace QMatrixClient * event MUST belong to the room. * \param mRead * The event ID to set the read receipt location at. This is - * equivalent to calling ``/receipt/m.read/$elsewhere:domain.com`` + * equivalent to calling ``/receipt/m.read/$elsewhere:example.org`` * and is provided here to save that extra call. */ explicit SetReadMarkerJob(const QString& roomId, const QString& mFullyRead, const QString& mRead = {}); diff --git a/lib/csapi/redaction.cpp b/lib/csapi/redaction.cpp index 64098670..1d54e36d 100644 --- a/lib/csapi/redaction.cpp +++ b/lib/csapi/redaction.cpp @@ -40,7 +40,7 @@ const QString& RedactEventJob::eventId() const BaseJob::Status RedactEventJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson<QString>(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index 320ec796..5dc9c1e5 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -30,7 +30,7 @@ BaseJob::Query queryToRegister(const QString& kind) static const auto RegisterJobName = QStringLiteral("RegisterJob"); -RegisterJob::RegisterJob(const QString& kind, const Omittable<AuthenticationData>& auth, bool bindEmail, const QString& username, const QString& password, const QString& deviceId, const QString& initialDeviceDisplayName, bool inhibitLogin) +RegisterJob::RegisterJob(const QString& kind, const Omittable<AuthenticationData>& auth, Omittable<bool> bindEmail, const QString& username, const QString& password, const QString& deviceId, const QString& initialDeviceDisplayName, Omittable<bool> inhibitLogin) : BaseJob(HttpVerb::Post, RegisterJobName, basePath % "/register", queryToRegister(kind), @@ -76,10 +76,10 @@ BaseJob::Status RegisterJob::parseJson(const QJsonDocument& data) if (!json.contains("user_id"_ls)) return { JsonParseError, "The key 'user_id' not found in the response" }; - d->userId = fromJson<QString>(json.value("user_id"_ls)); - d->accessToken = fromJson<QString>(json.value("access_token"_ls)); - d->homeServer = fromJson<QString>(json.value("home_server"_ls)); - d->deviceId = fromJson<QString>(json.value("device_id"_ls)); + fromJson(json.value("user_id"_ls), d->userId); + fromJson(json.value("access_token"_ls), d->accessToken); + fromJson(json.value("home_server"_ls), d->homeServer); + fromJson(json.value("device_id"_ls), d->deviceId); return Success; } @@ -114,7 +114,7 @@ const Sid& RequestTokenToRegisterEmailJob::data() const BaseJob::Status RequestTokenToRegisterEmailJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Sid>(data); + fromJson(data, d->data); return Success; } @@ -150,7 +150,7 @@ const Sid& RequestTokenToRegisterMSISDNJob::data() const BaseJob::Status RequestTokenToRegisterMSISDNJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Sid>(data); + fromJson(data, d->data); return Success; } @@ -197,7 +197,7 @@ const Sid& RequestTokenToResetPasswordEmailJob::data() const BaseJob::Status RequestTokenToResetPasswordEmailJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Sid>(data); + fromJson(data, d->data); return Success; } @@ -233,7 +233,7 @@ const Sid& RequestTokenToResetPasswordMSISDNJob::data() const BaseJob::Status RequestTokenToResetPasswordMSISDNJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<Sid>(data); + fromJson(data, d->data); return Success; } @@ -251,7 +251,7 @@ DeactivateAccountJob::DeactivateAccountJob(const Omittable<AuthenticationData>& class CheckUsernameAvailabilityJob::Private { public: - bool available; + Omittable<bool> available; }; BaseJob::Query queryToCheckUsernameAvailability(const QString& username) @@ -281,7 +281,7 @@ CheckUsernameAvailabilityJob::CheckUsernameAvailabilityJob(const QString& userna CheckUsernameAvailabilityJob::~CheckUsernameAvailabilityJob() = default; -bool CheckUsernameAvailabilityJob::available() const +Omittable<bool> CheckUsernameAvailabilityJob::available() const { return d->available; } @@ -289,7 +289,7 @@ bool CheckUsernameAvailabilityJob::available() const BaseJob::Status CheckUsernameAvailabilityJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->available = fromJson<bool>(json.value("available"_ls)); + fromJson(json.value("available"_ls), d->available); return Success; } diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h index 9002b5c8..ca1a1c21 100644 --- a/lib/csapi/registration.h +++ b/lib/csapi/registration.h @@ -80,7 +80,7 @@ namespace QMatrixClient * returned from this call, therefore preventing an automatic * login. Defaults to false. */ - explicit RegisterJob(const QString& kind = QStringLiteral("user"), const Omittable<AuthenticationData>& auth = none, bool bindEmail = false, const QString& username = {}, const QString& password = {}, const QString& deviceId = {}, const QString& initialDeviceDisplayName = {}, bool inhibitLogin = false); + explicit RegisterJob(const QString& kind = QStringLiteral("user"), const Omittable<AuthenticationData>& auth = none, Omittable<bool> bindEmail = none, const QString& username = {}, const QString& password = {}, const QString& deviceId = {}, const QString& initialDeviceDisplayName = {}, Omittable<bool> inhibitLogin = none); ~RegisterJob() override; // Result properties @@ -418,7 +418,7 @@ namespace QMatrixClient /// A flag to indicate that the username is available. This should always /// be ``true`` when the server replies with 200 OK. - bool available() const; + Omittable<bool> available() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/room_send.cpp b/lib/csapi/room_send.cpp index 2b39ede2..0d25eb69 100644 --- a/lib/csapi/room_send.cpp +++ b/lib/csapi/room_send.cpp @@ -38,7 +38,7 @@ const QString& SendMessageJob::eventId() const BaseJob::Status SendMessageJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson<QString>(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } diff --git a/lib/csapi/room_state.cpp b/lib/csapi/room_state.cpp index 8f87979d..3aa7d736 100644 --- a/lib/csapi/room_state.cpp +++ b/lib/csapi/room_state.cpp @@ -38,7 +38,7 @@ const QString& SetRoomStateWithKeyJob::eventId() const BaseJob::Status SetRoomStateWithKeyJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson<QString>(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } @@ -68,7 +68,7 @@ const QString& SetRoomStateJob::eventId() const BaseJob::Status SetRoomStateJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->eventId = fromJson<QString>(json.value("event_id"_ls)); + fromJson(json.value("event_id"_ls), d->eventId); return Success; } diff --git a/lib/csapi/room_upgrades.cpp b/lib/csapi/room_upgrades.cpp new file mode 100644 index 00000000..f58fd675 --- /dev/null +++ b/lib/csapi/room_upgrades.cpp @@ -0,0 +1,49 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "room_upgrades.h" + +#include "converters.h" + +#include <QtCore/QStringBuilder> + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +class UpgradeRoomJob::Private +{ + public: + QString replacementRoom; +}; + +static const auto UpgradeRoomJobName = QStringLiteral("UpgradeRoomJob"); + +UpgradeRoomJob::UpgradeRoomJob(const QString& roomId, const QString& newVersion) + : BaseJob(HttpVerb::Post, UpgradeRoomJobName, + basePath % "/rooms/" % roomId % "/upgrade") + , d(new Private) +{ + QJsonObject _data; + addParam<>(_data, QStringLiteral("new_version"), newVersion); + setRequestData(_data); +} + +UpgradeRoomJob::~UpgradeRoomJob() = default; + +const QString& UpgradeRoomJob::replacementRoom() const +{ + return d->replacementRoom; +} + +BaseJob::Status UpgradeRoomJob::parseJson(const QJsonDocument& data) +{ + auto json = data.object(); + if (!json.contains("replacement_room"_ls)) + return { JsonParseError, + "The key 'replacement_room' not found in the response" }; + fromJson(json.value("replacement_room"_ls), d->replacementRoom); + return Success; +} + diff --git a/lib/csapi/room_upgrades.h b/lib/csapi/room_upgrades.h new file mode 100644 index 00000000..4da5941a --- /dev/null +++ b/lib/csapi/room_upgrades.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + + +namespace QMatrixClient +{ + // Operations + + /// Upgrades a room to a new room version. + /// + /// Upgrades the given room to a particular room version. + class UpgradeRoomJob : public BaseJob + { + public: + /*! Upgrades a room to a new room version. + * \param roomId + * The ID of the room to upgrade. + * \param newVersion + * The new version for the room. + */ + explicit UpgradeRoomJob(const QString& roomId, const QString& newVersion); + ~UpgradeRoomJob() override; + + // Result properties + + /// The ID of the new room. + const QString& replacementRoom() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; + }; +} // namespace QMatrixClient diff --git a/lib/csapi/rooms.cpp b/lib/csapi/rooms.cpp index 3befeee5..0b08ccec 100644 --- a/lib/csapi/rooms.cpp +++ b/lib/csapi/rooms.cpp @@ -42,16 +42,10 @@ EventPtr&& GetOneRoomEventJob::data() BaseJob::Status GetOneRoomEventJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<EventPtr>(data); + fromJson(data, d->data); return Success; } -class GetRoomStateWithKeyJob::Private -{ - public: - StateEventPtr data; -}; - QUrl GetRoomStateWithKeyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& eventType, const QString& stateKey) { return BaseJob::makeRequestUrl(std::move(baseUrl), @@ -63,29 +57,9 @@ static const auto GetRoomStateWithKeyJobName = QStringLiteral("GetRoomStateWithK GetRoomStateWithKeyJob::GetRoomStateWithKeyJob(const QString& roomId, const QString& eventType, const QString& stateKey) : BaseJob(HttpVerb::Get, GetRoomStateWithKeyJobName, basePath % "/rooms/" % roomId % "/state/" % eventType % "/" % stateKey) - , d(new Private) -{ -} - -GetRoomStateWithKeyJob::~GetRoomStateWithKeyJob() = default; - -StateEventPtr&& GetRoomStateWithKeyJob::data() -{ - return std::move(d->data); -} - -BaseJob::Status GetRoomStateWithKeyJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<StateEventPtr>(data); - return Success; } -class GetRoomStateByTypeJob::Private -{ - public: - StateEventPtr data; -}; - QUrl GetRoomStateByTypeJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& eventType) { return BaseJob::makeRequestUrl(std::move(baseUrl), @@ -97,21 +71,7 @@ static const auto GetRoomStateByTypeJobName = QStringLiteral("GetRoomStateByType GetRoomStateByTypeJob::GetRoomStateByTypeJob(const QString& roomId, const QString& eventType) : BaseJob(HttpVerb::Get, GetRoomStateByTypeJobName, basePath % "/rooms/" % roomId % "/state/" % eventType) - , d(new Private) -{ -} - -GetRoomStateByTypeJob::~GetRoomStateByTypeJob() = default; - -StateEventPtr&& GetRoomStateByTypeJob::data() -{ - return std::move(d->data); -} - -BaseJob::Status GetRoomStateByTypeJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<StateEventPtr>(data); - return Success; } class GetRoomStateJob::Private @@ -144,7 +104,7 @@ StateEvents&& GetRoomStateJob::data() BaseJob::Status GetRoomStateJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<StateEvents>(data); + fromJson(data, d->data); return Success; } @@ -154,17 +114,28 @@ class GetMembersByRoomJob::Private EventsArray<RoomMemberEvent> chunk; }; -QUrl GetMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) +BaseJob::Query queryToGetMembersByRoom(const QString& at, const QString& membership, const QString& notMembership) +{ + BaseJob::Query _q; + addParam<IfNotEmpty>(_q, QStringLiteral("at"), at); + addParam<IfNotEmpty>(_q, QStringLiteral("membership"), membership); + addParam<IfNotEmpty>(_q, QStringLiteral("not_membership"), notMembership); + return _q; +} + +QUrl GetMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& at, const QString& membership, const QString& notMembership) { return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/rooms/" % roomId % "/members"); + basePath % "/rooms/" % roomId % "/members", + queryToGetMembersByRoom(at, membership, notMembership)); } static const auto GetMembersByRoomJobName = QStringLiteral("GetMembersByRoomJob"); -GetMembersByRoomJob::GetMembersByRoomJob(const QString& roomId) +GetMembersByRoomJob::GetMembersByRoomJob(const QString& roomId, const QString& at, const QString& membership, const QString& notMembership) : BaseJob(HttpVerb::Get, GetMembersByRoomJobName, - basePath % "/rooms/" % roomId % "/members") + basePath % "/rooms/" % roomId % "/members", + queryToGetMembersByRoom(at, membership, notMembership)) , d(new Private) { } @@ -179,7 +150,7 @@ EventsArray<RoomMemberEvent>&& GetMembersByRoomJob::chunk() BaseJob::Status GetMembersByRoomJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->chunk = fromJson<EventsArray<RoomMemberEvent>>(json.value("chunk"_ls)); + fromJson(json.value("chunk"_ls), d->chunk); return Success; } @@ -187,17 +158,12 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetJoinedMembersByRoomJob::RoomMember> + template <> struct JsonObjectConverter<GetJoinedMembersByRoomJob::RoomMember> { - GetJoinedMembersByRoomJob::RoomMember operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, GetJoinedMembersByRoomJob::RoomMember& result) { - GetJoinedMembersByRoomJob::RoomMember result; - result.displayName = - fromJson<QString>(jo.value("display_name"_ls)); - result.avatarUrl = - fromJson<QString>(jo.value("avatar_url"_ls)); - - return result; + fromJson(jo.value("display_name"_ls), result.displayName); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } }; } // namespace QMatrixClient @@ -233,7 +199,7 @@ const QHash<QString, GetJoinedMembersByRoomJob::RoomMember>& GetJoinedMembersByR BaseJob::Status GetJoinedMembersByRoomJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->joined = fromJson<QHash<QString, RoomMember>>(json.value("joined"_ls)); + fromJson(json.value("joined"_ls), d->joined); return Success; } diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h index 2366918b..b4d3d9b6 100644 --- a/lib/csapi/rooms.h +++ b/lib/csapi/rooms.h @@ -80,19 +80,6 @@ namespace QMatrixClient */ static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& eventType, const QString& stateKey); - ~GetRoomStateWithKeyJob() override; - - // Result properties - - /// The content of the state event. - StateEventPtr&& data(); - - protected: - Status parseJson(const QJsonDocument& data) override; - - private: - class Private; - QScopedPointer<Private> d; }; /// Get the state identified by the type, with the empty state key. @@ -122,19 +109,6 @@ namespace QMatrixClient */ static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& eventType); - ~GetRoomStateByTypeJob() override; - - // Result properties - - /// The content of the state event. - StateEventPtr&& data(); - - protected: - Status parseJson(const QJsonDocument& data) override; - - private: - class Private; - QScopedPointer<Private> d; }; /// Get all state events in the current state of a room. @@ -184,8 +158,17 @@ namespace QMatrixClient /*! Get the m.room.member events for the room. * \param roomId * The room to get the member events for. + * \param at + * The token defining the timeline position as-of which to return + * the list of members. This token can be obtained from a batch token + * returned for each room by the sync API, or from + * a ``start``/``end`` token returned by a ``/messages`` request. + * \param membership + * Only return users with the specified membership + * \param notMembership + * Only return users with membership state other than specified */ - explicit GetMembersByRoomJob(const QString& roomId); + explicit GetMembersByRoomJob(const QString& roomId, const QString& at = {}, const QString& membership = {}, const QString& notMembership = {}); /*! Construct a URL without creating a full-fledged job object * @@ -193,7 +176,7 @@ namespace QMatrixClient * GetMembersByRoomJob is necessary but the job * itself isn't. */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId); + static QUrl makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& at = {}, const QString& membership = {}, const QString& notMembership = {}); ~GetMembersByRoomJob() override; diff --git a/lib/csapi/search.cpp b/lib/csapi/search.cpp index 9436eb47..a5f83c79 100644 --- a/lib/csapi/search.cpp +++ b/lib/csapi/search.cpp @@ -16,146 +16,113 @@ namespace QMatrixClient { // Converters - QJsonObject toJson(const SearchJob::IncludeEventContext& pod) + template <> struct JsonObjectConverter<SearchJob::IncludeEventContext> { - QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("before_limit"), pod.beforeLimit); - addParam<IfNotEmpty>(jo, QStringLiteral("after_limit"), pod.afterLimit); - addParam<IfNotEmpty>(jo, QStringLiteral("include_profile"), pod.includeProfile); - return jo; - } - - QJsonObject toJson(const SearchJob::Group& pod) - { - QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("key"), pod.key); - return jo; - } + static void dumpTo(QJsonObject& jo, const SearchJob::IncludeEventContext& pod) + { + addParam<IfNotEmpty>(jo, QStringLiteral("before_limit"), pod.beforeLimit); + addParam<IfNotEmpty>(jo, QStringLiteral("after_limit"), pod.afterLimit); + addParam<IfNotEmpty>(jo, QStringLiteral("include_profile"), pod.includeProfile); + } + }; - QJsonObject toJson(const SearchJob::Groupings& pod) + template <> struct JsonObjectConverter<SearchJob::Group> { - QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("group_by"), pod.groupBy); - return jo; - } + static void dumpTo(QJsonObject& jo, const SearchJob::Group& pod) + { + addParam<IfNotEmpty>(jo, QStringLiteral("key"), pod.key); + } + }; - QJsonObject toJson(const SearchJob::RoomEventsCriteria& pod) - { - QJsonObject jo; - addParam<>(jo, QStringLiteral("search_term"), pod.searchTerm); - addParam<IfNotEmpty>(jo, QStringLiteral("keys"), pod.keys); - addParam<IfNotEmpty>(jo, QStringLiteral("filter"), pod.filter); - addParam<IfNotEmpty>(jo, QStringLiteral("order_by"), pod.orderBy); - addParam<IfNotEmpty>(jo, QStringLiteral("event_context"), pod.eventContext); - addParam<IfNotEmpty>(jo, QStringLiteral("include_state"), pod.includeState); - addParam<IfNotEmpty>(jo, QStringLiteral("groupings"), pod.groupings); - return jo; - } - - QJsonObject toJson(const SearchJob::Categories& pod) + template <> struct JsonObjectConverter<SearchJob::Groupings> { - QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("room_events"), pod.roomEvents); - return jo; - } + static void dumpTo(QJsonObject& jo, const SearchJob::Groupings& pod) + { + addParam<IfNotEmpty>(jo, QStringLiteral("group_by"), pod.groupBy); + } + }; - template <> struct FromJsonObject<SearchJob::UserProfile> + template <> struct JsonObjectConverter<SearchJob::RoomEventsCriteria> { - SearchJob::UserProfile operator()(const QJsonObject& jo) const + static void dumpTo(QJsonObject& jo, const SearchJob::RoomEventsCriteria& pod) { - SearchJob::UserProfile result; - result.displayname = - fromJson<QString>(jo.value("displayname"_ls)); - result.avatarUrl = - fromJson<QString>(jo.value("avatar_url"_ls)); + addParam<>(jo, QStringLiteral("search_term"), pod.searchTerm); + addParam<IfNotEmpty>(jo, QStringLiteral("keys"), pod.keys); + addParam<IfNotEmpty>(jo, QStringLiteral("filter"), pod.filter); + addParam<IfNotEmpty>(jo, QStringLiteral("order_by"), pod.orderBy); + addParam<IfNotEmpty>(jo, QStringLiteral("event_context"), pod.eventContext); + addParam<IfNotEmpty>(jo, QStringLiteral("include_state"), pod.includeState); + addParam<IfNotEmpty>(jo, QStringLiteral("groupings"), pod.groupings); + } + }; - return result; + template <> struct JsonObjectConverter<SearchJob::Categories> + { + static void dumpTo(QJsonObject& jo, const SearchJob::Categories& pod) + { + addParam<IfNotEmpty>(jo, QStringLiteral("room_events"), pod.roomEvents); } }; - template <> struct FromJsonObject<SearchJob::EventContext> + template <> struct JsonObjectConverter<SearchJob::UserProfile> { - SearchJob::EventContext operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::UserProfile& result) { - SearchJob::EventContext result; - result.begin = - fromJson<QString>(jo.value("start"_ls)); - result.end = - fromJson<QString>(jo.value("end"_ls)); - result.profileInfo = - fromJson<QHash<QString, SearchJob::UserProfile>>(jo.value("profile_info"_ls)); - result.eventsBefore = - fromJson<RoomEvents>(jo.value("events_before"_ls)); - result.eventsAfter = - fromJson<RoomEvents>(jo.value("events_after"_ls)); - - return result; + fromJson(jo.value("displayname"_ls), result.displayname); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } }; - template <> struct FromJsonObject<SearchJob::Result> + template <> struct JsonObjectConverter<SearchJob::EventContext> { - SearchJob::Result operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::EventContext& result) { - SearchJob::Result result; - result.rank = - fromJson<double>(jo.value("rank"_ls)); - result.result = - fromJson<RoomEventPtr>(jo.value("result"_ls)); - result.context = - fromJson<SearchJob::EventContext>(jo.value("context"_ls)); - - return result; + fromJson(jo.value("start"_ls), result.begin); + fromJson(jo.value("end"_ls), result.end); + fromJson(jo.value("profile_info"_ls), result.profileInfo); + fromJson(jo.value("events_before"_ls), result.eventsBefore); + fromJson(jo.value("events_after"_ls), result.eventsAfter); } }; - template <> struct FromJsonObject<SearchJob::GroupValue> + template <> struct JsonObjectConverter<SearchJob::Result> { - SearchJob::GroupValue operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::Result& result) { - SearchJob::GroupValue result; - result.nextBatch = - fromJson<QString>(jo.value("next_batch"_ls)); - result.order = - fromJson<int>(jo.value("order"_ls)); - result.results = - fromJson<QStringList>(jo.value("results"_ls)); - - return result; + fromJson(jo.value("rank"_ls), result.rank); + fromJson(jo.value("result"_ls), result.result); + fromJson(jo.value("context"_ls), result.context); } }; - template <> struct FromJsonObject<SearchJob::ResultRoomEvents> + template <> struct JsonObjectConverter<SearchJob::GroupValue> { - SearchJob::ResultRoomEvents operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::GroupValue& result) { - SearchJob::ResultRoomEvents result; - result.count = - fromJson<int>(jo.value("count"_ls)); - result.highlights = - fromJson<QStringList>(jo.value("highlights"_ls)); - result.results = - fromJson<std::vector<SearchJob::Result>>(jo.value("results"_ls)); - result.state = - fromJson<std::unordered_map<QString, StateEvents>>(jo.value("state"_ls)); - result.groups = - fromJson<QHash<QString, QHash<QString, SearchJob::GroupValue>>>(jo.value("groups"_ls)); - result.nextBatch = - fromJson<QString>(jo.value("next_batch"_ls)); - - return result; + fromJson(jo.value("next_batch"_ls), result.nextBatch); + fromJson(jo.value("order"_ls), result.order); + fromJson(jo.value("results"_ls), result.results); } }; - template <> struct FromJsonObject<SearchJob::ResultCategories> + template <> struct JsonObjectConverter<SearchJob::ResultRoomEvents> { - SearchJob::ResultCategories operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchJob::ResultRoomEvents& result) { - SearchJob::ResultCategories result; - result.roomEvents = - fromJson<SearchJob::ResultRoomEvents>(jo.value("room_events"_ls)); + fromJson(jo.value("count"_ls), result.count); + fromJson(jo.value("highlights"_ls), result.highlights); + fromJson(jo.value("results"_ls), result.results); + fromJson(jo.value("state"_ls), result.state); + fromJson(jo.value("groups"_ls), result.groups); + fromJson(jo.value("next_batch"_ls), result.nextBatch); + } + }; - return result; + template <> struct JsonObjectConverter<SearchJob::ResultCategories> + { + static void fillFrom(const QJsonObject& jo, SearchJob::ResultCategories& result) + { + fromJson(jo.value("room_events"_ls), result.roomEvents); } }; } // namespace QMatrixClient @@ -199,7 +166,7 @@ BaseJob::Status SearchJob::parseJson(const QJsonDocument& data) if (!json.contains("search_categories"_ls)) return { JsonParseError, "The key 'search_categories' not found in the response" }; - d->searchCategories = fromJson<ResultCategories>(json.value("search_categories"_ls)); + fromJson(json.value("search_categories"_ls), d->searchCategories); return Success; } diff --git a/lib/csapi/search.h b/lib/csapi/search.h index 85b0886b..86a0ee92 100644 --- a/lib/csapi/search.h +++ b/lib/csapi/search.h @@ -39,7 +39,7 @@ namespace QMatrixClient /// historic profile information for the users /// that sent the events that were returned. /// By default, this is ``false``. - bool includeProfile; + Omittable<bool> includeProfile; }; /// Configuration for group. @@ -74,7 +74,7 @@ namespace QMatrixClient Omittable<IncludeEventContext> eventContext; /// Requests the server return the current state for /// each room returned. - bool includeState; + Omittable<bool> includeState; /// Requests that the server partitions the result set /// based on the provided list of keys. Omittable<Groupings> groupings; diff --git a/lib/csapi/sso_login_redirect.cpp b/lib/csapi/sso_login_redirect.cpp new file mode 100644 index 00000000..7323951c --- /dev/null +++ b/lib/csapi/sso_login_redirect.cpp @@ -0,0 +1,38 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "sso_login_redirect.h" + +#include "converters.h" + +#include <QtCore/QStringBuilder> + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +BaseJob::Query queryToRedirectToSSO(const QString& redirectUrl) +{ + BaseJob::Query _q; + addParam<>(_q, QStringLiteral("redirectUrl"), redirectUrl); + return _q; +} + +QUrl RedirectToSSOJob::makeRequestUrl(QUrl baseUrl, const QString& redirectUrl) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + basePath % "/login/sso/redirect", + queryToRedirectToSSO(redirectUrl)); +} + +static const auto RedirectToSSOJobName = QStringLiteral("RedirectToSSOJob"); + +RedirectToSSOJob::RedirectToSSOJob(const QString& redirectUrl) + : BaseJob(HttpVerb::Get, RedirectToSSOJobName, + basePath % "/login/sso/redirect", + queryToRedirectToSSO(redirectUrl), + {}, false) +{ +} + diff --git a/lib/csapi/sso_login_redirect.h b/lib/csapi/sso_login_redirect.h new file mode 100644 index 00000000..c09365b0 --- /dev/null +++ b/lib/csapi/sso_login_redirect.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + + +namespace QMatrixClient +{ + // Operations + + /// Redirect the user's browser to the SSO interface. + /// + /// A web-based Matrix client should instruct the user's browser to + /// navigate to this endpoint in order to log in via SSO. + /// + /// The server MUST respond with an HTTP redirect to the SSO interface. + class RedirectToSSOJob : public BaseJob + { + public: + /*! Redirect the user's browser to the SSO interface. + * \param redirectUrl + * URI to which the user will be redirected after the homeserver has + * authenticated the user with SSO. + */ + explicit RedirectToSSOJob(const QString& redirectUrl); + + /*! Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for + * RedirectToSSOJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl, const QString& redirectUrl); + + }; +} // namespace QMatrixClient diff --git a/lib/csapi/tags.cpp b/lib/csapi/tags.cpp index 808915ac..94026bb9 100644 --- a/lib/csapi/tags.cpp +++ b/lib/csapi/tags.cpp @@ -16,16 +16,12 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<GetRoomTagsJob::Tag> + template <> struct JsonObjectConverter<GetRoomTagsJob::Tag> { - GetRoomTagsJob::Tag operator()(QJsonObject jo) const + static void fillFrom(QJsonObject jo, GetRoomTagsJob::Tag& result) { - GetRoomTagsJob::Tag result; - result.order = - fromJson<float>(jo.take("order"_ls)); - - result.additionalProperties = fromJson<QVariantHash>(jo); - return result; + fromJson(jo.take("order"_ls), result.order); + fromJson(jo, result.additionalProperties); } }; } // namespace QMatrixClient @@ -61,7 +57,7 @@ const QHash<QString, GetRoomTagsJob::Tag>& GetRoomTagsJob::tags() const BaseJob::Status GetRoomTagsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->tags = fromJson<QHash<QString, Tag>>(json.value("tags"_ls)); + fromJson(json.value("tags"_ls), d->tags); return Success; } diff --git a/lib/csapi/third_party_lookup.cpp b/lib/csapi/third_party_lookup.cpp index 3ba1a5ad..12cb7c59 100644 --- a/lib/csapi/third_party_lookup.cpp +++ b/lib/csapi/third_party_lookup.cpp @@ -42,7 +42,7 @@ const QHash<QString, ThirdPartyProtocol>& GetProtocolsJob::data() const BaseJob::Status GetProtocolsJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<QHash<QString, ThirdPartyProtocol>>(data); + fromJson(data, d->data); return Success; } @@ -76,7 +76,7 @@ const ThirdPartyProtocol& GetProtocolMetadataJob::data() const BaseJob::Status GetProtocolMetadataJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<ThirdPartyProtocol>(data); + fromJson(data, d->data); return Success; } @@ -119,7 +119,7 @@ const QVector<ThirdPartyLocation>& QueryLocationByProtocolJob::data() const BaseJob::Status QueryLocationByProtocolJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<QVector<ThirdPartyLocation>>(data); + fromJson(data, d->data); return Success; } @@ -162,7 +162,7 @@ const QVector<ThirdPartyUser>& QueryUserByProtocolJob::data() const BaseJob::Status QueryUserByProtocolJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<QVector<ThirdPartyUser>>(data); + fromJson(data, d->data); return Success; } @@ -205,7 +205,7 @@ const QVector<ThirdPartyLocation>& QueryLocationByAliasJob::data() const BaseJob::Status QueryLocationByAliasJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<QVector<ThirdPartyLocation>>(data); + fromJson(data, d->data); return Success; } @@ -248,7 +248,7 @@ const QVector<ThirdPartyUser>& QueryUserByIDJob::data() const BaseJob::Status QueryUserByIDJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<QVector<ThirdPartyUser>>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/users.cpp b/lib/csapi/users.cpp index deb9cb8a..97d8962d 100644 --- a/lib/csapi/users.cpp +++ b/lib/csapi/users.cpp @@ -16,19 +16,13 @@ namespace QMatrixClient { // Converters - template <> struct FromJsonObject<SearchUserDirectoryJob::User> + template <> struct JsonObjectConverter<SearchUserDirectoryJob::User> { - SearchUserDirectoryJob::User operator()(const QJsonObject& jo) const + static void fillFrom(const QJsonObject& jo, SearchUserDirectoryJob::User& result) { - SearchUserDirectoryJob::User result; - result.userId = - fromJson<QString>(jo.value("user_id"_ls)); - result.displayName = - fromJson<QString>(jo.value("display_name"_ls)); - result.avatarUrl = - fromJson<QString>(jo.value("avatar_url"_ls)); - - return result; + fromJson(jo.value("user_id"_ls), result.userId); + fromJson(jo.value("display_name"_ls), result.displayName); + fromJson(jo.value("avatar_url"_ls), result.avatarUrl); } }; } // namespace QMatrixClient @@ -71,11 +65,11 @@ BaseJob::Status SearchUserDirectoryJob::parseJson(const QJsonDocument& data) if (!json.contains("results"_ls)) return { JsonParseError, "The key 'results' not found in the response" }; - d->results = fromJson<QVector<User>>(json.value("results"_ls)); + fromJson(json.value("results"_ls), d->results); if (!json.contains("limited"_ls)) return { JsonParseError, "The key 'limited' not found in the response" }; - d->limited = fromJson<bool>(json.value("limited"_ls)); + fromJson(json.value("limited"_ls), d->limited); return Success; } diff --git a/lib/csapi/versions.cpp b/lib/csapi/versions.cpp index 128902e2..6ee6725d 100644 --- a/lib/csapi/versions.cpp +++ b/lib/csapi/versions.cpp @@ -16,6 +16,7 @@ class GetVersionsJob::Private { public: QStringList versions; + QHash<QString, bool> unstableFeatures; }; QUrl GetVersionsJob::makeRequestUrl(QUrl baseUrl) @@ -40,10 +41,19 @@ const QStringList& GetVersionsJob::versions() const return d->versions; } +const QHash<QString, bool>& GetVersionsJob::unstableFeatures() const +{ + return d->unstableFeatures; +} + BaseJob::Status GetVersionsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->versions = fromJson<QStringList>(json.value("versions"_ls)); + if (!json.contains("versions"_ls)) + return { JsonParseError, + "The key 'versions' not found in the response" }; + fromJson(json.value("versions"_ls), d->versions); + fromJson(json.value("unstable_features"_ls), d->unstableFeatures); return Success; } diff --git a/lib/csapi/versions.h b/lib/csapi/versions.h index 309de184..b56f293f 100644 --- a/lib/csapi/versions.h +++ b/lib/csapi/versions.h @@ -6,6 +6,8 @@ #include "jobs/basejob.h" +#include <QtCore/QHash> +#include "converters.h" namespace QMatrixClient { @@ -19,6 +21,19 @@ namespace QMatrixClient /// /// 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``. + /// + /// The server may additionally advertise experimental features it supports + /// through ``unstable_features``. These features should be namespaced and + /// may optionally include version information within their name if desired. + /// Features listed here are not for optionally toggling parts of the Matrix + /// specification and should only be used to advertise support for a feature + /// which has not yet landed in the spec. For example, a feature currently + /// undergoing the proposal process may appear here and eventually be taken + /// off this list once the feature lands in the spec and the server deems it + /// reasonable to do so. Servers may wish to keep advertising features here + /// after they've been released into the spec to give clients a chance to + /// upgrade appropriately. Additionally, clients should avoid using unstable + /// features in their stable releases. class GetVersionsJob : public BaseJob { public: @@ -38,6 +53,10 @@ namespace QMatrixClient /// The supported versions. const QStringList& versions() const; + /// Experimental features the server supports. Features not listed here, + /// or the lack of this property all together, indicate that a feature is + /// not supported. + const QHash<QString, bool>& unstableFeatures() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/voip.cpp b/lib/csapi/voip.cpp index 0479b645..e8158723 100644 --- a/lib/csapi/voip.cpp +++ b/lib/csapi/voip.cpp @@ -42,7 +42,7 @@ const QJsonObject& GetTurnServerJob::data() const BaseJob::Status GetTurnServerJob::parseJson(const QJsonDocument& data) { - d->data = fromJson<QJsonObject>(data); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/wellknown.cpp b/lib/csapi/wellknown.cpp index d42534a0..a6107f86 100644 --- a/lib/csapi/wellknown.cpp +++ b/lib/csapi/wellknown.cpp @@ -15,8 +15,7 @@ static const auto basePath = QStringLiteral("/.well-known"); class GetWellknownJob::Private { public: - HomeserverInformation homeserver; - Omittable<IdentityServerInformation> identityServer; + DiscoveryInformation data; }; QUrl GetWellknownJob::makeRequestUrl(QUrl baseUrl) @@ -36,24 +35,14 @@ GetWellknownJob::GetWellknownJob() GetWellknownJob::~GetWellknownJob() = default; -const HomeserverInformation& GetWellknownJob::homeserver() const +const DiscoveryInformation& GetWellknownJob::data() const { - return d->homeserver; -} - -const Omittable<IdentityServerInformation>& GetWellknownJob::identityServer() const -{ - return d->identityServer; + return d->data; } BaseJob::Status GetWellknownJob::parseJson(const QJsonDocument& data) { - auto json = data.object(); - if (!json.contains("m.homeserver"_ls)) - return { JsonParseError, - "The key 'm.homeserver' not found in the response" }; - d->homeserver = fromJson<HomeserverInformation>(json.value("m.homeserver"_ls)); - d->identityServer = fromJson<IdentityServerInformation>(json.value("m.identity_server"_ls)); + fromJson(data, d->data); return Success; } diff --git a/lib/csapi/wellknown.h b/lib/csapi/wellknown.h index df4c8c6e..8da9ce9f 100644 --- a/lib/csapi/wellknown.h +++ b/lib/csapi/wellknown.h @@ -6,9 +6,8 @@ #include "jobs/basejob.h" +#include "csapi/definitions/wellknown/full.h" #include "converters.h" -#include "csapi/definitions/wellknown/identity_server.h" -#include "csapi/definitions/wellknown/homeserver.h" namespace QMatrixClient { @@ -41,10 +40,8 @@ namespace QMatrixClient // Result properties - /// Information about the homeserver to connect to. - const HomeserverInformation& homeserver() const; - /// Optional. Information about the identity server to connect to. - const Omittable<IdentityServerInformation>& identityServer() const; + /// Server discovery information. + const DiscoveryInformation& data() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/whoami.cpp b/lib/csapi/whoami.cpp index cb6439ef..aebdf5d3 100644 --- a/lib/csapi/whoami.cpp +++ b/lib/csapi/whoami.cpp @@ -46,7 +46,7 @@ BaseJob::Status GetTokenOwnerJob::parseJson(const QJsonDocument& data) if (!json.contains("user_id"_ls)) return { JsonParseError, "The key 'user_id' not found in the response" }; - d->userId = fromJson<QString>(json.value("user_id"_ls)); + fromJson(json.value("user_id"_ls), d->userId); return Success; } diff --git a/lib/csapi/{{base}}.cpp.mustache b/lib/csapi/{{base}}.cpp.mustache index 64fd8bf3..ff888d76 100644 --- a/lib/csapi/{{base}}.cpp.mustache +++ b/lib/csapi/{{base}}.cpp.mustache @@ -8,49 +8,52 @@ {{/operations}} using namespace QMatrixClient; {{#models.model}}{{#in?}} -QJsonObject QMatrixClient::toJson(const {{qualifiedName}}& pod) +void JsonObjectConverter<{{qualifiedName}}>::dumpTo( + QJsonObject& jo, const {{qualifiedName}}& pod) { - QJsonObject jo{{#propertyMap}} = toJson(pod.{{nameCamelCase}}){{/propertyMap}};{{#vars}} - addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});{{/vars}} - return jo; -} +{{#propertyMap}} fillJson(jo, pod.{{nameCamelCase}}); +{{/propertyMap}}{{#parents}} fillJson<{{name}}>(jo, pod); +{{/parents}}{{#vars}} addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}}); +{{/vars}}}{{!<- dumpTo() ends here}} {{/in?}}{{#out?}} -{{qualifiedName}} FromJsonObject<{{qualifiedName}}>::operator()({{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}} jo) const +void JsonObjectConverter<{{qualifiedName}}>::fillFrom( + {{^propertyMap}}const QJsonObject&{{/propertyMap + }}{{#propertyMap}}QJsonObject{{/propertyMap}} jo, {{qualifiedName}}& result) { - {{qualifiedName}} result; -{{#vars}} result.{{nameCamelCase}} = - fromJson<{{dataType.qualifiedName}}>(jo.{{#propertyMap}}take{{/propertyMap}}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls)); +{{#parents}} fillFromJson<{{qualifiedName}}>(jo, result); +{{/parents}}{{#vars}} fromJson(jo.{{#propertyMap}}take{{/propertyMap + }}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls), result.{{nameCamelCase}}); {{/vars}}{{#propertyMap}} - result.{{nameCamelCase}} = fromJson<{{dataType.qualifiedName}}>(jo);{{/propertyMap}} - return result; -} + fromJson(jo, result.{{nameCamelCase}}); +{{/propertyMap}}} {{/out?}}{{/models.model}}{{#operations}} static const auto basePath = QStringLiteral("{{basePathWithoutHost}}"); {{# operation}}{{#models}} namespace QMatrixClient { // Converters -{{#model}}{{#in?}} - QJsonObject toJson(const {{qualifiedName}}& pod) - { - QJsonObject jo{{#propertyMap}} = toJson(pod.{{nameCamelCase}}){{/propertyMap}};{{#vars}} - addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});{{/vars}} - return jo; - } -{{/in?}}{{#out?}} - template <> struct FromJsonObject<{{qualifiedName}}> +{{#model}} + template <> struct JsonObjectConverter<{{qualifiedName}}> { - {{qualifiedName}} operator()({{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}} jo) const +{{#in?}} static void dumpTo(QJsonObject& jo, const {{qualifiedName}}& pod) { - {{qualifiedName}} result; -{{#vars}} result.{{nameCamelCase}} = - fromJson<{{dataType.qualifiedName}}>(jo.{{#propertyMap}}take{{/propertyMap}}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls)); -{{/vars}}{{#propertyMap}} - result.{{nameCamelCase}} = fromJson<{{dataType.qualifiedName}}>(jo);{{/propertyMap}} - return result; - } - }; -{{/out?}}{{/model}}} // namespace QMatrixClient +{{#propertyMap}} fillJson(jo, pod.{{nameCamelCase}}); + {{/propertyMap}}{{#parents}}fillJson<{{name}}>(jo, pod); + {{/parents}}{{#vars +}} addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo, QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}}); +{{/vars}} } +{{/in?}}{{#out? +}} static void fillFrom({{^propertyMap}}const QJsonObject&{{/propertyMap + }}{{#propertyMap}}QJsonObject{{/propertyMap}} jo, {{qualifiedName}}& result) + { +{{#parents}} fillFromJson<{{qualifiedName}}{{!of the parent!}}>(jo, result); + {{/parents}}{{#vars +}} fromJson(jo.{{#propertyMap}}take{{/propertyMap + }}{{^propertyMap}}value{{/propertyMap}}("{{baseName}}"_ls), result.{{nameCamelCase}}); +{{/vars}}{{#propertyMap}} fromJson(jo, result.{{nameCamelCase}}); +{{/propertyMap}} } +{{/out?}} }; +{{/model}}} // namespace QMatrixClient {{/ models}}{{#responses}}{{#normalResponse?}}{{#allProperties?}} class {{camelCaseOperationId}}Job::Private { @@ -109,12 +112,12 @@ BaseJob::Status {{camelCaseOperationId}}Job::parseReply(QNetworkReply* reply) }{{/ producesNonJson?}}{{^producesNonJson?}} BaseJob::Status {{camelCaseOperationId}}Job::parseJson(const QJsonDocument& data) { -{{#inlineResponse}} d->{{paramName}} = fromJson<{{dataType.name}}>(data); +{{#inlineResponse}} fromJson(data, d->{{paramName}}); {{/inlineResponse}}{{^inlineResponse}} auto json = data.object(); {{#properties}}{{#required?}} if (!json.contains("{{baseName}}"_ls)) return { JsonParseError, "The key '{{baseName}}' not found in the response" }; -{{/required?}} d->{{paramName}} = fromJson<{{dataType.name}}>(json.value("{{baseName}}"_ls)); +{{/required?}} fromJson(json.value("{{baseName}}"_ls), d->{{paramName}}); {{/properties}}{{/inlineResponse}} return Success; }{{/ producesNonJson?}} {{/allProperties?}}{{/normalResponse?}}{{/responses}}{{/operation}}{{/operations}} diff --git a/lib/csapi/{{base}}.h.mustache b/lib/csapi/{{base}}.h.mustache index 147c8607..a9c3a63a 100644 --- a/lib/csapi/{{base}}.h.mustache +++ b/lib/csapi/{{base}}.h.mustache @@ -18,14 +18,13 @@ namespace QMatrixClient {{/vars}}{{#propertyMap}}{{#description}} /// {{_}} {{/description}} {{>maybeOmittableType}} {{nameCamelCase}}; {{/propertyMap}} }; -{{#in?}} - QJsonObject toJson(const {{name}}& pod); -{{/in?}}{{#out?}} - template <> struct FromJsonObject<{{name}}> + template <> struct JsonObjectConverter<{{name}}> { - {{name}} operator()({{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}} jo) const; - }; -{{/ out?}}{{/model}} + {{#in?}}static void dumpTo(QJsonObject& jo, const {{name}}& pod); + {{/in?}}{{#out?}}static void fillFrom({{^propertyMap}}const QJsonObject&{{/propertyMap + }}{{#propertyMap}}QJsonObject{{/propertyMap}} jo, {{name}}& pod); +{{/out?}} }; +{{/model}} {{/models}}{{#operations}} // Operations {{# operation}}{{#summary}} /// {{summary}}{{#description?}}{{!add a linebreak between summary and description if both exist}} |