Add event contents

This commit is contained in:
Konstantinos Sideris 2017-05-02 04:22:33 +03:00
parent 9cc9b623eb
commit b064df8b45
23 changed files with 1517 additions and 7 deletions

View file

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.1)
project(nheko CXX) project(nheko CXX)
option(BUILD_TESTS "Build all tests" OFF)
find_package(Qt5Widgets REQUIRED) find_package(Qt5Widgets REQUIRED)
find_package(Qt5Network REQUIRED) find_package(Qt5Network REQUIRED)
@ -114,8 +116,22 @@ set(SRC_FILES
src/ui/ThemeManager.cc src/ui/ThemeManager.cc
) )
set(MATRIX_EVENTS
src/events/AliasesEventContent.cc
src/events/AvatarEventContent.cc
src/events/CanonicalAliasEventContent.cc
src/events/CreateEventContent.cc
src/events/HistoryVisibilityEventContent.cc
src/events/JoinRulesEventContent.cc
src/events/MemberEventContent.cc
src/events/NameEventContent.cc
src/events/PowerLevelsEventContent.cc
src/events/TopicEventContent.cc
)
include_directories(include) include_directories(include)
include_directories(include/ui) include_directories(include/ui)
include_directories(include/events)
qt5_wrap_ui (UI_HEADERS qt5_wrap_ui (UI_HEADERS
forms/ChatPage.ui forms/ChatPage.ui
@ -161,9 +177,24 @@ qt5_wrap_cpp(MOC_HEADERS
qt5_add_resources(QRC resources/res.qrc) qt5_add_resources(QRC resources/res.qrc)
add_executable (nheko ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC}) add_library(matrix_events ${MATRIX_EVENTS} src/Deserializable.cc)
target_link_libraries (nheko Qt5::Widgets Qt5::Network) target_link_libraries(matrix_events Qt5::Core)
if(WIN32) if (BUILD_TESTS)
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(events_test tests/events.cc)
target_link_libraries(events_test matrix_events ${GTEST_BOTH_LIBRARIES})
add_test(MatrixEvents events_test)
else()
add_executable (nheko ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC})
target_link_libraries (nheko matrix_events Qt5::Widgets Qt5::Network)
if(WIN32)
target_link_libraries(nheko Qt5::WinMain) target_link_libraries(nheko Qt5::WinMain)
endif(WIN32) endif(WIN32)
endif()

View file

@ -1,11 +1,11 @@
SRC := $(shell find include src -type f -type f \( -iname "*.cc" -o -iname "*.h" \)) SRC := $(shell find include src -type f -type f \( -iname "*.cc" -o -iname "*.h" \))
debug: debug:
@cmake -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Debug @cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Debug
@cmake --build build @cmake --build build
release-debug: release-debug:
@cmake -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo @cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
@cmake --build build @cmake --build build
run: run:
@ -14,6 +14,11 @@ run:
lint: lint:
@clang-format -i $(SRC) @clang-format -i $(SRC)
test:
@cmake -DBUILD_TESTS=ON -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release
@cmake --build build
@cd build && GTEST_COLOR=1 ctest --verbose
clean: clean:
rm -rf build rm -rf build

View file

@ -0,0 +1,42 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ALIASES_EVENT_CONTENT_H
#define ALIASES_EVENT_CONTENT_H
#include <QJsonValue>
#include <QList>
#include "Deserializable.h"
class AliasesEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QList<QString> aliases() const;
private:
QList<QString> aliases_;
};
inline QList<QString> AliasesEventContent::aliases() const
{
return aliases_;
}
#endif // ALIASES_EVENT_CONTENT_H

View file

@ -0,0 +1,46 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AVATAR_EVENT_CONTENT_H
#define AVATAR_EVENT_CONTENT_H
#include <QJsonValue>
#include <QUrl>
#include "Deserializable.h"
/*
* A picture that is associated with the room.
*/
class AvatarEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QUrl url() const;
private:
QUrl url_;
};
inline QUrl AvatarEventContent::url() const
{
return url_;
}
#endif // AVATAR_EVENT_CONTENT_H

View file

@ -0,0 +1,49 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CANONICAL_ALIAS_EVENT_CONTENT_H
#define CANONICAL_ALIAS_EVENT_CONTENT_H
#include <QJsonValue>
#include "CanonicalAliasEventContent.h"
#include "Deserializable.h"
/*
* This event is used to inform the room about which alias should be considered
* the canonical one. This could be for display purposes or as suggestion to
* users which alias to use to advertise the room.
*/
class CanonicalAliasEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QString alias() const;
private:
QString alias_;
};
inline QString CanonicalAliasEventContent::alias() const
{
return alias_;
}
#endif // CANONICAL_ALIAS_EVENT_CONTENT_H

View file

@ -0,0 +1,46 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CREATE_EVENT_CONTENT_H
#define CREATE_EVENT_CONTENT_H
#include <QJsonValue>
#include "Deserializable.h"
/*
* This is the first event in a room and cannot be changed. It acts as the root of all other events.
*/
class CreateEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QString creator() const;
private:
// The user_id of the room creator. This is set by the homeserver.
QString creator_;
};
inline QString CreateEventContent::creator() const
{
return creator_;
}
#endif // CREATE_EVENT_CONTENT_H

View file

@ -0,0 +1,48 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HISTORY_VISIBILITY_EVENT_CONTENT_H
#define HISTORY_VISIBILITY_EVENT_CONTENT_H
#include <QJsonValue>
#include "Deserializable.h"
enum HistoryVisibility {
Invited,
Joined,
Shared,
WorldReadable,
};
class HistoryVisibilityEventContent : public Deserializable
{
public:
inline HistoryVisibility historyVisibility() const;
void deserialize(const QJsonValue &data) override;
private:
HistoryVisibility history_visibility_;
};
inline HistoryVisibility HistoryVisibilityEventContent::historyVisibility() const
{
return history_visibility_;
}
#endif // HISTORY_VISIBILITY_EVENT_CONTENT_H

View file

@ -0,0 +1,60 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JOIN_RULES_EVENT_CONTENT_H
#define JOIN_RULES_EVENT_CONTENT_H
#include <QJsonValue>
#include "Deserializable.h"
enum JoinRule {
// A user who wishes to join the room must first receive
// an invite to the room from someone already inside of the room.
Invite,
// Reserved but not yet implemented by the Matrix specification.
Knock,
// Reserved but not yet implemented by the Matrix specification.
Private,
/// Anyone can join the room without any prior action.
Public,
};
/*
* Describes how users are allowed to join the room.
*/
class JoinRulesEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline JoinRule joinRule() const;
private:
JoinRule join_rule_;
};
inline JoinRule JoinRulesEventContent::joinRule() const
{
return join_rule_;
}
#endif // JOIN_RULES_EVENT_CONTENT_H

View file

@ -0,0 +1,77 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MEMBER_EVENT_CONTENT_H
#define MEMBER_EVENT_CONTENT_H
#include <QJsonValue>
#include <QUrl>
#include "Deserializable.h"
enum Membership {
// The user is banned.
BanState,
// The user has been invited.
InviteState,
// The user has joined.
JoinState,
// The user has requested to join.
KnockState,
// The user has left.
LeaveState,
};
/*
* The current membership state of a user in the room.
*/
class MemberEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QUrl avatarUrl() const;
inline QString displayName() const;
inline Membership membershipState() const;
private:
QUrl avatar_url_;
QString display_name_;
Membership membership_state_;
};
inline QUrl MemberEventContent::avatarUrl() const
{
return avatar_url_;
}
inline QString MemberEventContent::displayName() const
{
return display_name_;
}
inline Membership MemberEventContent::membershipState() const
{
return membership_state_;
}
#endif // MEMBER_EVENT_CONTENT_H

View file

@ -0,0 +1,45 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NAME_EVENT_CONTENT_H
#define NAME_EVENT_CONTENT_H
#include <QJsonValue>
#include "Deserializable.h"
/*
* A human-friendly room name designed to be displayed to the end-user.
*/
class NameEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QString name() const;
private:
QString name_;
};
inline QString NameEventContent::name() const
{
return name_;
}
#endif // NAME_EVENT_CONTENT_H

View file

@ -0,0 +1,102 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef POWER_LEVELS_EVENT_CONTENT_H
#define POWER_LEVELS_EVENT_CONTENT_H
#include <QJsonValue>
#include <QMap>
#include "Deserializable.h"
enum PowerLevels {
User = 0,
Moderator = 50,
Admin = 100,
};
/*
* Defines the power levels (privileges) of users in the room.
*/
class PowerLevelsEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline int banLevel() const;
inline int inviteLevel() const;
inline int kickLevel() const;
inline int redactLevel() const;
inline int eventsDefaultLevel() const;
inline int stateDefaultLevel() const;
inline int usersDefaultLevel() const;
int eventLevel(QString event_type) const;
int userLevel(QString user_id) const;
private:
int ban_ = PowerLevels::Moderator;
int invite_ = PowerLevels::Moderator;
int kick_ = PowerLevels::Moderator;
int redact_ = PowerLevels::Moderator;
int events_default_ = PowerLevels::User;
int state_default_ = PowerLevels::Moderator;
int users_default_ = PowerLevels::User;
QMap<QString, int> events_;
QMap<QString, int> users_;
};
inline int PowerLevelsEventContent::banLevel() const
{
return ban_;
}
inline int PowerLevelsEventContent::inviteLevel() const
{
return invite_;
}
inline int PowerLevelsEventContent::kickLevel() const
{
return kick_;
}
inline int PowerLevelsEventContent::redactLevel() const
{
return redact_;
}
inline int PowerLevelsEventContent::eventsDefaultLevel() const
{
return events_default_;
}
inline int PowerLevelsEventContent::stateDefaultLevel() const
{
return state_default_;
}
inline int PowerLevelsEventContent::usersDefaultLevel() const
{
return users_default_;
}
#endif // POWER_LEVELS_EVENT_CONTENT_H

View file

@ -0,0 +1,45 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TOPIC_EVENT_CONTENT_H
#define TOPIC_EVENT_CONTENT_H
#include <QJsonValue>
#include "Deserializable.h"
/*
* A topic is a short message detailing what is currently being discussed in the room.
*/
class TopicEventContent : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QString topic() const;
private:
QString topic_;
};
inline QString TopicEventContent::topic() const
{
return topic_;
}
#endif // TOPIC_EVENT_CONTENT_H

View file

@ -0,0 +1,36 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QJsonArray>
#include "AliasesEventContent.h"
void AliasesEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("AliasesEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("aliases") == QJsonValue::Undefined)
throw DeserializationException("aliases key is missing");
auto aliases = object.value("aliases").toArray();
for (const auto &alias : aliases)
aliases_.push_back(alias.toString());
}

View file

@ -0,0 +1,36 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QDebug>
#include "AvatarEventContent.h"
void AvatarEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("AvatarEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("url") == QJsonValue::Undefined)
throw DeserializationException("url key is missing");
url_ = QUrl(object.value("url").toString());
if (!url_.isValid())
qWarning() << "Invalid avatar url" << url_;
}

View file

@ -0,0 +1,31 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanonicalAliasEventContent.h"
void CanonicalAliasEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("CanonicalAliasEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("alias") == QJsonValue::Undefined)
throw DeserializationException("alias key is missing");
alias_ = object.value("alias").toString();
}

View file

@ -0,0 +1,31 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CreateEventContent.h"
void CreateEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("CreateEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("creator") == QJsonValue::Undefined)
throw DeserializationException("creator key is missing");
creator_ = object.value("creator").toString();
}

View file

@ -0,0 +1,42 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "HistoryVisibilityEventContent.h"
void HistoryVisibilityEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("HistoryVisibilityEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("history_visibility") == QJsonValue::Undefined)
throw DeserializationException("history_visibility key is missing");
auto value = object.value("history_visibility").toString();
if (value == "invited")
history_visibility_ = HistoryVisibility::Invited;
else if (value == "joined")
history_visibility_ = HistoryVisibility::Joined;
else if (value == "shared")
history_visibility_ = HistoryVisibility::Shared;
else if (value == "world_readable")
history_visibility_ = HistoryVisibility::WorldReadable;
else
throw DeserializationException(QString("Unknown history_visibility value: %1").arg(value).toUtf8().constData());
}

View file

@ -0,0 +1,42 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "JoinRulesEventContent.h"
void JoinRulesEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("JoinRulesEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("join_rule") == QJsonValue::Undefined)
throw DeserializationException("join_rule key is missing");
auto value = object.value("join_rule").toString();
if (value == "invite")
join_rule_ = JoinRule::Invite;
else if (value == "knock")
join_rule_ = JoinRule::Knock;
else if (value == "private")
join_rule_ = JoinRule::Private;
else if (value == "public")
join_rule_ = JoinRule::Public;
else
throw DeserializationException(QString("Unknown join_rule value: %1").arg(value).toUtf8().constData());
}

View file

@ -0,0 +1,55 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QDebug>
#include "MemberEventContent.h"
void MemberEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("MemberEventContent is not a JSON object");
auto object = data.toObject();
if (!object.contains("membership"))
throw DeserializationException("membership key is missing");
auto value = object.value("membership").toString();
if (value == "ban")
membership_state_ = Membership::BanState;
else if (value == "invite")
membership_state_ = Membership::InviteState;
else if (value == "join")
membership_state_ = Membership::JoinState;
else if (value == "knock")
membership_state_ = Membership::KnockState;
else if (value == "leave")
membership_state_ = Membership::LeaveState;
else
throw DeserializationException(QString("Unknown membership value: %1").arg(value).toUtf8().constData());
if (object.contains("avatar_url"))
avatar_url_ = QUrl(object.value("avatar_url").toString());
if (!avatar_url_.toString().isEmpty() && !avatar_url_.isValid())
qWarning() << "Invalid avatar url" << avatar_url_;
if (object.contains("displayname"))
display_name_ = object.value("displayname").toString();
}

View file

@ -0,0 +1,31 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "NameEventContent.h"
void NameEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("NameEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("name") == QJsonValue::Undefined)
throw DeserializationException("name key is missing");
name_ = object.value("name").toString();
}

View file

@ -0,0 +1,80 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QJsonObject>
#include "Deserializable.h"
#include "PowerLevelsEventContent.h"
void PowerLevelsEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("PowerLevelsEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("ban") != QJsonValue::Undefined)
ban_ = object.value("ban").toInt();
if (object.value("invite") != QJsonValue::Undefined)
invite_ = object.value("invite").toInt();
if (object.value("kick") != QJsonValue::Undefined)
kick_ = object.value("kick").toInt();
if (object.value("redact") != QJsonValue::Undefined)
redact_ = object.value("redact").toInt();
if (object.value("events_default") != QJsonValue::Undefined)
events_default_ = object.value("events_default").toInt();
if (object.value("state_default") != QJsonValue::Undefined)
state_default_ = object.value("state_default").toInt();
if (object.value("users_default") != QJsonValue::Undefined)
users_default_ = object.value("users_default").toInt();
if (object.value("users").isObject()) {
auto users = object.value("users").toObject();
for (auto it = users.constBegin(); it != users.constEnd(); it++)
users_.insert(it.key(), it.value().toInt());
}
if (object.value("events").isObject()) {
auto events = object.value("events").toObject();
for (auto it = events.constBegin(); it != events.constEnd(); it++)
events_.insert(it.key(), it.value().toInt());
}
}
int PowerLevelsEventContent::eventLevel(QString event_type) const
{
if (events_.contains(event_type))
return events_[event_type];
return events_default_;
}
int PowerLevelsEventContent::userLevel(QString userid) const
{
if (users_.contains(userid))
return users_[userid];
return users_default_;
}

View file

@ -0,0 +1,31 @@
/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TopicEventContent.h"
void TopicEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("TopicEventContent is not a JSON object");
auto object = data.toObject();
if (object.value("topic") == QJsonValue::Undefined)
throw DeserializationException("topic key is missing");
topic_ = object.value("topic").toString();
}

499
tests/events.cc Normal file
View file

@ -0,0 +1,499 @@
#include <gtest/gtest.h>
#include <QJsonArray>
#include "AliasesEventContent.h"
#include "AvatarEventContent.h"
#include "CanonicalAliasEventContent.h"
#include "CreateEventContent.h"
#include "HistoryVisibilityEventContent.h"
#include "JoinRulesEventContent.h"
#include "MemberEventContent.h"
#include "NameEventContent.h"
#include "PowerLevelsEventContent.h"
#include "TopicEventContent.h"
TEST(AliasesEventContent, Deserialization)
{
auto data = QJsonObject{
{"aliases", QJsonArray{"#test:matrix.org", "#test2:matrix.org"}}};
AliasesEventContent content;
content.deserialize(data);
EXPECT_EQ(content.aliases().size(), 2);
}
TEST(AliasesEventContent, NotAnObject)
{
auto data = QJsonArray{"#test:matrix.org", "#test2:matrix.org"};
AliasesEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(AliasesEventContent, MissingKey)
{
auto data = QJsonObject{
{"key", QJsonArray{"#test:matrix.org", "#test2:matrix.org"}}};
AliasesEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("aliases key is missing", e.what());
}
}
TEST(AvatarEventContent, Deserialization)
{
auto data = QJsonObject{{"url", "https://matrix.org/avatar.png"}};
AvatarEventContent content;
content.deserialize(data);
EXPECT_EQ(content.url().toString(), "https://matrix.org/avatar.png");
}
TEST(AvatarEventContent, NotAnObject)
{
auto data = QJsonArray{"key", "url"};
AvatarEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(AvatarEventContent, MissingKey)
{
auto data = QJsonObject{{"key", "https://matrix.org"}};
AvatarEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("url key is missing", e.what());
}
}
TEST(CreateEventContent, Deserialization)
{
auto data = QJsonObject{{"creator", "@alice:matrix.org"}};
CreateEventContent content;
content.deserialize(data);
EXPECT_EQ(content.creator(), "@alice:matrix.org");
}
TEST(CreateEventContent, NotAnObject)
{
auto data = QJsonArray{"creator", "alice"};
CreateEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(CreateEventContent, MissingKey)
{
auto data = QJsonObject{{"key", "@alice:matrix.org"}};
CreateEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("creator key is missing", e.what());
}
}
TEST(HistoryVisibilityEventContent, Deserialization)
{
auto data = QJsonObject{{"history_visibility", "invited"}};
HistoryVisibilityEventContent content;
content.deserialize(data);
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Invited);
data = QJsonObject{{"history_visibility", "joined"}};
content.deserialize(data);
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Joined);
data = QJsonObject{{"history_visibility", "shared"}};
content.deserialize(data);
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Shared);
data = QJsonObject{{"history_visibility", "world_readable"}};
content.deserialize(data);
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::WorldReadable);
}
TEST(HistoryVisibilityEventContent, NotAnObject)
{
auto data = QJsonArray{"history_visibility", "alice"};
HistoryVisibilityEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(HistoryVisibilityEventContent, InvalidHistoryVisibility)
{
auto data = QJsonObject{{"history_visibility", "wrong"}};
HistoryVisibilityEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("Unknown history_visibility value: wrong", e.what());
}
}
TEST(HistoryVisibilityEventContent, MissingKey)
{
auto data = QJsonObject{{"key", "joined"}};
HistoryVisibilityEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("history_visibility key is missing", e.what());
}
}
TEST(JoinRulesEventContent, Deserialization)
{
auto data = QJsonObject{{"join_rule", "invite"}};
JoinRulesEventContent content;
content.deserialize(data);
EXPECT_EQ(content.joinRule(), JoinRule::Invite);
data = QJsonObject{{"join_rule", "knock"}};
content.deserialize(data);
EXPECT_EQ(content.joinRule(), JoinRule::Knock);
data = QJsonObject{{"join_rule", "private"}};
content.deserialize(data);
EXPECT_EQ(content.joinRule(), JoinRule::Private);
data = QJsonObject{{"join_rule", "public"}};
content.deserialize(data);
EXPECT_EQ(content.joinRule(), JoinRule::Public);
}
TEST(JoinRulesEventContent, NotAnObject)
{
auto data = QJsonArray{"rule", "alice"};
JoinRulesEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(JoinRulesEventContent, InvalidHistoryVisibility)
{
auto data = QJsonObject{{"join_rule", "wrong"}};
JoinRulesEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("Unknown join_rule value: wrong", e.what());
}
}
TEST(JoinRulesEventContent, MissingKey)
{
auto data = QJsonObject{{"key", "invite"}};
JoinRulesEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("join_rule key is missing", e.what());
}
}
TEST(CanonicalAliasEventContent, Deserialization)
{
auto data = QJsonObject{{"alias", "Room Alias"}};
CanonicalAliasEventContent content;
content.deserialize(data);
EXPECT_EQ(content.alias(), "Room Alias");
}
TEST(CanonicalAliasEventContent, NotAnObject)
{
auto data = QJsonArray{"alias", "Room Alias"};
CanonicalAliasEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(CanonicalAliasEventContent, MissingKey)
{
auto data = QJsonObject{{"key", "alias"}};
CanonicalAliasEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("alias key is missing", e.what());
}
}
TEST(MemberEventContent, Deserialization)
{
MemberEventContent content;
auto data = QJsonObject{{"membership", "join"}};
content.deserialize(data);
EXPECT_EQ(content.membershipState(), Membership::JoinState);
data = QJsonObject{{"membership", "invite"}, {"displayname", "Username"}};
content.deserialize(data);
EXPECT_EQ(content.membershipState(), Membership::InviteState);
EXPECT_EQ(content.displayName(), "Username");
data = QJsonObject{{"membership", "leave"}, {"avatar_url", "https://matrix.org"}};
content.deserialize(data);
EXPECT_EQ(content.membershipState(), Membership::LeaveState);
EXPECT_EQ(content.avatarUrl().toString(), "https://matrix.org");
data = QJsonObject{{"membership", "ban"}};
content.deserialize(data);
EXPECT_EQ(content.membershipState(), Membership::BanState);
data = QJsonObject{{"membership", "knock"}};
content.deserialize(data);
EXPECT_EQ(content.membershipState(), Membership::KnockState);
}
TEST(MemberEventContent, InvalidMembership)
{
auto data = QJsonObject{{"membership", "wrong"}};
MemberEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("Unknown membership value: wrong", e.what());
}
}
TEST(MemberEventContent, NotAnObject)
{
auto data = QJsonArray{"name", "join"};
MemberEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(MemberEventContent, MissingName)
{
auto data = QJsonObject{{"key", "random"}};
MemberEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("membership key is missing", e.what());
}
}
TEST(NameEventContent, Deserialization)
{
auto data = QJsonObject{{"name", "Room Name"}};
NameEventContent content;
content.deserialize(data);
EXPECT_EQ(content.name(), "Room Name");
}
TEST(NameEventContent, NotAnObject)
{
auto data = QJsonArray{"name", "Room Name"};
NameEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(NameEventContent, MissingName)
{
auto data = QJsonObject{{"key", "Room Name"}};
NameEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("name key is missing", e.what());
}
}
TEST(PowerLevelsEventContent, DefaultValues)
{
PowerLevelsEventContent power_levels;
EXPECT_EQ(power_levels.banLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.inviteLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.kickLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.redactLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.eventsDefaultLevel(), PowerLevels::User);
EXPECT_EQ(power_levels.usersDefaultLevel(), PowerLevels::User);
EXPECT_EQ(power_levels.stateDefaultLevel(), PowerLevels::Moderator);
// Default levels.
EXPECT_EQ(power_levels.userLevel("@joe:matrix.org"), PowerLevels::User);
EXPECT_EQ(power_levels.eventLevel("m.room.message"), PowerLevels::User);
}
TEST(PowerLevelsEventContent, FullDeserialization)
{
auto data = QJsonObject{
{"ban", 1},
{"invite", 2},
{"kick", 3},
{"redact", 4},
{"events_default", 5},
{"state_default", 6},
{"users_default", 7},
{"events", QJsonObject{{"m.message.text", 8}, {"m.message.image", 9}}},
{"users", QJsonObject{{"@alice:matrix.org", 10}, {"@bob:matrix.org", 11}}},
};
PowerLevelsEventContent power_levels;
power_levels.deserialize(data);
EXPECT_EQ(power_levels.banLevel(), 1);
EXPECT_EQ(power_levels.inviteLevel(), 2);
EXPECT_EQ(power_levels.kickLevel(), 3);
EXPECT_EQ(power_levels.redactLevel(), 4);
EXPECT_EQ(power_levels.eventsDefaultLevel(), 5);
EXPECT_EQ(power_levels.stateDefaultLevel(), 6);
EXPECT_EQ(power_levels.usersDefaultLevel(), 7);
EXPECT_EQ(power_levels.userLevel("@alice:matrix.org"), 10);
EXPECT_EQ(power_levels.userLevel("@bob:matrix.org"), 11);
EXPECT_EQ(power_levels.userLevel("@carl:matrix.org"), 7);
EXPECT_EQ(power_levels.eventLevel("m.message.text"), 8);
EXPECT_EQ(power_levels.eventLevel("m.message.image"), 9);
EXPECT_EQ(power_levels.eventLevel("m.message.gif"), 5);
}
TEST(PowerLevelsEventContent, PartialDeserialization)
{
auto data = QJsonObject{
{"ban", 1},
{"invite", 2},
{"events_default", 5},
{"users_default", 7},
{"users", QJsonObject{{"@alice:matrix.org", 10}, {"@bob:matrix.org", 11}}},
};
PowerLevelsEventContent power_levels;
power_levels.deserialize(data);
EXPECT_EQ(power_levels.banLevel(), 1);
EXPECT_EQ(power_levels.inviteLevel(), 2);
EXPECT_EQ(power_levels.kickLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.redactLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.eventsDefaultLevel(), 5);
EXPECT_EQ(power_levels.stateDefaultLevel(), PowerLevels::Moderator);
EXPECT_EQ(power_levels.usersDefaultLevel(), 7);
EXPECT_EQ(power_levels.userLevel("@alice:matrix.org"), 10);
EXPECT_EQ(power_levels.userLevel("@bob:matrix.org"), 11);
EXPECT_EQ(power_levels.userLevel("@carl:matrix.org"), 7);
EXPECT_EQ(power_levels.eventLevel("m.message.text"), 5);
EXPECT_EQ(power_levels.eventLevel("m.message.image"), 5);
EXPECT_EQ(power_levels.eventLevel("m.message.gif"), 5);
}
TEST(PowerLevelsEventContent, NotAnObject)
{
auto data = QJsonArray{"test", "test2"};
PowerLevelsEventContent power_levels;
ASSERT_THROW(power_levels.deserialize(data), DeserializationException);
}
TEST(TopicEventContent, Deserialization)
{
auto data = QJsonObject{{"topic", "Room Topic"}};
TopicEventContent content;
content.deserialize(data);
EXPECT_EQ(content.topic(), "Room Topic");
}
TEST(TopicEventContent, NotAnObject)
{
auto data = QJsonArray{"topic", "Room Topic"};
TopicEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
}
TEST(TopicEventContent, MissingName)
{
auto data = QJsonObject{{"key", "Room Name"}};
TopicEventContent content;
ASSERT_THROW(content.deserialize(data), DeserializationException);
try {
content.deserialize(data);
} catch (const DeserializationException &e) {
ASSERT_STREQ("topic key is missing", e.what());
}
}