From 78f6f8210d76760e3be8d76abe29796a20873e90 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 20 Nov 2019 01:56:09 +0100 Subject: Continue on 4chan, update readme info about tor --- README.md | 4 +- project.conf | 3 +- src/Body.cpp | 2 +- src/plugins/Fourchan.cpp | 392 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 395 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d19b120..e452ca3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # QuickMedia Native clients of websites with fast access to what you want to see, **with TOR support**. See [old video demo with manga](https://beta.lbry.tv/quickmedia_manga-2019-08-05_21.20.46/7).\ -Currently supported websites: `youtube`, `manganelo` and _others_. **Note:** Manganelo doesn't work when used with TOR.\ +Currently supported websites: `youtube`, `manganelo` and _others_.\ +**Note:** Manganelo doesn't work when used with TOR.\ +**Note:** TOR system service needs to be running (`systemctl start tor.service`).\ Here is an example with YouTube:\ ![QuickMedia Youtube Picture](QuickMediaYoutube.png)\ Config data, including manga progress is stored under `$HOME/.config/quickmedia` diff --git a/project.conf b/project.conf index f93e09e..fb21e5d 100644 --- a/project.conf +++ b/project.conf @@ -11,4 +11,5 @@ version = "c++17" sfml-graphics = "2" x11 = "1.6.5" jsoncpp = "1.5" -cppcodec-1 = "0.1" \ No newline at end of file +cppcodec-1 = "0.1" +tidy = "5" \ No newline at end of file diff --git a/src/Body.cpp b/src/Body.cpp index 7ed1a7f..db27214 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -222,7 +222,7 @@ namespace QuickMedia { image.setPosition(item_pos); window.draw(image); text_offset_x = width_ratio * image_size.x; - } else { + } else if(!item->thumbnail_url.empty()) { image_fallback.setPosition(item_pos); window.draw(image_fallback); text_offset_x = image_fallback.getSize().x; diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp index 0c3bffb..01039b9 100644 --- a/src/plugins/Fourchan.cpp +++ b/src/plugins/Fourchan.cpp @@ -1,6 +1,8 @@ #include "../../plugins/Fourchan.hpp" #include #include +#include +#include // API documentation: https://github.com/4chan/4chan-API @@ -17,6 +19,38 @@ curl 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJ -H 'Content-Type: application/x-www-form-urlencoded' --data 'c=03AOLTBLQ66PjSi9s8S-R1vUS2Jgm-Z_ghEejvvjAaeF3FoR9MiM0zHhCxuertrCo7MAcFUEqcIg4l2WJzVtrJhJVLkncF12OzCaeIvbm46hgDZDZjLD89-LMn1Zs0TP37P-Hd4cuRG8nHuEBXc2ZBD8CVX-6HAs9VBgSmsgQeKF1PWm1tAMBccJhlh4rAOkpjzaEXMMGOe17N0XViwDYZxLGhe4H8IAG2KNB1fb4rz4YKJTPbL30_FvHw7zkdFtojjWiqVW0yCN6N192dhfd9oKz2r9pGRrR6N4AkkX-L0DsBD4yNK3QRsQn3dB1fs3JRZPAh1yqUqTQYhOaqdggyc1EwL8FZHouGRkHTOcCmLQjyv6zuhi6CJbg&response=1&response=4&response=5&response=7' */ +/* +Response: + + + + + + reCAPTCHA challenge + + + +
+
+
+ +
+
+
Copy this code and paste it in the empty box below
+
+ +
This code is valid for 2 minutes
+
+
+ +
+ + + +*/ /* Posting message: curl 'https://sys.4chan.org/bant/post' @@ -27,6 +61,249 @@ curl 'https://sys.4chan.org/bant/post' -H 'Cookie: __cfduid=d4bd4932e46bc3272fae4ce7a4e2aac511546800687; 4chan_pass=_SsBuZaATt3dIqfVEWlpemhU5XLQ6i9RC' --data-binary $'-----------------------------119561554312148213571335532670\r\nContent-Disposition: form-data; name="resto"\r\n\r\n8640736\r\n-----------------------------119561554312148213571335532670\r\nContent-Disposition: form-data; name="com"\r\n\r\n>>8640771\r\nShe looks finnish\r\n-----------------------------119561554312148213571335532670\r\nContent-Disposition: form-data; name="mode"\r\n\r\nregist\r\n-----------------------------119561554312148213571335532670\r\nContent-Disposition: form-data; name="pwd"\r\n\r\n_SsBuZaATt3dIqfVEWlpemhU5XLQ6i9RC\r\n-----------------------------119561554312148213571335532670\r\nContent-Disposition: form-data; name="g-recaptcha-response"\r\n\r\n03AOLTBLS5lshp5aPj5pG6xdVMQ0pHuHxAtJoCEYuPLNKYlsRWNCPQegjB9zgL-vwdGMzjcT-L9iW4bnQ5W3TqUWHOVqtsfnx9GipLUL9o2XbC6r9zy-EEiPde7l6J0WcZbr9nh_MGcUpKl6RGaZoYB3WwXaDq74N5hkmEAbqM_CBtbAVVlQyPmemI2HhO2J6K0yFVKBrBingtIZ6-oXBXZ4jC4rT0PeOuVaH_gf_EBjTpb55ueaPmTbeLGkBxD4-wL1qA8F8h0D8c\r\n-----------------------------119561554312148213571335532670--\r\n' */ +/* Response if banned: + + + + + + + + + + + + + + +/g/ - Technology - 4chan + + + + + + +
+ +[a / +b / +c / +d / +e / +f / +g / +gif / +h / +hr / +k / +m / +o / +p / +r / +s / +t / +u / +v / +vg / +vr / +w + / wg] + +[i / +ic] + +[r9k / +s4s / +vip / +qa] + +[cm / +hm / +lgbt + / y] + +[3 / +aco / +adv / +an / +asp / +bant / +biz / +cgl / +ck / +co / +diy / +fa / +fit / +gd / +hc / +his / +int / +jp / +lit / +mlp / +mu / +n / +news / +out / +po / +pol / +qst / +sci / +soc / +sp / +tg / +toy / +trv / +tv / +vp / +wsg / +wsr / +x] + + + +[Settings] +[Search] +[Mobile] +[Home] +
+ +
+
+ Board + +
+ +
+ + Settings + Mobile + Home +
+ +
+ + +
+
+
/g/ - Technology
+ +
+
Error: You are banned.

[Return]



+ + + + +All trademarks and copyrights on this page are owned by their respective parties. Images uploaded are the responsibility of the Poster. Comments are owned by the Poster. + + +
+ +
+ +*/ +/* Banned page: + + + + + +4chan - Banned + + + + + + + + + + + +
+
+
+4chan +
+
+
+
+
+

You are banned! ;_;

+
+
+Banned + +You have been banned from /g/ for posting >>73505519, a violation of Rule 1:

+Off-topic; all images and discussion should pertain to technology and related topics.

+Your ban was filed on November 9th, 2019 and expires on November 10th, 2019 at 22:10 ET, which is 23 hours and 14 minutes from now. +

+According to our server, your IP is: YOURIP. The name you were posting with was Anonymous.
+
+Because of the short length of your ban, you may not appeal it. Please check back when your ban has expired. +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + + + +*/ namespace QuickMedia { PluginResult Fourchan::get_front_page(BodyItems &result_items) { @@ -52,7 +329,7 @@ namespace QuickMedia { if(board_id.isString() && board_title.isString() && board_description.isString()) { std::string board_description_str = board_description.asString(); html_unescape_sequences(board_description_str); - auto body_item = std::make_unique(board_title.asString()); + auto body_item = std::make_unique("/" + board_id.asString() + "/ " + board_title.asString()); body_item->url = board_id.asString(); result_items.emplace_back(std::move(body_item)); } @@ -134,6 +411,94 @@ namespace QuickMedia { return PluginResult::OK; } + struct CommentPiece { + enum class Type { + TEXT, + QUOTE, // > + QUOTELINK, // >>POSTNO, + LINEBREAK + }; + + std::string_view text; // Set when type is TEXT, QUOTE or QUOTELINK + int64_t quote_postnumber; // Set when type is QUOTELINK + Type type; + }; + + static TidyAttr get_attribute_by_name(TidyNode node, const char *name) { + for(TidyAttr attr = tidyAttrFirst(node); attr; attr = tidyAttrNext(attr)) { + const char *attr_name = tidyAttrName(attr); + if(attr_name && strcmp(name, attr_name) == 0) + return attr; + } + return nullptr; + } + + static const char* get_attribute_value(TidyNode node, const char *name) { + TidyAttr attr = get_attribute_by_name(node, name); + if(attr) + return tidyAttrValue(attr); + return nullptr; + } + + using CommentPieceCallback = std::function; + static void extract_comment_pieces(TidyDoc doc, TidyNode node, CommentPieceCallback callback) { + const char *node_name = tidyNodeGetName(node); + printf("node name: %s\n", node_name ? node_name : "N/A"); + + TidyNodeType node_type = tidyNodeGetType(node); + if(node_type == TidyNode_Text) { + TidyBuffer tidy_buffer; + tidyBufInit(&tidy_buffer); + if(tidyNodeGetText(doc, node, &tidy_buffer)) { + CommentPiece comment_piece; + comment_piece.type = CommentPiece::Type::TEXT; + if(node_name) { + if(strncmp("a", (const char*)tidy_buffer.bp, tidy_buffer.size) == 0) { + const char *a_href = get_attribute_value(node, "href"); + if(a_href && strncmp(a_href, "#p", 2) == 0) { + comment_piece.type = CommentPiece::Type::QUOTELINK; + comment_piece.quote_postnumber = strtoll(a_href + 2, nullptr, 10); + } + } else if(strncmp("span", (const char*)tidy_buffer.bp, tidy_buffer.size) == 0) { + const char *a_class = get_attribute_value(node, "class"); + if(a_class && strcmp(a_class, "quote") == 0) { + comment_piece.type = CommentPiece::Type::QUOTE; + comment_piece.text = { (const char*)tidy_buffer.bp, tidy_buffer.size }; + } + } + } + printf("Comment piece value: %.*s\n", tidy_buffer.size, tidy_buffer.bp); + comment_piece.text = { (const char*)tidy_buffer.bp, tidy_buffer.size }; + callback(comment_piece); + } + tidyBufFree(&tidy_buffer); + } else if(node_name) { + if(strcmp("br", node_name) == 0) { + CommentPiece comment_piece; + comment_piece.type = CommentPiece::Type::LINEBREAK; + callback(comment_piece); + } + } + + for(TidyNode child = tidyGetChild(node); child; child = tidyGetNext(child)) { + extract_comment_pieces(doc, child, callback); + } + } + + static void extract_comment_pieces(const char *html_source, size_t size, CommentPieceCallback callback) { + TidyDoc doc = tidyCreate(); + tidyOptSetBool(doc, TidyShowWarnings, no); + if(tidyParseString(doc, html_source) < 0) { + CommentPiece comment_piece; + comment_piece.type = CommentPiece::Type::TEXT; + comment_piece.text = { html_source, size }; + callback(comment_piece); + } else { + extract_comment_pieces(doc, tidyGetBody(doc), std::move(callback)); + } + tidyRelease(doc); + } + PluginResult Fourchan::get_content_details(const std::string &list_url, const std::string &url, BodyItems &result_items) { std::string server_response; if(download_to_string(fourchan_url + list_url + "/thread/" + url + ".json", server_response) != DownloadResult::OK) @@ -155,14 +520,35 @@ namespace QuickMedia { continue; const Json::Value &com = post["com"]; - if(!com.isString()) + const char *comment_begin; + const char *comment_end; + if(!com.getString(&comment_begin, &comment_end)) continue; const Json::Value &post_num = post["no"]; if(!post_num.isNumeric()) continue; - auto body_item = std::make_unique(com.asString()); + std::string comment_text; + extract_comment_pieces(comment_begin, comment_end - comment_begin, [&comment_text](const CommentPiece &cp) { + switch(cp.type) { + case CommentPiece::Type::TEXT: + comment_text += cp.text; + break; + case CommentPiece::Type::QUOTE: + comment_text += '>'; + comment_text += cp.text; + break; + case CommentPiece::Type::QUOTELINK: + comment_text += cp.text; + break; + case CommentPiece::Type::LINEBREAK: + // comment_text += '\n'; + break; + } + }); + html_unescape_sequences(comment_text); + auto body_item = std::make_unique(std::move(comment_text)); body_item->url = std::to_string(post_num.asInt64()); const Json::Value &ext = post["ext"]; -- cgit v1.2.3