Skip to content
Snippets Groups Projects
Unverified Commit b1d71485 authored by Joe Donofry's avatar Joe Donofry Committed by GitHub
Browse files

Merge pull request #18 from MonokelPinguin/0.3.0-dev

Basic support for room upgrade handling.  Closes PR #18
parents 8c6e9ba8 708f0322
No related branches found
No related tags found
No related merge requests found
......@@ -133,6 +133,7 @@ add_library(matrix_client
lib/structs/events/power_levels.cpp
lib/structs/events/redaction.cpp
lib/structs/events/tag.cpp
lib/structs/events/tombstone.cpp
lib/structs/events/topic.cpp
lib/structs/events/messages/audio.cpp
lib/structs/events/messages/emote.cpp
......
......@@ -48,6 +48,8 @@ enum class EventType
RoomRedaction,
/// m.room.pinned_events
RoomPinnedEvents,
/// m.room.tombstone
RoomTombstone,
// m.sticker
Sticker,
// m.tag
......@@ -136,6 +138,9 @@ to_json(json &obj, const Event<Content> &event)
case EventType::RoomPinnedEvents:
obj["type"] = "m.room.pinned_events";
break;
case EventType::RoomTombstone:
obj["type"] = "m.room.tombstone";
break;
case EventType::Sticker:
obj["type"] = "m.sticker";
break;
......
......@@ -18,6 +18,7 @@
#include "mtx/events/power_levels.hpp"
#include "mtx/events/redaction.hpp"
#include "mtx/events/tag.hpp"
#include "mtx/events/tombstone.hpp"
#include "mtx/events/topic.hpp"
#include "mtx/events/messages/audio.hpp"
......@@ -54,6 +55,7 @@ using StateEvents = boost::variant<events::StateEvent<states::Aliases>,
events::StateEvent<states::Name>,
events::StateEvent<states::PinnedEvents>,
events::StateEvent<states::PowerLevels>,
events::StateEvent<states::Tombstone>,
events::StateEvent<states::Topic>,
events::StateEvent<msgs::Redacted>>;
......@@ -69,6 +71,7 @@ using StrippedEvents = boost::variant<events::StrippedEvent<states::Aliases>,
events::StrippedEvent<states::Name>,
events::StrippedEvent<states::PinnedEvents>,
events::StrippedEvent<states::PowerLevels>,
events::StrippedEvent<states::Tombstone>,
events::StrippedEvent<states::Topic>>;
//! Collection of @p StateEvent and @p RoomEvent. Those events would be
......@@ -85,6 +88,7 @@ using TimelineEvents = boost::variant<events::StateEvent<states::Aliases>,
events::StateEvent<states::Name>,
events::StateEvent<states::PinnedEvents>,
events::StateEvent<states::PowerLevels>,
events::StateEvent<states::Tombstone>,
events::StateEvent<states::Topic>,
events::EncryptedEvent<msgs::Encrypted>,
events::RedactionEvent<msgs::Redaction>,
......@@ -164,6 +168,10 @@ from_json(const json &obj, TimelineEvent &e)
e.data = events::RedactionEvent<mtx::events::msg::Redaction>(obj);
break;
}
case events::EventType::RoomTombstone: {
e.data = events::StateEvent<Tombstone>(obj);
break;
}
case events::EventType::RoomTopic: {
e.data = events::StateEvent<Topic>(obj);
break;
......
#pragma once
#include <boost/optional.hpp>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
......@@ -8,6 +9,14 @@ namespace mtx {
namespace events {
namespace state {
struct PreviousRoom
{
//! Required. The ID of the old room.
std::string room_id;
//! Required. The event ID of the last known event in the old room.
std::string event_id;
};
//! Content of the `m.room.create` event.
//
//! This is the first event in a room and cannot be changed.
......@@ -16,9 +25,16 @@ struct Create
{
//! The `user_id` of the room creator. This is set by the homeserver.
std::string creator;
//! Whether users on other servers can join this room.
//! Defaults to **true** if key does not exist.
bool federate = true;
//! The version of the room. Defaults to "1" if the key does not exist.
std::string room_version = "1";
//! A reference to the room this room replaces, if the previous room was upgraded.
boost::optional<PreviousRoom> predecessor;
};
void
......
#pragma once
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace mtx {
namespace events {
namespace state {
//! Content for the `m.room.tombstone` event.
//
//! A state event signifying that a room has been
//! upgraded to a different room version, and
//! that clients should go there.
struct Tombstone
{
//! Required. A server-defined message.
std::string body;
//! Required. The new room the client should be visiting.
std::string replacement_room;
};
//! Deserialization method needed by @p nlohmann::json.
void
from_json(const json &obj, Tombstone &content);
//! Serialization method needed by @p nlohmann::json.
void
to_json(json &obj, const Tombstone &content);
} // namespace state
} // namespace events
} // namespace mtx
......@@ -93,7 +93,7 @@ unpickle(const std::string &pickled, const std::string &key)
if (ret == -1)
throw olm_exception("unpickle", object.get());
return std::move(object);
return object;
}
using OlmSessionPtr = std::unique_ptr<OlmSession, OlmDeleter>;
......
......@@ -528,7 +528,7 @@ mtx::http::Client::create_session(HeadersCallback<Response> callback)
boost::signals2::signal<void()>::slot_type(&Session::terminate, session.get())
.track_foreign(session));
return std::move(session);
return session;
}
template<class Payload, mtx::events::EventType Event>
......
......@@ -42,6 +42,8 @@ getEventType(const std::string &type)
return EventType::RoomRedaction;
else if (type == "m.room.pinned_events")
return EventType::RoomPinnedEvents;
else if (type == "m.room.tombstone")
return EventType::RoomTombstone;
else if (type == "m.sticker")
return EventType::Sticker;
else if (type == "m.tag")
......@@ -88,6 +90,8 @@ to_string(EventType type)
return "m.room.redaction";
case EventType::RoomPinnedEvents:
return "m.room.pinned_events";
case EventType::RoomTombstone:
return "m.room.tombstone";
case EventType::Sticker:
return "m.sticker";
case EventType::Tag:
......
......@@ -8,6 +8,19 @@ namespace mtx {
namespace events {
namespace state {
void
from_json(const json &obj, PreviousRoom &predecessor)
{
predecessor.room_id = obj.at("room_id");
predecessor.event_id = obj.at("event_id");
}
void
to_json(json &obj, const PreviousRoom &predecessor)
{
obj["room_id"] = predecessor.room_id;
obj["event_id"] = predecessor.event_id;
}
void
from_json(const json &obj, Create &create)
{
......@@ -15,13 +28,23 @@ from_json(const json &obj, Create &create)
if (obj.find("m.federate") != obj.end())
create.federate = obj.at("m.federate").get<bool>();
if (obj.find("room_version") != obj.end())
create.room_version = obj.at("room_version");
if (obj.find("predecessor") != obj.end())
create.predecessor = obj.at("predecessor").get<PreviousRoom>();
}
void
to_json(json &obj, const Create &create)
{
obj["creator"] = create.creator;
obj["m.federate"] = create.federate;
obj["creator"] = create.creator;
obj["m.federate"] = create.federate;
obj["room_version"] = create.room_version;
if (create.predecessor)
obj["predecessor"] = *create.predecessor;
}
} // namespace state
......
#include <nlohmann/json.hpp>
using json = nlohmann::json;
#include "mtx/events/tombstone.hpp"
namespace mtx {
namespace events {
namespace state {
void
from_json(const json &obj, Tombstone &content)
{
content.body = obj.at("body");
content.replacement_room = obj.at("replacement_room");
}
void
to_json(json &obj, const Tombstone &content)
{
obj["body"] = content.body;
obj["replacement_room"] = content.replacement_room;
}
} // namespace state
} // namespace events
} // namespace mtx
......@@ -93,6 +93,7 @@ parse_room_account_data_events(
case events::EventType::RoomMessage:
case events::EventType::RoomName:
case events::EventType::RoomPowerLevels:
case events::EventType::RoomTombstone:
case events::EventType::RoomTopic:
case events::EventType::RoomRedaction:
case events::EventType::RoomPinnedEvents:
......@@ -233,6 +234,15 @@ parse_timeline_events(const json &events,
break;
}
case events::EventType::RoomTombstone: {
try {
container.emplace_back(events::StateEvent<Tombstone>(e));
} catch (json::exception &err) {
log_error(err, e);
}
break;
}
case events::EventType::RoomTopic: {
try {
container.emplace_back(events::StateEvent<Topic>(e));
......@@ -474,6 +484,15 @@ parse_state_events(const json &events,
break;
}
case events::EventType::RoomTombstone: {
try {
container.emplace_back(events::StateEvent<Tombstone>(e));
} catch (json::exception &err) {
log_error(err, e);
}
break;
}
case events::EventType::RoomTopic: {
try {
container.emplace_back(events::StateEvent<Topic>(e));
......@@ -597,6 +616,15 @@ parse_stripped_events(const json &events,
break;
}
case events::EventType::RoomTombstone: {
try {
container.emplace_back(events::StrippedEvent<Tombstone>(e));
} catch (json::exception &err) {
log_error(err, e);
}
break;
}
case events::EventType::RoomTopic: {
try {
container.emplace_back(events::StrippedEvent<Topic>(e));
......
......@@ -51,6 +51,7 @@ TEST(Events, Conversions)
EXPECT_EQ("m.room.name", ns::to_string(ns::EventType::RoomName));
EXPECT_EQ("m.room.power_levels", ns::to_string(ns::EventType::RoomPowerLevels));
EXPECT_EQ("m.room.topic", ns::to_string(ns::EventType::RoomTopic));
EXPECT_EQ("m.room.tombstone", ns::to_string(ns::EventType::RoomTombstone));
EXPECT_EQ("m.room.redaction", ns::to_string(ns::EventType::RoomRedaction));
EXPECT_EQ("m.room.pinned_events", ns::to_string(ns::EventType::RoomPinnedEvents));
EXPECT_EQ("m.tag", ns::to_string(ns::EventType::Tag));
......@@ -179,6 +180,41 @@ TEST(StateEvents, Create)
EXPECT_EQ(event.origin_server_ts, 1506761923948L);
EXPECT_EQ(event.state_key, "");
EXPECT_EQ(event.content.creator, "@mujx:matrix.org");
json example_from_spec = R"({
"content": {
"creator": "@example:example.org",
"m.federate": true,
"predecessor": {
"event_id": "$something:example.org",
"room_id": "!oldroom:example.org"
},
"room_version": "1"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "",
"type": "m.room.create",
"unsigned": {
"age": 1234
}
})"_json;
event = example_from_spec;
EXPECT_EQ(event.type, ns::EventType::RoomCreate);
EXPECT_EQ(event.event_id, "$143273582443PhrSn:example.org");
EXPECT_EQ(event.sender, "@example:example.org");
EXPECT_EQ(event.unsigned_data.age, 1234);
EXPECT_EQ(event.origin_server_ts, 1432735824653L);
EXPECT_EQ(event.state_key, "");
EXPECT_EQ(event.content.creator, "@example:example.org");
EXPECT_EQ(event.content.federate, true);
EXPECT_EQ(event.content.room_version, "1");
EXPECT_EQ(event.content.predecessor->room_id, "!oldroom:example.org");
EXPECT_EQ(event.content.predecessor->event_id, "$something:example.org");
}
TEST(StateEvents, GuestAccess)
......@@ -512,6 +548,37 @@ TEST(StateEvents, PowerLevels)
EXPECT_EQ(event.content.user_level("@not:matrix.org"), event.content.users_default);
}
TEST(StateEvents, Tombstone)
{
json data = R"({
"content": {
"body": "This room has been replaced",
"replacement_room": "!newroom:example.org"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "",
"type": "m.room.tombstone",
"unsigned": {
"age": 1234
}
})"_json;
ns::StateEvent<ns::state::Tombstone> event = data;
EXPECT_EQ(event.type, ns::EventType::RoomTombstone);
EXPECT_EQ(event.event_id, "$143273582443PhrSn:example.org");
EXPECT_EQ(event.room_id, "!jEsUZKDJdhlrceRyVU:example.org");
EXPECT_EQ(event.sender, "@example:example.org");
EXPECT_EQ(event.origin_server_ts, 1432735824653);
EXPECT_EQ(event.unsigned_data.age, 1234);
EXPECT_EQ(event.state_key, "");
EXPECT_EQ(event.content.body, "This room has been replaced");
EXPECT_EQ(event.content.replacement_room, "!newroom:example.org");
}
TEST(StateEvents, Topic)
{
json data = R"({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment