Compare commits

...

18 Commits

Author SHA1 Message Date
Vxrtrauter e50ef32c66 refactor: clean up imports and remove unused code in scrapers and download modules 2026-03-05 23:19:08 +01:00
KeksNino d6e418d045 fix: crash when there are no results in search tab 2026-03-04 21:24:56 +01:00
Vxrtrauter a7c71b37f5 refactor: remove duplicate stripping 2026-03-04 21:00:37 +01:00
Vxrtrauter 8fb1bb9e8d Merge branch 'main' of https://github.com/KeksPirates/SoftwareManager 2026-03-04 20:58:58 +01:00
Vxrtrauter 89fd8b4ebb fix: fix scraping for uztracker posts to support displaying authors properly 2026-03-04 20:58:56 +01:00
KeksNino 3915e114a3 fix: logging in uztracker scraper and search for non-ascii letters and remove unused imports 2026-03-04 20:28:55 +01:00
Vxrtrauter 34a50e1a1b refactor: rename scraping functions for consistency and improve data handling 2026-03-04 19:11:31 +01:00
KeksNino 90124fd9c8 fix: smaller author column in search tab 2026-03-04 14:07:43 +01:00
Vxrtrauter 4175f82967 feat: add windowCloseHelper function and integrate it into keyboard interrupt handling 2026-03-03 21:56:28 +01:00
Vxrtrauter 4bf2e9af81 feat: add download existence checks and improve log removal feedback 2026-03-01 23:14:10 +01:00
Vxrtrauter a6bb879db3 feat: enhance download logging with path handling and timeout mechanism 2026-02-28 04:01:00 +01:00
Vxrtrauter 7653748599 chore: remove unused file_list utility 2026-02-28 03:34:56 +01:00
Vxrtrauter 9bec3f9189 Merge branch 'main' of https://github.com/KeksPirates/SoftwareManager 2026-02-28 03:33:13 +01:00
Vxrtrauter 04d93b870a refactor: reorganize logging functionality and remove unused log files 2026-02-28 03:33:10 +01:00
KeksNino 664e660198 fix a bunch of lsp errors 2026-02-28 03:31:17 +01:00
Vxrtrauter 60019e0d2e refactor: update log imports and restructure logging functionality 2026-02-28 03:31:05 +01:00
Vxrtrauter 8238cfbe56 Merge branch 'main' of https://github.com/KeksPirates/SoftwareManager 2026-02-28 03:05:10 +01:00
Vxrtrauter 7ccff5c5a1 Refactor monkrus scraper to implement caching and improve post fetching logic 2026-02-28 03:05:09 +01:00
20 changed files with 162 additions and 183 deletions
+34 -6
View File
@@ -1,16 +1,28 @@
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import requests import requests
from core.utils.general.logs import consoleLog import time
def scrape_monkrus_telegram(query): cache = {
"data": [],
"last_fetched": 0
}
cache_expiry = 300
def _get_telegram_posts():
post = 100 post = 100
max_posts = 250 max_posts = 250
posts: list[dict] = [] posts = []
added = set() added = set()
current_time = time.time()
if cache["data"] and (current_time - cache["last_fetched"] < cache_expiry):
return cache["data"]
while post <= max_posts: while post <= max_posts:
url = f"https://t.me/s/real_monkrus/{post}" url = f"https://t.me/s/real_monkrus/{post}"
response = requests.get(url) response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.text, "html.parser") soup = BeautifulSoup(response.text, "html.parser")
bubbles = soup.find_all("div", class_="tgme_widget_message_bubble") bubbles = soup.find_all("div", class_="tgme_widget_message_bubble")
@@ -25,7 +37,7 @@ def scrape_monkrus_telegram(query):
title = post_txt.b.text title = post_txt.b.text
link = bubble.find("a", href=lambda x: x and x.startswith("https://uztracker.net")) link = bubble.find("a", href=lambda x: x and x.startswith("https://uztracker.net"))
if query.lower() in title.lower() and link: if link:
post_url = link["href"] post_url = link["href"]
if post_url not in added: if post_url not in added:
added.add(post_url) added.add(post_url)
@@ -39,4 +51,20 @@ def scrape_monkrus_telegram(query):
post += 22 post += 22
posts.reverse() posts.reverse()
cache["data"] = posts
cache["last_fetched"] = current_time
return(posts) 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
+4 -6
View File
@@ -1,10 +1,9 @@
import requests import requests
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
def scrape_rutracker(query):
def scrape_rutracker(search_text): search = requests.get(f"{state.api_url}/search?q={query}")
search = requests.get(f"{state.api_url}/search?q={search_text}")
consoleLog("Sent request to server") consoleLog("Sent request to server")
if search: if search:
try: try:
@@ -12,10 +11,9 @@ def scrape_rutracker(search_text):
except Exception: except Exception:
consoleLog("No results found / No response from server") consoleLog("No results found / No response from server")
return None return None
else: else:
return None return None
# This function utilizes the SoftwareManager server - source code can be found under the "server" branch. # This function utilizes the SoftwareManager server - source code can be found under the SoftwareManager-Server repository.
+26 -74
View File
@@ -1,83 +1,35 @@
import requests import requests
import threading
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from core.utils.data.state import state from urllib.parse import urljoin
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.utils.general.wrappers import run_thread
def scrape_uztracker(query):
base_url="https://uztracker.net/"
search_url = f"{base_url.rstrip('/')}/tracker.php?nm={query}"
consoleLog(search_url)
posts = []
global url_uztracker
url_uztracker = "https://uztracker.net/tracker.php?nm="
def init_uztracker():
global up
global soup
try: try:
response = requests.get(url_uztracker, timeout=10) response = requests.get(search_url)
if response.status_code == 200: response.raise_for_status()
up = True
else:
up = False
consoleLog(f"Uztracker seems down, status code: {response.status_code}")
except requests.exceptions.RequestException as e:
consoleLog(f"Request Exception on {url_uztracker}:")
consoleLog(str(e))
consoleLog("Is the Site down?")
up = False
run_thread(threading.Thread(target=init_uztracker))
def scrape_uztracker(search):
if up:
search_url = url_uztracker + search
consoleLog(search_url)
result = False
global results
global resulttitles
results = []
resulttitles = []
try:
resultCount = 0
response = requests.get(search_url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
links = soup.find_all('a', class_="genmed tLink", href=lambda x: x and x.startswith('./viewtopic'))
for link in links:
if link.b:
resultCount += 1
results.append(link['href'])
resulttitles.append(link.b.text)
result = True
if result:
return resulttitles, results
if not result:
# add popup in gui for no result
return None
except requests.RequestException as e:
if result:
consoleLog(f"Failed to fetch {search_url}: {e}")
return None
else:
consoleLog("Error: Uztracker down")
return None, None
def get_post_title(post_url):
if up:
response = requests.get(post_url)
soup = BeautifulSoup(response.text, 'html.parser') soup = BeautifulSoup(response.text, 'html.parser')
maintitle = soup.find(class_='tt-text') links = soup.find_all('tr', class_="tCenter hl-tr", id=lambda x: x and x.startswith('tor_'))
if maintitle: for link in links:
return maintitle.text
else:
consoleLog("Program not found")
else:
consoleLog("Error: Uztracker down")
return None
theme_link = link.find('a', class_="genmed tLink", href=lambda x: x and x.startswith('./viewtopic'))
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,
url=url,
author=author
))
return posts
except requests.RequestException as e:
consoleLog(f"Failed to fetch {search_url}: {e}")
return None
+1 -1
View File
@@ -1,6 +1,6 @@
from core.utils.config.settings import save_settings from core.utils.config.settings import save_settings
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.interface.utils.tabhelper import general_tab from core.interface.utils.tabhelper import general_tab
from core.interface.utils.tabhelper import paths_tab from core.interface.utils.tabhelper import paths_tab
from core.interface.utils.tabhelper import network_tab from core.interface.utils.tabhelper import network_tab
+20 -18
View File
@@ -1,5 +1,5 @@
from PySide6 import QtWidgets, QtCore, QtGui from PySide6 import QtWidgets
from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent, QSize from PySide6.QtCore import QPersistentModelIndex, Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent, QSize
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QLineEdit, QLineEdit,
QTableView, QTableView,
@@ -18,7 +18,7 @@ from PySide6.QtWidgets import (
QStyledItemDelegate, QStyledItemDelegate,
) )
from PySide6.QtGui import QIcon, QCloseEvent, QImage, QPixmap, QContextMenuEvent from PySide6.QtGui import QIcon, QCloseEvent, QImage, QPixmap, QContextMenuEvent, QGuiApplication
import darkdetect import darkdetect
import threading import threading
import platform import platform
@@ -30,7 +30,7 @@ import time
import sys import sys
import json import json
import base64 import base64
from core.utils.general.logs import consoleLog, remove_download_log, flush_log_buffer from core.utils.logging.logs import consoleLog, remove_download_log, flush_log_buffer
from core.utils.general.wrappers import run_thread from core.utils.general.wrappers import run_thread
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.network.download import download_selected from core.utils.network.download import download_selected
@@ -41,7 +41,6 @@ from core.interface.dialogs.settings import settings_dialog
from core.interface.assets.base64_icons import settings_black_base64 from core.interface.assets.base64_icons import settings_black_base64
from core.interface.assets.base64_icons import settings_white_base64 from core.interface.assets.base64_icons import settings_white_base64
from core.interface.assets.base64_icons import logo_base64 from core.interface.assets.base64_icons import logo_base64
from core.network.libtorrent_misc import cleanup_session
from core.utils.general.shutdown import closehelper from core.utils.general.shutdown import closehelper
@@ -68,6 +67,9 @@ def download_update(latest_version):
sys.exit(0) sys.exit(0)
def windowCloseHelper():
QGuiApplication.quit()
class MainWindow(QtWidgets.QMainWindow, QWidget): class MainWindow(QtWidgets.QMainWindow, QWidget):
log_signal = Signal(str) # Thread-safe signal for logging log_signal = Signal(str) # Thread-safe signal for logging
@@ -183,19 +185,19 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
super().__init__() super().__init__()
self.headers = ["Action", "Name", "Status", "Progress", "Speed", "Size", "Total Size"] self.headers = ["Action", "Name", "Status", "Progress", "Speed", "Size", "Total Size"]
def rowCount(self, parent=QModelIndex()): def rowCount(self, parent: QModelIndex | QPersistentModelIndex = QModelIndex()) -> int:
return len(state.active_downloads) return len(state.active_downloads)
def columnCount(self, parent=QModelIndex()): def columnCount(self, parent: QModelIndex | QPersistentModelIndex = QModelIndex()):
return len(self.headers) return len(self.headers)
def headerData(self, section, orientation, role=Qt.DisplayRole): def headerData(self, section, orientation, role: int = Qt.ItemDataRole.DisplayRole):
if role == Qt.DisplayRole and orientation == Qt.Horizontal: if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return self.headers[section] return self.headers[section]
return None return None
def data(self, index, role=Qt.DisplayRole): def data(self, index: QModelIndex | QPersistentModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
if role == Qt.DisplayRole: if role == Qt.ItemDataRole.DisplayRole:
col = index.column() col = index.column()
if index.row() >= len(state.active_downloads) or index.row() < 0: if index.row() >= len(state.active_downloads) or index.row() < 0:
@@ -211,9 +213,9 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
elif col == 1: elif col == 1:
return status.name if status.has_metadata else "Fetching metadata..." return status.name if status.has_metadata else "Fetching metadata..."
elif col == 2: elif col == 2:
if status.state == lt.torrent_status.downloading: if status.state == lt.torrent_status.downloading:
return "Downloading" return "Downloading"
elif status.state == lt.torrent_status.seeding: elif status.state == lt.torrent_status.seeding:
return "Seeding" return "Seeding"
elif status.paused: elif status.paused:
return "Paused" return "Paused"
@@ -257,7 +259,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
else: else:
return "" if status.paused else "Stalled" return "" if status.paused else "Stalled"
if role == Qt.UserRole and index.column() == 0: if role == Qt.ItemDataRole.UserRole and index.column() == 0:
magnet_link = list(state.active_downloads.keys())[index.row()] magnet_link = list(state.active_downloads.keys())[index.row()]
magnetdl = state.active_downloads[magnet_link] magnetdl = state.active_downloads[magnet_link]
return magnetdl.status().paused return magnetdl.status().paused
@@ -511,12 +513,12 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
event.accept() event.accept()
def set_tracker(self, _): def set_tracker(self, _):
old_tracker = state.tracker
state.tracker = self.tracker_list.currentText() state.tracker = self.tracker_list.currentText()
while self.horizontal_layout.count(): old_widget = state.tracker_list[old_tracker]
item = self.horizontal_layout.takeAt(0) self.horizontal_layout.removeWidget(old_widget)
if item.widget(): old_widget.setParent(None)
item.widget().setParent(None)
tracker_widget = state.tracker_list[state.tracker] tracker_widget = state.tracker_list[state.tracker]
self.horizontal_layout.addWidget(tracker_widget) self.horizontal_layout.addWidget(tracker_widget)
+13 -30
View File
@@ -1,11 +1,17 @@
from PySide6.QtWidgets import QTableWidgetItem from PySide6.QtWidgets import QTableWidgetItem
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.data.scrapers.uztracker import scrape_uztracker from core.data.scrapers.uztracker import scrape_uztracker
from core.data.scrapers.rutracker import scrape_rutracker from core.data.scrapers.rutracker import scrape_rutracker
from core.data.scrapers.monkrus import scrape_monkrus_telegram from core.data.scrapers.monkrus import scrape_m0nkrus
from core.utils.network.jsonhandler import split_data, format_data, format_data_m0nkrus from core.utils.network.jsonhandler import split_data, format_data, format_data_minimal
from core.utils.data.state import state from core.utils.data.state import state
scrapers = {
"uztracker": scrape_uztracker,
"rutracker": scrape_rutracker,
"m0nkrus": scrape_m0nkrus
}
def return_pressed(self): def return_pressed(self):
search_text = self.searchbar.text() search_text = self.searchbar.text()
if search_text == "": if search_text == "":
@@ -13,29 +19,7 @@ def return_pressed(self):
return return
consoleLog(f"User searched for: {search_text}") consoleLog(f"User searched for: {search_text}")
if state.tracker == "uztracker": if state.tracker == "rutracker":
response = scrape_uztracker(search_text)
if response:
state.post_titles, state.post_urls = response
state.tracker_list[state.tracker].clear()
if state.post_titles and len(state.post_titles) > 0:
state.tracker_list[state.tracker].setHorizontalHeaderLabels(["Post Title", "Author"])
state.tracker_list[state.tracker].setRowCount(len(state.post_titles))
for i, author in enumerate(state.post_author):
state.tracker_list[state.tracker].setItem(i, 1, QTableWidgetItem(author))
for i, title in enumerate(state.post_titles):
state.tracker_list[state.tracker].setItem(i, 0, QTableWidgetItem(title))
self.show_empty_results(False)
else:
consoleLog(f"No Results for {search_text}")
state.tracker_list[state.tracker].clear()
self.show_empty_results(True)
else:
consoleLog(f"No response from uztracker")
state.tracker_list[state.tracker].clear()
self.show_empty_results(True)
elif state.tracker == "rutracker":
response = scrape_rutracker(search_text) response = scrape_rutracker(search_text)
if response: if response:
_, state.posts, _, _, cached = split_data(response) _, state.posts, _, _, cached = split_data(response)
@@ -64,15 +48,14 @@ def return_pressed(self):
state.tracker_list[state.tracker].clear() state.tracker_list[state.tracker].clear()
self.show_empty_results(True) self.show_empty_results(True)
elif state.tracker == "m0nkrus": elif state.tracker is not None:
state.posts = scrape_monkrus_telegram(search_text) state.posts = scrapers[state.tracker](search_text)
if state.posts == []: if state.posts == []:
consoleLog(f"No Results for {search_text}") consoleLog(f"No Results for {search_text}")
state.tracker_list[state.tracker].clear() state.tracker_list[state.tracker].clear()
self.show_empty_results(True) self.show_empty_results(True)
else: else:
state.post_titles, _, state.post_author = format_data_m0nkrus(state.posts) state.post_author, state.post_titles, state.post_urls = format_data_minimal(state.posts)
self.show_empty_results(False) self.show_empty_results(False)
state.tracker_list[state.tracker].clear() state.tracker_list[state.tracker].clear()
state.tracker_list[state.tracker].setHorizontalHeaderLabels(["Post Title", "Author"]) state.tracker_list[state.tracker].setHorizontalHeaderLabels(["Post Title", "Author"])
+1 -1
View File
@@ -1,4 +1,4 @@
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.utils.data.state import state from core.utils.data.state import state
import psutil import psutil
+1 -1
View File
@@ -4,7 +4,7 @@ from core.network.interface import get_interface_ip
import threading import threading
import libtorrent as lt import libtorrent as lt
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
global loop_running global loop_running
+3 -3
View File
@@ -1,6 +1,6 @@
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import update_download_completed_by_hash from core.utils.logging.logs import update_download_completed_by_hash
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from plyer import notification from plyer import notification
import libtorrent as lt import libtorrent as lt
import time import time
@@ -57,4 +57,4 @@ def update_log(shutdown_event):
updated.add(magnet_uri) updated.add(magnet_uri)
except Exception: except Exception:
pass pass
time.sleep(5) time.sleep(5)
+1 -1
View File
@@ -1,4 +1,4 @@
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.network.libtorrent_int import add_download from core.network.libtorrent_int import add_download
def add_magnet(uri): def add_magnet(uri):
+1 -1
View File
@@ -1,6 +1,6 @@
from core.network.libtorrent_int import update_settings from core.network.libtorrent_int import update_settings
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from .config import create_config from .config import create_config
+1
View File
@@ -7,6 +7,7 @@ class Download:
title: str title: str
url: str url: str
magnet_uri: str magnet_uri: str
path: str
completed: bool completed: bool
@dataclass @dataclass
+5 -5
View File
@@ -8,9 +8,9 @@ class AppState(QObject):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.posts: List[Dict[str, Any]] = [] self.posts: list[Any] | None = None
self.post_titles: List[str] = [] self.post_titles: Optional[List] = None
self.post_urls: List[str] = [] self.post_urls: Optional[List] = None
self.post_author: List[str] = [] self.post_author: List[str] = []
self.post_seeders: List[str] = [] self.post_seeders: List[str] = []
self.post_leechers: List[str] = [] self.post_leechers: List[str] = []
@@ -29,11 +29,11 @@ class AppState(QObject):
self.max_downloads: int = 10 self.max_downloads: int = 10
self.settings_path: str = "" self.settings_path: str = ""
self.dl_session: Any = None self.dl_session: Any = None
self.active_downloads: List[str] = {} self.active_downloads: Dict = {}
self.window_transparency: bool = False self.window_transparency: bool = False
self.interfaces: List = [] self.interfaces: List = []
self.active_interfaces: List = [] self.active_interfaces: List = []
self.bound_interface: str = None self.bound_interface: Any = None
@property @property
def image_path(self) -> str: def image_path(self) -> str:
+1 -1
View File
@@ -1,7 +1,7 @@
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.utils.network.jsonhandler import format_data from core.utils.network.jsonhandler import format_data
@@ -1,6 +1,8 @@
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog, remove_download_log
from core.utils.network.download import run_download_direct from core.utils.network.download import run_download_direct
import os
def split_data(data): def split_data(data):
count = data.count count = data.count
@@ -16,6 +18,11 @@ def check_completed(downloads, resume):
run_download_direct(download.magnet_uri) run_download_direct(download.magnet_uri)
consoleLog(f"Resuming {download.title}") consoleLog(f"Resuming {download.title}")
def check_downloads(downloads):
for download in downloads:
if os.path.exists(download.path):
consoleLog(f"Existing Download: {download.title}")
else:
consoleLog(f"Inexistent Download: {download.title}")
remove_download_log(download.magnet_uri)
@@ -5,6 +5,7 @@ from datetime import datetime
import json import json
import os import os
import re import re
import time
_log_buffer = [] _log_buffer = []
@@ -21,7 +22,21 @@ def add_download_log(title, url, magnet_uri, completed) -> DownloadList:
downloads = [] downloads = []
else: else:
downloads = [] downloads = []
magnetdl = state.active_downloads.get(magnet_uri)
if magnetdl:
status = magnetdl.status()
timeout = 60
start = time.time()
while not status.has_metadata and (time.time() - start) < timeout:
time.sleep(0.5)
status = magnetdl.status()
torrent_name = status.name
save_path = status.save_path
consoleLog(f"Torrent name (has_metadata={status.has_metadata}): {torrent_name}")
path = os.path.join(save_path, torrent_name)
else:
path = os.path.join(state.download_path, title)
if any(d.magnet_uri == magnet_uri or d.url == url for d in downloads): if any(d.magnet_uri == magnet_uri or d.url == url for d in downloads):
if magnet_uri in state.active_downloads: if magnet_uri in state.active_downloads:
@@ -37,7 +52,8 @@ def add_download_log(title, url, magnet_uri, completed) -> DownloadList:
title=title, title=title,
url=url, url=url,
magnet_uri=magnet_uri, magnet_uri=magnet_uri,
completed=completed, path=path,
completed=completed
)) ))
consoleLog(f"Added {title} to Log File") consoleLog(f"Added {title} to Log File")
@@ -61,10 +77,12 @@ def remove_download_log(magnet_uri) -> DownloadList:
else: else:
downloads = [] downloads = []
magnet_link = (magnet_uri or "").strip() magnet_link = (magnet_uri or "").strip()
title = next((getattr(d, 'title', 'Unknown') for d in downloads if (getattr(d, 'magnet_uri', None) or '').strip() == magnet_link or (getattr(d, 'url', None) or '').strip() == magnet_link))
downloads = [d for d in downloads if (getattr(d, 'magnet_uri', None) or "").strip() != magnet_link and (getattr(d, 'url', None) or "").strip() != magnet_link] downloads = [d for d in downloads if (getattr(d, 'magnet_uri', None) or "").strip() != magnet_link and (getattr(d, 'url', None) or "").strip() != magnet_link]
consoleLog(f"Removed {magnet_link} from Log File") consoleLog(f"Removed {title} from Log File")
download_list = DownloadList(data=downloads, count=len(downloads)) download_list = DownloadList(data=downloads, count=len(downloads))
with open(downloads_file, "w") as file: with open(downloads_file, "w") as file:
+4 -9
View File
@@ -1,11 +1,9 @@
from core.utils.data.state import state from core.utils.logging.logs import consoleLog
from core.utils.general.logs import consoleLog
from core.utils.data.tracker import get_item_url from core.utils.data.tracker import get_item_url
from core.utils.data.tracker import get_magnet_link from core.utils.data.tracker import get_magnet_link
from core.network.libtorrent_wrapper import add_download from core.network.libtorrent_wrapper import add_download
from core.utils.general.wrappers import run_thread from core.utils.general.wrappers import run_thread
from core.utils.general.logs import add_download_log from core.utils.logging.logs import add_download_log
import threading import threading
@@ -21,11 +19,8 @@ def run_download(item, posts, post_titles):
consoleLog(f"Selected URL: {post_url}") consoleLog(f"Selected URL: {post_url}")
magnet_uri = get_magnet_link(post_url) magnet_uri = get_magnet_link(post_url)
add_download_log(item, post_url, magnet_uri, False)
add_download(magnet_uri) add_download(magnet_uri)
add_download_log(item, post_url, magnet_uri, False)
def run_download_direct(magnet_uri): def run_download_direct(magnet_uri):
add_download(magnet_uri) add_download(magnet_uri)
+3 -3
View File
@@ -20,16 +20,16 @@ def format_data(data):
return post_titles, post_links, post_author, post_seeders, post_leechers return post_titles, post_links, post_author, post_seeders, post_leechers
def format_data_m0nkrus(data): def format_data_minimal(data):
post_author = [post["author"] for post in data] post_author = [post["author"] for post in data]
post_titles = [post["title"] for post in data] post_titles = [post["title"] for post in data]
post_links = [post["url"] for post in data] post_links = [post["url"] for post in data]
return post_titles, post_links, post_author return post_author, post_titles, post_links
# https://open.spotify.com/track/70vjXI7oBou5buTtgiJeRW?si=25640cc4243c4bf3 # https://open.spotify.com/track/0F0fMcIdL2FmcC9eYqwazX
+1 -1
View File
@@ -1,6 +1,6 @@
import requests import requests
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
def check_for_updates(): def check_for_updates():
url = f"https://api.github.com/repos/KeksPirates/SoftwareManager/releases" url = f"https://api.github.com/repos/KeksPirates/SoftwareManager/releases"
+10 -15
View File
@@ -1,13 +1,12 @@
from core.interface.gui import MainWindow from core.interface.gui import MainWindow, windowCloseHelper
from core.utils.data.state import state from core.utils.data.state import state
from core.utils.general.logs import consoleLog from core.utils.logging.logs import consoleLog
from core.network.libtorrent_misc import send_notification, update_log from core.network.libtorrent_misc import send_notification, update_log
from core.utils.general.logs import get_download_logs from core.utils.logging.logs import get_download_logs
from core.utils.general.shutdown import closehelper, shutdown_event from core.utils.general.shutdown import closehelper, shutdown_event
from core.utils.general.wrappers import run_thread from core.utils.general.wrappers import run_thread
from core.utils.general.loghandler import split_data, check_completed from core.utils.logging.loghandler import split_data, check_completed, check_downloads
from core.network.interface import list_interfaces, init_interfaces from core.network.interface import list_interfaces, init_interfaces
from core.network.libtorrent_int import update_bound_interface
from core.utils.config.config import read_config from core.utils.config.config import read_config
from PySide6 import QtWidgets from PySide6 import QtWidgets
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
@@ -15,15 +14,9 @@ import qdarktheme
import threading import threading
import platform import platform
import signal import signal
import argparse
import sys import sys
import time import time
parser = argparse.ArgumentParser()
parser.add_argument("--debug", action="store_true")
args = parser.parse_args()
def run_gui(): def run_gui():
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
qdarktheme.setup_theme("auto") qdarktheme.setup_theme("auto")
@@ -33,21 +26,20 @@ def run_gui():
widget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) widget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
qdarktheme.setup_theme("auto", custom_colors={"background": "#00000000"}) qdarktheme.setup_theme("auto", custom_colors={"background": "#00000000"})
from core.utils.general.logs import set_main_window from core.utils.logging.logs import set_main_window
set_main_window(widget) set_main_window(widget)
widget.show() widget.show()
sys.exit(app.exec()) sys.exit(app.exec())
def keyboardinterrupthandler(signum, frame): def keyboardinterrupthandler(signum, frame):
closehelper() closehelper()
windowCloseHelper()
if __name__ == "__main__": def main():
start_time = time.perf_counter() start_time = time.perf_counter()
read_config() read_config()
logs = get_download_logs() logs = get_download_logs()
_, downloads = split_data(logs) _, downloads = split_data(logs)
if args.debug:
state.debug = args.debug # override of read_config
signal.signal(signal.SIGINT, keyboardinterrupthandler) signal.signal(signal.SIGINT, keyboardinterrupthandler)
consoleLog("Starting SoftwareManager...") consoleLog("Starting SoftwareManager...")
consoleLog("Fetching Network Interfaces...") consoleLog("Fetching Network Interfaces...")
@@ -61,7 +53,10 @@ if __name__ == "__main__":
consoleLog("Started Thread: update_log") consoleLog("Started Thread: update_log")
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume))) run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
consoleLog("Started Thread: check_completed") consoleLog("Started Thread: check_completed")
check_downloads(downloads)
elapsed = time.perf_counter() - start_time elapsed = time.perf_counter() - start_time
consoleLog(f"Initialization completed in {elapsed:.2f}s. Launching GUI") consoleLog(f"Initialization completed in {elapsed:.2f}s. Launching GUI")
run_gui() run_gui()
if __name__ == "__main__":
main()