aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Matrix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/Matrix.cpp')
-rw-r--r--src/plugins/Matrix.cpp137
1 files changed, 121 insertions, 16 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 9a2f70b..99d6bed 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -115,6 +115,51 @@ namespace QuickMedia {
return pinned_events;
}
+ bool RoomData::has_prev_batch() {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ return !prev_batch.empty();
+ }
+
+ void RoomData::set_prev_batch(const std::string &new_prev_batch) {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ prev_batch = new_prev_batch;
+ }
+
+ std::string RoomData::get_prev_batch() {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ return prev_batch;
+ }
+
+ bool RoomData::has_name() {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ return !name.empty();
+ }
+
+ void RoomData::set_name(const std::string &new_name) {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ name = new_name;
+ }
+
+ std::string RoomData::get_name() {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ return name;
+ }
+
+ bool RoomData::has_avatar_url() {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ return !avatar_url.empty();
+ }
+
+ void RoomData::set_avatar_url(const std::string &new_avatar_url) {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ avatar_url = new_avatar_url;
+ }
+
+ std::string RoomData::get_avatar_url() {
+ std::lock_guard<std::mutex> lock(room_mutex);
+ return avatar_url;
+ }
+
PluginResult Matrix::sync(RoomSyncData &room_sync_data) {
std::vector<CommandArg> additional_args = {
{ "-H", "Authorization: Bearer " + access_token },
@@ -227,11 +272,11 @@ namespace QuickMedia {
const rapidjson::Value &timeline_json = GetMember(it.value, "timeline");
if(timeline_json.IsObject()) {
- if(room->prev_batch.empty()) {
+ if(!room->has_prev_batch()) {
// This may be non-existent if this is the first event in the room
const rapidjson::Value &prev_batch_json = GetMember(timeline_json, "prev_batch");
if(prev_batch_json.IsString())
- room->prev_batch = prev_batch_json.GetString();
+ room->set_prev_batch(prev_batch_json.GetString());
}
// TODO: Use /_matrix/client/r0/notifications ? or remove this and always look for displayname/user_id in messages
@@ -258,6 +303,12 @@ namespace QuickMedia {
events_add_user_read_markers(events_json, room);
}
}
+
+ const rapidjson::Value &account_data_json = GetMember(it.value, "account_data");
+ if(account_data_json.IsObject()) {
+ const rapidjson::Value &events_json = GetMember(account_data_json, "events");
+ events_add_room_to_tags(events_json, room);
+ }
}
return PluginResult::OK;
@@ -709,11 +760,14 @@ namespace QuickMedia {
if(!name_json.IsString())
continue;
- room_data->name = name_json.GetString();
+ room_data->set_name(name_json.GetString());
}
+ bool has_room_name = room_data->has_name();
+ bool has_room_avatar_url = room_data->has_avatar_url();
+
std::vector<std::shared_ptr<UserInfo>> users_excluding_me;
- if(room_data->name.empty() || room_data->avatar_url.empty())
+ if(!has_room_name || !has_room_avatar_url)
users_excluding_me = room_data->get_users_excluding_me(user_id); // TODO: What about thread safety with user_id? its reset in /logout
for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
@@ -732,18 +786,21 @@ namespace QuickMedia {
if(!creator_json.IsString())
continue;
- if(room_data->name.empty())
- room_data->name = combine_user_display_names_for_room_name(users_excluding_me, creator_json.GetString());
+ if(!has_room_name) {
+ room_data->set_name(combine_user_display_names_for_room_name(users_excluding_me, creator_json.GetString()));
+ has_room_name = true;
+ }
- if(room_data->avatar_url.empty()) {
+ if(!has_room_avatar_url) {
if(users_excluding_me.empty()) {
auto user = room_data->get_user_by_id(creator_json.GetString());
if(user)
- room_data->avatar_url = user->avatar_url;
+ room_data->set_avatar_url(user->avatar_url);
} else {
// TODO: If there are multiple users, then we want to use some other type of avatar, not the first users avatar
- room_data->avatar_url = users_excluding_me.front()->avatar_url;
+ room_data->set_avatar_url(users_excluding_me.front()->avatar_url);
}
+ has_room_avatar_url = true;
}
}
@@ -764,7 +821,7 @@ namespace QuickMedia {
continue;
std::string url_json_str = url_json.GetString() + 6;
- room_data->avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + std::move(url_json_str) + "?width=32&height=32&method=crop";
+ room_data->set_avatar_url(homeserver + "/_matrix/media/r0/thumbnail/" + std::move(url_json_str) + "?width=32&height=32&method=crop");
}
}
@@ -801,8 +858,54 @@ namespace QuickMedia {
room_data->append_pinned_events(std::move(pinned_events));
}
+ // TODO: According to spec: "Any tag in the tld.name.* form but not matching the namespace of the current client should be ignored",
+ // should we follow this?
+ static const char* tag_get_name(const char *name, size_t size) {
+ if(size >= 2 && (memcmp(name, "m.", 2) == 0 || memcmp(name, "u.", 2) == 0))
+ return name + 2;
+ else if(size >= 9 && memcmp(name, "tld.name.", 9) == 0)
+ return name + 9;
+ else
+ return name;
+ }
+
+ void Matrix::events_add_room_to_tags(const rapidjson::Value &events_json, RoomData *room_data) {
+ if(!events_json.IsArray())
+ return;
+
+ std::vector<std::string> pinned_events;
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
+ continue;
+
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.tag") != 0)
+ continue;
+
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
+ continue;
+
+ const rapidjson::Value &tags_json = GetMember(content_json, "tags");
+ if(!tags_json.IsObject())
+ continue;
+
+ for(auto const &tag_json : tags_json.GetObject()) {
+ if(!tag_json.name.IsString() || !tag_json.value.IsObject())
+ continue;
+
+ const char *tag_name = tag_get_name(tag_json.name.GetString(), tag_json.name.GetStringLength());
+ if(!tag_name)
+ continue;
+
+ // TODO: Support tag order
+ rooms_by_tag_name[tag_name].push_back(room_data->index);
+ }
+ }
+ }
+
PluginResult Matrix::get_previous_room_messages(RoomData *room_data) {
- std::string from = room_data->prev_batch;
+ std::string from = room_data->get_prev_batch();
if(from.empty()) {
fprintf(stderr, "Info: missing previous batch for room: %s, using /sync next batch\n", room_data->id.c_str());
from = next_batch;
@@ -835,9 +938,9 @@ namespace QuickMedia {
if(!json_root.IsObject())
return PluginResult::ERR;
- const rapidjson::Value &state_json = GetMember(json_root, "state");
- events_add_user_info(state_json, room_data);
- events_set_room_name(state_json, room_data);
+ //const rapidjson::Value &state_json = GetMember(json_root, "state");
+ //events_add_user_info(state_json, room_data);
+ //events_set_room_name(state_json, room_data);
const rapidjson::Value &chunk_json = GetMember(json_root, "chunk");
events_add_messages(chunk_json, room_data, MessageDirection::BEFORE, nullptr, false);
@@ -848,7 +951,7 @@ namespace QuickMedia {
return PluginResult::OK;
}
- room_data->prev_batch = end_json.GetString();
+ room_data->set_prev_batch(end_json.GetString());
return PluginResult::OK;
}
@@ -1478,6 +1581,7 @@ namespace QuickMedia {
rooms.clear();
room_list_read_index = 0;
room_data_by_id.clear();
+ rooms_by_tag_name.clear();
user_id.clear();
username.clear();
access_token.clear();
@@ -1722,7 +1826,8 @@ namespace QuickMedia {
void Matrix::add_room(std::unique_ptr<RoomData> room) {
std::lock_guard<std::mutex> lock(room_data_mutex);
- room_data_by_id.insert(std::make_pair(room->id, rooms.size()));
+ room->index = rooms.size();
+ room_data_by_id.insert(std::make_pair(room->id, room->index));
rooms.push_back(std::move(room));
}