Rewrite as standard Python CLI app and more
Now this app supports configuration via lib/config.py. No more hardcode! Now torrent files sorted by last moderator check date, and torrents that haven't been checked will be skipped with log message.
This commit is contained in:
parent
795d7846bf
commit
d391c3ddea
10
lib/config.py.example
Executable file
10
lib/config.py.example
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
# user editable values
|
||||||
|
|
||||||
|
username = 'username'
|
||||||
|
password = 'password'
|
||||||
|
|
||||||
|
# system values, edit at your own risk
|
||||||
|
|
||||||
|
domain = 'http://nnm-club.me'
|
||||||
|
|
||||||
|
|
49
lib/messages.py
Executable file
49
lib/messages.py
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
# *-* encoding: utf-8 *-*
|
||||||
|
"""
|
||||||
|
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 code numbers starts from x00, success messages from x20, warnings from x40 and errors from x66. Console messages have same numbers starting from prefix ‘c’. Log messages start from prefix ‘m’
|
||||||
|
"""
|
||||||
|
c000 = "massdl.sh — скрипт для пакетной загрузки торрент-файлов из разделов NNM-club.ru.\nИспользование:\n\n\tpython massdl.py [номер_раздела]\n\nгде [номер_форума] — номер раздела на NNM-club.ru (например, для форума '*Nix Игры' это 316).\nПримеры:\n\n\tpython massdl.py 316 — скачивание форума '*Nix Игры'\n\tpython massdl.py 332 — скачивание форума 'Русский рок'\n\nАвтор: Valdos 'fat0troll' Sine.\nСкрипт использует Python версии 2.7. При запуске убедитесь, что используете правильный интерпретатор Python!\nКонфигурация скрипта производится в конфигурационном файле lib/config.py, имеющем опции с очевидными названиями.\nВерсия %s\n"
|
||||||
|
c010 = "Выполняется скрипт %s.\nВерсия скрипта %s."
|
||||||
|
c020 = "Параметры командной строки: %s"
|
||||||
|
c021 = "Скрипт завершен успешно."
|
||||||
|
c066 = "Ваша версия Python не поддерживается. Используйте Python 2.7!"
|
||||||
|
c067 = "У вас не установлен PycURL. Обратитесь к справке вашего дистрибутива для подробностей, как его установить."
|
||||||
|
c120 = "Вы залогинились успешно как пользователь %s."
|
||||||
|
c166 = "Не удалось залогиниться как пользователь %s. Проверьте ваши данные в файле lib/config.py!"
|
||||||
|
c200 = "Начинается загрузка форума..."
|
||||||
|
c210 = "Скачиваем страницу %s..."
|
||||||
|
c220 = "Скачиваем форум %s"
|
||||||
|
c221 = "Скачивание страниц завершено. Найдено топиков: %s."
|
||||||
|
c300 = "Начинаем загрузку торрентов..."
|
||||||
|
c310 = "Скачиваю топик %s/%s: %s (обновлён %s)."
|
||||||
|
c340 = "Топик %s/%s: %s не проверен модератором. Пропускается."
|
||||||
|
m000 = '================================================================================\n= Скрипт скачки раздела NNM-Club для Linux и Unix-like ОС. =\n= Версия: %s =\n================================================================================\n'
|
||||||
|
m020 = "[I] #020: окружение скрипта в порядке.\n"
|
||||||
|
m021 = "[I] #021: работа завершена успешно. Завершено.\n"
|
||||||
|
m025 = "[I] #100: пытаемся войти на %s...\n"
|
||||||
|
m066 = "[E] #066: версия Python не поддерживается. Завершено.\n"
|
||||||
|
m067 = "[E] #067: не установлен cURL. Завершено\n"
|
||||||
|
m120 = "[I] #120: выполнен успешный вход на сайт. Cookie лежит по адресу %s.\n"
|
||||||
|
m166 = "[E] #166: неправильное имя пользователя или пароль. Завершено.\n"
|
||||||
|
m210 = "[I] #200: загружаем страницу %s..."
|
||||||
|
m220 = "[I] #220: успешно загружена стартовая страница форума '%s'.\n"
|
||||||
|
m221 = "[I] #221: успешно загружены все страницы форума. Найдено топиков: %s.\n"
|
||||||
|
m310 = "[I] #310 загружаем торрент %s из %s по ссылке %s.\n"
|
||||||
|
m340 = "[W] #340 топик %s из %s [%s, %s] не проверен модераторами. Пропуск.\n"
|
131
massdl.py
Normal file → Executable file
131
massdl.py
Normal file → Executable file
@ -1,90 +1,76 @@
|
|||||||
# *-* encoding: utf-8 *-*
|
# *-* encoding: utf-8 *-*
|
||||||
# For NNM-Club Uploaders
|
# For NNM-Club Uploaders
|
||||||
# Copyright (c) 2012-2013 Valdos Sine <iam@toofat.ru>
|
# Copyright (c) 2012-2014 Valdos Sine <iam@toofat.ru>
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
#
|
#
|
||||||
# python2 ./massdl.py [user] [forum_number]
|
# python2 ./massdl.py [forum_number]
|
||||||
#
|
#
|
||||||
# For getting help, execute "python2 ./massdl.py" without params
|
# For getting help, execute "python2 ./massdl.py" without params
|
||||||
|
|
||||||
import time, tempfile, os, sys, commands
|
import time, tempfile, os, sys, commands
|
||||||
version = 0.61
|
import lib.config as uconfig
|
||||||
|
import lib.messages as umessages
|
||||||
|
import dateutil
|
||||||
|
from dateutil.parser import *
|
||||||
|
version = 0.80
|
||||||
unixtime = int(time.time())
|
unixtime = int(time.time())
|
||||||
cookie = tempfile.mkstemp()
|
cookie = tempfile.mkstemp()
|
||||||
curdir = os.getcwd()
|
curdir = os.getcwd()
|
||||||
log_file = "/%i-massdl.log" % unixtime
|
log_file = "/%i-massdl.log" % unixtime
|
||||||
# Anti-Zapret
|
domain = uconfig.domain
|
||||||
domain = "http://nnm-club.me"
|
|
||||||
|
|
||||||
|
|
||||||
def write_to_log(imessage):
|
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 = open(curdir + log_file, 'a')
|
||||||
log.write(imessage)
|
log.write(imessage)
|
||||||
log.close()
|
log.close()
|
||||||
|
|
||||||
def cnsl_message(imessage, *args):
|
def cnsl_message(imessage, *args):
|
||||||
if imessage == "invpyver":
|
if imessage == "invpyver":
|
||||||
print "Ваша версия Python не поддерживается. Используйте Python 2.7!"
|
print umessages.c066
|
||||||
write_to_log("[E] #066: версия Python не поддерживается. Завершено.\n")
|
write_to_log(umessages.m066)
|
||||||
sys.exit(666)
|
sys.exit(666)
|
||||||
elif imessage == "nocurl":
|
elif imessage == "nocurl":
|
||||||
print "У вас не установлен PycURL. Обратитесь к справке вашего дистрибутива для подробностей, как его установить."
|
print umessages.c067
|
||||||
write_to_log("[E] #067: не установлен cURL. Завершено\n")
|
write_to_log(umessages.m067)
|
||||||
sys.exit(666)
|
sys.exit(666)
|
||||||
elif imessage == "help":
|
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
|
print umessages.c000 % version
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif imessage == "start":
|
elif imessage == "start":
|
||||||
print "Выполняется скрипт %s.\nВерсия скрипта %s." % (sys.argv[0], version)
|
print umessages.c010 % (sys.argv[0], version)
|
||||||
print "Параметры командной строки: %s %s" % (sys.argv[1], sys.argv[2])
|
print umessages.c020 % sys.argv[1]
|
||||||
write_to_log("[I] #020: окружение скрипта в порядке.\n")
|
write_to_log(umessages.m020)
|
||||||
elif imessage == "login_ok":
|
elif imessage == "login_ok":
|
||||||
print "Вы залогинились успешно как пользователь %s." % set_username()[0]
|
print umessages.c120 % set_username()[0]
|
||||||
write_to_log("[I] #120: выполнен успешный вход на сайт. Cookie лежит по адресу %s.\n" % cookie[1])
|
write_to_log(umessages.m120 % cookie[1])
|
||||||
elif imessage == "login_failed":
|
elif imessage == "login_failed":
|
||||||
print "Не удалось залогиниться как пользователь %s. Проверьте ваши данные внутри скрипта!" % set_username()[0]
|
print umessages.c166 % set_username()[0]
|
||||||
write_to_log("[E] #166: неправильное имя пользователя или пароль. Завершено.\n")
|
write_to_log(umessages.m166)
|
||||||
sys.exit(666)
|
sys.exit(666)
|
||||||
elif imessage == "parsing_started":
|
elif imessage == "parsing_started":
|
||||||
print "Начинается загрузка форума..."
|
print umessages.c200
|
||||||
elif imessage == "forum":
|
elif imessage == "forum":
|
||||||
print "Скачиваем форум " + args[0]
|
print umessages.c220 % args[0]
|
||||||
write_to_log('[I] #220: успешно загружена стартовая страница форума "%s".\n' % args[0])
|
write_to_log(umessages.m220 % args[0])
|
||||||
elif imessage == "pages":
|
elif imessage == "pages":
|
||||||
print "Скачиваем страницу " + args[0]
|
print umessages.c210 % args[0]
|
||||||
write_to_log('[I] #200: загружаем страницу ' + args[0] + '...\n')
|
write_to_log(umessages.m210 % args[0])
|
||||||
elif imessage == "found_topics":
|
elif imessage == "found_topics":
|
||||||
print "Скачивание страниц завершено. Найдено топиков: " + args[0] + "."
|
print umessages.c221 % args[0]
|
||||||
write_to_log('[I] #221: успешно загружены все страницы форума. Найдено топиков: ' + args[0] + '.\n')
|
write_to_log(umessages.m221 % args[0])
|
||||||
elif imessage == "download_started":
|
elif imessage == "download_started":
|
||||||
print "Начинаем загрузку торрентов..."
|
print umessages.c300
|
||||||
elif imessage == "downloading_torrent":
|
elif imessage == "downloading_torrent":
|
||||||
print "Скачиваю топик " + args[0] + "/" + args[1] + ": " + args[2] + "."
|
print umessages.c310 % (args[0], args[1], args[2], args[4])
|
||||||
write_to_log("[I] #300 загружаем торрент " + args[0] + " из " + args[1] + " по ссылке " + args[3] + ".\n")
|
write_to_log(umessages.m310 % (args[0], args[1], args[3]))
|
||||||
|
elif imessage == "skip_non_approved":
|
||||||
|
print umessages.c340 % (args[0], args[1], args[2])
|
||||||
|
write_to_log(umessages.m340 % (args[0], args[1], args[2], args[3]))
|
||||||
elif imessage == "done":
|
elif imessage == "done":
|
||||||
print "Скрипт завершен успешно."
|
print umessages.c021
|
||||||
write_to_log("[I] #021: работа завершена успешно. Завершено.\n")
|
write_to_log(umessages.m021)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def check_requirements():
|
def check_requirements():
|
||||||
@ -108,36 +94,27 @@ def check_requirements():
|
|||||||
|
|
||||||
def check_params(params):
|
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!
|
Checking script parameters: if there is less or more than one param -- show help. If there's one param: check one’s consistency!
|
||||||
"""
|
"""
|
||||||
if len(params) != 3:
|
if len(params) != 2:
|
||||||
cnsl_message("help")
|
cnsl_message("help")
|
||||||
else:
|
else:
|
||||||
if params[1] in ["freeleech", "user"]:
|
if str(params[1]).isdigit():
|
||||||
if str(params[2]).isdigit():
|
pass;
|
||||||
pass;
|
|
||||||
else:
|
|
||||||
cnsl_message("help")
|
|
||||||
else:
|
else:
|
||||||
cnsl_message("help")
|
cnsl_message("help")
|
||||||
|
|
||||||
def start_log():
|
def start_log():
|
||||||
log = open(curdir + log_file, 'w')
|
log = open(curdir + log_file, 'w')
|
||||||
log.write('================================================================================\n= Скрипт скачки раздела NNM-Club для Linux и Unix-like ОС. =\n= Версия: %s =\n================================================================================\n' % version)
|
log.write(umessages.m000 % version)
|
||||||
log.close()
|
log.close()
|
||||||
|
|
||||||
def set_username():
|
def set_username():
|
||||||
if sys.argv[1] == "freeleech":
|
return (uconfig.username, uconfig.password)
|
||||||
username = "freeleech_user"
|
|
||||||
password = "freeleech_password"
|
|
||||||
else:
|
|
||||||
username = "username"
|
|
||||||
password = "password"
|
|
||||||
return (username, password)
|
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
cookiefile = open(cookie[1], 'r+w')
|
cookiefile = open(cookie[1], 'r+w')
|
||||||
write_to_log("[I] #100: пытаемся войти на " + domain + "...\n")
|
write_to_log(umessages.m025 % domain)
|
||||||
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 )
|
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 cookie_txt.find("Cookie") != -1:
|
||||||
# If it's -1, then there is no cookie!
|
# If it's -1, then there is no cookie!
|
||||||
@ -153,7 +130,7 @@ def iteratorium(links_array, offset):
|
|||||||
Links array -- array with links to topics containing torrents. Offset -- load parameter (for pages)
|
Links array -- array with links to topics containing torrents. Offset -- load parameter (for pages)
|
||||||
"""
|
"""
|
||||||
cnsl_message("pages", str((offset / 50) + 1))
|
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')
|
forum_page = commands.getoutput('curl -b ' + cookie[1] + ' "' + domain + '/forum/viewforum.php?f=' + sys.argv[1] + '&start=' + str(offset) + '" | iconv -f cp1251 -t utf-8')
|
||||||
for line in forum_page.splitlines():
|
for line in forum_page.splitlines():
|
||||||
if 'viewtopic.php' in line:
|
if 'viewtopic.php' in line:
|
||||||
if 'DL:' in line:
|
if 'DL:' in line:
|
||||||
@ -181,7 +158,7 @@ def download():
|
|||||||
"""
|
"""
|
||||||
# Firstly, we need to download forum's startpage
|
# Firstly, we need to download forum's startpage
|
||||||
cnsl_message("parsing_started")
|
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')
|
startpage = commands.getoutput('curl -b ' + cookie[1] + ' ' + domain + '/forum/viewforum.php?f=' + sys.argv[1] + ' | iconv -f cp1251 -t utf-8')
|
||||||
# Finding forum name :D
|
# Finding forum name :D
|
||||||
for line in startpage.splitlines():
|
for line in startpage.splitlines():
|
||||||
if 'maintitle' in line:
|
if 'maintitle' in line:
|
||||||
@ -192,7 +169,7 @@ def download():
|
|||||||
topics = iteratorium([], 0)
|
topics = iteratorium([], 0)
|
||||||
cnsl_message("found_topics", str(len(topics)))
|
cnsl_message("found_topics", str(len(topics)))
|
||||||
# Aaaand... the first real actions is here
|
# Aaaand... the first real actions is here
|
||||||
torrentsdir = "%s/%s" % (curdir, sys.argv[2])
|
torrentsdir = "%s/%s" % (curdir, sys.argv[1])
|
||||||
os.mkdir(torrentsdir)
|
os.mkdir(torrentsdir)
|
||||||
get_torrent(topics, torrentsdir, forumname)
|
get_torrent(topics, torrentsdir, forumname)
|
||||||
|
|
||||||
@ -202,17 +179,27 @@ def parse_topic(topic, forumname, topics, torrents_count, torrentsdir):
|
|||||||
if 'maintitle' in line:
|
if 'maintitle' in line:
|
||||||
tname_raw = line
|
tname_raw = line
|
||||||
topicname = tname_raw.split('>')[3].split('<')[0]
|
topicname = tname_raw.split('>')[3].split('<')[0]
|
||||||
|
for line in topicpage.splitlines():
|
||||||
|
if 'не проверено модератором!' in line:
|
||||||
|
cnsl_message("skip_non_approved", str(torrents_count), str(len(topics)), topicname, (domain + "/" + topic))
|
||||||
|
return 340
|
||||||
|
for line in topicpage.splitlines():
|
||||||
|
if 'проверено модератором' in line:
|
||||||
|
tdate_raw = line
|
||||||
|
# fix for russian months names (dateutil doesn't parse it, damnnt)
|
||||||
|
tdate_raw = tdate_raw.replace('Янв', '01').replace('Фев', '02').replace('Мар', '03').replace('Апр', '04').replace('Май', '05').replace('Июн', '06').replace('Июл', '07').replace('Авг', '08').replace('Сен', '09').replace('Окт', '10').replace('Ноя', '11').replace('Дек', '12')
|
||||||
|
topicdate = dateutil.parser.parse(tdate_raw.split('>')[1].split('<')[0].split(' ',3)[3]).strftime("%Y-%m-%d")
|
||||||
for line in topicpage.splitlines():
|
for line in topicpage.splitlines():
|
||||||
if 'download.php' in line:
|
if 'download.php' in line:
|
||||||
for lvl2 in line.split('>'):
|
for lvl2 in line.split('>'):
|
||||||
if 'download.php' in lvl2:
|
if 'download.php' in lvl2:
|
||||||
dl_raw = lvl2
|
dl_raw = lvl2
|
||||||
downlink = dl_raw.split('"')[1]
|
downlink = dl_raw.split('"')[1]
|
||||||
cnsl_message("downloading_torrent", str(torrents_count), str(len(topics)), topicname, (domain + "/" + topic))
|
cnsl_message("downloading_torrent", str(torrents_count), str(len(topics)), topicname, (domain + "/" + topic), topicdate)
|
||||||
os.chdir(torrentsdir)
|
os.chdir(torrentsdir)
|
||||||
if not os.path.exists("./%i00" % (torrents_count / 100)):
|
if not os.path.exists("./%s" % topicdate):
|
||||||
os.makedirs("./%i00" % (torrents_count / 100))
|
os.makedirs("./%s" % topicdate)
|
||||||
os.chdir("./%i00" % (torrents_count / 100))
|
os.chdir("./%s" % topicdate)
|
||||||
download_torrent(downlink)
|
download_torrent(downlink)
|
||||||
|
|
||||||
def download_torrent(downlink):
|
def download_torrent(downlink):
|
||||||
|
Loading…
Reference in New Issue
Block a user