PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/vkmp3.pl

https://bitbucket.org/KryDos/pl-vkmp3
Perl | 184 lines | 158 code | 17 blank | 9 comment | 13 complexity | 8d551888f915d9e8aff28b069c6231d0 MD5 | raw file
  1. #!/usr/bin/perl
  2. # vk-get-mp3.pl script v 0.9.11
  3. # (c) Alexandr A Alexeev 2011-2012 | http://eax.me/
  4. # Special thanks to Bekenev Ruslan ( http://bitbucket.org/KryDos )
  5. use strict;
  6. use URI::Escape;
  7. use Text::Iconv;
  8. use MP3::Info;
  9. use utf8;
  10. use constant VERSION => "0.9.11";
  11. use constant DEFAULT_LOGIN => 'billy@microsoft.com';
  12. use constant DEFAULT_PASSWORD => 'qwerty';
  13. use constant DEFAULT_SAVE_DIR => './';
  14. use constant DEFAULT_MAX_SHOW => 20;
  15. #### проверяем наличие всех необходимых утилит ####
  16. {
  17. my @depends = qw/wget/;
  18. my $not_found;
  19. for(@depends) {
  20. print "ERROR: $_ not found" and ++$not_found
  21. if(system("which $_ > /dev/null"));
  22. }
  23. exit 1 if($not_found);
  24. }
  25. my ($login, $password, $save_dir, $max_show);
  26. for my $x (qw/login password save_dir max_show/) {
  27. my $X = "\U$x";
  28. my $cmd = qq{
  29. \$$x = \$ENV{VKMP3_$X};
  30. \$$x = DEFAULT_$X unless(defined(\$$x));
  31. };
  32. eval $cmd;
  33. }
  34. my $hidden_pass = "*" x length($password);
  35. my $tmp = "/tmp/vkmp3_$$";
  36. my $wget_cmd = "wget --save-cookies $tmp --load-cookies $tmp";
  37. my $query = join " ", @ARGV;
  38. die "vk-get-mp3.pl ver ".VERSION."\nUsage:\n$0 <query>\n$0 --dialog\n"
  39. unless($query);
  40. if($query eq "--dialog") {
  41. print "Dialog mode, enter query or 'exit'\nvkmp3> ";
  42. while($query = <STDIN>) {
  43. chomp($query);
  44. if(length($query)) {
  45. last if(("\L$query" eq "exit")or("\L$query" eq "quit"));
  46. $query = quotemeta $query;
  47. system("$0 $query") unless($query eq "--dialog");
  48. print "\n";
  49. }
  50. print "vkmp3> ";
  51. }
  52. exit;
  53. }
  54. print "Looking for '$query'...\n";
  55. $_ = uri_escape($_) for(($login, $password));
  56. utf8::decode($query);
  57. my $win2utf = Text::Iconv->new("cp1251", "utf-8");
  58. # логинимся
  59. my $url = "http://login.vk.com/?act=login";
  60. my $data = `$wget_cmd -q '$url' --post-data 'email=$login&pass=$password' -O -`;
  61. if($?) {
  62. unlink $tmp;
  63. die "Login: wget returns $?\n";
  64. }
  65. unless(
  66. $data =~ m#<input\s+type="hidden"\s+name="act"\s+value="logout"\s+/>#i
  67. ) {
  68. unlink $tmp;
  69. die "Login failed ($login:$hidden_pass)!\n";
  70. }
  71. # ищем музыку
  72. $url = "http://vkontakte.ru/search?c[section]=audio&c[q]=".
  73. uri_escape_utf8($query);
  74. $data = `$wget_cmd -q '$url' -O -`;
  75. if($?) {
  76. unlink $tmp;
  77. die "Search: wget returns $?\n";
  78. }
  79. # парсим результат
  80. my @matches = $data =~
  81. m'<input type="hidden" id="audio_info(.*?)</span></div>'sgi;
  82. @matches = @matches[0..$max_show-1]
  83. if(scalar(@matches) > $max_show);
  84. my ($i, @links, @names);
  85. for my $t (@matches) {
  86. # получаем продолжительность и название песни
  87. $t =~ m{<div class="duration fl_r" onmousedown="if \(window.audioPlayer\) audioPlayer\.switchTimeFormat\('[^']+', event\);">(\d+:\d+)</div>}i;
  88. my $duration = $1;
  89. $t =~ m{<div class="audio_title_wrap"><b>(.+)<span class="user">}si;
  90. my $name = $1;
  91. if($duration) {
  92. my ($m, $s) = split /:/, $duration;
  93. $duration = sprintf "%02d:%02d", $m, $s;
  94. } else {
  95. $duration = "??:??";
  96. }
  97. # получаем ссылку
  98. my ($link) =
  99. $t =~ m{value="(http://[^",]+\.mp3)}i;
  100. # получаем размер файла
  101. my $file_size = `wget --spider $link 2>&1`;
  102. $file_size =~ m/\(([^)]+)\)/is;
  103. $file_size = $1;
  104. # очищаем название от мусора
  105. $name =~ s/<[^>]+>//g;
  106. $name =~ s/(^\s+|\s+$|\s{2,})//gs;
  107. $name =~ s/&#(\d+);/chr($1)/ge;
  108. $name =~ s/&amp;/&/g;
  109. $name = substr($name,0,64)."..." if(length($name) > 64);
  110. # cp1251 --> utf8
  111. $name = $win2utf->convert($name);
  112. print sprintf("%02d", ++$i)." [$duration] $name [$file_size]\n";
  113. push @links, $link;
  114. push @names, $name;
  115. }
  116. unless(scalar @links) {
  117. unlink $tmp;
  118. die "Nothing found\n";
  119. }
  120. print "Your choice(s) [none]: ";
  121. chomp(my $choice = <STDIN>);
  122. my @ch = split /\D/, $choice;
  123. for $choice (@ch) {
  124. print "$choice - ignored" and next
  125. unless($choice >= 1 and $choice <= scalar(@links));
  126. # определяем ссылку и имя файла
  127. $url = $links[$choice-1];
  128. my $name = $names[$choice-1];
  129. utf8::decode($name);
  130. my $fname = $save_dir.rus_to_lat($name).".mp3";
  131. # скачиваем
  132. print "Downloading $url to $fname...\n";
  133. system("$wget_cmd '$url' -O $fname");
  134. if($?) {
  135. unlink $tmp;
  136. die "Download: wget returns $?\n"
  137. }
  138. # выводим битрейт
  139. my $bitrate = abs(get_mp3info($fname)->{BITRATE});
  140. print "Bitrate = ".sprintf("%d",$bitrate)." kbps\n";
  141. print "$fname\n";
  142. }
  143. # генерируем имя файла на основе названия песни
  144. sub rus_to_lat {
  145. my ($str) = @_;
  146. $str = "\L$str";
  147. $str =~ tr/абвгдезийклмнопрстуфхцыэ /abvgdezijklmnoprstufxcye-/;
  148. $str =~ s/ё/yo/g;
  149. $str =~ s/ж/zh/g;
  150. $str =~ s/ч/ch/g;
  151. $str =~ s/ш/sh/g;
  152. $str =~ s/щ/shh/g;
  153. $str =~ s/ю/yu/g;
  154. $str =~ s/я/ya/g;
  155. $str =~ s/\./\-/g;
  156. $str =~ s/([^a-z0-9-])//g;
  157. $str =~ s/\-{2,}/\-/g;
  158. $str =~ s/(^\-|\-$)//g;
  159. $str;
  160. }