Initial commit
This commit is contained in:
155
YTMusicAPI/Parsers/Songs.pm
Normal file
155
YTMusicAPI/Parsers/Songs.pm
Normal file
@@ -0,0 +1,155 @@
|
||||
package YTMusicAPI::Parsers::Songs;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Exporter 'import';
|
||||
use Regexp::Common qw(number);
|
||||
|
||||
use YTMusicAPI::Parsers::Utils;
|
||||
use YTMusicAPI::Navigation;
|
||||
|
||||
sub parse_song_artists {
|
||||
my ( $data, $index ) = @_;
|
||||
my $flex_item = get_flex_column_item( $data, $index );
|
||||
|
||||
if ( !$flex_item ) {
|
||||
return undef;
|
||||
}
|
||||
else {
|
||||
my $runs = $flex_item->{"text"}{"runs"};
|
||||
return parse_song_artists_runs($runs);
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_song_artists_runs {
|
||||
my ($runs) = @_;
|
||||
my @artists = ();
|
||||
|
||||
for my $j ( 0 .. int( @$runs / 2 ) ) {
|
||||
push @artists,
|
||||
{
|
||||
"name" => $runs->[ $j * 2 ]{"text"},
|
||||
"id" => nav( $runs->[ $j * 2 ], $NAVIGATION_BROWSE_ID, 1 )
|
||||
};
|
||||
}
|
||||
return \@artists;
|
||||
}
|
||||
|
||||
sub parse_song_runs {
|
||||
my ($runs) = @_;
|
||||
my %parsed = ( "artists" => [] );
|
||||
my $i = 0;
|
||||
|
||||
for my $run (@$runs) {
|
||||
if ( $i % 2 ) { # uneven items are always separators
|
||||
$i++;
|
||||
next;
|
||||
}
|
||||
|
||||
my $text = $run->{"text"};
|
||||
|
||||
if ( exists $run->{"navigationEndpoint"} ) { # artist or album
|
||||
my $item = {
|
||||
"name" => $text,
|
||||
"id" => nav( $run, $NAVIGATION_BROWSE_ID, 1 )
|
||||
};
|
||||
|
||||
if (
|
||||
$item->{"id"}
|
||||
&& ( $item->{"id"} =~ /^MPRE/
|
||||
|| $item->{"id"} =~ /release_detail/ )
|
||||
)
|
||||
{ # album
|
||||
$parsed{"album"} = $item;
|
||||
}
|
||||
else { # artist
|
||||
push @{ $parsed{"artists"} }, $item;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
# note: YT uses non-breaking space \xa0 to separate number and magnitude
|
||||
if ( $text =~ /^\d([^ ])* [^ ]*$/ && $i > 0 ) {
|
||||
( $parsed{"views"} ) = split( / /, $text, 2 );
|
||||
}
|
||||
elsif ( $text =~ /^(\d+:)*\d+:\d+$/ ) {
|
||||
$parsed{"duration"} = $text;
|
||||
$parsed{"duration_seconds"} = parse_duration($text);
|
||||
}
|
||||
elsif ( $text =~ /^\d{4}$/ ) {
|
||||
$parsed{"year"} = $text;
|
||||
}
|
||||
else { # artist without id
|
||||
push @{ $parsed{"artists"} },
|
||||
{ "name" => $text, "id" => undef };
|
||||
}
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
return \%parsed;
|
||||
}
|
||||
|
||||
sub parse_song_album {
|
||||
my ( $data, $index ) = @_;
|
||||
my $flex_item = get_flex_column_item( $data, $index );
|
||||
my $browse_id = nav( $flex_item, $TEXT_RUN + $NAVIGATION_BROWSE_ID, 1 );
|
||||
return !$flex_item
|
||||
? undef
|
||||
: { "name" => get_item_text( $data, $index ), "id" => $browse_id };
|
||||
}
|
||||
|
||||
sub parse_song_library_status {
|
||||
my ($item) = @_;
|
||||
my $library_status =
|
||||
nav( $item, [ $TOGGLE_MENU, "defaultIcon", "iconType" ], 1 );
|
||||
return $library_status eq "LIBRARY_SAVED";
|
||||
}
|
||||
|
||||
sub parse_song_menu_tokens {
|
||||
my ($item) = @_;
|
||||
my $toggle_menu = $item->{$TOGGLE_MENU};
|
||||
|
||||
my $library_add_token =
|
||||
nav( $toggle_menu, [ "defaultServiceEndpoint", $FEEDBACK_TOKEN ], 1 );
|
||||
my $library_remove_token =
|
||||
nav( $toggle_menu, [ "toggledServiceEndpoint", $FEEDBACK_TOKEN ], 1 );
|
||||
|
||||
my $in_library = parse_song_library_status($item);
|
||||
if ($in_library) {
|
||||
my $tmp = $library_remove_token;
|
||||
$library_add_token = $library_remove_token;
|
||||
$library_remove_token = $tmp;
|
||||
}
|
||||
|
||||
return { "add" => $library_add_token, "remove" => $library_remove_token };
|
||||
}
|
||||
|
||||
sub parse_like_status {
|
||||
my ($service) = @_;
|
||||
my @status = ( "LIKE", "INDIFFERENT" );
|
||||
|
||||
my $status_index = 0;
|
||||
for my $i ( 0 .. $#status ) {
|
||||
if ( $status[$i] eq $service->{"likeEndpoint"}{"status"} ) {
|
||||
$status_index = $i;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $status[ $status_index - 1 ];
|
||||
}
|
||||
|
||||
our @EXPORT = qw(
|
||||
parse_song_artists
|
||||
parse_song_artists_runs
|
||||
parse_song_runs
|
||||
parse_song_album
|
||||
parse_song_library_status
|
||||
parse_song_menu_tokens
|
||||
parse_like_status
|
||||
);
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user