aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Notification.cpp4
-rw-r--r--src/QuickMedia.cpp1
-rw-r--r--src/plugins/MyAnimeList.cpp310
-rw-r--r--src/plugins/NyaaSi.cpp9
4 files changed, 9 insertions, 315 deletions
diff --git a/src/Notification.cpp b/src/Notification.cpp
index 791f4b2..848c74d 100644
--- a/src/Notification.cpp
+++ b/src/Notification.cpp
@@ -19,7 +19,7 @@ namespace QuickMedia {
void show_notification(const std::string &title, const std::string &description, Urgency urgency) {
fprintf(stderr, "Notification: title: %s, description: %s\n", title.c_str(), description.c_str());
- const char *args[] = { "notify-send", "-t", "10000", "-u", urgency_string(urgency), "--", title.c_str(), description.c_str(), nullptr };
+ const char *args[] = { "notify-send", "-a", "QuickMedia", "-t", "10000", "-u", urgency_string(urgency), "--", title.c_str(), description.c_str(), nullptr };
exec_program_async(args, nullptr);
}
-} \ No newline at end of file
+}
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 23cd17b..fb97ca6 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -19,7 +19,6 @@
#include "../plugins/Saucenao.hpp"
#include "../plugins/Info.hpp"
#include "../plugins/HotExamples.hpp"
-#include "../plugins/MyAnimeList.hpp"
#include "../plugins/AniList.hpp"
#include "../include/Scale.hpp"
#include "../include/Program.hpp"
diff --git a/src/plugins/MyAnimeList.cpp b/src/plugins/MyAnimeList.cpp
deleted file mode 100644
index aa72750..0000000
--- a/src/plugins/MyAnimeList.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-#include "../../plugins/MyAnimeList.hpp"
-#include "../../include/Theme.hpp"
-#include "../../include/NetUtils.hpp"
-#include "../../include/StringUtils.hpp"
-#include <quickmedia/HtmlSearch.h>
-#include <json/value.h>
-
-namespace QuickMedia {
- // Returns {0, 0} if unknown
- static mgl::vec2i thumbnail_url_get_resolution(const std::string &url) {
- const size_t index = url.find("/r/");
- if(index == std::string::npos)
- return {0, 0};
-
- const size_t width_index = index + 3;
- const size_t x_index = url.find('x', width_index);
- if(x_index == std::string::npos)
- return {0, 0};
-
- const size_t height_index = x_index + 1;
- const size_t size_end_index = url.find('/', height_index);
- if(size_end_index == std::string::npos)
- return {0, 0};
-
- mgl::vec2i size;
- if(!to_num(url.c_str() + width_index, (x_index - width_index), size.x) || !to_num(url.c_str() + height_index, (size_end_index - height_index), size.y))
- return {0, 0};
-
- return size;
- }
-
- static std::shared_ptr<BodyItem> search_item_to_body_item(const Json::Value &search_item_json) {
- if(!search_item_json.isObject())
- return nullptr;
-
- const Json::Value &name_json = search_item_json["name"];
- const Json::Value &url_json = search_item_json["url"];
- const Json::Value &payload_json = search_item_json["payload"];
- if(!name_json.isString() || !url_json.isString() || !payload_json.isObject())
- return nullptr;
-
- std::string name = name_json.asString();
- const Json::Value &media_type_json = payload_json["media_type"];
- if(media_type_json.isString())
- name += " (" + media_type_json.asString() + ")";
-
- auto body_item = BodyItem::create("");
- body_item->url = url_json.asString();
- body_item->set_author(std::move(name));
-
- const Json::Value &image_url_json = search_item_json["thumbnail_url"];
- body_item->thumbnail_size = {116, 76};
- if(image_url_json.isString()) {
- body_item->thumbnail_url = image_url_json.asString();
- body_item->thumbnail_size = thumbnail_url_get_resolution(body_item->thumbnail_url);
- }
-
- std::string description;
- const Json::Value &aired_json = payload_json["aired"];
- if(aired_json.isString()) {
- if(!description.empty())
- description += '\n';
- description += "Aired: " + aired_json.asString();
- }
-
- const Json::Value &published_json = payload_json["published"];
- if(published_json.isString()) {
- if(!description.empty())
- description += '\n';
- description += "Published: " + published_json.asString();
- }
-
- const Json::Value &score_json = payload_json["score"];
- if(score_json.isString()) {
- if(!description.empty())
- description += '\n';
- description += "Score: " + score_json.asString();
- }
-
- const Json::Value &status_json = payload_json["status"];
- if(status_json.isString()) {
- if(!description.empty())
- description += '\n';
- description += "Status: " + status_json.asString();
- }
-
- if(!description.empty()) {
- body_item->set_description(std::move(description));
- body_item->set_description_color(get_theme().faded_text_color);
- }
-
- return body_item;
- }
-
- SearchResult MyAnimeListSearchPage::search(const std::string &str, BodyItems &result_items) {
- std::string url = "https://myanimelist.net/search/prefix.json?type=all&keyword=";
- url += url_param_encode(str) + "&v=1";
-
- Json::Value json_root;
- DownloadResult download_result = download_json(json_root, url, {}, true);
- if(download_result != DownloadResult::OK) return download_result_to_search_result(download_result);
-
- if(!json_root.isObject())
- return SearchResult::ERR;
-
- const Json::Value &categories_json = json_root["categories"];
- if(!categories_json.isArray())
- return SearchResult::ERR;
-
- BodyItems anime_items;
- BodyItems manga_items;
- for(const Json::Value &category_json : categories_json) {
- if(!category_json.isObject())
- continue;
-
- const Json::Value &type_json = category_json["type"];
- const Json::Value &items_json = category_json["items"];
- if(!type_json.isString() || !items_json.isArray())
- continue;
-
- if(strcmp(type_json.asCString(), "anime") == 0) {
- for(const Json::Value &item_json : items_json) {
- auto body_item = search_item_to_body_item(item_json);
- if(body_item)
- anime_items.push_back(std::move(body_item));
- }
- } else if(strcmp(type_json.asCString(), "manga") == 0) {
- for(const Json::Value &item_json : items_json) {
- auto body_item = search_item_to_body_item(item_json);
- if(body_item)
- manga_items.push_back(std::move(body_item));
- }
- }
- }
-
- if(!anime_items.empty()) {
- auto anime_title_item = BodyItem::create("", false);
- anime_title_item->set_author("Anime");
- result_items.push_back(std::move(anime_title_item));
- result_items.insert(result_items.end(), std::move_iterator(anime_items.begin()), std::move_iterator(anime_items.end()));
- }
-
- if(!manga_items.empty()) {
- auto manga_title_item = BodyItem::create("", false);
- manga_title_item->set_author("Manga");
- result_items.push_back(std::move(manga_title_item));
- result_items.insert(result_items.end(), std::move_iterator(manga_items.begin()), std::move_iterator(manga_items.end()));
- }
-
- return SearchResult::OK;
- }
-
- PluginResult MyAnimeListSearchPage::submit(const SubmitArgs &args, std::vector<Tab> &result_tabs) {
- if(args.url.empty())
- return PluginResult::OK;
-
- result_tabs.push_back({ create_body(), std::make_unique<MyAnimeListDetailsPage>(program, args.url), nullptr });
- result_tabs.push_back({ create_body(false, true), std::make_unique<MyAnimeListRecommendationsPage>(program, args.url), nullptr });
- return PluginResult::OK;
- }
-
- PluginResult MyAnimeListDetailsPage::submit(const SubmitArgs &args, std::vector<Tab> &result_tabs) {
- return PluginResult::OK;
- }
-
- PluginResult MyAnimeListDetailsPage::lazy_fetch(BodyItems &result_items) {
- std::string website_data;
- DownloadResult download_result = download_to_string(url, website_data, {}, true);
- if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
-
- std::string thumbnail_url;
- std::string description;
-
- QuickMediaHtmlSearch html_search;
- int result = quickmedia_html_search_init(&html_search, website_data.c_str(), website_data.size());
- if(result != 0)
- return PluginResult::ERR;
-
- quickmedia_html_find_nodes_xpath(&html_search, "//img[itemprop='image']",
- [](QuickMediaMatchNode *node, void *userdata) {
- std::string *thumbnail_url = (std::string*)userdata;
- QuickMediaStringView data_src = quickmedia_html_node_get_attribute_value(node->node, "data-src");
- if(data_src.data) {
- thumbnail_url->assign(data_src.data, data_src.size);
- html_unescape_sequences(*thumbnail_url);
- }
- return 1;
- }, &thumbnail_url);
-
- quickmedia_html_find_nodes_xpath(&html_search, "//p[itemprop='description']",
- [](QuickMediaMatchNode *node, void *userdata) {
- std::string *description = (std::string*)userdata;
- QuickMediaStringView text = quickmedia_html_node_get_text(node);
- if(text.data) {
- *description = "Synopsis:\n";
- description->append(text.data, text.size);
- html_unescape_sequences(*description);
- }
- return 1;
- }, &description);
-
- quickmedia_html_search_deinit(&html_search);
-
- auto synopsis_body_item = BodyItem::create("");
- synopsis_body_item->set_description(std::move(description));
- synopsis_body_item->thumbnail_url = std::move(thumbnail_url);
- synopsis_body_item->thumbnail_size = {225, 337};
- result_items.push_back(std::move(synopsis_body_item));
-
- return PluginResult::OK;
- }
-
- PluginResult MyAnimeListRecommendationsPage::submit(const SubmitArgs &args, std::vector<Tab> &result_tabs) {
- result_tabs.push_back({ create_body(), std::make_unique<MyAnimeListDetailsPage>(program, args.url), nullptr });
- result_tabs.push_back({ create_body(false, true), std::make_unique<MyAnimeListRecommendationsPage>(program, args.url), nullptr });
- return PluginResult::OK;
- }
-
- static std::string img_alt_get_title(const std::string &alt) {
- size_t index = alt.find(':');
- if(index == std::string::npos)
- return alt;
- return alt.substr(index + 2);
- }
-
- PluginResult MyAnimeListRecommendationsPage::lazy_fetch(BodyItems &result_items) {
- std::string website_data;
- DownloadResult download_result = download_to_string(url + "/userrecs", website_data, {}, true);
- if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
-
- QuickMediaHtmlSearch html_search;
- int result = quickmedia_html_search_init(&html_search, website_data.c_str(), website_data.size());
- if(result != 0)
- return PluginResult::ERR;
-
- quickmedia_html_find_nodes_xpath(&html_search, "//div[class='picSurround']/a",
- [](QuickMediaMatchNode *node, void *userdata) {
- BodyItems *result_items = (BodyItems*)userdata;
- QuickMediaStringView href = quickmedia_html_node_get_attribute_value(node->node, "href");
- if(!href.data)
- return 0;
-
- auto body_item = BodyItem::create("");
- body_item->url.assign(href.data, href.size);
- html_unescape_sequences(body_item->url);
- result_items->push_back(body_item);
- if(!node->node->first_child || !node->node->first_child->node.name.data || node->node->first_child->node.name.size != 3 || memcmp(node->node->first_child->node.name.data, "img", 3) != 0)
- return 0;
-
- QuickMediaStringView data_src = quickmedia_html_node_get_attribute_value(&node->node->first_child->node, "data-src");
- QuickMediaStringView alt = quickmedia_html_node_get_attribute_value(&node->node->first_child->node, "alt");
- if(data_src.data && alt.data) {
- std::string title = img_alt_get_title(std::string(alt.data, alt.size));
- html_unescape_sequences(title);
- body_item->set_author(std::move(title));
-
- body_item->thumbnail_url.assign(data_src.data, data_src.size);
- html_unescape_sequences(body_item->thumbnail_url);
-
- if(body_item->thumbnail_url.empty())
- body_item->thumbnail_size = {50, 70};
- else
- body_item->thumbnail_size = thumbnail_url_get_resolution(body_item->thumbnail_url);
- }
- return 0;
- }, &result_items);
-
- BodyItemContext body_item_image_context;
- body_item_image_context.body_items = &result_items;
- body_item_image_context.index = 0;
-
- // TODO: Fix, incorrect descriptions!
- #if 0
- quickmedia_html_find_nodes_xpath(&html_search, "//div[class='*detail-user-recs-text']",
- [](QuickMediaMatchNode *node, void *userdata) {
- BodyItemContext *item_data = (BodyItemContext*)userdata;
- QuickMediaStringView text = quickmedia_html_node_get_text(node);
- if(text.data && item_data->index < item_data->body_items->size()) {
- std::string description(text.data, text.size);
- html_unescape_sequences(description);
- (*item_data->body_items)[item_data->index]->set_description(std::move(description));
- (*item_data->body_items)[item_data->index]->set_description_color(get_theme().faded_text_color);
- item_data->index++;
- }
- return 0;
- }, &body_item_image_context);
- #endif
-
- /*
- quickmedia_html_find_nodes_xpath(&html_search, "//div[class='borderClass']//div[class='*detail-user-recs-text']",
- [](QuickMediaMatchNode *node, void *userdata) {
- BodyItems *result_items = (BodyItems*)userdata;
- QuickMediaStringView text = quickmedia_html_node_get_text(node);
- if(text.data) {
- std::string description(text.data, text.size);
- html_unescape_sequences(description);
-
- auto body_item = BodyItem::create("");
- body_item->set_description(std::move(description));
- body_item->set_description_color(get_theme().faded_text_color);
- result_items->push_back(std::move(body_item));
- }
- return 0;
- }, &result_items);
- */
-
- quickmedia_html_search_deinit(&html_search);
- return PluginResult::OK;
- }
-} \ No newline at end of file
diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp
index b56ef69..705d961 100644
--- a/src/plugins/NyaaSi.cpp
+++ b/src/plugins/NyaaSi.cpp
@@ -268,16 +268,21 @@ namespace QuickMedia {
index = tr_end + 5;
- std::string description = "Size: " + size + " | Published: " + unix_time_to_local_time_str(nyaa_si_time_to_unix_time(timestamp.c_str())) + " | Seeders: " + seeders + " | Leechers: " + leechers + " | Completed: " + completed;
auto body_item = BodyItem::create(std::move(title));
body_item->thumbnail_url = "https://" + domain + "/static/img/icons/" + (is_sukebei ? "sukebei" : "nyaa") + "/" + website_data.substr(category_begin + 4, category_end - (category_begin + 4)) + ".png";
- body_item->set_description(std::move(description));
body_item->url = "https://" + domain + std::move(view_url);
if(is_trusted)
body_item->set_title_color(mgl::Color(43, 255, 47));
else if(is_remake)
body_item->set_title_color(mgl::Color(255, 45, 47));
body_item->thumbnail_size = mgl::vec2i(80, 28);
+
+ body_item->add_reaction("Size: " + size, nullptr);
+ body_item->add_reaction("Published: " + unix_time_to_local_time_str(nyaa_si_time_to_unix_time(timestamp.c_str())), nullptr);
+ body_item->add_reaction("Seeders: " + seeders, nullptr);
+ body_item->add_reaction("Leechers: " + leechers, nullptr);
+ body_item->add_reaction("Completed: " + completed, nullptr);
+
result_items.push_back(std::move(body_item));
}