aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortrizen <trizen@protonmail.com>2020-09-18 19:44:07 +0300
committerJesús <heckyel@hyperbola.info>2020-09-28 22:17:04 -0500
commit27774c9579fad5b7595c3f936597307feadaef9d (patch)
treeccb6664bd6e32a258befeb84f35c1b347b892fff
parent8caf34c363ee1554787104f1b90a820075833655 (diff)
downloadfair-viewer-27774c9579fad5b7595c3f936597307feadaef9d.tar.lz
fair-viewer-27774c9579fad5b7595c3f936597307feadaef9d.tar.xz
fair-viewer-27774c9579fad5b7595c3f936597307feadaef9d.zip
- Implemented `sort_by` and `date` parameters for `/search`. (https://github.com/iv-org/invidious/wiki/API#get-apiv1search)
In the CLI version, we have: --order=s # valid values: relevance rating upload_date view_count --date=s # valid values: hour today week month year In the GTK3 version, this is implemented in the "Order by" and "Published within" comboboxes. Also implemented the `--hd`, `--captions` and `--region=s` options. Signed-off-by: Jesús <heckyel@hyperbola.info>
-rwxr-xr-xbin/fair-viewer289
-rwxr-xr-xbin/gtk-fair-viewer353
-rw-r--r--lib/WWW/FairViewer.pm48
-rw-r--r--lib/WWW/FairViewer/GuideCategories.pm4
-rw-r--r--lib/WWW/FairViewer/Search.pm149
-rw-r--r--lib/WWW/FairViewer/VideoCategories.pm4
-rw-r--r--lib/WWW/FairViewer/Videos.pm5
-rw-r--r--share/gtk-fair-viewer.glade41
8 files changed, 413 insertions, 480 deletions
diff --git a/bin/fair-viewer b/bin/fair-viewer
index ab84393..ff70dea 100755
--- a/bin/fair-viewer
+++ b/bin/fair-viewer
@@ -36,8 +36,7 @@ See: fair-viewer --help
=head1 LICENSE AND COPYRIGHT
-Copyright 2013-2015 Trizen.
-
+Copyright 2010-2020 Trizen.
Copyright 2020 Jesus E.
This program is free software; you can redistribute it and/or modify it
@@ -58,7 +57,7 @@ use 5.016;
use warnings;
no warnings 'once';
-my $DEVEL; # true in devel mode
+my $DEVEL; # true in devel mode
use if ($DEVEL = 0), lib => qw(../lib); # devel mode
use WWW::FairViewer v1.0.4;
@@ -175,7 +174,7 @@ my %CONFIG = (
video_player_selected => (
$constant{win32}
? 'vlc'
- : undef # auto-defined
+ : undef # auto-defined
),
# YouTube options
@@ -191,16 +190,15 @@ my %CONFIG = (
safeSearch => undef,
videoCaption => undef,
videoDuration => undef,
- videoSyndicated => undef,
- publishedBefore => undef,
- publishedAfter => undef,
- order => undef,
- comments_order => 'top', # valid values: top, new
+ order => undef,
+ date => undef,
+
+ comments_order => 'top', # valid values: top, new
subscriptions_order => 'relevance', # valid values: alphabetical, relevance, unread
- hl => 'en_US',
- regionCode => undef,
+ hl => 'en_US',
+ region => undef,
# URI options
youtube_video_url => 'https://www.youtube.com/watch?v=%s',
@@ -248,13 +246,13 @@ my %CONFIG = (
highlight_watched => 1,
highlight_color => 'bold',
remove_played_file => 0,
- history => undef, # auto-defined
+ history => undef, # auto-defined
history_limit => 100_000,
history_file => $history_file,
convert_cmd => 'ffmpeg -i *IN* *OUT*',
convert_to => undef,
- custom_layout => undef, # auto-defined
+ custom_layout => undef, # auto-defined
custom_layout_format => [{width => 3, align => "right", color => "bold", text => "*NO*.",},
{width => "55%", align => "left", color => "bold blue", text => "*TITLE*",},
{width => "15%", align => "left", color => "yellow", text => "*AUTHOR*",},
@@ -536,12 +534,12 @@ sub load_config {
dump_configuration($config_file) if $update_config;
-foreach my $path($CONFIG{cache_dir}) {
- next if -d $path;
- require File::Path;
- File::Path::make_path($path)
- or warn "[!] Can't create path <<$path>>: $!";
-}
+ foreach my $path ($CONFIG{cache_dir}) {
+ next if -d $path;
+ require File::Path;
+ File::Path::make_path($path)
+ or warn "[!] Can't create path <<$path>>: $!";
+ }
@opt{keys %CONFIG} = values(%CONFIG);
}
@@ -572,7 +570,7 @@ if ($opt{history}) {
if (not -d $dir) {
require File::Path;
File::Path::make_path($dir)
- or warn "[!] Can't create path <<$dir>>: $!";
+ or warn "[!] Can't create path <<$dir>>: $!";
}
open my $fh, '>', $opt{history_file}
@@ -602,15 +600,15 @@ if ($opt{history}) {
}
my $yv_obj = WWW::FairViewer->new(
- escape_utf8 => 1,
- config_dir => $config_dir,
- cache_dir => $opt{cache_dir},
- env_proxy => $opt{env_proxy},
- cookie_file => $opt{cookie_file},
- http_proxy => $opt{http_proxy},
- user_agent => $opt{user_agent},
- timeout => $opt{timeout},
- );
+ escape_utf8 => 1,
+ config_dir => $config_dir,
+ cache_dir => $opt{cache_dir},
+ env_proxy => $opt{env_proxy},
+ cookie_file => $opt{cookie_file},
+ http_proxy => $opt{http_proxy},
+ user_agent => $opt{user_agent},
+ timeout => $opt{timeout},
+ );
require WWW::FairViewer::Utils;
my $yv_utils = WWW::FairViewer::Utils->new(youtube_url_format => $opt{youtube_video_url},
@@ -668,7 +666,6 @@ usage: $execname [options] ([url] | [keywords])
* Trending
--trending:s : show trending videos in a given category ID or name
- use the `--within=s` option to restrict the results
* Channels
-sc --channels : search for YouTube channels
@@ -681,16 +678,15 @@ usage: $execname [options] ([url] | [keywords])
* Filtering
--author=s : search in videos uploaded by a specific user
--duration=s : filter search results based on video length
- valid values are: short medium long
- --caption=s : only videos with/without closed captions
- valid values are: any closedCaption none
+ valid values: short long
+ --captions! : only videos with or without closed captions
--category=s : search only for videos in a specific category name/ID
--safe-search=s : YouTube will skip restricted videos for your location
valid values are: none moderate strict
--order=s : order the results using a specific sorting method
- valid values: date rating viewCount title videoCount
- --within=s : show only videos uploaded within the specified time
- valid values are: Nd, Nw, Nm, Ny, where N is a number
+ valid values: relevance rating upload_date view_count
+ --date=s : short videos published in a time period
+ valid values: hour today week month year
--hd! : search only for videos available in at least 720p
--vd=s : set the video definition (any, high or standard)
--page=i : get results starting with a specific page number
@@ -973,22 +969,13 @@ Results: show video comments for a specific video URL or videoID.
Command: $execname --results=5 -up=khanacademy -D
Results: the most recent 5 videos by a specific author (-up), printed with extra details (-D).
-Command: $execname --author=MIT atom
-Results: search only in videos by a specific author.
-
-Command: $execname --author=MIT atom --within=2y
-Results: search only in videos by a specific author, published in the last 2 years.
-
-Command: $execname --popular=MIT --within=6m
-Results: show the most popular videos by a specific user, published in the last 6 months.
-
Command: $execname -S=vsauce
Results: get the subscriptions for a username.
Command: $execname --page=2 -u=Google
Results: show latest videos uploaded by Google, starting with the page number 2.
-Command: $execname cats --order=viewCount --duration=short
+Command: $execname cats --order=view_count --duration=short
Results: search for 'cats' videos, ordered by ViewCount and short duration.
Command: $execname --channels math lessons
@@ -1094,13 +1081,11 @@ sub apply_configuration {
foreach my $option_name (
qw(
api_host
- videoCaption maxResults order
- videoDefinition videoCategoryId
+ videoCaption
+ videoDefinition
videoDimension videoDuration
- videoEmbeddable videoLicense
- videoSyndicated channelId
- publishedAfter publishedBefore
- safeSearch regionCode debug hl
+ date order
+ channelId region debug hl
http_proxy page comments_order
subscriptions_order user_agent
cookie_file timeout
@@ -1169,18 +1154,6 @@ sub apply_configuration {
}
}
- if (defined $opt->{within}) {
- my $value = delete $opt->{within};
-
- if ($value =~ /^\s*(\d+(?:\.\d+)?)([dwmy])/i) {
- my $date = $yv_utils->period_to_date($1, $2);
- $yv_obj->set_publishedAfter($date);
- }
- else {
- warn "\n[!] Invalid value <$value> for option `--within`!\n";
- }
- }
-
if (defined $opt->{more_results}) {
$yv_obj->set_maxResults(delete($opt->{more_results}) ? 50 : $CONFIG{maxResults});
}
@@ -1488,7 +1461,7 @@ sub parse_arguments {
'720p|7' => sub { $opt{resolution} = 720 },
'1080p|1' => sub { $opt{resolution} = 1080 },
- 'hfr!' => \$opt{hfr},
+ 'hfr!' => \$opt{hfr},
'res|resolution=s' => \$opt{resolution},
'comments=s' => \$opt{get_comments},
@@ -1530,11 +1503,12 @@ sub parse_arguments {
'catlang|cl|hl=s' => \$opt{hl},
'category|cat-id|cat=s' => \$opt{category_id},
- 'r|region|region-code=s' => \$opt{regionCode},
+ 'r|region|region-code=s' => \$opt{region},
+
+ 'order|order-by|sort|sort-by=s' => \$opt{order},
+ 'date=s' => \$opt{date},
- 'orderby|order|order-by=s' => \$opt{order},
- 'duration=s' => \$opt{videoDuration},
- 'within=s' => \$opt{within},
+ 'duration=s' => \$opt{videoDuration},
'max-seconds|max_seconds=i' => \$opt{max_seconds},
'min-seconds|min_seconds=i' => \$opt{min_seconds},
@@ -1588,7 +1562,7 @@ sub parse_arguments {
'colorful|colourful|C!' => \$opt{results_with_colors},
'details|D!' => \$opt{results_with_details},
'fixed-width|W|fw!' => \$opt{results_fixed_width},
- 'caption=s' => \$opt{videoCaption},
+ 'captions!' => \$opt{videoCaption},
'fullscreen|fs|f!' => \$opt{fullscreen},
'dash!' => \$opt{dash_support},
'confirm!' => \$opt{confirm},
@@ -1936,14 +1910,18 @@ sub get_user_input {
}
my $input = unpack(
- 'A*', defined($opt{std_input})
- ? delete($opt{std_input})
- : (do {
- my @lines = split(/\R/, $text);
- say for @lines[0..$#lines-1];
- $term->readline($lines[-1]);
- } // return ':return')
- ) =~ s/^\s+//r;
+ 'A*',
+ defined($opt{std_input})
+ ? delete($opt{std_input})
+ : (
+ do {
+ my @lines = split(/\R/, $text);
+ say for @lines[0 .. $#lines - 1];
+ $term->readline($lines[-1]);
+ }
+ // return ':return'
+ )
+ ) =~ s/^\s+//r;
return q{:next} if $input eq q{}; # <ENTER> for the next page
@@ -2116,9 +2094,9 @@ sub get_and_play_video_ids {
## OK
}
else {
- $info->{title} = "unknwon";
+ $info->{title} = "unknwon";
$info->{lengthSeconds} = 0;
- $info->{videoId} = $id;
+ $info->{videoId} = $id;
warn_cant_do('get info for', $id);
}
@@ -2262,12 +2240,12 @@ sub general_options {
my $results = $args{res};
my $info = $args{info};
- my $token = undef;
+ my $token = undef;
my $has_token = 0;
if (ref($info->{results}) eq 'HASH' and exists $info->{results}{continuation}) {
$has_token = 1;
- $token = $info->{results}{continuation};
+ $token = $info->{results}{continuation};
}
if (not defined($option)) {
@@ -2524,7 +2502,7 @@ sub print_channels {
}
my $url = $results->{url};
- my $channels = $results->{results} // [];
+ my $channels = $results->{results} // [];
foreach my $i (0 .. $#{$channels}) {
my $channel = $channels->[$i];
@@ -2546,7 +2524,7 @@ sub print_channels {
print "\n" if $i == 0;
printf("%s. %s (%s)\n",
colored(sprintf('%2d', $i + 1), 'bold'),
- colored($yv_utils->get_channel_title($channel), 'blue'),
+ colored($yv_utils->get_channel_title($channel), 'blue'),
colored($yv_utils->get_publication_date($channel), 'magenta'),
);
}
@@ -2641,7 +2619,7 @@ sub print_comments {
my $i = 0;
foreach my $comment (@{$comments}) {
- my $comment_id = $yv_utils->get_comment_id($comment);
+ my $comment_id = $yv_utils->get_comment_id($comment);
my $comment_age = $yv_utils->get_publication_age_approx($comment);
printf(
@@ -2660,23 +2638,23 @@ sub print_comments {
);
#~ if (exists $comment->{replies}) {
- #~ foreach my $reply (reverse @{$comment->{replies}{comments}}) {
- #~ my $reply_age = $yv_utils->date_to_age($reply->{snippet}{publishedAt});
- #~ printf(
- #~ "\n %s (%s) replied:\n%s\n",
- #~ colored($reply->{snippet}{authorDisplayName}, 'bold'),
- #~ (
- #~ $reply_age =~ /sec|min|hour|day/
- #~ ? "$reply_age ago"
- #~ : $yv_utils->format_date($reply->{snippet}{publishedAt})
- #~ ),
- #~ wrap_text(
- #~ i_tab => q{ } x 6,
- #~ s_tab => q{ } x 6,
- #~ text => [$reply->{snippet}{textDisplay} // 'Empty comment...']
- #~ ),
- #~ );
- #~ }
+ #~ foreach my $reply (reverse @{$comment->{replies}{comments}}) {
+ #~ my $reply_age = $yv_utils->date_to_age($reply->{snippet}{publishedAt});
+ #~ printf(
+ #~ "\n %s (%s) replied:\n%s\n",
+ #~ colored($reply->{snippet}{authorDisplayName}, 'bold'),
+ #~ (
+ #~ $reply_age =~ /sec|min|hour|day/
+ #~ ? "$reply_age ago"
+ #~ : $yv_utils->format_date($reply->{snippet}{publishedAt})
+ #~ ),
+ #~ wrap_text(
+ #~ i_tab => q{ } x 6,
+ #~ s_tab => q{ } x 6,
+ #~ text => [$reply->{snippet}{textDisplay} // 'Empty comment...']
+ #~ ),
+ #~ );
+ #~ }
#~ }
}
@@ -3047,12 +3025,12 @@ sub get_streaming_url {
if (ref($captions) eq 'ARRAY' and @$captions and $opt{get_captions} and not $opt{novideo}) {
require WWW::FairViewer::GetCaption;
my $yv_cap = WWW::FairViewer::GetCaption->new(
- auto_captions => $opt{auto_captions},
- captions_dir => $opt{cache_dir},
- captions => $captions,
- languages => $CONFIG{srt_languages},
- yv_obj => $yv_obj,
- );
+ auto_captions => $opt{auto_captions},
+ captions_dir => $opt{cache_dir},
+ captions => $captions,
+ languages => $CONFIG{srt_languages},
+ yv_obj => $yv_obj,
+ );
$srt_file = $yv_cap->save_caption($video_id);
}
@@ -3076,7 +3054,7 @@ sub get_streaming_url {
resolution => ($opt{novideo} ? 'audio' : $opt{resolution}),
hfr => $opt{hfr},
dash => $dash,
- dash_mp4_audio => ($opt{novideo} ? 1 : $opt{dash_mp4_audio}),
+ dash_mp4_audio => ($opt{novideo} ? 1 : $opt{dash_mp4_audio}),
dash_segmented => ($opt{download_video} ? 0 : $opt{dash_segmented}),
);
@@ -3568,23 +3546,26 @@ sub print_video_info {
$rep = 0 if $rep < 0;
- print("\n$hr\n", q{ } x $rep => (_bold_color("=>> $title <<=") . "\n\n"),
- (
- map { sprintf(q{-> } . "%-*s: %s\n", $opt{_colors} ? 18 : 10, _bold_color($_->[0]), $_->[1]) }
- grep { defined($_->[1]) and $_->[1] !~ /^(0|unknown)\z/i } (
- ['Channel' => $yv_utils->get_channel_title($video)],
- ['ChannelID' => $yv_utils->get_channel_id($video)],
- ['VideoID' => $yv_utils->get_video_id($video)],
- ['Category' => $yv_utils->get_category_name($video)],
- ['Definition' => $yv_utils->get_definition($video)],
- ['Duration' => $yv_utils->get_time($video)],
- ['Likes' => $yv_utils->set_thousands($yv_utils->get_likes($video))],
- ['Dislikes' => $yv_utils->set_thousands($yv_utils->get_dislikes($video))],
- ['Views' => $yv_utils->set_thousands($yv_utils->get_views($video))],
- ['Published' => $yv_utils->get_publication_date($video)],
- )
- ),
- "$hr\n");
+ print(
+ "\n$hr\n",
+ q{ } x $rep => (_bold_color("=>> $title <<=") . "\n\n"),
+ (
+ map { sprintf(q{-> } . "%-*s: %s\n", $opt{_colors} ? 18 : 10, _bold_color($_->[0]), $_->[1]) }
+ grep { defined($_->[1]) and $_->[1] !~ /^(0|unknown)\z/i } (
+ ['Channel' => $yv_utils->get_channel_title($video)],
+ ['ChannelID' => $yv_utils->get_channel_id($video)],
+ ['VideoID' => $yv_utils->get_video_id($video)],
+ ['Category' => $yv_utils->get_category_name($video)],
+ ['Definition' => $yv_utils->get_definition($video)],
+ ['Duration' => $yv_utils->get_time($video)],
+ ['Likes' => $yv_utils->set_thousands($yv_utils->get_likes($video))],
+ ['Dislikes' => $yv_utils->set_thousands($yv_utils->get_dislikes($video))],
+ ['Views' => $yv_utils->set_thousands($yv_utils->get_views($video))],
+ ['Published' => $yv_utils->get_publication_date($video)],
+ )
+ ),
+ "$hr\n"
+ );
return 1;
}
@@ -3620,24 +3601,24 @@ sub print_videos {
#my $videos = $info->{items} // [];
#~ foreach my $entry (@$videos) {
- #~ if ($yv_utils->is_activity($entry)) {
- #~ my $type = $entry->{snippet}{type};
-
- #~ if ($type eq 'upload') {
- #~ $entry->{kind} = 'youtube#video';
- #~ $entry->{id} = $entry->{contentDetails}{upload}{videoId};
- #~ }
-
- #~ if ($type eq 'playlistItem') {
- #~ $entry->{kind} = 'youtube#video';
- #~ $entry->{id} = $entry->{contentDetails}{playlistItem}{resourceId}{videoId};
- #~ }
-
- #~ if ($type eq 'bulletin' and $entry->{contentDetails}{bulletin}{resourceId}{kind} eq 'youtube#video') {
- #~ $entry->{kind} = 'youtube#video';
- #~ $entry->{id} = $entry->{contentDetails}{bulletin}{resourceId}{videoId};
- #~ }
- #~ }
+ #~ if ($yv_utils->is_activity($entry)) {
+ #~ my $type = $entry->{snippet}{type};
+
+ #~ if ($type eq 'upload') {
+ #~ $entry->{kind} = 'youtube#video';
+ #~ $entry->{id} = $entry->{contentDetails}{upload}{videoId};
+ #~ }
+
+ #~ if ($type eq 'playlistItem') {
+ #~ $entry->{kind} = 'youtube#video';
+ #~ $entry->{id} = $entry->{contentDetails}{playlistItem}{resourceId}{videoId};
+ #~ }
+
+ #~ if ($type eq 'bulletin' and $entry->{contentDetails}{bulletin}{resourceId}{kind} eq 'youtube#video') {
+ #~ $entry->{kind} = 'youtube#video';
+ #~ $entry->{id} = $entry->{contentDetails}{bulletin}{resourceId}{videoId};
+ #~ }
+ #~ }
#~ }
#<<<
@@ -3657,16 +3638,16 @@ sub print_videos {
#~ if (@{$videos} and not $results->{has_extra_info}) {
- #~ my @video_ids = grep { defined } map { $yv_utils->get_video_id($_) } @{$videos};
- #~ my $content_details = $yv_obj->video_details(join(',', @video_ids), VIDEO_PART);
- #~ my $video_details = $content_details->{results}{items};
+ #~ my @video_ids = grep { defined } map { $yv_utils->get_video_id($_) } @{$videos};
+ #~ my $content_details = $yv_obj->video_details(join(',', @video_ids), VIDEO_PART);
+ #~ my $video_details = $content_details->{results}{items};
- #~ foreach my $i (0 .. $#{$videos}) {
- #~ @{$videos->[$i]}{qw(id contentDetails statistics snippet)} =
- #~ @{$video_details->[$i]}{qw(id contentDetails statistics snippet)};
- #~ }
+ #~ foreach my $i (0 .. $#{$videos}) {
+ #~ @{$videos->[$i]}{qw(id contentDetails statistics snippet)} =
+ #~ @{$video_details->[$i]}{qw(id contentDetails statistics snippet)};
+ #~ }
- #~ $results->{has_extra_info} = 1;
+ #~ $results->{has_extra_info} = 1;
#~ }
#<<<
@@ -3795,7 +3776,7 @@ sub print_videos {
sprintf(
"%s. %s (by %s) [%s]\n",
colored(sprintf('%2d', $i + 1), 'bold'), $yv_utils->get_title($video),
- $yv_utils->get_channel_title($video), $yv_utils->get_time($video),
+ $yv_utils->get_channel_title($video), $yv_utils->get_time($video),
);
}
}
@@ -3824,7 +3805,7 @@ sub print_videos {
) {
if ($opt{play_backwards}) {
if (defined($url)) {
- __SUB__->($yv_obj->previous_page($url), auto => 1);
+ __SUB__->($yv_obj->previous_page($url), auto => 1);
}
else {
$opt{play_backwards} = 0;
diff --git a/bin/gtk-fair-viewer b/bin/gtk-fair-viewer
index f8f40d5..593e929 100755
--- a/bin/gtk-fair-viewer
+++ b/bin/gtk-fair-viewer
@@ -29,7 +29,7 @@ use 5.016;
use warnings;
no warnings 'once';
-my $DEVEL; # true in devel mode
+my $DEVEL; # true in devel mode
use if ($DEVEL = 0), lib => qw(../lib); # devel only
use WWW::FairViewer v1.0.4;
@@ -54,9 +54,9 @@ my $version = $WWW::FairViewer::VERSION;
# Share directory
my $share_dir =
- ($DEVEL and -d "../share")
- ? '../share'
- : do { require File::ShareDir; File::ShareDir::dist_dir('WWW-FairViewer') };
+ ($DEVEL and -d "../share")
+ ? '../share'
+ : do { require File::ShareDir; File::ShareDir::dist_dir('WWW-FairViewer') };
# Configuration dir/file
my $home_dir;
@@ -184,25 +184,21 @@ my %CONFIG = (
hpaned_position => 420,
# Fair options
- dash_support => 1,
- dash_mp4_audio => 1,
- dash_segmented => 1, # may load slow
- prefer_mp4 => 0,
- prefer_av1 => 0,
- maxResults => 10,
- hfr => 1, # true to prefer high frame rate (HFR) videos
- resolution => 'best',
- videoDimension => undef,
- videoEmbeddable => undef,
- videoLicense => undef,
- videoSyndicated => undef,
- publishedBefore => undef,
- publishedAfter => undef,
- hl => 'en_US',
- regionCode => undef,
+ dash_support => 1,
+ dash_mp4_audio => 1,
+ dash_segmented => 1, # may load slow
+ prefer_mp4 => 0,
+ prefer_av1 => 0,
+ maxResults => 10,
+ hfr => 1, # true to prefer high frame rate (HFR) videos
+ resolution => 'best',
+ videoDimension => undef,
+ videoLicense => undef,
+ hl => 'en_US',
+ region => undef,
comments_width => 80, # wrap comments longer than `n` characters
- comments_order => 'top', # valid values: time, relevance
+ comments_order => 'top', # valid values: time, relevance
# API
api_host => "auto",
@@ -231,7 +227,7 @@ my %CONFIG = (
audio_only => 0,
tooltips => 1,
- tooltip_max_len => 512, # max length of description in tooltips
+ tooltip_max_len => 512, # max length of description in tooltips
thousand_separator => q{,},
downloads_dir => curdir(),
@@ -356,7 +352,6 @@ my %objects = (
'channels_checkbox' => \my $search_for_channels_checkbox,
'spinbutton1' => \my $spin_results,
'spinbutton2' => \my $spin_start_with_page,
- 'spinbutton3' => \my $spin_published_within,
'thumbs_checkbutton' => \my $thumbs_checkbutton,
'fullscreen_checkbutton' => \my $fullscreen_checkbutton,
'clear_list_checkbutton' => \my $clear_list_checkbutton,
@@ -467,7 +462,7 @@ if (not defined $CONFIG{cache_dir}) {
$CONFIG{cache_dir} = catdir($cache_dir, 'fair-viewer');
}
-foreach my $path($CONFIG{cache_dir}) {
+foreach my $path ($CONFIG{cache_dir}) {
next if -d $path;
require File::Path;
File::Path::make_path($path)
@@ -808,15 +803,15 @@ my %ResultsHistory = (
$CONFIG{fair_viewer} //= which_command('fair-viewer') // 'fair-viewer';
my $yv_obj = WWW::FairViewer->new(
- escape_utf8 => 1,
- config_dir => $config_dir,
- hl => $CONFIG{hl},
- env_proxy => $CONFIG{env_proxy},
- cache_dir => $CONFIG{cache_dir},
- cookie_file => $CONFIG{cookie_file},
- user_agent => $CONFIG{user_agent},
- timeout => $CONFIG{timeout},
- );
+ escape_utf8 => 1,
+ config_dir => $config_dir,
+ hl => $CONFIG{hl},
+ env_proxy => $CONFIG{env_proxy},
+ cache_dir => $CONFIG{cache_dir},
+ cookie_file => $CONFIG{cookie_file},
+ user_agent => $CONFIG{user_agent},
+ timeout => $CONFIG{timeout},
+ );
#$yv_obj->load_authentication_tokens();
@@ -866,9 +861,8 @@ sub apply_configuration {
api_host
videoSyndicated comments_order
maxResults videoDimension
- videoEmbeddable videoLicense
- publishedAfter publishedBefore
- regionCode videoCategoryId
+ videoLicense
+ region videoCategoryId
debug http_proxy user_agent
timeout cookie_file
)
@@ -1426,8 +1420,8 @@ $accel->connect(ord('g'), ['control-mask'], ['visible'], \&show_user_favorited_v
$accel->connect(ord('m'), ['control-mask'], ['visible'], \&show_videos_from_selected_author);
$accel->connect(ord('k'), ['control-mask'], ['visible'], \&show_playlists_from_selected_author);
$accel->connect(ord('w'), ['control-mask'], ['visible'], \&show_warnings_window);
-$accel->connect(0xffff, ['lock-mask'], ['visible'], \&delete_selected_row);
-$accel->connect(0xffc8, ['lock-mask'], ['visible'], \&maximize_unmaximize_mainw);
+$accel->connect(0xffff, ['lock-mask'], ['visible'], \&delete_selected_row);
+$accel->connect(0xffc8, ['lock-mask'], ['visible'], \&maximize_unmaximize_mainw);
$mainw->add_accel_group($accel);
# Support for navigating back and forth using the side buttons of the mouse
@@ -1456,7 +1450,7 @@ $accel->connect(0xff1b, ['lock-mask'], ['visible'], \&hide_feeds_window);
$feeds_window->add_accel_group($accel);
$accel = Gtk3::AccelGroup->new;
-$accel->connect(0xff1b, ['lock-mask'], ['visible'], \&hide_preferences_window);
+$accel->connect(0xff1b, ['lock-mask'], ['visible'], \&hide_preferences_window);
$accel->connect(ord('s'), ['control-mask'], ['visible'], \&save_configuration);
$prefernces_window->add_accel_group($accel);
@@ -1700,25 +1694,10 @@ sub combobox_published_within_changed {
my $period = $published_within_combobox->get_active_text;
if ($period =~ /^any/) {
- $spin_published_within->hide;
+ $yv_obj->set_date(undef);
}
else {
- $spin_published_within->show;
- }
-
- spin_published_within_changed();
-}
-
-sub spin_published_within_changed {
- my $period = $published_within_combobox->get_active_text;
-
- if ($period =~ /^any/) {
- $yv_obj->set_publishedAfter(undef);
- }
- else {
- my $amount = $spin_published_within->get_value;
- my $date = $yv_utils->period_to_date($amount, $period);
- $yv_obj->set_publishedAfter($date);
+ $yv_obj->set_date($period);
}
}
@@ -2030,8 +2009,8 @@ sub set_youtube_tops {
}
sub remove_selected_user {
- my $selection = $users_treeview->get_selection // return;
- my $iter = $selection->get_selected // return;
+ my $selection = $users_treeview->get_selection // return;
+ my $iter = $selection->get_selected // return;
my $channel_id = $users_liststore->get($iter, 0);
delete $channels{$channel_id};
$users_liststore->remove($iter);
@@ -2278,8 +2257,6 @@ sub search {
append_to_history($keywords, 1);
}
- spin_published_within_changed();
-
# Set the username
my $username = $from_author_entry->get_text;
@@ -2513,7 +2490,8 @@ sub get_pixbuf_thumbnail_from_entry {
sub display_results {
my ($results, $from_history) = @_;
- my $url = $results->{url};
+ my $url = $results->{url};
+
#my $info = $results->{results} // {};
my $items = $results->{results} // [];
@@ -2538,11 +2516,10 @@ sub display_results {
my $current_instance = $yv_obj->get_api_host();
$yv_obj->pick_and_set_random_instance(); # set a random invidious instance
- die
- "Probably $current_instance is down.\n"
- . "\nTry changing the `api_host` in configuration file:\n\n"
- . qq{\tapi_host => "auto",\n}
- . qq{\nSee also: https://libregit.org/heckyel/fair-viewer#invidious-instances\n};
+ die "Probably $current_instance is down.\n"
+ . "\nTry changing the `api_host` in configuration file:\n\n"
+ . qq{\tapi_host => "auto",\n}
+ . qq{\nSee also: https://libregit.org/heckyel/fair-viewer#invidious-instances\n};
}
if (not $yv_utils->has_entries($results)) {
@@ -2555,68 +2532,68 @@ sub display_results {
#~ if (not $from_history) {
- #~ foreach my $entry (@$items) {
- #~ if ($yv_utils->is_activity($entry)) {
- #~ my $type = $entry->{snippet}{type};
-
- #~ if ($type eq 'upload') {
- #~ $entry->{kind} = 'youtube#video';
- #~ $entry->{id} = $entry->{contentDetails}{upload}{videoId};
- #~ }
-
- #~ if ($type eq 'playlistItem') {
- #~ $entry->{kind} = 'youtube#video';
- #~ $entry->{id} = $entry->{contentDetails}{playlistItem}{resourceId}{videoId};
- #~ }
-
- #~ if ($type eq 'subscription') {
- #~ $entry->{kind} = 'youtube#channel';
- #~ $entry->{snippet}{title} = $entry->{snippet}{channelTitle};
- #~ $entry->{snippet}{channelId} = $entry->{contentDetails}{subscription}{resourceId}{channelId};
- #~ }
-
- #~ if ($type eq 'bulletin' and $entry->{contentDetails}{bulletin}{resourceId}{kind} eq 'youtube#video') {
- #~ $entry->{kind} = 'youtube#video';
- #~ $entry->{id} = $entry->{contentDetails}{bulletin}{resourceId}{videoId};
- #~ }
- #~ }
- #~ }
+ #~ foreach my $entry (@$items) {
+ #~ if ($yv_utils->is_activity($entry)) {
+ #~ my $type = $entry->{snippet}{type};
- #~ my @video_ids;
- #~ my @playlist_ids;
+ #~ if ($type eq 'upload') {
+ #~ $entry->{kind} = 'youtube#video';
+ #~ $entry->{id} = $entry->{contentDetails}{upload}{videoId};
+ #~ }
- #~ foreach my $i (0 .. $#{$items}) {
- #~ my $item = $items->[$i];
+ #~ if ($type eq 'playlistItem') {
+ #~ $entry->{kind} = 'youtube#video';
+ #~ $entry->{id} = $entry->{contentDetails}{playlistItem}{resourceId}{videoId};
+ #~ }
- #~ if ($yv_utils->is_playlist($item)) {
- #~ push @playlist_ids, $yv_utils->get_playlist_id($item);
- #~ }
- #~ elsif ($yv_utils->is_video($item)) {
- #~ push @video_ids, $yv_utils->get_video_id($item);
- #~ }
- #~ }
+ #~ if ($type eq 'subscription') {
+ #~ $entry->{kind} = 'youtube#channel';
+ #~ $entry->{snippet}{title} = $entry->{snippet}{channelTitle};
+ #~ $entry->{snippet}{channelId} = $entry->{contentDetails}{subscription}{resourceId}{channelId};
+ #~ }
- #~ my %id_lookup;
+ #~ if ($type eq 'bulletin' and $entry->{contentDetails}{bulletin}{resourceId}{kind} eq 'youtube#video') {
+ #~ $entry->{kind} = 'youtube#video';
+ #~ $entry->{id} = $entry->{contentDetails}{bulletin}{resourceId}{videoId};
+ #~ }
+ #~ }
+ #~ }
- #~ if (@video_ids) {
- #~ my $content_details = $yv_obj->video_details(join(',', @video_ids), VIDEO_PART);
- #~ my $video_details = $content_details->{results}{items};
+ #~ my @video_ids;
+ #~ my @playlist_ids;
- #~ foreach my $i (0 .. $#video_ids) {
- #~ $id_lookup{$video_ids[$i]} = $video_details->[$i];
- #~ }
- #~ }
+ #~ foreach my $i (0 .. $#{$items}) {
+ #~ my $item = $items->[$i];
- #~ if (@playlist_ids) {
- #~ my $content_details = $yv_obj->playlist_from_id(join(',', @playlist_ids), 'contentDetails');
- #~ my $playlist_details = $content_details->{results}{items};
+ #~ if ($yv_utils->is_playlist($item)) {
+ #~ push @playlist_ids, $yv_utils->get_playlist_id($item);
+ #~ }
+ #~ elsif ($yv_utils->is_video($item)) {
+ #~ push @video_ids, $yv_utils->get_video_id($item);
+ #~ }
+ #~ }
- #~ foreach my $i (0 .. $#playlist_ids) {
- #~ $id_lookup{$playlist_ids[$i]} = $playlist_details->[$i];
- #~ }
- #~ }
+ #~ my %id_lookup;
- #~ $info->{__extra_info__} = \%id_lookup;
+ #~ if (@video_ids) {
+ #~ my $content_details = $yv_obj->video_details(join(',', @video_ids), VIDEO_PART);
+ #~ my $video_details = $content_details->{results}{items};
+
+ #~ foreach my $i (0 .. $#video_ids) {
+ #~ $id_lookup{$video_ids[$i]} = $video_details->[$i];
+ #~ }
+ #~ }
+
+ #~ if (@playlist_ids) {
+ #~ my $content_details = $yv_obj->playlist_from_id(join(',', @playlist_ids), 'contentDetails');
+ #~ my $playlist_details = $content_details->{results}{items};
+
+ #~ foreach my $i (0 .. $#playlist_ids) {
+ #~ $id_lookup{$playlist_ids[$i]} = $playlist_details->[$i];
+ #~ }
+ #~ }
+
+ #~ $info->{__extra_info__} = \%id_lookup;
#~ }
foreach my $i (0 .. $#{$items}) {
@@ -2627,8 +2604,8 @@ sub display_results {
#~ my $playlist_id = $yv_utils->get_playlist_id($item) || next;
#~ if (exists($info->{__extra_info__}{$playlist_id})) {
- #~ @{$item}{qw(contentDetails)} =
- #~ @{$info->{__extra_info__}{$playlist_id}}{qw(contentDetails)};
+ #~ @{$item}{qw(contentDetails)} =
+ #~ @{$info->{__extra_info__}{$playlist_id}}{qw(contentDetails)};
#~ }
add_playlist_entry($item);
@@ -2644,8 +2621,8 @@ sub display_results {
#~ my $video_id = $yv_utils->get_video_id($item) || next;
#~ if (exists($info->{__extra_info__}{$video_id})) {
- #~ @{$item}{qw(id contentDetails statistics snippet)} =
- #~ @{$info->{__extra_info__}{$video_id}}{qw(id contentDetails statistics snippet)};
+ #~ @{$item}{qw(id contentDetails statistics snippet)} =
+ #~ @{$info->{__extra_info__}{$video_id}}{qw(id contentDetails statistics snippet)};
#~ }
# Filter out private or deleted videos
@@ -2668,7 +2645,7 @@ sub display_results {
if (ref($results->{results}) eq 'HASH' and exists($results->{results}{continuation})) {
if (defined $results->{results}{continuation}) {
- append_next_page($url, $results->{results}{continuation});
+ append_next_page($url, $results->{results}{continuation});
}
}
else {
@@ -3017,12 +2994,12 @@ sub get_streaming_url {
if (ref($captions) eq 'ARRAY' and @$captions and $CONFIG{get_captions}) {
require WWW::FairViewer::GetCaption;
my $yv_cap = WWW::FairViewer::GetCaption->new(
- auto_captions => $CONFIG{auto_captions},
- captions_dir => $CONFIG{cache_dir},
- captions => $captions,
- languages => $CONFIG{srt_languages},
- yv_obj => $yv_obj,
- );
+ auto_captions => $CONFIG{auto_captions},
+ captions_dir => $CONFIG{cache_dir},
+ captions => $captions,
+ languages => $CONFIG{srt_languages},
+ yv_obj => $yv_obj,
+ );
$srt_file = $yv_cap->save_caption($video_id);
}
@@ -3205,10 +3182,10 @@ sub get_options_as_arguments {
'no-interactive' => q{},
'resolution' => $CONFIG{resolution},
'download-dir' => quotemeta(rel2abs($CONFIG{downloads_dir})),
- 'fullscreen' => $CONFIG{fullscreen} ? q{} : undef,
+ 'fullscreen' => $CONFIG{fullscreen} ? q{} : undef,
'no-dash' => $CONFIG{dash_support} ? undef : q{},
- 'no-video' => $CONFIG{audio_only} ? q{} : undef,
- 'resolution=audio' => $CONFIG{audio_only} ? q{} : undef,
+ 'no-video' => $CONFIG{audio_only} ? q{} : undef,
+ 'resolution=audio' => $CONFIG{audio_only} ? q{} : undef,
);
while (my ($argv, $value) = each %options) {
@@ -3312,7 +3289,7 @@ sub execute_cli_fair_viewer {
$CONFIG{terminal_exec},
join(q{ },
$CONFIG{fair_viewer}, get_options_as_arguments(),
- @arguments, @{$CONFIG{fair_viewer_args}}),
+ @arguments, @{$CONFIG{fair_viewer_args}}),
)
);
my $code = execute_external_program($command);
@@ -3411,9 +3388,9 @@ sub display_comments {
return 1 if ref($results) ne 'HASH';
- my $url = $results->{url};
- my $video_id = $results->{results}{videoId};
- my $comments = $results->{results}{comments} // [];
+ my $url = $results->{url};
+ my $video_id = $results->{results}{videoId};
+ my $comments = $results->{results}{comments} // [];
my $continuation = $results->{results}{continuation};
foreach my $comment (@{$comments}) {
@@ -3422,7 +3399,7 @@ sub display_comments {
#pp $comment;
#my $comment_age = $yv_utils->date_to_age($snippet->{publishedAt});
- my $comment_id = $yv_utils->get_comment_id($comment);
+ my $comment_id = $yv_utils->get_comment_id($comment);
my $comment_age = $yv_utils->get_publication_age_approx($comment);
my $comment_text = reflow_text(
@@ -3436,12 +3413,12 @@ sub display_comments {
)
. ") commented:</big>\n"
. encode_entities(
- wrap_text(
- i_tab => "\t",
- s_tab => "\t",
- text => [$yv_utils->get_comment_content($comment) // 'Empty comment...'],
- )
- )
+ wrap_text(
+ i_tab => "\t",
+ s_tab => "\t",
+ text => [$yv_utils->get_comment_content($comment) // 'Empty comment...'],
+ )
+ )
);
my $iter = $feeds_liststore->append;
@@ -3453,39 +3430,39 @@ sub display_comments {
);
#~ if (exists $comment->{replies}) {
- #~ foreach my $reply (reverse @{$comment->{replies}{comments}}) {
- #~ my $reply_age = $yv_utils->date_to_age($reply->{snippet}{publishedAt});
- #~ my $reply_text = reflow_text(
- #~ "\t<big><b>"
- #~ . encode_entities($reply->{snippet}{authorDisplayName})
- #~ . "</b> ("
- #~ . (
- #~ $reply_age =~ /sec|min|hour|day/
- #~ ? "$reply_age ago"
- #~ : $yv_utils->format_date($reply->{snippet}{publishedAt})
- #~ )
- #~ . ") replied:</big>\n"
- #~ . encode_entities(
- #~ wrap_text(
- #~ i_tab => "\t\t",
- #~ s_tab => "\t\t",
- #~ text => [$reply->{snippet}{textDisplay} // 'Empty comment...']
- #~ )
- #~ )
- #~ );
-
- #~ my $iter = $feeds_liststore->append;
- #~ $feeds_liststore->set(
- #~ $iter,
- #~ 0 => $reply_text,
- #~ 3 => $reply->{snippet}{videoId},
- #~ 4 => $reply->{id},
- #~ );
- #~ }
+ #~ foreach my $reply (reverse @{$comment->{replies}{comments}}) {
+ #~ my $reply_age = $yv_utils->date_to_age($reply->{snippet}{publishedAt});
+ #~ my $reply_text = reflow_text(
+ #~ "\t<big><b>"
+ #~ . encode_entities($reply->{snippet}{authorDisplayName})
+ #~ . "</b> ("
+ #~ . (
+ #~ $reply_age =~ /sec|min|hour|day/
+ #~ ? "$reply_age ago"
+ #~ : $yv_utils->format_date($reply->{snippet}{publishedAt})
+ #~ )
+ #~ . ") replied:</big>\n"
+ #~ . encode_entities(
+ #~ wrap_text(
+ #~ i_tab => "\t\t",
+ #~ s_tab => "\t\t",
+ #~ text => [$reply->{snippet}{textDisplay} // 'Empty comment...']
+ #~ )
+ #~ )
+ #~ );
+
+ #~ my $iter = $feeds_liststore->append;
+ #~ $feeds_liststore->set(
+ #~ $iter,
+ #~ 0 => $reply_text,
+ #~ 3 => $reply->{snippet}{videoId},
+ #~ 4 => $reply->{id},
+ #~ );
+ #~ }
#~ }
}
- if (defined $continuation) {
+ if (defined $continuation) {
my $iter = $feeds_liststore->append;
$feeds_liststore->set(
$iter,
@@ -3618,10 +3595,10 @@ sub set_entry_details {
my $info = $yv_obj->parse_json_string($liststore->get($iter, 8));
my %thumbs = (
- start => 1,
- middle => 2,
- end => 3,
- );
+ start => 1,
+ middle => 2,
+ end => 3,
+ );
# Getting thumbs
foreach my $type (keys %thumbs) {
@@ -3634,18 +3611,18 @@ sub set_entry_details {
my $url = $yv_utils->get_thumbnail_url($info, $type);
- #~ my $thumbnail = $info->{snippet}{thumbnails}{medium};
- #~ my $url = $thumbnail->{url};
+ #~ my $thumbnail = $info->{snippet}{thumbnails}{medium};
+ #~ my $url = $thumbnail->{url};
- if ($url =~ /_live\.\w+\z/) {
- ## no extra thumbnails available while video is LIVE
- }
- else {
- $url =~ s{/\w+\.(\w+)\z}{/mq$thumbs{$type}.$1};
- }
+ if ($url =~ /_live\.\w+\z/) {
+ ## no extra thumbnails available while video is LIVE
+ }
+ else {
+ $url =~ s{/\w+\.(\w+)\z}{/mq$thumbs{$type}.$1};
+ }
- my $pixbuf = get_pixbuf_thumbnail_from_url($url, 160, 90);
- $gui->get_object("image$thumbs{$type}")->set_from_pixbuf($pixbuf);
+ my $pixbuf = get_pixbuf_thumbnail_from_url($url, 160, 90);
+ $gui->get_object("image$thumbs{$type}")->set_from_pixbuf($pixbuf);
return 0;
},
diff --git a/lib/WWW/FairViewer.pm b/lib/WWW/FairViewer.pm
index 4e3bed8..5657c4c 100644
--- a/lib/WWW/FairViewer.pm
+++ b/lib/WWW/FairViewer.pm
@@ -46,34 +46,33 @@ our $VERSION = '1.0.4';
my %valid_options = (
# Main options
- v => {valid => q[], default => 3},
- page => {valid => qr/^(?!0+\z)\d+\z/, default => 1},
- http_proxy => {valid => qr/./, default => undef},
- hl => {valid => qr/^\w+(?:[\-_]\w+)?\z/, default => undef},
- maxResults => {valid => [1 .. 50], default => 10},
- topicId => {valid => qr/./, default => undef},
- order => {valid => [qw(relevance date rating viewCount title videoCount)], default => undef},
- publishedAfter => {valid => qr/^\d+/, default => undef},
- publishedBefore => {valid => qr/^\d+/, default => undef},
- channelId => {valid => qr/^[-\w]{2,}\z/, default => undef},
- channelType => {valid => [qw(any show)], default => undef},
+ v => {valid => q[], default => 3},
+ page => {valid => qr/^(?!0+\z)\d+\z/, default => 1},
+ http_proxy => {valid => qr/./, default => undef},
+ hl => {valid => qr/^\w+(?:[\-_]\w+)?\z/, default => undef},
+ maxResults => {valid => [1 .. 50], default => 10},
+ order => {valid => [qw(relevance rating upload_date view_count)], default => undef},
+ date => {valid => [qw(hour today week month year)], default => undef},
+
+ channelId => {valid => qr/^[-\w]{2,}\z/, default => undef},
+ channelType => {valid => [qw(any show)], default => undef},
# Video only options
- videoCaption => {valid => [qw(any closedCaption none)], default => undef},
- videoDefinition => {valid => [qw(any high standard)], default => undef},
- videoCategoryId => {valid => qr/^\d+\z/, default => undef},
- videoDimension => {valid => [qw(any 2d 3d)], default => undef},
- videoDuration => {valid => [qw(any short medium long)], default => undef},
- videoEmbeddable => {valid => [qw(any true)], default => undef},
- videoLicense => {valid => [qw(any creativeCommon youtube)], default => undef},
- videoSyndicated => {valid => [qw(any true)], default => undef},
- eventType => {valid => [qw(completed live upcoming)], default => undef},
- chart => {valid => [qw(mostPopular)], default => 'mostPopular'},
-
- regionCode => {valid => qr/^[A-Z]{2}\z/i, default => undef},
+ videoCaption => {valid => [qw(1 true)], default => undef},
+ videoDefinition => {valid => [qw(high standard)], default => undef},
+ videoCategoryId => {valid => qr/^\d+\z/, default => undef},
+ videoDimension => {valid => [qw(2d 3d)], default => undef},
+ videoDuration => {valid => [qw(short long)], default => undef},
+ videoEmbeddable => {valid => [qw(true)], default => undef},
+ videoLicense => {valid => [qw(creative_commons)], default => undef},
+ videoSyndicated => {valid => [qw(true)], default => undef},
+ eventType => {valid => [qw(completed live upcoming)], default => undef},
+ chart => {valid => [qw(mostPopular)], default => 'mostPopular'},
+
+ region => {valid => qr/^[A-Z]{2}\z/i, default => undef},
relevanceLanguage => {valid => qr/^[a-z]+(?:\-\w+)?\z/i, default => undef},
safeSearch => {valid => [qw(none moderate strict)], default => undef},
- videoType => {valid => [qw(any episode movie)], default => undef},
+ videoType => {valid => [qw(episode movie)], default => undef},
comments_order => {valid => [qw(top new)], default => 'top'},
subscriptions_order => {valid => [qw(alphabetical relevance unread)], default => undef},
@@ -669,7 +668,6 @@ sub default_arguments {
#part => 'snippet',
#prettyPrint => 'false',
#maxResults => $self->get_maxResults,
- #regionCode => $self->get_regionCode,
%args,
);
diff --git a/lib/WWW/FairViewer/GuideCategories.pm b/lib/WWW/FairViewer/GuideCategories.pm
index 34d0a1d..a348abb 100644
--- a/lib/WWW/FairViewer/GuideCategories.pm
+++ b/lib/WWW/FairViewer/GuideCategories.pm
@@ -22,7 +22,7 @@ sub _make_guideCategories_url {
my ($self, %opts) = @_;
if (not exists $opts{id}) {
- $opts{regionCode} //= $self->get_regionCode;
+ $opts{region} //= $self->get_region;
}
$self->_make_feed_url('guideCategories', hl => $self->get_hl, %opts);
@@ -47,7 +47,7 @@ Return info for a list of comma-separated category IDs.
name => 'guide_categories_info',
},
{
- key => 'regionCode',
+ key => 'region',
name => 'guide_categories',
},
) {
diff --git a/lib/WWW/FairViewer/Search.pm b/lib/WWW/FairViewer/Search.pm
index 8e8162c..af6005b 100644
--- a/lib/WWW/FairViewer/Search.pm
+++ b/lib/WWW/FairViewer/Search.pm
@@ -21,43 +21,46 @@ WWW::FairViewer::Search - Search functions for Fair API v3
sub _make_search_url {
my ($self, %opts) = @_;
+ my @features;
+
+ if (defined(my $vd = $self->get_videoDefinition)) {
+ if ($vd eq 'high') {
+ push @features, 'hd';
+ }
+ }
+
+ if (defined(my $vc = $self->get_videoCaption)) {
+ if ($vc eq 'true' or $vc eq '1') {
+ push @features, 'subtitles';
+ }
+ }
+
+ if (defined(my $vd = $self->get_videoDimension)) {
+ if ($vd eq '3d') {
+ push @features, '3d';
+ }
+ }
+
+ if (defined(my $license = $self->get_videoLicense)) {
+ if ($license eq 'creative_commons') {
+ push @features, 'creative_commons';
+ }
+ }
+
return $self->_make_feed_url(
'search',
- topicId => $self->get_topicId,
- regionCode => $self->get_regionCode,
-
- maxResults => $self->get_maxResults,
- order => $self->get_order,
- publishedAfter => $self->get_publishedAfter,
- publishedBefore => $self->get_publishedBefore,
- regionCode => $self->get_regionCode,
- relevanceLanguage => $self->get_relevanceLanguage,
- safeSearch => $self->get_safeSearch,
- channelId => $self->get_channelId,
- channelType => $self->get_channelType,
- pageToken => $self->page_token,
-
- (
- $opts{type} eq 'video'
- ? (
- videoCaption => $self->get_videoCaption,
- videoCategoryId => $self->get_videoCategoryId,
- videoDefinition => $self->get_videoDefinition,
- videoDimension => $self->get_videoDimension,
- videoDuration => $self->get_videoDuration,
- videoEmbeddable => $self->get_videoEmbeddable,
- videoLicense => $self->get_videoLicense,
- videoSyndicated => $self->get_videoSyndicated,
- videoType => $self->get_videoType,
- eventType => $self->get_eventType,
- )
- : ()
- ),
+ region => $self->get_region,
+ sort_by => $self->get_order,
+ date => $self->get_date,
+ channelId => $self->get_channelId,
+ pageToken => $self->page_token,
+ duration => $self->get_videoDuration,
+
+ (@features ? (features => join(',', @features)) : ()),
%opts,
);
-
}
=head2 search_for($types,$keywords;\%args)
@@ -146,19 +149,21 @@ be set to a YouTube video ID.
sub related_to_videoID {
my ($self, $videoID) = @_;
- my %info = $self->_get_video_info($videoID);
+ my %info = $self->_get_video_info($videoID);
my $watch_next_response = $self->parse_json_string($info{watch_next_response});
- my $related = eval { $watch_next_response->{contents}{twoColumnWatchNextResults}{secondaryResults}{secondaryResults}{results} } // return { results => []};
+ my $related =
+ eval { $watch_next_response->{contents}{twoColumnWatchNextResults}{secondaryResults}{secondaryResults}{results} }
+ // return {results => []};
#use Data::Dump qw(pp);
#pp $related;
my @results;
- foreach my $entry(@$related) {
+ foreach my $entry (@$related) {
- my $info = $entry->{compactVideoRenderer} // next;
- my $title = $info->{title}{simpleText} // next;
+ my $info = $entry->{compactVideoRenderer} // next;
+ my $title = $info->{title}{simpleText} // next;
my $viewCount = 0;
@@ -166,39 +171,39 @@ sub related_to_videoID {
$viewCount = ($1 =~ tr/,//dr);
}
elsif ($info->{viewCountText}{simpleText} =~ /Recommended for you/i) {
- next; # filter out recommended videos from related videos
+ next; # filter out recommended videos from related videos
}
my $lengthSeconds = 0;
if ($info->{lengthText}{simpleText} =~ /([\d:]+)/) {
- my $time = $1;
+ my $time = $1;
my @fields = split(/:/, $time);
my $seconds = pop(@fields) // 0;
my $minutes = pop(@fields) // 0;
- my $hours = pop(@fields) // 0;
+ my $hours = pop(@fields) // 0;
- $lengthSeconds = 3600 * $hours + 60*$minutes + $seconds;
+ $lengthSeconds = 3600 * $hours + 60 * $minutes + $seconds;
}
my $published = 0;
if (exists $info->{publishedTimeText} and $info->{publishedTimeText}{simpleText} =~ /(\d+)\s+(\w+)\s+ago/) {
my $quantity = $1;
- my $period = $2;
+ my $period = $2;
- $period =~ s/s\z//; # make it singural
+ $period =~ s/s\z//; # make it singural
my %table = (
- year => 31556952, # seconds in a year
- month => 2629743.83, # seconds in a month
- week => 604800, # seconds in a week
- day => 86400, # seconds in a day
- hour => 3600, # seconds in a hour
- minute => 60, # seconds in a minute
- second => 1, # seconds in a second
- );
+ year => 31556952, # seconds in a year
+ month => 2629743.83, # seconds in a month
+ week => 604800, # seconds in a week
+ day => 86400, # seconds in a day
+ hour => 3600, # seconds in a hour
+ minute => 60, # seconds in a minute
+ second => 1, # seconds in a second
+ );
if (exists $table{$period}) {
$published = int(time - $quantity * $table{$period});
@@ -209,40 +214,42 @@ sub related_to_videoID {
}
push @results, {
- type => "video",
- title => $title,
- videoId => $info->{videoId},
- author => $info->{longBylineText}{runs}[0]{text},
+ type => "video",
+ title => $title,
+ videoId => $info->{videoId},
+ author => $info->{longBylineText}{runs}[0]{text},
authorId => $info->{longBylineText}{runs}[0]{navigationEndpoint}{browseEndpoint}{browseId},
+
#authorUrl => $info->{longBylineText}{runs}[0]{navigationEndpoint}{browseEndpoint}{browseId},
- description => $info->{accessibility}{accessibilityData}{label},
+ description => $info->{accessibility}{accessibilityData}{label},
descriptionHtml => undef,
- viewCount => $viewCount,
- published => $published,
- publishedText => $info->{publishedTimeText}{simpleText},
- lengthSeconds => $lengthSeconds,
- liveNow => ($lengthSeconds == 0), # maybe it's live if lengthSeconds == 0?
- paid => 0,
- premium => 0,
+ viewCount => $viewCount,
+ published => $published,
+ publishedText => $info->{publishedTimeText}{simpleText},
+ lengthSeconds => $lengthSeconds,
+ liveNow => ($lengthSeconds == 0), # maybe it's live if lengthSeconds == 0?
+ paid => 0,
+ premium => 0,
videoThumbnails => [
map {
scalar {
- quality => 'medium',
- url => $_->{url},
- width => $_->{width},
- height => $_->{height},
- }
+ quality => 'medium',
+ url => $_->{url},
+ width => $_->{width},
+ height => $_->{height},
+ }
} @{$info->{thumbnail}{thumbnails}}
],
};
}
- return scalar {
- url => undef,
- results => \@results,
- };
+ return
+ scalar {
+ url => undef,
+ results => \@results,
+ };
}
=head1 AUTHOR
diff --git a/lib/WWW/FairViewer/VideoCategories.pm b/lib/WWW/FairViewer/VideoCategories.pm
index ecca0c2..85045fd 100644
--- a/lib/WWW/FairViewer/VideoCategories.pm
+++ b/lib/WWW/FairViewer/VideoCategories.pm
@@ -39,8 +39,8 @@ sub video_categories {
require File::Spec;
- my $region = $self->get_regionCode() // 'US';
- my $url = $self->_make_videoCategories_url(regionCode => $region);
+ my $region = $self->get_region() // 'US';
+ my $url = $self->_make_videoCategories_url(region => $region);
my $file = File::Spec->catfile($self->get_config_dir, "categories-$region-" . $self->get_hl() . ".json");
my $json;
diff --git a/lib/WWW/FairViewer/Videos.pm b/lib/WWW/FairViewer/Videos.pm
index da6af0b..a0f5e1b 100644
--- a/lib/WWW/FairViewer/Videos.pm
+++ b/lib/WWW/FairViewer/Videos.pm
@@ -74,12 +74,7 @@ sub trending_videos_from_category {
my ($self, $cat_id) = @_;
my $results = do {
- local $self->{publishedAfter} = do {
- state $yv_utils = WWW::FairViewer::Utils->new;
- $yv_utils->period_to_date(1, 'w');
- } if !defined($self->get_publishedAfter);
local $self->{videoCategoryId} = $cat_id;
- local $self->{regionCode} = "US" if !defined($self->get_regionCode);
$self->search_videos("");
};
diff --git a/share/gtk-fair-viewer.glade b/share/gtk-fair-viewer.glade
index 9b9edc0..48b3a05 100644
--- a/share/gtk-fair-viewer.glade
+++ b/share/gtk-fair-viewer.glade
@@ -986,11 +986,9 @@ Author: Jesus E. https://framagit.org/heckyel
<property name="active">0</property>
<items>
<item translatable="yes">relevance</item>
- <item translatable="yes">title</item>
<item translatable="yes">rating</item>
- <item translatable="yes">date</item>
- <item translatable="yes">videoCount</item>
- <item translatable="yes">viewCount</item>
+ <item translatable="yes">upload_date</item>
+ <item translatable="yes">view_count</item>
</items>
<signal name="changed" handler="combobox_order_changed" swapped="no"/>
</object>
@@ -1041,7 +1039,6 @@ long – longer than 20 minutes</property>
<items>
<item translatable="yes">any</item>
<item translatable="yes">short</item>
- <item translatable="yes">medium</item>
<item translatable="yes">long</item>
</items>
<signal name="changed" handler="combobox_duration_changed" swapped="no"/>
@@ -1082,8 +1079,7 @@ long – longer than 20 minutes</property>
<property name="active">0</property>
<items>
<item translatable="yes">any</item>
- <item translatable="yes">closedCaption</item>
- <item translatable="yes">none</item>
+ <item translatable="yes">true</item>
</items>
<signal name="changed" handler="combobox_caption_changed" swapped="no"/>
</object>
@@ -1124,7 +1120,6 @@ long – longer than 20 minutes</property>
<items>
<item translatable="yes">any</item>
<item translatable="yes">high</item>
- <item translatable="yes">standard</item>
</items>
<signal name="changed" handler="combobox_definition_changed" swapped="no"/>
</object>
@@ -1305,36 +1300,16 @@ Recommended: 10</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
- <object class="GtkSpinButton" id="spinbutton3">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">•</property>
- <property name="caps_lock_warning">False</property>
- <property name="primary_icon_activatable">False</property>
- <property name="secondary_icon_activatable">False</property>
- <property name="adjustment">adjustment3</property>
- <property name="climb_rate">1</property>
- <property name="numeric">True</property>
- <property name="update_policy">if-valid</property>
- <signal name="activate" handler="search" swapped="no"/>
- <signal name="value-changed" handler="spin_published_within_changed" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
<object class="GtkComboBoxText" id="comboboxtext1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<items>
<item translatable="yes">anytime</item>
- <item translatable="yes">days</item>
- <item translatable="yes">weeks</item>
- <item translatable="yes">months</item>
- <item translatable="yes">years</item>
+ <item translatable="yes">hour</item>
+ <item translatable="yes">today</item>
+ <item translatable="yes">week</item>
+ <item translatable="yes">month</item>
+ <item translatable="yes">year</item>
</items>
<signal name="changed" handler="combobox_published_within_changed" swapped="no"/>
</object>