1

Rewrite downloader script to Python 2

Old shell scripts moved to legacy/shell branch.
This commit is contained in:
Valdos Sine 2013-08-24 22:04:28 +04:00 committed by Vladimir Hodakov
parent caa6945b7e
commit 795d7846bf
3 changed files with 244 additions and 228 deletions

244
massdl.py Normal file
View File

@ -0,0 +1,244 @@
# *-* encoding: utf-8 *-*
# For NNM-Club Uploaders
# Copyright (c) 2012-2013 Valdos Sine <iam@toofat.ru>
#
# 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()

197
massdl.sh
View File

@ -1,197 +0,0 @@
#!/bin/bash
# For NNM-Club Uploaders
# Copyright (c) 2012 Valdos Sine <fat0troll at yandex dot ru>
#
# 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/.*<a href=\([^>]*\).*/\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/.*<a href=\([^>]*\).*/\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/.*<a href=\([^>]*\).*/\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

View File

@ -1,31 +0,0 @@
#!/bin/bash
# For NNM-Club Uploaders
# Copyright (c) 2012 Valdos Sine <fat0troll at yandex dot ru>
#
# 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