diff --git a/bin/gtk-pipe-viewer b/bin/gtk-pipe-viewer index 9c08790..0b5e9e0 100755 --- a/bin/gtk-pipe-viewer +++ b/bin/gtk-pipe-viewer @@ -1371,17 +1371,27 @@ sub get_treeview_popup_menu { my $item = 'Gtk3::ImageMenuItem'->new("Uploads"); $item->signal_connect(activate => sub { list_channel_videos($channel_id) }); $item->set_property(tooltip_text => "Show the most recent videos from this author"); + $item->set_image('Gtk3::Image'->new_from_icon_name("emblem-videos-symbolic", q{menu})); + $item->show; + $author->append($item); + } + + # Recent shorts from this author + { + my $item = 'Gtk3::ImageMenuItem'->new("Shorts"); + $item->signal_connect(activate => sub { list_channel_shorts($channel_id) }); + $item->set_property(tooltip_text => "Show the most recent shorts from this author"); $item->set_image('Gtk3::Image'->new_from_icon_name("emblem-shared-symbolic", q{menu})); $item->show; $author->append($item); } - # Most popular uploads from this author + # Recent streams from this author { - my $item = 'Gtk3::ImageMenuItem'->new("Popular"); - $item->signal_connect(activate => sub { popular_uploads($channel_id) }); - $item->set_property(tooltip_text => "Show the most popular videos from this author"); - $item->set_image('Gtk3::Image'->new_from_icon_name("emblem-videos-symbolic", q{menu})); + my $item = 'Gtk3::ImageMenuItem'->new("Streams"); + $item->signal_connect(activate => sub { list_channel_streams($channel_id) }); + $item->set_property(tooltip_text => "Show the most recent streams from this author"); + $item->set_image('Gtk3::Image'->new_from_icon_name("media-record-symbolic", q{menu})); $item->show; $author->append($item); } @@ -1403,6 +1413,33 @@ sub get_treeview_popup_menu { $author->append($item); } + # Most popular videos from this author + { + my $item = 'Gtk3::ImageMenuItem'->new("Popular videos"); + $item->signal_connect(activate => sub { popular_uploads($channel_id) }); + $item->set_property(tooltip_text => "Show the most popular videos from this author"); + $item->set_image('Gtk3::Image'->new_from_icon_name("emblem-favorite", q{menu})); + $item->show; + $author->append($item); + } + + # Most popular streams from this author + { + my $item = 'Gtk3::ImageMenuItem'->new("Popular streams"); + $item->signal_connect(activate => sub { popular_streams($channel_id) }); + $item->set_property(tooltip_text => "Show the most popular livestreams from this author"); + $item->set_image('Gtk3::Image'->new_from_icon_name("media-record", q{menu})); + $item->show; + $author->append($item); + } + + # Separator + { + my $item = 'Gtk3::SeparatorMenuItem'->new; + $item->show; + $author->append($item); + } + my $channel_data = parse_json_string($liststore->get($iter, 8)); my $channel_name = $yv_utils->get_channel_title($channel_data); @@ -2342,6 +2379,12 @@ sub popular_uploads { return; } +sub popular_streams { + my ($channel_id) = @_; + send_search_request("No popular livestreams for channel: <<$channel_id>>", 'popular_streams', [$channel_id]); + return; +} + sub get_selected_entry_code { my (%options) = @_; my $iter = $treeview->get_selection->get_selected // return; @@ -3126,6 +3169,18 @@ sub list_channel_videos { return; } +sub list_channel_streams { + my ($channel) = @_; + send_search_request("[!] No livestreams for channel: $channel", 'streams', [$channel]); + return; +} + +sub list_channel_shorts { + my ($channel) = @_; + send_search_request("[!] No short videos for channel: $channel", 'shorts', [$channel]); + return; +} + sub list_channel_playlists { my ($channel) = @_; send_search_request("[!] No playlists for channel: $channel", 'playlists', [$channel]); diff --git a/lib/WWW/PipeViewer/Channels.pm b/lib/WWW/PipeViewer/Channels.pm index 1d1bab8..fb6846e 100644 --- a/lib/WWW/PipeViewer/Channels.pm +++ b/lib/WWW/PipeViewer/Channels.pm @@ -63,6 +63,40 @@ sub uploads { return $self->_get_results($url); } +=head2 streams($channel_id) + +Get the livestreams for a given channel ID. + +=cut + +sub streams { + my ($self, $channel_id) = @_; + + if (my $results = $self->yt_channel_streams($channel_id)) { + return $results; + } + + my $url = $self->_make_feed_url("channels/$channel_id/streams"); # FIXME + return $self->_get_results($url); +} + +=head2 shorts($channel_id) + +Get the shorts for a given channel ID. + +=cut + +sub shorts { + my ($self, $channel_id) = @_; + + if (my $results = $self->yt_channel_shorts($channel_id)) { + return $results; + } + + my $url = $self->_make_feed_url("channels/$channel_id/shorts"); # FIXME + return $self->_get_results($url); +} + =head2 popular_videos($channel_id) Get the most popular videos for a given channel ID. @@ -84,6 +118,23 @@ sub popular_videos { return $self->_get_results($url); } +=head2 popular_streams($channel_id) + +Get the most popular livestreams for a given channel ID. + +=cut + +sub popular_streams { + my ($self, $channel_id) = @_; + + if (my $results = $self->yt_channel_streams($channel_id, sort_by => 'popular')) { + return $results; + } + + my $url = $self->_make_feed_url("channels/$channel_id/streams", sort_by => 'popular'); # FIXME + return $self->_get_results($url); +} + =head2 channels_info($channel_id) Return information for the comma-separated list of the YouTube channel ID(s). diff --git a/lib/WWW/PipeViewer/InitialData.pm b/lib/WWW/PipeViewer/InitialData.pm index 5739bf5..deeeebe 100644 --- a/lib/WWW/PipeViewer/InitialData.pm +++ b/lib/WWW/PipeViewer/InitialData.pm @@ -535,6 +535,30 @@ sub _extract_channel_tabs { return %channel_tabs; } +sub _extract_videos_from_channel_data { + my ($self, $url, $hash, %args) = @_; + + $hash // return; + + my @results = $self->_extract_channel_uploads($hash, %args, type => 'video'); + my $author_name = @results ? $results[0]->{author} : undef; + + # Popular videos + if (defined($args{sort_by}) and $args{sort_by} eq 'popular') { + my %channel_tabs = $self->_extract_channel_tabs($hash); + foreach my $key (keys %channel_tabs) { + $key =~ /popular/i or next; + my $value = $channel_tabs{$key}; + ref($value) eq 'HASH' or next; + my $token = eval { $value->{navigationEndpoint}{continuationCommand}{token} } // next; + my $popular_videos = $self->yt_browse_request($url, $token, %args, type => 'video', author_name => $author_name); + return $popular_videos; + } + } + + $self->_prepare_results_for_return(\@results, %args, url => $url); +} + sub _add_author_to_results { my ($self, $data, $results, %args) = @_; @@ -1018,26 +1042,39 @@ Additionally, for getting the popular videos, call the function with the argumen sub yt_channel_uploads { my ($self, $channel, %args) = @_; my ($url, $hash) = $self->_channel_data($channel, %args, type => 'videos'); + $self->_extract_videos_from_channel_data($url, $hash, %args); +} - $hash // return; +=head2 yt_channel_streams($channel, %args) - my @results = $self->_extract_channel_uploads($hash, %args, type => 'video'); - my $author_name = @results ? $results[0]->{author} : undef; +Latest streams for a given channel ID or username. - # Popular videos - if (defined($args{sort_by}) and $args{sort_by} eq 'popular') { - my %channel_tabs = $self->_extract_channel_tabs($hash); - foreach my $key (keys %channel_tabs) { - $key =~ /popular/i or next; - my $value = $channel_tabs{$key}; - ref($value) eq 'HASH' or next; - my $token = eval { $value->{navigationEndpoint}{continuationCommand}{token} } // next; - my $popular_videos = $self->yt_browse_request($url, $token, %args, type => 'video', author_name => $author_name); - return $popular_videos; - } - } +Additionally, for getting the popular streams, call the function with the arguments: - $self->_prepare_results_for_return(\@results, %args, url => $url); + sort_by => 'popular', + +=cut + +sub yt_channel_streams { + my ($self, $channel, %args) = @_; + my ($url, $hash) = $self->_channel_data($channel, %args, type => 'streams'); + $self->_extract_videos_from_channel_data($url, $hash, %args); +} + +=head2 yt_channel_shorts($channel, %args) + +Latest short videos for a given channel ID or username. + +Additionally, for getting the popular short videos, call the function with the arguments: + + sort_by => 'popular', + +=cut + +sub yt_channel_shorts { + my ($self, $channel, %args) = @_; + my ($url, $hash) = $self->_channel_data($channel, %args, type => 'shorts'); + $self->_extract_videos_from_channel_data($url, $hash, %args); } =head2 yt_channel_info($channel, %args)