Browse Source

Added torrent date creation before title (optional), deleted .json, various fix

master
imDMG 5 years ago
parent
commit
f6ecf15ace
  1. 6
      README.md
  2. 11
      kinozal.json
  3. 166
      kinozal.py
  4. 6
      nnmclub.py

6
README.md

@ -11,12 +11,13 @@ One of biggest russian torrent tracker.
## Installation ## Installation
According of the name of search plugin: According of the name of search plugin:
* Edit `*.json` file by replacing `USERNAME` and `PASSWORD` with your torrent tracker username and password. * After installation edit `*.json` file by replacing `USERNAME` and `PASSWORD` with your torrent tracker username and password.
* If tracker is blocked in your country, in same file: * If tracker is blocked in your country, in same file:
* find `"proxy": false` and switch in `true` (`"proxy": true`) * find `"proxy": false` and switch in `true` (`"proxy": true`)
* add proxy links working for you in `proxies` (`{"http": "proxy.example.org:8080"}`) * add proxy links working for you in `proxies` (`{"http": "proxy.example.org:8080"}`)
* *make sure that your proxy work with right protocol* * *make sure that your proxy work with right protocol*
* Move `*.json` and `*.png` to qBittorrent search engines directory: * **_Optionally_**: move `*.ico` to qBittorrent search engines directory:
* Windows: `%localappdata%\qBittorrent\nova3\engines\` * Windows: `%localappdata%\qBittorrent\nova3\engines\`
* Linux: `~/.local/share/data/qBittorrent/nova3/engines/` * Linux: `~/.local/share/data/qBittorrent/nova3/engines/`
* OS X: `~/Library/Application Support/qBittorrent/nova3/engines/` * OS X: `~/Library/Application Support/qBittorrent/nova3/engines/`
@ -24,7 +25,6 @@ According of the name of search plugin:
## Troubleshooting ## Troubleshooting
:warning: If the plugin is't installed with a message about the incompatibility of the plugin: :warning: If the plugin is't installed with a message about the incompatibility of the plugin:
* check that you added all included files
* if torrent tracker is't avalaible for you in web - configure the proxy in `*.json` file * if torrent tracker is't avalaible for you in web - configure the proxy in `*.json` file
All other errors and warnings you can see in log file `*.log`: All other errors and warnings you can see in log file `*.log`:

11
kinozal.json

@ -1,11 +0,0 @@
{
"username": "USERNAME",
"password": "PASSWORD",
"proxy": true,
"proxies": {
"http": "",
"https": ""
},
"magnet": true,
"ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0"
}

166
kinozal.py

@ -1,11 +1,10 @@
# VERSION: 2.0 # VERSION: 2.1
# AUTHORS: imDMG [imdmgg@gmail.com] # AUTHORS: imDMG [imdmgg@gmail.com]
# Kinozal.tv search engine plugin for qBittorrent # Kinozal.tv search engine plugin for qBittorrent
import json import json
import logging import logging
import math
import os import os
import re import re
import tempfile import tempfile
@ -15,18 +14,9 @@ import time
from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler
from urllib.parse import urlencode from urllib.parse import urlencode
from urllib.error import URLError, HTTPError from urllib.error import URLError, HTTPError
from http.cookiejar import CookieJar from http.cookiejar import MozillaCookieJar
from novaprinter import prettyPrinter from novaprinter import prettyPrinter
# setup logging into qBittorrent/logs
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M',
filename=os.path.abspath(os.path.join(os.path.dirname(__file__), '../../logs', 'kinozal.log')),
filemode='w')
start_time = time.time()
class kinozal(object): class kinozal(object):
name = 'Kinozal' name = 'Kinozal'
@ -39,28 +29,46 @@ class kinozal(object):
'anime': '20', 'anime': '20',
'software': '32'} 'software': '32'}
# getting config from kinozal.json # default config for kinozal.json
config = None config = {
try: "version": 2,
# try to load user data from file "torrentDate": True,
with open(os.path.abspath(os.path.join(os.path.dirname(__file__), 'kinozal.json'))) as f: "username": "USERNAME",
config: dict = json.load(f) "password": "PASSWORD",
except OSError as e: "proxy": False,
# file not found "proxies": {
logging.error(e) "http": "",
raise e "https": ""
},
"magnet": True,
"ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0"
}
def __init__(self): def __init__(self):
logging.info('Initialisation') # setup logging into qBittorrent/logs
self.result = [] logging.basicConfig(handlers=[logging.FileHandler(self.path_to('../../logs', 'kinozal.log'), 'w', 'utf-8')],
# establish connection level=logging.DEBUG,
# format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
# make cookie datefmt='%m-%d %H:%M')
cj = CookieJar()
self.session = build_opener(HTTPCookieProcessor(cj))
# avoid endless waiting try:
self.blocked = False # try to load user data from file
with open(self.path_to('kinozal.json'), 'r+') as f:
config = json.load(f)
if "version" not in config.keys():
config.update({"version": 2, "torrentDate": True})
f.seek(0)
f.write(json.dumps(config, indent=4, sort_keys=False))
f.truncate()
self.config = config
except OSError as e:
logging.error(e)
# if file doesn't exist, we'll create it
with open(self.path_to('kinozal.json'), 'w') as f:
f.write(json.dumps(self.config, indent=4, sort_keys=False))
# establish connection
self.session = build_opener()
# add proxy handler if needed # add proxy handler if needed
if self.config['proxy'] and any(self.config['proxies'].keys()): if self.config['proxy'] and any(self.config['proxies'].keys()):
@ -70,26 +78,60 @@ class kinozal(object):
self.session.addheaders.pop() self.session.addheaders.pop()
self.session.addheaders.append(('User-Agent', self.config['ua'])) self.session.addheaders.append(('User-Agent', self.config['ua']))
# avoid endless waiting
self.blocked = False
mcj = MozillaCookieJar()
cookie_file = os.path.abspath(os.path.join(os.path.dirname(__file__), 'kinozal.cookie'))
# load local cookies
if os.path.isfile(cookie_file):
mcj.load(cookie_file, ignore_discard=True)
if 'uid' in [cookie.name for cookie in mcj]:
# if cookie.expires < int(time.time())
logging.info("Local cookies is loaded")
self.session.add_handler(HTTPCookieProcessor(mcj))
else:
logging.info("Local cookies expired or bad")
logging.debug(f"That we have: {[cookie for cookie in mcj]}")
mcj.clear()
self.login(mcj, cookie_file)
else:
self.login(mcj, cookie_file)
def login(self, mcj, cookie_file):
self.session.add_handler(HTTPCookieProcessor(mcj))
form_data = {"username": self.config['username'], "password": self.config['password']} form_data = {"username": self.config['username'], "password": self.config['password']}
# so we first encode keys to cp1251 then do default decode whole string # so we first encode keys to cp1251 then do default decode whole string
data_encoded = urlencode({k: v.encode('cp1251') for k, v in form_data.items()}).encode() data_encoded = urlencode({k: v.encode('cp1251') for k, v in form_data.items()}).encode()
self._catch_error_request(self.url + '/takelogin.php', data_encoded) self._catch_error_request(self.url + '/takelogin.php', data_encoded)
if not self.blocked: if 'uid' not in [cookie.name for cookie in mcj]:
if 'uid' not in [cookie.name for cookie in cj]: logging.warning("we not authorized, please check your credentials")
logging.warning("we not authorized, please check your credentials") else:
else: mcj.save(cookie_file, ignore_discard=True, ignore_expires=True)
logging.info('We successfully authorized') logging.info('We successfully authorized')
def draw(self, html: str): def draw(self, html: str):
torrents = re.findall(r'nam"><a\s+?href="(.+?)"\s+?class="r\d">(.*?)</a>' torrents = re.findall(r'nam"><a\s+?href="(.+?)"\s+?class="r\d">(.*?)</a>'
r'.+?s\'>.+?s\'>(.*?)<.+?sl_s\'>(\d+)<.+?sl_p\'>(\d+)<', html, re.S) r'.+?s\'>.+?s\'>(.*?)<.+?sl_s\'>(\d+)<.+?sl_p\'>(\d+)<.+?s\'>(.*?)</td>', html, re.S)
today, yesterday = time.strftime("%y.%m.%d"), time.strftime("%y.%m.%d", time.localtime(time.time()-86400))
for tor in torrents: for tor in torrents:
torrent_date = ""
if self.config['torrentDate']:
ct = tor[5].split()[0]
if "сегодня" in ct:
torrent_date = today
elif "вчера" in ct:
# yeah this is yesterday
torrent_date = yesterday
else:
torrent_date = time.strftime("%y.%m.%d", time.strptime(ct, "%d.%m.%Y"))
torrent_date = f'[{torrent_date}] '
torrent = {"engine_url": self.url, torrent = {"engine_url": self.url,
"desc_link": self.url + tor[0], "desc_link": self.url + tor[0],
"name": tor[1], "name": torrent_date + tor[1],
"link": 'http://dl.kinozal.tv/download.php?id=' + tor[0].split('=')[1], "link": "http://dl.kinozal.tv/download.php?id=" + tor[0].split("=")[1],
"size": self.units_convert(tor[2]), "size": self.units_convert(tor[2]),
"seeds": tor[3], "seeds": tor[3],
"leech": tor[4]} "leech": tor[4]}
@ -98,6 +140,9 @@ class kinozal(object):
del torrents del torrents
# return len(torrents) # return len(torrents)
def path_to(self, *file):
return os.path.abspath(os.path.join(os.path.dirname(__file__), *file))
@staticmethod @staticmethod
def units_convert(unit): def units_convert(unit):
# replace size units # replace size units
@ -112,7 +157,7 @@ class kinozal(object):
# choose download method # choose download method
if self.config.get("magnet"): if self.config.get("magnet"):
res = self._catch_error_request(self.url + "/get_srv_details.php?action=2&id=" + url.split("=")[1]) res = self._catch_error_request(self.url + "/get_srv_details.php?action=2&id=" + url.split("=")[1])
# magnet = re.search(":\s([A-Z0-9]{40})\<", res.read().decode())[1] # magnet = re.search(":\s([A-Z0-9]{40})<", res.read().decode())[1]
magnet = 'magnet:?xt=urn:btih:' + res.read().decode()[18:58] magnet = 'magnet:?xt=urn:btih:' + res.read().decode()[18:58]
# return magnet link # return magnet link
logging.debug(magnet + " " + url) logging.debug(magnet + " " + url)
@ -141,36 +186,18 @@ class kinozal(object):
return total return total
def search_old(self, what, cat='all'):
if self.blocked:
return
total, current = -1, 0
while total != current:
query = '{}/browse.php?s={}&c={}&page={}'.format(self.url, what.replace(" ", "+"),
self.supported_categories[cat],
math.ceil(current / 50))
response = self._catch_error_request(query)
page = response.read().decode('cp1251')
if total == -1:
total = int(re.search(r'</span>Найдено\s+?(\d+)\s+?раздач</td>', page)[1])
current += self.draw(page)
logging.debug("--- {} seconds ---".format(time.time() - start_time))
logging.info("Found torrents: {}".format(total))
def search(self, what, cat='all'): def search(self, what, cat='all'):
if self.blocked: if self.blocked:
return return
query = '{}/browse.php?s={}&c={}'.format(self.url, what.replace(" ", "+"), query = f'{self.url}/browse.php?s={what.replace(" ", "+")}&c={self.supported_categories[cat]}'
self.supported_categories[cat])
# make first request (maybe it enough) # make first request (maybe it enough)
total = self.searching(query, True) total = self.searching(query, True)
# do async requests # do async requests
if total > 50: if total > 50:
tasks = [] tasks = []
for x in range(1, math.ceil(total / 50)): for x in range(1, -(-total//50)):
task = threading.Thread(target=self.searching, args=(query + "&page={}".format(x),)) task = threading.Thread(target=self.searching, args=(query + f"&page={x}",))
tasks.append(task) tasks.append(task)
task.start() task.start()
@ -179,11 +206,11 @@ class kinozal(object):
task.join() task.join()
del tasks del tasks
logging.debug("--- {} seconds ---".format(time.time() - start_time)) logging.debug(f"--- {time.time() - start_time} seconds ---")
logging.info("Found torrents: {}".format(total)) logging.info(f"Found torrents: {total}")
def _catch_error_request(self, url='', data=None): def _catch_error_request(self, url='', data=None):
url = url if url else self.url url = url or self.url
try: try:
response = self.session.open(url, data) response = self.session.open(url, data)
@ -191,7 +218,7 @@ class kinozal(object):
if response.getcode() != 200: if response.getcode() != 200:
logging.error('Unable connect') logging.error('Unable connect')
raise HTTPError(response.geturl(), response.getcode(), raise HTTPError(response.geturl(), response.getcode(),
"HTTP request to {} failed with status: {}".format(url, response.getcode()), f"HTTP request to {url} failed with status: {response.getcode()}",
response.info(), None) response.info(), None)
except (URLError, HTTPError) as e: except (URLError, HTTPError) as e:
logging.error(e) logging.error(e)
@ -200,15 +227,16 @@ class kinozal(object):
# checking that tracker is'nt blocked # checking that tracker is'nt blocked
self.blocked = False self.blocked = False
if self.url not in response.geturl(): if self.url not in response.geturl():
logging.warning("{} is blocked. Try proxy or another proxy".format(self.url)) logging.warning(f"{self.url} is blocked. Try proxy or another proxy")
self.blocked = True self.blocked = True
return response return response
if __name__ == "__main__": if __name__ == "__main__":
# f = open("result.html", "r") # benchmark start
start_time = time.time()
kinozal_se = kinozal() kinozal_se = kinozal()
# kinozal_se.draw(f.read())
kinozal_se.search('doctor') kinozal_se.search('doctor')
print("--- %s seconds ---" % (time.time() - start_time)) print("--- %s seconds ---" % (time.time() - start_time))
# benchmark end

6
nnmclub.py

@ -32,7 +32,7 @@ class nnmclub(object):
# default config for nnmclub.json # default config for nnmclub.json
config = { config = {
"version": 2, "version": 2,
"torrentDate": False, "torrentDate": True,
"username": "USERNAME", "username": "USERNAME",
"password": "PASSWORD", "password": "PASSWORD",
"proxy": False, "proxy": False,
@ -55,7 +55,7 @@ class nnmclub(object):
with open(self.path_to('nnmclub.json'), 'r+') as f: with open(self.path_to('nnmclub.json'), 'r+') as f:
config = json.load(f) config = json.load(f)
if "version" not in config.keys(): if "version" not in config.keys():
config.update({"version": 2, "torrentDate": False}) config.update({"version": 2, "torrentDate": True})
f.seek(0) f.seek(0)
f.write(json.dumps(config, indent=4, sort_keys=False)) f.write(json.dumps(config, indent=4, sort_keys=False))
f.truncate() f.truncate()
@ -128,7 +128,7 @@ class nnmclub(object):
for tor in torrents: for tor in torrents:
torrent_date = "" torrent_date = ""
if self.config['torrentDate']: if self.config['torrentDate']:
torrent_date = f'[{time.strftime("%d.%m.%y", time.localtime(int(tor[6])))}] ' torrent_date = f'[{time.strftime("%y.%m.%d", time.localtime(int(tor[6])))}] '
torrent = {"engine_url": self.url, torrent = {"engine_url": self.url,
"desc_link": self.url + tor[0], "desc_link": self.url + tor[0],
"name": torrent_date + tor[1], "name": torrent_date + tor[1],

Loading…
Cancel
Save