aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-03-12 16:13:33 +0100
committerdec05eba <dec05eba@protonmail.com>2021-03-12 16:13:33 +0100
commit34828885b99a808a09bb05820faa3f10a5025a47 (patch)
tree814ba088e41392ecd97923a0a2c70f875113d0a1 /src/plugins
parentb7a68af26f2d377ef28c7ff521da1e62ccd97ebd (diff)
Matrix: add support for sending (code)blocks and greentext in replies
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Matrix.cpp129
1 files changed, 85 insertions, 44 deletions
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index c725fc8..1a70a54 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -2577,6 +2577,84 @@ namespace QuickMedia {
return "m.file";
}
+ static size_t find_backquote_index_with_escape(const std::string &str, size_t start_index = 0) {
+ bool escape = false;
+ for(size_t i = start_index; i < str.size(); ++i) {
+ char c = str[i];
+ if(c == '\\') {
+ escape = !escape;
+ } else if(c == '`' && !escape) {
+ return i;
+ } else {
+ escape = false;
+ }
+ }
+ return std::string::npos;
+ }
+
+ static void formatted_body_add_line(std::string &formatted_body, const std::string &line_str) {
+ size_t index = 0;
+ while(true) {
+ size_t backquote_start_index = find_backquote_index_with_escape(line_str, index);
+ if(backquote_start_index != std::string::npos) {
+ size_t backquote_end_index = find_backquote_index_with_escape(line_str, backquote_start_index + 1);
+ if(backquote_end_index != std::string::npos) {
+ formatted_body += line_str.substr(0, backquote_start_index);
+ formatted_body += "<code>";
+ formatted_body += line_str.substr(backquote_start_index + 1, backquote_end_index - (backquote_start_index + 1));
+ formatted_body += "</code>";
+ index = backquote_end_index + 1;
+ continue;
+ }
+ }
+
+ formatted_body += line_str.substr(index);
+ break;
+ }
+ }
+
+ static std::string body_to_formatted_body(const std::string &body) {
+ std::string formatted_body;
+ bool is_inside_code_block = false;
+ bool is_first_line = true;
+ string_split(body, '\n', [&formatted_body, &is_inside_code_block, &is_first_line](const char *str, size_t size){
+ if(!is_first_line)
+ formatted_body += "<br/>";
+
+ std::string line_str(str, size);
+ html_escape_sequences(line_str);
+ if(size >= 3 && strncmp(str, "```", 3) == 0) {
+ if(is_inside_code_block) {
+ formatted_body += "</code></pre>";
+ is_inside_code_block = false;
+ } else {
+ if(size > 3) {
+ formatted_body += "<pre><code class=\"language-" + strip(line_str.substr(3)) + "\">";
+ } else {
+ formatted_body += "<pre><code>";
+ }
+ is_inside_code_block = true;
+ }
+ is_first_line = true;
+ } else {
+ if(!is_inside_code_block && size > 0 && str[0] == '>') {
+ formatted_body += "<font color=\"#789922\">";
+ formatted_body_add_line(formatted_body, line_str);
+ formatted_body += "</font>";
+ } else {
+ if(is_inside_code_block)
+ formatted_body += line_str;
+ else
+ formatted_body_add_line(formatted_body, line_str);
+ }
+ is_first_line = false;
+ }
+
+ return true;
+ });
+ return formatted_body;
+ }
+
PluginResult Matrix::post_message(RoomData *room, const std::string &body, std::string &event_id_response, const std::optional<UploadInfo> &file_info, const std::optional<UploadInfo> &thumbnail_info, const std::string &msgtype) {
std::string transaction_id = create_transaction_id();
if(transaction_id.empty())
@@ -2585,26 +2663,8 @@ namespace QuickMedia {
my_events_transaction_ids.insert(transaction_id);
std::string formatted_body;
- bool contains_formatted_text = false;
- if(!file_info) {
- int line = 0;
- string_split(body, '\n', [&formatted_body, &contains_formatted_text, &line](const char *str, size_t size){
- if(line > 0)
- formatted_body += "<br/>";
- std::string line_str(str, size);
- html_escape_sequences(line_str);
- if(size > 0 && str[0] == '>') {
- formatted_body += "<font color=\"#789922\">";
- formatted_body += line_str;
- formatted_body += "</font>";
- contains_formatted_text = true;
- } else {
- formatted_body += line_str;
- }
- ++line;
- return true;
- });
- }
+ if(!file_info)
+ formatted_body = body_to_formatted_body(body);
rapidjson::Document request_data(rapidjson::kObjectType);
if(msgtype.empty())
@@ -2612,7 +2672,7 @@ namespace QuickMedia {
else
request_data.AddMember("msgtype", rapidjson::StringRef(msgtype.c_str()), request_data.GetAllocator());
request_data.AddMember("body", rapidjson::StringRef(body.c_str()), request_data.GetAllocator());
- if(contains_formatted_text) {
+ if(!formatted_body.empty()) {
request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_body.c_str()), request_data.GetAllocator());
}
@@ -2752,9 +2812,8 @@ namespace QuickMedia {
}
static std::string create_formatted_body_for_message_reply(RoomData *room, const Message *message, const std::string &body) {
- std::string formatted_body = body;
+ std::string formatted_body = body_to_formatted_body(body);
std::string related_to_body = get_reply_message(message);
- html_escape_sequences(formatted_body);
html_escape_sequences(related_to_body);
// TODO: Add keybind to navigate to the reply message, which would also depend on this formatting.
// Note: user id and event id is not url escaped here on purpose, because that messes up riot.im replies for certain user ids...
@@ -2834,30 +2893,12 @@ namespace QuickMedia {
return PluginResult::ERR;
my_events_transaction_ids.insert(transaction_id);
- std::string formatted_body;
- bool contains_formatted_text = false;
- int line = 0;
- string_split(body, '\n', [&formatted_body, &contains_formatted_text, &line](const char *str, size_t size){
- if(line > 0)
- formatted_body += "<br/>";
- if(size > 0 && str[0] == '>') {
- std::string line(str, size);
- html_escape_sequences(line);
- formatted_body += "<font color=\"#789922\">";
- formatted_body += line;
- formatted_body += "</font>";
- contains_formatted_text = true;
- } else {
- formatted_body.append(str, size);
- }
- ++line;
- return true;
- });
+ std::string formatted_body = body_to_formatted_body(body);
rapidjson::Document new_content_json(rapidjson::kObjectType);
new_content_json.AddMember("msgtype", "m.text", new_content_json.GetAllocator());
new_content_json.AddMember("body", rapidjson::StringRef(body.c_str()), new_content_json.GetAllocator());
- if(contains_formatted_text) {
+ if(!formatted_body.empty()) {
new_content_json.AddMember("format", "org.matrix.custom.html", new_content_json.GetAllocator());
new_content_json.AddMember("formatted_body", rapidjson::StringRef(formatted_body.c_str()), new_content_json.GetAllocator());
}
@@ -2872,7 +2913,7 @@ namespace QuickMedia {
rapidjson::Document request_data(rapidjson::kObjectType);
request_data.AddMember("msgtype", "m.text", request_data.GetAllocator()); // TODO: Allow other types of edits
request_data.AddMember("body", rapidjson::StringRef(body_edit_str.c_str()), request_data.GetAllocator());
- if(contains_formatted_text) {
+ if(!formatted_body.empty()) {
formatted_body_edit_str = " * " + formatted_body;
request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_body_edit_str.c_str()), request_data.GetAllocator());