## Please see file perltidy.ERR package Peertube::DL::Downloaders; use strict; use warnings; use feature 'say'; use Symbol 'gensym'; use IPC::Open3; use File::Basename; use JSON; use Data::Dumper; use Mojo::DOM; use File::MimeInfo; use Peertube::DL::Javascript; use Peertube::DL::Utils; sub youtube { my $ua = shift; my $response = shift; my $options = shift; my $dom = Mojo::DOM->new( $response->decoded_content ); my $script_tag = $dom->find('script')->grep( sub { $_[0]->text =~ /var ytInitialPlayerResponse =/; } )->first; my ($ytInitialPlayerResponse) = $script_tag->text =~ /^var ytInitialPlayerResponse = (.*?\});var meta/; $ytInitialPlayerResponse = JSON::from_json($ytInitialPlayerResponse); my $microformat = $ytInitialPlayerResponse->{microformat}{playerMicroformatRenderer}; $ytInitialPlayerResponse = $ytInitialPlayerResponse->{streamingData}; if ( defined $options->{format} ) { my $format = $options->{format}; ($format) = grep { $_->{itag} eq $format } ( scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} } ? @{ $ytInitialPlayerResponse->{adaptiveFormats} } : (), scalar @{ $ytInitialPlayerResponse->{formats} } ? @{ $ytInitialPlayerResponse->{formats} } : () ); my $url_data = $format->{signatureCipher}; $url_data = { map { my ( $a, $b ) = /(.*?)=(.*)$/; ( $a => Peertube::DL::Utils::uri_decode( Peertube::DL::Utils::uri_decode($b) ) ) } split '&', $url_data }; say Data::Dumper::Dumper $url_data; my ($player_url) = $response->decoded_content =~ m/"jsUrl"\s*:\s*("[^"]+")/; $player_url = JSON::from_json( $player_url, { allow_nonref => 1 } ); $player_url = 'https://www.youtube.com' . $player_url unless $player_url =~ m'^https://www.youtube.com'; say $player_url; my $hostname = $player_url =~ s/https?:\/\///r; $hostname = $hostname =~ s/\/.*$//; $hostname = JSON::encode_json($hostname); my $js = Peertube::DL::Javascript->new; my $player_response = $ua->get($player_url); my $regexes_search_function_name = [ qr/\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?(?:[a-zA-Z0-9]|\$)+)\(/, qr/\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?(?:[a-zA-Z0-9]|\$)+)\(/, qr/(?:\b|(?:[^a-zA-Z0-9]|\$))(?(?:[a-zA-Z0-9]|\$){2})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)/, qr/(?(?:[a-zA-Z0-9]|\$)+)\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)/, ]; my $function_name_regen_sig; for my $regex (@$regexes_search_function_name) { ($function_name_regen_sig) = $player_response->decoded_content =~ /$regex/; last if defined $function_name_regen_sig; } my ($extract_function_sig) = $player_response->decoded_content =~ m/\n(${function_name_regen_sig}=function\([a-zA-Z]+\)\{.*?\};)\n/; my ($class_decoding) = $extract_function_sig =~ /;([a-zA-Z]+)\.[a-zA-Z]+\(/; my ($class_decoding_code) = $player_response->decoded_content =~ /;(var ${class_decoding}=\{.*?\}\};)/s; $js->evalJS( join "\n", $class_decoding_code ); $js->evalJS( join "\n", $extract_function_sig ); my $signature = $js->callJSFunction( $function_name_regen_sig, $url_data->{s} ); my $url = $url_data->{url} . "&sig=${signature}"; say Data::Dumper::Dumper $format; my $mime_type = $format->{mimeType} =~ s/;.*$//r; say $mime_type; my $extension = scalar File::MimeInfo::extensions($mime_type); $extension = 'mp4' if $mime_type eq 'video/mp4'; say $url; return { url => $url, filename => $microformat->{title}{simpleText} . '.' . $extension, }; } else { return { options => { list_formats => 1 }, title => $microformat->{title}{simpleText}, description => $microformat->{description}{simpleText}, formats => [ map { { id => $_->{itag}, mimeType => $_->{mimeType} } } ( scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} } ? @{ $ytInitialPlayerResponse->{adaptiveFormats} } : (), scalar @{ $ytInitialPlayerResponse->{formats} } ? @{ $ytInitialPlayerResponse->{formats} } : () ) ] }; } } sub kjanime { my $ua = shift; my $response = shift; my $dom = Mojo::DOM->new( $response->decoded_content ); my $hotlink_span = $dom->find('.spoikj .ddserver')->grep( sub { my $i = shift; $i->text =~ /HotLink/; } )->first; my ($k_poi) = $hotlink_span->attr('onclick') =~ /getKpoi\((.*)\)/; $k_poi =~ s/'//g; my ( $t, $s, $l ) = ( split /,/, $k_poi ); my $url_get_php = 'https://kjanime.net/link/get.php?t=' . Peertube::DL::Utils::uri_encode($t) . '&s=' . Peertube::DL::Utils::uri_encode($s) . '&l=' . Peertube::DL::Utils::uri_encode($l); my $get_php_response = $ua->get( $url_get_php, 'X-Requested-With' => 'XMLHttpRequest', ); $dom = Mojo::DOM->new( $get_php_response->decoded_content ); my $links = [ map { $_->attr('href') =~ s/^http:\/\//https:\/\//r } @{ $dom->find('a')->to_array } ]; return { options => { list => 1 }, urls => $links }; } sub kjanime_ch { my $ua = shift; my $response = shift; my ($id) = $response->filename; say $id; my $param = join '', map { Peertube::DL::Utils::uri_decode("%$_") } unpack( "(A2)*", $id ); say $param; # FORMAT: KJA://70714B6E314943383135712B72582B70713768797A4B6E4D734D474775773D3D/1 # REQUEST: GET https://hotlink-api.kjanime.net/dl/serie.php?id=70714B6E314943383135712B72582B70713768797A4B6E4D734D474775773D3D&ep=1 $param =~ s/^KJA:\/\///; my ( $real_id, $ep ) = split '/', $param; my $url_serie_php = 'https://hotlink-api.kjanime.net/dl/serie.php?id=' . Peertube::DL::Utils::uri_encode($real_id) . '&ep=' . Peertube::DL::Utils::uri_encode($ep); say $url_serie_php; my $response_serie_php = $ua->get( $url_serie_php, 'X-Requested-With' => 'XMLHttpRequest', ); my $download_data = JSON::decode_json( $response_serie_php->decoded_content ); say Data::Dumper::Dumper $download_data; $download_data->{filename} = delete $download_data->{name}; $download_data->{url} = delete $download_data->{link}; return $download_data; } sub gocdn { my $ua = shift; my $response = shift; my ($id) = $response->decoded_content =~ /gocdn\.html#(.+?)"/; die "Id undefined" if !defined $id; my $url_gocdn = 'https://streamium.xyz/gocdn.php?v=' . $id; my $response_gocdn = $ua->get($url_gocdn); die $response_gocdn->status_line . ' from ' . $url_gocdn unless $response_gocdn->is_success; my $google_url = JSON::decode_json( $response_gocdn->decoded_content )->{file}; my ($filename) = $response->base =~ s/^.*\///gr . '.mp4'; return { url => $google_url, filename => $filename }; } sub animeid { my $ua = shift; my $response = shift; my @order = ( 'id', 'title', 'refer' ); my $url = $response->base; my $url_ajax = 'https://animeid.to/ajax.php?'; my ($get_params) = $response->decoded_content =~ /animeid\.to\/streaming\.php\?(.*?)"/; $get_params = { map { my ( $key, $value ) = /^(.*?)=(.*)$/; ( $key, Peertube::DL::Utils::uri_decode($value) ) } split '&', $get_params }; say "Got from $url params for ajax:"; print Data::Dumper::Dumper $get_params; say 'Adding passed url as refer.'; $get_params->{refer} = $url; my $filename = $get_params->{title}; $url_ajax .= join '&', map { join '=', ( $_ => Peertube::DL::Utils::uri_encode( $get_params->{$_} ) ) } @order; say 'Getting video location from: ' . $url_ajax; my $ajax_data = $ua->get( $url_ajax, Referer => $url, Host => 'animeid.to', 'X-Requested-With' => 'XMLHttpRequest', )->decoded_content; say "Decoding json... $ajax_data"; $ajax_data = JSON::decode_json $ajax_data; die 'No video source found.' if ( !defined $ajax_data->{source} ); my $download_redirect_url = $ajax_data->{source}[0]{file} // die "No url found."; my $extension = $ajax_data->{source}[0]{type} // die "No extension found."; $filename .= ".$extension"; say "Getting redirect to download url from $download_redirect_url..."; my $video_response = $ua->get( $download_redirect_url, Referer => $url, Host => 'animeid.to', ); if ( $video_response->is_redirect ) { my $video_location = $video_response->header('Location'); die "No redirection." unless $video_location; return { url => $video_location, filename => $filename, }; } else { die 'Getting redirect failed because: ' . $video_response->status_line; } } 1;