diff --git a/kinozal.py b/kinozal.py index 63cc766..4239344 100644 --- a/kinozal.py +++ b/kinozal.py @@ -1,4 +1,4 @@ -# VERSION: 2.4 +# VERSION: 2.5 # AUTHORS: imDMG [imdmgg@gmail.com] # Kinozal.tv search engine plugin for qBittorrent @@ -7,16 +7,15 @@ import base64 import gzip import json import logging -import os import re import socket -import tempfile import time - from concurrent.futures.thread import ThreadPoolExecutor from functools import partial from html import unescape from http.cookiejar import MozillaCookieJar +from pathlib import Path +from tempfile import NamedTemporaryFile from urllib.error import URLError, HTTPError from urllib.parse import urlencode, unquote from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler @@ -25,7 +24,6 @@ from novaprinter import prettyPrinter # default config config = { - "version": 3, "torrentDate": True, "username": "USERNAME", "password": "PASSWORD", @@ -38,24 +36,26 @@ config = { "ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 " } +FILE = Path(__file__) +BASEDIR = FILE.parent.absolute() + +FILENAME = FILE.name[:-3] +FILE_J, FILE_C = [BASEDIR / (FILENAME + fl) for fl in ['.json', '.cookie']] -def path_to(*file): - return os.path.abspath(os.path.join(os.path.dirname(__file__), *file)) +PAGES = 50 def rng(t): - return range(1, -(-t // 50)) + return range(1, -(-t // PAGES)) RE_TORRENTS = re.compile( r'nam">(.+?).+?s\'>.+?s\'>(.+?)<.+?' - r'sl_s\'>(\d+?)<.+?sl_p\'>(\d+?)<.+?s\'>(.+?)', re.S) + r'sl_s\'>(\d+?)<.+?sl_p\'>(\d+?)<.+?s\'>(.+?)', re.S +) RE_RESULTS = re.compile(r'Найдено\s+?(\d+?)\s+?раздач', re.S) PATTERNS = ('%sbrowse.php?s=%s&c=%s', "%s&page=%s") -FILENAME = os.path.basename(__file__)[:-3] -FILE_J, FILE_C = [path_to(FILENAME + fe) for fe in ['.json', '.cookie']] - # base64 encoded image ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAA" "AAAAAAAAAAAACARztMgEc7/4BHO/+ARztMAAAAAIBHO0yhd2n/gEc7/6F3af+ARztMAAAA" @@ -84,33 +84,24 @@ ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAA" logging.basicConfig( format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s", datefmt="%m-%d %H:%M", - level=logging.DEBUG) + level=logging.DEBUG +) logger = logging.getLogger(__name__) try: - # try to load user data from file - with open(FILE_J, 'r+') as f: - cfg = json.load(f) - if "version" not in cfg.keys(): - cfg.update({"version": 2, "torrentDate": True}) - f.seek(0) - f.write(json.dumps(cfg, indent=4, sort_keys=False)) - f.truncate() - config = cfg + config = json.loads(FILE_J.read_text()) logger.debug("Config is loaded.") except OSError as e: logger.error(e) # if file doesn't exist, we'll create it - with open(FILE_J, 'w') as f: - f.write(json.dumps(config, indent=4, sort_keys=False)) + FILE_J.write_text(json.dumps(config, indent=4, sort_keys=False)) # also write/rewrite ico file - with open(path_to(FILENAME + '.ico'), 'wb') as f: - f.write(base64.b64decode(ICON)) + (BASEDIR / (FILENAME + '.ico')).write_bytes(base64.b64decode(ICON)) logger.debug("Write files.") -class kinozal: +class Kinozal: name = 'Kinozal' url = 'http://kinozal.tv/' url_dl = url.replace("//", "//dl.") @@ -170,7 +161,7 @@ class kinozal: self.pretty_error(what) return None # do async requests - if total > 50: + if total > PAGES: qrs = [PATTERNS[1] % (query, x) for x in rng(total)] with ThreadPoolExecutor(len(qrs)) as executor: executor.map(self.searching, qrs, timeout=30) @@ -195,10 +186,9 @@ class kinozal: path = 'magnet:?xt=urn:btih:' + response.decode()[18:58] else: # Create a torrent file - file, path = tempfile.mkstemp('.torrent') - with os.fdopen(file, "wb") as fd: - # Write it to a file + with NamedTemporaryFile(suffix='.torrent', delete=False) as fd: fd.write(response) + path = fd.name # return magnet link / file path logger.debug(path + " " + url) @@ -214,7 +204,8 @@ class kinozal: logger.debug(f"Login. Data before: {form_data}") # so we first encode vals to cp1251 then do default decode whole string data_encoded = urlencode( - {k: v.encode('cp1251') for k, v in form_data.items()}).encode() + {k: v.encode('cp1251') for k, v in form_data.items()} + ).encode() logger.debug(f"Login. Data after: {data_encoded}") self._catch_error_request(self.url_login, data_encoded) @@ -311,6 +302,9 @@ class kinozal: self.error = None +# pep8 +kinozal = Kinozal + if __name__ == "__main__": engine = kinozal() engine.search('doctor') diff --git a/modules/helpers.py b/modules/helpers.py index f17dad5..2633c0e 100644 --- a/modules/helpers.py +++ b/modules/helpers.py @@ -1,4 +1,4 @@ -#VERSION: 1.42 +#VERSION: 1.43 # Author: # Christophe DUMEZ (chris@qbittorrent.org) @@ -40,7 +40,7 @@ import urllib.parse import urllib.request # Some sites blocks default python User-agent -user_agent = 'Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0' +user_agent = 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' headers = {'User-Agent': user_agent} # SOCKS5 Proxy support if "sock_proxy" in os.environ and len(os.environ["sock_proxy"].strip()) > 0: diff --git a/nnmclub.py b/nnmclub.py index d715741..61efdef 100644 --- a/nnmclub.py +++ b/nnmclub.py @@ -1,4 +1,4 @@ -# VERSION: 2.6 +# VERSION: 2.7 # AUTHORS: imDMG [imdmgg@gmail.com] # NoNaMe-Club search engine plugin for qBittorrent @@ -6,14 +6,14 @@ import base64 import json import logging -import os import re import socket -import tempfile import time from concurrent.futures import ThreadPoolExecutor from html import unescape from http.cookiejar import Cookie, MozillaCookieJar +from pathlib import Path +from tempfile import NamedTemporaryFile from urllib.error import URLError, HTTPError from urllib.parse import urlencode, unquote from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler @@ -35,25 +35,27 @@ config = { "ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 " } +FILE = Path(__file__) +BASEDIR = FILE.parent.absolute() -def path_to(*file): - return os.path.abspath(os.path.join(os.path.dirname(__file__), *file)) +FILENAME = FILE.name[:-3] +FILE_J, FILE_C = [BASEDIR / (FILENAME + fl) for fl in ['.json', '.cookie']] + +PAGES = 50 def rng(t): - return range(50, -(-t // 50) * 50, 50) + return range(PAGES, -(-t // PAGES) * PAGES, PAGES) RE_TORRENTS = re.compile( r'topictitle"\shref="(.+?)">(.+?).+?href="(d.+?)".+?(\d+?).+?' - r'(\d+).+?(\d+).+?(\d+)', re.S) + r'(\d+).+?(\d+).+?(\d+)', re.S +) RE_RESULTS = re.compile(r'TP_VER">(?:Результатов\sпоиска:\s(\d{1,3}))?\s', re.S) RE_CODE = re.compile(r'name="code"\svalue="(.+?)"', re.S) PATTERNS = ('%stracker.php?nm=%s&%s', "%s&start=%s") -FILENAME = os.path.basename(__file__)[:-3] -FILE_J, FILE_C = [path_to(FILENAME + fe) for fe in ['.json', '.cookie']] - # base64 encoded image ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaQicAXRQFADICAQAHAAAA" @@ -82,33 +84,24 @@ ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAA" logging.basicConfig( format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s", datefmt="%m-%d %H:%M", - level=logging.DEBUG) + level=logging.DEBUG +) logger = logging.getLogger(__name__) try: - # try to load user data from file - with open(FILE_J, 'r+') as f: - cfg = json.load(f) - if "version" not in cfg.keys(): - cfg.update({"version": 2, "torrentDate": True}) - f.seek(0) - f.write(json.dumps(cfg, indent=4, sort_keys=False)) - f.truncate() - config = cfg + config = json.loads(FILE_J.read_text()) logger.debug("Config is loaded.") except OSError as e: logger.error(e) # if file doesn't exist, we'll create it - with open(FILE_J, 'w') as f: - f.write(json.dumps(config, indent=4, sort_keys=False)) + FILE_J.write_text(json.dumps(config, indent=4, sort_keys=False)) # also write/rewrite ico file - with open(path_to(FILENAME + '.ico'), 'wb') as f: - f.write(base64.b64decode(ICON)) + (BASEDIR / (FILENAME + '.ico')).write_bytes(base64.b64decode(ICON)) logger.debug("Write files.") -class nnmclub: +class NNMClub: name = 'NoNaMe-Club' url = 'https://nnmclub.to/forum/' url_dl = 'https://nnm-club.ws/' @@ -169,7 +162,7 @@ class nnmclub: self.pretty_error(what) return None # do async requests - if total > 50: + if total > PAGES: qrs = [PATTERNS[1] % (query, x) for x in rng(total)] with ThreadPoolExecutor(len(qrs)) as executor: executor.map(self.searching, qrs, timeout=30) @@ -185,14 +178,12 @@ class nnmclub: return None # Create a torrent file - file, path = tempfile.mkstemp('.torrent') - with os.fdopen(file, "wb") as fd: - # Write it to a file + with NamedTemporaryFile(suffix='.torrent', delete=False) as fd: fd.write(response) - # return file path - logger.debug(path + " " + url) - print(path + " " + url) + # return file path + logger.debug(fd.name + " " + url) + print(fd.name + " " + url) def login(self, mcj): if self.error: @@ -214,7 +205,8 @@ class nnmclub: "login": "Вход"} # so we first encode vals to cp1251 then do default decode whole string data_encoded = urlencode( - {k: v.encode('cp1251') for k, v in form_data.items()}).encode() + {k: v.encode('cp1251') for k, v in form_data.items()} + ).encode() self._catch_error_request(self.url_login, data_encoded) if self.error: @@ -303,6 +295,9 @@ class nnmclub: self.error = None +# pep8 +nnmclub = NNMClub + if __name__ == "__main__": engine = nnmclub() engine.search('doctor') diff --git a/rutor.py b/rutor.py index 7eb8686..3dbfbc9 100644 --- a/rutor.py +++ b/rutor.py @@ -1,20 +1,18 @@ -# VERSION: 1.1 +# VERSION: 1.2 # AUTHORS: imDMG [imdmgg@gmail.com] # Rutor.org search engine plugin for qBittorrent - import base64 import json import logging -import os import re import socket -import tempfile import time - from concurrent.futures.thread import ThreadPoolExecutor from html import unescape +from pathlib import Path +from tempfile import NamedTemporaryFile from urllib.error import URLError, HTTPError from urllib.parse import unquote from urllib.request import build_opener, ProxyHandler @@ -23,7 +21,6 @@ from novaprinter import prettyPrinter # default config config = { - "version": 2, "torrentDate": True, "username": "USERNAME", "password": "PASSWORD", @@ -35,24 +32,26 @@ config = { "ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 " } +FILE = Path(__file__) +BASEDIR = FILE.parent.absolute() + +FILENAME = FILE.name[:-3] +FILE_J, FILE_C = [BASEDIR / (FILENAME + fl) for fl in ['.json', '.cookie']] -def path_to(*file): - return os.path.abspath(os.path.join(os.path.dirname(__file__), *file)) +PAGES = 100 def rng(t): - return range(1, -(-t // 100)) + return range(1, -(-t // PAGES)) RE_TORRENTS = re.compile( r'(?:gai|tum)">(.+?)(.+?)([.\d]+ \w+)(.+?)(.+?)([.\d]+ \w+)(.+?)(.+?)\sРезультатов\sпоиска\s(\d{1,4})\s', re.S) PATTERNS = ('%ssearch/%i/%i/000/0/%s',) -FILENAME = os.path.basename(__file__)[:-3] -FILE_J, FILE_C = [path_to(FILENAME + fe) for fe in ['.json', '.cookie']] - # base64 encoded image ICON = ("AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAc4AAMwHNdcQ4vsN3fYS2fUY3fUe3fMj4fkk4fco4PYo5fgk7f5gp8Zu" @@ -77,27 +76,24 @@ ICON = ("AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAA" logging.basicConfig( format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s", datefmt="%m-%d %H:%M", - level=logging.DEBUG) + level=logging.DEBUG +) logger = logging.getLogger(__name__) try: - # try to load user data from file - with open(FILE_J, 'r+') as f: - config = json.load(f) + config = json.loads(FILE_J.read_text()) logger.debug("Config is loaded.") except OSError as e: logger.error(e) # if file doesn't exist, we'll create it - with open(FILE_J, 'w') as f: - f.write(json.dumps(config, indent=4, sort_keys=False)) + FILE_J.write_text(json.dumps(config, indent=4, sort_keys=False)) # also write/rewrite ico file - with open(path_to(FILENAME + '.ico'), 'wb') as f: - f.write(base64.b64decode(ICON)) + (BASEDIR / (FILENAME + '.ico')).write_bytes(base64.b64decode(ICON)) logger.debug("Write files.") -class rutor: +class Rutor: name = 'Rutor' url = 'http://rutor.info/' url_dl = url.replace("//", "//d.") + "download/" @@ -142,7 +138,7 @@ class rutor: self.pretty_error(what) return None # do async requests - if total > 100: + if total > PAGES: query = query.replace('h/0', 'h/%i') qrs = [query % x for x in rng(total)] with ThreadPoolExecutor(len(qrs)) as executor: @@ -159,14 +155,12 @@ class rutor: return None # Create a torrent file - file, path = tempfile.mkstemp('.torrent') - with os.fdopen(file, "wb") as fd: - # Write it to a file + with NamedTemporaryFile(suffix='.torrent', delete=False) as fd: fd.write(response) - # return file path - logger.debug(path + " " + url) - print(path + " " + url) + # return file path + logger.debug(fd.name + " " + url) + print(fd.name + " " + url) def searching(self, query, first=False): response = self._catch_error_request(query) @@ -242,6 +236,9 @@ class rutor: self.error = None +# pep8 +rutor = Rutor + if __name__ == "__main__": engine = rutor() engine.search('doctor') diff --git a/rutracker.py b/rutracker.py index f4c5195..a2cf81f 100644 --- a/rutracker.py +++ b/rutracker.py @@ -1,4 +1,4 @@ -# VERSION: 1.3 +# VERSION: 1.4 # AUTHORS: imDMG [imdmgg@gmail.com] # rutracker.org search engine plugin for qBittorrent @@ -6,15 +6,14 @@ import base64 import json import logging -import os import re import socket -import tempfile import time - from concurrent.futures import ThreadPoolExecutor from html import unescape from http.cookiejar import Cookie, MozillaCookieJar +from pathlib import Path +from tempfile import NamedTemporaryFile from urllib.error import URLError, HTTPError from urllib.parse import urlencode, unquote from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler @@ -23,7 +22,6 @@ from novaprinter import prettyPrinter # default config config = { - "version": 2, "torrentDate": True, "username": "USERNAME", "password": "PASSWORD", @@ -35,25 +33,27 @@ config = { "ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 " } +FILE = Path(__file__) +BASEDIR = FILE.parent.absolute() + +FILENAME = FILE.name[:-3] +FILE_J, FILE_C = [BASEDIR / (FILENAME + fl) for fl in ['.json', '.cookie']] -def path_to(*file): - return os.path.abspath(os.path.join(os.path.dirname(__file__), *file)) +PAGES = 50 def rng(t): - return range(50, -(-t // 50) * 50, 50) + return range(PAGES, -(-t // PAGES) * PAGES, PAGES) RE_TORRENTS = re.compile( r'data-topic_id="(\d+?)".+?">(.+?)' r'.+?data-ts_text="([-0-9]+?)">.+?Личи">(\d+?)', - re.S) + re.S +) RE_RESULTS = re.compile(r'Результатов\sпоиска:\s(\d{1,3})\s 50: + if total > PAGES: qrs = [PATTERNS[1] % (query, x) for x in rng(total)] with ThreadPoolExecutor(len(qrs)) as executor: executor.map(self.searching, qrs, timeout=30) @@ -179,14 +169,12 @@ class rutracker: return None # Create a torrent file - file, path = tempfile.mkstemp('.torrent') - with os.fdopen(file, "wb") as fd: - # Write it to a file + with NamedTemporaryFile(suffix='.torrent', delete=False) as fd: fd.write(response) - # return file path - logger.debug(path + " " + url) - print(path + " " + url) + # return file path + logger.debug(fd.name + " " + url) + print(fd.name + " " + url) def login(self, mcj): if self.error: @@ -203,7 +191,8 @@ class rutracker: logger.debug(f"Login. Data before: {form_data}") # so we first encode vals to cp1251 then do default decode whole string data_encoded = urlencode( - {k: v.encode('cp1251') for k, v in form_data.items()}).encode() + {k: v.encode('cp1251') for k, v in form_data.items()} + ).encode() logger.debug(f"Login. Data after: {data_encoded}") self._catch_error_request(self.url_login, data_encoded) if self.error: @@ -293,6 +282,9 @@ class rutracker: self.error = None +# pep8 +rutracker = Rutracker + if __name__ == "__main__": engine = rutracker() engine.search('doctor')