diff --git a/massdl.py b/massdl.py new file mode 100644 index 0000000..4ba507a --- /dev/null +++ b/massdl.py @@ -0,0 +1,244 @@ +# *-* encoding: utf-8 *-* +# For NNM-Club Uploaders +# Copyright (c) 2012-2013 Valdos Sine +# +# Usage: +# +# python2 ./massdl.py [user] [forum_number] +# +# For getting help, execute "python2 ./massdl.py" without params + +import time, tempfile, os, sys, commands +version = 0.61 +unixtime = int(time.time()) +cookie = tempfile.mkstemp() +curdir = os.getcwd() +log_file = "/%i-massdl.log" % unixtime +# Anti-Zapret +domain = "http://nnm-club.me" + + +def write_to_log(imessage): + """ + Note, all script messages must be formatted as: + + [status] #status_number: message + + where: + + status: "I" = information, "W" - warning, "E" - error. + status_number - error number: + + 0xx -- script environment messages + 1xx -- authentication messages + 2xx -- grabbing and parsing messages + 3xx -- torrents downloading messages + 4xx -- torrents check messages + + Last message in log must be ended with "Stopped" word. + + Information starts from x00, success messages from x20, warnings from x40 and errors from x66. + """ + log = open(curdir + log_file, 'a') + log.write(imessage) + log.close() + +def cnsl_message(imessage, *args): + if imessage == "invpyver": + print "Ваша версия Python не поддерживается. Используйте Python 2.7!" + write_to_log("[E] #066: версия Python не поддерживается. Завершено.\n") + sys.exit(666) + elif imessage == "nocurl": + print "У вас не установлен PycURL. Обратитесь к справке вашего дистрибутива для подробностей, как его установить." + write_to_log("[E] #067: не установлен cURL. Завершено\n") + sys.exit(666) + elif imessage == "help": + print "massdl.sh — скрипт для пакетной загрузки торрент-файлов из разделов NNM-club.ru.\nИспользование:\n\n\tpython massdl.py [режим] [номер_раздела]\n\nгде [режим] это режим загрузки (от имени пользователя, указанного в конфигурации скрипта — значение user, или же от имени фрилич-пользователя — значение freeleech), а [номер_форума] — номер раздела на NNM-club.ru (например, для форума '*Nix Игры' это 316).\nПримеры:\n\n\tpython massdl.py freeleech 316 — скачивание форума '*Nix Игры' от фрилич-пользователя\n\tpython massdl.py user 332 — скачивание форума 'Русский рок' от собственного, указанного в скрипте, имени\n\nАвтор: Valdos 'fat0troll' Sine.\nСкрипт использует Python версии 2.7. При запуске убедитесь, что используете правильный интерпретатор Python!\nВерсия %s\n" % version + sys.exit(0) + elif imessage == "start": + print "Выполняется скрипт %s.\nВерсия скрипта %s." % (sys.argv[0], version) + print "Параметры командной строки: %s %s" % (sys.argv[1], sys.argv[2]) + write_to_log("[I] #020: окружение скрипта в порядке.\n") + elif imessage == "login_ok": + print "Вы залогинились успешно как пользователь %s." % set_username()[0] + write_to_log("[I] #120: выполнен успешный вход на сайт. Cookie лежит по адресу %s.\n" % cookie[1]) + elif imessage == "login_failed": + print "Не удалось залогиниться как пользователь %s. Проверьте ваши данные внутри скрипта!" % set_username()[0] + write_to_log("[E] #166: неправильное имя пользователя или пароль. Завершено.\n") + sys.exit(666) + elif imessage == "parsing_started": + print "Начинается загрузка форума..." + elif imessage == "forum": + print "Скачиваем форум " + args[0] + write_to_log('[I] #220: успешно загружена стартовая страница форума "%s".\n' % args[0]) + elif imessage == "pages": + print "Скачиваем страницу " + args[0] + write_to_log('[I] #200: загружаем страницу ' + args[0] + '...\n') + elif imessage == "found_topics": + print "Скачивание страниц завершено. Найдено топиков: " + args[0] + "." + write_to_log('[I] #221: успешно загружены все страницы форума. Найдено топиков: ' + args[0] + '.\n') + elif imessage == "download_started": + print "Начинаем загрузку торрентов..." + elif imessage == "downloading_torrent": + print "Скачиваю топик " + args[0] + "/" + args[1] + ": " + args[2] + "." + write_to_log("[I] #300 загружаем торрент " + args[0] + " из " + args[1] + " по ссылке " + args[3] + ".\n") + elif imessage == "done": + print "Скрипт завершен успешно." + write_to_log("[I] #021: работа завершена успешно. Завершено.\n") + sys.exit(0) + +def check_requirements(): + req_py_version = (2,7) + unsupported_py_version = (3,0) + cur_version = sys.version_info + + if cur_version >= req_py_version: + if cur_version < unsupported_py_version: + pass; + else: + cnsl_message("invpyver") + else: + cnsl_message("invpyver") + + try: + import curl + import pycurl + except ImportError: + cnsl_message("nocurl") + +def check_params(params): + """ + Checking script parameters: if there is less or more than 2 params -- show help. If there's 2 params: check it's consistency! + """ + if len(params) != 3: + cnsl_message("help") + else: + if params[1] in ["freeleech", "user"]: + if str(params[2]).isdigit(): + pass; + else: + cnsl_message("help") + else: + cnsl_message("help") + +def start_log(): + log = open(curdir + log_file, 'w') + log.write('================================================================================\n= Скрипт скачки раздела NNM-Club для Linux и Unix-like ОС. =\n= Версия: %s =\n================================================================================\n' % version) + log.close() + +def set_username(): + if sys.argv[1] == "freeleech": + username = "freeleech_user" + password = "freeleech_password" + else: + username = "username" + password = "password" + return (username, password) + +def connect(): + cookiefile = open(cookie[1], 'r+w') + write_to_log("[I] #100: пытаемся войти на " + domain + "...\n") + cookie_txt = commands.getoutput('curl -c - -d "username=' + set_username()[0] + '&password=' + set_username()[1] + '&autologin=on&login=%C2%F5%EE%E4&redirect=index.php" "' + domain + '/forum/login.php" 2>>' + curdir + log_file ) + if cookie_txt.find("Cookie") != -1: + # If it's -1, then there is no cookie! + cookiefile.write(cookie_txt) + print cookiefile.read() + cnsl_message("login_ok") + else: + cnsl_message("login_failed") + sys.exit(666) + +def iteratorium(links_array, offset): + """ + Links array -- array with links to topics containing torrents. Offset -- load parameter (for pages) + """ + cnsl_message("pages", str((offset / 50) + 1)) + forum_page = commands.getoutput('curl -b ' + cookie[1] + ' "' + domain + '/forum/viewforum.php?f=' + sys.argv[2] + '&start=' + str(offset) + '" | iconv -f cp1251 -t utf-8') + for line in forum_page.splitlines(): + if 'viewtopic.php' in line: + if 'DL:' in line: + for substring in line.split('"'): + if 'viewtopic.php' in substring: + links_array.append(substring.split('&')[0]) + # Check for the next page + if forum_page.find("След.") != -1: + iteratorium(links_array, offset + 50) + clean_array = [] + for item in links_array: + if item not in clean_array: + clean_array.append(item) + return clean_array + +def download(): + """ + And now that's main part of the script. We need to: + + * iterate over each other page of the forum + * collect all forum topics + * collect all torrents from topics + * check the integrity of downloaded stuff (or why we want to see the log?) + The magic begins... + """ + # Firstly, we need to download forum's startpage + cnsl_message("parsing_started") + startpage = commands.getoutput('curl -b ' + cookie[1] + ' ' + domain + '/forum/viewforum.php?f=' + sys.argv[2] + ' | iconv -f cp1251 -t utf-8') + # Finding forum name :D + for line in startpage.splitlines(): + if 'maintitle' in line: + fname_raw = line + forumname = fname_raw.split('>')[3].split('<')[0] + cnsl_message("forum", forumname) + # And now we start our "good iteratorium" + topics = iteratorium([], 0) + cnsl_message("found_topics", str(len(topics))) + # Aaaand... the first real actions is here + torrentsdir = "%s/%s" % (curdir, sys.argv[2]) + os.mkdir(torrentsdir) + get_torrent(topics, torrentsdir, forumname) + +def parse_topic(topic, forumname, topics, torrents_count, torrentsdir): + topicpage = commands.getoutput('curl -b ' + cookie[1] + ' "' + domain + '/forum/' + topic + '" | iconv -f cp1251 -t utf-8') + for line in topicpage.splitlines(): + if 'maintitle' in line: + tname_raw = line + topicname = tname_raw.split('>')[3].split('<')[0] + for line in topicpage.splitlines(): + if 'download.php' in line: + for lvl2 in line.split('>'): + if 'download.php' in lvl2: + dl_raw = lvl2 + downlink = dl_raw.split('"')[1] + cnsl_message("downloading_torrent", str(torrents_count), str(len(topics)), topicname, (domain + "/" + topic)) + os.chdir(torrentsdir) + if not os.path.exists("./%i00" % (torrents_count / 100)): + os.makedirs("./%i00" % (torrents_count / 100)) + os.chdir("./%i00" % (torrents_count / 100)) + download_torrent(downlink) + +def download_torrent(downlink): + os.system('curl -b ' + cookie[1] + ' -O -J -L "' + domain + '/forum/' + downlink + '" 2>>' + curdir + log_file) + +def get_torrent(topics, torrentsdir, forumname): + cnsl_message("download_started") + torrents_count = 0 + for topic in topics: + torrents_count = torrents_count + 1 + parse_topic(topic, forumname, topics, torrents_count, torrentsdir) + +def cleanup(): + os.remove(cookie[1]) + cnsl_message("done") + + +# That's da fuckin' magic here ;-) + +check_params(sys.argv) +start_log() +check_requirements() + +import curl, pycurl + +cnsl_message("start") +connect() +download() +cleanup() diff --git a/massdl.sh b/massdl.sh deleted file mode 100755 index 82f59ef..0000000 --- a/massdl.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash -# For NNM-Club Uploaders -# Copyright (c) 2012 Valdos Sine -# -# Usage: -# -# ./massdl.sh [mode] [forum] -# -# For getting help, execute ./massdl.sh without params - -UNIXTIME=`date +%s` -TMPDIR=`mktemp -d` -CURDIR=`pwd` -LOG_FILE="$UNIXTIME-massdl.log" -SUBFORUMSDL=0 - -wget_func () { - # Wget helper, which makes many wget usages more stable - # Usage wget_func [path_to_redirect] [anything (wget params, such as -O...)] - wget -t 99 --wait=1 --post-data="username=$USERNAME&password=$PASSWORD&autologin=on&login=%C2%F5%EE%E4&redirect=${1}" "http://nnm-club.me/forum/login.php" ${2} -a $CURDIR/$LOG_FILE - if [[ $? -gt 0 ]] ; then - echo -ne "..ошибка загрузки, повтор.." - wget_func "${1}" "${2}" - fi -} - -# Checking if we have parameter, otherwise show help in Russian -if [[ ${@} == "" ]] ; then - echo "massdl.sh — скрипт для пакетной загрузки торрент-файлов из разделов NNM-club.ru." - echo "Использование:" - echo -ne "\n\t./massdl.sh [режим] [номер_раздела]\n\n" - echo "где [режим] это режим загрузки (от имени пользователя, указанного в конфигурации скрипта — значение user, или же от имени фрилич-пользователя — значение freeleech), а [номер_форума] — номер раздела на NNM-club.ru (например, для форума '*Nix Игры' это 316)." - echo -ne "Примеры:\n\n\t./massdl.sh freeleech 316 — скачивание форума '*Nix Игры' от фрилич-пользователя\n\t./massdl.sh user 332 — скачивание форума 'Русский рок' от собственного, указанного в скрипте, имени\n\n" - echo "Автор: Valdos 'fat0troll' Sine." - echo "Основано на технологиях GNU." - echo "Версия 0.51" - exit 0 -else - echo "Выполняется скрипт ${0}." - echo "Строка параметров работы: ${@}." - echo -ne "Проводим разбор строки..." - # Script configuration - case "x${1}" in - "xuser" ) - # TYPE YOUR USERNAME AND PASSWORD HERE! - USERNAME=user - PASSWORD=password - echo -ne "пользователь $USERNAME" - ;; - "xfreeleech" ) - # Freeleech user credentials - USERNAME=freeleech_user - PASSWORD=freeleech_password - echo -ne "фрилич" - ;; - * ) - # ERROR! - echo -ne "ошибка, неправильный режим работы скрипта! Разрешённые режимы — freeleech или же user.\nЗавершение...\n" - exit 1 - ;; - esac - FORUM=${2} - echo -ne ", номер форума ${FORUM}.\n" - echo "Начинаем работу..." -fi - -# Heading log file - -cat > $LOG_FILE << EOF -================================================================================ -= Скрипт скачки раздела NNM-Club для Linux и Unix-like ОС. = -= Построен на технологиях GNU. = - Дата запуска: `date`. -================================================================================ -EOF - -# Downloading main page of the selected forum -wget_func `echo 'viewforum.php?f='$FORUM` "-O $TMPDIR/page0.html" -FORUMNAME=`cat $TMPDIR/page0.html | iconv -f cp1251 -t utf-8 | grep maintitle | cut -d '>' -f 4 | cut -d '<' -f 1 | sed 's/\//_/g'` -echo "Скачиваем форум \"${FORUMNAME}\"..." -ITERATOR=0 -THREADS=0 - -# Downloading all pages -while [ `cat $TMPDIR/page$ITERATOR.html | iconv -f cp1251 -t utf-8 | grep "След."| grep 'start' | wc -l` == "2" ] -do - iconv -f cp1251 -t utf-8 $TMPDIR/page$ITERATOR.html > $TMPDIR/page$ITERATOR.utf8.html - cat $TMPDIR/page$ITERATOR.utf8.html | grep "download.php" -B 2 | grep topictitle | sed 's/.*]*\).*/\1/' | cut -d '"' -f 2 >> $TMPDIR/alllinkz.txt - THREADS=$(($THREADS + 50)) - ITERATOR=$(($ITERATOR + 1)) - START=$(($ITERATOR * 50)) - echo "Скачиваем страницу $((${ITERATOR} + 1))..." - wget_func `echo 'viewforum.php?f='$FORUM'%26start='$START` "-O $TMPDIR/page$ITERATOR.html" -done -# Last loop ending :) -iconv -f cp1251 -t utf-8 $TMPDIR/page$ITERATOR.html > $TMPDIR/page$ITERATOR.utf8.html -cat $TMPDIR/page$ITERATOR.utf8.html | grep 'download.php' -B 2 | grep topictitle | sed 's/.*]*\).*/\1/' | cut -d '"' -f 2 >> $TMPDIR/alllinkz.txt - -# Detecting subforums -cat $TMPDIR/page0.utf8.html | grep viewforum | grep forumlink | grep -v "images" | cut -d '"' -f 14 | cut -d '=' -f 2 >> $TMPDIR/subforumz.txt - -if [[ `cat $TMPDIR/subforumz.txt | wc -l` -gt 0 ]] ; then - echo "Выявлены подфорумы!" - while read subline - do - echo "Добавляем в очередь закачки форум $subline..." - echo "${0} ${1} $subline" >> $TMPDIR/$UNIXTIME-subforumsdl.sh - done < $TMPDIR/subforumz.txt - chmod +x $TMPDIR/$UNIXTIME-subforumsdl.sh - SUBFORUMSDL=1 -fi - -# You can use it as statistic :) -THREADS=`cat $TMPDIR/alllinkz.txt | wc -l` -echo -ne "Выявлено $THREADS топиков, содержащих торренты! Скачиваем...\n" -# And this is what we need -- getting threads and torrents! -# Torrents will be saved in folders like 100, 200, 300... Every folder contains -# 100 torrents (except the last one). -THREAD=0 -mkdir "$FORUM-$FORUMNAME" -while read line -do - pushd "$FORUM-${FORUMNAME}" >> /dev/null - mkdir "$(($THREAD / 100))" 2>> /dev/null - THREAD=$(($THREAD + 1)) - echo -ne "Скачиваем торрент $THREAD/$THREADS." - # Temporary solution until will be finded way to use cookie.txt... - wget_func $line "-O $TMPDIR/out_$THREAD.html" - # :3 - TOPICHDR=`cat $TMPDIR/out_$THREAD.html | grep maintitle | cut -d '>' -f 4 | cut -d '<' -f 1 | iconv -f cp1251 -t utf-8` - TOPICLNK=`cat $TMPDIR/out_$THREAD.html | grep maintitle | cut -d '"' -f 10` - echo -ne "." - wget_func `cat $TMPDIR/out_$THREAD.html | iconv -f cp1251 -t utf-8 | grep download.php | sed 's/.*]*\).*/\1/' | cut -d '"' -f 2 | tail -1 -` "-P "$(($THREAD / 100))/" --content-disposition" - # Check for bad wget saving... - if [[ -f login.php ]] ; then - echo -ne ".имя файла потеряно. используется сгенерированное скриптом.." - mv login.php "$(($THREAD / 100 ))"/$THREAD.torrent - # Check if file is real torrent. If not... get an error - if [[ `file "$(($THREAD / 100 ))"/$THREAD.torrent | grep BitTorrent` ]] ; then - echo -ne ".файл сохранён как $(($THREAD / 100 ))/$THREAD.torrent.." - else - echo -ne ".скачан не BitTorrent-файл! После завершения работы скрипта проверьте файл $UNIXTIME-error.log — там будет ссылка на нескачанный топик!\n" - echo -ne "Пишем информацию в лог-файл.." - echo "Топик $THREAD: ошибка скачивания $TOPICHDR [https://nnm-club.ru/forum/$TOPICLNK]" >> $CURDIR/$UNIXTIME-error.log - rm "$(($THREAD / 100 ))"/$THREAD.torrent - fi - fi - echo -ne "." - # Check sanity: torrents must equal threads. If not -- post a warning ;) - sanity_error () { - echo -ne ".кажется, топик не отдал нам файла. После завершения работы скрипта проверьте $UNIXTIME-error.log — там будет ссылка на проблемный топик!\n" - echo -ne "Пишем информацию в лог-файл.." - echo "Топик $THREAD: подозрительный $TOPICHDR [https://nnm-club.ru/forum/$TOPICLNK]" >> $CURDIR/$UNIXTIME-error.log - } - actualize_delta () { - # Actualizes delta between files count and expected count: when we switching - # folder delta should be nulled! - if [[ $(($THREAD / 100)) -gt $LAST_ERROR ]] ; then - ERROR_DELTA=0 - else - if [[ x$ERROR_DELTA == "x" ]] ; then - ERROR_DELTA=0 - fi - fi - } - add_delta () { - # Adding delta - LAST_ERROR=$(($THREAD / 100)) - ERROR_DELTA=$(($ERROR_DELTA + 1)) - } - actualize_delta - if [[ $(($THREAD / 100)) -eq '0' ]] ; then - if [[ `ls $(($THREAD / 100))/*.torrent | wc -l` -eq $(($THREAD - $(($THREAD / 100 * 100)) - $ERROR_DELTA)) ]] ; then - echo -ne "" - else - sanity_error - add_delta - fi - else - if [[ `ls $(($THREAD / 100))/*.torrent | wc -l` -eq $(($THREAD - $(($THREAD / 100 * 100)) + 1 - $ERROR_DELTA)) ]] ; then - echo -ne "" - else - sanity_error - add_delta - fi - fi - echo -ne ".\n" - popd >> /dev/null -done < $TMPDIR/alllinkz.txt - -# Downloading subforums -if [[ "x$SUBFORUMSDL" == "x1" ]] ; then - $TMPDIR/$UNIXTIME-subforumsdl.sh -fi - -# Cleaning up... -rm -r $TMPDIR diff --git a/massps.sh b/massps.sh deleted file mode 100755 index 66daf18..0000000 --- a/massps.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# For NNM-Club Uploaders -# Copyright (c) 2012 Valdos Sine -# -# Usage: -# -# ./massps.sh -# -# Install pyrocore by executing: -# -# sudo easy_install pyrocore - -TMPDIR=`mktemp -d` - -SIZE=0 -COUNT=0 - -# Find all torrents -find . -name *torrent > $TMPDIR/allfilez.txt - -while read line -do - COUNT=$(($COUNT + 1)) - echo "$COUNT" - INCREMENT=`lstor "$line" -qo __size__` - SIZE=$(($SIZE + $INCREMENT)) -done < $TMPDIR/allfilez.txt - -echo "$SIZE bytes -> $(($SIZE / 1024)) KB -> $(($SIZE / 1024 / 1024 )) MB -> $(($SIZE / 1024 / 1024 / 1024)) GB." - -rm -r $TMPDIR