aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-13 23:30:20 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-13 23:30:20 +0200
commitacb6ac0a04e800a79876908fd1fdb98dc7e93678 (patch)
treee8d0e97b3ac22d8ee1fc5b5a515047bf4a173014 /src
parent4af866c610a8f6650a5d2c5045c085d9af7d7951 (diff)
Show local time for nyaa.si, soundcloud and spotify. Add sukebei
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp11
-rw-r--r--src/Utils.cpp21
-rw-r--r--src/plugins/NyaaSi.cpp138
-rw-r--r--src/plugins/Soundcloud.cpp20
-rw-r--r--src/plugins/Spotify.cpp11
-rw-r--r--src/plugins/Youtube.cpp22
6 files changed, 156 insertions, 67 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index c81e0c5..a58b3d8 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -1076,10 +1076,13 @@ namespace QuickMedia {
tabs.push_back(Tab{create_body(), std::make_unique<MangaCombinedSearchPage>(this, std::move(pages)), create_search_bar("Search...", 400)});
} else if(strcmp(plugin_name, "nyaa.si") == 0) {
- auto category_page = std::make_unique<NyaaSiCategoryPage>(this);
- auto categories_body = create_body();
- category_page->get_categories(categories_body->items);
- tabs.push_back(Tab{std::move(categories_body), std::move(category_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ auto categories_nyaa_si_body = create_body();
+ get_nyaa_si_categories(categories_nyaa_si_body->items);
+ tabs.push_back(Tab{std::move(categories_nyaa_si_body), std::make_unique<NyaaSiCategoryPage>(this, false), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ auto categories_sukebei_body = create_body();
+ get_sukebei_categories(categories_sukebei_body->items);
+ tabs.push_back(Tab{std::move(categories_sukebei_body), std::make_unique<NyaaSiCategoryPage>(this, true), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "4chan") == 0) {
auto boards_page = std::make_unique<FourchanBoardsPage>(this, resources_root);
auto boards_body = create_body();
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 2a36d27..7ed6574 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -85,4 +85,25 @@ namespace QuickMedia {
qm_enable_touch_set = true;
return qm_enable_touch;
}
+
+ time_t iso_utc_to_unix_time(const char *time_str) {
+ int year = 0;
+ int month = 0;
+ int day = 0;
+ int hour = 0;
+ int minute = 0;
+ int second = 0;
+ sscanf(time_str, "%d-%d-%dT%d:%d:%d", &year, &month, &day, &hour, &minute, &second);
+ if(year == 0) return 0;
+
+ struct tm time;
+ memset(&time, 0, sizeof(time));
+ time.tm_year = year - 1900;
+ time.tm_mon = month - 1;
+ time.tm_mday = day;
+ time.tm_hour = hour;
+ time.tm_min = minute;
+ time.tm_sec = second;
+ return timegm(&time);
+ }
} \ No newline at end of file
diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp
index 7a84346..2afedb3 100644
--- a/src/plugins/NyaaSi.cpp
+++ b/src/plugins/NyaaSi.cpp
@@ -39,16 +39,86 @@ namespace QuickMedia {
return body_item;
}
+ void get_nyaa_si_categories(BodyItems &result_items) {
+ result_items.push_back(create_front_page_item("All categories", "0_0"));
+ result_items.push_back(create_front_page_item("Anime", "1_0"));
+ result_items.push_back(create_front_page_item(" Anime - Music video", "1_1"));
+ result_items.push_back(create_front_page_item(" Anime - English translated", "1_2"));
+ result_items.push_back(create_front_page_item(" Anime - Non-english translated", "1_3"));
+ result_items.push_back(create_front_page_item(" Anime - Raw", "1_4"));
+ result_items.push_back(create_front_page_item("Audio", "2_0"));
+ result_items.push_back(create_front_page_item(" Audio - Lossless", "2_1"));
+ result_items.push_back(create_front_page_item(" Anime - Lossy", "2_2"));
+ result_items.push_back(create_front_page_item("Literature", "3_0"));
+ result_items.push_back(create_front_page_item(" Literature - English translated", "3_1"));
+ result_items.push_back(create_front_page_item(" Literature - Non-english translated", "3_1"));
+ result_items.push_back(create_front_page_item(" Literature - Raw", "3_3"));
+ result_items.push_back(create_front_page_item("Live Action", "4_0"));
+ result_items.push_back(create_front_page_item(" Live Action - English translated", "4_1"));
+ result_items.push_back(create_front_page_item(" Live Action - Non-english translated", "4_3"));
+ result_items.push_back(create_front_page_item(" Live Action - Idol/Promotional video", "4_2"));
+ result_items.push_back(create_front_page_item(" Live Action - Raw", "4_4"));
+ result_items.push_back(create_front_page_item("Pictures", "5_0"));
+ result_items.push_back(create_front_page_item(" Pictures - Graphics", "5_1"));
+ result_items.push_back(create_front_page_item(" Pictures - Photos", "5_2"));
+ result_items.push_back(create_front_page_item("Software", "6_0"));
+ result_items.push_back(create_front_page_item(" Software - Applications", "6_1"));
+ result_items.push_back(create_front_page_item(" Software - Games", "6_2"));
+ }
+
+ void get_sukebei_categories(BodyItems &result_items) {
+ result_items.push_back(create_front_page_item("All categories", "0_0"));
+ result_items.push_back(create_front_page_item("Art", "1_0"));
+ result_items.push_back(create_front_page_item(" Anime", "1_1"));
+ result_items.push_back(create_front_page_item(" Doujinshi", "1_2"));
+ result_items.push_back(create_front_page_item(" Games", "1_3"));
+ result_items.push_back(create_front_page_item(" Manga", "1_4"));
+ result_items.push_back(create_front_page_item(" Pictures", "1_5"));
+ result_items.push_back(create_front_page_item("Real Life", "2_0"));
+ result_items.push_back(create_front_page_item(" Photobooks and Pictures", "2_1"));
+ result_items.push_back(create_front_page_item(" Videos", "2_2"));
+ }
+
+ static time_t nyaa_si_time_to_unix_time(const char *time_str) {
+ int year = 0;
+ int month = 0;
+ int day = 0;
+ int hour = 0;
+ int minute = 0;
+ sscanf(time_str, "%d-%d-%d %d:%d", &year, &month, &day, &hour, &minute);
+ if(year == 0) return 0;
+
+ struct tm time;
+ memset(&time, 0, sizeof(time));
+ time.tm_year = year - 1900;
+ time.tm_mon = month - 1;
+ time.tm_mday = day;
+ time.tm_hour = hour;
+ time.tm_min = minute;
+ time.tm_sec = 0;
+ return timegm(&time);
+ }
+
+ static std::string unix_time_to_local_time_str(time_t unix_time) {
+ struct tm time_tm;
+ localtime_r(&unix_time, &time_tm);
+ char time_str[128] = {0};
+ strftime(time_str, sizeof(time_str) - 1, "%Y-%m-%d %H:%M", &time_tm);
+ return time_str;
+ }
+
// TODO: Also show the number of comments for each torrent. TODO: Optimize?
// TODO: Show each field as seperate columns instead of seperating by |
- static SearchResult search_page(const std::string &list_url, const std::string &text, int page, BodyItems &result_items) {
- std::string full_url = "https://nyaa.si/?c=" + list_url + "&f=0&p=" + std::to_string(page) + "&q=";
+ static SearchResult search_page(const std::string &domain, const std::string &list_url, const std::string &text, int page, BodyItems &result_items) {
+ std::string full_url = "https://" + domain + "/?c=" + list_url + "&f=0&p=" + std::to_string(page) + "&q=";
full_url += url_param_encode(text);
std::string website_data;
if(download_to_string(full_url, website_data, {}, true) != DownloadResult::OK)
return SearchResult::NET_ERR;
+ const bool is_sukebei = (domain == "sukebei.nyaa.si");
+
size_t tbody_begin = website_data.find("<tbody>");
if(tbody_begin == std::string::npos)
return SearchResult::OK;
@@ -161,11 +231,11 @@ namespace QuickMedia {
index = tr_end + 5;
- std::string description = "Size: " + size + " | Published: " + timestamp + " | Seeders: " + seeders + " | Leechers: " + leechers + " | Completed: " + completed;
+ 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://nyaa.si/static/img/icons/nyaa/" + website_data.substr(category_begin + 4, category_end - (category_begin + 4)) + ".png";
+ 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://nyaa.si" + std::move(view_url);
+ body_item->url = "https://" + domain + std::move(view_url);
if(is_trusted)
body_item->set_title_color(sf::Color(43, 255, 47));
else if(is_remake)
@@ -178,51 +248,31 @@ namespace QuickMedia {
}
PluginResult NyaaSiCategoryPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
+ std::string domain = is_sukebei ? "sukebei.nyaa.si" : "nyaa.si";
+
BodyItems result_items;
- SearchResult search_result = search_page(url, "", 1, result_items);
+ SearchResult search_result = search_page(domain, url, "", 1, result_items);
if(search_result != SearchResult::OK) return search_result_to_plugin_result(search_result);
auto body = create_body();
body->items = std::move(result_items);
- result_tabs.push_back(Tab{std::move(body), std::make_unique<NyaaSiSearchPage>(program, strip(title), url), create_search_bar("Search...", 300)});
+ result_tabs.push_back(Tab{std::move(body), std::make_unique<NyaaSiSearchPage>(program, strip(title), url, std::move(domain)), create_search_bar("Search...", 300)});
return PluginResult::OK;
}
- void NyaaSiCategoryPage::get_categories(BodyItems &result_items) {
- result_items.push_back(create_front_page_item("All categories", "0_0"));
- result_items.push_back(create_front_page_item("Anime", "1_0"));
- result_items.push_back(create_front_page_item(" Anime - Music video", "1_1"));
- result_items.push_back(create_front_page_item(" Anime - English translated", "1_2"));
- result_items.push_back(create_front_page_item(" Anime - Non-english translated", "1_3"));
- result_items.push_back(create_front_page_item(" Anime - Raw", "1_4"));
- result_items.push_back(create_front_page_item("Audio", "2_0"));
- result_items.push_back(create_front_page_item(" Audio - Lossless", "2_1"));
- result_items.push_back(create_front_page_item(" Anime - Lossy", "2_2"));
- result_items.push_back(create_front_page_item("Literature", "3_0"));
- result_items.push_back(create_front_page_item(" Literature - English translated", "3_1"));
- result_items.push_back(create_front_page_item(" Literature - Non-english translated", "3_1"));
- result_items.push_back(create_front_page_item(" Literature - Raw", "3_3"));
- result_items.push_back(create_front_page_item("Live Action", "4_0"));
- result_items.push_back(create_front_page_item(" Live Action - English translated", "4_1"));
- result_items.push_back(create_front_page_item(" Live Action - Non-english translated", "4_3"));
- result_items.push_back(create_front_page_item(" Live Action - Idol/Promotional video", "4_2"));
- result_items.push_back(create_front_page_item(" Live Action - Raw", "4_4"));
- result_items.push_back(create_front_page_item("Pictures", "5_0"));
- result_items.push_back(create_front_page_item(" Pictures - Graphics", "5_1"));
- result_items.push_back(create_front_page_item(" Pictures - Photos", "5_2"));
- result_items.push_back(create_front_page_item("Software", "6_0"));
- result_items.push_back(create_front_page_item(" Software - Applications", "6_1"));
- result_items.push_back(create_front_page_item(" Software - Games", "6_2"));
- }
-
SearchResult NyaaSiSearchPage::search(const std::string &str, BodyItems &result_items) {
- return search_page(category_id, str, 1, result_items);
+ return search_page(domain, category_id, str, 1, result_items);
}
PluginResult NyaaSiSearchPage::get_page(const std::string &str, int page, BodyItems &result_items) {
- return search_result_to_plugin_result(search_page(category_id, str, 1 + page, result_items));
+ return search_result_to_plugin_result(search_page(domain, category_id, str, 1 + page, result_items));
}
+ struct ResultItemExtra {
+ BodyItems *result_items;
+ const std::string *domain;
+ };
+
PluginResult NyaaSiSearchPage::submit(const std::string&, const std::string &url, std::vector<Tab> &result_tabs) {
size_t comments_start_index;
std::string title;
@@ -232,6 +282,10 @@ namespace QuickMedia {
std::string magnet_url;
std::string description;
+ ResultItemExtra result_item_extra;
+ result_item_extra.result_items = &result_items;
+ result_item_extra.domain = &domain;
+
std::string website_data;
if(download_to_string(url, website_data, {}, true) != DownloadResult::OK)
return PluginResult::NET_ERR;
@@ -261,16 +315,16 @@ namespace QuickMedia {
result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='panel-body']//div[class='row']//a",
[](QuickMediaHtmlNode *node, void *userdata) {
- auto *item_data = (BodyItems*)userdata;
+ ResultItemExtra *item_data = (ResultItemExtra*)userdata;
const char *href = quickmedia_html_node_get_attribute_value(node, "href");
const char *text = quickmedia_html_node_get_text(node);
- if(item_data->empty() && href && text && strncmp(href, "/user/", 6) == 0) {
+ if(item_data->result_items->empty() && href && text && strncmp(href, "/user/", 6) == 0) {
auto body_item = BodyItem::create("");
body_item->set_description("Submitter: " + strip(text));
- body_item->url = "https://nyaa.si/" + std::string(href);
- item_data->push_back(std::move(body_item));
+ body_item->url = "https://" + *item_data->domain + "/" + std::string(href);
+ item_data->result_items->push_back(std::move(body_item));
}
- }, &result_items);
+ }, &result_item_extra);
if(result != 0)
goto cleanup;
@@ -313,7 +367,7 @@ namespace QuickMedia {
goto cleanup;
if(magnet_url.empty()) {
- fprintf(stderr, "Error: nyaa.si: failed to get magnet link\n");
+ fprintf(stderr, "Error: %s: failed to get magnet link\n", domain.c_str());
result = -1;
goto cleanup;
}
diff --git a/src/plugins/Soundcloud.cpp b/src/plugins/Soundcloud.cpp
index 9a5fe64..9c2d5f4 100644
--- a/src/plugins/Soundcloud.cpp
+++ b/src/plugins/Soundcloud.cpp
@@ -1,6 +1,7 @@
#include "../../plugins/Soundcloud.hpp"
#include "../../include/NetUtils.hpp"
#include "../../include/StringUtils.hpp"
+#include "../../include/Utils.hpp"
#include "../../include/Scale.hpp"
#include <quickmedia/HtmlSearch.h>
@@ -64,6 +65,14 @@ namespace QuickMedia {
return "";
}
+ static std::string unix_time_to_local_time_str(time_t unix_time) {
+ struct tm time_tm;
+ localtime_r(&unix_time, &time_tm);
+ char time_str[128] = {0};
+ strftime(time_str, sizeof(time_str) - 1, "%Y-%m-%d %H:%M", &time_tm);
+ return time_str;
+ }
+
static std::shared_ptr<BodyItem> parse_collection_item(const Json::Value &item_json) {
std::string title;
@@ -105,6 +114,12 @@ namespace QuickMedia {
auto body_item = BodyItem::create(std::move(title));
std::string description;
+ const Json::Value &last_modified_json = item_json["last_modified"];
+ if(last_modified_json.isString()) {
+ const time_t unix_time = iso_utc_to_unix_time(last_modified_json.asCString());
+ description = "Updated " + unix_time_to_local_time_str(unix_time);
+ }
+
const Json::Value &media_json = item_json["media"];
if(media_json.isObject())
body_item->url = get_best_transcoding_audio_url(media_json);
@@ -129,6 +144,8 @@ namespace QuickMedia {
}
num_tracks = tracks_json.size();
+ if(!description.empty())
+ description += '\n';
description = "Playlist with " + std::to_string(num_tracks) + " track" + (num_tracks == 1 ? "" : "s");
body_item->extra = std::move(playlist);
body_item->url = "track";
@@ -167,6 +184,9 @@ namespace QuickMedia {
body_item->thumbnail_size.x = 100;
body_item->thumbnail_size.y = 100;
body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE;
+ } else {
+ body_item->thumbnail_size.x = 100;
+ body_item->thumbnail_size.y = 100;
}
if(username_json.isString()) {
diff --git a/src/plugins/Spotify.cpp b/src/plugins/Spotify.cpp
index f56ed6c..d41446b 100644
--- a/src/plugins/Spotify.cpp
+++ b/src/plugins/Spotify.cpp
@@ -1,5 +1,6 @@
#include "../../plugins/Spotify.hpp"
#include "../../include/NetUtils.hpp"
+#include "../../include/Utils.hpp"
#include "../../include/Scale.hpp"
namespace QuickMedia {
@@ -171,6 +172,14 @@ namespace QuickMedia {
return result;
}
+ static std::string unix_time_to_local_time_str(time_t unix_time) {
+ struct tm time_tm;
+ localtime_r(&unix_time, &time_tm);
+ char time_str[128] = {0};
+ strftime(time_str, sizeof(time_str) - 1, "%Y-%m-%d %H:%M", &time_tm);
+ return time_str;
+ }
+
PluginResult SpotifyEpisodeListPage::get_page(const std::string &, int page, BodyItems &result_items) {
std::string request_url = "https://api-partner.spotify.com/pathfinder/v1/query?operationName=queryShowEpisodes&variables=";
request_url += url_param_encode("{\"uri\":\"" + url + "\",\"offset\":" + std::to_string(page * 50) + ",\"limit\":50}");
@@ -242,7 +251,7 @@ namespace QuickMedia {
if(release_data_json.isObject()) {
const Json::Value &iso_string_json = release_data_json["isoString"];
if(iso_string_json.isString())
- time += iso_string_json.asString();
+ time += unix_time_to_local_time_str(iso_utc_to_unix_time(iso_string_json.asCString()));
}
const Json::Value &duration_json = episode_json["duration"];
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index 0fcf61d..a93dcb6 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -4,6 +4,7 @@
#include "../../include/StringUtils.hpp"
#include "../../include/Scale.hpp"
#include "../../include/Notification.hpp"
+#include "../../include/Utils.hpp"
extern "C" {
#include <HtmlParser.h>
}
@@ -1375,26 +1376,7 @@ namespace QuickMedia {
subscription_data.subscription_entry.back().video_id.assign(html_parser->text_stripped.data, html_parser->text_stripped.size);
} else if(string_view_equals(&html_parser->tag_name, "published") && parse_type == HTML_PARSE_TAG_END) {
std::string published_str(html_parser->text_stripped.data, html_parser->text_stripped.size);
-
- int year = 0;
- int month = 0;
- int day = 0;
- int hour = 0;
- int minute = 0;
- int second = 0;
- sscanf(published_str.c_str(), "%d-%d-%dT%d:%d:%d", &year, &month, &day, &hour, &minute, &second);
- if(year == 0) return;
-
- struct tm time;
- memset(&time, 0, sizeof(time));
- time.tm_year = year - 1900;
- time.tm_mon = month - 1;
- time.tm_mday = day;
- time.tm_hour = hour;
- time.tm_min = minute;
- time.tm_sec = second;
-
- subscription_data.subscription_entry.back().published = timegm(&time);
+ subscription_data.subscription_entry.back().published = iso_utc_to_unix_time(published_str.c_str());
}
}, &subscription_data);