conformist

vkmusic.sh

Dec 12th, 2015
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 20.35 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. # Пример работы с VKAPI в shell-скрипте.
  4.  # Скрипт для работы с музыкой ВКонтакте. by snoopcatt.
  5.    _version="0.03a"
  6.  
  7. # Системные переменные
  8. id="5807425" # системная переменная. ID создателя приложения. Взято из VK_Search Amarok Script (c)
  9. method='audio.search' # метод поиска музыки ВКонтакте.
  10. secret='dTckAoaSzH' # системная переменная. Секретный код приложения. Взято из VK_Search Amarok Script (c)
  11. query="$1" # запрос на сервер. По-умолчанию это $1, то есть первый аргумент программы.
  12. tmp='/tmp' # временная директория. По-умолчанию это /tmp.
  13. debug='0'  # выводить отладочные сообщения в STDERR. По-умолчанию 1.
  14. ffbuffer='65536'  # сколько байт закачивать для попытки определения лучшего битрета. по умолчанию 65536 байт, идеально работает с битрейтом <320kbps.
  15. delete_time_doubles='1' # удалять одинаковые по времени. По-умолчанию 1.
  16. noterasem3u='0' # не удалять предыдущую M3U
  17. noterasetmpfiles='0' # не удалять временные файлы перед запуском
  18. update_url='http://sctt.ath.cx/projects/vksearch/vksearch.sh'
  19.  
  20. # Пользовательские переменные
  21. playlist="$HOME/vk.playlist" ## плейлист
  22. getdir="$HOME"  ## папка для сохранения файлов
  23. count='200' ## сколько искать для глоб.поиска
  24. singlecount='15' ## сколько искать для одиноч.поиска
  25. player='mplayer -playlist' # плеер, обрабатывающий плейлисты
  26. download="wget -cqO" # менеджер загрузок
  27. random='0' #  рандом?
  28. detect_best_song='0' # определять лучшие песни
  29. tag_id3='1' # записывать ли теги в свежескачанные mp3
  30. m3u='0' # экспорт плейлиста в M3U
  31. mode='play' # дефолтный режим работы
  32.  
  33.  
  34.    
  35.  
  36.  
  37.  
  38.   # удаление темповых файлов
  39.     [ "$noterasetmpfiles" != "1" ] && rm $tmp/vk.* 2>/dev/null
  40.  
  41.  showHelp() {
  42.    echo '
  43.    VKontakte Search '"$_version"'
  44.      VKSearch - Shell-скрипт для поиска, сортировки и закачки музыки с сайта VKontakte.ru.
  45.        Наличие учетной записи на VK не требуется.
  46.          Возможности:
  47. * Поиск
  48. * Сортировка: удаление дублей, рандомизация
  49. * Проигрывание: создание m3u
  50. * Закачка: Определение трека с лучшим битрейтом; Запись ID3v1, ID3v2 в UTF-8, отправка на проигрывание в любой плеер
  51.  Для определения возможностей, используемых по умолчанию, просто откройте исполняемый файл и измените секцию "Пользовательские переменные".
  52.  
  53.   Зависимости:
  54.      coreutils; curl; ffmpeg; id3*; mplayer*; wget
  55. *(id3 - не обязательная зависимость. Просто отключите поддержку tag_id3 в скрипте в секции "Пользовательские переменные"
  56. mplayer - не обязательная зависимость. Просто исправьте переменную player в секции "Пользовательские переменные")
  57.  
  58.   Пример использования:
  59.       vksearch "Ваш Запрос" Опции
  60. Например, для поиска "Театр Яда" в количестве 1000 штук, с рандомизацией и последущей отправкой плейлиста в плеер mplayer:
  61.       vksearch "Театр Яда" --count=1000 --random --play --player="mplayer -playlist"
  62.   для закачки песен "Театр Яда" в кол-ве 100 штук делаем:
  63.       vksearch "Театр Яда" --count=100 --get
  64.   а для закачки одной песни "Театр Яда - Курс к наилучшему худшему" с наилучшим качеством делаем:
  65.       vksearch "Театр Яда - Курс к наилучшему худшему" --get-one --best
  66.  
  67.   По-умолчанию скрипт работает в режиме "Play" (найти и проиграть).
  68.    Вы можете изменить режим работы либо запустив с параметром --get, --get-one, --play, --play-one, --playlist, либо изменив переменную $mode в скрипте в секции "Пользовтельские переменные"
  69.  
  70.   Все опции:
  71.     $1 (первый аргумент) - строка поиска.
  72.     --help - показать эту страницу
  73.     --getdir="путь" - папка для сохранения mp3 и плейлистов
  74.     --count="число" - сколько песен искать
  75.     --singlecount="число" - сколько песен искать для "одиночного" поиска (одной песни) (для последущего выбора из этих песен трека с лучшим битрейтом)
  76.     --play - установка режима работы "Создать плейлист и отправить в плеер"
  77.     --playlist - установка режима работы "Создать плейлист"
  78.     --update - автообновление скрипта
  79.     --player="плейер" - плеер, в котором будем открывать плейлист
  80.     --dloader="менеджер закачек" - программа, которая будет закачивать плейлист/трек
  81.     --get - установка режима работы "Создать плейлист и скачать его"
  82.     --get-one - установка режима рабтоы "
  83.     --random - случайное воспроизведение
  84.     --best - определить трек с лучшим кач-вом
  85.     --id3 - разрешить запись ID3 после закачки
  86.     --debug - показывать отладочные сообщения
  87. '
  88.  exit 0
  89. }
  90.  
  91.  #Умертвление (;
  92. die() {
  93.  echo "$@"
  94.   exit 1
  95. }
  96.  
  97.  
  98. for param in $@ ;
  99. do
  100.   case $param in
  101.     --help) showHelp ;;
  102.     --getdir=*) getdir=$( echo $param | cut -d '=' -f 2 ) ;;
  103.     --count=*) count=$( echo $param | cut -d '=' -f 2 ) ;;
  104.     --singlecount=*) singlecount=$( echo $param | cut -d '=' -f 2 ) ;;
  105.     --play) mode=play ;;
  106.     --play-one) mode=play_one ;;
  107.     --update) mode=update ;;
  108.     --get) mode=get ;;
  109.     --dloader=*) download=$( echo $param | cut -d '=' -f 2 ) ;;
  110.     --player=*) player=$( echo $param | cut -d '=' -f 2 ) ;;
  111.     --get-one) mode=get_one ;;
  112.     --random) random=1;;
  113.     --playlist) mode=playlist ;;
  114.     --best) detect_best_song=1 ;;
  115.     --id3) tag_id3=1 ;;
  116.     --debug) debug=1 ;;
  117.   esac
  118. done
  119.  
  120. [ -n "`echo $mode|grep one`" ] && count=$singlecount
  121.  
  122. # Приветствие. Проверка хэшей, возможности работы, итд
  123.  sayHello() {
  124.   echo "[`date +%k:%M:%S`] Добро пожаловать в VKSearch!"
  125.      [ -z "$query" ] && die "[`date +%k:%M:%S`] Пустой запрос...Наберите '$0 --help' для получения помощи"
  126. # проверка id3
  127.  if [ "$tag_id3" == "1" ]; then
  128.    id3 >/dev/null 2>&1
  129.    [ "$?" == "127" ] && die "[`date +%k:%M:%S`] Не найдена утилита ID3! Установите её или отключите режим tag_id3!"
  130. fi
  131.  
  132.  if [ "$count" -gt "300" ];
  133.   then  
  134.     echo "[`date +%k:%M:%S`] Warning: Указано число поиска больше 300...Установлено максимальное (300) значение."
  135.     count=300
  136.  fi
  137.  
  138. # Получение сигнатуры
  139. sig=`echo -n "${id}api_id=1696393count=${count}method=${method}q=${query}test_mode=1v=2.0${secret}"|md5sum|awk '{ print $1 }'`
  140. # Получение списка
  141. wget "http://api.vkontakte.ru/api.php?api_id=1696393&count=${count}&v=2.0&method=${method}&sig=$sig&test_mode=1&q=$query" -qO $tmp/vk.out
  142. allcount=`cat $tmp/vk.out | grep count|grep -oE "[0-9]*"`  
  143.   if [ "$allcount" == "0" ]
  144.    then die "[`date +%k:%M:%S`] Не найдено ни одной композиции..."
  145.      else
  146.        [ "$allcount" -gt "$count" ] || count=$allcount # если найдено меньше, чем запрошено
  147.        echo "[`date +%k:%M:%S`] По запросу $query найдено $allcount композиций. Обрабатываю первых $count композиций."
  148.    fi
  149. }
  150.  
  151. # Создать плейлист
  152. createPlaylist() {
  153. cat $tmp/vk.out|grep -o -E "http://[^ ]+\.mp3" > $playlist
  154. echo "[`date +%k:%M:%S`] Плейлист создан - $(cat $playlist|wc -l) трек(ов)"
  155. }
  156.  
  157. # Получение mp3 лучшего качества. Переменные: singlecount (кол-во одинаковых mp3's)
  158. getBestmp3() {
  159.   tnum=1
  160.   num=$[$singlecount+1]
  161.     [ "$num" -gt "`cat $playlist|wc -l`" ] && num=`cat $playlist|wc -l`
  162.     [ "$debug" == "1" ] && echo "[`date +%k:%M:%S`] Обрабатываю $num песен..."
  163. if [ "$num" == "1" ];
  164.  then
  165.     best=`cat $playlist`
  166.  else
  167.   while [ "$tnum" != "$num" ];
  168.     do
  169.       [ "$debug" == "1" ] && echo "[`date +%k:%M:%S`] <MOD: getBestmp3> Обработка $tnum " 1>&2
  170.       rate=$(curl --range 0-${ffbuffer} "`cat $playlist | head -n $tnum|tail -n 1`"  2>/dev/null | ffmpeg -i - 2>&1|grep Stream|grep -oE "[0-9]{1,3} kb/s"|awk '{ print $1 }')
  171.       echo -n "$rate" >> $tmp/vk.bitrate
  172.       echo -n " $tnum">> $tmp/vk.bitrate
  173.       echo >> $tmp/vk.bitrate
  174.       tnum=$[$tnum+1]
  175.     done
  176.   bestnum=$(cat $tmp/vk.bitrate|sort -n | tail -n 1 | awk '{ print $2 }')
  177.   echo "[`date +%k:%M:%S`] ${bestnum}-й трек с лучшим качеством"
  178.   best=`cat $playlist|sed -n ${bestnum}p`
  179.  fi
  180. }
  181.  
  182. # Получение информации вида 'Исполнитель - Композиция Длительность' для парсинга
  183.  # или вида 'Длительность,Исполнитель - Композиция' для m3u-списочка
  184. getNameByID() {
  185. if [ -n "$1" ] ; then
  186.    num=`cat $tmp/vk.out |grep -n "$1"|grep -o ".*[0-9]:"| sed 's/\://'` #| awk '{ print $1 }'
  187.    [ -n "`echo $num|awk '{ print $2 }'`" ] && num=`echo $num|awk '{ print $1 }'`
  188.    artist=` cat $tmp/vk.out | head -n $num|tail -n 4|sed -n 's|<artist>\(.*\)</artist>|\1|p'|sed 's/^[ \t]*//'`
  189.    title=` cat $tmp/vk.out | head -n $num|tail -n 4|sed -n 's|<title>\(.*\)</title>|\1|p'|sed 's/^[ \t]*//'`
  190.    secs=` cat $tmp/vk.out| head  -n $num|tail -n 4|sed -n 's|<duration>\(.*\)</duration>|\1|p'|sed 's/^[ \t]*//'`  
  191.   [ "$debug" == "1" ] && echo "Обработана $num-я песенка - $artist - $title - $secs сек" 1>&2
  192.   [ -z "$2" ] && echo "$secs $artist - $title "
  193.   [ "$2" == "m3u" ] && echo "$secs,$artist - $title"    
  194.   [ "$2" == "get" ] && echo "$artist - $title"    
  195.   [ "$2" == "artist" ] && echo "$artist"    
  196.   [ "$2" == "title" ] && echo "$title"    
  197.   fi
  198.  }
  199.  
  200. # Парсинг XML-листа. Рандомизация, если требуетса. Удаление дублей.
  201. parseList() {
  202.   num=$[$count+1]
  203.     tnum=1
  204.      
  205. # Сортируем все в $tmp/vk.playlist-sorted
  206.  bylo=$(cat $playlist|wc -l)
  207.  while [ "$tnum" != "$num" ];
  208.        do
  209.       [ "$debug" == "1" ] && echo "[`date +%k:%M:%S`] Парсинг. $tnum из $num" 1>&2
  210.         curr=`cat $playlist|sed -n ${tnum}p`
  211.         echo -n " `getNameByID $curr`" >> $tmp/vk.playlist
  212.         echo -n "$curr" >> $tmp/vk.playlist # сначала http в конец для sort-а
  213.         echo >> $tmp/vk.playlist
  214.       #getNameByID $curr
  215.          tnum=$[$tnum+1]
  216.       done
  217.      cat $tmp/vk.playlist | sort -f -o $tmp/vk.playlist-sorted # отсортировали, теперь перенести http:// ... влево ;)
  218.  
  219. #  Переносим ссылки влево
  220.   tnum=1
  221.    while [ "$tnum" != "$num" ];
  222.      do
  223.       [ "$debug" == "1" ] && echo "[`date +%k:%M:%S`] Вторичный Парсинг. $tnum из $num"
  224.       echo -n "$(cat $tmp/vk.playlist-sorted | sed -n ${tnum}p | awk '{ print $NF }') " >> $playlist.parsed
  225.       echo -n "$(cat $tmp/vk.playlist-sorted | sed -n ${tnum}p |sed -e 's/http.*//')" >> $playlist.parsed
  226.      echo >> $playlist.parsed
  227.      tnum=$[$tnum+1]
  228.     done  
  229.  
  230. #  Парсим
  231.    cat $playlist.parsed | uniq -f 1 -i > $playlist.uniq;
  232. if [ "$delete_time_doubles" == "1" ]; then
  233.   cat $playlist.uniq | awk '{ print $2" "$1 }' | sort -n | awk '{ print $2" "$1 }' | uniq -f 1 | awk '{ print $1 }' > $playlist.parsed
  234.  
  235. else  
  236.   cat $playlist.uniq | awk '{ print $1 }' > $playlist.parsed
  237. fi
  238.   cat $playlist.parsed | sort | uniq > $playlist
  239.   [ "$random" == "1" ] && cat $playlist|sort -R -o $playlist
  240.   rm $playlist.uniq $playlist.parsed 2>/dev/null # удаление лишних
  241.   stalo=$(cat $playlist|wc -l)
  242.   echo "[`date +%k:%M:%S`] Парсинг завершён. Удалено $[$bylo-$stalo] дублей, сейчас в плейлисте $stalo треков"
  243. }
  244.  
  245. mkm3ulist() {
  246.   [ "$noterasem3u" == "1" ] || rm $getdir/playlist.m3u 2>/dev/null
  247.   [ -f "$getdir/playlist.m3u" ] || echo "#EXTM3U" >> $getdir/playlist.m3u
  248.   [ -f "$getdir/playlist.m3u" ] ||  echo >> $getdir/playlist.m3u
  249.  num=$[$(cat $playlist|wc -l)+1]
  250.    tnum=1
  251.     while [ "$tnum" != "$num" ]; do
  252.         curr=`cat $playlist|sed -n ${tnum}p`
  253.        [ "$debug" = "1" ] && echo Добавляю песню $curr под номером $tnum 1>&2
  254.         echo "#EXTINF:`getNameByID "$curr" m3u`" >> $getdir/playlist.m3u
  255.         echo $curr >> $getdir/playlist.m3u
  256.        tnum=$[$tnum+1]
  257.     done
  258. echo "[`date +%k:%M:%S`] M3U-плейлист сохранён как $getdir/playlist.m3u"
  259. }
  260.  
  261. # аутоупдате :p
  262. update() {
  263. # обновление
  264. wget $update_url -o /dev/null -O $tmp/vk.update
  265.  if [ "$?" != "0" ];
  266.   then
  267.      echo "[`date +%k:%M:%S`] Неудача. Не могу загрузить файл. Проверьте UpdateUrl."
  268.   else
  269.      _new=`cat $tmp/vk.update|grep '_version='|head -n 1|sed 's/\_ver=//' | sed 's/\"//g'`
  270.     if [ "$_version" == "$_new" ];
  271.       then
  272.           echo "[`date +%k:%M:%S`] Обновление не требуется!"
  273.        else
  274.          echo "[`date +%k:%M:%S`] Сейчас будет завершено обновление с версии $_version на $_new. Наберите 'go' для продолжения."
  275.          read _accept
  276.          if [ "$_accept" != "go" ] ;
  277.              then
  278.                 echo "[`date +%k:%M:%S`] Обновление отменено!"
  279.                 rm $tmp/vk.update
  280.              else
  281.                 [ -f "$0" ] && _bin="$0"
  282.                 [ -f "`which $0`" ] && _bin="$0"
  283.                 [ -z "$_bin" ] && die "[`date +%k:%M:%S`] Ошибка: Не могу найти исполняемый файл"
  284.                 [ -r "$_bin" ] || die "[`date +%k:%M:%S`] Ошибка: Нет прав на запись исполняемого файла"
  285.                mv $_bin $_bin-saved 2>/dev/null #backup\
  286.                [ "$?" != "0" ] && die "[`date +%k:%M:%S`] Ошибка: Не могу переместить файл"
  287.                mv $tmp/vk.update $_bin 2>/dev/null
  288.                [ "$?" != "0" ] && die "[`date +%k:%M:%S`] Ошибка: Не могу переместить файл"
  289.                [ -x "$_bin" ] || chmod +x $_bin 2>/dev/null
  290.                [ "$?" != "0" ] && echo "[`date +%k:%M:%S`] Обновление завершено, но невозможно дать скрипту права на выполнение. Сделайте это вручную. "
  291.                echo "[`date +%k:%M:%S`] Обновление завершено успешно. Работоспособность скрипта не гарантируется *_*"
  292.               rm $tmp/vk.update
  293.          fi
  294.     fi          
  295. fi          # end 'обновление'
  296. #exit 0;
  297. #saved.
  298.  }
  299.  
  300. #вообщемта обновление \=
  301. if [ "$mode" == "update" ];
  302.  then
  303.    update
  304. fi
  305.  
  306. # это вообщем режим такой: обрабатываем плейлист, генерим мтриушку и передаем в мплеер(%
  307.  if [ "$mode" == "play" ];
  308.    then
  309.       sayHello ;
  310.       createPlaylist ;
  311.       parseList;
  312.       mkm3ulist;
  313.       echo "[`date +%k:%M:%S`] Передаю управлению плееру..."
  314.        # да некавай\=
  315.            # йа знаю :P
  316.         [ "$debug" == "1" ] && $player $getdir/playlist.m3u || $player $getdir/playlist.m3u 2>/dev/null
  317. fi
  318.  
  319. # ну а это тупо одну штучкуЪ
  320.  if [ "$mode" == "play_one" ];
  321.  then
  322.    sayHello
  323.     createPlaylist
  324.      parseList
  325.       head -n 1 $playlist | tee $playlist >/dev/null
  326.       mkm3ulist
  327.       echo "[`date +%k:%M:%S`] Передаю управлению плееру..."
  328.       [ "$debug" == "1" ] && $player $getdir/playlist.m3u || $player $getdir/playlist.m3u 2>/dev/null
  329. fi
  330.  
  331. # проста сохраняем плейлист
  332.  if [ "$mode" == "playlist" ];    
  333.   then
  334.     sayHello;
  335.      createPlaylist;
  336.      parseList;
  337.      mkm3ulist;
  338.      rm $playlist;
  339.  fi
  340.  
  341. #гетаем все песни
  342.  if [ "$mode" == "get" ];
  343.   then
  344.        sayHello;
  345.        createPlaylist;
  346.        parseList;
  347.        #$download -i $playlist -O $getdir  
  348.           # так тоже конечшна можна..но это НЕКАвай впринципе.
  349.              tnum=1
  350.              num=$[$(cat $playlist|wc -l)+1]
  351.              echo "[`date +%k:%M:%S`] Начинаю закачку. Всего $[$num-1] песен..."
  352.                while [ "$tnum" != "$num" ];
  353.                  do
  354.                    curr=`cat $playlist|sed -n ${tnum}p`
  355.                     iname=`getNameByID $curr get`
  356.                       echo "[`date +%k:%M:%S`] Закачиваю $iname ($[$tnum-1] из $[$num-1] выполнено)"
  357.                       $download "$getdir/$iname.mp3" "$curr"
  358.                         echo "[`date +%k:%M:%S`] Закачка $iname завершена!"
  359.                      if [ "$tag_id3" == "1" ]; then  id3 -1 -2 -a "$(getNameByID $curr artist)" -t "$(getNameByID $curr title)" "$getdir/$iname.mp3";
  360.                        [ "$?" == "0" ] && echo "[`date +%k:%M:%S`] Теги записаны!"; fi
  361.                 tnum=$[$tnum+1]
  362.                done
  363.  fi
  364.  
  365. #или только одну
  366.  if [ "$mode" == "get_one" ];
  367.   then
  368.        sayHello;
  369.        createPlaylist;
  370.        parseList;
  371.             if [ "$detect_best_song" == "1" ];
  372.                 then
  373.                      getBestmp3
  374.                      iname=`getNameByID $best get`
  375.                      echo "[`date +%k:%M:%S`] Начинаю закачку..."
  376.                      echo "[`date +%k:%M:%S`] Закачиваю $iname"
  377.                       $download "$getdir/$iname.mp3" "$best"
  378.                      echo "[`date +%k:%M:%S`] Закачка завершена!"
  379.                       if [ "$tag_id3" == "1" ]; then  id3 -1 -2 -a "$(getNameByID $best artist)" -t "$(getNameByID $best title)" "$getdir/$iname.mp3";
  380.                        [ "$?" == "0" ] && echo "[`date +%k:%M:%S`] Теги записаны!"; fi
  381.                else
  382.                      song=`cat $playlist|head -n 1`
  383.                      echo "[`date +%k:%M:%S`] Начинаю закачку..."
  384.                      iname=`getNameByID $song get`
  385.                      echo "[`date +%k:%M:%S`] Закачиваю $iname"
  386.                       $download "$getdir/$iname.mp3" "$song"
  387.                      echo "[`date +%k:%M:%S`] Закачка завершена!"
  388.                       if [ "$tag_id3" == "1" ]; then  id3 -1 -2 -a "$(getNameByID $song artist)" -t "$(getNameByID $song title)" "$getdir/$iname.mp3";
  389.                        [ "$?" == "0" ] && echo "[`date +%k:%M:%S`] Теги записаны!"; fi
  390.            fi
  391.  fi
  392.  
  393. # дел лишнее
  394. rm $tmp/vk.*
  395. exit 0
Add Comment
Please, Sign In to add comment