Use actual video publication date if availiable

This commit add usage of the video publication date in addition to the
"Added to playlist" date that was used up to this point. This improves
the video list behavior for channels which upload videos and add them to
the playlists a while before the actual publication date. Before these
published, but old in the playlist videos would show up at their upload
date instead of the publication date which is the relevant one for this
application. The "added to playlist" date is still recorded and being kept.
This commit is contained in:
Daniel Schulte 2021-07-18 16:39:32 +02:00
parent b77cd9c227
commit 17b8727f62
3 changed files with 21 additions and 15 deletions

View File

@ -118,7 +118,8 @@ void draw_channel_list(const std::vector<Video> &videos, bool show_channel_name=
struct tm tm; struct tm tm;
memset(&tm, 0, sizeof(tm)); memset(&tm, 0, sizeof(tm));
if(strptime(video.published.c_str(), "%FT%T%z", &tm) != nullptr) { const std::string &date_str = !video.published.empty() ? video.published : video.added_to_playlist;
if(strptime(date_str.c_str(), "%FT%T%z", &tm) != nullptr) {
strftime(dt.data(), date_width + 10, "%F %H:%M", &tm); strftime(dt.data(), date_width + 10, "%F %H:%M", &tm);
} }

30
yt.cpp
View File

@ -218,31 +218,33 @@ bool video_is_known(sqlite3 *db, const std::string &channel_id, const std::strin
return known; return known;
} }
void add_video(sqlite3 *db, const json &snippet, const std::string &channel_id) { void add_video(sqlite3 *db, const json &snippet, const json &content_details, const std::string &channel_id) {
const std::string video_id = snippet["resourceId"]["videoId"]; const std::string video_id = snippet["resourceId"]["videoId"];
const std::string title = snippet["title"]; const std::string title = snippet["title"];
const std::string description = snippet["description"]; const std::string description = snippet["description"];
const int flags = 0; const int flags = 0;
const std::string published = snippet["publishedAt"]; const std::string added_to_playlist = snippet["publishedAt"];
const std::string published = content_details["videoPublishedAt"];
sqlite3_stmt *query; sqlite3_stmt *query;
SC(sqlite3_prepare_v2(db, "INSERT INTO videos (videoId, channelId, title, description, flags, published) values(?1,?2,?3,?4,?5,?6);", -1, &query, nullptr)); SC(sqlite3_prepare_v2(db, "INSERT INTO videos (videoId, channelId, title, description, flags, added_to_playlist, published) values(?1,?2,?3,?4,?5,?6,?7);", -1, &query, nullptr));
SC(sqlite3_bind_text(query, 1, video_id.c_str(), -1, SQLITE_TRANSIENT)); SC(sqlite3_bind_text(query, 1, video_id.c_str(), -1, SQLITE_TRANSIENT));
SC(sqlite3_bind_text(query, 2, channel_id.c_str(), -1, SQLITE_TRANSIENT)); SC(sqlite3_bind_text(query, 2, channel_id.c_str(), -1, SQLITE_TRANSIENT));
SC(sqlite3_bind_text(query, 3, title.c_str(), -1, SQLITE_TRANSIENT)); SC(sqlite3_bind_text(query, 3, title.c_str(), -1, SQLITE_TRANSIENT));
SC(sqlite3_bind_text(query, 4, description.c_str(), -1, SQLITE_TRANSIENT)); SC(sqlite3_bind_text(query, 4, description.c_str(), -1, SQLITE_TRANSIENT));
SC(sqlite3_bind_int(query, 5, flags)); SC(sqlite3_bind_int(query, 5, flags));
SC(sqlite3_bind_text(query, 6, published.c_str(), -1, SQLITE_TRANSIENT)); SC(sqlite3_bind_text(query, 6, added_to_playlist.c_str(), -1, SQLITE_TRANSIENT));
SC(sqlite3_bind_text(query, 7, published.c_str(), -1, SQLITE_TRANSIENT));
sqlite3_step(query); sqlite3_step(query);
SC(sqlite3_finalize(query)); SC(sqlite3_finalize(query));
} }
int Channel::fetch_new_videos(sqlite3 *db, progress_info *info, std::optional<std::string> after, std::optional<int> max_count) int Channel::fetch_new_videos(sqlite3 *db, progress_info *info, std::optional<std::string> after, std::optional<int> max_count) const
{ {
const std::string playlist_id = upload_playlist(); const std::string playlist_id = upload_playlist();
std::map<std::string, std::string> params = { std::map<std::string, std::string> params = {
{"part", "snippet"}, {"part", "snippet,contentDetails"},
{"playlistId", playlist_id}, {"playlistId", playlist_id},
{"maxResults", "50"}, {"maxResults", "50"},
{"key", yt_config.api_key}, {"key", yt_config.api_key},
@ -260,13 +262,15 @@ int Channel::fetch_new_videos(sqlite3 *db, progress_info *info, std::optional<st
for(auto &item: response["items"]) { for(auto &item: response["items"]) {
auto snippet = item["snippet"]; auto snippet = item["snippet"];
auto content_details = item["contentDetails"];
std::string channel_id = snippet["channelId"]; std::string channel_id = snippet["channelId"];
std::string video_id = snippet["resourceId"]["videoId"]; std::string video_id = snippet["resourceId"]["videoId"];
std::string title = snippet["title"]; std::string title = snippet["title"];
if(after) { if(after) {
auto publishedAt = snippet["publishedAt"]; auto addedToPlaylistAt = snippet["publishedAt"];
if(publishedAt < *after) { auto publishedAt = content_details["videoPublishedAt"];
if(addedToPlaylistAt < *after) {
//fprintf(stderr, "Stopping at video '%s': Too old.\r\n", title.c_str()); //fprintf(stderr, "Stopping at video '%s': Too old.\r\n", title.c_str());
abort = true; abort = true;
break; break;
@ -279,7 +283,7 @@ int Channel::fetch_new_videos(sqlite3 *db, progress_info *info, std::optional<st
break; break;
} }
add_video(db, snippet, channel_id); add_video(db, snippet, content_details, channel_id);
//fprintf(stderr, "New video: '%s': %s.\r\n", title.c_str(), video_id.c_str()); //fprintf(stderr, "New video: '%s': %s.\r\n", title.c_str(), video_id.c_str());
processed++; processed++;
if(max_count && processed >= *max_count) { if(max_count && processed >= *max_count) {
@ -341,8 +345,8 @@ void Channel::save_user_flags(sqlite3 *db)
} }
Video::Video(sqlite3_stmt *row): id(get_string(row, 0)), channel_id(get_string(row, 1)), title(get_string(row, 2)), Video::Video(sqlite3_stmt *row): id(get_string(row, 0)), channel_id(get_string(row, 1)), title(get_string(row, 2)),
description(get_string(row, 3)), flags(sqlite3_column_int(row, 4)), published(get_string(row, 5)), description(get_string(row, 3)), flags(sqlite3_column_int(row, 4)), added_to_playlist(get_string(row, 6)),
tui_title_width(0) published(get_string(row, 5)), tui_title_width(0)
{ {
} }
@ -367,7 +371,7 @@ std::vector<Video> Video::get_all_for_channel(const std::string &channel_id)
std::vector<Video> videos; std::vector<Video> videos;
sqlite3_stmt *query; sqlite3_stmt *query;
SC(sqlite3_prepare_v2(db, "SELECT * FROM videos WHERE channelId=?1 ORDER BY published DESC;", -1, &query, nullptr)); SC(sqlite3_prepare_v2(db, "SELECT * FROM videos WHERE channelId=?1 ORDER BY published DESC, added_to_playlist DESC;", -1, &query, nullptr));
SC(sqlite3_bind_text(query, 1, channel_id.c_str(), -1, SQLITE_TRANSIENT)); SC(sqlite3_bind_text(query, 1, channel_id.c_str(), -1, SQLITE_TRANSIENT));
while(sqlite3_step(query) == SQLITE_ROW) { while(sqlite3_step(query) == SQLITE_ROW) {
@ -384,7 +388,7 @@ std::vector<Video> Video::get_all_with_flag_value(const VideoFlag flag, const in
std::vector<Video> videos; std::vector<Video> videos;
sqlite3_stmt *query; sqlite3_stmt *query;
SC(sqlite3_prepare_v2(db, "SELECT * FROM videos WHERE flags & ?1 = ?2 ORDER BY published DESC;", -1, &query, nullptr)); SC(sqlite3_prepare_v2(db, "SELECT * FROM videos WHERE flags & ?1 = ?2 ORDER BY published DESC, added_to_playlist DESC;", -1, &query, nullptr));
SC(sqlite3_bind_int(query, 1, flag)); SC(sqlite3_bind_int(query, 1, flag));
SC(sqlite3_bind_int(query, 2, value)); SC(sqlite3_bind_int(query, 2, value));

3
yt.h
View File

@ -56,7 +56,7 @@ public:
static std::vector<Channel> get_all(sqlite3 *db); static std::vector<Channel> get_all(sqlite3 *db);
std::string upload_playlist() const; std::string upload_playlist() const;
int fetch_new_videos(sqlite3 *db, progress_info *info=nullptr, std::optional<std::string> after={}, std::optional<int> max_count={}); int fetch_new_videos(sqlite3 *db, progress_info *info=nullptr, std::optional<std::string> after={}, std::optional<int> max_count={}) const;
void load_info(sqlite3 *db); void load_info(sqlite3 *db);
bool is_valid() const; bool is_valid() const;
@ -75,6 +75,7 @@ struct Video
std::string title; std::string title;
std::string description; std::string description;
int flags; int flags;
std::string added_to_playlist;
std::string published; std::string published;
Video(sqlite3_stmt *row); Video(sqlite3_stmt *row);