Guest User

yandex musik downloader

a guest
Jan 14th, 2014
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 22.98 KB | None | 0 0
  1. package YandexMusikDownloader;
  2. use Mojo::Base -base;
  3. use Mojo::UserAgent;
  4. use Mojo::JSON;
  5. use Mojo::URL;
  6. use POSIX qw(strftime);
  7. use autodie;
  8. use Cwd;
  9. use File::Spec;
  10. use File::Path qw/make_path/;
  11. use utf8;
  12.  
  13. $ENV{MOJO_MAX_MESSAGE_SIZE} = 9_999_999_999;
  14.  
  15. has ua => sub{
  16.     my $ua = Mojo::UserAgent->new;
  17.     #thanx http://techblog.willshouse.com/2012/01/03/most-common-user-agents/ )
  18.     my $uas=[
  19.             'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  20.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  21.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11',
  22.             'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0',
  23.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  24.             'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  25.             'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  26.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71',
  27.             'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53',
  28.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  29.             'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0',
  30.             'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  31.             'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  32.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0',
  33.             'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
  34.             'Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53',
  35.             'Mozilla/5.0 (Windows NT 5.1; rv:26.0) Gecko/20100101 Firefox/26.0',
  36.             'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  37.             'Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0',
  38.             'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0',
  39.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  40.             'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0',
  41.             'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.72 Safari/537.36',
  42.             'Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0',
  43.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:26.0) Gecko/20100101 Firefox/26.0',
  44.             'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/31.0.1650.63 Chrome/31.0.1650.63 Safari/537.36',
  45.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:26.0) Gecko/20100101 Firefox/26.0',
  46.             'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
  47.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  48.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10',
  49.             'Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0',
  50.             'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0',
  51.             'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
  52.             'Mozilla/5.0 (Windows NT 5.1; rv:25.0) Gecko/20100101 Firefox/25.0',
  53.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/6.1.1 Safari/537.73.11',
  54.             'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  55.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.71 (KHTML, like Gecko) Version/6.1 Safari/537.71',
  56.             'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
  57.             'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:26.0) Gecko/20100101 Firefox/26.0',
  58.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0',
  59.             'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko',
  60.             'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  61.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
  62.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:26.0) Gecko/20100101 Firefox/26.0',
  63.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/6.1.1 Safari/537.73.11',
  64.             'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_3 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B511 Safari/9537.53',
  65.             'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0',
  66.             'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
  67.             'Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/31.0.1650.18 Mobile/11B554a Safari/8536.25',
  68.             'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36',
  69.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1',
  70.             'Mozilla/5.0 (Windows NT 6.0; rv:26.0) Gecko/20100101 Firefox/26.0',
  71.             'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)',
  72.             'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Safari/537.36',
  73.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.68 Safari/537.36',
  74.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.71 (KHTML, like Gecko) Version/6.1 Safari/537.71',
  75.             'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0',
  76.             'Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16',
  77.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36',
  78.             'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.41 Safari/537.36',
  79.             'Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25',
  80.             'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36',
  81.             'Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0',
  82.             'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0',
  83.             'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.72 Safari/537.36',
  84.             'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36',
  85.             'Mozilla/5.0 (iPod; CPU iPhone OS 6_1_5 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B400 Safari/8536.25',
  86.             'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36'
  87.             ];
  88.  
  89.     #Cloacking...
  90.     $ua->transactor->name($uas->[ int rand((scalar @{$uas}) -1)] );
  91.     $ua->inactivity_timeout(3000);
  92.     $ua->connect_timeout(3000);
  93.     $ua->request_timeout(3000);
  94.     $ua->max_redirects(20);
  95.     return $ua;
  96. };
  97.  
  98. has json => sub { Mojo::JSON->new };
  99.  
  100. has artist_albums_url =>  sub { Mojo::URL->new('http://music.yandex.ru/get/artist_albums_list.xml?artist=0'); };
  101. has album_tracks_url =>  'http://music.yandex.ru/fragment/album/';
  102. has info_url => 'http://storage.music.yandex.ru/download-info/';
  103. has ref_url => 'http://swf.static.yandex.net/music/service-player.swf?v=12.27.1&proxy-host=http://storage.music.yandex.ru';
  104. has base_path => './yandex-musik/';
  105.  
  106. sub artist_albums {
  107.     my ($self, $artist_id) = (shift, shift);
  108.    
  109.     my $artist_url = $self->artist_albums_url->clone;
  110.     $artist_url->query->param( artist => $artist_id);
  111.    
  112.     my $tx = $self->ua->get($artist_url);
  113.     warn 'ERROR get artist_albums for ' . $artist_id . ' : ' . $tx->error and return undef if $tx->error;
  114.  
  115.     return $tx->res->json;
  116. }
  117.  
  118. sub album_tracks {
  119.     my ($self, $album_id) = (shift, shift);
  120.     my $album_url = Mojo::URL->new( $self->album_tracks_url . $album_id );
  121.    
  122.     $album_url->query->param( prefix => 'facegen-' . strftime('%Y-%m-%dT00-00-00', localtime));
  123.        
  124.     my $tx = $self->ua->get($album_url => {Referer => $self->ref_url});
  125.     warn 'ERROR get album_tracks for ' . $album_url . ' : ' . $tx->error and return undef if $tx->error;
  126.    
  127.     my $res = $tx->res->dom->at('div.js-album');
  128.     unless( $res){
  129.         warn 'ERROR find album_tracks for ' . $album_url;
  130.        
  131.         return undef;
  132.     }
  133.    
  134.     $res = $res->{onclick};
  135.    
  136.     #fix content
  137.     utf8::encode($res);
  138.     $res =~ s/^return//;
  139.     $res =~ s/\'(.*?)\':/\"$1\":/g;
  140.     $res = $self->json->decode($res);
  141.    
  142.     return $res;
  143. }
  144.  
  145. sub download_track {
  146.     my ($self, $track_hash) = (shift, shift);
  147.    
  148.     my $artist = $track_hash->{artist};
  149.     $artist =~ s{/}{ }g;
  150.    
  151.     my $title = $track_hash->{title};
  152.     $title =~ s{/}{ }g;
  153.    
  154.     utf8::encode($artist);
  155.     utf8::encode($title);
  156.    
  157.     my $info_url_mp3 = $self->info_url . $track_hash->{storage_dir} . '/2.mp3?nc=' . rand;
  158.    
  159.     my $tx_info = $self->ua->get($info_url_mp3 => { Referer => $self->ref_url });
  160.     say 'ERROR GET INFO URL: ' . $tx_info->error and return undef if $tx_info->error;
  161.    
  162.     my $dom_host = $tx_info->res->dom->at('download-info regional-host') || $tx_info->res->dom->at('download-info host');
  163.     my $mp3_host = $dom_host->text;
  164.     my $mp3_s = $tx_info->res->dom->at('download-info s')->text;
  165.     my $mp3_ts = $tx_info->res->dom->at('download-info ts')->text;
  166.    
  167.     my $mp3_path = $tx_info->res->dom->at('download-info path')->text;
  168.    
  169.     my $test = substr($mp3_path,1)  . $mp3_s;
  170.     my $rpath = $self->track_path_pp($test);
  171.    
  172.     my $mp3_url = 'http://' . $mp3_host . '/get-mp3/' . $rpath . '/' . $mp3_ts  . $mp3_path . '?track-id=' . $track_hash->{id} . '&from=service-10-track-album&similarities-experiment=default';
  173.    
  174.    
  175.     my $mp3_local_path = File::Spec->catfile( getcwd, $self->base_path , $artist ,  $track_hash->{album});
  176.    
  177.     make_path($mp3_local_path) unless -d $mp3_local_path;
  178.     my $mp3_local = File::Spec->catfile($mp3_local_path, $artist . ' - ' . $title . '.mp3');
  179.    
  180.     say 'WORKING ON ' . $mp3_local . ' <<< ' . $mp3_url;
  181.     say 'SKIPPING coz exists ' . $mp3_local and return undef if -f $mp3_local;
  182.    
  183.     my $tx_mp3 = $self->ua->get($mp3_url => { Referer => $self->ref_url } );
  184.     say 'ERROR GET MP3: ' . $tx_mp3->error and return undef if $tx_mp3->error;
  185.    
  186.     open(my $mp3h, '>', $mp3_local);
  187.     binmode($mp3h);
  188.     print $mp3h $tx_mp3->res->body;
  189.     close($mp3h);
  190. }
  191.  
  192. sub download_album {
  193.     my ($self, $album_id) = (shift, shift);
  194.    
  195.     my $album_hash = $self->album_tracks( $album_id);
  196.    
  197.     for my $track_hash (@{$album_hash->{tracks}}){
  198.         $self->download_track( $track_hash );
  199.     }
  200. }
  201.  
  202. sub download_artist {
  203.     my ($self, $artist_id) = (shift, shift);
  204.    
  205.     my $albums_hash = $self->artist_albums( $artist_id );
  206.    
  207.     for my $album_id (@{$albums_hash->{albums}}){
  208.         $self->download_album($album_id);
  209.     }
  210. }
  211.  
  212. sub track_path_pp{
  213.         my $self = shift;
  214.         my $str = shift;
  215.                
  216.         sub to32{ unpack('i', pack('i', shift)); }
  217.         sub M_js {
  218.             my ($c1, $b1) = (shift, shift);
  219.             return to32( to32($c1 << $b1) | to32( ($c1 & 0xffffffff) >> (32 - $b1))); #>>>
  220.         }
  221.  
  222.         sub L_js {
  223.             my ($x, $c) = (shift, shift || 0);
  224.             my ($G, $b1, $k, $F, $d);
  225.             $k = to32($x & 2147483648);
  226.             $F = to32($c & 2147483648);
  227.             $G = to32($x & 1073741824);
  228.             $b1 =to32($c & 1073741824);
  229.             $d = to32($x & 1073741823) + to32($c & 1073741823);
  230.             if ( to32($G & $b1)) {
  231.                 return to32($d ^ 2147483648 ^ $k ^ $F);
  232.             }
  233.             if ($G | $b1) {
  234.                 if (to32($d & 1073741824)) {
  235.                     return to32($d ^ 3221225472 ^ $k ^ $F);
  236.                 } else {
  237.                     return to32($d ^ 1073741824 ^ $k ^ $F);
  238.                 }
  239.             } else {
  240.                 return to32($d ^ $k ^ $F);
  241.             }
  242.         }
  243.  
  244.         sub r_js{
  245.             my ($b1, $d, $c) = (shift, shift, shift);
  246.             return to32( to32($b1 & $d) | to32(to32(~$b1) & $c) );
  247.         }
  248.  
  249.         sub q_js {
  250.             my ($b1, $d, $c) = (shift, shift, shift);
  251.             return to32($b1 & $c) | to32($d & to32(~$c));
  252.         }
  253.  
  254.         sub p_js{
  255.             my ($b1, $d, $c) = (shift, shift, shift);
  256.             return to32($b1 ^ $d ^ $c);
  257.         }
  258.  
  259.         sub n_js {
  260.             my ($b1, $d, $c) = (shift, shift, shift);
  261.             return to32($d ^ to32($b1 | to32(~$c)));
  262.         }
  263.  
  264.         sub u_js {
  265.             my ($G, $F, $ab, $aa, $k, $H, $I) = (shift, shift, shift, shift, shift, shift, shift);
  266.             $G = L_js($G, L_js(L_js(r_js($F, $ab, $aa), $k), $I));
  267.             return L_js(M_js($G, $H), $F);
  268.         }
  269.  
  270.         sub f_js {
  271.             my ($G, $F, $ab, $aa, $k, $H, $I) = (shift, shift, shift, shift, shift, shift, shift);
  272.             $G = L_js($G, L_js(L_js(q_js($F, $ab, $aa), $k), $I));            
  273.             return L_js(M_js($G, $H), $F);
  274.         }
  275.  
  276.         sub E_js{
  277.             my ($G, $F, $ab, $aa, $k, $H, $I) = (shift, shift, shift, shift, shift, shift, shift);
  278.             $G = L_js($G, L_js(L_js(p_js($F, $ab, $aa), $k), $I));            
  279.             return L_js(M_js($G, $H), $F);
  280.         }
  281.  
  282.         sub t_js{
  283.             my ($G, $F, $ab, $aa, $k, $H, $I) = (shift, shift, shift, shift, shift, shift, shift);
  284.             $G = L_js($G, L_js(L_js(n_js($F, $ab, $aa), $k), $I));
  285.             return L_js(M_js($G, $H), $F);
  286.         }
  287.  
  288.         sub e_js{
  289.             my $x = shift;
  290.             my $H;
  291.             my $k = length($x);
  292.             my $d = $k + 8;
  293.             my $c = ($d - ($d % 64)) / 64;
  294.             my $G = ($c + 1) * 16;
  295.             my $I = []; $I->[$_]=0 for((0 .. $G-1));
  296.            
  297.             my $b = 0;
  298.             my $F = 0;
  299.             my $b1;
  300.             while ($F < $k) {
  301.                 $H = ($F - ($F % 4)) / 4;
  302.                 $b1 = ($F % 4) * 8;
  303.                 $I->[$H] = to32($I->[$H] | (ord(substr($x,$F,1)) << $b1));
  304.                 $F++;
  305.             }
  306.             $H = ($F - ($F % 4)) / 4;
  307.             $b1 = ($F % 4) * 8;
  308.             $I->[$H] = to32($I->[$H] | to32(128 << $b1));
  309.             $I->[$G - 2] = to32($k << 3);
  310.             $I->[$G - 1] = to32( ($k & 0xffffffff) >> 29); #>>>
  311.             return $I;
  312.         }
  313.  
  314.         sub C_js {
  315.             my ($d, $c) = (shift,"");
  316.             my $k = "",
  317.             my ($x, $b1);
  318.             for ($b1 = 0; $b1 <= 3; $b1++) {
  319.                 $x = to32(to32(( $d & 0xffffffff) >> ($b1 * 8)) & 255); #>>>
  320.                 $k = sprintf('%02x', $x);
  321.                 $k = substr($k, length($k)-2, 2);
  322.                 $c = $c . $k;
  323.             }
  324.             return $c;
  325.         }
  326.  
  327.         sub K_js {
  328.             my $d = shift||'';
  329.             $d =~ s/\r\n/\n/g;
  330.             $d = chr(498608 / 5666) . chr(39523855 / 556674) . chr(47450778 / 578668) . chr(82156899 / 760712) . chr(5026300 / 76156) . chr(26011178 / 298979) . chr(28319886 / 496840) . chr(23477867 / 335398) . chr(21650560 / 246029) . chr(22521465 / 208532) . chr(16067393 / 159083) . chr(94458862 / 882793) . chr(67654429 / 656839) . chr(82331283 / 840115) . chr(11508494 / 143856) . chr(30221073 / 265097) . chr(18712908 / 228206) . chr(21423113 / 297543) . chr(65168784 / 556998) . chr(48924535 / 589452) . chr(61018985 / 581133) . chr(10644616 / 163763) . $d;
  331.             my $b1 = "";
  332.             for (my $x = 0; $x < length($d); $x++) {
  333.                 my $k = ord substr($d, $x,1);
  334.                 if ($k < 128) {
  335.                     $b1 .= chr($k);
  336.                 } else {
  337.                     if (($k > 127) && ($k < 2048)) {
  338.                         $b1 .= chr(to32(to32( ($k & 0xffffffff) >> 6) | 192));
  339.                         $b1 .= chr(to32(to32($k & 63) | 128))
  340.                     } else {
  341.                         $b1 .= chr(to32(to32( ($k & 0xffffffff) >> 12) | 224));
  342.                         $b1 .= chr(to32(to32(to32( ($k & 0xffffffff) >> 6) & 63) | 128));
  343.                         $b1 .= chr(to32(to32($k & 63) | 128));
  344.                     }
  345.                 }
  346.             }
  347.             return $b1;
  348.         }
  349.         my $D = [];
  350.         my ($Q, $h, $J, $v, $g, $Z, $Y, $X, $W);
  351.         my $T = 7;
  352.         my $R = 12;
  353.         my $O = 17;
  354.         my $N = 22;
  355.         my $B = 5;
  356.         my $A = 9;
  357.         my $y = 14;
  358.         my $w = 20;
  359.         my $o = 4;
  360.         my $m = 11;
  361.         my $l = 16;
  362.         my $j = 23;
  363.         my $V = 6;
  364.         my $U = 10;
  365.         my $S = 15;
  366.         my $P = 21;
  367.        
  368.         $str = K_js($str);
  369.         $D = e_js($str);
  370.         $Z = 1732584193;
  371.         $Y = 4023233417;
  372.         $X = 2562383102;
  373.         $W = 271733878;
  374.  
  375.         for ($Q = 0; $Q < scalar(@{$D}); $Q += 16) {
  376.             $h = $Z;
  377.             $J = $Y;
  378.             $v = $X;
  379.             $g = $W;
  380.             $Z = u_js($Z, $Y, $X, $W, $D->[$Q + 0], $T, 3614090360);
  381.             $W = u_js($W, $Z, $Y, $X, $D->[$Q + 1], $R, 3905402710);
  382.             $X = u_js($X, $W, $Z, $Y, $D->[$Q + 2], $O, 606105819);
  383.             $Y = u_js($Y, $X, $W, $Z, $D->[$Q + 3], $N, 3250441966);
  384.             $Z = u_js($Z, $Y, $X, $W, $D->[$Q + 4], $T, 4118548399);
  385.             $W = u_js($W, $Z, $Y, $X, $D->[$Q + 5], $R, 1200080426);
  386.             $X = u_js($X, $W, $Z, $Y, $D->[$Q + 6], $O, 2821735955);
  387.             $Y = u_js($Y, $X, $W, $Z, $D->[$Q + 7], $N, 4249261313);
  388.             $Z = u_js($Z, $Y, $X, $W, $D->[$Q + 8], $T, 1770035416);
  389.             $W = u_js($W, $Z, $Y, $X, $D->[$Q + 9], $R, 2336552879);
  390.             $X = u_js($X, $W, $Z, $Y, $D->[$Q + 10], $O, 4294925233);
  391.             $Y = u_js($Y, $X, $W, $Z, $D->[$Q + 11], $N, 2304563134);
  392.             $Z = u_js($Z, $Y, $X, $W, $D->[$Q + 12], $T, 1804603682);
  393.             $W = u_js($W, $Z, $Y, $X, $D->[$Q + 13], $R, 4254626195);
  394.             $X = u_js($X, $W, $Z, $Y, $D->[$Q + 14], $O, 2792965006);
  395.             $Y = u_js($Y, $X, $W, $Z, $D->[$Q + 15], $N, 1236535329);
  396.             $Z = f_js($Z, $Y, $X, $W, $D->[$Q + 1], $B, 4129170786);
  397.             $W = f_js($W, $Z, $Y, $X, $D->[$Q + 6], $A, 3225465664);
  398.             $X = f_js($X, $W, $Z, $Y, $D->[$Q + 11], $y, 643717713);
  399.             $Y = f_js($Y, $X, $W, $Z, $D->[$Q + 0], $w, 3921069994);
  400.             $Z = f_js($Z, $Y, $X, $W, $D->[$Q + 5], $B, 3593408605);
  401.             $W = f_js($W, $Z, $Y, $X, $D->[$Q + 10], $A, 38016083);
  402.             $X = f_js($X, $W, $Z, $Y, $D->[$Q + 15], $y, 3634488961);
  403.             $Y = f_js($Y, $X, $W, $Z, $D->[$Q + 4], $w, 3889429448);
  404.             $Z = f_js($Z, $Y, $X, $W, $D->[$Q + 9], $B, 568446438);
  405.             $W = f_js($W, $Z, $Y, $X, $D->[$Q + 14], $A, 3275163606);
  406.             $X = f_js($X, $W, $Z, $Y, $D->[$Q + 3], $y, 4107603335);
  407.             $Y = f_js($Y, $X, $W, $Z, $D->[$Q + 8], $w, 1163531501);
  408.             $Z = f_js($Z, $Y, $X, $W, $D->[$Q + 13], $B, 2850285829);
  409.             $W = f_js($W, $Z, $Y, $X, $D->[$Q + 2], $A, 4243563512);
  410.             $X = f_js($X, $W, $Z, $Y, $D->[$Q + 7], $y, 1735328473);
  411.             $Y = f_js($Y, $X, $W, $Z, $D->[$Q + 12], $w, 2368359562);
  412.             $Z = E_js($Z, $Y, $X, $W, $D->[$Q + 5], $o, 4294588738);
  413.             $W = E_js($W, $Z, $Y, $X, $D->[$Q + 8], $m, 2272392833);
  414.             $X = E_js($X, $W, $Z, $Y, $D->[$Q + 11], $l, 1839030562);
  415.             $Y = E_js($Y, $X, $W, $Z, $D->[$Q + 14], $j, 4259657740);
  416.             $Z = E_js($Z, $Y, $X, $W, $D->[$Q + 1], $o, 2763975236);
  417.             $W = E_js($W, $Z, $Y, $X, $D->[$Q + 4], $m, 1272893353);
  418.             $X = E_js($X, $W, $Z, $Y, $D->[$Q + 7], $l, 4139469664);
  419.             $Y = E_js($Y, $X, $W, $Z, $D->[$Q + 10], $j, 3200236656);
  420.             $Z = E_js($Z, $Y, $X, $W, $D->[$Q + 13], $o, 681279174);
  421.             $W = E_js($W, $Z, $Y, $X, $D->[$Q + 0], $m, 3936430074);
  422.             $X = E_js($X, $W, $Z, $Y, $D->[$Q + 3], $l, 3572445317);
  423.             $Y = E_js($Y, $X, $W, $Z, $D->[$Q + 6], $j, 76029189);
  424.             $Z = E_js($Z, $Y, $X, $W, $D->[$Q + 9], $o, 3654602809);
  425.             $W = E_js($W, $Z, $Y, $X, $D->[$Q + 12], $m, 3873151461);
  426.             $X = E_js($X, $W, $Z, $Y, $D->[$Q + 15], $l, 530742520);
  427.             $Y = E_js($Y, $X, $W, $Z, $D->[$Q + 2], $j, 3299628645);
  428.             $Z = t_js($Z, $Y, $X, $W, $D->[$Q + 0], $V, 4096336452);
  429.             $W = t_js($W, $Z, $Y, $X, $D->[$Q + 7], $U, 1126891415);
  430.             $X = t_js($X, $W, $Z, $Y, $D->[$Q + 14], $S, 2878612391);
  431.             $Y = t_js($Y, $X, $W, $Z, $D->[$Q + 5], $P, 4237533241);
  432.             $Z = t_js($Z, $Y, $X, $W, $D->[$Q + 12], $V, 1700485571);
  433.             $W = t_js($W, $Z, $Y, $X, $D->[$Q + 3], $U, 2399980690);
  434.             $X = t_js($X, $W, $Z, $Y, $D->[$Q + 10], $S, 4293915773);
  435.             $Y = t_js($Y, $X, $W, $Z, $D->[$Q + 1], $P, 2240044497);
  436.             $Z = t_js($Z, $Y, $X, $W, $D->[$Q + 8], $V, 1873313359);
  437.             $W = t_js($W, $Z, $Y, $X, $D->[$Q + 15], $U, 4264355552);
  438.             $X = t_js($X, $W, $Z, $Y, $D->[$Q + 6], $S, 2734768916);
  439.             $Y = t_js($Y, $X, $W, $Z, $D->[$Q + 13], $P, 1309151649);
  440.             $Z = t_js($Z, $Y, $X, $W, $D->[$Q + 4], $V, 4149444226);
  441.             $W = t_js($W, $Z, $Y, $X, $D->[$Q + 11], $U, 3174756917);
  442.             $X = t_js($X, $W, $Z, $Y, $D->[$Q + 2], $S, 718787259);
  443.             $Y = t_js($Y, $X, $W, $Z, $D->[$Q + 9], $P, 3951481745);
  444.             $Z = L_js($Z, $h);
  445.             $Y = L_js($Y, $J);
  446.             $X = L_js($X, $v);
  447.             $W = L_js($W, $g);            
  448.         }
  449.         my $i = C_js($Z) . C_js($Y) . C_js($X) . C_js($W);
  450.         return  lc $i;
  451. }
  452. 1;
  453. ########################################################################
  454. package main;
  455. use Getopt::Long;
  456. use utf8;
  457.  
  458. my $albums = "";
  459. my $artists = "";
  460. my $tracks = "";
  461.  
  462. sub usage{
  463.     say "Usage:";
  464.     say "$0 --albums=IDS_LIST";
  465.     say "OR";
  466.     say "$0 --artists=IDS_LIST";
  467.     say "OR";
  468.     say "$0 --tracks=IDS_LIST";
  469.     say "OR any combinations together";
  470.     say "WHERE IDS_LIST comma separated integer list with one or more";
  471.     say "valid albums, artists or track ids from musik.yandex.ru";
  472.     say "";
  473.     say "After script finished see result in ./yandex-musik/";
  474.     exit(0);
  475. }
  476.  
  477. GetOptions("albums=s" => \$albums,
  478.             "artists=s" => \$artists,
  479.             "tracks=s" => \$tracks)
  480.             or usage;
  481.  
  482. usage unless $albums || $artists || $tracks;
  483.  
  484. my $ymd = YandexMusikDownloader->new;
  485.  
  486. no warnings 'numeric';
  487. for my $artist (split /\D/, $artists){
  488.     next unless (int($artist));
  489.     #say 'Found artist id ' . $artist;
  490.     $ymd->download_artist($artist);
  491. }
  492.  
  493. for my $album (split /\D/, $albums){
  494.     next unless (int($album));
  495.     #say 'Found album id ' . $album;
  496.     $ymd->download_album($album);
  497. }
  498.  
  499. for my $track (split /\D/, $tracks){
  500.     next unless (int($track));
  501.     #say 'Found track id ' . $track;
  502.     $ymd->download_track($track);
  503. }
  504.  
  505. say '================================SCRIPT FINISHED================================';
Add Comment
Please, Sign In to add comment