matrixion/src/EventAccessors.cpp

553 lines
14 KiB
C++
Raw Normal View History

// SPDX-FileCopyrightText: Nheko Contributors
2021-03-05 02:35:15 +03:00
//
// SPDX-License-Identifier: GPL-3.0-or-later
2019-12-27 23:49:55 +03:00
#include "EventAccessors.h"
2020-10-27 19:45:28 +03:00
#include <nlohmann/json.hpp>
2020-07-24 20:30:12 +03:00
#include <algorithm>
#include <cctype>
2019-12-27 23:49:55 +03:00
#include <type_traits>
namespace {
2023-10-31 02:47:12 +03:00
2021-02-01 00:41:43 +03:00
struct IsStateEvent
{
2021-09-18 01:22:33 +03:00
template<class T>
2023-03-20 04:28:13 +03:00
constexpr bool operator()(const mtx::events::StateEvent<T> &)
2021-09-18 01:22:33 +03:00
{
return true;
}
template<class T>
2023-03-20 04:28:13 +03:00
constexpr bool operator()(const mtx::events::Event<T> &)
2021-09-18 01:22:33 +03:00
{
return false;
}
2021-02-01 00:41:43 +03:00
};
2019-12-27 23:49:55 +03:00
struct EventMsgType
{
2021-09-18 01:22:33 +03:00
template<class T>
mtx::events::MessageType operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires(decltype(e) t) { t.content.msgtype.value(); })
return mtx::events::getMessageType(e.content.msgtype.value());
else if constexpr (requires(decltype(e) t) { std::string{t.content.msgtype}; })
return mtx::events::getMessageType(e.content.msgtype);
2021-09-18 01:22:33 +03:00
return mtx::events::MessageType::Unknown;
}
2019-12-27 23:49:55 +03:00
};
2023-10-31 02:47:12 +03:00
struct EventType
{
template<class T>
mtx::events::EventType operator()(const mtx::events::Event<T> &e)
{
return e.type;
}
};
2020-07-24 20:30:12 +03:00
struct CallType
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const T &e)
{
2022-06-27 19:09:31 +03:00
if constexpr (std::is_same_v<mtx::events::RoomEvent<mtx::events::voip::CallInvite>, T>) {
2021-09-18 01:22:33 +03:00
const char video[] = "m=video";
2022-06-27 19:38:02 +03:00
const std::string &sdp = e.content.offer.sdp;
2021-09-18 01:22:33 +03:00
return std::search(sdp.cbegin(),
sdp.cend(),
std::cbegin(video),
std::cend(video) - 1,
[](unsigned char c1, unsigned char c2) {
return std::tolower(c1) == std::tolower(c2);
}) != sdp.cend()
? "video"
: "voice";
2020-07-24 20:30:12 +03:00
}
return "";
2021-09-18 01:22:33 +03:00
}
2020-07-24 20:30:12 +03:00
};
2019-12-27 23:49:55 +03:00
struct EventBody
{
2021-09-18 01:22:33 +03:00
template<class T>
2023-03-20 04:28:13 +03:00
const std::string *operator()(const mtx::events::Event<T> &e)
2021-09-18 01:22:33 +03:00
{
2022-09-21 03:58:35 +03:00
if constexpr (requires(decltype(e) t) { t.content.body.value(); })
2023-03-20 04:28:13 +03:00
return e.content.body ? &e.content.body.value() : nullptr;
2022-09-21 03:58:35 +03:00
else if constexpr (requires(decltype(e) t) { std::string{t.content.body}; })
2023-03-20 04:28:13 +03:00
return &e.content.body;
return nullptr;
2021-09-18 01:22:33 +03:00
}
2019-12-27 23:49:55 +03:00
};
struct EventFormattedBody
{
2021-09-18 01:22:33 +03:00
template<class T>
2023-03-20 04:28:13 +03:00
const std::string *operator()(const mtx::events::RoomEvent<T> &e)
2021-09-18 01:22:33 +03:00
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { T::formatted_body; }) {
2021-09-18 01:22:33 +03:00
if (e.content.format == "org.matrix.custom.html")
2023-03-20 04:28:13 +03:00
return &e.content.formatted_body;
2019-12-27 23:49:55 +03:00
}
2023-03-20 04:28:13 +03:00
return nullptr;
2021-09-18 01:22:33 +03:00
}
2019-12-27 23:49:55 +03:00
};
struct EventFile
{
2021-09-18 01:22:33 +03:00
template<class T>
2023-03-20 04:28:13 +03:00
const std::optional<mtx::crypto::EncryptedFile> *operator()(const mtx::events::Event<T> &e)
2021-09-18 01:22:33 +03:00
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { T::file; })
2023-03-20 04:28:13 +03:00
return &e.content.file;
return nullptr;
2021-09-18 01:22:33 +03:00
}
2019-12-27 23:49:55 +03:00
};
struct EventThumbnailFile
{
template<class T>
std::optional<mtx::crypto::EncryptedFile> operator()(const mtx::events::Event<T> &e)
{
2023-03-22 23:01:31 +03:00
if constexpr (requires { e.content.info.thumbnail_file; })
return e.content.info.thumbnail_file;
return std::nullopt;
}
};
2019-12-27 23:49:55 +03:00
struct EventUrl
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { T::url; }) {
2023-03-20 04:28:13 +03:00
if (auto file = EventFile{}(e); file && *file)
return (*file)->url;
2021-09-18 01:22:33 +03:00
return e.content.url;
2019-12-27 23:49:55 +03:00
}
2021-09-18 01:22:33 +03:00
return "";
}
2019-12-27 23:49:55 +03:00
};
struct EventThumbnailUrl
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.thumbnail_url; }) {
if (auto file = EventThumbnailFile{}(e))
return file->url;
2021-09-18 01:22:33 +03:00
return e.content.info.thumbnail_url;
2019-12-27 23:49:55 +03:00
}
2021-09-18 01:22:33 +03:00
return "";
}
2019-12-27 23:49:55 +03:00
};
2022-03-21 02:48:27 +03:00
struct EventDuration
{
template<class T>
uint64_t operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.duration; }) {
2022-03-21 02:48:27 +03:00
return e.content.info.duration;
}
return 0;
}
};
struct EventBlurhash
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.blurhash; }) {
2021-09-18 01:22:33 +03:00
return e.content.info.blurhash;
}
2021-09-18 01:22:33 +03:00
return "";
}
};
2019-12-27 23:49:55 +03:00
struct EventFilename
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const mtx::events::Event<T> &)
{
return "";
}
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Audio> &e)
{
// body may be the original filename
return e.content.body;
}
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Video> &e)
{
// body may be the original filename
return e.content.body;
}
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Image> &e)
{
// body may be the original filename
return e.content.body;
}
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::File> &e)
{
// body may be the original filename
if (!e.content.filename.empty())
return e.content.filename;
return e.content.body;
}
2019-12-27 23:49:55 +03:00
};
struct EventMimeType
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.mimetype; }) {
2021-09-18 01:22:33 +03:00
return e.content.info.mimetype;
2019-12-27 23:49:55 +03:00
}
2021-09-18 01:22:33 +03:00
return "";
}
2019-12-27 23:49:55 +03:00
};
struct EventFilesize
{
2021-09-18 01:22:33 +03:00
template<class T>
int64_t operator()(const mtx::events::RoomEvent<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.size; }) {
2021-09-18 01:22:33 +03:00
return e.content.info.size;
2019-12-27 23:49:55 +03:00
}
2021-09-18 01:22:33 +03:00
return 0;
}
2019-12-27 23:49:55 +03:00
};
2021-01-27 00:36:35 +03:00
struct EventRelations
2019-12-27 23:49:55 +03:00
{
inline const static mtx::common::Relations empty;
2021-09-18 01:22:33 +03:00
template<class T>
const mtx::common::Relations &operator()(const mtx::events::Event<T> &e)
2021-09-18 01:22:33 +03:00
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { T::relations; }) {
2021-09-18 01:22:33 +03:00
return e.content.relations;
2020-07-20 01:42:48 +03:00
}
return empty;
2021-09-18 01:22:33 +03:00
}
2020-07-20 01:42:48 +03:00
};
2021-01-27 18:14:03 +03:00
struct SetEventRelations
{
2021-09-18 01:22:33 +03:00
mtx::common::Relations new_relations;
template<class T>
void operator()(mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { T::relations; }) {
2021-09-18 01:22:33 +03:00
e.content.relations = std::move(new_relations);
2021-01-27 18:14:03 +03:00
}
2021-09-18 01:22:33 +03:00
}
2021-01-27 18:14:03 +03:00
};
struct EventTransactionId
{
2021-09-18 01:22:33 +03:00
template<class T>
std::string operator()(const mtx::events::RoomEvent<T> &e)
{
return e.unsigned_data.transaction_id;
}
template<class T>
std::string operator()(const mtx::events::Event<T> &e)
{
return e.unsigned_data.transaction_id;
}
};
2019-12-27 23:49:55 +03:00
struct EventMediaHeight
{
2021-09-18 01:22:33 +03:00
template<class T>
uint64_t operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.h; }) {
2021-09-18 01:22:33 +03:00
return e.content.info.h;
2019-12-27 23:49:55 +03:00
}
2021-09-18 01:22:33 +03:00
return -1;
}
2019-12-27 23:49:55 +03:00
};
struct EventMediaWidth
{
2021-09-18 01:22:33 +03:00
template<class T>
uint64_t operator()(const mtx::events::Event<T> &e)
{
2022-09-21 03:58:35 +03:00
if constexpr (requires { e.content.info.h; }) {
2021-09-18 01:22:33 +03:00
return e.content.info.w;
2019-12-27 23:49:55 +03:00
}
2021-09-18 01:22:33 +03:00
return -1;
}
2019-12-27 23:49:55 +03:00
};
template<class T>
double
eventPropHeight(const mtx::events::RoomEvent<T> &e)
{
2021-09-18 01:22:33 +03:00
auto w = eventWidth(e);
if (w == 0)
w = 1;
2019-12-27 23:49:55 +03:00
2021-09-18 01:22:33 +03:00
double prop = eventHeight(e) / (double)w;
2019-12-27 23:49:55 +03:00
2021-09-18 01:22:33 +03:00
return prop > 0 ? prop : 1.;
2019-12-27 23:49:55 +03:00
}
}
const std::string &
2019-12-27 23:49:55 +03:00
mtx::accessors::event_id(const mtx::events::collections::TimelineEvents &event)
{
return std::visit([](const auto &e) -> const std::string & { return e.event_id; }, event);
2019-12-27 23:49:55 +03:00
}
const std::string &
2019-12-27 23:49:55 +03:00
mtx::accessors::room_id(const mtx::events::collections::TimelineEvents &event)
{
return std::visit([](const auto &e) -> const std::string & { return e.room_id; }, event);
2019-12-27 23:49:55 +03:00
}
const std::string &
2019-12-27 23:49:55 +03:00
mtx::accessors::sender(const mtx::events::collections::TimelineEvents &event)
{
return std::visit([](const auto &e) -> const std::string & { return e.sender; }, event);
2019-12-27 23:49:55 +03:00
}
QDateTime
mtx::accessors::origin_server_ts(const mtx::events::collections::TimelineEvents &event)
{
2023-10-31 02:47:12 +03:00
return QDateTime::fromMSecsSinceEpoch(origin_server_ts_ms(event));
}
std::uint64_t
mtx::accessors::origin_server_ts_ms(const mtx::events::collections::TimelineEvents &event)
{
return std::visit([](const auto &e) { return e.origin_server_ts; }, event);
2019-12-27 23:49:55 +03:00
}
std::string
mtx::accessors::filename(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventFilename{}, event);
2019-12-27 23:49:55 +03:00
}
2023-10-31 02:47:12 +03:00
mtx::events::EventType
mtx::accessors::event_type(const mtx::events::collections::TimelineEvents &event)
{
return std::visit(EventType{}, event);
}
2019-12-27 23:49:55 +03:00
mtx::events::MessageType
mtx::accessors::msg_type(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventMsgType{}, event);
2019-12-27 23:49:55 +03:00
}
2023-03-20 04:28:13 +03:00
2019-12-27 23:49:55 +03:00
std::string
mtx::accessors::room_name(const mtx::events::collections::TimelineEvents &event)
{
2023-03-20 04:28:13 +03:00
if (auto c = std::get_if<mtx::events::StateEvent<mtx::events::state::Name>>(&event))
return c->content.name;
else
return "";
2019-12-27 23:49:55 +03:00
}
2023-03-20 04:28:13 +03:00
2019-12-27 23:49:55 +03:00
std::string
mtx::accessors::room_topic(const mtx::events::collections::TimelineEvents &event)
{
2023-03-20 04:28:13 +03:00
if (auto c = std::get_if<mtx::events::StateEvent<mtx::events::state::Topic>>(&event))
return c->content.topic;
else
return "";
2019-12-27 23:49:55 +03:00
}
2020-07-24 20:30:12 +03:00
std::string
mtx::accessors::call_type(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(CallType{}, event);
2020-07-24 20:30:12 +03:00
}
2019-12-27 23:49:55 +03:00
std::string
mtx::accessors::body(const mtx::events::collections::TimelineEvents &event)
{
2023-03-20 04:28:13 +03:00
auto body = std::visit(EventBody{}, event);
return body ? *body : std::string{};
2019-12-27 23:49:55 +03:00
}
std::string
mtx::accessors::formatted_body(const mtx::events::collections::TimelineEvents &event)
{
2023-03-20 04:28:13 +03:00
auto body = std::visit(EventFormattedBody{}, event);
return body ? *body : std::string{};
2019-12-27 23:49:55 +03:00
}
QString
mtx::accessors::formattedBodyWithFallback(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
auto formatted = formatted_body(event);
if (!formatted.empty())
return QString::fromStdString(formatted);
else
return QString::fromStdString(body(event))
.toHtmlEscaped()
.replace(QLatin1String("\n"), QLatin1String("<br>"));
2019-12-27 23:49:55 +03:00
}
std::optional<mtx::crypto::EncryptedFile>
mtx::accessors::file(const mtx::events::collections::TimelineEvents &event)
{
2023-03-20 04:28:13 +03:00
auto temp = std::visit(EventFile{}, event);
if (temp)
return *temp;
else
return {};
2019-12-27 23:49:55 +03:00
}
std::optional<mtx::crypto::EncryptedFile>
mtx::accessors::thumbnail_file(const mtx::events::collections::TimelineEvents &event)
{
return std::visit(EventThumbnailFile{}, event);
}
2019-12-27 23:49:55 +03:00
std::string
mtx::accessors::url(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventUrl{}, event);
2019-12-27 23:49:55 +03:00
}
std::string
mtx::accessors::thumbnail_url(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventThumbnailUrl{}, event);
2019-12-27 23:49:55 +03:00
}
2022-03-21 02:48:27 +03:00
uint64_t
mtx::accessors::duration(const mtx::events::collections::TimelineEvents &event)
{
return std::visit(EventDuration{}, event);
}
2019-12-27 23:49:55 +03:00
std::string
mtx::accessors::blurhash(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventBlurhash{}, event);
}
std::string
2019-12-27 23:49:55 +03:00
mtx::accessors::mimetype(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventMimeType{}, event);
2019-12-27 23:49:55 +03:00
}
const mtx::common::Relations &
2021-01-27 00:36:35 +03:00
mtx::accessors::relations(const mtx::events::collections::TimelineEvents &event)
2020-07-20 01:42:48 +03:00
{
2021-09-18 01:22:33 +03:00
return std::visit(EventRelations{}, event);
2020-07-20 01:42:48 +03:00
}
2019-12-27 23:49:55 +03:00
2021-01-27 18:14:03 +03:00
void
mtx::accessors::set_relations(mtx::events::collections::TimelineEvents &event,
mtx::common::Relations relations)
{
2021-09-18 01:22:33 +03:00
std::visit(SetEventRelations{std::move(relations)}, event);
2021-01-27 18:14:03 +03:00
}
std::string
mtx::accessors::transaction_id(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventTransactionId{}, event);
}
2019-12-27 23:49:55 +03:00
int64_t
mtx::accessors::filesize(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventFilesize{}, event);
2019-12-27 23:49:55 +03:00
}
uint64_t
mtx::accessors::media_height(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventMediaHeight{}, event);
2019-12-27 23:49:55 +03:00
}
uint64_t
mtx::accessors::media_width(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(EventMediaWidth{}, event);
2019-12-27 23:49:55 +03:00
}
2020-05-30 17:37:51 +03:00
nlohmann::json
mtx::accessors::serialize_event(const mtx::events::collections::TimelineEvents &event)
{
2023-04-11 01:11:46 +03:00
return nlohmann::json(event);
2020-05-30 17:37:51 +03:00
}
2021-02-01 00:41:43 +03:00
2023-10-31 02:47:12 +03:00
bool
mtx::accessors::is_state_event(const mtx::events::collections::StateEvents &event)
{
return std::visit(IsStateEvent{}, event);
}
2021-02-01 00:41:43 +03:00
bool
mtx::accessors::is_state_event(const mtx::events::collections::TimelineEvents &event)
{
2021-09-18 01:22:33 +03:00
return std::visit(IsStateEvent{}, event);
2021-02-01 00:41:43 +03:00
}
2023-10-31 02:47:12 +03:00
template<typename T>
static constexpr auto
isMessage(const mtx::events::RoomEvent<T> &e)
-> std::enable_if_t<std::is_same<decltype(e.content.msgtype), std::string>::value, bool>
{
return true;
}
template<typename T>
static constexpr auto
isMessage(const mtx::events::Event<T> &)
{
return false;
}
template<typename T>
static constexpr auto
isMessage(const mtx::events::EncryptedEvent<T> &)
{
return true;
}
static constexpr auto
isMessage(const mtx::events::RoomEvent<mtx::events::voip::CallInvite> &)
{
return true;
}
static constexpr auto
isMessage(const mtx::events::RoomEvent<mtx::events::voip::CallAnswer> &)
{
return true;
}
static constexpr auto
isMessage(const mtx::events::RoomEvent<mtx::events::voip::CallHangUp> &)
{
return true;
}
static constexpr auto
isMessage(const mtx::events::RoomEvent<mtx::events::voip::CallReject> &)
{
return true;
}
static constexpr auto
isMessage(const mtx::events::RoomEvent<mtx::events::voip::CallSelectAnswer> &)
{
return true;
}
bool
mtx::accessors::is_message(const mtx::events::collections::TimelineEvents &event)
{
return std::visit([](const auto &e) { return isMessage(e); }, event);
}