From d391c3ddea192713e052960969aa57cbff791688 Mon Sep 17 00:00:00 2001 From: Valdos Sine Date: Fri, 26 Dec 2014 23:08:52 +0400 Subject: [PATCH] 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. --- lib/config.py.example | 10 ++++ lib/messages.py | 49 ++++++++++++++++ massdl.py | 131 +++++++++++++++++++----------------------- 3 files changed, 118 insertions(+), 72 deletions(-) create mode 100755 lib/config.py.example create mode 100755 lib/messages.py mode change 100644 => 100755 massdl.py diff --git a/lib/config.py.example b/lib/config.py.example new file mode 100755 index 0000000..5b330a6 --- /dev/null +++ b/lib/config.py.example @@ -0,0 +1,10 @@ +# user editable values + +username = 'username' +password = 'password' + +# system values, edit at your own risk + +domain = 'http://nnm-club.me' + + diff --git a/lib/messages.py b/lib/messages.py new file mode 100755 index 0000000..5f7e946 --- /dev/null +++ b/lib/messages.py @@ -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" diff --git a/massdl.py b/massdl.py old mode 100644 new mode 100755 index 4ba507a..2c22b3b --- a/massdl.py +++ b/massdl.py @@ -1,90 +1,76 @@ # *-* encoding: utf-8 *-* # For NNM-Club Uploaders -# Copyright (c) 2012-2013 Valdos Sine +# Copyright (c) 2012-2014 Valdos Sine # # Usage: # -# python2 ./massdl.py [user] [forum_number] +# python2 ./massdl.py [forum_number] # # For getting help, execute "python2 ./massdl.py" without params 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()) cookie = tempfile.mkstemp() curdir = os.getcwd() log_file = "/%i-massdl.log" % unixtime -# Anti-Zapret -domain = "http://nnm-club.me" +domain = uconfig.domain 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") + print umessages.c066 + write_to_log(umessages.m066) sys.exit(666) elif imessage == "nocurl": - print "У вас не установлен PycURL. Обратитесь к справке вашего дистрибутива для подробностей, как его установить." - write_to_log("[E] #067: не установлен cURL. Завершено\n") + print umessages.c067 + write_to_log(umessages.m067) 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 + print umessages.c000 % 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") + print umessages.c010 % (sys.argv[0], version) + print umessages.c020 % sys.argv[1] + write_to_log(umessages.m020) elif imessage == "login_ok": - print "Вы залогинились успешно как пользователь %s." % set_username()[0] - write_to_log("[I] #120: выполнен успешный вход на сайт. Cookie лежит по адресу %s.\n" % cookie[1]) + print umessages.c120 % set_username()[0] + write_to_log(umessages.m120 % cookie[1]) elif imessage == "login_failed": - print "Не удалось залогиниться как пользователь %s. Проверьте ваши данные внутри скрипта!" % set_username()[0] - write_to_log("[E] #166: неправильное имя пользователя или пароль. Завершено.\n") + print umessages.c166 % set_username()[0] + write_to_log(umessages.m166) sys.exit(666) elif imessage == "parsing_started": - print "Начинается загрузка форума..." + print umessages.c200 elif imessage == "forum": - print "Скачиваем форум " + args[0] - write_to_log('[I] #220: успешно загружена стартовая страница форума "%s".\n' % args[0]) + print umessages.c220 % args[0] + write_to_log(umessages.m220 % args[0]) elif imessage == "pages": - print "Скачиваем страницу " + args[0] - write_to_log('[I] #200: загружаем страницу ' + args[0] + '...\n') + print umessages.c210 % args[0] + write_to_log(umessages.m210 % args[0]) elif imessage == "found_topics": - print "Скачивание страниц завершено. Найдено топиков: " + args[0] + "." - write_to_log('[I] #221: успешно загружены все страницы форума. Найдено топиков: ' + args[0] + '.\n') + print umessages.c221 % args[0] + write_to_log(umessages.m221 % args[0]) elif imessage == "download_started": - print "Начинаем загрузку торрентов..." + print umessages.c300 elif imessage == "downloading_torrent": - print "Скачиваю топик " + args[0] + "/" + args[1] + ": " + args[2] + "." - write_to_log("[I] #300 загружаем торрент " + args[0] + " из " + args[1] + " по ссылке " + args[3] + ".\n") + print umessages.c310 % (args[0], args[1], args[2], args[4]) + 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": - print "Скрипт завершен успешно." - write_to_log("[I] #021: работа завершена успешно. Завершено.\n") + print umessages.c021 + write_to_log(umessages.m021) sys.exit(0) def check_requirements(): @@ -108,36 +94,27 @@ def check_requirements(): 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") else: - if params[1] in ["freeleech", "user"]: - if str(params[2]).isdigit(): - pass; - else: - cnsl_message("help") + if str(params[1]).isdigit(): + pass; 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.write(umessages.m000 % 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) + return (uconfig.username, uconfig.password) def connect(): 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 ) if cookie_txt.find("Cookie") != -1: # 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) """ 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(): if 'viewtopic.php' in line: if 'DL:' in line: @@ -181,7 +158,7 @@ def download(): """ # 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') + 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 for line in startpage.splitlines(): if 'maintitle' in line: @@ -192,7 +169,7 @@ def download(): topics = iteratorium([], 0) cnsl_message("found_topics", str(len(topics))) # Aaaand... the first real actions is here - torrentsdir = "%s/%s" % (curdir, sys.argv[2]) + torrentsdir = "%s/%s" % (curdir, sys.argv[1]) os.mkdir(torrentsdir) get_torrent(topics, torrentsdir, forumname) @@ -202,17 +179,27 @@ def parse_topic(topic, forumname, topics, torrents_count, torrentsdir): if 'maintitle' in line: tname_raw = line 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(): 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)) + cnsl_message("downloading_torrent", str(torrents_count), str(len(topics)), topicname, (domain + "/" + topic), topicdate) os.chdir(torrentsdir) - if not os.path.exists("./%i00" % (torrents_count / 100)): - os.makedirs("./%i00" % (torrents_count / 100)) - os.chdir("./%i00" % (torrents_count / 100)) + if not os.path.exists("./%s" % topicdate): + os.makedirs("./%s" % topicdate) + os.chdir("./%s" % topicdate) download_torrent(downlink) def download_torrent(downlink):