/****************************************************************************** * Copyright (C) 2015 Felix Rohrbach * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * 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 */ #include "roommessageevent.h" #include "logging.h" #include using namespace QMatrixClient; using namespace EventContent; using MsgType = RoomMessageEvent::MsgType; template TypedBase* make(const QJsonObject& json) { return new ContentT(json); } struct MsgTypeDesc { QString jsonType; MsgType enumType; TypedBase* (*maker)(const QJsonObject&); }; const std::vector msgTypes = { { QStringLiteral("m.text"), MsgType::Text, make } , { QStringLiteral("m.emote"), MsgType::Emote, make } , { QStringLiteral("m.notice"), MsgType::Notice, make } , { QStringLiteral("m.image"), MsgType::Image, make } , { QStringLiteral("m.file"), MsgType::File, make } , { QStringLiteral("m.location"), MsgType::Location, make } , { QStringLiteral("m.video"), MsgType::Video, make } , { QStringLiteral("m.audio"), MsgType::Audio, make } }; QString msgTypeToJson(MsgType enumType) { auto it = std::find_if(msgTypes.begin(), msgTypes.end(), [=](const MsgTypeDesc& mtd) { return mtd.enumType == enumType; }); if (it != msgTypes.end()) return it->jsonType; return {}; } MsgType jsonToMsgType(const QString& jsonType) { auto it = std::find_if(msgTypes.begin(), msgTypes.end(), [=](const MsgTypeDesc& mtd) { return mtd.jsonType == jsonType; }); if (it != msgTypes.end()) return it->enumType; return MsgType::Unknown; } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, MsgType msgType, TypedBase* content) : RoomMessageEvent(plainBody, msgTypeToJson(msgType), content) { } RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) : RoomEvent(Type::RoomMessage, obj), _content(nullptr) { if (isRedacted()) return; const QJsonObject content = contentJson(); if ( content.contains("msgtype") && content.contains("body") ) { _plainBody = content["body"].toString(); _msgtype = content["msgtype"].toString(); for (const auto& mt: msgTypes) if (mt.jsonType == _msgtype) _content.reset(mt.maker(content)); if (!_content) { qCWarning(EVENTS) << "RoomMessageEvent: couldn't load content," << " full content dump follows"; qCWarning(EVENTS) << formatJson << content; } } else { qCWarning(EVENTS) << "No body or msgtype in room message event"; qCWarning(EVENTS) << formatJson << obj; } } RoomMessageEvent::MsgType RoomMessageEvent::msgtype() const { return jsonToMsgType(_msgtype); } QMimeType RoomMessageEvent::mimeType() const { return _content ? _content->type() : QMimeDatabase().mimeTypeForName("text/plain"); } bool RoomMessageEvent::hasTextContent() const { return content() && (msgtype() == MsgType::Text || msgtype() == MsgType::Emote || msgtype() == MsgType::Notice); // FIXME: Unbind from specific msgtypes } bool RoomMessageEvent::hasFileContent() const { return content() && content()->fileInfo(); } bool RoomMessageEvent::hasThumbnail() const { return content() && content()->thumbnailInfo(); } QJsonObject RoomMessageEvent::toJson() const { QJsonObject obj = _content ? _content->toJson() : QJsonObject(); obj.insert("msgtype", msgTypeToJson(msgtype())); obj.insert("body", plainBody()); return obj; } TextContent::TextContent(const QString& text, const QString& contentType) : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(text) { } TextContent::TextContent(const QJsonObject& json) { QMimeDatabase db; // Special-casing the custom matrix.org's (actually, Riot's) way // of sending HTML messages. if (json["format"].toString() == "org.matrix.custom.html") { mimeType = db.mimeTypeForName("text/html"); body = json["formatted_body"].toString(); } else { // Falling back to plain text, as there's no standard way to describe // rich text in messages. mimeType = db.mimeTypeForName("text/plain"); body = json["body"].toString(); } } void TextContent::fillJson(QJsonObject* json) const { Q_ASSERT(json); json->insert("format", QStringLiteral("org.matrix.custom.html")); json->insert("formatted_body", body); } LocationContent::LocationContent(const QString& geoUri, const ImageInfo& thumbnail) : geoUri(geoUri), thumbnail(thumbnail) { } LocationContent::LocationContent(const QJsonObject& json) : TypedBase(json) , geoUri(json["geo_uri"].toString()) , thumbnail(json["info"].toObject()) { } QMimeType LocationContent::type() const { return QMimeDatabase().mimeTypeForData(geoUri.toLatin1()); } void LocationContent::fillJson(QJsonObject* o) const { Q_ASSERT(o); o->insert("geo_uri", geoUri); o->insert("info", toInfoJson(thumbnail)); }