From 8f9f77d63fb4a56024b5f8852bee0adfdb8102da Mon Sep 17 00:00:00 2001 From: Vxrtrauter <101264710+Vxrtrauter@users.noreply.github.com> Date: Sat, 31 Jan 2026 03:05:31 +0100 Subject: [PATCH] update settings dialog & config, remove aria2 --- core/interface/dialogs/settings.py | 46 +++++++----- core/interface/gui.py | 9 --- core/network/aria2_integration.py | 109 ----------------------------- core/network/aria2_wrapper.py | 18 ----- core/network/libtorrent_int.py | 18 +++-- core/network/libtorrent_misc.py | 45 ++++++++++++ core/utils/config/config.py | 5 +- core/utils/config/settings.py | 20 ++---- core/utils/data/state.py | 5 +- main.py | 12 +--- 10 files changed, 102 insertions(+), 185 deletions(-) delete mode 100644 core/network/aria2_integration.py delete mode 100644 core/network/aria2_wrapper.py create mode 100644 core/network/libtorrent_misc.py diff --git a/core/interface/dialogs/settings.py b/core/interface/dialogs/settings.py index 24bb5a9..81cf02b 100644 --- a/core/interface/dialogs/settings.py +++ b/core/interface/dialogs/settings.py @@ -60,9 +60,9 @@ def settings_dialog(self): autoresume_layout.addWidget(autoresume_checkbox) dialog.layout().addWidget(autoresume_container) - ################## - # THREAD SETTING # - ################## + ##################### + # DOWNLOAD SETTINGS # + ##################### thread_box = QSpinBox() thread_box.setMinimum(1) thread_box.setMaximum(16) @@ -128,19 +128,33 @@ def settings_dialog(self): # SPEED LIMITING # ################## - speed_limit_container = QWidget() - speed_limit_layout = QHBoxLayout() + down_speed_limit_container = QWidget() + down_speed_limit_layout = QHBoxLayout() - speed_limit_layout.addWidget(QLabel("Max Download Speed (KiB, 0 for unlimited): ")) - speed_limit = QSpinBox() - speed_limit.setMinimum(0) - speed_limit.setMaximum(10000000) - speed_limit.setValue(state.speed_limit) - speed_limit_container.setLayout(speed_limit_layout) - speed_limit_layout.addWidget(speed_limit) - speed_limit.setFixedWidth(180) - speed_limit.setFixedHeight(30) - dialog.layout().addWidget(speed_limit_container) + down_speed_limit_layout.addWidget(QLabel("Max Download Speed (KiB, 0 for unlimited): ")) + down_speed_limit = QSpinBox() + down_speed_limit.setMinimum(0) + down_speed_limit.setMaximum(10000000) + down_speed_limit.setValue(state.down_speed_limit) + down_speed_limit_container.setLayout(down_speed_limit_layout) + down_speed_limit_layout.addWidget(down_speed_limit) + down_speed_limit.setFixedWidth(180) + down_speed_limit.setFixedHeight(30) + dialog.layout().addWidget(down_speed_limit_container) + + up_speed_limit_container = QWidget() + up_speed_limit_layout = QHBoxLayout() + + up_speed_limit_layout.addWidget(QLabel("Max Upload Speed (KiB, 0 for unlimited): ")) + up_speed_limit = QSpinBox() + up_speed_limit.setMinimum(0) + up_speed_limit.setMaximum(10000000) + up_speed_limit.setValue(state.up_speed_limit) + up_speed_limit_container.setLayout(up_speed_limit_layout) + up_speed_limit_layout.addWidget(up_speed_limit) + up_speed_limit.setFixedWidth(180) + up_speed_limit.setFixedHeight(30) + dialog.layout().addWidget(up_speed_limit_container) ############### # IMAGE PATH # @@ -174,7 +188,7 @@ def settings_dialog(self): save_btn = QPushButton("Save") cancel_btn = QPushButton("Cancel") - save_btn.clicked.connect(lambda: save_settings(thread_box.value(), close_settings, api_url.text(), download_path.text(), speed_limit.value(), image_path.text())) + save_btn.clicked.connect(lambda: save_settings(thread_box.value(), close_settings, api_url.text(), download_path.text(), down_speed_limit.value(), up_speed_limit.value(), image_path.text())) cancel_btn.clicked.connect(dialog.reject) layout.addWidget(cancel_btn) diff --git a/core/interface/gui.py b/core/interface/gui.py index 18f5093..2e838d1 100644 --- a/core/interface/gui.py +++ b/core/interface/gui.py @@ -42,7 +42,6 @@ from core.utils.general.shutdown import closehelper from core.interface.utils.tabhelper import create_tab from core.interface.utils.searchhelper import return_pressed from core.interface.dialogs.settings import settings_dialog -from core.network.aria2_integration import dlprogress def download_update(latest_version): @@ -400,10 +399,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): self.consoleLog.setFixedHeight(150) containerLayout.addWidget(self.consoleLog) - self.progress_timer = QTimer() - self.progress_timer.timeout.connect(lambda: run_thread(threading.Thread(target=self.update_progress))) - self.progress_timer.start(1000) - self.download_timer = QTimer() self.download_timer.timeout.connect(lambda: run_thread(threading.Thread(target=self.download_list_update))) self.download_timer.start(500) @@ -443,10 +438,6 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): def set_tracker(self, _): state.tracker = self.tracker_list.currentText() - def update_progress(self): - progress = dlprogress() - self.progressbar.setValue(progress) - def show_empty_results(self, show: bool): if show: self.qtablewidget.hide() diff --git a/core/network/aria2_integration.py b/core/network/aria2_integration.py deleted file mode 100644 index 77fa6eb..0000000 --- a/core/network/aria2_integration.py +++ /dev/null @@ -1,109 +0,0 @@ -import aria2p -import subprocess -from core.utils.data.state import state -from core.utils.general.logs import update_download_completed_by_hash -from core.utils.general.logs import consoleLog -from plyer import notification -import socket -import time -import sys - -def run_aria2p(): - - state.aria2 = aria2p.API( - aria2p.Client( - host="http://localhost", - port=6800, - secret="" - ) - ) - - return state.aria2 - - -def aria2server(): - download_path = state.download_path - speed_limit = state.speed_limit - - cmd = [ - "aria2c", - "--enable-rpc", - "--disable-ipv6", # added this since it caused problems with vpns - "--rpc-listen-all", - "--rpc-listen-port=6800", - f"--dir={download_path}", - f"--max-download-limit={speed_limit * 1024}", - "-x", str(state.aria2_threads), - "-s", str(state.aria2_threads), - ] - - aria2server = subprocess.Popen( - cmd, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0 - ) - - max_checks = 50 - for check in range(max_checks): - try: - sock = socket.socket() - sock.settimeout(0.1) - sock.connect(("localhost", 6800)) - sock.close() - break - except(ConnectionRefusedError, socket.timeout): - time.sleep(0.1) - else: - raise RuntimeError("Aria2 Server failed to start") - - consoleLog("Aria2 Server started") - return aria2server - -def dlprogress(): - try: - state.downloads = [download for download in state.aria2.get_downloads() if not download.is_metadata] - downloads = state.downloads - if downloads: - for download in downloads: - progress = download.progress_string(0) - progress_int = int(progress.strip('%')) - return progress_int - return 0 - except: - return 0 - -def send_notification(shutdown_event): - notified = set() - while not shutdown_event.is_set(): - try: - for d in state.aria2.get_downloads(): - if d.is_metadata: - continue - if d.progress == 100 and d.gid not in notified: - notification.notify( - title="Download finished", - message=f"{d.name} has finished downloading.", - timeout=4 - ) - notified.add(d.gid) - state.downloads = [d for d in state.aria2.get_downloads() if d.is_active and not d.is_metadata] - except Exception: - pass - time.sleep(5) - -def update_log(shutdown_event): - updated = set() - while not shutdown_event.is_set(): - try: - for d in state.aria2.get_downloads(): - if d.is_metadata: - continue - if d.progress == 100 and d.gid not in updated: - consoleLog(f"Marking {d.name} as completed") - update_download_completed_by_hash(d.info_hash, True) - updated.add(d.gid) - state.downloads = [d for d in state.aria2.get_downloads() if d.is_active and not d.is_metadata] - except Exception: - pass - time.sleep(5) \ No newline at end of file diff --git a/core/network/aria2_wrapper.py b/core/network/aria2_wrapper.py deleted file mode 100644 index 46361da..0000000 --- a/core/network/aria2_wrapper.py +++ /dev/null @@ -1,18 +0,0 @@ -from .aria2_integration import run_aria2p -from core.utils.data.state import state -from core.utils.general.logs import consoleLog - -def start_client(): - global aria2 - aria2 = run_aria2p() - consoleLog("Started Aria2p") - -def add_magnet(uri): - if uri is not None and uri.startswith("magnet:?"): - aria2.add_magnet(uri) - consoleLog("Magnet URI added to Aria2") - else: - consoleLog(f"Invalid Magnet Link: {uri}") - - - diff --git a/core/network/libtorrent_int.py b/core/network/libtorrent_int.py index 4f7d847..4b65779 100644 --- a/core/network/libtorrent_int.py +++ b/core/network/libtorrent_int.py @@ -16,15 +16,15 @@ def init_session(): state.dl_session = lt.session() settings = { - "upload_rate_limit": 0, - "download_rate_limit": 0, + "upload_rate_limit": state.up_speed_limit, + "download_rate_limit": state.down_speed_limit, "enable_dht": True, "enable_lsd": True, "enable_upnp": True, "enable_natpmp": True, "dht_bootstrap_nodes": "router.bittorrent.com:6881,dht.transmissionbt.com:6881", - "connections_limit": 200, - "active_downloads": 10 + "connections_limit": state.max_connections, + "active_downloads": state.max_downloads } @@ -87,6 +87,14 @@ def dl_status_loop(): loop_running = False +def update_settings(): + settings = { + "upload_rate_limit": state.up_speed_limit, + "download_rate_limit": state.down_speed_limit, + "connections_limit": state.max_connections, + "active_downloads": state.max_downloads + } - + state.dl_session.apply_settings(settings) + consoleLog("Updated Settings") diff --git a/core/network/libtorrent_misc.py b/core/network/libtorrent_misc.py new file mode 100644 index 0000000..ca9e978 --- /dev/null +++ b/core/network/libtorrent_misc.py @@ -0,0 +1,45 @@ +import aria2p +import subprocess +from core.utils.data.state import state +from core.utils.general.logs import update_download_completed_by_hash +from core.utils.general.logs import consoleLog +from plyer import notification +import socket +import time +import sys + + +def send_notification(shutdown_event): + notified = set() + while not shutdown_event.is_set(): + try: + for d in state.aria2.get_downloads(): + if d.is_metadata: + continue + if d.progress == 100 and d.gid not in notified: + notification.notify( + title="Download finished", + message=f"{d.name} has finished downloading.", + timeout=4 + ) + notified.add(d.gid) + state.downloads = [d for d in state.aria2.get_downloads() if d.is_active and not d.is_metadata] + except Exception: + pass + time.sleep(5) + +def update_log(shutdown_event): + updated = set() + while not shutdown_event.is_set(): + try: + for d in state.aria2.get_downloads(): + if d.is_metadata: + continue + if d.progress == 100 and d.gid not in updated: + consoleLog(f"Marking {d.name} as completed") + update_download_completed_by_hash(d.info_hash, True) + updated.add(d.gid) + state.downloads = [d for d in state.aria2.get_downloads() if d.is_active and not d.is_metadata] + except Exception: + pass + time.sleep(5) \ No newline at end of file diff --git a/core/utils/config/config.py b/core/utils/config/config.py index 0532d17..fcc19fe 100644 --- a/core/utils/config/config.py +++ b/core/utils/config/config.py @@ -6,7 +6,7 @@ from core.utils.data.state import state def create_config(): config = configparser.ConfigParser() - config["General"] = {"debug": True, "api_url": f"{state.api_url}", "aria2_threads": f"{state.aria2_threads}", "download_path": f"{state.download_path}", f"speed_limit": f"{state.speed_limit}", + config["General"] = {"debug": True, "api_url": f"{state.api_url}", "aria2_threads": f"{state.aria2_threads}", "download_path": f"{state.download_path}", f"download_speed_limit": f"{state.down_speed_limit}", f"upload_speed_limit": f"{state.up_speed_limit}", "ignore_updates": f"{state.ignore_updates}", "image_path": f"{state.image_path}", "autoresume": f"{state.autoresume}"} if platform.system() == "Windows": @@ -42,7 +42,8 @@ def read_config(): state.api_url = config.get("General", "api_url", fallback=state.api_url) state.aria2_threads = config.getint("General", "aria2_threads", fallback=state.aria2_threads) state.download_path = config.get("General", "download_path", fallback=state.download_path) - state.speed_limit = config.getint("General", "speed_limit", fallback=state.speed_limit) + state.down_speed_limit = config.getint("General", "download_speed_limit", fallback=state.down_speed_limit) + state.up_speed_limit = config.getint("General", "upload_speed_limit", fallback=state.up_speed_limit) state.ignore_updates = config.getboolean("General", "ignore_updates", fallback=state.ignore_updates) state.image_path = config.get("General", "image_path", fallback=state.image_path) state.autoresume = config.getboolean("General", "autoresume", fallback=state.autoresume) diff --git a/core/utils/config/settings.py b/core/utils/config/settings.py index 3f67f51..35eabfc 100644 --- a/core/utils/config/settings.py +++ b/core/utils/config/settings.py @@ -1,27 +1,18 @@ from core.utils.data.state import state -from core.utils.general.shutdown import kill_aria2server from .config import create_config -def restart_aria2c(): - import main # had to do this because of circle import :( - import signal - import atexit - kill_aria2server() - state.aria2process.wait() - state.aria2process = main.run_aria2server() - signal.signal(signal.SIGINT, main.keyboardinterrupthandler) - atexit.unregister(kill_aria2server) - atexit.register(kill_aria2server) -def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_path=None, speed_limit=None, image_path=None, autoresume=None): +def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_path=None, down_speed_limit=None, up_speed_limit=None, image_path=None, autoresume=None): if thread_count is not None: state.aria2_threads = thread_count if apiurl is not None: state.api_url = apiurl if download_path is not None: state.download_path = download_path - if speed_limit is not None: - state.speed_limit = speed_limit + if down_speed_limit is not None: + state.down_speed_limit = down_speed_limit + if up_speed_limit is not None: + state.up_speed_limit = up_speed_limit if image_path is not None: state.image_path = image_path if autoresume is not None: @@ -29,5 +20,4 @@ def save_settings(thread_count=None, close=lambda: None, apiurl=None, download_p create_config() - restart_aria2c() close() diff --git a/core/utils/data/state.py b/core/utils/data/state.py index cf6d33f..c2b952b 100644 --- a/core/utils/data/state.py +++ b/core/utils/data/state.py @@ -19,7 +19,10 @@ class AppState(QObject): self.tracker: str = "rutracker" self.api_url: str = "https://api.michijackson.xyz" self.download_path: str = str(Path.home() / "Downloads") - self.speed_limit: int = 0 + self.up_speed_limit: int = 0 + self.down_speed_limit: int = 0 + self.max_connections: int = 200 + self.max_downloads: int = 10 self.aria2process: Optional[Any] = None self.aria2: Any = None self.aria2p: Any = None diff --git a/main.py b/main.py index f02807d..47edf20 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,6 @@ from core.interface.gui import MainWindow from core.utils.data.state import state from core.utils.general.logs import consoleLog -from core.network.aria2_integration import aria2server -from core.network.aria2_integration import send_notification, update_log from core.utils.general.logs import get_download_logs from core.utils.general.shutdown import closehelper, shutdown_event from core.utils.general.wrappers import run_thread @@ -35,10 +33,6 @@ def run_gui(): widget.show() sys.exit(app.exec()) -def run_aria2server(): - aria2process = aria2server() - return aria2process - def keyboardinterrupthandler(signum, frame): closehelper() @@ -48,12 +42,10 @@ if __name__ == "__main__": count, downloads = split_data(logs) if args.debug: state.debug = args.debug # override of read_config - consoleLog("Starting Aria2 Server") - state.aria2process = run_aria2server() signal.signal(signal.SIGINT, keyboardinterrupthandler) - run_thread(threading.Thread(target=send_notification, args=(shutdown_event,), daemon=True)) + # run_thread(threading.Thread(target=send_notification, args=(shutdown_event,), daemon=True)) consoleLog("Started send_notification thread") - run_thread(threading.Thread(target=update_log, args=(shutdown_event,), daemon=True)) + # run_thread(threading.Thread(target=update_log, args=(shutdown_event,), daemon=True)) consoleLog("Started update_log thread") run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume))) consoleLog("Started check_completed thread")