diff options
author | dec05eba <dec05eba@protonmail.com> | 2021-09-18 18:07:10 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2021-09-18 18:07:16 +0200 |
commit | d74766245facd48805c2576c711d20cafa33aa35 (patch) | |
tree | 0be58368480ada332d62af14ef1a300170149871 /src/plugins/Saucenao.cpp | |
parent | 63774155016ad581dcf418c94cd2ec84fcf86445 (diff) |
Show option to open saucenao result urls
ctrl+c for info should only copy the url
Diffstat (limited to 'src/plugins/Saucenao.cpp')
-rw-r--r-- | src/plugins/Saucenao.cpp | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/plugins/Saucenao.cpp b/src/plugins/Saucenao.cpp index d81e233..ccb01f9 100644 --- a/src/plugins/Saucenao.cpp +++ b/src/plugins/Saucenao.cpp @@ -1,8 +1,78 @@ #include "../../plugins/Saucenao.hpp" +#include "../../plugins/Info.hpp" #include "../../include/StringUtils.hpp" #include <quickmedia/HtmlSearch.h> namespace QuickMedia { + class SaucenaoBodyItemUrls : public BodyItemExtra { + public: + std::vector<std::string> urls; + }; + + static int string_views_equal_case_insensitive(const QuickMediaStringView str1, const QuickMediaStringView str2) { + if(str2.size != str1.size) + return 1; + + for(size_t i = 0; i < str1.size; ++i) { + char c1 = str1.data[i]; + char c2 = str2.data[i]; + if(to_upper(c1) != to_upper(c2)) + return 1; + } + + return 0; + } + + static QuickMediaHtmlAttribute* get_attribute_by_name(QuickMediaHtmlNode *node, QuickMediaStringView name) { + for(QuickMediaHtmlAttribute *attr = node->first_attribute; attr; attr = attr->next) { + if(string_views_equal_case_insensitive(attr->key, name) == 0) + return attr; + } + return NULL; + } + + static void match_node_get_urls(QuickMediaHtmlNode *node, std::vector<std::string> &urls) { + if(node->is_tag && string_views_equal_case_insensitive(node->name, {"a", 1}) == 0) { + QuickMediaHtmlAttribute *attr = get_attribute_by_name(node, {"href", 4}); + if(attr) + urls.emplace_back(attr->value.data, attr->value.size); + } + + QuickMediaHtmlChildNode *child_node = node->first_child; + while(child_node) { + match_node_get_urls(&child_node->node, urls); + child_node = child_node->next; + } + } + + static std::string get_first_line(const std::string &str) { + const size_t line_end = str.find('\n'); + if(line_end == std::string::npos) + return str; + else + return str.substr(0, line_end); + } + + PluginResult SaucenaoPage::submit(const std::string &title, const std::string&, std::vector<Tab> &result_tabs) { + if(!submit_body_item) + return PluginResult::OK; + + SaucenaoBodyItemUrls *urls = static_cast<SaucenaoBodyItemUrls*>(submit_body_item->extra.get()); + BodyItems body_items; + + for(const std::string &url : urls->urls) { + // Ignore saucenao info pages + if(url.find("saucenao.com") == std::string::npos) + body_items.push_back(InfoPage::add_url(url)); + } + body_items.push_back(InfoPage::add_google_search(get_first_line(title))); + + auto body = create_body(); + body->set_items(std::move(body_items)); + result_tabs.push_back(Tab{ std::move(body), std::make_unique<InfoPage>(program), create_search_bar("Search...", SEARCH_DELAY_FILTER) }); + return PluginResult::OK; + } + PluginResult SaucenaoPage::lazy_fetch(BodyItems &result_items) { std::vector<CommandArg> additional_args; if(is_local) { @@ -31,6 +101,9 @@ namespace QuickMedia { title = title.erase(0, p_index + 1); title = strip(title); auto item = BodyItem::create(title); + auto urls = std::make_shared<SaucenaoBodyItemUrls>(); + match_node_get_urls(node->node, urls->urls); + item->extra = std::move(urls); item_data->push_back(std::move(item)); } return 0; |