mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-04 09:59:41 +02:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0686c7aec2 | |||
| 6be1784903 | |||
| 4589322f0a | |||
| 8132d789ef | |||
| 3f39e67933 | |||
| d43d6e57cc | |||
| f1726f4e9a | |||
| f2a79e5eed | |||
| 990135450f |
@@ -27,6 +27,9 @@ SoftwareManager is a Python-based GUI/TUI tool that simplifies downloading and m
|
|||||||
- If you want to host your own server, clone the server branch of this repo, enter your cookie for rutracker.org and run server.py. Detailed Instructions on how to get your rutracker cookie are in the README of its branch.
|
- If you want to host your own server, clone the server branch of this repo, enter your cookie for rutracker.org and run server.py. Detailed Instructions on how to get your rutracker cookie are in the README of its branch.
|
||||||
- This tool is for educational purposes only. Use it responsibly.
|
- This tool is for educational purposes only. Use it responsibly.
|
||||||
|
|
||||||
|
## Activity
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Star History
|
## Star History
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -134,18 +134,18 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
self.searchbar.returnPressed.connect(lambda: run_thread(threading.Thread(target=return_pressed, args=(self,)))) # Triggers data function thread on enter
|
self.searchbar.returnPressed.connect(lambda: run_thread(threading.Thread(target=return_pressed, args=(self,)))) # Triggers data function thread on enter
|
||||||
|
|
||||||
self.dlbutton = QtWidgets.QPushButton("Download")
|
self.dlbutton = QtWidgets.QPushButton("Download")
|
||||||
self.dlbutton.setCursor(Qt.PointingHandCursor)
|
self.dlbutton.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
self.libraryList = QListWidget()
|
self.libraryList = QListWidget()
|
||||||
|
|
||||||
self.emptyResults = QLabel("No Results")
|
self.emptyResults = QLabel("No Results")
|
||||||
self.emptyResults.setAlignment(Qt.AlignCenter)
|
self.emptyResults.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
self.emptyResults.hide()
|
self.emptyResults.hide()
|
||||||
|
|
||||||
self.download_model = None
|
self.download_model = None
|
||||||
self.downloadList = QTableView()
|
self.downloadList = QTableView()
|
||||||
self.emptyLibrary = QLabel("No items in library.")
|
self.emptyLibrary = QLabel("No items in library.")
|
||||||
self.emptyDownload = QLabel("No items in downloads.")
|
self.emptyDownload = QLabel("No items in downloads.")
|
||||||
self.emptyDownload.setAlignment(Qt.AlignCenter)
|
self.emptyDownload.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
self.consoleLog = QTextEdit()
|
self.consoleLog = QTextEdit()
|
||||||
self.progressbar = QProgressBar()
|
self.progressbar = QProgressBar()
|
||||||
@@ -154,22 +154,22 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
self.qtablewidget = QTableWidget()
|
self.qtablewidget = QTableWidget()
|
||||||
|
|
||||||
self.qtablewidget.setColumnCount(2)
|
self.qtablewidget.setColumnCount(2)
|
||||||
self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
|
||||||
self.qtablewidget.verticalHeader().setVisible(False)
|
self.qtablewidget.verticalHeader().setVisible(False)
|
||||||
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"])
|
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
header = self.qtablewidget.horizontalHeader()
|
header = self.qtablewidget.horizontalHeader()
|
||||||
header.setSectionResizeMode(0, QHeaderView.Stretch)
|
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
|
||||||
header.setSectionResizeMode(1, QHeaderView.Fixed)
|
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
|
||||||
header.setStretchLastSection(False)
|
header.setStretchLastSection(False)
|
||||||
|
|
||||||
self.qtablewidget.setAttribute(Qt.WA_TranslucentBackground)
|
self.qtablewidget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
self.qtablewidget.viewport().setAttribute(Qt.WA_TranslucentBackground)
|
self.qtablewidget.viewport().setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
|
|
||||||
header = self.qtablewidget.horizontalHeader()
|
header = self.qtablewidget.horizontalHeader()
|
||||||
header.setSectionResizeMode(1, QHeaderView.Fixed)
|
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
|
||||||
header.resizeSection(1, 500)
|
header.resizeSection(1, 500)
|
||||||
|
|
||||||
container = QWidget()
|
container = QWidget()
|
||||||
@@ -338,10 +338,10 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
self.download_model = DownloadModel()
|
self.download_model = DownloadModel()
|
||||||
self.downloadList.setModel(self.download_model)
|
self.downloadList.setModel(self.download_model)
|
||||||
self.downloadList.horizontalHeader().setStretchLastSection(False)
|
self.downloadList.horizontalHeader().setStretchLastSection(False)
|
||||||
self.downloadList.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
|
self.downloadList.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
|
||||||
self.downloadList.setSelectionBehavior(QTableView.SelectRows)
|
self.downloadList.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
|
||||||
self.downloadList.setAttribute(Qt.WA_TranslucentBackground)
|
self.downloadList.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
self.downloadList.viewport().setAttribute(Qt.WA_TranslucentBackground)
|
self.downloadList.viewport().setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
|
|
||||||
download_model = self.download_model
|
download_model = self.download_model
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
from core.utils.general.logs import consoleLog
|
||||||
|
from core.utils.data.state import state
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
addrs = psutil.net_if_addrs()
|
||||||
|
stats = psutil.net_if_stats()
|
||||||
|
|
||||||
|
def get_net_interfaces():
|
||||||
|
for interface in addrs.keys():
|
||||||
|
consoleLog(f"Found Interface: {interface}")
|
||||||
|
return addrs.keys()
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_interfaces():
|
||||||
|
active = []
|
||||||
|
|
||||||
|
for interface, addr_list in addrs.items():
|
||||||
|
up = stats[interface].isup
|
||||||
|
for addr in addr_list:
|
||||||
|
if addr.family == 2: # ipv4
|
||||||
|
ipv4 = addr.address
|
||||||
|
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up == True:
|
||||||
|
active.append(interface)
|
||||||
|
consoleLog(f"Found Active: {interface}")
|
||||||
|
|
||||||
|
return active
|
||||||
|
|
||||||
|
|
||||||
|
def list_interfaces() -> None:
|
||||||
|
|
||||||
|
for interface, addr_list in addrs.items():
|
||||||
|
up = stats[interface].isup
|
||||||
|
for addr in addr_list:
|
||||||
|
if addr.family == 2: # ipv4
|
||||||
|
ipv4 = addr.address
|
||||||
|
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up == True:
|
||||||
|
status = "ACTIVE"
|
||||||
|
else:
|
||||||
|
status = "INACTIVE"
|
||||||
|
consoleLog(f"Found Interface: {interface} [{status}]")
|
||||||
|
|
||||||
|
def init_interfaces():
|
||||||
|
state.interfaces = list(addrs.keys())
|
||||||
|
state.active_interfaces = get_active_interfaces()
|
||||||
|
|
||||||
|
def get_interface_ip(interface_name):
|
||||||
|
if interface_name in addrs:
|
||||||
|
for addr in addrs[interface_name]:
|
||||||
|
if addr.family == 2: # ipv4
|
||||||
|
if not addr.address.startswith("127.") and not addr.address.startswith("169.254"):
|
||||||
|
return addr.address
|
||||||
|
return None
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import time
|
import time
|
||||||
from core.utils.general.wrappers import run_thread
|
from core.utils.general.wrappers import run_thread
|
||||||
|
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
|
||||||
@@ -15,6 +16,7 @@ def init_session():
|
|||||||
|
|
||||||
state.dl_session = lt.session()
|
state.dl_session = lt.session()
|
||||||
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
"upload_rate_limit": state.up_speed_limit,
|
"upload_rate_limit": state.up_speed_limit,
|
||||||
"download_rate_limit": state.down_speed_limit,
|
"download_rate_limit": state.down_speed_limit,
|
||||||
@@ -27,7 +29,14 @@ def init_session():
|
|||||||
"active_downloads": state.max_downloads
|
"active_downloads": state.max_downloads
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.bound_interface:
|
||||||
|
interface_ip = get_interface_ip(state.bound_interface)
|
||||||
|
if interface_ip:
|
||||||
|
settings["outgoing_interfaces"] = interface_ip
|
||||||
|
settings["listen_interfaces"] = f"{interface_ip}:6881"
|
||||||
|
consoleLog(f"Binding to Interface IP: {interface_ip}")
|
||||||
|
else:
|
||||||
|
consoleLog(f"Error finding IP for Interface {state.bound_interface}")
|
||||||
|
|
||||||
state.dl_session.apply_settings(settings)
|
state.dl_session.apply_settings(settings)
|
||||||
|
|
||||||
@@ -45,7 +54,6 @@ def add_download(magnet_uri, dl_path=state.download_path):
|
|||||||
consoleLog("Skipping, download already running...")
|
consoleLog("Skipping, download already running...")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
||||||
magnetdl.save_path = dl_path
|
magnetdl.save_path = dl_path
|
||||||
|
|
||||||
@@ -99,5 +107,20 @@ def update_settings():
|
|||||||
"active_downloads": state.max_downloads
|
"active_downloads": state.max_downloads
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.bound_interface:
|
||||||
|
interface_ip = get_interface_ip(state.bound_interface)
|
||||||
|
if interface_ip:
|
||||||
|
settings["outgoing_interfaces"] = interface_ip
|
||||||
|
settings["listen_interfaces"] = f"{interface_ip}:6881"
|
||||||
|
consoleLog(f"Binding to Interface IP: {interface_ip}")
|
||||||
|
else:
|
||||||
|
consoleLog(f"Error finding IP for Interface {state.bound_interface}")
|
||||||
|
|
||||||
|
state.dl_session.apply_settings(settings)
|
||||||
|
|
||||||
|
def update_bound_interface():
|
||||||
|
|
||||||
|
settings = { "outgoing_interfaces": state.bound_interface }
|
||||||
|
|
||||||
state.dl_session.apply_settings(settings)
|
state.dl_session.apply_settings(settings)
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,3 @@ def add_magnet(uri):
|
|||||||
consoleLog("Magnet URI added to LibTorrent")
|
consoleLog("Magnet URI added to LibTorrent")
|
||||||
else:
|
else:
|
||||||
consoleLog(f"Invalid Magnet Link: {uri}")
|
consoleLog(f"Invalid Magnet Link: {uri}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,13 @@ class AppState(QObject):
|
|||||||
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 = None
|
self.settings_path: str = ""
|
||||||
self.dl_session: Any = None
|
self.dl_session: Any = None
|
||||||
self.active_downloads: List[str] = {}
|
self.active_downloads: List[str] = {}
|
||||||
self.window_transparency: bool = False
|
self.window_transparency: bool = False
|
||||||
|
self.interfaces: List = []
|
||||||
|
self.active_interfaces: List = []
|
||||||
|
self.bound_interface: str = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def image_path(self) -> str:
|
def image_path(self) -> str:
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ from core.utils.general.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.general.loghandler import split_data, check_completed
|
||||||
|
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
|
||||||
@@ -45,12 +47,17 @@ if __name__ == "__main__":
|
|||||||
if args.debug:
|
if args.debug:
|
||||||
state.debug = args.debug # override of read_config
|
state.debug = args.debug # override of read_config
|
||||||
signal.signal(signal.SIGINT, keyboardinterrupthandler)
|
signal.signal(signal.SIGINT, keyboardinterrupthandler)
|
||||||
|
consoleLog("Started check_completed thread")
|
||||||
|
consoleLog("Fetching Network Interfaces...")
|
||||||
|
list_interfaces()
|
||||||
|
consoleLog("Initialiting Interface variables...")
|
||||||
|
init_interfaces()
|
||||||
|
consoleLog(f"Current Bound: {state.bound_interface}")
|
||||||
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")
|
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")
|
consoleLog("Started update_log thread")
|
||||||
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
|
run_thread(threading.Thread(target=check_completed, args=(downloads, state.autoresume)))
|
||||||
consoleLog("Started check_completed thread")
|
|
||||||
consoleLog("Launching GUI")
|
consoleLog("Launching GUI")
|
||||||
run_gui()
|
run_gui()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import psutil
|
||||||
|
|
||||||
|
addrs = psutil.net_if_addrs()
|
||||||
|
stats = psutil.net_if_stats()
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_interfaces():
|
||||||
|
active = []
|
||||||
|
|
||||||
|
for interface, addr_list in addrs.items():
|
||||||
|
up = stats[interface].isup
|
||||||
|
for addr in addr_list:
|
||||||
|
if addr.family == 2: # ipv4
|
||||||
|
ipv4 = addr.address
|
||||||
|
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up == True:
|
||||||
|
print(f'"{interface}": True')
|
||||||
|
active.append(interface)
|
||||||
|
print(active)
|
||||||
|
return active
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print(list(addrs.keys()))
|
||||||
|
|
||||||
|
# print(addrs)
|
||||||
|
# print()
|
||||||
|
# sigmer = list()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# for interface in stats.keys():
|
||||||
|
# print(f"{interface}: UP = {stats[interface].isup}")
|
||||||
|
# sigmer.append(f"{interface}: {stats[interface].isup}")
|
||||||
|
|
||||||
|
# print(sigmer)
|
||||||
Reference in New Issue
Block a user