aboutsummaryrefslogtreecommitdiffstats
path: root/bin/fair-viewer
diff options
context:
space:
mode:
Diffstat (limited to 'bin/fair-viewer')
-rwxr-xr-xbin/fair-viewer289
1 files changed, 135 insertions, 154 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;