diff options
author | Andres Salomon <dilinger@queued.net> | 2021-01-18 04:00:14 -0500 |
---|---|---|
committer | Andres Salomon <dilinger@queued.net> | 2021-01-18 04:00:14 -0500 |
commit | 09eb39236666e81d5da014acea011dcd74d0999b (patch) | |
tree | 52876d96be71be1a39d5d935c1295a51995e8949 /lib/events/roommessageevent.cpp | |
parent | f1788ee27f33e9339334e0d79bde9a27d9ce2e44 (diff) | |
parent | a4e78956f105875625b572d8b98459ffa86fafe5 (diff) | |
download | libquotient-09eb39236666e81d5da014acea011dcd74d0999b.tar.gz libquotient-09eb39236666e81d5da014acea011dcd74d0999b.zip |
Update upstream source from tag 'upstream/0.6.4'
Update to upstream version '0.6.4'
with Debian dir aa8705fd74743e79c043bc9e3e425d5064404cfe
Diffstat (limited to 'lib/events/roommessageevent.cpp')
-rw-r--r-- | lib/events/roommessageevent.cpp | 154 |
1 files changed, 81 insertions, 73 deletions
diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 1edf82e4..616a034f 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -13,26 +13,25 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "roommessageevent.h" #include "logging.h" -#include <QtCore/QMimeDatabase> #include <QtCore/QFileInfo> +#include <QtCore/QMimeDatabase> #include <QtGui/QImageReader> #include <QtMultimedia/QMediaResource> -using namespace QMatrixClient; +using namespace Quotient; using namespace EventContent; using MsgType = RoomMessageEvent::MsgType; static const auto RelatesToKeyL = "m.relates_to"_ls; static const auto MsgTypeKeyL = "msgtype"_ls; -static const auto BodyKeyL = "body"_ls; static const auto FormattedBodyKeyL = "formatted_body"_ls; static const auto TextTypeKey = "m.text"; @@ -51,31 +50,33 @@ template <> TypedBase* make<TextContent>(const QJsonObject& json) { return json.contains(FormattedBodyKeyL) || json.contains(RelatesToKeyL) - ? new TextContent(json) : nullptr; + ? new TextContent(json) + : nullptr; } -struct MsgTypeDesc -{ +struct MsgTypeDesc { QString matrixType; MsgType enumType; TypedBase* (*maker)(const QJsonObject&); }; -const std::vector<MsgTypeDesc> msgTypes = - { { TextTypeKey, MsgType::Text, make<TextContent> } - , { EmoteTypeKey, MsgType::Emote, make<TextContent> } - , { NoticeTypeKey, MsgType::Notice, make<TextContent> } - , { QStringLiteral("m.image"), MsgType::Image, make<ImageContent> } - , { QStringLiteral("m.file"), MsgType::File, make<FileContent> } - , { QStringLiteral("m.location"), MsgType::Location, make<LocationContent> } - , { QStringLiteral("m.video"), MsgType::Video, make<VideoContent> } - , { QStringLiteral("m.audio"), MsgType::Audio, make<AudioContent> } - }; +const std::vector<MsgTypeDesc> msgTypes = { + { TextTypeKey, MsgType::Text, make<TextContent> }, + { EmoteTypeKey, MsgType::Emote, make<TextContent> }, + { NoticeTypeKey, MsgType::Notice, make<TextContent> }, + { QStringLiteral("m.image"), MsgType::Image, make<ImageContent> }, + { QStringLiteral("m.file"), MsgType::File, make<FileContent> }, + { QStringLiteral("m.location"), MsgType::Location, make<LocationContent> }, + { QStringLiteral("m.video"), MsgType::Video, make<VideoContent> }, + { QStringLiteral("m.audio"), MsgType::Audio, make<AudioContent> } +}; QString msgTypeToJson(MsgType enumType) { auto it = std::find_if(msgTypes.begin(), msgTypes.end(), - [=](const MsgTypeDesc& mtd) { return mtd.enumType == enumType; }); + [=](const MsgTypeDesc& mtd) { + return mtd.enumType == enumType; + }); if (it != msgTypes.end()) return it->matrixType; @@ -85,15 +86,23 @@ QString msgTypeToJson(MsgType enumType) MsgType jsonToMsgType(const QString& matrixType) { auto it = std::find_if(msgTypes.begin(), msgTypes.end(), - [=](const MsgTypeDesc& mtd) { return mtd.matrixType == matrixType; }); + [=](const MsgTypeDesc& mtd) { + return mtd.matrixType == matrixType; + }); if (it != msgTypes.end()) return it->enumType; return MsgType::Unknown; } +inline bool isReplacement(const Omittable<RelatesTo>& rel) +{ + return rel && rel->type == RelatesTo::ReplacementTypeId(); +} + QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, - const QString& jsonMsgType, TypedBase* content) + const QString& jsonMsgType, + TypedBase* content) { auto json = content ? content->toJson() : QJsonObject(); if (json.contains(RelatesToKeyL)) { @@ -107,9 +116,10 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, // After the above, we know for sure that the content is TextContent // and that its RelatesTo structure is not omitted auto* textContent = static_cast<const TextContent*>(content); + Q_ASSERT(textContent && textContent->relatesTo.has_value()); if (textContent->relatesTo->type == RelatesTo::ReplacementTypeId()) { auto newContentJson = json.take("m.new_content"_ls).toObject(); - newContentJson.insert(BodyKeyL, plainBody); + newContentJson.insert(BodyKey, plainBody); newContentJson.insert(MsgTypeKeyL, jsonMsgType); json.insert(QStringLiteral("m.new_content"), newContentJson); json[MsgTypeKeyL] = jsonMsgType; @@ -124,24 +134,24 @@ QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, - const QString& jsonMsgType, TypedBase* content) + const QString& jsonMsgType, + TypedBase* content) : RoomEvent(typeId(), matrixTypeId(), assembleContentJson(plainBody, jsonMsgType, content)) , _content(content) -{ } +{} -RoomMessageEvent::RoomMessageEvent(const QString& plainBody, - MsgType msgType, TypedBase* content) +RoomMessageEvent::RoomMessageEvent(const QString& plainBody, MsgType msgType, + TypedBase* content) : RoomMessageEvent(plainBody, msgTypeToJson(msgType), content) -{ } +{} TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) { auto filePath = file.absoluteFilePath(); auto localUrl = QUrl::fromLocalFile(filePath); auto mimeType = QMimeDatabase().mimeTypeForFile(file); - if (!asGenericFile) - { + if (!asGenericFile) { auto mimeTypeName = mimeType.name(); if (mimeTypeName.startsWith("image/")) return new ImageContent(localUrl, file.size(), mimeType, @@ -163,11 +173,12 @@ TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, - const QFileInfo& file, bool asGenericFile) + const QFileInfo& file, bool asGenericFile) : RoomMessageEvent(plainBody, - asGenericFile ? QStringLiteral("m.file") : rawMsgTypeForFile(file), - contentFromFile(file, asGenericFile)) -{ } + asGenericFile ? QStringLiteral("m.file") + : rawMsgTypeForFile(file), + contentFromFile(file, asGenericFile)) +{} RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) : RoomEvent(typeId(), obj), _content(nullptr) @@ -175,26 +186,21 @@ RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) if (isRedacted()) return; const QJsonObject content = contentJson(); - if ( content.contains(MsgTypeKeyL) && content.contains(BodyKeyL) ) - { + if (content.contains(MsgTypeKeyL) && content.contains(BodyKeyL)) { auto msgtype = content[MsgTypeKeyL].toString(); bool msgTypeFound = false; - for (const auto& mt: msgTypes) - if (mt.matrixType == msgtype) - { + for (const auto& mt : msgTypes) + if (mt.matrixType == msgtype) { _content.reset(mt.maker(content)); msgTypeFound = true; } - if (!msgTypeFound) - { + if (!msgTypeFound) { qCWarning(EVENTS) << "RoomMessageEvent: unknown msg_type," << " full content dump follows"; qCWarning(EVENTS) << formatJson << content; } - } - else - { + } else { qCWarning(EVENTS) << "No body or msgtype in room message event"; qCWarning(EVENTS) << formatJson << obj; } @@ -218,15 +224,15 @@ QString RoomMessageEvent::plainBody() const QMimeType RoomMessageEvent::mimeType() const { static const auto PlainTextMimeType = - QMimeDatabase().mimeTypeForName("text/plain"); + QMimeDatabase().mimeTypeForName("text/plain"); return _content ? _content->type() : PlainTextMimeType; } bool RoomMessageEvent::hasTextContent() const { - return !content() || - (msgtype() == MsgType::Text || msgtype() == MsgType::Emote || - msgtype() == MsgType::Notice); + return !content() + || (msgtype() == MsgType::Text || msgtype() == MsgType::Emote + || msgtype() == MsgType::Notice); } bool RoomMessageEvent::hasFileContent() const @@ -245,17 +251,18 @@ QString RoomMessageEvent::replacedEvent() const return {}; const auto& rel = static_cast<const TextContent*>(content())->relatesTo; - return !rel.omitted() && rel->type == RelatesTo::ReplacementTypeId() - ? rel->eventId : QString(); + return isReplacement(rel) ? rel->eventId : QString(); } QString rawMsgTypeForMimeType(const QMimeType& mimeType) { auto name = mimeType.name(); - return name.startsWith("image/") ? QStringLiteral("m.image") : - name.startsWith("video/") ? QStringLiteral("m.video") : - name.startsWith("audio/") ? QStringLiteral("m.audio") : - QStringLiteral("m.file"); + return name.startsWith("image/") + ? QStringLiteral("m.image") + : name.startsWith("video/") + ? QStringLiteral("m.video") + : name.startsWith("audio/") ? QStringLiteral("m.audio") + : QStringLiteral("m.file"); } QString RoomMessageEvent::rawMsgTypeForUrl(const QUrl& url) @@ -268,18 +275,21 @@ QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi) return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi)); } -TextContent::TextContent(const QString& text, const QString& contentType, +TextContent::TextContent(QString text, const QString& contentType, Omittable<RelatesTo> relatesTo) - : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(text) + : mimeType(QMimeDatabase().mimeTypeForName(contentType)) + , body(std::move(text)) , relatesTo(std::move(relatesTo)) { if (contentType == HtmlContentTypeId) mimeType = QMimeDatabase().mimeTypeForName("text/html"); } -namespace QMatrixClient -{ -Omittable<RelatesTo> relationFromJson(const QJsonValue& jv) +namespace Quotient { +// Overload the default fromJson<> logic that defined in converters.h +// as we want +template <> +Omittable<RelatesTo> fromJson(const QJsonValue& jv) { const auto jo = jv.toObject(); if (jo.isEmpty()) @@ -291,22 +301,21 @@ Omittable<RelatesTo> relationFromJson(const QJsonValue& jv) return RelatesTo { jo.value("rel_type"_ls).toString(), jo.value(EventIdKeyL).toString() }; } -} +} // namespace Quotient TextContent::TextContent(const QJsonObject& json) - : relatesTo(relationFromJson(json[RelatesToKeyL])) + : relatesTo(fromJson<Omittable<RelatesTo>>(json[RelatesToKeyL])) { QMimeDatabase db; static const auto PlainTextMimeType = db.mimeTypeForName("text/plain"); static const auto HtmlMimeType = db.mimeTypeForName("text/html"); - const auto actualJson = - relatesTo.omitted() || relatesTo->type != RelatesTo::ReplacementTypeId() - ? json : json.value("m.new_content"_ls).toObject(); + const auto actualJson = isReplacement(relatesTo) + ? json.value("m.new_content"_ls).toObject() + : json; // Special-casing the custom matrix.org's (actually, Riot's) way // of sending HTML messages. - if (actualJson["format"_ls].toString() == HtmlContentTypeId) - { + if (actualJson["format"_ls].toString() == HtmlContentTypeId) { mimeType = HtmlMimeType; body = actualJson[FormattedBodyKeyL].toString(); } else { @@ -320,22 +329,21 @@ TextContent::TextContent(const QJsonObject& json) void TextContent::fillJson(QJsonObject* json) const { static const auto FormatKey = QStringLiteral("format"); - static const auto RichBodyKey = QStringLiteral("formatted_body"); + static const auto FormattedBodyKey = QStringLiteral("formatted_body"); Q_ASSERT(json); - if (mimeType.inherits("text/html")) - { + if (mimeType.inherits("text/html")) { json->insert(FormatKey, HtmlContentTypeId); - json->insert(RichBodyKey, body); + json->insert(FormattedBodyKey, body); } - if (!relatesTo.omitted()) { + if (relatesTo) { json->insert(QStringLiteral("m.relates_to"), - QJsonObject { { relatesTo->type, relatesTo->eventId } }); + QJsonObject { { "rel_type", relatesTo->type }, { EventIdKey, relatesTo->eventId } }); if (relatesTo->type == RelatesTo::ReplacementTypeId()) { QJsonObject newContentJson; if (mimeType.inherits("text/html")) { json->insert(FormatKey, HtmlContentTypeId); - json->insert(RichBodyKey, body); + json->insert(FormattedBodyKey, body); } json->insert(QStringLiteral("m.new_content"), newContentJson); } @@ -345,13 +353,13 @@ void TextContent::fillJson(QJsonObject* json) const LocationContent::LocationContent(const QString& geoUri, const Thumbnail& thumbnail) : geoUri(geoUri), thumbnail(thumbnail) -{ } +{} LocationContent::LocationContent(const QJsonObject& json) : TypedBase(json) , geoUri(json["geo_uri"_ls].toString()) , thumbnail(json["info"_ls].toObject()) -{ } +{} QMimeType LocationContent::type() const { |