From 818f65e1d9e21a2b0dcecf34312b217000da7c92 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 22 Nov 2020 11:46:01 +0100 Subject: Matrix: add /react --- src/QuickMedia.cpp | 54 +++++++++++++++++++++++++++++++++++--------------- src/plugins/Matrix.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index d9b1041..0f4c695 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -3433,7 +3433,7 @@ namespace QuickMedia { auto filter_my_messages = [&me](Messages &messages) { for(auto it = messages.begin(); it != messages.end();) { - if((*it)->user == me && (*it)->type == MessageType::TEXT) + if((*it)->user == me && ((*it)->type == MessageType::TEXT || (*it)->type == MessageType::REACTION)) it = messages.erase(it); else ++it; @@ -3467,7 +3467,7 @@ namespace QuickMedia { } }; - chat_input.on_submit_callback = [this, &tabs, &me, &chat_input, &selected_tab, ¤t_room, &new_page, &chat_state, ¤tly_operating_on_item, &post_task_queue, &unreferenced_events, &find_body_item_by_event_id](std::string text) mutable { + chat_input.on_submit_callback = [this, &tabs, &me, &chat_input, &selected_tab, ¤t_room, &new_page, &chat_state, ¤tly_operating_on_item, &post_task_queue, &process_reactions, &find_body_item_by_event_id](std::string text) mutable { if(!current_room) return false; @@ -3500,8 +3500,11 @@ namespace QuickMedia { } else if(strncmp(text.c_str(), "/me ", 4) == 0) { msgtype = "m.emote"; text.erase(text.begin(), text.begin() + 4); + } else if(strncmp(text.c_str(), "/react ", 7) == 0) { + msgtype = "m.reaction"; + text.erase(text.begin(), text.begin() + 7); } else { - fprintf(stderr, "Error: invalid command: %s, expected /upload, /logout or /me\n", text.c_str()); + fprintf(stderr, "Error: invalid command: %s, expected /upload, /logout, /me or /react\n", text.c_str()); return false; } } @@ -3523,17 +3526,38 @@ namespace QuickMedia { scroll_to_end = true; if(chat_state == ChatState::TYPING_MESSAGE) { - auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); - body_item->set_description_color(provisional_message_color); - tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item}); - post_task_queue.push([this, ¤t_room, text, msgtype, body_item, message]() { - ProvisionalMessage provisional_message; - provisional_message.body_item = body_item; - provisional_message.message = message; - if(matrix->post_message(current_room, text, provisional_message.event_id, std::nullopt, std::nullopt, msgtype) != PluginResult::OK) - fprintf(stderr, "Failed to post matrix message\n"); - return provisional_message; - }); + BodyItem *selected_item = tabs[MESSAGES_TAB_INDEX].body->get_selected(); + if(msgtype == "m.reaction" && selected_item) { + void *related_to_message = selected_item->userdata; + message->type = MessageType::REACTION; + message->related_event_type = RelatedEventType::REACTION; + message->related_event_id = static_cast(related_to_message)->event_id; + auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); + tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item}); + Messages messages; + messages.push_back(message); + process_reactions(messages); + post_task_queue.push([this, ¤t_room, text, body_item, message, related_to_message]() { + ProvisionalMessage provisional_message; + provisional_message.body_item = body_item; + provisional_message.message = message; + if(matrix->post_reaction(current_room, text, related_to_message, provisional_message.event_id) != PluginResult::OK) + fprintf(stderr, "Failed to post matrix reaction\n"); + return provisional_message; + }); + } else { + auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); + body_item->set_description_color(provisional_message_color); + tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item}); + post_task_queue.push([this, ¤t_room, text, msgtype, body_item, message]() { + ProvisionalMessage provisional_message; + provisional_message.body_item = body_item; + provisional_message.message = message; + if(matrix->post_message(current_room, text, provisional_message.event_id, std::nullopt, std::nullopt, msgtype) != PluginResult::OK) + fprintf(stderr, "Failed to post matrix message\n"); + return provisional_message; + }); + } chat_input.set_editable(false); chat_state = ChatState::NAVIGATING; if(scroll_to_end) @@ -4107,8 +4131,6 @@ namespace QuickMedia { if((selected_tab == MESSAGES_TAB_INDEX || selected_tab == PINNED_TAB_INDEX) && event.key.code == sf::Keyboard::Enter) { BodyItem *selected = tabs[selected_tab].body->get_selected(); if(selected) { - Message *mess = static_cast(selected->userdata); - fprintf(stderr, "Mess type: %d\n", mess->type); if(!display_url_or_image(selected)) display_url_or_image(selected->embedded_item.get()); } diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index e5e4922..05881d5 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -2733,6 +2733,53 @@ namespace QuickMedia { return PluginResult::OK; } + PluginResult Matrix::post_reaction(RoomData *room, const std::string &body, void *relates_to, std::string &event_id_response) { + Message *relates_to_message_raw = (Message*)relates_to; + + char random_characters[18]; + if(!generate_random_characters(random_characters, sizeof(random_characters))) + return PluginResult::ERR; + + std::string random_readable_chars = random_characters_to_readable_string(random_characters, sizeof(random_characters)); + + rapidjson::Document relates_to_json(rapidjson::kObjectType); + relates_to_json.AddMember("event_id", rapidjson::StringRef(relates_to_message_raw->event_id.c_str()), relates_to_json.GetAllocator()); + relates_to_json.AddMember("key", rapidjson::StringRef(body.c_str()), relates_to_json.GetAllocator()); + relates_to_json.AddMember("rel_type", "m.annotation", relates_to_json.GetAllocator()); + + rapidjson::Document request_json(rapidjson::kObjectType); + request_json.AddMember("m.relates_to", std::move(relates_to_json), request_json.GetAllocator()); + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + request_json.Accept(writer); + + std::vector additional_args = { + { "-X", "PUT" }, + { "-H", "content-type: application/json" }, + { "-H", "Authorization: Bearer " + access_token }, + { "--data-binary", buffer.GetString() } + }; + + char request_url[512]; + snprintf(request_url, sizeof(request_url), "%s/_matrix/client/r0/rooms/%s/send/m.reaction/m%ld.%.*s", homeserver.c_str(), room->id.c_str(), time(NULL), (int)random_readable_chars.size(), random_readable_chars.c_str()); + + rapidjson::Document json_root; + DownloadResult download_result = download_json(json_root, request_url, std::move(additional_args), true); + if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result); + + if(!json_root.IsObject()) + return PluginResult::ERR; + + const rapidjson::Value &event_id_json = GetMember(json_root, "event_id"); + if(!event_id_json.IsString()) + return PluginResult::ERR; + + fprintf(stderr, "Matrix post reaction, response event id: %s\n", event_id_json.GetString()); + event_id_response = std::string(event_id_json.GetString(), event_id_json.GetStringLength()); + return PluginResult::OK; + } + std::shared_ptr Matrix::get_message_by_id(RoomData *room, const std::string &event_id) { std::shared_ptr existing_room_message = room->get_message_by_id(event_id); if(existing_room_message) -- cgit v1.2.3