aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Saucenao.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-09-18 18:07:10 +0200
committerdec05eba <dec05eba@protonmail.com>2021-09-18 18:07:16 +0200
commitd74766245facd48805c2576c711d20cafa33aa35 (patch)
tree0be58368480ada332d62af14ef1a300170149871 /src/plugins/Saucenao.cpp
parent63774155016ad581dcf418c94cd2ec84fcf86445 (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.cpp73
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;