129 lines
2.7 KiB
Perl
129 lines
2.7 KiB
Perl
package YTMusicAPI::Helpers;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Exporter 'import';
|
|
use POSIX qw(strftime locale_h);
|
|
use LWP::UserAgent;
|
|
use JSON;
|
|
use HTTP::Cookies;
|
|
use Digest::SHA qw(sha1_hex);
|
|
use Time::HiRes qw(time);
|
|
use Unicode::Normalize;
|
|
use locale;
|
|
|
|
use YTMusicAPI::Constants qw(YTM_DOMAIN USER_AGENT);
|
|
|
|
sub initialize_headers {
|
|
return {
|
|
'user-agent' => USER_AGENT,
|
|
'accept' => '*/*',
|
|
'accept-encoding' => 'gzip, deflate',
|
|
'content-type' => 'application/json',
|
|
'content-encoding' => 'gzip',
|
|
'origin' => YTM_DOMAIN,
|
|
};
|
|
}
|
|
|
|
sub initialize_context {
|
|
return {
|
|
'context' => {
|
|
'client' => {
|
|
'clientName' => "WEB_REMIX",
|
|
'clientVersion' => "1."
|
|
. strftime( "%Y%m%d", gmtime )
|
|
. ".01.00",
|
|
},
|
|
'user' => {},
|
|
}
|
|
};
|
|
}
|
|
|
|
sub get_visitor_id {
|
|
my ($content) = @_;
|
|
my @matches = $content =~ /ytcfg\.set\s*\(\s*({.+?})\s*\)\s*;/g;
|
|
my $visitor_id = "";
|
|
|
|
if (@matches) {
|
|
my $ytcfg = decode_json( $matches[0] );
|
|
$visitor_id = $ytcfg->{"VISITOR_DATA"} // "";
|
|
}
|
|
|
|
return $visitor_id;
|
|
}
|
|
|
|
sub sapisid_from_cookie {
|
|
my ($raw_cookie) = @_;
|
|
my $cookie_jar = HTTP::Cookies->new();
|
|
$raw_cookie =~ s/\"//g; # Replace double quotes
|
|
$cookie_jar->parse_headers( { 'set-cookie' => $raw_cookie } );
|
|
my $sapisid = $cookie_jar->get_cookie("__Secure-3PAPISID");
|
|
return $sapisid;
|
|
}
|
|
|
|
sub get_authorization {
|
|
my ($auth) = @_;
|
|
my $unix_timestamp = int(time);
|
|
my $digest = sha1_hex( $unix_timestamp . " " . $auth );
|
|
return "SAPISIDHASH " . $unix_timestamp . "_" . $digest;
|
|
}
|
|
|
|
sub to_int {
|
|
my ($string) = @_;
|
|
$string = NFKD($string);
|
|
my $number_string = $string =~ s/\D//gr;
|
|
setlocale( LC_ALL, "en_US.UTF-8" );
|
|
my $int_value;
|
|
|
|
eval { $int_value = atoi($number_string); };
|
|
|
|
if ($@) {
|
|
$number_string =~ s/,//g;
|
|
$int_value = int($number_string);
|
|
}
|
|
|
|
return $int_value;
|
|
}
|
|
|
|
sub sum_total_duration {
|
|
my ($item) = @_;
|
|
|
|
return 0 unless exists $item->{tracks};
|
|
|
|
my $total_duration =
|
|
sum( map { exists $_->{duration_seconds} ? $_->{duration_seconds} : 0 }
|
|
@{ $item->{tracks} } );
|
|
|
|
return $total_duration;
|
|
}
|
|
|
|
sub array_index {
|
|
my ( $list, $value ) = @_;
|
|
my $index = 0;
|
|
my $found_index = -1;
|
|
|
|
foreach my $type (@$list) {
|
|
if ( $type eq $value ) {
|
|
$found_index = $index;
|
|
last;
|
|
}
|
|
$index++;
|
|
}
|
|
|
|
return $found_index;
|
|
}
|
|
|
|
our @EXPORT = qw(
|
|
initialize_headers
|
|
initialize_context
|
|
get_visitor_id
|
|
sapisid_from_cookie
|
|
get_authorization
|
|
to_int
|
|
sum_total_duration
|
|
array_index
|
|
);
|
|
|
|
1;
|