aboutsummaryrefslogtreecommitdiffstats
path: root/lib/WWW/StrawViewer
diff options
context:
space:
mode:
Diffstat (limited to 'lib/WWW/StrawViewer')
-rw-r--r--lib/WWW/StrawViewer/Activities.pm93
-rw-r--r--lib/WWW/StrawViewer/Authentication.pm216
-rw-r--r--lib/WWW/StrawViewer/Channels.pm200
-rw-r--r--lib/WWW/StrawViewer/CommentThreads.pm98
-rw-r--r--lib/WWW/StrawViewer/GetCaption.pm280
-rw-r--r--lib/WWW/StrawViewer/GuideCategories.pm85
-rw-r--r--lib/WWW/StrawViewer/Itags.pm319
-rw-r--r--lib/WWW/StrawViewer/ParseJSON.pm76
-rw-r--r--lib/WWW/StrawViewer/ParseXML.pm311
-rw-r--r--lib/WWW/StrawViewer/PlaylistItems.pm146
-rw-r--r--lib/WWW/StrawViewer/Playlists.pm124
-rw-r--r--lib/WWW/StrawViewer/RegularExpressions.pm89
-rw-r--r--lib/WWW/StrawViewer/Search.pm175
-rw-r--r--lib/WWW/StrawViewer/Subscriptions.pm272
-rw-r--r--lib/WWW/StrawViewer/Utils.pm801
-rw-r--r--lib/WWW/StrawViewer/VideoCategories.pm97
-rw-r--r--lib/WWW/StrawViewer/Videos.pm230
17 files changed, 0 insertions, 3612 deletions
diff --git a/lib/WWW/StrawViewer/Activities.pm b/lib/WWW/StrawViewer/Activities.pm
deleted file mode 100644
index 39a6a3d..0000000
--- a/lib/WWW/StrawViewer/Activities.pm
+++ /dev/null
@@ -1,93 +0,0 @@
-package WWW::StrawViewer::Activities;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Activities - list of channel activity events that match the request criteria.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $activities = $obj->activities($channel_id);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_activities_url {
- my ($self, %opts) = @_;
- $self->_make_feed_url('activities', part => 'snippet,contentDetails', %opts);
-}
-
-=head2 activities($channel_id)
-
-Get activities for channel ID.
-
-=cut
-
-sub activities {
- my ($self, $channel_id) = @_;
-
- if ($channel_id eq 'mine') {
- return $self->my_activities;
- }
-
- if ($channel_id !~ /^UC/) {
- $channel_id = $self->channel_id_from_username($channel_id) // $channel_id;
- }
-
- $self->_get_results($self->_make_activities_url(channelId => $channel_id));
-}
-
-=head2 activities_from_username($username)
-
-Get activities for username.
-
-=cut
-
-sub activities_from_username {
- my ($self, $username) = @_;
- return $self->activities($username);
-}
-
-=head2 my_activities()
-
-Get authenticated user's activities.
-
-=cut
-
-sub my_activities {
- my ($self) = @_;
- $self->get_access_token() // return;
- $self->_get_results($self->_make_activities_url(mine => 'true'));
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Activities
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Activities
diff --git a/lib/WWW/StrawViewer/Authentication.pm b/lib/WWW/StrawViewer/Authentication.pm
deleted file mode 100644
index 1fa2368..0000000
--- a/lib/WWW/StrawViewer/Authentication.pm
+++ /dev/null
@@ -1,216 +0,0 @@
-package WWW::StrawViewer::Authentication;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Authentication - OAuth login support.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $hash_ref = WWW::StrawViewer->oauth_login($code);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _get_token_oauth_url {
- my ($self) = @_;
- return $self->get_oauth_url() . 'token';
-}
-
-=head2 oauth_refresh_token()
-
-Refresh the access_token using the refresh_token. Returns a HASH ref with the `access_token` or undef.
-
-=cut
-
-sub oauth_refresh_token {
- my ($self) = @_;
-
- my $json_data = $self->lwp_post(
- $self->_get_token_oauth_url(),
- [Content => $self->get_www_content_type,
- client_id => $self->get_client_id() // return,
- client_secret => $self->get_client_secret() // return,
- refresh_token => $self->get_refresh_token() // return,
- grant_type => 'refresh_token',
- ]
- );
-
- return $self->parse_json_string($json_data);
-}
-
-=head2 get_accounts_oauth_url()
-
-Creates an OAuth URL with the 'code' response type. (Google's authorization server)
-
-=cut
-
-sub get_accounts_oauth_url {
- my ($self) = @_;
-
- my $url = $self->_append_url_args(
- ($self->get_oauth_url() . 'auth'),
- response_type => 'code',
- client_id => $self->get_client_id() // return,
- redirect_uri => $self->get_redirect_uri() // return,
- scope => 'https://www.googleapis.com/auth/youtube.force-ssl',
- access_type => 'offline',
- );
- return $url;
-}
-
-=head2 oauth_login($code)
-
-Returns a HASH ref with the access_token, refresh_token and some other info.
-
-The $code can be obtained by going to the URL returned by the C<get_accounts_oauth_url()> method.
-
-=cut
-
-sub oauth_login {
- my ($self, $code) = @_;
-
- length($code) < 20 and return;
-
- my $json_data = $self->lwp_post(
- $self->_get_token_oauth_url(),
- [Content => $self->get_www_content_type,
- client_id => $self->get_client_id() // return,
- client_secret => $self->get_client_secret() // return,
- redirect_uri => $self->get_redirect_uri() // return,
- grant_type => 'authorization_code',
- code => $code,
- ]
- );
-
- return $self->parse_json_string($json_data);
-}
-
-sub __AUTH_EOL__() { "\0\0\0" }
-
-=head2 load_authentication_tokens()
-
-Will try to load the access and refresh tokens from I<authentication_file>.
-
-=cut
-
-sub load_authentication_tokens {
- my ($self) = @_;
-
- if (defined $self->get_access_token and defined $self->get_refresh_token) {
- return 1;
- }
-
- my $file = $self->get_authentication_file() // return;
- my $key = $self->get_key() // return;
-
- if (-f $file) {
- local $/ = __AUTH_EOL__;
- open my $fh, '<:raw', $file or return;
-
- my @tokens;
- foreach my $i (0 .. 1) {
- chomp(my $token = <$fh>);
- $token =~ /\S/ || last;
- push @tokens, $self->decode_token($token);
- }
-
- $self->set_access_token($tokens[0]) // return;
- $self->set_refresh_token($tokens[1]) // return;
-
- close $fh;
- return 1;
- }
-
- return;
-}
-
-=head2 encode_token($token)
-
-Encode the token with the I<key> and return it.
-
-=cut
-
-sub encode_token {
- my ($self, $token) = @_;
-
- if (defined(my $key = $self->get_key)) {
- require MIME::Base64;
- return MIME::Base64::encode_base64($token ^ substr($key, -length($token)));
- }
-
- return;
-}
-
-=head2 decode_token($token)
-
-Decode the token with the I<key> and return it.
-
-=cut
-
-sub decode_token {
- my ($self, $token) = @_;
-
- if (defined(my $key = $self->get_key)) {
- require MIME::Base64;
- my $bin = MIME::Base64::decode_base64($token);
- return $bin ^ substr($key, -length($bin));
- }
-
- return;
-}
-
-=head2 save_authentication_tokens()
-
-Encode and save the access and refresh into the I<authentication_file>.
-
-=cut
-
-sub save_authentication_tokens {
- my ($self) = @_;
-
- my $file = $self->get_authentication_file() // return;
- my $access_token = $self->get_access_token() // return;
- my $refresh_token = $self->get_refresh_token() // return;
-
- if (open my $fh, '>:raw', $file) {
- foreach my $token ($access_token, $refresh_token) {
- print {$fh} $self->encode_token($token) . __AUTH_EOL__;
- }
- close $fh;
- return 1;
- }
-
- return;
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Authentication
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Authentication
diff --git a/lib/WWW/StrawViewer/Channels.pm b/lib/WWW/StrawViewer/Channels.pm
deleted file mode 100644
index b2c2c99..0000000
--- a/lib/WWW/StrawViewer/Channels.pm
+++ /dev/null
@@ -1,200 +0,0 @@
-package WWW::StrawViewer::Channels;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Channels - Channels interface.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $videos = $obj->channels_from_categoryID($category_id);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_channels_url {
- my ($self, %opts) = @_;
- return $self->_make_feed_url('channels', %opts);
-}
-
-sub videos_from_channel_id {
- my ($self, $channel_id) = @_;
- return $self->_get_results($self->_make_feed_url("channels/$channel_id/videos"));
-}
-
-sub videos_from_username {
- my ($self, $channel_id) = @_;
- return $self->_get_results($self->_make_feed_url("channels/$channel_id/videos"));
-}
-
-=head2 channels_from_categoryID($category_id)
-
-Return the YouTube channels associated with the specified category.
-
-=head2 channels_info($channel_id)
-
-Return information for the comma-separated list of the YouTube channel ID(s).
-
-=head1 Channel details
-
-For all functions, C<$channels->{results}{items}> contains:
-
-=cut
-
-{
- no strict 'refs';
-
- foreach my $method (
- {
- key => 'categoryId',
- name => 'channels_from_guide_category',
- },
- {
- key => 'id',
- name => 'channels_info',
- },
- {
- key => 'forUsername',
- name => 'channels_from_username',
- },
- ) {
- *{__PACKAGE__ . '::' . $method->{name}} = sub {
- my ($self, $channel_id) = @_;
- return $self->_get_results($self->_make_channels_url($method->{key} => $channel_id));
- };
- }
-
- foreach my $part (qw(id contentDetails statistics topicDetails)) {
- *{__PACKAGE__ . '::' . 'channels_' . $part} = sub {
- my ($self, $id) = @_;
- return $self->_get_results($self->_make_channels_url(id => $id, part => $part));
- };
- }
-}
-
-=head2 my_channel()
-
-Returns info about the channel of the current authenticated user.
-
-=cut
-
-sub my_channel {
- my ($self) = @_;
- $self->get_access_token() // return;
- return $self->_get_results($self->_make_channels_url(part => 'snippet', mine => 'true'));
-}
-
-=head2 my_channel_id()
-
-Returns the channel ID of the current authenticated user.
-
-=cut
-
-sub my_channel_id {
- my ($self) = @_;
-
- state $cache = {};
-
- if (exists $cache->{id}) {
- return $cache->{id};
- }
-
- $cache->{id} = undef;
- my $channel = $self->my_channel() // return;
- $cache->{id} = $channel->{results}{items}[0]{id} // return;
-}
-
-=head2 channels_my_subscribers()
-
-Retrieve a list of channels that subscribed to the authenticated user's channel.
-
-=cut
-
-sub channels_my_subscribers {
- my ($self) = @_;
- $self->get_access_token() // return;
- return $self->_get_results($self->_make_channels_url(mySubscribers => 'true'));
-}
-
-=head2 channel_id_from_username($username)
-
-Return the channel ID for an username.
-
-=cut
-
-sub channel_id_from_username {
- my ($self, $username) = @_;
-
- state $username_lookup = {};
-
- if (exists $username_lookup->{$username}) {
- return $username_lookup->{$username};
- }
-
- $username_lookup->{$username} = undef;
- my $channel = $self->channels_from_username($username) // return;
- $username_lookup->{$username} = $channel->{results}{items}[0]{id} // return;
-}
-
-=head2 channel_title_from_id($channel_id)
-
-Return the channel title for a given channel ID.
-
-=cut
-
-sub channel_title_from_id {
- my ($self, $channel_id) = @_;
-
- if ($channel_id eq 'mine') {
- $channel_id = $self->my_channel_id();
- }
-
- my $info = $self->channels_info($channel_id // return) // return;
-
- ( ref($info) eq 'HASH'
- and ref($info->{results}) eq 'HASH'
- and ref($info->{results}{items}) eq 'ARRAY'
- and ref($info->{results}{items}[0]) eq 'HASH')
- ? $info->{results}{items}[0]{snippet}{title}
- : ();
-}
-
-=head2 channels_contentDetails($channelID)
-
-=head2 channels_statistics($channelID);
-
-=head2 channels_topicDetails($channelID)
-
-=cut
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Channels
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Channels
diff --git a/lib/WWW/StrawViewer/CommentThreads.pm b/lib/WWW/StrawViewer/CommentThreads.pm
deleted file mode 100644
index 1eba143..0000000
--- a/lib/WWW/StrawViewer/CommentThreads.pm
+++ /dev/null
@@ -1,98 +0,0 @@
-package WWW::StrawViewer::CommentThreads;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::CommentThreads - Retrieve comments threads.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $videos = $obj->comments_from_video_id($video_id);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_commentThreads_url {
- my ($self, %opts) = @_;
- return
- $self->_make_feed_url(
- 'commentThreads',
- pageToken => $self->page_token,
- %opts
- );
-}
-
-=head2 comments_from_videoID($videoID)
-
-Retrieve comments from a video ID.
-
-=cut
-
-sub comments_from_video_id {
- my ($self, $video_id) = @_;
- $self->_get_results(
- $self->_make_feed_url("comments/$video_id",
- sort_by => $self->get_comments_order,
- ),
- );
-}
-
-=head2 comment_to_video_id($comment, $videoID)
-
-Send a comment to a video ID.
-
-=cut
-
-sub comment_to_video_id {
- my ($self, $comment, $video_id) = @_;
-
- my $url = $self->_simple_feeds_url('commentThreads', part => 'snippet');
-
- my $hash = {
- "snippet" => {
-
- "topLevelComment" => {
- "snippet" => {
- "textOriginal" => $comment,
- }
- },
- "videoId" => $video_id,
-
- #"channelId" => $channel_id,
- },
- };
-
- $self->post_as_json($url, $hash);
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::CommentThreads
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2015-2016 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::CommentThreads
diff --git a/lib/WWW/StrawViewer/GetCaption.pm b/lib/WWW/StrawViewer/GetCaption.pm
deleted file mode 100644
index 81af4e2..0000000
--- a/lib/WWW/StrawViewer/GetCaption.pm
+++ /dev/null
@@ -1,280 +0,0 @@
-package WWW::StrawViewer::GetCaption;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::GetCaption - Save the YouTube closed captions as .srt files for a videoID.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer::GetCaption;
-
- my $yv_cap = WWW::StrawViewer::GetCaption->new(%opts);
-
- print $yv_cap->get_caption($videoID);
-
-=head1 SUBROUTINES/METHODS
-
-=head2 new(%opts)
-
-Options:
-
-=over 4
-
-=item captions => []
-
-The captions data.
-
-=item captions_dir => "."
-
-Where to save the closed captions.
-
-=item languages => [qw(en es ro jp)]
-
-Preferred languages. First found is saved and returned.
-
-=back
-
-=cut
-
-sub new {
- my ($class, %opts) = @_;
-
- my $self = bless {}, $class;
- $self->{captions_dir} = undef;
- $self->{captions} = [];
- $self->{auto_captions} = 0;
- $self->{languages} = [qw(en es)];
-
- foreach my $key (keys %{$self}) {
- $self->{$key} = delete $opts{$key}
- if exists $opts{$key};
- }
-
- foreach my $invalid_key (keys %opts) {
- warn "Invalid key: '${invalid_key}'";
- }
-
- return $self;
-}
-
-=head2 find_caption_data()
-
-Find a caption data, based on the preferred languages.
-
-=cut
-
-sub find_caption_data {
- my ($self) = @_;
-
- my @found;
- foreach my $caption (@{$self->{captions}}) {
- if (defined $caption->{languageCode}) {
- foreach my $i (0 .. $#{$self->{languages}}) {
- my $lang = $self->{languages}[$i];
- if ($caption->{languageCode} =~ /^\Q$lang\E(?:\z|[_-])/i) {
-
- # Automatic Speech Recognition
- my $auto = defined($caption->{kind}) && lc($caption->{kind}) eq 'asr';
-
- # Check against auto-generated captions
- if ($auto and not $self->{auto_captions}) {
- next;
- }
-
- # Fuzzy match or auto-generated caption
- if (lc($caption->{languageCode}) ne lc($lang) or $auto) {
- $found[$i + (($auto ? 2 : 1) * scalar(@{$self->{languages}}))] = $caption;
- }
-
- # Perfect match
- else {
- $i == 0 and return $caption;
- $found[$i] = $caption;
- }
- }
- }
- }
- }
-
- foreach my $caption (@found) {
- return $caption if defined($caption);
- }
-
- return;
-}
-
-=head2 sec2time(@seconds)
-
-Convert a list of seconds to .srt times.
-
-=cut
-
-sub sec2time {
- my $self = shift;
-
- my @out;
- foreach my $sec (map { sprintf '%.3f', $_ } @_) {
- push @out,
- sprintf('%02d:%02d:%02d,%03d', ($sec / 3600 % 24, $sec / 60 % 60, $sec % 60, substr($sec, index($sec, '.') + 1)));
- }
-
- return @out;
-}
-
-=head2 xml2srt($xml_string)
-
-Convert the XML data to SubRip format.
-
-=cut
-
-sub xml2srt {
- my ($self, $xml) = @_;
-
- require WWW::StrawViewer::ParseXML;
- my $hash = eval { WWW::StrawViewer::ParseXML::xml2hash($xml) } // return;
-
- my $sections;
- if ( exists $hash->{transcript}
- and ref($hash->{transcript}) eq 'ARRAY'
- and ref($hash->{transcript}[0]) eq 'HASH'
- and exists $hash->{transcript}[0]{text}) {
- $sections = $hash->{transcript}[0]{text};
- }
- else {
- return;
- }
-
- require HTML::Entities;
-
- my @text;
- foreach my $i (0 .. $#{$sections}) {
- my $line = $sections->[$i];
-
- if (not defined($line->{'-dur'})) {
- if (exists $sections->[$i + 1]) {
- $line->{'-dur'} = $sections->[$i + 1]{'-start'} - $line->{'-start'};
- }
- else {
- $line->{'-dur'} = 10;
- }
- }
-
- my $start = $line->{'-start'};
- my $end = $start + $line->{'-dur'};
-
- push @text,
- join("\n",
- $i + 1,
- join(' --> ', $self->sec2time($start, $end)),
- HTML::Entities::decode_entities($line->{'#text'} // ''));
- }
-
- return join("\n\n", @text);
-}
-
-=head2 get_xml_data($caption_data)
-
-Get the XML content for a given caption data.
-
-=cut
-
-sub get_xml_data {
- my ($self, $url) = @_;
-
- state $lwp = do {
-
- require LWP::UserAgent;
-
- my $agent = LWP::UserAgent->new(
- timeout => 30,
- env_proxy => 1,
- agent =>
- 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36',
- );
-
- require LWP::ConnCache;
- state $cache = LWP::ConnCache->new;
- $cache->total_capacity(undef); # no limit
-
- state $accepted_encodings = do {
- require HTTP::Message;
- HTTP::Message::decodable();
- };
-
- $agent->ssl_opts(Timeout => 30);
- $agent->default_header('Accept-Encoding' => $accepted_encodings);
- $agent->conn_cache($cache);
-
- $agent;
- };
-
- my $req = $lwp->get($url);
-
- if ($req->is_success) {
- return $req->decoded_content;
- }
-
- return;
-}
-
-=head2 save_caption($video_ID)
-
-Save the caption in a .srt file and return its file path.
-
-=cut
-
-sub save_caption {
- my ($self, $video_id) = @_;
-
- # Find one of the preferred languages
- my $info = $self->find_caption_data() // return;
-
- require File::Spec;
- my $filename = "${video_id}_$info->{languageCode}.srt";
- my $srt_file = File::Spec->catfile($self->{captions_dir} // File::Spec->tmpdir, $filename);
-
- # Return the srt file if it already exists
- return $srt_file if (-e $srt_file);
-
- # Get XML data, then transform it to SubRip data
- my $xml = $self->get_xml_data($info->{baseUrl} // return) // return;
- my $srt = $self->xml2srt($xml) // return;
-
- # Write the SubRib data to the $srt_file
- open(my $fh, '>:utf8', $srt_file) or return;
- print {$fh} $srt, "\n";
- close $fh;
-
- # Return the .srt file path
- return $srt_file;
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::GetCaption
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2012-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::GetCaption
diff --git a/lib/WWW/StrawViewer/GuideCategories.pm b/lib/WWW/StrawViewer/GuideCategories.pm
deleted file mode 100644
index 1f164b1..0000000
--- a/lib/WWW/StrawViewer/GuideCategories.pm
+++ /dev/null
@@ -1,85 +0,0 @@
-package WWW::StrawViewer::GuideCategories;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::GuideCategories - Categories interface.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $videos = $obj->youtube_categories('US');
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_guideCategories_url {
- my ($self, %opts) = @_;
-
- if (not exists $opts{id}) {
- $opts{regionCode} //= $self->get_regionCode;
- }
-
- $self->_make_feed_url('guideCategories', hl => $self->get_hl, %opts);
-}
-
-=head2 guide_categories(;$region_id)
-
-Return guide categories for a specific region ID.
-
-=head2 guide_categories_info($category_id)
-
-Return info for a list of comma-separated category IDs.
-
-=cut
-
-{
- no strict 'refs';
-
- foreach my $method (
- {
- key => 'id',
- name => 'guide_categories_info',
- },
- {
- key => 'regionCode',
- name => 'guide_categories',
- },
- ) {
- *{__PACKAGE__ . '::' . $method->{name}} = sub {
- my ($self, $id) = @_;
- return $self->_get_results($self->_make_guideCategories_url($method->{key} => $id // return));
- };
- }
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::GuideCategories
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::GuideCategories
diff --git a/lib/WWW/StrawViewer/Itags.pm b/lib/WWW/StrawViewer/Itags.pm
deleted file mode 100644
index 95ed483..0000000
--- a/lib/WWW/StrawViewer/Itags.pm
+++ /dev/null
@@ -1,319 +0,0 @@
-package WWW::StrawViewer::Itags;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Itags - Get the YouTube itags.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer::Itags;
-
- my $yv_itags = WWW::StrawViewer::Itags->new();
-
- my $itags = $yv_itags->get_itags();
- my $res = $yv_itags->get_resolutions();
-
-=head1 SUBROUTINES/METHODS
-
-=head2 new()
-
-Return the blessed object.
-
-=cut
-
-sub new {
- my ($class) = @_;
- bless {}, $class;
-}
-
-=head2 get_itags()
-
-Get a HASH ref with the YouTube itags. {resolution => [itags]}.
-
-Reference: http://en.wikipedia.org/wiki/YouTube#Quality_and_formats
-
-=cut
-
-sub get_itags {
-#<<<
- scalar {
- 'best' => [
- 38, # mp4 (3072p) (v-a)
- [138, # mp4 (2160p-4320p) (v)
- 266, # mp4 (2160p-2304p) (v)
- ],
- ],
-
- '2160' => [
- [
- 315, # webm HFR (v)
- 272, # webm (v)
- 313, # webm (v)
- 401, # av1 (v)
- ],
- ],
-
- '1440' => [
- [
- 308, # webm HFR (v)
- 271, # webm (v)
- 264, # mp4 (v)
- 400, # av1 (v)
- ],
- ],
-
- '1080' => [
- [303, # webm HFR (v)
- 299, # mp4 HFR (v)
- ],
- 46, # webm (v-a)
- 37, # mp4 (v-a)
- [248, # webm (v)
- 137, # mp4 (v)
- 399, # av1 (v)
- ],
- 301, # mp4 (live) (v-a)
- 96, # ts (live) (v-a)
- ],
-
- '720' => [
- [302, # webm HFR (v)
- 298, # mp4 HFR (v)
- ],
- 45, # webm (v-a)
- 22, # mp4 (v-a)
- [247, # webm (v)
- 136, # mp4 (v)
- 398, # av1 (v)
- ],
- 300, # mp4 (live) (v-a)
- 120, # flv (live) (v-a)
- 95, # ts (live) (v-a)
- ],
-
- '480' => [
- 44, # webm (v-a)
- 35, # flv (v-a)
- [244, # webm (v)
- 135, # mp4 (v)
- 397, # av1 (v)
- ],
- 94, # mp4 (live) (v-a)
- ],
-
- '360' => [
- 43, # webm (v-a)
- 34, # flv (v-a)
- [243, # webm (v)
- 134, # mp4 (v)
- 396, # av1 (v)
- ],
- 93, # mp4 (live) (v-a)
- 18, # mp4 (v-a)
- ],
-
- '240' => [
- 6, # flv (270p) (v-a)
- 5, # flv (v-a)
- 36, # 3gp (v-a)
- 13, # 3gp (v-a)
- [242, # webm (v)
- 133, # mp4 (v)
- 395, # av1 (v)
- ],
- 92, # mp4 (live) (v-a)
- 132, # ts (live) (v-a)
- ],
-
- '144' => [
- 17, # 3gp (v-a)
- [278, # webm (v)
- 160, # mp4 (v)
- 394, # av1 (v)
- ],
- 91, # mp4 (live) (v-a)
- 151, # ts (live) (v-a)
- ],
-
- 'audio' => [172, # webm (192 kbps)
- 251, # webm opus (128-160 kbps)
- 171, # webm vorbis (92-128 kbps)
- 140, # mp4a (128 kbps)
- 141, # mp4a (256 kbps)
- 250, # webm opus (64 kbps)
- 249, # webm opus (48 kbps)
- 139, # mp4a (48 kbps)
- ],
- };
-#>>>
-}
-
-=head2 get_resolutions()
-
-Get an ARRAY ref with the supported resolutions ordered from highest to lowest.
-
-=cut
-
-sub get_resolutions {
- my ($self) = @_;
-
- state $itags = $self->get_itags();
- return [
- grep { exists $itags->{$_} }
- qw(
- best
- 2160
- 1440
- 1080
- 720
- 480
- 360
- 240
- 144
- audio
- )
- ];
-}
-
-sub _find_streaming_url {
- my ($self, %args) = @_;
-
- my $stream = $args{stream} // return;
- my $resolution = $args{resolution} // return;
-
- foreach my $itag (@{$args{itags}->{$resolution}}) {
-
- if (ref($itag) eq 'ARRAY') {
-
- $args{dash} || next;
-
- foreach my $i (@{$itag}) {
-
- next if not exists $stream->{$i};
-
- my $video_info = $stream->{$i};
- my $audio_info = $self->_find_streaming_url(%args, resolution => 'audio', dash => 0);
-
- if (defined $audio_info) {
- $video_info->{__AUDIO__} = $audio_info;
- return $video_info;
- }
- }
-
- next;
- }
-
- if (exists $stream->{$itag}) {
- if ($resolution eq 'audio' and not $args{dash_mp4_audio}) {
- if ($itag == 140 or $itag == 141 or $itag == 139) {
- next; # skip mp4 audio URLs
- }
- }
-
- my $entry = $stream->{$itag};
-
- # Ignore segmented DASH URLs (they load pretty slow in mpv)
- if (not $args{dash_segmented}) {
- next if ($entry->{url} =~ m{^https://manifest\.googlevideo\.com/api/manifest/dash/});
- }
-
- return $entry;
- }
- }
-
- return;
-}
-
-=head2 find_streaming_url(%options)
-
-Return the streaming URL which corresponds with the specified resolution.
-
- (
- urls => \@streaming_urls,
- resolution => 'resolution_name', # from $obj->get_resolutions(),
- dash => 1/0, # include or exclude DASH itags
- dash_mp4_audio => 1/0, # include or exclude DASH videos with MP4 audio
- dash_segmented => 1/0, # include or exclude segmented DASH videos
- )
-
-=cut
-
-sub find_streaming_url {
- my ($self, %args) = @_;
-
- my $urls_array = $args{urls};
- my $resolution = $args{resolution};
-
- state $itags = $self->get_itags();
-
- if (defined($resolution) and $resolution =~ /^([0-9]+)/) {
- $resolution = $1;
- }
-
- my %stream;
- foreach my $info_ref (@{$urls_array}) {
- if (exists $info_ref->{itag} and exists $info_ref->{url}) {
- $stream{$info_ref->{itag}} = $info_ref;
- }
- }
-
- $args{stream} = \%stream;
- $args{itags} = $itags;
- $args{resolution} = $resolution;
-
- my ($streaming, $found_resolution);
-
- # Try to find the wanted resolution
- if (defined($resolution) and exists $itags->{$resolution}) {
- $streaming = $self->_find_streaming_url(%args);
- $found_resolution = $resolution;
- }
-
- # Otherwise, find the best resolution available
- if (not defined $streaming) {
-
- state $resolutions = $self->get_resolutions();
-
- foreach my $res (@{$resolutions}) {
-
- $streaming = $self->_find_streaming_url(%args, resolution => $res);
-
- if (defined($streaming)) {
- $found_resolution = $res;
- last;
- }
- }
- }
-
- wantarray ? ($streaming, $found_resolution) : $streaming;
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Itags
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2012-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Itags
diff --git a/lib/WWW/StrawViewer/ParseJSON.pm b/lib/WWW/StrawViewer/ParseJSON.pm
deleted file mode 100644
index e2e7d65..0000000
--- a/lib/WWW/StrawViewer/ParseJSON.pm
+++ /dev/null
@@ -1,76 +0,0 @@
-package WWW::StrawViewer::ParseJSON;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::ParseJSON - Parse JSON content.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer::ParseJSON;
- my $obj = WWW::StrawViewer::ParseJSON->new(%opts);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-=head2 parse_json_string($json_string)
-
-Parse a JSON string and return a HASH ref.
-
-=cut
-
-sub parse_json_string {
- my ($self, $json) = @_;
-
- if (not defined($json) or $json eq '') {
- return {};
- }
-
- require JSON;
- my $hash = eval { JSON::decode_json($json) };
- return $@ ? do { warn "[JSON]: $@\n"; {} } : $hash;
-}
-
-=head2 make_json_string($ref)
-
-Create a JSON string from a HASH or ARRAY ref.
-
-=cut
-
-sub make_json_string {
- my ($self, $ref) = @_;
-
- require JSON;
- my $str = eval { JSON::encode_json($ref) };
- return $@ ? do { warn "[JSON]: $@\n"; '' } : $str;
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::ParseJSON
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::ParseJSON
diff --git a/lib/WWW/StrawViewer/ParseXML.pm b/lib/WWW/StrawViewer/ParseXML.pm
deleted file mode 100644
index b6039b1..0000000
--- a/lib/WWW/StrawViewer/ParseXML.pm
+++ /dev/null
@@ -1,311 +0,0 @@
-package WWW::StrawViewer::ParseXML;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=encoding utf8
-
-=head1 NAME
-
-WWW::StrawViewer::ParseXML - Convert XML to a HASH ref structure.
-
-=head1 SYNOPSIS
-
-Parse XML content and return an HASH ref structure.
-
-Usage:
-
- use WWW::StrawViewer::ParseXML;
- my $hash_ref = WWW::StrawViewer::ParseXML::xml2hash($xml_string);
-
-=head1 SUBROUTINES/METHODS
-
-=head2 xml2hash($xml_string)
-
-Parse XML and return an HASH ref.
-
-=cut
-
-sub xml2hash {
- my $xml = shift() // return;
-
- $xml = "$xml"; # copy the string
-
- my $xml_ref = {};
-
- my %args = (
- attr => '-',
- text => '#text',
- empty => q{},
- @_
- );
-
- my %ctags;
- my $ref = $xml_ref;
-
- state $inv_chars = q{!"#$@%&'()*+,/;\\<=>?\]\[^`{|}~};
- state $valid_tag = qr{[^\-.\s0-9$inv_chars][^$inv_chars\s]*};
-
- {
- if (
- $xml =~ m{\G< \s*
- ($valid_tag) \s*
- ((?>$valid_tag\s*=\s*(?>".*?"|'.*?')|\s+)+)? \s*
- (/)?\s*> \s*
- }gcsxo
- ) {
-
- my ($tag, $attrs, $closed) = ($1, $2, $3);
-
- if (defined $attrs) {
- push @{$ctags{$tag}}, $ref;
-
- $ref =
- ref $ref eq 'HASH'
- ? ref $ref->{$tag}
- ? $ref->{$tag}
- : (
- defined $ref->{$tag}
- ? ($ref->{$tag} = [$ref->{$tag}])
- : ($ref->{$tag} //= [])
- )
- : ref $ref eq 'ARRAY' ? ref $ref->[-1]{$tag}
- ? $ref->[-1]{$tag}
- : (
- defined $ref->[-1]{$tag}
- ? ($ref->[-1]{$tag} = [$ref->[-1]{$tag}])
- : ($ref->[-1]{$tag} //= [])
- )
- : [];
-
- ++$#{$ref} if ref $ref eq 'ARRAY';
-
- while (
- $attrs =~ m{\G
- ($valid_tag) \s*=\s*
- (?>
- "(.*?)"
- |
- '(.*?)'
- ) \s*
- }gsxo
- ) {
- my ($key, $value) = ($1, $+);
- $key = join(q{}, $args{attr}, $key);
- if (ref $ref eq 'ARRAY') {
- $ref->[-1]{$key} = _decode_entities($value);
- }
- elsif (ref $ref eq 'HASH') {
- $ref->{$key} = $value;
- }
- }
-
- if (defined $closed) {
- $ref = pop @{$ctags{$tag}};
- }
-
- if ($xml =~ m{\G<\s*/\s*\Q$tag\E\s*>\s*}gc) {
- $ref = pop @{$ctags{$tag}};
- }
- elsif ($xml =~ m{\G([^<]+)(?=<)}gsc) {
- if (ref $ref eq 'ARRAY') {
- $ref->[-1]{$args{text}} .= _decode_entities($1);
- $ref = pop @{$ctags{$tag}};
- }
- elsif (ref $ref eq 'HASH') {
- $ref->{$args{text}} .= $1;
- $ref = pop @{$ctags{$tag}};
- }
- }
- }
- elsif (defined $closed) {
- if (ref $ref eq 'ARRAY') {
- if (exists $ref->[-1]{$tag}) {
- if (ref $ref->[-1]{$tag} ne 'ARRAY') {
- $ref->[-1]{$tag} = [$ref->[-1]{$tag}];
- }
- push @{$ref->[-1]{$tag}}, $args{empty};
- }
- else {
- $ref->[-1]{$tag} = $args{empty};
- }
- }
- }
- else {
- if ($xml =~ /\G(?=<(?!!))/) {
- push @{$ctags{$tag}}, $ref;
-
- $ref =
- ref $ref eq 'HASH'
- ? ref $ref->{$tag}
- ? $ref->{$tag}
- : (
- defined $ref->{$tag}
- ? ($ref->{$tag} = [$ref->{$tag}])
- : ($ref->{$tag} //= [])
- )
- : ref $ref eq 'ARRAY' ? ref $ref->[-1]{$tag}
- ? $ref->[-1]{$tag}
- : (
- defined $ref->[-1]{$tag}
- ? ($ref->[-1]{$tag} = [$ref->[-1]{$tag}])
- : ($ref->[-1]{$tag} //= [])
- )
- : [];
-
- ++$#{$ref} if ref $ref eq 'ARRAY';
- redo;
- }
- elsif ($xml =~ /\G<!\[CDATA\[(.*?)\]\]>\s*/gcs or $xml =~ /\G([^<]+)(?=<)/gsc) {
- my ($text) = $1;
-
- if ($xml =~ m{\G<\s*/\s*\Q$tag\E\s*>\s*}gc) {
- if (ref $ref eq 'ARRAY') {
- if (exists $ref->[-1]{$tag}) {
- if (ref $ref->[-1]{$tag} ne 'ARRAY') {
- $ref->[-1]{$tag} = [$ref->[-1]{$tag}];
- }
- push @{$ref->[-1]{$tag}}, $text;
- }
- else {
- $ref->[-1]{$tag} .= _decode_entities($text);
- }
- }
- elsif (ref $ref eq 'HASH') {
- $ref->{$tag} .= $text;
- }
- }
- else {
- push @{$ctags{$tag}}, $ref;
-
- $ref =
- ref $ref eq 'HASH'
- ? ref $ref->{$tag}
- ? $ref->{$tag}
- : (
- defined $ref->{$tag}
- ? ($ref->{$tag} = [$ref->{$tag}])
- : ($ref->{$tag} //= [])
- )
- : ref $ref eq 'ARRAY' ? ref $ref->[-1]{$tag}
- ? $ref->[-1]{$tag}
- : (
- defined $ref->[-1]{$tag}
- ? ($ref->[-1]{$tag} = [$ref->[-1]{$tag}])
- : ($ref->[-1]{$tag} //= [])
- )
- : [];
-
- ++$#{$ref} if ref $ref eq 'ARRAY';
-
- if (ref $ref eq 'ARRAY') {
- if (exists $ref->[-1]{$tag}) {
- if (ref $ref->[-1]{$tag} ne 'ARRAY') {
- $ref->[-1] = [$ref->[-1]{$tag}];
- }
- push @{$ref->[-1]}, {$args{text} => $text};
- }
- else {
- $ref->[-1]{$args{text}} .= $text;
- }
- }
- elsif (ref $ref eq 'HASH') {
- $ref->{$tag} .= $text;
- }
- }
- }
- }
-
- if ($xml =~ m{\G<\s*/\s*\Q$tag\E\s*>\s*}gc) {
- ## tag closed - ok
- }
-
- redo;
- }
- elsif ($xml =~ m{\G<\s*/\s*($valid_tag)\s*>\s*}gco) {
- if (exists $ctags{$1} and @{$ctags{$1}}) {
- $ref = pop @{$ctags{$1}};
- }
- redo;
- }
- elsif ($xml =~ /\G<!\[CDATA\[(.*?)\]\]>\s*/gcs or $xml =~ m{\G([^<]+)(?=<)}gsc) {
- if (ref $ref eq 'ARRAY') {
- $ref->[-1]{$args{text}} .= $1;
- }
- elsif (ref $ref eq 'HASH') {
- $ref->{$args{text}} .= $1;
- }
- redo;
- }
- elsif ($xml =~ /\G<\?/gc) {
- $xml =~ /\G.*?\?>\s*/gcs or die "Invalid XML!";
- redo;
- }
- elsif ($xml =~ /\G<!--/gc) {
- $xml =~ /\G.*?-->\s*/gcs or die "Comment not closed!";
- redo;
- }
- elsif ($xml =~ /\G<!DOCTYPE\s+/gc) {
- $xml =~ /\G(?>$valid_tag|\s+|".*?"|'.*?')*\[.*?\]>\s*/sgco
- or $xml =~ /\G.*?>\s*/sgc
- or die "DOCTYPE not closed!";
- redo;
- }
- elsif ($xml =~ /\G\z/gc) {
- ## ok
- }
- elsif ($xml =~ /\G\s+/gc) {
- redo;
- }
- else {
- die "Syntax error near: --> ", [split(/\n/, substr($xml, pos(), 2**6))]->[0], " <--\n";
- }
- }
-
- return $xml_ref;
-}
-
-{
- my %entities = (
- 'amp' => '&',
- 'quot' => '"',
- 'apos' => "'",
- 'gt' => '>',
- 'lt' => '<',
- );
-
- state $ent_re = do {
- local $" = '|';
- qr/&(@{[keys %entities]});/;
- };
-
- sub _decode_entities {
- $_[0] =~ s/$ent_re/$entities{$1}/gor;
- }
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::ParseXML
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2012-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::ParseXML
diff --git a/lib/WWW/StrawViewer/PlaylistItems.pm b/lib/WWW/StrawViewer/PlaylistItems.pm
deleted file mode 100644
index ab41a0d..0000000
--- a/lib/WWW/StrawViewer/PlaylistItems.pm
+++ /dev/null
@@ -1,146 +0,0 @@
-package WWW::StrawViewer::PlaylistItems;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::PlaylistItems - Manage playlist entries.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $videos = $obj->videos_from_playlistID($playlist_id);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_playlistItems_url {
- my ($self, %opts) = @_;
- return
- $self->_make_feed_url(
- 'playlistItems',
- pageToken => $self->page_token,
- %opts
- );
-}
-
-=head2 add_video_to_playlist($playlistID, $videoID; $position=1)
-
-Add a video to given playlist ID, at position 1 (by default)
-
-=cut
-
-sub add_video_to_playlist {
- my ($self, $playlist_id, $video_id, $position) = @_;
-
- $self->get_access_token() // return;
-
- $playlist_id // return;
- $video_id // return;
- $position //= 0;
-
- my $hash = {
- "snippet" => {
- "playlistId" => $playlist_id,
- "resourceId" => {
- "videoId" => $video_id,
- "kind" => "youtube#video"
- },
- "position" => $position,
- }
- };
-
- my $url = $self->_make_playlistItems_url(pageToken => undef);
- $self->post_as_json($url, $hash);
-}
-
-=head2 favorite_video($videoID)
-
-Favorite a video. Returns true on success.
-
-=cut
-
-sub favorite_video {
- my ($self, $video_id) = @_;
- $video_id // return;
- $self->get_access_token() // return;
- my $playlist_id = $self->get_playlist_id('favorites', mine => 'true') // return;
- $self->add_video_to_playlist($playlist_id, $video_id);
-}
-
-=head2 videos_from_playlist_id($playlist_id)
-
-Get videos from a specific playlistID.
-
-=cut
-
-sub videos_from_playlist_id {
- my ($self, $id) = @_;
- $self->_get_results($self->_make_feed_url("playlists/$id"));
-}
-
-=head2 favorites($channel_id)
-
-=head2 uploads($channel_id)
-
-=head2 likes($channel_id)
-
-Get the favorites, uploads and likes for a given channel ID.
-
-=cut
-
-=head2 favorites_from_username($username)
-
-=head2 uploads_from_username($username)
-
-=head2 likes_from_username($username)
-
-Get the favorites, uploads and likes for a given YouTube username.
-
-=cut
-
-{
- no strict 'refs';
- foreach my $name (qw(favorites uploads likes)) {
-
- *{__PACKAGE__ . '::' . $name . '_from_username'} = sub {
- my ($self, $username) = @_;
- $self->videos_from_username($username);
- };
-
- *{__PACKAGE__ . '::' . $name} = sub {
- my ($self, $channel_id) = @_;
- $self->videos_from_channel_id($channel_id);
- };
- }
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::PlaylistItems
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::PlaylistItems
diff --git a/lib/WWW/StrawViewer/Playlists.pm b/lib/WWW/StrawViewer/Playlists.pm
deleted file mode 100644
index 5d4e07d..0000000
--- a/lib/WWW/StrawViewer/Playlists.pm
+++ /dev/null
@@ -1,124 +0,0 @@
-package WWW::StrawViewer::Playlists;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Playlists - Straw playlists handle.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $info = $obj->playlist_from_id($playlist_id);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_playlists_url {
- my ($self, %opts) = @_;
-
- if (not exists $opts{'part'}) {
- $opts{'part'} = 'snippet,contentDetails';
- }
-
- $self->_make_feed_url(
- 'playlists',
- pageToken => $self->page_token,
- %opts,
- );
-}
-
-sub get_playlist_id {
- my ($self, $playlist_name, %fields) = @_;
-
- my $url = $self->_simple_feeds_url('channels', qw(part contentDetails), %fields);
- my $res = $self->_get_results($url);
-
- ref($res->{results}{items}) eq 'ARRAY' || return;
- @{$res->{results}{items}} || return;
-
- return $res->{results}{items}[0]{contentDetails}{relatedPlaylists}{$playlist_name};
-}
-
-=head2 playlist_from_id($playlist_id)
-
-Return info for one or more playlists.
-PlaylistIDs can be separated by commas.
-
-=cut
-
-sub playlist_from_id {
- my ($self, $id, $part) = @_;
- $self->_get_results($self->_make_playlists_url(id => $id, part => ($part // 'snippet')));
-}
-
-=head2 playlists($channel_id)
-
-Get and return playlists from a channel ID.
-
-=cut
-
-sub playlists {
- my ($self, $channel_id) = @_;
- $self->_get_results(
- $self->_make_playlists_url(
- ($channel_id and $channel_id ne 'mine')
- ? (channelId => $channel_id)
- : do { $self->get_access_token() // return; (mine => 'true') }
- )
- );
-}
-
-=head2 playlists_from_username($username)
-
-Get and return the playlists created for a given username.
-
-=cut
-
-sub playlists_from_username {
- my ($self, $username) = @_;
- my $channel_id = $self->channel_id_from_username($username) // $username;
- $self->playlists($channel_id);
-}
-
-=head2 my_playlists()
-
-Get and return your playlists.
-
-=cut
-
-sub my_playlists {
- my ($self) = @_;
- $self->get_access_token() // return;
- $self->_get_results($self->_make_playlists_url(mine => 'true'));
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Playlists
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Playlists
diff --git a/lib/WWW/StrawViewer/RegularExpressions.pm b/lib/WWW/StrawViewer/RegularExpressions.pm
deleted file mode 100644
index edf9dd5..0000000
--- a/lib/WWW/StrawViewer/RegularExpressions.pm
+++ /dev/null
@@ -1,89 +0,0 @@
-package WWW::StrawViewer::RegularExpressions;
-
-use utf8;
-use 5.014;
-use warnings;
-
-require Exporter;
-our @ISA = qw(Exporter);
-
-=head1 NAME
-
-WWW::StrawViewer::RegularExpressions - Various utils.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer::RegularExpressions;
- use WWW::StrawViewer::RegularExpressions ($get_video_id_re);
-
-=cut
-
-my $opt_begin_chars = q{:;=}; # stdin option valid begin chars
-
-# Options
-our $range_num_re = qr{^([0-9]{1,2}+)(?>-|\.\.)([0-9]{1,2}+)?\z};
-our $digit_or_equal_re = qr/(?(?=[1-9])|=)/;
-our $non_digit_or_opt_re = qr{^(?!$range_num_re)(?>[0-9]{1,2}[^0-9]|[0-9]{3}|[^0-9$opt_begin_chars])};
-
-# Generic name
-my $generic_name_re = qr/[a-zA-Z0-9_.\-]{11,34}/;
-our $valid_channel_id_re = qr{^(?:.*/channel/)?(?<channel_id>(?:\w+(?:[-.]++\w++)*|$generic_name_re))(?:/.*)?\z};
-
-our $get_channel_videos_id_re = qr{^.*/channel/(?<channel_id>(?:\w+(?:[-.]++\w++)*|$generic_name_re))};
-our $get_channel_playlists_id_re = qr{$get_channel_videos_id_re/playlists};
-
-our $get_username_videos_re = qr{^.*/user/(?<username>[-.\w]+)};
-our $get_username_playlists_re = qr{$get_username_videos_re/playlists};
-
-# Video ID
-my $video_id_re = qr/[0-9A-Za-z_\-]{11}/;
-our $valid_video_id_re = qr{^$video_id_re\z};
-our $get_video_id_re = qr{(?:%3F|\b)(?>v|embed|youtu[.]be)(?>[=/]|%3D)(?<video_id>$video_id_re)};
-
-# Playlist ID
-our $valid_playlist_id_re = qr{^$generic_name_re\z};
-our $get_playlist_id_re = qr{(?:(?:(?>playlist\?list|view_play_list\?p|list)=)|\w#p/c/)(?<playlist_id>$generic_name_re)\b};
-
-our $valid_opt_re = qr{^[$opt_begin_chars]([A-Za-z]++(?:-[A-Za-z]++)?(?>${digit_or_equal_re}.*)?)$};
-
-our @EXPORT = qw(
- $range_num_re
- $digit_or_equal_re
- $non_digit_or_opt_re
- $valid_channel_id_re
- $valid_video_id_re
- $get_video_id_re
- $valid_playlist_id_re
- $get_playlist_id_re
- $valid_opt_re
- $get_channel_videos_id_re
- $get_channel_playlists_id_re
- $get_username_videos_re
- $get_username_playlists_re
- );
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::RegularExpressions
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2012-2013 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::RegularExpressions
diff --git a/lib/WWW/StrawViewer/Search.pm b/lib/WWW/StrawViewer/Search.pm
deleted file mode 100644
index 67b8982..0000000
--- a/lib/WWW/StrawViewer/Search.pm
+++ /dev/null
@@ -1,175 +0,0 @@
-package WWW::StrawViewer::Search;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Search - Search functions for Straw API v3
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- $obj->search_videos(@keywords);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_search_url {
- my ($self, %opts) = @_;
-
- 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,
- )
- : ()
- ),
-
- %opts,
- );
-
-}
-
-=head2 search_for($types,$keywords;\%args)
-
-Search for a list of types (comma-separated).
-
-=cut
-
-sub search_for {
- my ($self, $type, $keywords, $args) = @_;
-
- $keywords //= [];
- if (ref $keywords ne 'ARRAY') {
- $keywords = [split ' ', $keywords];
- }
-
- my $url = $self->_make_search_url(
- type => $type,
- q => $self->escape_string(join(' ', @{$keywords})),
- (ref $args eq 'HASH' ? %{$args} : (part => 'snippet')),
- );
-
- return $self->_get_results($url);
-}
-
-{
- no strict 'refs';
-
- foreach my $pair (
- {
- name => 'videos',
- type => 'video',
- },
- {
- name => 'playlists',
- type => 'playlist',
- },
- {
- name => 'channels',
- type => 'channel',
- },
- {
- name => 'all',
- type => 'video,channel,playlist',
- }
- ) {
- *{__PACKAGE__ . '::' . "search_$pair->{name}"} = sub {
- my $self = shift;
- $self->search_for($pair->{type}, @_);
- };
- }
-}
-
-=head2 search_videos($keywords;\%args)
-
-Search and return the found video results.
-
-=cut
-
-=head2 search_playlists($keywords;\%args)
-
-Search and return the found playlists.
-
-=cut
-
-=head2 search_channels($keywords;\%args)
-
-Search and return the found channels.
-
-=cut
-
-=head2 search_all($keywords;\%args)
-
-Search and return the results.
-
-=cut
-
-=head2 related_to_videoID($id)
-
-Retrieves a list of videos that are related to the video
-that the parameter value identifies. The parameter value must
-be set to a YouTube video ID.
-
-=cut
-
-sub related_to_videoID {
- my ($self, $id) = @_;
- return $self->search_for('video', [], {relatedToVideoId => $id});
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Search
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Search
diff --git a/lib/WWW/StrawViewer/Subscriptions.pm b/lib/WWW/StrawViewer/Subscriptions.pm
deleted file mode 100644
index 063a875..0000000
--- a/lib/WWW/StrawViewer/Subscriptions.pm
+++ /dev/null
@@ -1,272 +0,0 @@
-package WWW::StrawViewer::Subscriptions;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Subscriptions - Subscriptions handler.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $videos = $obj->subscriptions_from_channelID($channel_id);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_subscriptions_url {
- my ($self, %opts) = @_;
- return $self->_make_feed_url('subscriptions', %opts);
-}
-
-=head2 subscribe_channel($channel_id)
-
-Subscribe to an YouTube channel.
-
-=cut
-
-sub subscribe_channel {
- my ($self, $channel_id) = @_;
-
- my $resource = {
- snippet => {
- resourceId => {
- kind => 'youtube#channel',
- channelId => $channel_id,
- }
- }
- };
-
- my $url = $self->_simple_feeds_url('subscriptions', part => 'snippet');
- return $self->post_as_json($url, $resource);
-}
-
-=head2 subscribe_channel_from_username($username)
-
-Subscribe to an YouTube channel via username.
-
-=cut
-
-sub subscribe_channel_from_username {
- my ($self, $username) = @_;
- $self->subscribe_channel($self->channel_id_from_username($username) // $username);
-}
-
-=head2 subscriptions(;$channel_id)
-
-Retrieve the subscriptions for a channel ID or for the authenticated user.
-
-=cut
-
-sub subscriptions {
- my ($self, $channel_id) = @_;
- $self->_get_results(
- $self->_make_subscriptions_url(
- order => $self->get_subscriptions_order,
- part => 'snippet',
- (
- ($channel_id and $channel_id ne 'mine')
- ? (channelId => $channel_id)
- : do { $self->get_access_token() // return; (mine => 'true') }
- ),
- )
- );
-}
-
-=head2 subscriptions_from_username($username)
-
-Retrieve subscriptions for a given YouTube username.
-
-=cut
-
-sub subscriptions_from_username {
- my ($self, $username) = @_;
- $self->subscriptions($self->channel_id_from_username($username) // $username);
-}
-
-=head2 subscription_videos(;$channel_id)
-
-Retrieve the video subscriptions for a channel ID or for the current authenticated user.
-
-=cut
-
-sub subscription_videos {
- my ($self, $channel_id, $order) = @_;
-
- my $max_results = $self->get_maxResults();
-
- my @subscription_items;
- my $next_page_token;
-
- while (1) {
-
- my $url = $self->_make_subscriptions_url(
- order => $self->get_subscriptions_order,
- maxResults => 50,
- part => 'snippet,contentDetails',
- ($channel_id and $channel_id ne 'mine')
- ? (channelId => $channel_id)
- : do { $self->get_access_token() // return; (mine => 'true') },
- defined($next_page_token) ? (pageToken => $next_page_token) : (),
- );
-
- my $subscriptions = $self->_get_results($url)->{results};
-
- if ( ref($subscriptions) eq 'HASH'
- and ref($subscriptions->{items}) eq 'ARRAY') {
- push @subscription_items, @{$subscriptions->{items}};
- }
-
- $next_page_token = $subscriptions->{nextPageToken} || last;
- }
-
- my (undef, undef, undef, $mday, $mon, $year) = localtime;
-
- $mon += 1;
- $year += 1900;
-
- my @videos;
- foreach my $channel (@subscription_items) {
-
- my $new_items = $channel->{contentDetails}{newItemCount};
-
- # Ignore channels with zero new items
- $new_items > 0 || next;
-
- # Set the number of results
- $self->set_maxResults(1); # don't load more than 1 video from each channel
- # maybe, this value should be configurable (?)
-
- my $uploads = $self->uploads($channel->{snippet}{resourceId}{channelId});
-
- (ref($uploads) eq 'HASH' and ref($uploads->{results}) eq 'HASH' and ref($uploads->{results}{items}) eq 'ARRAY')
- || return;
-
- my $items = $uploads->{results}{items};
-
- # Get and store the video uploads from each channel
- foreach my $item (@$items) {
- my $publishedAt = $item->{snippet}{publishedAt};
- my ($p_year, $p_mon, $p_mday) = $publishedAt =~ /^(\d{4})-(\d{2})-(\d{2})/;
-
- my $year_diff = $year - $p_year;
- my $mon_diff = $mon - $p_mon;
- my $mday_diff = $mday - $p_mday;
-
- my $days_diff = $year_diff * 365.2422 + $mon_diff * 30.436875 + $mday_diff;
-
- # Ignore old entries
- if ($days_diff > 3) {
- next;
- }
-
- push @videos, $item;
- }
-
- # Stop when the limit is reached
- last if (@videos >= $max_results);
- }
-
- # When there are no new videos, load one from each channel
- if ($#videos == -1) {
- foreach my $channel (@subscription_items) {
- $self->set_maxResults(1);
- push @videos, @{$self->uploads($channel->{snippet}{resourceId}{channelId})->{results}{items}};
- last if (@videos >= $max_results);
- }
- }
-
- $self->set_maxResults($max_results);
-
- state $parse_time_re = qr/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/;
-
- @videos =
- sort {
- my ($y1, $M1, $d1, $h1, $m1, $s1) = $a->{snippet}{publishedAt} =~ $parse_time_re;
- my ($y2, $M2, $d2, $h2, $m2, $s2) = $b->{snippet}{publishedAt} =~ $parse_time_re;
-
- ($y2 <=> $y1) || ($M2 <=> $M1) || ($d2 <=> $d1) || ($h2 <=> $h1) || ($m2 <=> $m1) || ($s2 <=> $s1)
- } @videos;
-
- return {results => {pageInfo => {totalResults => $#videos + 1}, items => \@videos}};
-}
-
-=head2 subscription_videos_from_username($username)
-
-Retrieve the video subscriptions for a username.
-
-=cut
-
-sub subscription_videos_from_username {
- my ($self, $username) = @_;
- $self->subscription_videos($self->channel_id_from_username($username) // $username);
-}
-
-=head2 subscriptions_from_channelID(%args)
-
-Get subscriptions for the specified channel ID.
-
-=head2 subscriptions_info($subscriptionID, %args)
-
-Get details for the comma-separated subscriptionID(s).
-
-=head3 HASH '%args' supports the following pairs:
-
- %args = (
- part => {contentDetails,id,snippet},
- forChannelId => $channelID,
- maxResults => [0-50],
- order => {alphabetical, relevance, unread},
- pageToken => {$nextPageToken, $prevPageToken},
- );
-
-=cut
-
-{
- no strict 'refs';
- foreach my $method (
- {
- key => 'id',
- name => 'subscriptions_info',
- },
- {
- key => 'channelId',
- name => 'subscriptions_from_channel_id',
- }
- ) {
- *{__PACKAGE__ . '::' . $method->{name}} = sub {
- my ($self, $id, %args) = @_;
- return $self->_get_results($self->_make_subscriptions_url($method->{key} => $id, %args));
- };
- }
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Subscriptions
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Subscriptions
diff --git a/lib/WWW/StrawViewer/Utils.pm b/lib/WWW/StrawViewer/Utils.pm
deleted file mode 100644
index 153aab9..0000000
--- a/lib/WWW/StrawViewer/Utils.pm
+++ /dev/null
@@ -1,801 +0,0 @@
-package WWW::StrawViewer::Utils;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Utils - Various utils.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer::Utils;
-
- my $yv_utils = WWW::StrawViewer::Utils->new(%opts);
-
- print $yv_utils->format_time(3600);
-
-=head1 SUBROUTINES/METHODS
-
-=head2 new(%opts)
-
-Options:
-
-=over 4
-
-=item thousand_separator => ""
-
-Character used as thousand separator.
-
-=item months => []
-
-Month names for I<format_date()>
-
-=item youtube_url_format => ""
-
-A youtube URL format for sprintf(format, videoID).
-
-=back
-
-=cut
-
-sub new {
- my ($class, %opts) = @_;
-
- my $self = bless {
- thousand_separator => q{,},
- youtube_url_format => 'https://www.youtube.com/watch?v=%s',
- }, $class;
-
- $self->{months} = [
- qw(
- Jan Feb Mar
- Apr May Jun
- Jul Aug Sep
- Oct Nov Dec
- )
- ];
-
- foreach my $key (keys %{$self}) {
- $self->{$key} = delete $opts{$key}
- if exists $opts{$key};
- }
-
- foreach my $invalid_key (keys %opts) {
- warn "Invalid key: '${invalid_key}'";
- }
-
- return $self;
-}
-
-=head2 extension($type)
-
-Returns the extension format from a given type.
-
-From a string like 'video/webm;+codecs="vp9"', it returns 'webm'.
-
-=cut
-
-sub extension {
- my ($self, $type) = @_;
- $type =~ /\bflv\b/i ? q{flv}
- : $type =~ /\bwebm\b/i ? q{webm}
- : $type =~ /\b3gpp?\b/i ? q{3gp}
- : $type =~ m{^video/(\w+)} ? $1
- : $type =~ m{^audio/(\w+)} ? $1
- : q{mp4};
-}
-
-=head2 format_time($sec)
-
-Returns time from seconds.
-
-=cut
-
-sub format_time {
- my ($self, $sec) = @_;
- $sec >= 3600
- ? join q{:}, map { sprintf '%02d', $_ } $sec / 3600 % 24, $sec / 60 % 60, $sec % 60
- : join q{:}, map { sprintf '%02d', $_ } $sec / 60 % 60, $sec % 60;
-}
-
-=head2 format_duration($duration)
-
-Return seconds from duration (PT1H20M10S).
-
-=cut
-
-# PT5M3S -> 05:03
-# PT1H20M10S -> 01:20:10
-# PT16S -> 00:16
-
-sub format_duration {
- my ($self, $duration) = @_;
-
- $duration // return 0;
- my ($hour, $min, $sec) = (0, 0, 0);
-
- $hour = $1 if ($duration =~ /(\d+)H/);
- $min = $1 if ($duration =~ /(\d+)M/);
- $sec = $1 if ($duration =~ /(\d+)S/);
-
- $hour * 60 * 60 + $min * 60 + $sec;
-}
-
-=head2 format_date($date)
-
-Return string "04 May 2010" from "2010-05-04T00:25:55.000Z"
-
-=cut
-
-sub format_date {
- my ($self, $date) = @_;
-
- # 2010-05-04T00:25:55.000Z
- # to: 04 May 2010
-
- $date =~ s{^
- (?<year>\d{4})
- -
- (?<month>\d{2})
- -
- (?<day>\d{2})
- .*
- }
- {$+{day} $self->{months}[$+{month} - 1] $+{year}}x;
-
- return $date;
-}
-
-=head2 date_to_age($date)
-
-Return the (approximated) age for a given date of the form "2010-05-04T00:25:55.000Z".
-
-=cut
-
-sub date_to_age {
- my ($self, $date) = @_;
-
- $date =~ m{^
- (?<year>\d{4})
- -
- (?<month>\d{2})
- -
- (?<day>\d{2})
- [a-zA-Z]
- (?<hour>\d{2})
- :
- (?<min>\d{2})
- :
- (?<sec>\d{2})
- }x || return undef;
-
- my ($sec, $min, $hour, $day, $month, $year) = gmtime(time);
-
- $year += 1900;
- $month += 1;
-
- my $lambda = sub {
-
- if ($year == $+{year}) {
- if ($month == $+{month}) {
- if ($day == $+{day}) {
- if ($hour == $+{hour}) {
- if ($min == $+{min}) {
- return join(' ', $sec - $+{sec}, 'seconds');
- }
- return join(' ', $min - $+{min}, 'minutes');
- }
- return join(' ', $hour - $+{hour}, 'hours');
- }
- return join(' ', $day - $+{day}, 'days');
- }
- return join(' ', $month - $+{month}, 'months');
- }
-
- if ($year - $+{year} == 1) {
- my $month_diff = $+{month} - $month;
- if ($month_diff > 0) {
- return join(' ', 12 - $month_diff, 'months');
- }
- }
-
- return join(' ', $year - $+{year}, 'years');
- };
-
- my $age = $lambda->();
-
- if ($age =~ /^1\s/) { # singular mode
- $age =~ s/s\z//;
- }
-
- return $age;
-}
-
-=head2 has_entries($result)
-
-Returns true if a given result has entries.
-
-=cut
-
-sub has_entries {
- my ($self, $result) = @_;
-
- if (ref($result->{results}) eq 'HASH') {
-
- if (exists $result->{results}{comments}) {
- return scalar @{$result->{results}{comments}} > 0;
- }
-
- my $type = $result->{results}{type}//'';
-
- if ($type eq 'playlist') {
- return $result->{results}{videoCount} > 0;
- }
- }
-
- if (ref($result->{results}) eq 'ARRAY') {
- return scalar(@{$result->{results}}) > 0;
- }
-
- return 1; # maybe?
- #ref($result) eq 'HASH' and ($result->{results}{pageInfo}{totalResults} > 0);
-}
-
-=head2 normalize_video_title($title, $fat32safe)
-
-Replace file-unsafe characters and trim spaces.
-
-=cut
-
-sub normalize_video_title {
- my ($self, $title, $fat32safe) = @_;
-
- if ($fat32safe) {
- $title =~ s/: / - /g;
- $title =~ tr{:"*/?\\|}{;'+%!%%}; # "
- $title =~ tr/<>//d;
- }
- else {
- $title =~ tr{/}{%};
- }
-
- join(q{ }, split(q{ }, $title));
-}
-
-=head2 format_text(%opt)
-
-Formats a text with information from streaming and video info.
-
-The structure of C<%opt> is:
-
- (
- streaming => HASH,
- info => HASH,
- text => STRING,
- escape => BOOL,
- fat32safe => BOOL,
- )
-
-=cut
-
-sub format_text {
- my ($self, %opt) = @_;
-
- my $streaming = $opt{streaming};
- my $info = $opt{info};
- my $text = $opt{text};
- my $escape = $opt{escape};
- my $fat32safe = $opt{fat32safe};
-
- my %special_tokens = (
- ID => sub { $self->get_video_id($info) },
- AUTHOR => sub { $self->get_channel_title($info) },
- CHANNELID => sub { $self->get_channel_id($info) },
- DEFINITION => sub { $self->get_definition($info) },
- DIMENSION => sub { $self->get_dimension($info) },
- VIEWS => sub { $self->get_views($info) },
- VIEWS_SHORT => sub { $self->get_views_approx($info) },
- LIKES => sub { $self->get_likes($info) },
- DISLIKES => sub { $self->get_dislikes($info) },
- COMMENTS => sub { $self->get_comments($info) },
- DURATION => sub { $self->get_duration($info) },
- TIME => sub { $self->get_time($info) },
- TITLE => sub { $self->get_title($info) },
- FTITLE => sub { $self->normalize_video_title($self->get_title($info), $fat32safe) },
- CAPTION => sub { $self->get_caption($info) },
- PUBLISHED => sub { $self->get_publication_date($info) },
- AGE => sub { $self->get_publication_age($info) },
- AGE_SHORT => sub { $self->get_publication_age_approx($info) },
- DESCRIPTION => sub { $self->get_description($info) },
-
- RATING => sub {
- my $likes = $self->get_likes($info) // 0;
- my $dislikes = $self->get_dislikes($info) // 0;
-
- my $rating = 0;
- if ($likes + $dislikes > 0) {
- $rating = $likes / ($likes + $dislikes) * 5;
- }
-
- sprintf('%.2f', $rating);
- },
-
- (
- defined($streaming)
- ? (
- RESOLUTION => sub {
- $streaming->{resolution} =~ /^\d+\z/
- ? $streaming->{resolution} . 'p'
- : $streaming->{resolution};
- },
-
- ITAG => sub { $streaming->{streaming}{itag} },
- SUB => sub { $streaming->{srt_file} },
- VIDEO => sub { $streaming->{streaming}{url} },
- FORMAT => sub { $self->extension($streaming->{streaming}{type}) },
-
- AUDIO => sub {
- ref($streaming->{streaming}{__AUDIO__}) eq 'HASH'
- ? $streaming->{streaming}{__AUDIO__}{url}
- : q{};
- },
-
- AOV => sub {
- ref($streaming->{streaming}{__AUDIO__}) eq 'HASH'
- ? $streaming->{streaming}{__AUDIO__}{url}
- : $streaming->{streaming}{url};
- },
- )
- : ()
- ),
-
- URL => sub { sprintf($self->{youtube_url_format}, $self->get_video_id($info)) },
- );
-
- my $tokens_re = do {
- local $" = '|';
- qr/\*(@{[keys %special_tokens]})\*/;
- };
-
- my %special_escapes = (
- a => "\a",
- b => "\b",
- e => "\e",
- f => "\f",
- n => "\n",
- r => "\r",
- t => "\t",
- );
-
- my $escapes_re = do {
- local $" = q{};
- qr/\\([@{[keys %special_escapes]}])/;
- };
-
- $text =~ s/$escapes_re/$special_escapes{$1}/g;
-
- $escape
- ? $text =~ s/$tokens_re/\Q${\$special_tokens{$1}()}\E/gr
- : $text =~ s/$tokens_re/${\$special_tokens{$1}()}/gr;
-}
-
-=head2 set_thousands($num)
-
-Return the number with thousand separators.
-
-=cut
-
-sub set_thousands { # ugly, but fast
- my ($self, $n) = @_;
-
- return 0 unless $n;
- length($n) > 3 or return $n;
-
- my $l = length($n) - 3;
- my $i = ($l - 1) % 3 + 1;
- my $x = substr($n, 0, $i) . $self->{thousand_separator};
-
- while ($i < $l) {
- $x .= substr($n, $i, 3) . $self->{thousand_separator};
- $i += 3;
- }
-
- return $x . substr($n, $i);
-}
-
-=head2 get_video_id($info)
-
-Get videoID.
-
-=cut
-
-sub get_video_id {
- my ($self, $info) = @_;
- $info->{videoId};
-
- #~ ref($info->{id}) eq 'HASH' ? $info->{id}{videoId}
- #~ : exists($info->{snippet}{resourceId}{videoId}) ? $info->{snippet}{resourceId}{videoId}
- #~ : exists($info->{contentDetails}{videoId}) ? $info->{contentDetails}{videoId}
- #~ : exists($info->{contentDetails}{playlistItem}{resourceId}{videoId})
- #~ ? $info->{contentDetails}{playlistItem}{resourceId}{videoId}
- #~ : exists($info->{contentDetails}{upload}{videoId}) ? $info->{contentDetails}{upload}{videoId}
- #~ : do {
- #~ my $id = $info->{id} // return undef;
-
- #~ if (length($id) != 11) {
- #~ return undef;
- #~ }
-
- #~ $id;
- #~ };
-}
-
-sub get_playlist_id {
- my ($self, $info) = @_;
- $info->{playlistId};
-}
-
-sub get_playlist_video_count {
- my ($self, $info) = @_;
- $info->{videoCount};
-}
-
-=head2 get_description($info)
-
-Get description.
-
-=cut
-
-sub get_description {
- my ($self, $info) = @_;
- my $desc = $info->{description};
- (defined($desc) and $desc =~ /\S/) ? $desc : 'No description available...';
-}
-
-=head2 get_title($info)
-
-Get title.
-
-=cut
-
-sub get_title {
- my ($self, $info) = @_;
- $info->{title};
-}
-
-=head2 get_thumbnail_url($info;$type='default')
-
-Get thumbnail URL.
-
-=cut
-
-sub get_thumbnail_url {
- my ($self, $info, $type) = @_;
-
- if (exists $info->{videoId}) {
- $info->{type} = 'video';
- }
-
- if ($info->{type} eq 'playlist') {
- return $info->{playlistThumbnail};
- }
-
- if ($info->{type} eq 'channel') {
- ref($info->{authorThumbnails}) eq 'ARRAY' or return '';
- return $info->{authorThumbnails}[0]{url};
- }
-
- ref($info->{videoThumbnails}) eq 'ARRAY' or return '';
-
- my @thumbs = @{$info->{videoThumbnails}};
- my @wanted = grep{$_->{quality} eq $type} @thumbs;
-
- if (@wanted) {
- return $wanted[0]{url};
- }
-
- warn "[!] Couldn't find thumbnail of type <<$type>>...";
- $thumbs[0]{url};
-}
-
-sub get_channel_title {
- my ($self, $info) = @_;
- #$info->{snippet}{channelTitle} || $self->get_channel_id($info);
- $info->{author};
-}
-
-sub get_author {
- my ($self, $info) = @_;
- $info->{author};
-}
-
-sub get_comment_id {
- my ($self, $info) = @_;
- $info->{commentId};
-}
-
-sub get_comment_content {
- my ($self, $info) = @_;
- $info->{content};
-}
-
-sub get_id {
- my ($self, $info) = @_;
- #$info->{id};
- $info->{videoId};
-}
-
-sub get_channel_id {
- my ($self, $info) = @_;
- #$info->{snippet}{resourceId}{channelId} // $info->{snippet}{channelId};
- $info->{authorId};
-}
-
-sub get_category_id {
- my ($self, $info) = @_;
- #$info->{snippet}{resourceId}{categoryId} // $info->{snippet}{categoryId};
- #"unknown";
- $info->{genre} // 'Unknown';
-}
-
-sub get_category_name {
- my ($self, $info) = @_;
-
- state $categories = {
- 1 => 'Film & Animation',
- 2 => 'Autos & Vehicles',
- 10 => 'Music',
- 15 => 'Pets & Animals',
- 17 => 'Sports',
- 19 => 'Travel & Events',
- 20 => 'Gaming',
- 22 => 'People & Blogs',
- 23 => 'Comedy',
- 24 => 'Entertainment',
- 25 => 'News & Politics',
- 26 => 'Howto & Style',
- 27 => 'Education',
- 28 => 'Science & Technology',
- 29 => 'Nonprofits & Activism',
- };
-
- #$categories->{$self->get_category_id($info) // ''} // 'Unknown';
-
- $info->{genre} // 'Unknown';
-}
-
-sub get_publication_date {
- my ($self, $info) = @_;
- #$self->format_date($info->{snippet}{publishedAt});
- #$self->format_date
- require Time::Piece;
- my $time = Time::Piece->new($info->{published});
- $time->strftime("%d %B %Y");
-}
-
-sub get_publication_age {
- my ($self, $info) = @_;
- ($info->{publishedText} // '') =~ s/\sago\z//r;;
-}
-
-sub get_publication_age_approx {
- my ($self, $info) = @_;
-
- my $age = $self->get_publication_age($info) // '';
-
- if ($age =~ /hour|min|sec/) {
- return "0d";
- }
-
- if ($age =~ /^(\d+) day/) {
- return "$1d";
- }
-
- if ($age =~ /^(\d+) week/) {
- return "$1w";
- }
-
- if ($age =~ /^(\d+) month/) {
- return "$1m";
- }
-
- if ($age =~ /^(\d+) year/) {
- return "$1y";
- }
-
- return $age;
-}
-
-sub get_duration {
- my ($self, $info) = @_;
- #$self->format_duration($info->{contentDetails}{duration});
- #$self->format_duration($info->{lengthSeconds});
- $info->{lengthSeconds};
-}
-
-sub get_time {
- my ($self, $info) = @_;
-
- if ($info->{liveNow}) {
- return 'LIVE';
- }
-
- $self->format_time($self->get_duration($info));
-
- #$self->format_time($self->get_duration($info));
-}
-
-sub get_definition {
- my ($self, $info) = @_;
- #uc($info->{contentDetails}{definition} // '-');
- #...;
- "unknown";
-}
-
-sub get_dimension {
- my ($self, $info) = @_;
- #uc($info->{contentDetails}{dimension});
- #...;
- "unknown";
-}
-
-sub get_caption {
- my ($self, $info) = @_;
- #$info->{contentDetails}{caption};
- #...;
- "unknown";
-}
-
-sub get_views {
- my ($self, $info) = @_;
- $info->{viewCount} // 0;
-}
-
-sub get_views_approx {
- my ($self, $info) = @_;
- my $views = $self->get_views($info);
-
- if ($views < 1000) {
- return $views;
- }
-
- if ($views >= 10 * 1e9) { # ten billions
- return sprintf("%dB", int($views / 1e9));
- }
-
- if ($views >= 1e9) { # billions
- return sprintf("%.2gB", $views / 1e9);
- }
-
- if ($views >= 10 * 1e6) { # ten millions
- return sprintf("%dM", int($views / 1e6));
- }
-
- if ($views >= 1e6) { # millions
- return sprintf("%.2gM", $views / 1e6);
- }
-
- if ($views >= 10 * 1e3) { # ten thousands
- return sprintf("%dK", int($views / 1e3));
- }
-
- if ($views >= 1e3) { # thousands
- return sprintf("%.2gK", $views / 1e3);
- }
-
- return $views;
-}
-
-sub get_likes {
- my ($self, $info) = @_;
- $info->{likeCount} // 0;
-}
-
-sub get_dislikes {
- my ($self, $info) = @_;
- $info->{dislikeCount} // 0;
-}
-
-sub get_comments {
- my ($self, $info) = @_;
- #$info->{statistics}{commentCount};
- 1;
-}
-
-{
- no strict 'refs';
- foreach my $pair (
- [playlist => {'playlist' => 1}],
- [channel => {'channel' => 1}],
- [video => {'video' => 1, 'playlistItem' => 1}],
- [subscription => {'subscription' => 1}],
- [activity => {'activity' => 1}],
- ) {
-
- *{__PACKAGE__ . '::' . 'is_' . $pair->[0]} = sub {
- my ($self, $item) = @_;
-
- if ($pair->[0] eq 'video') {
- return 1 if exists $item->{videoId};
- }
-
- exists $pair->[1]{$item->{type} // ''};
-
- #~ if (ref($item->{id}) eq 'HASH') {
- #~ if (exists $pair->[1]{$item->{id}{kind}}) {
- #~ return 1;
- #~ }
- #~ }
- #~ elsif (exists $item->{kind}) {
- #~ if (exists $pair->[1]{$item->{kind}}) {
- #~ return 1;
- #~ }
- #~ }
-
- #~ return;
- };
-
- }
-}
-
-sub is_channelID {
- my ($self, $id) = @_;
- $id || return;
- $id eq 'mine' or $id =~ /^UC[-a-zA-Z0-9_]{22}\z/;
-}
-
-sub is_videoID {
- my ($self, $id) = @_;
- $id || return;
- $id =~ /^[-a-zA-Z0-9_]{11}\z/;
-}
-
-sub period_to_date {
- my ($self, $amount, $period) = @_;
-
- state $day = 60 * 60 * 24;
- state $week = $day * 7;
- state $month = $day * 30.4368;
- state $year = $day * 365.242;
-
- my $time = $amount * (
- $period =~ /^d/i ? $day
- : $period =~ /^w/i ? $week
- : $period =~ /^m/i ? $month
- : $period =~ /^y/i ? $year
- : 0
- );
-
- my $now = time;
- my @time = gmtime($now - $time);
- join('-', $time[5] + 1900, sprintf('%02d', $time[4] + 1), sprintf('%02d', $time[3])) . 'T'
- . join(':', sprintf('%02d', $time[2]), sprintf('%02d', $time[1]), sprintf('%02d', $time[0])) . 'Z';
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Utils
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2012-2020 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Utils
diff --git a/lib/WWW/StrawViewer/VideoCategories.pm b/lib/WWW/StrawViewer/VideoCategories.pm
deleted file mode 100644
index 30e2e6e..0000000
--- a/lib/WWW/StrawViewer/VideoCategories.pm
+++ /dev/null
@@ -1,97 +0,0 @@
-package WWW::StrawViewer::VideoCategories;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::VideoCategories - videoCategory resource handler.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $cats = $obj->video_categories();
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_videoCategories_url {
- my ($self, %opts) = @_;
-
- $self->_make_feed_url(
- 'videoCategories',
- hl => $self->get_hl,
- %opts,
- );
-}
-
-=head2 video_categories()
-
-Return video categories for a specific region ID.
-
-=cut
-
-sub video_categories {
- my ($self) = @_;
-
- require File::Spec;
-
- my $region = $self->get_regionCode() // 'US';
- my $url = $self->_make_videoCategories_url(regionCode => $region);
- my $file = File::Spec->catfile($self->get_config_dir, "categories-$region-" . $self->get_hl() . ".json");
-
- my $json;
- if (open(my $fh, '<:utf8', $file)) {
- local $/;
- $json = <$fh>;
- close $fh;
- }
- else {
- $json = $self->lwp_get($url, simple => 1);
- open my $fh, '>:utf8', $file;
- print {$fh} $json;
- close $fh;
- }
-
- return $self->parse_json_string($json);
-}
-
-=head2 video_category_id_info($cagegory_id)
-
-Return info for the comma-separated specified category ID(s).
-
-=cut
-
-sub video_category_id_info {
- my ($self, $id) = @_;
- return $self->_get_results($self->_make_videoCategories_url(id => $id));
-}
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::VideoCategories
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::VideoCategories
diff --git a/lib/WWW/StrawViewer/Videos.pm b/lib/WWW/StrawViewer/Videos.pm
deleted file mode 100644
index 11bf60b..0000000
--- a/lib/WWW/StrawViewer/Videos.pm
+++ /dev/null
@@ -1,230 +0,0 @@
-package WWW::StrawViewer::Videos;
-
-use utf8;
-use 5.014;
-use warnings;
-
-=head1 NAME
-
-WWW::StrawViewer::Videos - videos handler.
-
-=head1 SYNOPSIS
-
- use WWW::StrawViewer;
- my $obj = WWW::StrawViewer->new(%opts);
- my $info = $obj->video_details($videoID);
-
-=head1 SUBROUTINES/METHODS
-
-=cut
-
-sub _make_videos_url {
- my ($self, %opts) = @_;
- return $self->_make_feed_url('videos', %opts);
-}
-
-{
- no strict 'refs';
- foreach my $part (
- qw(
- id
- snippet
- contentDetails
- fileDetails
- player
- liveStreamingDetails
- processingDetails
- recordingDetails
- statistics
- status
- suggestions
- topicDetails
- )
- ) {
- *{__PACKAGE__ . '::' . 'video_' . $part} = sub {
- my ($self, $id) = @_;
- return $self->_get_results($self->_make_videos_url(id => $id, part => $part));
- };
- }
-}
-
-=head2 videos_from_category($category_id)
-
-Get videos from a category ID.
-
-=cut
-
-sub videos_from_category {
- my ($self, $cat_id) = @_;
- $self->_get_results(
- $self->_make_videos_url(
- chart => $self->get_chart,
- videoCategoryId => $cat_id,
- )
- );
-}
-
-=head2 trending_videos_from_category($category_id)
-
-Get popular videos from a category ID.
-
-=cut
-
-sub trending_videos_from_category {
- my ($self, $cat_id) = @_;
-
- my $results = do {
- local $self->{publishedAfter} = do {
- state $yv_utils = WWW::StrawViewer::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("");
- };
-
- return $results;
-}
-
-=head2 popular_videos($channel_id)
-
-Get the most popular videos for a given channel ID.
-
-=cut
-
-sub popular_videos {
- my ($self, $id) = @_;
-
- my $results = do {
- local $self->{channelId} = $id;
- local $self->{order} = 'viewCount';
- $self->search_videos("");
- };
-
- return $results;
-}
-
-=head2 my_likes()
-
-Get the videos liked by the authenticated user.
-
-=cut
-
-sub my_likes {
- my ($self) = @_;
- $self->get_access_token() // return;
- $self->_get_results($self->_make_videos_url(myRating => 'like', pageToken => $self->page_token));
-}
-
-=head2 my_dislikes()
-
-Get the videos disliked by the authenticated user.
-
-=cut
-
-sub my_dislikes {
- my ($self) = @_;
- $self->get_access_token() // return;
- $self->_get_results($self->_make_videos_url(myRating => 'dislike', pageToken => $self->page_token));
-}
-
-=head2 send_rating_to_video($videoID, $rating)
-
-Send rating to a video. $rating can be either 'like' or 'dislike'.
-
-=cut
-
-sub send_rating_to_video {
- my ($self, $video_id, $rating) = @_;
-
- if ($rating eq 'none' or $rating eq 'like' or $rating eq 'dislike') {
- my $url = $self->_simple_feeds_url('videos/rate', id => $video_id, rating => $rating);
- return defined($self->lwp_post($url, $self->_auth_lwp_header()));
- }
-
- return;
-}
-
-=head2 like_video($videoID)
-
-Like a video. Returns true on success.
-
-=cut
-
-sub like_video {
- my ($self, $video_id) = @_;
- $self->send_rating_to_video($video_id, 'like');
-}
-
-=head2 dislike_video($videoID)
-
-Dislike a video. Returns true on success.
-
-=cut
-
-sub dislike_video {
- my ($self, $video_id) = @_;
- $self->send_rating_to_video($video_id, 'dislike');
-}
-
-=head2 videos_details($id, $part)
-
-Get info about a videoID, such as: channelId, title, description,
-tags, and categoryId.
-
-Available values for I<part> are: I<id>, I<snippet>, I<contentDetails>
-I<player>, I<statistics>, I<status> and I<topicDetails>.
-
-C<$part> string can contain more values, comma-separated.
-
-Example:
-
- part => 'snippet,contentDetails,statistics'
-
-When C<$part> is C<undef>, it defaults to I<snippet>.
-
-=cut
-
-sub video_details {
- my ($self, $id, $fields) = @_;
- $fields //= $self->basic_video_info_fields;
- $self->_get_results($self->_make_feed_url("videos/$id", fields => $fields));
-}
-
-=head2 Return details
-
-Each function returns a HASH ref, with a key called 'results', and another key, called 'url'.
-
-The 'url' key contains a string, which is the URL for the retrieved content.
-
-The 'results' key contains another HASH ref with the keys 'etag', 'items' and 'kind'.
-From the 'results' key, only the 'items' are relevant to us. This key contains an ARRAY ref,
-with a HASH ref for each result. An example of the item array's content are shown below.
-
-=cut
-
-=head1 AUTHOR
-
-Trizen, C<< <echo dHJpemVuQHByb3Rvbm1haWwuY29tCg== | base64 -d> >>
-
-
-=head1 SUPPORT
-
-You can find documentation for this module with the perldoc command.
-
- perldoc WWW::StrawViewer::Videos
-
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright 2013-2015 Trizen.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of either: the GNU General Public License as published
-by the Free Software Foundation; or the Artistic License.
-
-See L<http://dev.perl.org/licenses/> for more information.
-
-=cut
-
-1; # End of WWW::StrawViewer::Videos