mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-03 17:39:42 +02:00
220 lines
6.8 KiB
Python
220 lines
6.8 KiB
Python
from network.interface import get_interface_ip
|
|
from utils.general.wrappers import run_thread
|
|
from utils.logging.logs import consoleLog
|
|
from utils.data.state import state
|
|
import libtorrent as lt
|
|
import threading
|
|
import platform
|
|
import ctypes
|
|
import time
|
|
import os
|
|
|
|
|
|
loop_running = False
|
|
|
|
def get_free_space_mb(dirname):
|
|
if platform.system() == 'Windows':
|
|
free_bytes = ctypes.c_ulonglong(0)
|
|
ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(dirname), None, None, ctypes.pointer(free_bytes))
|
|
return free_bytes.value
|
|
else:
|
|
st = os.statvfs(dirname)
|
|
return st.f_bavail * st.f_frsize
|
|
|
|
def check_space():
|
|
while not state.shutdown_event.is_set():
|
|
for magnet_uri, magnetdl in list(state.active_downloads.items()):
|
|
try:
|
|
status = magnetdl.status()
|
|
except RuntimeError:
|
|
continue
|
|
|
|
if status.state == lt.torrent_status.downloading:
|
|
free_space = get_free_space_mb(state.download_path)
|
|
total_size = status.total_wanted
|
|
|
|
if free_space < total_size:
|
|
consoleLog(f"Not enough free space to continue downloading: {status.name}")
|
|
magnetdl.pause()
|
|
break
|
|
|
|
time.sleep(5)
|
|
|
|
def init_session():
|
|
if state.dl_session is not None:
|
|
return
|
|
|
|
state.dl_session = lt.session()
|
|
|
|
|
|
settings = {
|
|
"upload_rate_limit": state.up_speed_limit * 1024,
|
|
"download_rate_limit": state.down_speed_limit * 1024,
|
|
"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": state.max_connections,
|
|
"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"Skipping Binding, no Interface set. ({state.bound_interface})")
|
|
|
|
state.dl_session.apply_settings(settings)
|
|
|
|
consoleLog("Initialized Session")
|
|
|
|
|
|
def add_download(magnet_uri):
|
|
|
|
if state.active_downloads is None:
|
|
state.active_downloads = {}
|
|
|
|
init_session()
|
|
free_space = get_free_space_mb(state.download_path)
|
|
|
|
if magnet_uri in state.active_downloads:
|
|
try:
|
|
handle = state.active_downloads[magnet_uri]
|
|
status = handle.status()
|
|
|
|
if status.has_metadata:
|
|
filepath = os.path.join(status.save_path, status.name)
|
|
|
|
if not os.path.exists(filepath):
|
|
|
|
consoleLog(f"File Deleted, redownloading: {status.name}")
|
|
state.dl_session.remove_torrent(handle)
|
|
del state.active_downloads[magnet_uri]
|
|
else:
|
|
consoleLog("Skipping Downloading, download already running...")
|
|
return False
|
|
else:
|
|
consoleLog("Skipping Downloading, download already running... ")
|
|
return False
|
|
except RuntimeError as e:
|
|
consoleLog(f"Error in LibTorrent Handle: {e}")
|
|
del state.active_downloads[magnet_uri]
|
|
|
|
try:
|
|
params = lt.parse_magnet_uri(magnet_uri)
|
|
params.save_path = state.download_path
|
|
|
|
handle = state.dl_session.add_torrent(params)
|
|
while not handle.has_metadata():
|
|
time.sleep(1)
|
|
|
|
total_size = handle.get_torrent_info().total_size()
|
|
|
|
if free_space > total_size:
|
|
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
|
magnetdl.save_path = state.download_path
|
|
download = state.dl_session.add_torrent(magnetdl)
|
|
else:
|
|
state.dl_session.remove_torrent(handle)
|
|
consoleLog("Not enough free space to download this item.")
|
|
return False
|
|
|
|
except Exception as e:
|
|
consoleLog(f"Failed to add torrent or fetch info: {e}")
|
|
return False
|
|
if download:
|
|
state.active_downloads[magnet_uri] = download
|
|
consoleLog(f"Added {magnet_uri} to downloads")
|
|
|
|
run_thread(threading.Thread(target=dl_status_loop))
|
|
return True
|
|
|
|
|
|
def add_seed(magnet_uri, file_path):
|
|
if state.active_downloads is None:
|
|
state.active_downloads = {}
|
|
|
|
init_session()
|
|
|
|
if magnet_uri in state.active_downloads:
|
|
consoleLog("Already seeding this torrent")
|
|
return False
|
|
|
|
try:
|
|
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
|
magnetdl.save_path = os.path.dirname(file_path)
|
|
handle = state.dl_session.add_torrent(magnetdl)
|
|
except Exception as e:
|
|
consoleLog(f"Failed to add seed: {e}")
|
|
return False
|
|
state.active_downloads[magnet_uri] = handle
|
|
state.seeded_magnets.add(magnet_uri)
|
|
return True
|
|
|
|
|
|
def dl_status_loop():
|
|
global loop_running
|
|
if loop_running == True:
|
|
return
|
|
|
|
loop_running = True
|
|
completed_set = set()
|
|
|
|
if not state.active_downloads:
|
|
consoleLog("No active downloads")
|
|
loop_running = False
|
|
return
|
|
|
|
while state.active_downloads and not state.shutdown_event.is_set():
|
|
for magnet_uri, magnetdl in list(state.active_downloads.items()):
|
|
try:
|
|
status = magnetdl.status()
|
|
except RuntimeError:
|
|
continue
|
|
|
|
if status.state == lt.torrent_status.seeding and magnet_uri not in completed_set:
|
|
consoleLog(f"Download completed: {status.name}")
|
|
|
|
completed_set.add(magnet_uri)
|
|
|
|
if not state.active_downloads:
|
|
loop_running = False
|
|
break
|
|
|
|
time.sleep(1)
|
|
|
|
loop_running = False
|
|
|
|
def update_settings():
|
|
|
|
if state.dl_session is None:
|
|
return
|
|
|
|
settings = {
|
|
"upload_rate_limit": state.up_speed_limit * 1024,
|
|
"download_rate_limit": state.down_speed_limit * 1024,
|
|
"connections_limit": state.max_connections,
|
|
"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"Skipping Binding, no Interface set. ({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)
|