mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-03 17:39:42 +02:00
Merge pull request #51 from KeksPirates/refactor/improve-code-quality
Refactor/improve code quality
This commit is contained in:
@@ -106,7 +106,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -c "
|
python -c "
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
img = Image.open('src/core/interface/assets/logo.png')
|
img = Image.open('src/interface/assets/logo.png')
|
||||||
img.save('app_icon.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)])
|
img.save('app_icon.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)])
|
||||||
print('Icon converted successfully')
|
print('Icon converted successfully')
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
from core.utils.data.tracker import get_magnet_link
|
|
||||||
from core.utils.data.state import state
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from typing import Dict
|
|
||||||
import requests
|
|
||||||
import time
|
|
||||||
|
|
||||||
cache = {
|
|
||||||
"data": [],
|
|
||||||
"last_fetched": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_expiry = 300
|
|
||||||
|
|
||||||
def _get_telegram_posts():
|
|
||||||
post = 100
|
|
||||||
max_posts = 250
|
|
||||||
posts = []
|
|
||||||
added = set()
|
|
||||||
|
|
||||||
current_time = time.time()
|
|
||||||
|
|
||||||
if cache["data"] and (current_time - cache["last_fetched"] < cache_expiry):
|
|
||||||
return cache["data"]
|
|
||||||
|
|
||||||
while post <= max_posts:
|
|
||||||
url = f"https://t.me/s/real_monkrus/{post}"
|
|
||||||
response = requests.get(url, timeout=10)
|
|
||||||
soup = BeautifulSoup(response.text, "html.parser")
|
|
||||||
bubbles = soup.find_all("div", class_="tgme_widget_message_bubble")
|
|
||||||
|
|
||||||
if not bubbles:
|
|
||||||
break
|
|
||||||
|
|
||||||
for bubble in bubbles:
|
|
||||||
post_txt = bubble.find("div", class_="tgme_widget_message_text js-message_text")
|
|
||||||
if post_txt is None or post_txt.b is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
title = post_txt.b.text
|
|
||||||
link = bubble.find("a", href=lambda x: x and x.startswith("https://uztracker.net"))
|
|
||||||
|
|
||||||
if link:
|
|
||||||
post_url = link["href"]
|
|
||||||
if post_url not in added:
|
|
||||||
added.add(post_url)
|
|
||||||
posts.append(dict(
|
|
||||||
title=title,
|
|
||||||
author="m0nkrus",
|
|
||||||
id=len(posts) + 1,
|
|
||||||
url=post_url
|
|
||||||
))
|
|
||||||
|
|
||||||
post += 22
|
|
||||||
|
|
||||||
posts.reverse()
|
|
||||||
|
|
||||||
cache["data"] = posts
|
|
||||||
cache["last_fetched"] = current_time
|
|
||||||
|
|
||||||
return(posts)
|
|
||||||
|
|
||||||
def scrape_m0nkrus(query):
|
|
||||||
posts = _get_telegram_posts()
|
|
||||||
filtered_posts = []
|
|
||||||
|
|
||||||
for post in posts:
|
|
||||||
if query.lower() in post["title"].lower():
|
|
||||||
filtered_post = post.copy()
|
|
||||||
filtered_post["id"] = len(filtered_posts) + 1
|
|
||||||
filtered_posts.append(filtered_post)
|
|
||||||
|
|
||||||
return filtered_posts
|
|
||||||
|
|
||||||
def get_magnet(post: Dict):
|
|
||||||
return get_magnet_link(post["url"])
|
|
||||||
|
|
||||||
Metadata = {
|
|
||||||
"name" : "m0nkrus",
|
|
||||||
"headers" : ["Post Title", "Author"],
|
|
||||||
"scrapeFunc" : scrape_m0nkrus,
|
|
||||||
"linkFunc" : get_magnet,
|
|
||||||
"isMagnet" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
def init_m0nkrus():
|
|
||||||
state.trackers.update({Metadata["name"] : Metadata})
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
from core.utils.network.jsonhandler import split_data, format_data
|
|
||||||
from core.utils.data.tracker import get_magnet_link
|
|
||||||
from core.utils.logging.logs import consoleLog
|
|
||||||
from core.utils.data.state import state
|
|
||||||
from typing import Dict
|
|
||||||
import requests
|
|
||||||
|
|
||||||
def scrape_rutracker(query):
|
|
||||||
search = requests.get(f"{state.api_url}/search?q={query}", timeout=15)
|
|
||||||
consoleLog("Sent request to server")
|
|
||||||
if search:
|
|
||||||
_, data, _, success, cached = split_data(search.text)
|
|
||||||
if cached:
|
|
||||||
consoleLog("Server response cached")
|
|
||||||
if success:
|
|
||||||
sorted_data = []
|
|
||||||
|
|
||||||
for entry in data:
|
|
||||||
sorted_data.append(
|
|
||||||
{
|
|
||||||
"title" : entry["title"],
|
|
||||||
"author" : entry["author"],
|
|
||||||
"seeders" : entry["seeders"],
|
|
||||||
"leechers" : entry["leechers"],
|
|
||||||
"url" : entry["url"],
|
|
||||||
"id" : entry["id"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return sorted_data
|
|
||||||
else:
|
|
||||||
consoleLog("Scraping failed server-side, unable to fetch posts from rutracker")
|
|
||||||
return []
|
|
||||||
else:
|
|
||||||
consoleLog("No response from server, returning nothing")
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def get_magnet(post: Dict):
|
|
||||||
_, post_links, _, _, _ = format_data([post])
|
|
||||||
return get_magnet_link(post_links[0])
|
|
||||||
|
|
||||||
Metadata = {
|
|
||||||
"name" : "rutracker",
|
|
||||||
"headers" : ["Post Title", "Author", "Seeders", "Leechers"],
|
|
||||||
"scrapeFunc" : scrape_rutracker,
|
|
||||||
"linkFunc" : get_magnet,
|
|
||||||
"isMagnet" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
def init_rutracker():
|
|
||||||
state.trackers.update({Metadata["name"] : Metadata})
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
from core.data.scrapers.provider.buzzheavier import scrape_buzzheavier
|
|
||||||
from core.data.scrapers.provider.gofile import scrape_gofile
|
|
||||||
from core.utils.logging.logs import consoleLog
|
|
||||||
from core.utils.data.state import state
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from typing import Dict
|
|
||||||
import webbrowser
|
|
||||||
import requests
|
|
||||||
import time
|
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
cache = {
|
|
||||||
"data": [],
|
|
||||||
"last_fetched": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_expiry = 300
|
|
||||||
|
|
||||||
def get_Metadata():
|
|
||||||
return Metadata
|
|
||||||
|
|
||||||
def scrape_steamrip_links():
|
|
||||||
|
|
||||||
current_time = time.time()
|
|
||||||
|
|
||||||
if cache["data"] != [] and (current_time - cache["last_fetched"] < cache_expiry):
|
|
||||||
return cache["data"]
|
|
||||||
|
|
||||||
url = f"https://steamrip.com/games-list-page/"
|
|
||||||
response = requests.get(url)
|
|
||||||
text = response.text
|
|
||||||
|
|
||||||
soup = BeautifulSoup(text, "html.parser")
|
|
||||||
games = soup.find_all("li", class_="az-list-item")
|
|
||||||
|
|
||||||
if len(games) == 0:
|
|
||||||
return []
|
|
||||||
|
|
||||||
links = []
|
|
||||||
names = []
|
|
||||||
for gamehtml in games:
|
|
||||||
link = gamehtml.find("a", href=lambda x: x and x.startswith("/"))
|
|
||||||
links += re.findall(r'(?<=href=")[^"]*', link.__str__())
|
|
||||||
name = gamehtml.find("a", href=lambda x: x and x.startswith("/"))
|
|
||||||
names += re.findall(r'(?<=\/">)[^<]*', name.__str__())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# construct the list[dict[str,str]]
|
|
||||||
|
|
||||||
ret = []
|
|
||||||
|
|
||||||
for i in range(len(names)):
|
|
||||||
ret.append({"title" : names[i], "url" : links[i]})
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def scrape_steamrip_game_downloads(gamelink):
|
|
||||||
url = "https://steamrip.com" + gamelink
|
|
||||||
response = requests.get(url)
|
|
||||||
soup = BeautifulSoup(response.text, "html.parser")
|
|
||||||
download_link_elements = soup.find_all("a",class_="shortc-button")
|
|
||||||
download_links = ["buzzheavier", "gofile"]
|
|
||||||
|
|
||||||
for download_link in download_link_elements:
|
|
||||||
pure = download_link.attrs.get("href")
|
|
||||||
if pure[2] == "b":
|
|
||||||
download_links[0] = "https:" + pure
|
|
||||||
if pure[2] == "g":
|
|
||||||
download_links[1] = "https:" + pure
|
|
||||||
|
|
||||||
ret = []
|
|
||||||
|
|
||||||
for link in download_links:
|
|
||||||
if len(link) != 1:
|
|
||||||
ret.append(link)
|
|
||||||
|
|
||||||
cache["data"] = ret
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def get_download_link(post: Dict):
|
|
||||||
url = post["url"]
|
|
||||||
links = scrape_steamrip_game_downloads(url)
|
|
||||||
best = ""
|
|
||||||
for link in links:
|
|
||||||
if link[0] == "h":
|
|
||||||
best = link
|
|
||||||
break
|
|
||||||
|
|
||||||
if links.index(best) == 0:
|
|
||||||
link = scrape_buzzheavier(best)
|
|
||||||
return link
|
|
||||||
elif links.index(best) == 1:
|
|
||||||
link, headers = scrape_gofile(best)
|
|
||||||
return link, headers
|
|
||||||
else:
|
|
||||||
consoleLog("Unable to retrieve download link due to captcha, launching browser...")
|
|
||||||
webbrowser.open(best)
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
def filter_steamrip(query: str):
|
|
||||||
games = scrape_steamrip_links()
|
|
||||||
|
|
||||||
filtered_games = [
|
|
||||||
game for game in games
|
|
||||||
if query.lower() in game["title"].lower()
|
|
||||||
]
|
|
||||||
|
|
||||||
return filtered_games
|
|
||||||
|
|
||||||
Metadata = {
|
|
||||||
"name" : "steamrip",
|
|
||||||
"headers" : ["Game"],
|
|
||||||
"scrapeFunc" : filter_steamrip,
|
|
||||||
"linkFunc" : get_download_link,
|
|
||||||
"isMagnet" : False,
|
|
||||||
}
|
|
||||||
|
|
||||||
def init_steamrip():
|
|
||||||
state.trackers.update({Metadata["name"] : Metadata})
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
from core.utils.data.tracker import get_magnet_link
|
|
||||||
from core.utils.logging.logs import consoleLog
|
|
||||||
from core.utils.data.state import state
|
|
||||||
from urllib.parse import urljoin
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from typing import Dict
|
|
||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
def scrape_uztracker(query):
|
|
||||||
base_url="https://uztracker.net/"
|
|
||||||
search_url = f"{base_url.rstrip('/')}/tracker.php?nm={query}"
|
|
||||||
consoleLog(search_url)
|
|
||||||
posts = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.get(search_url)
|
|
||||||
response.raise_for_status()
|
|
||||||
soup = BeautifulSoup(response.text, 'html.parser')
|
|
||||||
links = soup.find_all('tr', class_="tCenter hl-tr", id=lambda x: x and x.startswith('tor_'))
|
|
||||||
for link in links:
|
|
||||||
|
|
||||||
theme_link = link.find('a', class_="genmed tLink", href=lambda x: x and x.startswith('./viewtopic'))
|
|
||||||
if not theme_link or not theme_link.b:
|
|
||||||
continue
|
|
||||||
url = urljoin(base_url, theme_link['href'])
|
|
||||||
title = theme_link.b.text
|
|
||||||
author_link = link.find('a', class_="med")
|
|
||||||
author = author_link.text.strip() if author_link else "Unknown"
|
|
||||||
|
|
||||||
posts.append(dict(
|
|
||||||
title=title,
|
|
||||||
author=author,
|
|
||||||
url=url,
|
|
||||||
))
|
|
||||||
|
|
||||||
return posts
|
|
||||||
|
|
||||||
except requests.RequestException as e:
|
|
||||||
consoleLog(f"Failed to fetch {search_url}: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_magnet(post: Dict):
|
|
||||||
return get_magnet_link(post["url"])
|
|
||||||
|
|
||||||
Metadata = {
|
|
||||||
"name" : "uztracker",
|
|
||||||
"headers" : ["Post Title", "Author"],
|
|
||||||
"scrapeFunc" : scrape_uztracker,
|
|
||||||
"linkFunc" : get_magnet,
|
|
||||||
"isMagnet" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
def init_uztracker():
|
|
||||||
state.trackers.update({Metadata["name"] : Metadata})
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
from core.data.scrapers.rutracker import init_rutracker
|
|
||||||
from core.data.scrapers.uztracker import init_uztracker
|
|
||||||
from core.data.scrapers.steamrip import init_steamrip
|
|
||||||
from core.data.scrapers.monkrus import init_m0nkrus
|
|
||||||
from core.utils.logging.logs import consoleLog
|
|
||||||
from core.utils.data.state import state
|
|
||||||
|
|
||||||
init_rutracker()
|
|
||||||
init_uztracker()
|
|
||||||
init_m0nkrus()
|
|
||||||
init_steamrip()
|
|
||||||
|
|
||||||
def return_pressed(self):
|
|
||||||
self.show_empty_results(False)
|
|
||||||
search_text = self.searchbar.text()
|
|
||||||
if search_text == "":
|
|
||||||
consoleLog("Error: Can't search for nothing")
|
|
||||||
return
|
|
||||||
consoleLog(f"User searched for: {search_text}")
|
|
||||||
|
|
||||||
tracker = state.trackers[state.currenttracker]
|
|
||||||
scrapefunc = tracker["scrapeFunc"]
|
|
||||||
state.posts = scrapefunc(search_text)
|
|
||||||
|
|
||||||
from core.interface.gui import MainWindow
|
|
||||||
MainWindow._instance.search_results_signal.emit(tracker["headers"])
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
from PySide6.QtWidgets import QWidget, QVBoxLayout
|
|
||||||
|
|
||||||
|
|
||||||
def create_tab(title, searchbar, software_list, tabs, dlbutton, layout2):
|
|
||||||
tab = QWidget()
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
if searchbar:
|
|
||||||
layout.addWidget(searchbar)
|
|
||||||
if layout2:
|
|
||||||
layout.addLayout(layout2)
|
|
||||||
else:
|
|
||||||
layout.addWidget(software_list)
|
|
||||||
if dlbutton:
|
|
||||||
layout.addWidget(dlbutton)
|
|
||||||
tab.setLayout(layout)
|
|
||||||
tabs.addTab(tab, title)
|
|
||||||
return tab
|
|
||||||
|
|
||||||
#################
|
|
||||||
# SETTINGS TABS #
|
|
||||||
#################
|
|
||||||
def general_tab(title, autoresume, update_checkbox, transparent_window, tabs):
|
|
||||||
tab = QWidget()
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
layout.addWidget(autoresume)
|
|
||||||
layout.addWidget(update_checkbox)
|
|
||||||
layout.addWidget(transparent_window)
|
|
||||||
layout.addStretch()
|
|
||||||
tab.setLayout(layout)
|
|
||||||
tabs.addTab(tab, title)
|
|
||||||
return tab
|
|
||||||
|
|
||||||
def paths_tab(title, download_path, image_path, tabs):
|
|
||||||
tab = QWidget()
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
layout.addWidget(download_path)
|
|
||||||
layout.addWidget(image_path)
|
|
||||||
layout.addStretch()
|
|
||||||
tab.setLayout(layout)
|
|
||||||
tabs.addTab(tab, title)
|
|
||||||
return tab
|
|
||||||
|
|
||||||
|
|
||||||
def network_tab(title, network_interface, max_connections, max_downloads, up_speed_limit, down_speed_limit, api_url, tabs):
|
|
||||||
tab = QWidget()
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
layout.addWidget(network_interface)
|
|
||||||
layout.addWidget(max_connections)
|
|
||||||
layout.addWidget(max_downloads)
|
|
||||||
layout.addWidget(up_speed_limit)
|
|
||||||
layout.addWidget(down_speed_limit)
|
|
||||||
layout.addWidget(api_url)
|
|
||||||
layout.addStretch()
|
|
||||||
tab.setLayout(layout)
|
|
||||||
tabs.addTab(tab, title)
|
|
||||||
return tab
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
import requests
|
import requests
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from data.sources.rutracker import RutrackerScraper
|
||||||
|
from data.sources.uztracker import UztrackerScraper
|
||||||
|
from data.sources.steamrip import SteamripScraper
|
||||||
|
from data.sources.monkrus import MonkrusScraper
|
||||||
|
|
||||||
|
# Register Scrapers here
|
||||||
|
SCRAPERS = [
|
||||||
|
RutrackerScraper(),
|
||||||
|
SteamripScraper(),
|
||||||
|
MonkrusScraper(),
|
||||||
|
UztrackerScraper(),
|
||||||
|
]
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
from utils.data.tracker import get_magnet_link
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from typing import Dict
|
||||||
|
import requests
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class MonkrusScraper:
|
||||||
|
name = "m0nkrus"
|
||||||
|
headers = ["Post Title", "Author"]
|
||||||
|
is_magnet = True
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.cache = { "data": [], "last_fetched": 0 }
|
||||||
|
self.cache_expiry = 300
|
||||||
|
|
||||||
|
def _get_telegram_posts(self):
|
||||||
|
post = 100
|
||||||
|
max_posts = 250
|
||||||
|
posts = []
|
||||||
|
added = set()
|
||||||
|
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
if self.cache["data"] and (current_time - self.cache["last_fetched"] < self.cache_expiry):
|
||||||
|
return self.cache["data"]
|
||||||
|
|
||||||
|
while post <= max_posts:
|
||||||
|
url = f"https://t.me/s/real_monkrus/{post}"
|
||||||
|
response = requests.get(url, timeout=10)
|
||||||
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
bubbles = soup.find_all("div", class_="tgme_widget_message_bubble")
|
||||||
|
|
||||||
|
if not bubbles:
|
||||||
|
break
|
||||||
|
|
||||||
|
for bubble in bubbles:
|
||||||
|
post_txt = bubble.find("div", class_="tgme_widget_message_text js-message_text")
|
||||||
|
if post_txt is None or post_txt.b is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
title = post_txt.b.text
|
||||||
|
link = bubble.find("a", href=lambda x: x and x.startswith("https://uztracker.net"))
|
||||||
|
|
||||||
|
if link:
|
||||||
|
post_url = link["href"]
|
||||||
|
if post_url not in added:
|
||||||
|
added.add(post_url)
|
||||||
|
posts.append(dict(
|
||||||
|
title=title,
|
||||||
|
author="m0nkrus",
|
||||||
|
id=len(posts) + 1,
|
||||||
|
url=post_url
|
||||||
|
))
|
||||||
|
|
||||||
|
post += 22
|
||||||
|
|
||||||
|
posts.reverse()
|
||||||
|
|
||||||
|
self.cache["data"] = posts
|
||||||
|
self.cache["last_fetched"] = current_time
|
||||||
|
|
||||||
|
return(posts)
|
||||||
|
|
||||||
|
def search(self, query):
|
||||||
|
posts = self._get_telegram_posts()
|
||||||
|
filtered_posts = []
|
||||||
|
|
||||||
|
for post in posts:
|
||||||
|
if query.lower() in post["title"].lower():
|
||||||
|
filtered_post = post.copy()
|
||||||
|
filtered_post["id"] = len(filtered_posts) + 1
|
||||||
|
filtered_posts.append(filtered_post)
|
||||||
|
|
||||||
|
return filtered_posts
|
||||||
|
|
||||||
|
def get_download_link(self, post: Dict):
|
||||||
|
return get_magnet_link(post["url"])
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
from utils.network.jsonhandler import split_data, format_data
|
||||||
|
from utils.data.tracker import get_magnet_link
|
||||||
|
from utils.logging.logs import consoleLog
|
||||||
|
from utils.data.state import state
|
||||||
|
from typing import Dict
|
||||||
|
import requests
|
||||||
|
|
||||||
|
class RutrackerScraper:
|
||||||
|
name = "rutracker"
|
||||||
|
headers = ["Post Title", "Author", "Seeders", "Leechers"]
|
||||||
|
is_magnet = True
|
||||||
|
|
||||||
|
def search(self, query):
|
||||||
|
search = requests.get(f"{state.api_url}/search?q={query}", timeout=15)
|
||||||
|
consoleLog("Sent request to server")
|
||||||
|
if search:
|
||||||
|
_, data, _, success, cached = split_data(search.text)
|
||||||
|
if cached:
|
||||||
|
consoleLog("Server response cached")
|
||||||
|
if success:
|
||||||
|
sorted_data = []
|
||||||
|
|
||||||
|
for entry in data:
|
||||||
|
sorted_data.append(
|
||||||
|
{
|
||||||
|
"title" : entry["title"],
|
||||||
|
"author" : entry["author"],
|
||||||
|
"seeders" : entry["seeders"],
|
||||||
|
"leechers" : entry["leechers"],
|
||||||
|
"url" : entry["url"],
|
||||||
|
"id" : entry["id"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return sorted_data
|
||||||
|
else:
|
||||||
|
consoleLog("Scraping failed server-side, unable to fetch posts from rutracker")
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
consoleLog("No response from server, returning nothing")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_download_link(self, post: Dict):
|
||||||
|
_, post_links, _, _, _ = format_data([post])
|
||||||
|
return get_magnet_link(post_links[0])
|
||||||
|
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
from data.hosts.buzzheavier import scrape_buzzheavier
|
||||||
|
from data.hosts.gofile import scrape_gofile
|
||||||
|
from utils.logging.logs import consoleLog
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from typing import Dict
|
||||||
|
import webbrowser
|
||||||
|
import requests
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
|
class SteamripScraper:
|
||||||
|
name = "steamrip"
|
||||||
|
headers = ["Game"]
|
||||||
|
is_magnet = False
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.cache = { "data": [], "last_fetched": 0 }
|
||||||
|
self.cache_expiry = 300
|
||||||
|
|
||||||
|
def scrape_steamrip_links(self):
|
||||||
|
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
if self.cache["data"] != [] and (current_time - self.cache["last_fetched"] < self.cache_expiry):
|
||||||
|
return self.cache["data"]
|
||||||
|
|
||||||
|
url = f"https://steamrip.com/games-list-page/"
|
||||||
|
response = requests.get(url)
|
||||||
|
text = response.text
|
||||||
|
|
||||||
|
soup = BeautifulSoup(text, "html.parser")
|
||||||
|
games = soup.find_all("li", class_="az-list-item")
|
||||||
|
|
||||||
|
if len(games) == 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
links = []
|
||||||
|
names = []
|
||||||
|
for gamehtml in games:
|
||||||
|
link = gamehtml.find("a", href=lambda x: x and x.startswith("/"))
|
||||||
|
links += re.findall(r'(?<=href=")[^"]*', link.__str__())
|
||||||
|
name = gamehtml.find("a", href=lambda x: x and x.startswith("/"))
|
||||||
|
names += re.findall(r'(?<=\/">)[^<]*', name.__str__())
|
||||||
|
|
||||||
|
# construct the list[dict[str,str]]
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
for i in range(len(names)):
|
||||||
|
ret.append({"title" : names[i], "url" : links[i]})
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def scrape_steamrip_game_downloads(self, gamelink):
|
||||||
|
url = "https://steamrip.com" + gamelink
|
||||||
|
response = requests.get(url)
|
||||||
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
download_link_elements = soup.find_all("a",class_="shortc-button")
|
||||||
|
download_links = ["buzzheavier", "gofile"]
|
||||||
|
|
||||||
|
for download_link in download_link_elements:
|
||||||
|
pure = download_link.attrs.get("href")
|
||||||
|
if pure[2] == "b":
|
||||||
|
download_links[0] = "https:" + pure
|
||||||
|
if pure[2] == "g":
|
||||||
|
download_links[1] = "https:" + pure
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
for link in download_links:
|
||||||
|
if len(link) != 1:
|
||||||
|
ret.append(link)
|
||||||
|
|
||||||
|
self.cache["data"] = ret
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def get_download_link(self, post: Dict):
|
||||||
|
url = post["url"]
|
||||||
|
links = self.scrape_steamrip_game_downloads(url)
|
||||||
|
best = ""
|
||||||
|
for link in links:
|
||||||
|
if link[0] == "h":
|
||||||
|
best = link
|
||||||
|
break
|
||||||
|
|
||||||
|
if links.index(best) == 0:
|
||||||
|
link = scrape_buzzheavier(best)
|
||||||
|
return link
|
||||||
|
elif links.index(best) == 1:
|
||||||
|
link, headers = scrape_gofile(best)
|
||||||
|
return link, headers
|
||||||
|
else:
|
||||||
|
consoleLog("Unable to retrieve download link due to captcha, launching browser...")
|
||||||
|
webbrowser.open(best)
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def search(self, query: str):
|
||||||
|
games = self.scrape_steamrip_links()
|
||||||
|
|
||||||
|
filtered_games = [
|
||||||
|
game for game in games
|
||||||
|
if query.lower() in game["title"].lower()
|
||||||
|
]
|
||||||
|
|
||||||
|
return filtered_games
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
from utils.data.tracker import get_magnet_link
|
||||||
|
from utils.logging.logs import consoleLog
|
||||||
|
from utils.data.state import state
|
||||||
|
from urllib.parse import urljoin
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from typing import Dict
|
||||||
|
import requests
|
||||||
|
|
||||||
|
class UztrackerScraper:
|
||||||
|
name = "uztracker"
|
||||||
|
headers = ["Post Title", "Author"]
|
||||||
|
is_magnet = True
|
||||||
|
|
||||||
|
|
||||||
|
def search(self, query):
|
||||||
|
base_url="https://uztracker.net/"
|
||||||
|
search_url = f"{base_url.rstrip('/')}/tracker.php?nm={query}"
|
||||||
|
consoleLog(search_url)
|
||||||
|
posts = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(search_url)
|
||||||
|
response.raise_for_status()
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
links = soup.find_all('tr', class_="tCenter hl-tr", id=lambda x: x and x.startswith('tor_'))
|
||||||
|
for link in links:
|
||||||
|
|
||||||
|
theme_link = link.find('a', class_="genmed tLink", href=lambda x: x and x.startswith('./viewtopic'))
|
||||||
|
if not theme_link or not theme_link.b:
|
||||||
|
continue
|
||||||
|
url = urljoin(base_url, theme_link['href'])
|
||||||
|
title = theme_link.b.text
|
||||||
|
author_link = link.find('a', class_="med")
|
||||||
|
author = author_link.text.strip() if author_link else "Unknown"
|
||||||
|
|
||||||
|
posts.append(dict(
|
||||||
|
title=title,
|
||||||
|
author=author,
|
||||||
|
url=url,
|
||||||
|
))
|
||||||
|
|
||||||
|
return posts
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
consoleLog(f"Failed to fetch {search_url}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_download_link(self, post: Dict):
|
||||||
|
return get_magnet_link(post["url"])
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
@@ -1,7 +1,7 @@
|
|||||||
from core.utils.logging.logs import consoleLog, remove_download_log
|
from utils.logging.logs import consoleLog, remove_download_log
|
||||||
from PySide6.QtWidgets import QMessageBox
|
from PySide6.QtWidgets import QMessageBox
|
||||||
from core.utils.data.state import state
|
|
||||||
from PySide6.QtCore import Qt, QPoint
|
from PySide6.QtCore import Qt, QPoint
|
||||||
|
from utils.data.state import state
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
import subprocess
|
import subprocess
|
||||||
import platform
|
import platform
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
from core.interface.dialogs.pauseresumedelegate import PauseResumeDelegate
|
from interface.dialogs.pauseresumedelegate import PauseResumeDelegate
|
||||||
from core.interface.dialogs.hoverrowdelegate import HoverRowDelegate
|
from interface.dialogs.hoverrowdelegate import HoverRowDelegate
|
||||||
from core.interface.dialogs.downloadmodel import DownloadModel
|
from interface.dialogs.downloadmodel import DownloadModel
|
||||||
from core.interface.dialogs.theme import _table_stylesheet
|
from interface.dialogs.theme import _table_stylesheet
|
||||||
from PySide6.QtWidgets import QTableView, QHeaderView
|
from PySide6.QtWidgets import QTableView, QHeaderView
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
|
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
import subprocess
|
import subprocess
|
||||||
import platform
|
import platform
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
from core.interface.dialogs.theme import _theme_colors
|
from interface.dialogs.theme import _theme_colors
|
||||||
from PySide6.QtWidgets import QStyledItemDelegate
|
from PySide6.QtWidgets import QStyledItemDelegate
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from PySide6.QtCore import QEvent
|
from PySide6.QtCore import QEvent
|
||||||
|
|
||||||
def eventFilter(self, obj, event):
|
def eventFilter(self, obj, event):
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
from core.interface.dialogs.theme import _theme_colors
|
from interface.dialogs.theme import _theme_colors
|
||||||
from PySide6.QtWidgets import QStyledItemDelegate
|
from PySide6.QtWidgets import QStyledItemDelegate
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
|
|
||||||
class HoverRowDelegate(QStyledItemDelegate):
|
class HoverRowDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
def paint(self, painter, option, index):
|
def paint(self, painter, option, index):
|
||||||
from core.interface.gui import MainWindow
|
from interface.gui import MainWindow
|
||||||
|
|
||||||
opt = QtWidgets.QStyleOptionViewItem(option)
|
opt = QtWidgets.QStyleOptionViewItem(option)
|
||||||
option.state &= ~QtWidgets.QStyle.StateFlag.State_HasFocus
|
option.state &= ~QtWidgets.QStyle.StateFlag.State_HasFocus
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from PySide6.QtGui import QImage, QPixmap
|
from PySide6.QtGui import QImage, QPixmap
|
||||||
from core.utils.data.state import state
|
|
||||||
from PySide6.QtWidgets import QLabel
|
from PySide6.QtWidgets import QLabel
|
||||||
|
from utils.data.state import state
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
import os
|
import os
|
||||||
|
|
||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
from core.interface.dialogs.theme import _theme_colors, SVG_PLAY, SVG_PAUSE, SVG_FOLDER
|
from interface.dialogs.theme import _theme_colors, SVG_PLAY, SVG_PAUSE, SVG_FOLDER
|
||||||
from PySide6.QtWidgets import QStyledItemDelegate, QWidget, QHBoxLayout
|
from PySide6.QtWidgets import QStyledItemDelegate, QWidget, QHBoxLayout
|
||||||
from core.interface.utils.svghelper import svg_icon
|
from interface.utils.svghelper import svg_icon
|
||||||
from PySide6.QtCore import Qt, QSize, Signal
|
from PySide6.QtCore import Qt, QSize, Signal
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ class PauseResumeDelegate(QStyledItemDelegate):
|
|||||||
clicked = Signal(int)
|
clicked = Signal(int)
|
||||||
|
|
||||||
def paint(self, painter, option, index):
|
def paint(self, painter, option, index):
|
||||||
from core.interface.gui import MainWindow
|
from interface.gui import MainWindow
|
||||||
|
|
||||||
opt = QtWidgets.QStyleOptionViewItem(option)
|
opt = QtWidgets.QStyleOptionViewItem(option)
|
||||||
option.state &= ~QtWidgets.QStyle.StateFlag.State_HasFocus
|
option.state &= ~QtWidgets.QStyle.StateFlag.State_HasFocus
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
from core.interface.utils.tabhelper import general_tab
|
from interface.utils.tabhelper import create_tab
|
||||||
from core.interface.utils.tabhelper import network_tab
|
from utils.config.settings import save_settings
|
||||||
from core.utils.config.settings import save_settings
|
from interface.utils.svghelper import svg_icon
|
||||||
from core.interface.utils.tabhelper import paths_tab
|
from utils.logging.logs import consoleLog
|
||||||
from core.interface.utils.svghelper import svg_icon
|
|
||||||
from core.utils.logging.logs import consoleLog
|
|
||||||
from core.utils.data.state import state
|
|
||||||
from PySide6.QtCore import Qt, QSize
|
from PySide6.QtCore import Qt, QSize
|
||||||
|
from utils.data.state import state
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QLineEdit,
|
QLineEdit,
|
||||||
@@ -19,7 +17,6 @@ from PySide6.QtWidgets import (
|
|||||||
QCheckBox,
|
QCheckBox,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
QComboBox,
|
QComboBox,
|
||||||
QTabWidget,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
@@ -46,7 +43,7 @@ def settings_dialog(self):
|
|||||||
update_checkbox_container = QWidget()
|
update_checkbox_container = QWidget()
|
||||||
update_checkbox_layout = QHBoxLayout()
|
update_checkbox_layout = QHBoxLayout()
|
||||||
|
|
||||||
# ignore updates checkbox
|
# Ignore updates checkbox
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
update_checkbox = QCheckBox()
|
update_checkbox = QCheckBox()
|
||||||
@@ -57,7 +54,7 @@ def settings_dialog(self):
|
|||||||
update_checkbox.toggled.connect(lambda checked: setattr(state, 'ignore_updates', checked))
|
update_checkbox.toggled.connect(lambda checked: setattr(state, 'ignore_updates', checked))
|
||||||
update_checkbox_layout.addWidget(update_checkbox)
|
update_checkbox_layout.addWidget(update_checkbox)
|
||||||
|
|
||||||
# auto-resume downloads checkbox
|
# Auto-resume downloads checkbox
|
||||||
|
|
||||||
autoresume_container = QWidget()
|
autoresume_container = QWidget()
|
||||||
autoresume_layout = QHBoxLayout()
|
autoresume_layout = QHBoxLayout()
|
||||||
@@ -71,7 +68,7 @@ def settings_dialog(self):
|
|||||||
autoresume_layout.addWidget(autoresume_checkbox)
|
autoresume_layout.addWidget(autoresume_checkbox)
|
||||||
|
|
||||||
|
|
||||||
# transparent window checkbox
|
# Transparent window checkbox
|
||||||
transparent_window_container = QWidget()
|
transparent_window_container = QWidget()
|
||||||
transparent_window_layout = QHBoxLayout()
|
transparent_window_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -84,10 +81,8 @@ def settings_dialog(self):
|
|||||||
transparent_window_checkbox.toggled.connect(lambda checked: setattr(state, 'window_transparency', checked))
|
transparent_window_checkbox.toggled.connect(lambda checked: setattr(state, 'window_transparency', checked))
|
||||||
transparent_window_layout.addWidget(transparent_window_checkbox)
|
transparent_window_layout.addWidget(transparent_window_checkbox)
|
||||||
|
|
||||||
##################
|
|
||||||
# SERVER SETTING #
|
|
||||||
##################
|
|
||||||
|
|
||||||
|
# API Server Setting
|
||||||
api_url_container = QWidget()
|
api_url_container = QWidget()
|
||||||
api_url_layout = QHBoxLayout()
|
api_url_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -98,10 +93,8 @@ def settings_dialog(self):
|
|||||||
api_url_container.setLayout(api_url_layout)
|
api_url_container.setLayout(api_url_layout)
|
||||||
api_url.setText(state.api_url)
|
api_url.setText(state.api_url)
|
||||||
|
|
||||||
#################
|
|
||||||
# DOWNLOAD PATH #
|
|
||||||
#################
|
|
||||||
|
|
||||||
|
# Download Path
|
||||||
download_path_container = QWidget()
|
download_path_container = QWidget()
|
||||||
download_path_layout = QHBoxLayout()
|
download_path_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -133,10 +126,8 @@ def settings_dialog(self):
|
|||||||
download_path_layout.addWidget(browse_button)
|
download_path_layout.addWidget(browse_button)
|
||||||
browse_button.clicked.connect(browse_download_path)
|
browse_button.clicked.connect(browse_download_path)
|
||||||
|
|
||||||
###############
|
|
||||||
# IMAGE PATH #
|
|
||||||
###############
|
|
||||||
|
|
||||||
|
# Image Path
|
||||||
image_path_container = QWidget()
|
image_path_container = QWidget()
|
||||||
image_path_layout = QHBoxLayout()
|
image_path_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -167,10 +158,8 @@ def settings_dialog(self):
|
|||||||
image_path_layout.addWidget(browse_button)
|
image_path_layout.addWidget(browse_button)
|
||||||
browse_button.clicked.connect(browse_image_path)
|
browse_button.clicked.connect(browse_image_path)
|
||||||
|
|
||||||
##################
|
|
||||||
# SPEED LIMITING #
|
|
||||||
##################
|
|
||||||
|
|
||||||
|
# Speed Limiting
|
||||||
down_speed_limit_container = QWidget()
|
down_speed_limit_container = QWidget()
|
||||||
down_speed_limit_layout = QHBoxLayout()
|
down_speed_limit_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -197,10 +186,8 @@ def settings_dialog(self):
|
|||||||
up_speed_limit.setFixedWidth(180)
|
up_speed_limit.setFixedWidth(180)
|
||||||
up_speed_limit.setFixedHeight(30)
|
up_speed_limit.setFixedHeight(30)
|
||||||
|
|
||||||
######################
|
|
||||||
# CONNECTION CONFIGS #
|
# Connection Configs
|
||||||
######################
|
|
||||||
|
|
||||||
max_connections_container = QWidget()
|
max_connections_container = QWidget()
|
||||||
max_connections_layout = QHBoxLayout()
|
max_connections_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -214,10 +201,8 @@ def settings_dialog(self):
|
|||||||
max_connections.setFixedWidth(180)
|
max_connections.setFixedWidth(180)
|
||||||
max_connections.setFixedHeight(30)
|
max_connections.setFixedHeight(30)
|
||||||
|
|
||||||
####################
|
|
||||||
# DOWNLOAD CONFIGS #
|
|
||||||
####################
|
|
||||||
|
|
||||||
|
# Download Configs
|
||||||
max_downloads_container = QWidget()
|
max_downloads_container = QWidget()
|
||||||
max_downloads_layout = QHBoxLayout()
|
max_downloads_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -231,10 +216,8 @@ def settings_dialog(self):
|
|||||||
max_downloads.setFixedWidth(180)
|
max_downloads.setFixedWidth(180)
|
||||||
max_downloads.setFixedHeight(30)
|
max_downloads.setFixedHeight(30)
|
||||||
|
|
||||||
#####################
|
|
||||||
# INTERFACE BINDING #
|
|
||||||
#####################
|
|
||||||
|
|
||||||
|
# Interface Binding
|
||||||
interface_container = QWidget()
|
interface_container = QWidget()
|
||||||
interface_layout = QHBoxLayout()
|
interface_layout = QHBoxLayout()
|
||||||
|
|
||||||
@@ -257,10 +240,7 @@ def settings_dialog(self):
|
|||||||
interface_container.setLayout(interface_layout)
|
interface_container.setLayout(interface_layout)
|
||||||
|
|
||||||
|
|
||||||
###############
|
# Save / Cancel buttons
|
||||||
# SAVE/CANCEL #
|
|
||||||
###############
|
|
||||||
|
|
||||||
layout = QHBoxLayout()
|
layout = QHBoxLayout()
|
||||||
|
|
||||||
save_btn = QPushButton("Save")
|
save_btn = QPushButton("Save")
|
||||||
@@ -281,12 +261,12 @@ def settings_dialog(self):
|
|||||||
layout.addWidget(cancel_btn)
|
layout.addWidget(cancel_btn)
|
||||||
layout.addWidget(save_btn)
|
layout.addWidget(save_btn)
|
||||||
|
|
||||||
self.tabs = QTabWidget()
|
tabs = QtWidgets.QTabWidget()
|
||||||
self.tab1 = general_tab("General", autoresume_container, update_checkbox_container, transparent_window_container, self.tabs)
|
create_tab("General", [autoresume_container, update_checkbox_container, transparent_window_container], tabs=tabs, stretch=True)
|
||||||
self.tab2 = paths_tab("Paths", download_path_container, image_path_container, self.tabs)
|
create_tab("Paths", [download_path_container, image_path_container], tabs=tabs, stretch=True)
|
||||||
self.tab3 = network_tab("Network", interface_container, max_connections_container, max_downloads_container, up_speed_limit_container, down_speed_limit_container, api_url_container, self.tabs)
|
create_tab("Network", [interface_container, max_connections_container, max_downloads_container, up_speed_limit_container, down_speed_limit_container, api_url_container], tabs=tabs, stretch=True)
|
||||||
|
|
||||||
dialog_layout.addWidget(self.tabs)
|
dialog_layout.addWidget(tabs)
|
||||||
dialog_layout.addLayout(layout)
|
dialog_layout.addLayout(layout)
|
||||||
|
|
||||||
dialog.exec()
|
dialog.exec()
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
from core.interface.dialogs.theme import _theme_colors
|
from interface.dialogs.theme import _theme_colors
|
||||||
from PySide6.QtWidgets import QStyledItemDelegate
|
from PySide6.QtWidgets import QStyledItemDelegate
|
||||||
|
|
||||||
class TrackerHoverDelegate(QStyledItemDelegate):
|
class TrackerHoverDelegate(QStyledItemDelegate):
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from core.interface.dialogs.theme import _table_stylesheet
|
from interface.dialogs.theme import _table_stylesheet
|
||||||
from PySide6.QtWidgets import QTableWidget
|
from PySide6.QtWidgets import QTableWidget
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from core.utils.network.update_checker import get_updates
|
from utils.network.update_checker import get_updates
|
||||||
from core.utils.network.updater import download_update
|
|
||||||
from PySide6.QtWidgets import QDialog, QMessageBox
|
from PySide6.QtWidgets import QDialog, QMessageBox
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.network.updater import download_update
|
||||||
from core.utils.data.state import state
|
from utils.logging.logs import consoleLog
|
||||||
|
from utils.data.state import state
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import platform
|
import platform
|
||||||
import json
|
import json
|
||||||
@@ -24,7 +24,7 @@ def _get_build_info_path() -> (Path | None):
|
|||||||
def get_version() -> None:
|
def get_version() -> None:
|
||||||
# Get build info filepath
|
# Get build info filepath
|
||||||
build_info_path = _get_build_info_path()
|
build_info_path = _get_build_info_path()
|
||||||
if os.path.exists(build_info_path):
|
if build_info_path and os.path.exists(build_info_path):
|
||||||
with open(build_info_path, "r") as f:
|
with open(build_info_path, "r") as f:
|
||||||
build_info = json.load(f)
|
build_info = json.load(f)
|
||||||
state.version = build_info.get("version")
|
state.version = build_info.get("version")
|
||||||
@@ -46,3 +46,4 @@ class UpdateDialog(QDialog):
|
|||||||
response = msg.exec_()
|
response = msg.exec_()
|
||||||
if response == QMessageBox.StandardButton.Ok:
|
if response == QMessageBox.StandardButton.Ok:
|
||||||
download_update(assets)
|
download_update(assets)
|
||||||
|
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
from core.interface.dialogs.trackerhoverdelegate import TrackerHoverDelegate
|
from interface.dialogs.trackerhoverdelegate import TrackerHoverDelegate
|
||||||
from core.interface.dialogs.elideditemdelegate import ElidedItemDelegate
|
from interface.dialogs.elideditemdelegate import ElidedItemDelegate
|
||||||
from core.interface.dialogs.trackertable import _create_tracker_table
|
from interface.dialogs.trackertable import _create_tracker_table
|
||||||
from core.interface.dialogs.downloadlist import _create_download_list
|
from interface.dialogs.downloadlist import _create_download_list
|
||||||
from core.interface.assets.base64_icons import settings_white_base64
|
from interface.assets.base64_icons import settings_white_base64
|
||||||
from core.interface.assets.base64_icons import settings_black_base64
|
from interface.assets.base64_icons import settings_black_base64
|
||||||
from core.interface.dialogs.downloadlist import download_list_update
|
from interface.dialogs.downloadlist import download_list_update
|
||||||
from core.interface.dialogs.update import get_version, UpdateDialog
|
from interface.dialogs.update import get_version, UpdateDialog
|
||||||
from core.utils.logging.logs import consoleLog, flush_log_buffer
|
from utils.logging.logs import consoleLog, flush_log_buffer
|
||||||
from core.interface.dialogs.downloadmodel import DownloadModel
|
from interface.dialogs.downloadmodel import DownloadModel
|
||||||
from core.interface.utils.searchhelper import return_pressed
|
from interface.dialogs.settings import settings_dialog
|
||||||
from core.interface.dialogs.settings import settings_dialog
|
from interface.assets.base64_icons import logo_base64
|
||||||
from core.interface.assets.base64_icons import logo_base64
|
from interface.dialogs.eventfilter import eventFilter
|
||||||
from core.interface.dialogs.eventfilter import eventFilter
|
from utils.network.download import download_selected
|
||||||
from core.utils.network.download import download_selected
|
from interface.utils.searchhelper import run_search
|
||||||
from core.interface.utils.tabhelper import create_tab
|
from interface.utils.tabhelper import create_tab
|
||||||
from core.utils.general.shutdown import closehelper
|
from utils.general.shutdown import closehelper
|
||||||
from core.utils.general.wrappers import run_thread
|
from utils.general.wrappers import run_thread
|
||||||
from core.interface.dialogs.image import Image
|
from interface.dialogs.image import Image
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
|
|
||||||
import core.interface.dialogs.contextmenu
|
import interface.dialogs.contextmenu
|
||||||
|
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
from PySide6.QtCore import (
|
from PySide6.QtCore import (
|
||||||
@@ -86,7 +86,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
consoleLog(f"Could not set app ID: {e}")
|
consoleLog(f"Could not set app ID: {e}")
|
||||||
|
|
||||||
# Get current version
|
# Get current version
|
||||||
# core.interface.dialogs.update
|
# interface.dialogs.update
|
||||||
get_version()
|
get_version()
|
||||||
UpdateDialog()
|
UpdateDialog()
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
containerLayout.addWidget(self.searchbar)
|
containerLayout.addWidget(self.searchbar)
|
||||||
containerLayout.addWidget(state.trackertable)
|
containerLayout.addWidget(state.trackertable)
|
||||||
|
|
||||||
# core.interface.dialogs.hoverrowdelegate
|
# interface.dialogs.hoverrowdelegate
|
||||||
self.download_model = DownloadModel()
|
self.download_model = DownloadModel()
|
||||||
self.downloadList = _create_download_list(self)
|
self.downloadList = _create_download_list(self)
|
||||||
self.downloadList.viewport().installEventFilter(self)
|
self.downloadList.viewport().installEventFilter(self)
|
||||||
@@ -164,8 +164,8 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
self.horizontal_layout.addWidget(state.trackertable)
|
self.horizontal_layout.addWidget(state.trackertable)
|
||||||
|
|
||||||
# Tabs
|
# Tabs
|
||||||
self.tab1 = create_tab("Search", self.searchbar, state.trackertable, self.tabs, self.dlbutton, self.horizontal_layout)
|
create_tab("Search", [self.searchbar, self.horizontal_layout, self.dlbutton], tabs=self.tabs, stretch=False)
|
||||||
self.tab2 = create_tab("Downloads", self.emptyDownload, self.downloadList, self.tabs, None, None)
|
create_tab("Downloads", [self.emptyDownload, self.downloadList], tabs=self.tabs, stretch=False)
|
||||||
|
|
||||||
# Corner Widget (Settings Button, Tracker list, Tab button container)
|
# Corner Widget (Settings Button, Tracker list, Tab button container)
|
||||||
self.corner_widget = QWidget()
|
self.corner_widget = QWidget()
|
||||||
@@ -232,7 +232,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
self.statusbar.addPermanentWidget(self.version, Qt.AlignmentFlag.AlignLeft)
|
self.statusbar.addPermanentWidget(self.version, Qt.AlignmentFlag.AlignLeft)
|
||||||
|
|
||||||
# (\u2193) Arrow down, (\u2191) Arrow up
|
# (\u2193) Arrow down, (\u2191) Arrow up
|
||||||
self.speed_label = QLabel("\u2193 0.0 kB/s \u2191 0.0 kB/s")
|
self.speed_label = QLabel("↓ 0.0 kB/s ↑ 0.0 kB/s")
|
||||||
self.speed_label.setStyleSheet("padding-right: 6px;")
|
self.speed_label.setStyleSheet("padding-right: 6px;")
|
||||||
self.statusbar.addPermanentWidget(self.speed_label)
|
self.statusbar.addPermanentWidget(self.speed_label)
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
self.active_timer.timeout.connect(self.show_empty_downloads)
|
self.active_timer.timeout.connect(self.show_empty_downloads)
|
||||||
self.active_timer.start(500)
|
self.active_timer.start(500)
|
||||||
|
|
||||||
self._context_menu = core.interface.dialogs.contextmenu.ContextMenu(self)
|
self._context_menu = interface.dialogs.contextmenu.ContextMenu(self)
|
||||||
self.image_overlay = Image(self)
|
self.image_overlay = Image(self)
|
||||||
|
|
||||||
def _apply_default_headers(self, table):
|
def _apply_default_headers(self, table):
|
||||||
@@ -292,10 +292,9 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
table.setItemDelegateForColumn(i, self._tracker_hover_delegate)
|
table.setItemDelegateForColumn(i, self._tracker_hover_delegate)
|
||||||
|
|
||||||
def _start_search(self):
|
def _start_search(self):
|
||||||
self.searchbar.setEnabled(False)
|
|
||||||
def _search_thread():
|
def _search_thread():
|
||||||
try:
|
try:
|
||||||
return_pressed(self)
|
run_search(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
consoleLog(f"Search error: {e}", True)
|
consoleLog(f"Search error: {e}", True)
|
||||||
self.search_results_signal.emit([])
|
self.search_results_signal.emit([])
|
||||||
@@ -384,7 +383,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
def closeEvent(self, event: QCloseEvent):
|
def closeEvent(self, event: QCloseEvent):
|
||||||
closehelper()
|
closehelper()
|
||||||
event.accept()
|
event.accept()
|
||||||
from core.utils.general.shutdown import force_exit
|
from utils.general.shutdown import force_exit
|
||||||
force_exit()
|
force_exit()
|
||||||
|
|
||||||
def _invalidate_hover_row(self, row):
|
def _invalidate_hover_row(self, row):
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
from utils.logging.logs import consoleLog
|
||||||
|
from utils.data.state import state
|
||||||
|
from data.sources import SCRAPERS
|
||||||
|
|
||||||
|
for scraper in SCRAPERS:
|
||||||
|
state.trackers[scraper.name] = scraper
|
||||||
|
|
||||||
|
def run_search(self) -> None:
|
||||||
|
state.trackertable.setRowCount(0)
|
||||||
|
self.show_empty_results(False)
|
||||||
|
|
||||||
|
search_text = self.searchbar.text()
|
||||||
|
# Check for empty search
|
||||||
|
if search_text == "":
|
||||||
|
consoleLog("Error: Can't search for nothing")
|
||||||
|
return
|
||||||
|
|
||||||
|
state.posts = []
|
||||||
|
self.searchbar.setEnabled(False)
|
||||||
|
consoleLog(f"User searched for: {search_text}")
|
||||||
|
|
||||||
|
# Get current tracker and call its search function
|
||||||
|
scraper = state.trackers[state.currenttracker]
|
||||||
|
state.posts = scraper.search(search_text)
|
||||||
|
|
||||||
|
# Update GUI headers to match the current scraper
|
||||||
|
self.search_results_signal.emit(scraper.headers)
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
|
|
||||||
|
|
||||||
from PySide6 import QtWidgets
|
|
||||||
from PySide6.QtCore import Qt, QByteArray
|
|
||||||
from PySide6.QtGui import QIcon, QPixmap, QPainter
|
from PySide6.QtGui import QIcon, QPixmap, QPainter
|
||||||
|
from PySide6.QtCore import Qt, QByteArray
|
||||||
from PySide6.QtSvg import QSvgRenderer
|
from PySide6.QtSvg import QSvgRenderer
|
||||||
|
from PySide6 import QtWidgets
|
||||||
import darkdetect
|
import darkdetect
|
||||||
|
|
||||||
|
# Check if darkmode is enabled
|
||||||
def _is_dark_mode():
|
def _is_dark_mode():
|
||||||
return darkdetect.isDark()
|
return darkdetect.isDark()
|
||||||
|
|
||||||
|
|
||||||
def svg_icon(svg_str, size=20):
|
def svg_icon(svg_str, size=20):
|
||||||
app = QtWidgets.QApplication.instance()
|
app = QtWidgets.QApplication.instance()
|
||||||
if app:
|
if app:
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLayout
|
||||||
|
|
||||||
|
# Tab creation helper function
|
||||||
|
def create_tab(title, items, tabs, stretch):
|
||||||
|
tab = QWidget()
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
if item is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(item, QLayout):
|
||||||
|
layout.addLayout(item)
|
||||||
|
else:
|
||||||
|
layout.addWidget(item)
|
||||||
|
|
||||||
|
if stretch:
|
||||||
|
layout.addStretch()
|
||||||
|
|
||||||
|
tab.setLayout(layout)
|
||||||
|
tabs.addTab(tab, title)
|
||||||
|
return tab
|
||||||
+13
-13
@@ -1,16 +1,16 @@
|
|||||||
from core.network.libtorrent_misc import send_notification, update_log, check_deleted_files
|
from network.libtorrent_misc import send_notification, update_log, check_deleted_files
|
||||||
from core.utils.logging.loghandler import split_data, check_completed, check_downloads
|
from utils.logging.loghandler import split_data, check_completed, check_downloads
|
||||||
from core.network.interface import list_interfaces, init_interfaces
|
from network.interface import list_interfaces, init_interfaces
|
||||||
from core.utils.logging.logs import get_download_logs
|
from utils.logging.logs import get_download_logs
|
||||||
from core.utils.logging.logs import set_main_window
|
from utils.logging.logs import set_main_window
|
||||||
from core.network.libtorrent_int import check_space
|
from network.libtorrent_int import check_space
|
||||||
from core.utils.general.shutdown import closehelper
|
from utils.general.shutdown import closehelper
|
||||||
from core.utils.general.wrappers import run_thread
|
from utils.general.wrappers import run_thread
|
||||||
from core.utils.general.shutdown import force_exit
|
from utils.general.shutdown import force_exit
|
||||||
from core.utils.config.config import read_config
|
from utils.config.config import read_config
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.interface.gui import MainWindow
|
from interface.gui import MainWindow
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
import qdarktheme
|
import qdarktheme
|
||||||
|
|||||||
+5
-4
@@ -1,9 +1,10 @@
|
|||||||
|
from utils.logging.logs import consoleLog, add_download_log
|
||||||
|
from utils.data.state import state
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from core.utils.data.state import state
|
|
||||||
from core.utils.logging.logs import consoleLog, add_download_log
|
|
||||||
|
|
||||||
from .handle import DirectDownloadHandle
|
|
||||||
from .utils import (
|
from network.direct_download.handle import DirectDownloadHandle
|
||||||
|
from network.direct_download.utils import (
|
||||||
sanitize_filename,
|
sanitize_filename,
|
||||||
extract_filename_from_url,
|
extract_filename_from_url,
|
||||||
detect_filename_from_headers,
|
detect_filename_from_headers,
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
from core.utils.logging.logs import consoleLog, update_download_completed
|
from network.direct_download.status import DirectDownloadStatus, ChunkSpec
|
||||||
|
from utils.logging.logs import consoleLog, update_download_completed
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from .status import DirectDownloadStatus, ChunkSpec
|
from network.direct_download.utils import format_size
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from .utils import format_size
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
import threading
|
import threading
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
|
||||||
from urllib.parse import urlparse, unquote
|
from urllib.parse import urlparse, unquote
|
||||||
|
from utils.logging.logs import consoleLog
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
def get_net_interfaces():
|
def get_net_interfaces():
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from core.network.interface import get_interface_ip
|
from network.interface import get_interface_ip
|
||||||
from core.utils.general.wrappers import run_thread
|
from utils.general.wrappers import run_thread
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
import threading
|
import threading
|
||||||
import platform
|
import platform
|
||||||
@@ -23,7 +23,7 @@ def get_free_space_mb(dirname):
|
|||||||
|
|
||||||
def check_space():
|
def check_space():
|
||||||
while not state.shutdown_event.is_set():
|
while not state.shutdown_event.is_set():
|
||||||
for magnet_uri, magnetdl in list(state.active_downloads.items()):
|
for _, magnetdl in list(state.active_downloads.items()):
|
||||||
try:
|
try:
|
||||||
status = magnetdl.status()
|
status = magnetdl.status()
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
@@ -79,7 +79,6 @@ def add_download(magnet_uri):
|
|||||||
state.active_downloads = {}
|
state.active_downloads = {}
|
||||||
|
|
||||||
init_session()
|
init_session()
|
||||||
|
|
||||||
free_space = get_free_space_mb(state.download_path)
|
free_space = get_free_space_mb(state.download_path)
|
||||||
|
|
||||||
if magnet_uri in state.active_downloads:
|
if magnet_uri in state.active_downloads:
|
||||||
@@ -110,7 +109,6 @@ def add_download(magnet_uri):
|
|||||||
params.save_path = state.download_path
|
params.save_path = state.download_path
|
||||||
|
|
||||||
handle = state.dl_session.add_torrent(params)
|
handle = state.dl_session.add_torrent(params)
|
||||||
|
|
||||||
while not handle.has_metadata():
|
while not handle.has_metadata():
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from core.utils.logging.logs import update_download_completed_by_hash
|
from utils.logging.logs import update_download_completed_by_hash
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from plyer import notification
|
from plyer import notification
|
||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
import time
|
import time
|
||||||
@@ -17,9 +17,6 @@ def cleanup_session():
|
|||||||
state.dl_session = None
|
state.dl_session = None
|
||||||
state.active_downloads.clear()
|
state.active_downloads.clear()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def send_notification(shutdown_event):
|
def send_notification(shutdown_event):
|
||||||
notified = set()
|
notified = set()
|
||||||
while not shutdown_event.is_set():
|
while not shutdown_event.is_set():
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from core.network.libtorrent_int import add_download
|
from network.libtorrent_int import add_download
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
|
|
||||||
|
|
||||||
def add_magnet(uri):
|
def add_magnet(uri):
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
import configparser
|
import configparser
|
||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
from core.network.libtorrent_int import update_settings
|
from network.libtorrent_int import update_settings
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.config.config import create_config
|
||||||
from core.utils.data.state import state
|
from utils.logging.logs import consoleLog
|
||||||
from .config import create_config
|
from utils.data.state import state
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save_settings(close=lambda: None, apiurl=None, download_path=None, down_speed_limit=None, up_speed_limit=None, image_path=None, autoresume=None, max_connections=None, max_downloads=None, bound_interface=None):
|
def save_settings(close=lambda: None, apiurl=None, download_path=None, down_speed_limit=None, up_speed_limit=None, image_path=None, autoresume=None, max_connections=None, max_downloads=None, bound_interface=None):
|
||||||
@@ -9,43 +9,44 @@ class AppState(QObject):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.posts: list[Dict[str,str]] | None = None # titles, urls, author, seederm leecher
|
|
||||||
self.version: str = "dev"
|
|
||||||
self._image_path: str = ""
|
|
||||||
self.ignore_updates: bool = False
|
|
||||||
self.debug: bool = False
|
|
||||||
self.autoresume: bool = True
|
|
||||||
|
|
||||||
self.currenttracker: str = "rutracker"
|
# General
|
||||||
self.trackertable: QTableWidget
|
self.version: str = "Unknown"
|
||||||
self.trackers: Dict[str,Dict[str,Any]] = {} # each tracker should add itself here
|
self.debug: bool = False
|
||||||
'''
|
self.main_window: Any = None
|
||||||
an example:
|
self.loop_running: bool = False
|
||||||
"rutracker" : {
|
self.shutdown_event = threading.Event()
|
||||||
"name" : "rutracker", # name of the tracker
|
self.log_buffer: List[str] = []
|
||||||
"headers" : ["author", "title"], # keys shown in the table
|
|
||||||
"scrapeFunc" : function,
|
# Paths
|
||||||
}
|
self.settings_path: str = ""
|
||||||
'''
|
self._image_path: str = ""
|
||||||
self.api_url: str = "https://api.michijackson.xyz"
|
|
||||||
self.seeded_magnets: set = set()
|
|
||||||
self.download_path: str = str(Path.home() / "Downloads")
|
self.download_path: str = str(Path.home() / "Downloads")
|
||||||
|
|
||||||
|
# GUI
|
||||||
|
self.window_transparency: bool = False
|
||||||
|
self.trackertable: QTableWidget
|
||||||
|
self.interfaces: List = []
|
||||||
|
self.active_interfaces: List = []
|
||||||
|
self.bound_interface: Any = None
|
||||||
|
|
||||||
|
# Trackers / Scraping
|
||||||
|
self.posts: list[Dict[str,str]] | None = None # titles, urls, author, seeders, leechers
|
||||||
|
self.currenttracker: str = "rutracker"
|
||||||
|
self.api_url: str = "https://api.michijackson.xyz"
|
||||||
|
self.trackers: Dict[str,Dict[str,Any]] = {}
|
||||||
|
|
||||||
|
# LibTorrent / Download related stuff
|
||||||
|
self.dl_session: Any = None
|
||||||
|
self.active_downloads: Dict = {}
|
||||||
|
self.seeded_magnets: set = set()
|
||||||
|
self.ignore_updates: bool = False
|
||||||
|
self.autoresume: bool = True
|
||||||
self.up_speed_limit: int = 0
|
self.up_speed_limit: int = 0
|
||||||
self.down_speed_limit: int = 0
|
self.down_speed_limit: int = 0
|
||||||
self.max_connections: int = 200
|
self.max_connections: int = 200
|
||||||
self.max_downloads: int = 10
|
self.max_downloads: int = 10
|
||||||
self.settings_path: str = ""
|
|
||||||
self.dl_session: Any = None
|
|
||||||
self.active_downloads: Dict = {}
|
|
||||||
self.window_transparency: bool = False
|
|
||||||
self.interfaces: List = []
|
|
||||||
self.active_interfaces: List = []
|
|
||||||
self.bound_interface: Any = None
|
|
||||||
self.log_buffer: List[str] = []
|
|
||||||
self.downloads_lock = threading.RLock()
|
self.downloads_lock = threading.RLock()
|
||||||
self.main_window: Any = None
|
|
||||||
self.loop_running: bool = False
|
|
||||||
self.shutdown_event = threading.Event()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def image_path(self) -> str:
|
def image_path(self) -> str:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from core.network.libtorrent_misc import cleanup_session
|
from network.libtorrent_misc import cleanup_session
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def closehelper():
|
def closehelper():
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
|
|
||||||
def run_thread(thread):
|
def run_thread(thread):
|
||||||
target_name = thread._target.__name__
|
target_name = thread._target.__name__
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from core.utils.network.download import run_download_direct, seed_magnet
|
from utils.network.download import run_download_direct, seed_magnet
|
||||||
from core.utils.logging.logs import consoleLog, remove_download_log
|
from utils.logging.logs import consoleLog, remove_download_log
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def split_data(data):
|
def split_data(data):
|
||||||
@@ -18,7 +18,7 @@ def check_completed(downloads, resume):
|
|||||||
run_download_direct(download.magnet_uri, download.title)
|
run_download_direct(download.magnet_uri, download.title)
|
||||||
consoleLog(f"Resuming Magnet: {download.title}")
|
consoleLog(f"Resuming Magnet: {download.title}")
|
||||||
elif download.url:
|
elif download.url:
|
||||||
from core.network.direct_download import add_direct_download
|
from network.direct_download import add_direct_download
|
||||||
add_direct_download(download.url, download.title)
|
add_direct_download(download.url, download.title)
|
||||||
consoleLog(f"Resuming Direct Download: {download.title}")
|
consoleLog(f"Resuming Direct Download: {download.title}")
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from core.utils.data.models import Download, DownloadList
|
from utils.data.models import Download, DownloadList
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
@@ -243,7 +243,7 @@ def set_main_window(window):
|
|||||||
def flush_log_buffer(): # credits to claude
|
def flush_log_buffer(): # credits to claude
|
||||||
if state.log_buffer:
|
if state.log_buffer:
|
||||||
try:
|
try:
|
||||||
from core.interface.gui import MainWindow
|
from interface.gui import MainWindow
|
||||||
for log_entry in state.log_buffer:
|
for log_entry in state.log_buffer:
|
||||||
MainWindow.add_log(log_entry)
|
MainWindow.add_log(log_entry)
|
||||||
state.log_buffer = []
|
state.log_buffer = []
|
||||||
@@ -256,7 +256,7 @@ def consoleLog(text, printAnyways = False):
|
|||||||
formatted_text = f"[{current_time}] {text}"
|
formatted_text = f"[{current_time}] {text}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from core.interface.gui import MainWindow
|
from interface.gui import MainWindow
|
||||||
if not MainWindow.add_log(formatted_text):
|
if not MainWindow.add_log(formatted_text):
|
||||||
state.log_buffer.append(formatted_text)
|
state.log_buffer.append(formatted_text)
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
from core.network.direct_download import add_direct_download
|
from network.direct_download import add_direct_download
|
||||||
from core.network.libtorrent_wrapper import add_magnet
|
from network.libtorrent_wrapper import add_magnet
|
||||||
from core.utils.logging.logs import add_download_log
|
|
||||||
from core.utils.general.wrappers import run_thread
|
|
||||||
from core.network.libtorrent_int import add_seed
|
|
||||||
from PySide6.QtWidgets import QTableWidgetItem
|
from PySide6.QtWidgets import QTableWidgetItem
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import add_download_log
|
||||||
from core.utils.data.state import state
|
from utils.general.wrappers import run_thread
|
||||||
|
from network.libtorrent_int import add_seed
|
||||||
|
from utils.logging.logs import consoleLog
|
||||||
|
from utils.data.state import state
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import threading
|
import threading
|
||||||
@@ -31,9 +31,9 @@ def download_selected(items: list[QTableWidgetItem]):
|
|||||||
run_thread(threading.Thread(target=run_download, args=(post,)))
|
run_thread(threading.Thread(target=run_download, args=(post,)))
|
||||||
|
|
||||||
def run_download(post, headers: Optional[dict] = None):
|
def run_download(post, headers: Optional[dict] = None):
|
||||||
linkfunc = state.trackers[state.currenttracker]["linkFunc"]
|
link_method = state.trackers[state.currenttracker].get_download_link
|
||||||
ismagnet = state.trackers[state.currenttracker]["isMagnet"]
|
ismagnet = state.trackers[state.currenttracker].is_magnet
|
||||||
result = linkfunc(post)
|
result = link_method(post)
|
||||||
|
|
||||||
if ismagnet:
|
if ismagnet:
|
||||||
link = result
|
link = result
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_updates():
|
def get_updates():
|
||||||
url = f"https://api.github.com/repos/KeksPirates/SoftwareManager/releases/latest"
|
url = f"https://api.github.com/repos/KeksPirates/SoftwareManager/releases/latest"
|
||||||
try:
|
try:
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from core.network.direct_download.handle import DirectDownloadHandle
|
from network.direct_download.handle import DirectDownloadHandle
|
||||||
from core.utils.logging.logs import consoleLog
|
from utils.logging.logs import consoleLog
|
||||||
from core.utils.data.state import state
|
from utils.data.state import state
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
import libtorrent as lt
|
import libtorrent as lt
|
||||||
Reference in New Issue
Block a user