/****************************************************************************** * 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 MessageEventContent; using MsgType = RoomMessageEvent::MsgType; template Base* make(const QJsonObject& json) { return new ContentT(json); } struct MsgTypeDesc { QString jsonType; MsgType enumType; Base* (*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 } }; QJsonValue 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; qCCritical(EVENTS) << "Unknown msgtype:" << enumType; 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; qCCritical(EVENTS) << "Unknown msgtype:" << jsonType; return {}; } RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) : RoomEvent(Type::RoomMessage, obj), _msgtype(MsgType::Unknown) , _content(nullptr) { const QJsonObject content = contentJson(); if ( content.contains("msgtype") && content.contains("body") ) { _plainBody = content["body"].toString(); auto msgtype = content["msgtype"].toString(); for (auto mt: msgTypes) if (mt.jsonType == msgtype) { _msgtype = mt.enumType; _content.reset(mt.maker(content)); } if (_msgtype == MsgType::Unknown) { qCDebug(EVENTS) << "RoomMessageEvent: couldn't load content," << " full content dump follows"; qCDebug(EVENTS) << formatJson << content; } } else { qCWarning(EVENTS) << "No body or msgtype in room message event"; qCWarning(EVENTS) << formatJson << obj; } } QMimeType RoomMessageEvent::mimeType() const { return _content ? _content->mimeType : QMimeDatabase().mimeTypeForName("text/plain"); } QJsonObject RoomMessageEvent::toJson() const { QJsonObject obj = _content ? _content->toJson() : QJsonObject(); obj.insert("msgtype", msgTypeToJson(msgtype())); obj.insert("body", plainBody()); return obj; } QJsonObject Base::toJson() const { QJsonObject o; fillJson(&o); return o; } QJsonObject InfoBase::toInfoJson() const { QJsonObject info; fillInfoJson(&info); return info; } TextContent::TextContent(const QString& text, const QString& contentType) : Base(QMimeDatabase().mimeTypeForName(contentType)), body(text) { } TextContent::TextContent(const QJsonObject& json) { QMimeDatabase db; // Special-casing the custom matrix.org's (actually, Vector'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); } FileInfo::FileInfo(const QUrl& u, int payloadSize, const QMimeType& mimeType, const QString& originalFilename) : InfoBase(mimeType), url(u), payloadSize(payloadSize) , originalName(originalFilename) { } FileInfo::FileInfo(const QUrl& u, const QJsonObject& infoJson, const QString& originalFilename) : FileInfo(u, infoJson["size"].toInt(), QMimeDatabase().mimeTypeForName(infoJson["mimetype"].toString()), originalFilename) { if (!mimeType.isValid()) mimeType = QMimeDatabase().mimeTypeForData(QByteArray()); } void FileInfo::fillInfoJson(QJsonObject* infoJson) const { Q_ASSERT(infoJson); infoJson->insert("size", payloadSize); infoJson->insert("mimetype", mimeType.name()); } void FileInfo::fillJson(QJsonObject* json) const { Q_ASSERT(json); json->insert("url", url.toString()); if (!originalName.isEmpty()) json->insert("filename", originalName); json->insert("info", toInfoJson()); } LocationContent::LocationContent(const QString& geoUri, const ImageInfo<>& thumbnail) : Thumbnailed<>(thumbnail), geoUri(geoUri) { } LocationContent::LocationContent(const QJsonObject& json) : Thumbnailed<>(json["info"].toObject()) , geoUri(json["geo_uri"].toString()) { } void LocationContent::fillJson(QJsonObject* o) const { Q_ASSERT(o); o->insert("geo_uri", geoUri); o->insert("info", Thumbnailed::toInfoJson()); } PlayableInfo::PlayableInfo(const QUrl& u, int fileSize, const QMimeType& mimeType, int duration, const QString& originalFilename) : FileInfo(u, fileSize, mimeType, originalFilename) , duration(duration) { } PlayableInfo::PlayableInfo(const QUrl& u, const QJsonObject& infoJson, const QString& originalFilename) : FileInfo(u, infoJson, originalFilename) , duration(infoJson["duration"].toInt()) { } void PlayableInfo::fillInfoJson(QJsonObject* infoJson) const { FileInfo::fillInfoJson(infoJson); infoJson->insert("duration", duration); }