aboutsummaryrefslogtreecommitdiff
path: root/events/roommessageevent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'events/roommessageevent.cpp')
-rw-r--r--events/roommessageevent.cpp229
1 files changed, 122 insertions, 107 deletions
diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp
index 48f52453..09465238 100644
--- a/events/roommessageevent.cpp
+++ b/events/roommessageevent.cpp
@@ -19,7 +19,7 @@
#include "roommessageevent.h"
#include <QtCore/QJsonObject>
-#include <QtCore/QDateTime>
+#include <QtCore/QMimeDatabase>
#include <QtCore/QDebug>
using namespace QMatrixClient;
@@ -27,20 +27,18 @@ using namespace QMatrixClient;
class RoomMessageEvent::Private
{
public:
- Private() {}
+ Private() : msgtype(MessageEventType::Unknown), content(nullptr) {}
QString userId;
MessageEventType msgtype;
- QDateTime hsob_ts;
- MessageEventContent* content;
+ QString plainBody;
+ MessageEventContent::Base* content;
};
RoomMessageEvent::RoomMessageEvent()
: Event(EventType::RoomMessage)
, d(new Private)
-{
- d->content = nullptr;
-}
+{ }
RoomMessageEvent::~RoomMessageEvent()
{
@@ -57,21 +55,42 @@ MessageEventType RoomMessageEvent::msgtype() const
return d->msgtype;
}
+QString RoomMessageEvent::plainBody() const
+{
+ return d->plainBody;
+}
+
QString RoomMessageEvent::body() const
{
- return d->content->body;
+ return plainBody();
}
-QDateTime RoomMessageEvent::hsob_ts() const
+using namespace MessageEventContent;
+
+Base* RoomMessageEvent::content() const
{
- return d->hsob_ts;
+ return d->content;
}
-MessageEventContent* RoomMessageEvent::content() const
+template <class ContentT>
+Base* make(const QJsonObject& json)
{
- return d->content;
+ return new ContentT(json);
}
+Base* makeVideoContent(const QJsonObject& json)
+{
+ auto c = new VideoContent(json);
+ // Only for m.video, the spec puts a thumbnail inside "info" JSON key. Once
+ // this is fixed, VideoContent creation will switch to make<>().
+ const QJsonObject infoJson = json["info"].toObject();
+ if (infoJson.contains("thumbnail_url"))
+ c->thumbnail = ImageInfo(infoJson["thumbnail_url"].toString(),
+ infoJson["thumbnail_info"].toObject());
+
+ return c;
+};
+
RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj)
{
RoomMessageEvent* e = new RoomMessageEvent();
@@ -84,107 +103,103 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj)
}
if( obj.contains("content") )
{
- QJsonObject content = obj.value("content").toObject();
- QString msgtype = content.value("msgtype").toString();
-
- if( msgtype == "m.text" )
- {
- e->d->msgtype = MessageEventType::Text;
- e->d->content = new MessageEventContent();
- }
- else if( msgtype == "m.emote" )
- {
- e->d->msgtype = MessageEventType::Emote;
- e->d->content = new MessageEventContent();
- }
- else if( msgtype == "m.notice" )
- {
- e->d->msgtype = MessageEventType::Notice;
- e->d->content = new MessageEventContent();
- }
- else if( msgtype == "m.image" )
- {
- e->d->msgtype = MessageEventType::Image;
- ImageEventContent* c = new ImageEventContent;
- c->url = QUrl(content.value("url").toString());
- QJsonObject info = content.value("info").toObject();
- c->height = info.value("h").toInt();
- c->width = info.value("w").toInt();
- c->size = info.value("size").toInt();
- c->mimetype = info.value("mimetype").toString();
- e->d->content = c;
- }
- else if( msgtype == "m.file" )
- {
- e->d->msgtype = MessageEventType::File;
- FileEventContent* c = new FileEventContent;
- c->filename = content.value("filename").toString();
- c->url = QUrl(content.value("url").toString());
- QJsonObject info = content.value("info").toObject();
- c->size = info.value("size").toInt();
- c->mimetype = info.value("mimetype").toString();
- e->d->content = c;
- }
- else if( msgtype == "m.location" )
- {
- e->d->msgtype = MessageEventType::Location;
- LocationEventContent* c = new LocationEventContent;
- c->geoUri = content.value("geo_uri").toString();
- c->thumbnailUrl = QUrl(content.value("thumbnail_url").toString());
- QJsonObject info = content.value("thumbnail_info").toObject();
- c->thumbnailHeight = info.value("h").toInt();
- c->thumbnailWidth = info.value("w").toInt();
- c->thumbnailSize = info.value("size").toInt();
- c->thumbnailMimetype = info.value("mimetype").toString();
- e->d->content = c;
- }
- else if( msgtype == "m.video" )
+ const QJsonObject content = obj["content"].toObject();
+ if ( content.contains("msgtype") && content.contains("body") )
{
- e->d->msgtype = MessageEventType::Video;
- VideoEventContent* c = new VideoEventContent;
- c->url = QUrl(content.value("url").toString());
- QJsonObject info = content.value("info").toObject();
- c->height = info.value("h").toInt();
- c->width = info.value("w").toInt();
- c->duration = info.value("duration").toInt();
- c->size = info.value("size").toInt();
- c->thumbnailUrl = QUrl(info.value("thumnail_url").toString());
- QJsonObject thumbnailInfo = content.value("thumbnail_info").toObject();
- c->thumbnailHeight = thumbnailInfo.value("h").toInt();
- c->thumbnailWidth = thumbnailInfo.value("w").toInt();
- c->thumbnailSize = thumbnailInfo.value("size").toInt();
- c->thumbnailMimetype = thumbnailInfo.value("mimetype").toString();
- e->d->content = c;
- }
- else if( msgtype == "m.audio" )
- {
- e->d->msgtype = MessageEventType::Audio;
- AudioEventContent* c = new AudioEventContent;
- c->url = QUrl(content.value("url").toString());
- QJsonObject info = content.value("info").toObject();
- c->duration = info.value("duration").toInt();
- c->mimetype = info.value("mimetype").toString();
- c->size = info.value("size").toInt();
- e->d->content = c;
+ e->d->plainBody = content["body"].toString();
+
+ struct Factory
+ {
+ QString jsonTag;
+ MessageEventType enumTag;
+ Base*(*make)(const QJsonObject& json);
+ };
+
+ const Factory factories[] {
+ { "m.text", MessageEventType::Text, make<TextContent> },
+ { "m.emote", MessageEventType::Emote, make<TextContent> },
+ { "m.notice", MessageEventType::Notice, make<TextContent> },
+ { "m.image", MessageEventType::Image, make<ImageContent> },
+ { "m.file", MessageEventType::File, make<FileContent> },
+ { "m.location", MessageEventType::Location, make<LocationContent> },
+ { "m.video", MessageEventType::Video, makeVideoContent },
+ { "m.audio", MessageEventType::Audio, make<AudioContent> },
+ // Insert new message types before this line
+ };
+
+ QString msgtype = content.value("msgtype").toString();
+ for (auto f: factories)
+ {
+ if (msgtype == f.jsonTag)
+ {
+ e->d->msgtype = f.enumTag;
+ e->d->content = f.make(content);
+ break;
+ }
+ }
+ if (e->d->msgtype == MessageEventType::Unknown)
+ {
+ qDebug() << "RoomMessageEvent: unknown msgtype: " << msgtype;
+ qDebug() << obj;
+ e->d->content = new Base;
+ }
}
else
{
- qDebug() << "RoomMessageEvent: unknown msgtype: " << msgtype;
+ qWarning() << "RoomMessageEvent(" << e->id() << "): no body or msgtype";
qDebug() << obj;
- e->d->msgtype = MessageEventType::Unknown;
- e->d->content = new MessageEventContent;
- }
-
- if( content.contains("body") )
- {
- e->d->content->body = content.value("body").toString();
- } else {
- qDebug() << "RoomMessageEvent: body not found";
}
-// e->d->hsob_ts = QDateTime::fromMSecsSinceEpoch( content.value("hsoc_ts").toInt() );
-// } else {
-// qDebug() << "RoomMessageEvent: hsoc_ts not found";
-// }
}
return e;
}
+
+using namespace MessageEventContent;
+
+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 {
+ // Best-guessing from the content
+ body = json["body"].toString();
+ mimeType = db.mimeTypeForData(body.toUtf8());
+ }
+}
+
+FileInfo::FileInfo(QUrl u, const QJsonObject& infoJson, QString originalFilename)
+ : url(u)
+ , fileSize(infoJson["size"].toInt())
+ , mimetype(QMimeDatabase().mimeTypeForName(infoJson["mimetype"].toString()))
+ , originalName(originalFilename)
+{
+ if (!mimetype.isValid())
+ mimetype = QMimeDatabase().mimeTypeForData(QByteArray());
+}
+
+ImageInfo::ImageInfo(QUrl u, const QJsonObject& infoJson)
+ : FileInfo(u, infoJson)
+ , imageSize(infoJson["w"].toInt(), infoJson["h"].toInt())
+{ }
+
+LocationContent::LocationContent(const QJsonObject& json)
+ : geoUri(json["geo_uri"].toString())
+ , thumbnail(json["thumbnail_url"].toString(),
+ json["thumbnail_info"].toObject())
+{ }
+
+VideoInfo::VideoInfo(QUrl u, const QJsonObject& infoJson)
+ : FileInfo(u, infoJson)
+ , duration(infoJson["duration"].toInt())
+ , imageSize(infoJson["w"].toInt(), infoJson["h"].toInt())
+{ }
+
+AudioInfo::AudioInfo(QUrl u, const QJsonObject& infoJson)
+ : FileInfo(u, infoJson)
+ , duration(infoJson["duration"].toInt())
+{ }