aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp9
-rw-r--r--src/plugins/NyaaSi.cpp83
-rw-r--r--src/plugins/utils/EpisodeNameParser.cpp19
3 files changed, 103 insertions, 8 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index c2b2b95..447b863 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -699,6 +699,10 @@ namespace QuickMedia {
XSetErrorHandler(x_error_handler);
XSetIOErrorHandler(x_io_error_handler);
+ // Initialize config and theme early to prevent possible race condition on initialize
+ get_config();
+ get_theme();
+
mgl::vec2i monitor_size;
mgl::vec2i focused_monitor_center = get_focused_monitor_center(disp, monitor_size);
@@ -719,6 +723,7 @@ namespace QuickMedia {
}
window_create_params.hidden = no_dialog;
window_create_params.parent_window = parent_window;
+ window_create_params.background_color = get_theme().background_color;
if(!window.create("QuickMedia", std::move(window_create_params))) {
show_notification("QuickMedia", "Failed to create opengl window", Urgency::CRITICAL);
abort();
@@ -732,10 +737,6 @@ namespace QuickMedia {
resources_root = program_path + "../../../";
}
- // Initialize config and theme early to prevent possible race condition on initialize
- get_config();
- get_theme();
-
set_resource_loader_root_path(resources_root.c_str());
init_body_themes();
diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp
index cd80997..739032b 100644
--- a/src/plugins/NyaaSi.cpp
+++ b/src/plugins/NyaaSi.cpp
@@ -5,9 +5,80 @@
#include "../../include/StringUtils.hpp"
#include "../../include/NetUtils.hpp"
#include "../../include/Utils.hpp"
+#include "../../plugins/utils/EpisodeNameParser.hpp"
#include <quickmedia/HtmlSearch.h>
namespace QuickMedia {
+ static std::string combine_strings(const std::initializer_list<std::string_view> items, char divider) {
+ std::string result;
+ for(const auto &item : items) {
+ if(item.empty())
+ continue;
+
+ if(!result.empty())
+ result += divider;
+
+ result += item;
+ }
+ return result;
+ }
+
+ static TrackResult track(const std::string &str) {
+ std::optional<EpisodeNameParts> episode_parts = episode_name_extract_parts(str);
+ if(!episode_parts) {
+ show_notification("QuickMedia", "Failed to extract episode name from torrent name. Please add the rss manually with automedia", Urgency::CRITICAL);
+ return TrackResult::ERR;
+ }
+
+ const std::string track_name = combine_strings({ episode_parts->group, episode_parts->anime, episode_parts->episode, episode_parts->season, episode_parts->resolution }, ' ');
+
+ std::string url = "https://nyaa.si/?page=rss&q=" + url_param_encode(track_name) + "&c=0_0&f=0";
+ if(!episode_parts->group.empty())
+ url += "&u=" + url_param_decode(std::string(episode_parts->group));
+
+ std::string website_data;
+ if(download_to_string(url, website_data, {}, true) != DownloadResult::OK) {
+ show_notification("QuickMedia", "Invalid rss. Please add the rss manually with automedia", Urgency::CRITICAL);
+ return TrackResult::ERR;
+ }
+ struct HtmlFindUserdata {
+ const std::string &str;
+ bool found_title = false;
+ };
+ HtmlFindUserdata userdata{ str, false };
+
+ QuickMediaHtmlSearch html_search;
+ int result = quickmedia_html_search_init(&html_search, website_data.c_str(), website_data.size());
+ if(result != 0)
+ goto cleanup;
+
+ result = quickmedia_html_find_nodes_xpath(&html_search, "//channel/item/title",
+ [](QuickMediaMatchNode *node, void *userdata) {
+ HtmlFindUserdata &userdata_typed = *(HtmlFindUserdata*)userdata;
+ QuickMediaStringView text = quickmedia_html_node_get_text(node);
+ if(text.data && text.size == userdata_typed.str.size() && memcmp(text.data, userdata_typed.str.data(), text.size) == 0) {
+ userdata_typed.found_title = true;
+ }
+ return 0;
+ }, &userdata);
+
+ cleanup:
+ quickmedia_html_search_deinit(&html_search);
+ if(result != 0 || !userdata.found_title) {
+ show_notification("QuickMedia", "The item you tried to track was not found in the rss feed. Please add the rss manually with automedia", Urgency::CRITICAL);
+ return TrackResult::ERR;
+ }
+
+ const char *args[] = { "automedia", "add", "rss", url.c_str(), "--start-after", str.c_str(), "--name", track_name.c_str(), nullptr };
+ if(exec_program(args, nullptr, nullptr) == 0) {
+ show_notification("QuickMedia", "You are now tracking \"" + track_name + "\" after \"" + str + "\"", Urgency::LOW);
+ return TrackResult::OK;
+ } else {
+ show_notification("QuickMedia", "Failed to track media \"" + track_name + "\", episode: \"" + str + "\"", Urgency::CRITICAL);
+ return TrackResult::ERR;
+ }
+ }
+
// Return end of td tag, or std::string::npos
static size_t find_td_get_value(const std::string &str, size_t start_index, size_t end_index, std::string &result) {
size_t td_begin = str.find("<td", start_index);
@@ -310,7 +381,7 @@ namespace QuickMedia {
}
NyaaSiSearchPage::NyaaSiSearchPage(Program *program, std::string category_name, std::string category_id, std::string domain) :
- Page(program), category_name(std::move(category_name)), category_id(std::move(category_id)), domain(std::move(domain))
+ Page(program), TrackablePage("", ""), category_name(std::move(category_name)), category_id(std::move(category_id)), domain(std::move(domain))
{
set_sort_type(NyaaSiSortType::UPLOAD_DATE_DESC);
}
@@ -493,10 +564,14 @@ namespace QuickMedia {
auto body = create_body();
body->set_items(std::move(result_items));
- result_tabs.push_back(Tab{std::move(body), std::make_unique<NyaaSiTorrentPage>(program), nullptr});
+ result_tabs.push_back(Tab{std::move(body), std::make_unique<NyaaSiTorrentPage>(program, args.title), nullptr});
return PluginResult::OK;
}
+ TrackResult NyaaSiSearchPage::track(const std::string &str) {
+ return QuickMedia::track(str);
+ }
+
void NyaaSiSearchPage::set_sort_type(NyaaSiSortType sort_type) {
this->sort_type = sort_type;
title = category_name + " | " + sort_type_names[(size_t)sort_type];
@@ -524,4 +599,8 @@ namespace QuickMedia {
}
return PluginResult::OK;
}
+
+ TrackResult NyaaSiTorrentPage::track(const std::string&) {
+ return QuickMedia::track(content_title);
+ }
} \ No newline at end of file
diff --git a/src/plugins/utils/EpisodeNameParser.cpp b/src/plugins/utils/EpisodeNameParser.cpp
index de2b8ac..a381cca 100644
--- a/src/plugins/utils/EpisodeNameParser.cpp
+++ b/src/plugins/utils/EpisodeNameParser.cpp
@@ -71,7 +71,7 @@ namespace QuickMedia {
return episode_name_extract_anime(episode_name);
}
- static bool is_num_real_char(char c) {
+ static bool is_real_num(char c) {
return (c >= '0' && c <= '9') || c == '.';
}
@@ -79,7 +79,7 @@ namespace QuickMedia {
episode_name = strip_left(episode_name);
size_t i = 0;
for(; i < episode_name.size(); ++i) {
- if(!is_num_real_char(episode_name[i]))
+ if(!is_real_num(episode_name[i]))
break;
}
@@ -107,6 +107,21 @@ namespace QuickMedia {
if(name_parts.episode.empty())
return std::nullopt;
+ if(episode_name.find("480p") != std::string_view::npos)
+ name_parts.resolution = "480p";
+ else if(episode_name.find("720p") != std::string_view::npos)
+ name_parts.resolution = "720p";
+ else if(episode_name.find("1080p") != std::string_view::npos)
+ name_parts.resolution = "1080p";
+ else if(episode_name.find("2160p") != std::string_view::npos)
+ name_parts.resolution = "2160p";
+ else if(episode_name.find("1280x720") != std::string_view::npos)
+ name_parts.resolution = "1280x720";
+ else if(episode_name.find("1920x1080") != std::string_view::npos)
+ name_parts.resolution = "1920x1080";
+ else if(episode_name.find("3840x2160") != std::string_view::npos)
+ name_parts.resolution = "3840x2160";
+
return name_parts;
}
} \ No newline at end of file