Browse Source

kinozal v2.7, repo update

master
imDMG 3 years ago
parent
commit
cf46fb349e
  1. 27
      .gitignore
  2. 2
      README.md
  3. 0
      engines/kinozal.png
  4. 249
      engines/kinozal.py
  5. 0
      engines/nnmclub.png
  6. 0
      engines/nnmclub.py
  7. 0
      engines/rutor.png
  8. 8
      engines/rutor.py
  9. BIN
      engines/rutracker.png
  10. 0
      engines/rutracker.py
  11. 39
      proxychecker.py
  12. 83
      settings_gui.py

27
.gitignore vendored

@ -1,19 +1,12 @@
/engines/kinozal.cookie
/engines/kinozal.json
/engines/nnmclub.cookie
/engines/nnmclub.ico
/engines/nnmclub.json
/engines/rutor.ico
/engines/rutor.json
/engines/rutracker.cookie
/engines/rutracker.json
/modules
/tests /tests
/kinozal.cookie
/kinozal.cookie.bak
/kinozal.ico
/kinozal.json
/kinozal.json.bak
/nnmclub.cookie
/nnmclub.cookie.bak
/nnmclub.ico
/nnmclub.json
/nnmclub.json.bak
/proxylist.txt /proxylist.txt
/rutor.ico
/rutor.json
/rutracker.cookie
/rutracker.cookie.bak
/rutracker.ico
/rutracker.json
/rutracker.json.bak

2
README.md

@ -26,7 +26,7 @@ According of the name of search plugin:
* Then follow [official tutorial](https://github.com/qbittorrent/search-plugins/wiki/Install-search-plugins). * Then follow [official tutorial](https://github.com/qbittorrent/search-plugins/wiki/Install-search-plugins).
* _After installation you can change your settings with `*.json` file which will be created automatically in:_ * _After installation you can change your settings with `*.json` file which will be created automatically in:_
* Windows: `%localappdata%\qBittorrent\nova3\engines` * Windows: `%localappdata%\qBittorrent\nova3\engines`
* Linux: `~/.local/share/data/qBittorrent/nova3/engines` * Linux: `~/.local/share/qBittorrent/nova3/engines`
* OS X: `~/Library/Application Support/qBittorrent/nova3/engines` * OS X: `~/Library/Application Support/qBittorrent/nova3/engines`
**For update just reinstall `*.py` file.** **For update just reinstall `*.py` file.**

0
kinozal.png → engines/kinozal.png

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

249
kinozal.py → engines/kinozal.py

@ -1,4 +1,4 @@
# VERSION: 2.6 # VERSION: 2.7
# AUTHORS: imDMG [imdmgg@gmail.com] # AUTHORS: imDMG [imdmgg@gmail.com]
# Kinozal.tv search engine plugin for qBittorrent # Kinozal.tv search engine plugin for qBittorrent
@ -8,15 +8,16 @@ import gzip
import json import json
import logging import logging
import re import re
import socket
import sys import sys
import time import time
from concurrent.futures.thread import ThreadPoolExecutor from concurrent.futures.thread import ThreadPoolExecutor
from dataclasses import dataclass, field
from functools import partial from functools import partial
from html import unescape from html import unescape
from http.cookiejar import MozillaCookieJar from http.cookiejar import MozillaCookieJar
from pathlib import Path from pathlib import Path
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from typing import Union, Optional
from urllib.error import URLError, HTTPError from urllib.error import URLError, HTTPError
from urllib.parse import urlencode, unquote from urllib.parse import urlencode, unquote
from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler
@ -27,39 +28,29 @@ except ImportError:
sys.path.insert(0, str(Path(__file__).parent.parent.absolute())) sys.path.insert(0, str(Path(__file__).parent.parent.absolute()))
from novaprinter import prettyPrinter from novaprinter import prettyPrinter
# default config # setup logging
config = { logging.basicConfig(
"torrentDate": True, format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
"username": "USERNAME", datefmt="%m-%d %H:%M",
"password": "PASSWORD", level=logging.DEBUG
"proxy": False, )
"proxies": {
"http": "", logger = logging.getLogger(__name__)
"https": ""
},
"magnet": True,
"ua": "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 "
}
FILE = Path(__file__) FILE = Path(__file__)
BASEDIR = FILE.parent.absolute() BASEDIR = FILE.parent.absolute()
FILENAME = FILE.name[:-3] FILENAME = FILE.name[:-3]
FILE_J, FILE_C = [BASEDIR / (FILENAME + fl) for fl in ['.json', '.cookie']] FILE_J, FILE_C = [BASEDIR / (FILENAME + fl) for fl in (".json", ".cookie")]
PAGES = 50 PAGES = 50
def rng(t):
return range(1, -(-t // PAGES))
RE_TORRENTS = re.compile( RE_TORRENTS = re.compile(
r'nam"><a\s+?href="/(.+?)"\s+?class="r\d">(.+?)</a>.+?s\'>.+?s\'>(.+?)<.+?' r'nam"><a\s+?href="/(.+?)"\s+?class="r\d">(.+?)</a>.+?s\'>.+?s\'>(.+?)<.+?'
r'sl_s\'>(\d+?)<.+?sl_p\'>(\d+?)<.+?s\'>(.+?)</td>', re.S r'sl_s\'>(\d+?)<.+?sl_p\'>(\d+?)<.+?s\'>(.+?)</td>', re.S
) )
RE_RESULTS = re.compile(r'</span>Найдено\s+?(\d+?)\s+?раздач', re.S) RE_RESULTS = re.compile(r"</span>Найдено\s+?(\d+?)\s+?раздач", re.S)
PATTERNS = ('%sbrowse.php?s=%s&c=%s', "%s&page=%s") PATTERNS = ("%sbrowse.php?s=%s&c=%s", "%s&page=%s")
# base64 encoded image # base64 encoded image
ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAA" ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAA"
@ -85,75 +76,104 @@ ICON = ("AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAA"
"gEc7/4BHO/+ARztMAAAAAIBHO0yARzv/gEc7/4BHO0wAAAAACCEAAAABAAAAAQAAAAEAAI" "gEc7/4BHO/+ARztMAAAAAIBHO0yARzv/gEc7/4BHO0wAAAAACCEAAAABAAAAAQAAAAEAAI"
"ADAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAACAAwAAAAEAAAABAAAAAQAACCEAAA== ") "ADAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAACAAwAAAAEAAAABAAAAAQAACCEAAA== ")
# setup logging
logging.basicConfig(
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
datefmt="%m-%d %H:%M",
level=logging.DEBUG
)
logger = logging.getLogger(__name__) def rng(t: int) -> range:
return range(1, -(-t // PAGES))
@dataclass
class Config:
username: str = "USERNAME"
password: str = "PASSWORD"
torrent_date: bool = True
magnet: bool = False
proxy: bool = False
# dynamic_proxy: bool = True
proxies: dict = field(default_factory=lambda: {"http": "", "https": ""})
ua: str = ("Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 "
"Firefox/38.0 ")
def __post_init__(self):
try: try:
config = json.loads(FILE_J.read_text()) if not self._validate_json(json.loads(FILE_J.read_text())):
logger.debug("Config is loaded.") raise ValueError("Incorrect json scheme.")
except OSError as e: except Exception as e:
logger.error(e) logger.error(e)
# if file doesn't exist, we'll create it FILE_J.write_text(self.to_str())
FILE_J.write_text(json.dumps(config, indent=4, sort_keys=False)) (BASEDIR / f"{FILENAME}.ico").write_bytes(base64.b64decode(ICON))
# also write/rewrite ico file
(BASEDIR / (FILENAME + '.ico')).write_bytes(base64.b64decode(ICON)) def to_str(self) -> str:
logger.debug("Write files.") return json.dumps(self.to_dict(), indent=4, sort_keys=False)
def to_dict(self) -> dict:
return {self._to_camel(k): v for k, v in self.__dict__.items()}
def _validate_json(self, obj: dict) -> bool:
is_valid = True
for k, v in self.__dict__.items():
_val = obj.get(self._to_camel(k))
if type(_val) is not type(v):
is_valid = False
continue
setattr(self, k, _val)
return is_valid
@staticmethod
def _to_camel(s: str) -> str:
return "".join(x.title() if i else x
for i, x in enumerate(s.split("_")))
config = Config()
class Kinozal: class Kinozal:
name = 'Kinozal' name = "Kinozal"
url = 'http://kinozal.tv/' url = "http://kinozal.tv/"
url_dl = url.replace("//", "//dl.") url_dl = url.replace("//", "//dl.")
url_login = url + 'takelogin.php' url_login = url + "takelogin.php"
supported_categories = {'all': '0', supported_categories = {"all": "0",
'movies': '1002', "movies": "1002",
'tv': '1001', "tv": "1001",
'music': '1004', "music": "1004",
'games': '23', "games": "23",
'anime': '20', "anime": "20",
'software': '32'} "software": "32"}
def __init__(self):
# error message # error message
self.error = None error: Optional[str] = None
# cookies
mcj = MozillaCookieJar()
# establish connection # establish connection
self.session = build_opener() session = build_opener(HTTPCookieProcessor(mcj))
def __init__(self):
# add proxy handler if needed # add proxy handler if needed
if config['proxy']: if config.proxy:
if any(config['proxies'].values()): if any(config.proxies.values()):
self.session.add_handler(ProxyHandler(config['proxies'])) self.session.add_handler(ProxyHandler(config.proxies))
logger.debug("Proxy is set!") logger.debug("Proxy is set!")
else: else:
self.error = "Proxy enabled, but not set!" self.error = "Proxy enabled, but not set!"
# change user-agent # change user-agent
self.session.addheaders = [('User-Agent', config['ua'])] self.session.addheaders = [("User-Agent", config.ua)]
# load local cookies # load local cookies
mcj = MozillaCookieJar()
try: try:
mcj.load(FILE_C, ignore_discard=True) self.mcj.load(FILE_C, ignore_discard=True)
if 'uid' in [cookie.name for cookie in mcj]: if "uid" in [cookie.name for cookie in self.mcj]:
# if cookie.expires < int(time.time()) # if cookie.expires < int(time.time())
logger.info("Local cookies is loaded") logger.info("Local cookies is loaded")
self.session.add_handler(HTTPCookieProcessor(mcj))
else: else:
logger.info("Local cookies expired or bad") logger.info("Local cookies expired or bad")
logger.debug(f"That we have: {[cookie for cookie in mcj]}") logger.debug(f"That we have: {[cookie for cookie in self.mcj]}")
mcj.clear() self.mcj.clear()
self.login(mcj) self.login()
except FileNotFoundError: except FileNotFoundError:
self.login(mcj) self.login()
def search(self, what, cat='all'): def search(self, what: str, cat: str = "all") -> None:
if self.error: if self.error:
self.pretty_error(what) self.pretty_error(what)
return None return None
@ -174,24 +194,24 @@ class Kinozal:
logger.debug(f"--- {time.time() - t0} seconds ---") logger.debug(f"--- {time.time() - t0} seconds ---")
logger.info(f"Found torrents: {total}") logger.info(f"Found torrents: {total}")
def download_torrent(self, url: str): def download_torrent(self, url: str) -> None:
# choose download method # choose download method
if config.get("magnet"): if config.magnet:
url = "%sget_srv_details.php?action=2&id=%s" % (self.url, url = "%sget_srv_details.php?action=2&id=%s" % (self.url,
url.split('=')[1]) url.split("=")[1])
response = self._catch_error_request(url) response = self._request(url)
if self.error: if self.error:
self.pretty_error(url) self.pretty_error(url)
return None return None
if config.get("magnet"): if config.magnet:
if response.startswith(b"\x1f\x8b\x08"): if response.startswith(b"\x1f\x8b\x08"):
response = gzip.decompress(response) response = gzip.decompress(response)
path = 'magnet:?xt=urn:btih:' + response.decode()[18:58] path = "magnet:?xt=urn:btih:" + response.decode()[18:58]
else: else:
# Create a torrent file # Create a torrent file
with NamedTemporaryFile(suffix='.torrent', delete=False) as fd: with NamedTemporaryFile(suffix=".torrent", delete=False) as fd:
fd.write(response) fd.write(response)
path = fd.name path = fd.name
@ -199,55 +219,62 @@ class Kinozal:
logger.debug(path + " " + url) logger.debug(path + " " + url)
print(path + " " + url) print(path + " " + url)
def login(self, mcj): def login(self) -> None:
if self.error: if self.error:
return None return None
self.session.add_handler(HTTPCookieProcessor(mcj))
form_data = {"username": config['username'], form_data = {"username": config.username, "password": config.password}
"password": config['password']}
logger.debug(f"Login. Data before: {form_data}") logger.debug(f"Login. Data before: {form_data}")
# so we first encode vals to cp1251 then do default decode whole string # encoding to cp1251 then do default decode whole string
data_encoded = urlencode( data_encoded = urlencode(form_data, encoding="cp1251").encode()
{k: v.encode('cp1251') for k, v in form_data.items()}
).encode()
logger.debug(f"Login. Data after: {data_encoded}") logger.debug(f"Login. Data after: {data_encoded}")
self._catch_error_request(self.url_login, data_encoded) self._request(self.url_login, data_encoded)
if self.error: if self.error:
return None return None
logger.debug(f"That we have: {[cookie for cookie in mcj]}") logger.debug(f"That we have: {[cookie for cookie in self.mcj]}")
if 'uid' in [cookie.name for cookie in mcj]: if "uid" in [cookie.name for cookie in self.mcj]:
mcj.save(FILE_C, ignore_discard=True, ignore_expires=True) self.mcj.save(FILE_C, ignore_discard=True, ignore_expires=True)
logger.info('We successfully authorized') logger.info("We successfully authorized")
else: else:
self.error = "We not authorized, please check your credentials!" self.error = "We not authorized, please check your credentials!"
logger.warning(self.error) logger.warning(self.error)
def searching(self, query, first=False): def searching(self, query: str, first: bool = False) -> Union[None, int]:
response = self._catch_error_request(query) response = self._request(query)
if not response: if self.error:
return None return None
if response.startswith(b"\x1f\x8b\x08"): if response.startswith(b"\x1f\x8b\x08"):
response = gzip.decompress(response) response = gzip.decompress(response)
page, torrents_found = response.decode('cp1251'), -1 page, torrents_found = response.decode("cp1251"), -1
if first: if first:
# check login status
if "Гость! ( Зарегистрируйтесь )" in page:
logger.debug("Looks like we lost session id, lets login")
self.mcj.clear()
self.login()
if self.error:
return None
# firstly we check if there is a result # firstly we check if there is a result
torrents_found = int(RE_RESULTS.search(page)[1]) result = RE_RESULTS.search(page)
if not result:
self.error = "Unexpected page content"
return None
torrents_found = int(result[1])
if not torrents_found: if not torrents_found:
return 0 return 0
self.draw(page) self.draw(page)
return torrents_found return torrents_found
def draw(self, html: str): def draw(self, html: str) -> None:
torrents = RE_TORRENTS.findall(html) torrents = RE_TORRENTS.findall(html)
_part = partial(time.strftime, "%y.%m.%d") _part = partial(time.strftime, "%y.%m.%d")
# yeah this is yesterday # yeah this is yesterday
yesterday = _part(time.localtime(time.time() - 86400)) yesterday = _part(time.localtime(time.time() - 86400))
for tor in torrents: for tor in torrents:
torrent_date = "" torrent_date = ""
if config['torrentDate']: if config.torrent_date:
ct = tor[5].split()[0] ct = tor[5].split()[0]
if "сегодня" in ct: if "сегодня" in ct:
torrent_date = _part() torrent_date = _part()
@ -255,10 +282,10 @@ class Kinozal:
torrent_date = yesterday torrent_date = yesterday
else: else:
torrent_date = _part(time.strptime(ct, "%d.%m.%Y")) torrent_date = _part(time.strptime(ct, "%d.%m.%Y"))
torrent_date = f'[{torrent_date}] ' torrent_date = f"[{torrent_date}] "
# replace size units # replace size units
table = {'Т': 'T', 'Г': 'G', 'М': 'M', 'К': 'K', 'Б': 'B'} table = {"Т": "T", "Г": "G", "М": "M", "К": "K", "Б": "B"}
prettyPrinter({ prettyPrinter({
"engine_url": self.url, "engine_url": self.url,
@ -271,31 +298,31 @@ class Kinozal:
}) })
del torrents del torrents
def _catch_error_request(self, url=None, data=None, repeated=False): def _request(
url = url or self.url self, url: str, data: Optional[bytes] = None, repeated: bool = False
) -> Union[bytes, None]:
try: try:
with self.session.open(url, data, 5) as r: with self.session.open(url, data, 5) as r:
# checking that tracker isn't blocked # checking that tracker isn't blocked
if r.url.startswith((self.url, self.url_dl)): if r.geturl().startswith((self.url, self.url_dl)):
return r.read() return r.read()
raise URLError(f"{self.url} is blocked. Try another proxy.") self.error = f"{url} is blocked. Try another proxy."
except (socket.error, socket.timeout) as err:
if not repeated:
return self._catch_error_request(url, data, True)
logger.error(err)
self.error = f"{self.url} is not response! Maybe it is blocked."
if "no host given" in err.args:
self.error = "Proxy is bad, try another!"
except (URLError, HTTPError) as err: except (URLError, HTTPError) as err:
logger.error(err.reason) logger.error(err.reason)
self.error = err.reason error = str(err.reason)
if hasattr(err, 'code'): if "timed out" in error and not repeated:
logger.debug("Repeating request...")
return self._request(url, data, True)
if "no host given" in error:
self.error = "Proxy is bad, try another!"
elif hasattr(err, "code"):
self.error = f"Request to {url} failed with status: {err.code}" self.error = f"Request to {url} failed with status: {err.code}"
else:
self.error = f"{url} is not response! Maybe it is blocked."
return None return None
def pretty_error(self, what): def pretty_error(self, what: str) -> None:
prettyPrinter({"engine_url": self.url, prettyPrinter({"engine_url": self.url,
"desc_link": "https://github.com/imDMG/qBt_SE", "desc_link": "https://github.com/imDMG/qBt_SE",
"name": f"[{unquote(what)}][Error]: {self.error}", "name": f"[{unquote(what)}][Error]: {self.error}",
@ -311,9 +338,9 @@ class Kinozal:
kinozal = Kinozal kinozal = Kinozal
if __name__ == "__main__": if __name__ == "__main__":
if BASEDIR.parent.joinpath('settings_gui.py').exists(): if BASEDIR.parent.joinpath("settings_gui.py").exists():
from settings_gui import EngineSettingsGUI from settings_gui import EngineSettingsGUI
EngineSettingsGUI(FILENAME) EngineSettingsGUI(FILENAME)
engine = kinozal() engine = kinozal()
engine.search('doctor') engine.search("doctor")

0
nnmclub.png → engines/nnmclub.png

Before

Width:  |  Height:  |  Size: 912 B

After

Width:  |  Height:  |  Size: 912 B

0
nnmclub.py → engines/nnmclub.py

0
rutor.png → engines/rutor.png

Before

Width:  |  Height:  |  Size: 761 B

After

Width:  |  Height:  |  Size: 761 B

8
rutor.py → engines/rutor.py

@ -245,9 +245,9 @@ class Rutor:
rutor = Rutor rutor = Rutor
if __name__ == "__main__": if __name__ == "__main__":
if BASEDIR.parent.joinpath('settings_gui.py').exists(): # if BASEDIR.parent.joinpath('settings_gui.py').exists():
from settings_gui import EngineSettingsGUI # from settings_gui import EngineSettingsGUI
#
EngineSettingsGUI(FILENAME) # EngineSettingsGUI(FILENAME)
engine = rutor() engine = rutor()
engine.search('doctor') engine.search('doctor')

BIN
engines/rutracker.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

0
rutracker.py → engines/rutracker.py

39
proxychecker.py

@ -5,33 +5,31 @@ import threading
from concurrent.futures.thread import ThreadPoolExecutor from concurrent.futures.thread import ThreadPoolExecutor
from urllib.request import build_opener, ProxyHandler from urllib.request import build_opener, ProxyHandler
HOST = "https://rutracker.org/forum/" HOST = "http://rutor.info"
SCHEME = HOST[:HOST.rfind("://")] SCHEME = HOST[:HOST.rfind("://")]
PROXY_FILE = "proxylist1.txt" # one address per line PROXY_FILE = "proxylist.txt" # one address per line
async def is_good_proxy_aio(loop, proxy: str) -> bool: async def is_good_proxy_aio(proxy: str) -> bool:
try: try:
await asyncio.sleep(.1)
opener = build_opener(ProxyHandler({f"{SCHEME}": proxy})) opener = build_opener(ProxyHandler({f"{SCHEME}": proxy}))
opener.addheaders = [("User-agent", "Mozilla/5.0")] opener.addheaders = [("User-agent", "Mozilla/5.0")]
_part = functools.partial(opener.open, HOST, timeout=3) _part = functools.partial(opener.open, HOST, timeout=3)
res = await loop.run_in_executor(None, _part) # res = await loop.run_in_executor(None, _part)
if not res.geturl().startswith(HOST): if not _part().geturl().startswith(HOST):
raise Exception() raise Exception()
print(proxy) print(proxy)
return True return True
except Exception as e: except OSError:
# print(e)
return False return False
async def run_aio(proxies): async def run_aio(proxies):
loop = asyncio.get_event_loop() await asyncio.gather(*[is_good_proxy(proxy) for proxy in proxies])
for proxy in proxies:
await is_good_proxy_aio(loop, proxy)
def run_thread(proxies): def run_thread(proxies: list) -> None:
tasks = [] tasks = []
for proxy in proxies: for proxy in proxies:
task = threading.Thread(target=is_good_proxy, args=(proxy,)) task = threading.Thread(target=is_good_proxy, args=(proxy,))
@ -41,20 +39,19 @@ def run_thread(proxies):
t.join() t.join()
def run_pool(proxies): def run_pool(proxies: list) -> None:
with ThreadPoolExecutor(len(proxies)) as executor: with ThreadPoolExecutor(len(proxies)) as executor:
executor.map(is_good_proxy, proxies, timeout=30) executor.map(is_good_proxy, proxies, timeout=3)
def is_good_proxy(proxy): def is_good_proxy(proxy: str) -> bool:
try: try:
opener = build_opener(ProxyHandler({f"{SCHEME}": proxy})) opener = build_opener(ProxyHandler({f"{SCHEME}": proxy}))
opener.addheaders = [("User-agent", "Mozilla/5.0")] opener.addheaders = [("User-agent", "Mozilla/5.0")]
req = opener.open(HOST, timeout=3) with opener.open(HOST, timeout=3) as r:
if not req.geturl().startswith(HOST): if not r.geturl().startswith(HOST):
raise Exception() raise Exception()
except Exception as e: except OSError:
# print(e)
return False return False
else: else:
print(proxy) print(proxy)
@ -63,6 +60,12 @@ def is_good_proxy(proxy):
def main(): def main():
t0 = time.time() t0 = time.time()
if PROXY_FILE.startswith("http"):
opener = build_opener()
with opener.open(PROXY_FILE) as r:
proxy_list = [x.rstrip().decode("utf-8") for x in r]
else:
with open(PROXY_FILE) as f: with open(PROXY_FILE) as f:
proxy_list = [x.rstrip() for x in f] proxy_list = [x.rstrip() for x in f]

83
settings_gui.py

@ -1,6 +1,6 @@
import json import json
import tkinter as tk
from pathlib import Path from pathlib import Path
from tkinter import *
from tkinter import ttk, messagebox from tkinter import ttk, messagebox
@ -11,64 +11,65 @@ class EngineSettingsGUI:
if self.cfg_file.exists(): if self.cfg_file.exists():
self.config = json.loads(self.cfg_file.read_text()) self.config = json.loads(self.cfg_file.read_text())
self.window = Tk() self.window = tk.Tk()
self.window.title(engine_name + " Settings") self.window.title(engine_name.capitalize() + " Settings")
mainframe = ttk.Frame(self.window, padding="10") mainframe = ttk.Frame(self.window, padding="10")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) mainframe.grid(column=0, row=0, sticky=tk.N)
self.window.columnconfigure(0, weight=1) self.window.columnconfigure(0, weight=1)
self.window.rowconfigure(0, weight=1) self.window.rowconfigure(0, weight=1)
self.username = StringVar(value=self.config.get('username', '')) self.username = tk.StringVar(value=self.config.get("username", ""))
self.password = StringVar(value=self.config.get('password', '')) self.password = tk.StringVar(value=self.config.get("password", ""))
self.proxy_http = StringVar( self.proxy_http = tk.StringVar(
value=self.config.get('proxies').get('http', '') value=self.config.get("proxies").get("http", "")
) )
self.proxy_https = StringVar( self.proxy_https = tk.StringVar(
value=self.config.get('proxies').get('https', '') value=self.config.get("proxies").get("https", "")
) )
self.date = BooleanVar(value=self.config.get('torrentDate', True)) self.date = tk.BooleanVar(value=self.config.get("torrentDate", True))
self.magnet = BooleanVar(value=self.config.get('magnet', False)) self.magnet = tk.BooleanVar(value=self.config.get("magnet", False))
self.proxy = BooleanVar(value=self.config.get('proxy', False)) self.proxy = tk.BooleanVar(value=self.config.get("proxy", False))
ttk.Label(mainframe, text="Username:").grid(column=0, row=0, sticky=W) ttk.Label(mainframe, text="Username:").grid(
ttk.Label(mainframe, text="Password:").grid(column=0, row=1, sticky=W, column=0, row=0, sticky=tk.W)
rowspan=2) ttk.Label(mainframe, text="Password:").grid(
column=0, row=1, sticky=tk.W, rowspan=2)
ttk.Entry(mainframe, width=25, textvariable=self.username).grid( ttk.Entry(mainframe, width=25, textvariable=self.username).grid(
column=1, row=0, sticky=(W, E), padx=(0, 5) column=1, row=0, sticky=tk.EW, padx=(0, 5)
) )
ttk.Entry(mainframe, width=25, textvariable=self.password).grid( ttk.Entry(mainframe, width=25, textvariable=self.password).grid(
column=1, row=1, rowspan=2, sticky=(W, E), padx=(0, 5) column=1, row=1, rowspan=2, sticky=tk.EW, padx=(0, 5)
) )
ttk.Checkbutton( ttk.Checkbutton(
mainframe, text="Date before torrent", variable=self.date, mainframe, text="Date before torrent", variable=self.date,
onvalue=True onvalue=True
).grid(column=2, row=0, sticky=W) ).grid(column=2, row=0, sticky=tk.W)
ttk.Checkbutton( ttk.Checkbutton(
mainframe, text="Use magnet link", variable=self.magnet, mainframe, text="Use magnet link", variable=self.magnet,
onvalue=True onvalue=True
).grid(column=2, row=1, sticky=W) ).grid(column=2, row=1, sticky=tk.W)
ttk.Checkbutton( ttk.Checkbutton(
mainframe, text="Proxy", variable=self.proxy, onvalue=True, mainframe, text="Proxy", variable=self.proxy, onvalue=True,
command=self.proxy_action command=self.proxy_action
).grid(column=2, row=2, sticky=W) ).grid(column=2, row=2, sticky=tk.W)
ttk.Label(mainframe, text="HTTP:").grid(column=0, row=3, sticky=W) ttk.Label(mainframe, text="HTTP:").grid(column=0, row=3, sticky=tk.W)
ttk.Label(mainframe, text="HTTPS:").grid(column=0, row=4, sticky=W) ttk.Label(mainframe, text="HTTPS:").grid(column=0, row=4, sticky=tk.W)
proxy_state = NORMAL if self.proxy.get() else DISABLED proxy_state = tk.NORMAL if self.proxy.get() else tk.DISABLED
self.http_entry = ttk.Entry( self.http_entry = ttk.Entry(
mainframe, textvariable=self.proxy_http, state=proxy_state mainframe, textvariable=self.proxy_http, state=proxy_state
) )
self.http_entry.grid(column=1, row=3, sticky=(W, E), self.http_entry.grid(column=1, row=3, sticky=tk.EW,
padx=(0, 5), pady=(0, 5)) padx=(0, 5), pady=(0, 5))
self.https_entry = ttk.Entry( self.https_entry = ttk.Entry(
mainframe, textvariable=self.proxy_https, state=proxy_state mainframe, textvariable=self.proxy_https, state=proxy_state
) )
self.https_entry.grid(column=1, row=4, sticky=(W, E), padx=(0, 5)) self.https_entry.grid(column=1, row=4, sticky=tk.EW, padx=(0, 5))
ttk.Button( ttk.Button(
mainframe, text="Save", command=self.close mainframe, text="Save", command=self.close
@ -76,37 +77,37 @@ class EngineSettingsGUI:
self.window.mainloop() self.window.mainloop()
def proxy_action(self): def proxy_action(self) -> None:
state = ("!" if self.proxy.get() else "") + DISABLED state = ("!" if self.proxy.get() else "") + tk.DISABLED
self.http_entry.state([state]) self.http_entry.state([state])
self.https_entry.state([state]) self.https_entry.state([state])
def close(self): def close(self) -> None:
if not (self.username.get() or self.password.get()): if not (self.username.get() or self.password.get()):
messagebox.showinfo('Error', "Some fields is empty!") messagebox.showinfo("Error", "Some fields is empty!")
return None return None
if self.proxy.get() and not (self.http_entry.get() if self.proxy.get() and not (self.http_entry.get()
or self.https_entry.get()): or self.https_entry.get()):
messagebox.showinfo('Error', "Some fields is empty!") messagebox.showinfo("Error", "Some fields is empty!")
return None return None
self.config['username'] = self.username.get() self.config["username"] = self.username.get()
self.config['password'] = self.password.get() self.config["password"] = self.password.get()
self.config['proxy'] = self.proxy.get() self.config["proxy"] = self.proxy.get()
if self.config['proxy']: if self.config["proxy"]:
self.config['proxies'] = { self.config["proxies"] = {
'http': self.http_entry.get(), "http": self.http_entry.get(),
'https': self.https_entry.get() "https": self.https_entry.get()
} }
self.config['torrentDate'] = self.date.get() self.config["torrentDate"] = self.date.get()
self.config['magnet'] = self.magnet.get() self.config["magnet"] = self.magnet.get()
self.cfg_file.write_text( self.cfg_file.write_text(
json.dumps(self.config, indent=4, sort_keys=False) json.dumps(self.config, indent=4, sort_keys=False)
) )
self.window.destroy() self.window.destroy()
if __name__ == '__main__': if __name__ == "__main__":
settings = EngineSettingsGUI("kinozal") settings = EngineSettingsGUI("kinozal")
print(settings.config) print(settings.config)

Loading…
Cancel
Save