aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-11-12 23:53:29 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-12 23:53:29 +0100
commit3e55199544908a8026b4fe621b2b6af7770ce4a4 (patch)
treecdb68c3820d28ba59a9ebf3d320ee37729bb8065
parent5c27b5fbaa0f1693bf4605a3e6fc57d0f066c0ec (diff)
Add youtube description
-rw-r--r--TODO2
-rw-r--r--plugins/Youtube.hpp16
-rw-r--r--src/QuickMedia.cpp11
-rw-r--r--src/plugins/Youtube.cpp74
4 files changed, 86 insertions, 17 deletions
diff --git a/TODO b/TODO
index 4410ccc..b7b15e1 100644
--- a/TODO
+++ b/TODO
@@ -128,7 +128,6 @@ Ctrl+F to either bring up search that searches in the body (filtering, of search
Or do not have such an overlay and instead just put the autocomplete list below the search bar and close the autocomplete when pressing ESC or clicking inside the body or moving to another tab.
Automatically delete old thumbnails and media files.
Ctrl+I for youtube comments that have a timestamp should have an option to jump to the timestamp in the video. Also do the same for the youtube video description.
-Ctrl+R for youtube should have a page for the video title, description, views, upload date, likes/dislikes (and maybe a button to go to the channel instead of having a channels tab?).
Add a keybinding for going to the front page of the plugin. This would be especially useful for youtube and manga, where you have history, subscriptions and recommendations.
Reaching end of download menu filename entry should scroll the entry vertically instead of putting the text on multiple lines.
Ctrl+S saving a video should copy the video from cache if the video was downloaded to cache, instead of downloading it again.
@@ -205,3 +204,4 @@ Allow specifying start/end range for video/music downloads.
Limit text input length for 4chan posts to the server limit.
Allow creating a new thread on 4chan.
Add flag to quickmedia to use svp, by making svp use the same input ipc socket as quickmedia (and load the svp script manually).
+Support directly going to a youtube channel for a url. This is helpful for opening channel urls directly with quickmedia and also going to another channel from a youtube description. \ No newline at end of file
diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp
index 23f7e20..d3a57a6 100644
--- a/plugins/Youtube.hpp
+++ b/plugins/Youtube.hpp
@@ -23,6 +23,14 @@ namespace QuickMedia {
YoutubeFormat base;
};
+ struct YoutubeVideoDetails {
+ std::string title;
+ std::string author;
+ std::string rating;
+ std::string views;
+ std::string description;
+ };
+
// Returns |url| if the url is already a youtube url
std::string invidious_url_to_youtube_url(const std::string &url);
bool youtube_url_extract_id(const std::string &youtube_url, std::string &youtube_video_id);
@@ -52,6 +60,12 @@ namespace QuickMedia {
std::unordered_set<std::string> added_videos;
};
+ class YoutubeDescriptionPage : public Page {
+ public:
+ YoutubeDescriptionPage(Program *program) : Page(program) {}
+ const char* get_title() const override { return "Description"; }
+ };
+
class YoutubeCommentsPage : public LazyFetchPage {
public:
YoutubeCommentsPage(Program *program, const std::string &video_url, const std::string &continuation_token) : LazyFetchPage(program), video_url(video_url), continuation_token(continuation_token) {}
@@ -144,6 +158,7 @@ namespace QuickMedia {
const char* get_title() const override { return ""; }
BodyItems get_related_media(const std::string &url) override;
PluginResult get_related_pages(const BodyItems &related_videos, const std::string &channel_url, std::vector<Tab> &result_tabs) override;
+ int get_related_pages_first_tab() override { return 1; }
void set_url(std::string new_url) override;
std::string get_url_timestamp() override { return timestamp; }
std::string get_video_url(int max_height, bool &has_embedded_audio, std::string &ext) override;
@@ -166,5 +181,6 @@ namespace QuickMedia {
std::string playback_url;
std::string watchtime_url;
std::string tracking_url;
+ YoutubeVideoDetails video_details;
};
}
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 29976ad..a1320e0 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -3082,17 +3082,19 @@ namespace QuickMedia {
window.setMouseCursorVisible(true);
cursor_visible = true;
+ XUnmapWindow(disp, video_player_window);
+ XSync(disp, False);
+
std::vector<Tab> related_pages;
TaskResult related_pages_result = run_task_with_loading_screen([&video_page, &related_videos, &channel_url, &related_pages]{
return video_page->get_related_pages(related_videos, channel_url, related_pages) == PluginResult::OK;
});
if(related_pages_result == TaskResult::FALSE) {
+ XMapWindow(disp, video_player_window);
+ XSync(disp, False);
show_notification("QuickMedia", "Failed to get related pages", Urgency::CRITICAL);
} else if(related_pages_result == TaskResult::TRUE) {
- XUnmapWindow(disp, video_player_window);
- XSync(disp, False);
-
bool page_changed = false;
double resume_start_time = 0.0;
page_loop(related_pages, video_page->get_related_pages_first_tab(), [&](const std::vector<Tab> &new_tabs) {
@@ -3125,6 +3127,9 @@ namespace QuickMedia {
XMapWindow(disp, video_player_window);
XSync(disp, False);
}
+ } else {
+ XMapWindow(disp, video_player_window);
+ XSync(disp, False);
}
}
} else if(pressed_keysym == XK_c && pressing_ctrl) {
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index c7a9e5c..7a5f0d5 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -2167,9 +2167,46 @@ namespace QuickMedia {
return result_items;
}
+ static std::shared_ptr<BodyItem> video_details_to_body_item(const YoutubeVideoDetails &video_details) {
+ auto body_item = BodyItem::create(video_details.title);
+
+ std::string description;
+ if(!video_details.views.empty()) {
+ description = video_details.views + " view" + (video_details.views == "1" ? "" : "s");
+ }
+
+ if(!video_details.rating.empty()) {
+ if(!description.empty())
+ description += " • ";
+ description += "rated " + video_details.rating + "/5";
+ }
+
+ if(!video_details.author.empty()) {
+ if(!description.empty())
+ description += '\n';
+ description += video_details.author;
+ }
+
+ if(!video_details.description.empty()) {
+ if(!description.empty())
+ description += "\n\n";
+ description += video_details.description;
+ }
+
+ if(!description.empty())
+ body_item->set_description(std::move(description));
+
+ return body_item;
+ }
+
PluginResult YoutubeVideoPage::get_related_pages(const BodyItems &related_videos, const std::string &channel_url, std::vector<Tab> &result_tabs) {
+ auto description_page_body = create_body();
+ description_page_body->append_item(video_details_to_body_item(video_details));
+
auto related_page_body = create_body(false, true);
related_page_body->set_items(related_videos);
+
+ result_tabs.push_back(Tab{std::move(description_page_body), std::make_unique<YoutubeDescriptionPage>(program), nullptr});
result_tabs.push_back(Tab{create_body(), std::make_unique<YoutubeCommentsPage>(program, url, comments_continuation_token), nullptr});
result_tabs.push_back(Tab{std::move(related_page_body), std::make_unique<YoutubeRelatedVideosPage>(program), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
result_tabs.push_back(Tab{create_body(false, true), std::make_unique<YoutubeChannelPage>(program, channel_url, "", "Channel videos"), create_search_bar("Search...", 350)});
@@ -2342,6 +2379,14 @@ namespace QuickMedia {
}
}
+ static void video_details_clear(YoutubeVideoDetails &video_details) {
+ video_details.title.clear();
+ video_details.author.clear();
+ video_details.rating.clear();
+ video_details.views.clear();
+ video_details.description.clear();
+ }
+
PluginResult YoutubeVideoPage::parse_video_response(const Json::Value &json_root, std::string &title, std::string &channel_url, std::vector<MediaChapter> &chapters, std::string &err_str) {
livestream_url.clear();
video_formats.clear();
@@ -2350,6 +2395,7 @@ namespace QuickMedia {
title.clear();
channel_url.clear();
chapters.clear();
+ video_details_clear(video_details);
if(!json_root.isObject())
return PluginResult::ERR;
@@ -2392,19 +2438,25 @@ namespace QuickMedia {
const Json::Value &video_details_json = json_root["videoDetails"];
if(video_details_json.isObject()) {
- const Json::Value &title_json = video_details_json["title"];
- if(title_json.isString())
- title = title_json.asString();
-
const Json::Value &channel_id_json = video_details_json["channelId"];
if(channel_id_json.isString())
channel_url = "https://www.youtube.com/channel/" + channel_id_json.asString();
- const Json::Value &description_json = video_details_json["shortDescription"];
- if(description_json.isString()) {
- std::string description = description_json.asString();
- chapters = youtube_description_extract_chapters(description);
- }
+ const Json::Value &title_json = video_details_json["title"];
+ const Json::Value &author_json = video_details_json["author"];
+ const Json::Value &average_rating_json = video_details_json["averageRating"];
+ const Json::Value &view_count_json = video_details_json["viewCount"];
+ const Json::Value &short_description_json = video_details_json["shortDescription"];
+
+ if(title_json.isString()) video_details.title = title_json.asString();
+ if(author_json.isString()) video_details.author = author_json.asString();
+ if(average_rating_json.isDouble()) video_details.rating = std::to_string(average_rating_json.asDouble());
+ if(view_count_json.isString()) video_details.views = view_count_json.asString();
+ if(short_description_json.isString()) video_details.description = short_description_json.asString();
+
+ title = video_details.title;
+ if(!video_details.description.empty())
+ chapters = youtube_description_extract_chapters(video_details.description);
}
const Json::Value &captions_json = json_root["captions"];
@@ -2456,10 +2508,6 @@ namespace QuickMedia {
}
PluginResult YoutubeVideoPage::load(std::string &title, std::string &channel_url, std::vector<MediaChapter> &chapters, std::string &err_str) {
- livestream_url.clear();
- video_formats.clear();
- audio_formats.clear();
-
std::string video_id;
if(!youtube_url_extract_id(url, video_id)) {
fprintf(stderr, "Failed to extract youtube id from %s\n", url.c_str());