mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-04 09:59:41 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d1b3ba68f | |||
| dcc12c0b28 | |||
| 925fe21d03 | |||
| ec462afde6 | |||
| e50ef32c66 | |||
| d6e418d045 | |||
| a7c71b37f5 | |||
| 8fb1bb9e8d | |||
| 89fd8b4ebb | |||
| 3915e114a3 | |||
| 34a50e1a1b | |||
| 90124fd9c8 | |||
| 4175f82967 | |||
| 4bf2e9af81 | |||
| a6bb879db3 | |||
| 7653748599 | |||
| 9bec3f9189 | |||
| 04d93b870a | |||
| 664e660198 | |||
| 60019e0d2e | |||
| 8238cfbe56 | |||
| 7ccff5c5a1 | |||
| 8abe92fc4f | |||
| 0a3b5eeee2 |
@@ -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
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -1,84 +1,35 @@
|
|||||||
import requests
|
import requests
|
||||||
import asyncio
|
|
||||||
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):
|
||||||
global url_uztracker
|
base_url="https://uztracker.net/"
|
||||||
url_uztracker = "https://uztracker.net/tracker.php?nm="
|
search_url = f"{base_url.rstrip('/')}/tracker.php?nm={query}"
|
||||||
|
|
||||||
def init_uztracker():
|
|
||||||
global up
|
|
||||||
global soup
|
|
||||||
try:
|
|
||||||
response = requests.get(url_uztracker, timeout=10)
|
|
||||||
if response.status_code == 200:
|
|
||||||
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)
|
consoleLog(search_url)
|
||||||
result = False
|
posts = []
|
||||||
global results
|
|
||||||
global resulttitles
|
|
||||||
results = []
|
|
||||||
resulttitles = []
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resultCount = 0
|
|
||||||
response = requests.get(search_url)
|
response = requests.get(search_url)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
soup = BeautifulSoup(response.text, 'html.parser')
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
links = soup.find_all('a', class_="genmed tLink", href=lambda x: x and x.startswith('./viewtopic'))
|
links = soup.find_all('tr', class_="tCenter hl-tr", id=lambda x: x and x.startswith('tor_'))
|
||||||
for link in links:
|
for link in links:
|
||||||
if link.b:
|
|
||||||
resultCount += 1
|
|
||||||
results.append(link['href'])
|
|
||||||
resulttitles.append(link.b.text)
|
|
||||||
result = True
|
|
||||||
|
|
||||||
if result:
|
theme_link = link.find('a', class_="genmed tLink", href=lambda x: x and x.startswith('./viewtopic'))
|
||||||
return resulttitles, results
|
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"
|
||||||
|
|
||||||
if not result:
|
posts.append(dict(
|
||||||
# add popup in gui for no result
|
title=title,
|
||||||
return None
|
url=url,
|
||||||
|
author=author
|
||||||
|
))
|
||||||
|
|
||||||
|
return posts
|
||||||
|
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
if result:
|
|
||||||
consoleLog(f"Failed to fetch {search_url}: {e}")
|
consoleLog(f"Failed to fetch {search_url}: {e}")
|
||||||
return None
|
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')
|
|
||||||
maintitle = soup.find(class_='tt-text')
|
|
||||||
if maintitle:
|
|
||||||
return maintitle.text
|
|
||||||
else:
|
|
||||||
consoleLog("Program not found")
|
|
||||||
else:
|
|
||||||
consoleLog("Error: Uztracker down")
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+53
-36
@@ -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
|
||||||
|
|
||||||
@@ -145,51 +147,57 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
|
|
||||||
flush_log_buffer()
|
flush_log_buffer()
|
||||||
|
|
||||||
# Table Widget for Item List
|
def create_tracker_table(headers):
|
||||||
self.qtablewidget = QTableWidget()
|
table = QTableWidget()
|
||||||
|
table.setColumnCount(len(headers))
|
||||||
|
table.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
|
||||||
|
table.verticalHeader().setVisible(False)
|
||||||
|
table.setHorizontalHeaderLabels(headers)
|
||||||
|
|
||||||
self.qtablewidget.setColumnCount(4)
|
header = table.horizontalHeader()
|
||||||
self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
|
|
||||||
self.qtablewidget.verticalHeader().setVisible(False)
|
|
||||||
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author", "Seeders", "Leechers"])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
header = self.qtablewidget.horizontalHeader()
|
|
||||||
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
|
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
|
||||||
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
|
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
|
||||||
|
header.resizeSection(1, 500)
|
||||||
header.setStretchLastSection(False)
|
header.setStretchLastSection(False)
|
||||||
|
|
||||||
self.qtablewidget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
return table
|
||||||
self.qtablewidget.viewport().setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
|
||||||
|
|
||||||
header = self.qtablewidget.horizontalHeader()
|
|
||||||
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
|
self.rutrackerlist = create_tracker_table(["Post Title", "Author", "Seeders", "Leechers"])
|
||||||
header.resizeSection(1, 500)
|
self.uztrackerlist = create_tracker_table(["Post Title", "Author"])
|
||||||
|
self.monkruslist = create_tracker_table(["Post Title", "Author"])
|
||||||
|
|
||||||
|
state.tracker_list.update({"rutracker": self.rutrackerlist, "uztracker": self.uztrackerlist, "m0nkrus": self.monkruslist})
|
||||||
|
|
||||||
|
self.rutrackerlist.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
|
self.rutrackerlist.viewport().setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
|
|
||||||
|
self.uztrackerlist.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
|
self.uztrackerlist.viewport().setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
|
|
||||||
container = QWidget()
|
container = QWidget()
|
||||||
containerLayout = QVBoxLayout()
|
containerLayout = QVBoxLayout()
|
||||||
containerLayout.addWidget(self.searchbar)
|
containerLayout.addWidget(self.searchbar)
|
||||||
containerLayout.addWidget(self.qtablewidget)
|
containerLayout.addWidget(state.tracker_list[state.tracker])
|
||||||
|
|
||||||
class DownloadModel(QAbstractTableModel):
|
class DownloadModel(QAbstractTableModel):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
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:
|
||||||
@@ -251,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
|
||||||
@@ -351,7 +359,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
delegate.clicked.connect(on_pause_resume_clicked)
|
delegate.clicked.connect(on_pause_resume_clicked)
|
||||||
|
|
||||||
# download button triggers
|
# download button triggers
|
||||||
self.dlbutton.clicked.connect(lambda: run_thread(threading.Thread(target=download_selected, args=(self.qtablewidget.currentItem(), state.posts, state.post_titles))))
|
self.dlbutton.clicked.connect(lambda: run_thread(threading.Thread(target=download_selected, args=(state.tracker_list[state.tracker].currentItem(), state.posts, state.post_titles))))
|
||||||
|
|
||||||
container.setLayout(containerLayout)
|
container.setLayout(containerLayout)
|
||||||
self.setCentralWidget(container)
|
self.setCentralWidget(container)
|
||||||
@@ -371,15 +379,16 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
|
|
||||||
self.horizontal_layout = QHBoxLayout()
|
self.horizontal_layout = QHBoxLayout()
|
||||||
self.horizontal_layout.addWidget(self.emptyResults, stretch=3)
|
self.horizontal_layout.addWidget(self.emptyResults, stretch=3)
|
||||||
self.horizontal_layout.addWidget(self.qtablewidget)
|
self.tracker_widget = state.tracker_list[state.tracker]
|
||||||
|
self.horizontal_layout.addWidget(self.tracker_widget)
|
||||||
|
|
||||||
self.tab1 = create_tab("Search", self.searchbar, self.qtablewidget, self.tabs, self.dlbutton, self.horizontal_layout)
|
self.tab1 = create_tab("Search", self.searchbar, state.tracker_list[state.tracker], self.tabs, self.dlbutton, self.horizontal_layout)
|
||||||
# self.tab2 = create_tab("Library", self.emptyLibrary, self.libraryList, self.tabs, None, None)
|
# self.tab2 = create_tab("Library", self.emptyLibrary, self.libraryList, self.tabs, None, None)
|
||||||
self.tab3 = create_tab("Downloads", self.emptyDownload, self.downloadList, self.tabs, None, None)
|
self.tab3 = create_tab("Downloads", self.emptyDownload, self.downloadList, self.tabs, None, None)
|
||||||
|
|
||||||
if state.image_path is not None and os.path.exists(state.image_path):
|
if state.image_path is not None and os.path.exists(state.image_path):
|
||||||
self.image = QImage(state.image_path)
|
self.image = QImage(state.image_path)
|
||||||
self.image = self.image.scaledToWidth(300, Qt.SmoothTransformation)
|
self.image = self.image.scaledToWidth(300, Qt.TransformationMode.SmoothTransformation)
|
||||||
self.pixmap = QPixmap.fromImage(self.image)
|
self.pixmap = QPixmap.fromImage(self.image)
|
||||||
self.overlay_label = QLabel(self)
|
self.overlay_label = QLabel(self)
|
||||||
self.overlay_label.setPixmap(self.pixmap)
|
self.overlay_label.setPixmap(self.pixmap)
|
||||||
@@ -504,14 +513,22 @@ 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()
|
||||||
|
|
||||||
|
old_widget = state.tracker_list[old_tracker]
|
||||||
|
self.horizontal_layout.removeWidget(old_widget)
|
||||||
|
old_widget.setParent(None)
|
||||||
|
|
||||||
|
tracker_widget = state.tracker_list[state.tracker]
|
||||||
|
self.horizontal_layout.addWidget(tracker_widget)
|
||||||
|
|
||||||
def show_empty_results(self, show: bool):
|
def show_empty_results(self, show: bool):
|
||||||
if show:
|
if show:
|
||||||
self.qtablewidget.hide()
|
state.tracker_list[state.tracker].hide()
|
||||||
self.emptyResults.show()
|
self.emptyResults.show()
|
||||||
else:
|
else:
|
||||||
self.qtablewidget.show()
|
state.tracker_list[state.tracker].show()
|
||||||
self.emptyResults.hide()
|
self.emptyResults.hide()
|
||||||
|
|
||||||
def show_empty_downloads(self):
|
def show_empty_downloads(self):
|
||||||
@@ -525,8 +542,8 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
|
|||||||
# thank you claude
|
# thank you claude
|
||||||
def resizeEvent(self, event):
|
def resizeEvent(self, event):
|
||||||
super().resizeEvent(event)
|
super().resizeEvent(event)
|
||||||
table_width = self.qtablewidget.viewport().width()
|
table_width = state.tracker_list[state.tracker].viewport().width()
|
||||||
self.qtablewidget.setColumnWidth(1, int(table_width * 0.3))
|
state.tracker_list[state.tracker].setColumnWidth(1, int(table_width * 0.3))
|
||||||
|
|
||||||
def contextMenuEvent(self, event: QContextMenuEvent):
|
def contextMenuEvent(self, event: QContextMenuEvent):
|
||||||
if self.downloadList.underMouse():
|
if self.downloadList.underMouse():
|
||||||
|
|||||||
@@ -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,71 +19,48 @@ 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
|
|
||||||
self.qtablewidget.clear()
|
|
||||||
if state.post_titles and len(state.post_titles) > 0:
|
|
||||||
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"])
|
|
||||||
self.qtablewidget.setRowCount(len(state.post_titles))
|
|
||||||
for i, author in enumerate(state.post_author):
|
|
||||||
self.qtablewidget.setItem(i, 1, QTableWidgetItem(author))
|
|
||||||
for i, title in enumerate(state.post_titles):
|
|
||||||
self.qtablewidget.setItem(i, 0, QTableWidgetItem(title))
|
|
||||||
self.show_empty_results(False)
|
|
||||||
else:
|
|
||||||
consoleLog(f"No Results for {search_text}")
|
|
||||||
self.qtablewidget.clear()
|
|
||||||
self.show_empty_results(True)
|
|
||||||
else:
|
|
||||||
consoleLog(f"No response from uztracker")
|
|
||||||
self.qtablewidget.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)
|
||||||
if state.posts == []:
|
if state.posts == []:
|
||||||
consoleLog(f"No Results for {search_text}")
|
consoleLog(f"No Results for {search_text}")
|
||||||
self.qtablewidget.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, state.post_seeders, state.post_leechers = format_data(state.posts)
|
state.post_titles, _, state.post_author, state.post_seeders, state.post_leechers = format_data(state.posts)
|
||||||
self.show_empty_results(False)
|
self.show_empty_results(False)
|
||||||
self.qtablewidget.clear()
|
state.tracker_list[state.tracker].clear()
|
||||||
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author", "Seeders", "Leechers"])
|
state.tracker_list[state.tracker].setHorizontalHeaderLabels(["Post Title", "Author", "Seeders", "Leechers"])
|
||||||
self.qtablewidget.setRowCount(len(state.post_titles))
|
state.tracker_list[state.tracker].setRowCount(len(state.post_titles))
|
||||||
for i, author in enumerate(state.post_author):
|
for i, author in enumerate(state.post_author):
|
||||||
self.qtablewidget.setItem(i, 1, QTableWidgetItem(author))
|
state.tracker_list[state.tracker].setItem(i, 1, QTableWidgetItem(author))
|
||||||
for i, title in enumerate(state.post_titles):
|
for i, title in enumerate(state.post_titles):
|
||||||
self.qtablewidget.setItem(i, 0, QTableWidgetItem(title))
|
state.tracker_list[state.tracker].setItem(i, 0, QTableWidgetItem(title))
|
||||||
for i, seeders in enumerate(state.post_seeders):
|
for i, seeders in enumerate(state.post_seeders):
|
||||||
self.qtablewidget.setItem(i, 2, QTableWidgetItem(seeders))
|
state.tracker_list[state.tracker].setItem(i, 2, QTableWidgetItem(seeders))
|
||||||
for i, leechers in enumerate(state.post_leechers):
|
for i, leechers in enumerate(state.post_leechers):
|
||||||
self.qtablewidget.setItem(i, 3, QTableWidgetItem(leechers))
|
state.tracker_list[state.tracker].setItem(i, 3, QTableWidgetItem(leechers))
|
||||||
if state.debug == True:
|
if state.debug == True:
|
||||||
consoleLog(f"Response Cached: {cached}")
|
consoleLog(f"Response Cached: {cached}")
|
||||||
else:
|
else:
|
||||||
consoleLog(f"No response from rutracker")
|
consoleLog(f"No response from rutracker")
|
||||||
self.qtablewidget.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}")
|
||||||
self.qtablewidget.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)
|
||||||
self.qtablewidget.clear()
|
state.tracker_list[state.tracker].clear()
|
||||||
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author"])
|
state.tracker_list[state.tracker].setHorizontalHeaderLabels(["Post Title", "Author"])
|
||||||
self.qtablewidget.setRowCount(len(state.post_titles))
|
state.tracker_list[state.tracker].setRowCount(len(state.post_titles))
|
||||||
for i, author in enumerate(state.post_author):
|
for i, author in enumerate(state.post_author):
|
||||||
self.qtablewidget.setItem(i, 1, QTableWidgetItem(author))
|
state.tracker_list[state.tracker].setItem(i, 1, QTableWidgetItem(author))
|
||||||
for i, title in enumerate(state.post_titles):
|
for i, title in enumerate(state.post_titles):
|
||||||
self.qtablewidget.setItem(i, 0, QTableWidgetItem(title))
|
state.tracker_list[state.tracker].setItem(i, 0, QTableWidgetItem(title))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ def get_active_interfaces():
|
|||||||
for addr in addr_list:
|
for addr in addr_list:
|
||||||
if addr.family == 2: # ipv4
|
if addr.family == 2: # ipv4
|
||||||
ipv4 = addr.address
|
ipv4 = addr.address
|
||||||
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up == True:
|
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up:
|
||||||
active.append(interface)
|
active.append(interface)
|
||||||
consoleLog(f"Found Active: {interface}")
|
consoleLog(f"Found Active: {interface}")
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ def list_interfaces() -> None:
|
|||||||
for addr in addr_list:
|
for addr in addr_list:
|
||||||
if addr.family == 2: # ipv4
|
if addr.family == 2: # ipv4
|
||||||
ipv4 = addr.address
|
ipv4 = addr.address
|
||||||
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up == True:
|
if not ipv4.startswith("127.") and not ipv4.startswith("169.254") and up:
|
||||||
status = "ACTIVE"
|
status = "ACTIVE"
|
||||||
else:
|
else:
|
||||||
status = "INACTIVE"
|
status = "INACTIVE"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import time
|
import time
|
||||||
|
import os
|
||||||
from core.utils.general.wrappers import run_thread
|
from core.utils.general.wrappers import run_thread
|
||||||
from core.network.interface import get_interface_ip
|
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
|
||||||
@@ -51,8 +52,26 @@ def add_download(magnet_uri, dl_path=state.download_path):
|
|||||||
init_session()
|
init_session()
|
||||||
|
|
||||||
if magnet_uri in state.active_downloads:
|
if magnet_uri in state.active_downloads:
|
||||||
|
try:
|
||||||
|
handle = state.active_downloads[magnet_uri]
|
||||||
|
status = handle.status()
|
||||||
|
except RuntimeError as e:
|
||||||
|
consoleLog(f"Error in LibTorrent Handle: {e}")
|
||||||
|
|
||||||
|
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...")
|
consoleLog("Skipping Downloading, download already running...")
|
||||||
return
|
return False
|
||||||
|
else:
|
||||||
|
consoleLog("Skipping Downloading, download already running... ")
|
||||||
|
return False
|
||||||
|
|
||||||
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
||||||
magnetdl.save_path = dl_path
|
magnetdl.save_path = dl_path
|
||||||
@@ -62,8 +81,27 @@ def add_download(magnet_uri, dl_path=state.download_path):
|
|||||||
consoleLog(f"Added {magnet_uri} to downloads")
|
consoleLog(f"Added {magnet_uri} to downloads")
|
||||||
|
|
||||||
run_thread(threading.Thread(target=dl_status_loop))
|
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
|
||||||
|
|
||||||
|
magnetdl = lt.parse_magnet_uri(magnet_uri)
|
||||||
|
magnetdl.save_path = os.path.dirname(file_path)
|
||||||
|
|
||||||
|
handle = state.dl_session.add_torrent(magnetdl)
|
||||||
|
state.active_downloads[magnet_uri] = handle
|
||||||
|
state.seeded_magnets.add(magnet_uri)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def dl_status_loop():
|
def dl_status_loop():
|
||||||
global loop_running
|
global loop_running
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
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 os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ def update_log(shutdown_event):
|
|||||||
|
|
||||||
status = magnetdl.status()
|
status = magnetdl.status()
|
||||||
|
|
||||||
if status.state == lt.torrent_status.seeding and magnet_uri not in updated:
|
if status.state == lt.torrent_status.seeding and magnet_uri not in updated and magnet_uri not in state.seeded_magnets:
|
||||||
consoleLog(f"Marking {status.name} as completed")
|
consoleLog(f"Marking {status.name} as completed")
|
||||||
info_hash = str(status.info_hash)
|
info_hash = str(status.info_hash)
|
||||||
update_download_completed_by_hash(info_hash, True)
|
update_download_completed_by_hash(info_hash, True)
|
||||||
@@ -58,3 +59,24 @@ def update_log(shutdown_event):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
|
def check_deleted_files(shutdown_event):
|
||||||
|
while not shutdown_event.is_set():
|
||||||
|
try:
|
||||||
|
for magnet_uri, magnetdl in list(state.active_downloads.items()):
|
||||||
|
if isinstance(magnetdl, dict):
|
||||||
|
continue
|
||||||
|
|
||||||
|
status = magnetdl.status()
|
||||||
|
|
||||||
|
if status.state == lt.torrent_status.seeding and status.has_metadata:
|
||||||
|
file_path = os.path.join(status.save_path, status.name)
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
consoleLog(f"Registered File Deletion: {status.name}")
|
||||||
|
state.dl_session.remove_torrent(magnetdl)
|
||||||
|
del state.active_downloads[magnet_uri]
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
time.sleep(5)
|
||||||
@@ -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,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from PySide6.QtCore import QObject, Signal
|
from PySide6.QtCore import QObject, Signal
|
||||||
|
from PySide6.QtWidgets import QTableWidget
|
||||||
from typing import Optional, Any, List, Dict
|
from typing import Optional, Any, List, Dict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -7,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] = []
|
||||||
@@ -19,6 +20,7 @@ class AppState(QObject):
|
|||||||
self.debug: bool = False
|
self.debug: bool = False
|
||||||
self.autoresume: bool = True
|
self.autoresume: bool = True
|
||||||
self.tracker: str = "rutracker"
|
self.tracker: str = "rutracker"
|
||||||
|
self.tracker_list: dict[str, QTableWidget] = {}
|
||||||
self.api_url: str = "https://api.michijackson.xyz"
|
self.api_url: str = "https://api.michijackson.xyz"
|
||||||
self.download_path: str = str(Path.home() / "Downloads")
|
self.download_path: str = str(Path.home() / "Downloads")
|
||||||
self.up_speed_limit: int = 0
|
self.up_speed_limit: int = 0
|
||||||
@@ -27,11 +29,12 @@ 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.seeded_magnets: set = set()
|
||||||
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,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,21 +0,0 @@
|
|||||||
from core.utils.general.logs import consoleLog
|
|
||||||
from core.utils.network.download import run_download_direct
|
|
||||||
|
|
||||||
def split_data(data):
|
|
||||||
|
|
||||||
count = data.count
|
|
||||||
downloads = data.data
|
|
||||||
|
|
||||||
return count, downloads
|
|
||||||
|
|
||||||
def check_completed(downloads, resume):
|
|
||||||
for download in downloads:
|
|
||||||
if download.completed == False:
|
|
||||||
consoleLog(f"Found unfinished download: {download.title}")
|
|
||||||
if resume == True:
|
|
||||||
run_download_direct(download.magnet_uri)
|
|
||||||
consoleLog(f"Resuming {download.title}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
from core.utils.logging.logs import consoleLog, remove_download_log
|
||||||
|
from core.utils.network.download import run_download_direct, seed_magnet
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
def split_data(data):
|
||||||
|
|
||||||
|
count = data.count
|
||||||
|
downloads = data.data
|
||||||
|
|
||||||
|
return count, downloads
|
||||||
|
|
||||||
|
def check_completed(downloads, resume):
|
||||||
|
for download in downloads:
|
||||||
|
if download.completed == False:
|
||||||
|
consoleLog(f"Found unfinished download: {download.title}")
|
||||||
|
if resume == True:
|
||||||
|
run_download_direct(download.magnet_uri)
|
||||||
|
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}")
|
||||||
|
seed_magnet(download.magnet_uri, download.path)
|
||||||
|
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 = []
|
||||||
|
|
||||||
@@ -22,6 +23,20 @@ def add_download_log(title, url, magnet_uri, completed) -> DownloadList:
|
|||||||
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:
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
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
|
||||||
|
from core.network.libtorrent_int import add_seed
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
@@ -21,11 +20,14 @@ 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)
|
||||||
|
|
||||||
|
if add_download(magnet_uri):
|
||||||
add_download_log(item, post_url, magnet_uri, False)
|
add_download_log(item, post_url, magnet_uri, False)
|
||||||
add_download(magnet_uri)
|
|
||||||
|
|
||||||
def run_download_direct(magnet_uri):
|
def run_download_direct(magnet_uri):
|
||||||
|
consoleLog(f"Direct download: {magnet_uri[:60]}")
|
||||||
add_download(magnet_uri)
|
add_download(magnet_uri)
|
||||||
|
add_download_log("Direct Download", "", magnet_uri, False)
|
||||||
|
|
||||||
|
def seed_magnet(magnet_uri, file_path):
|
||||||
|
consoleLog(f"Seeding: {magnet_uri[:60]}")
|
||||||
|
add_seed(magnet_uri, file_path)
|
||||||
@@ -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,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"
|
||||||
|
|||||||
+13
-16
@@ -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, check_deleted_files
|
||||||
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,12 @@ 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")
|
||||||
|
run_thread(threading.Thread(target=check_deleted_files, args=(shutdown_event,), daemon=True))
|
||||||
|
consoleLog("Started Thread: check_deleted_files")
|
||||||
|
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()
|
||||||
|
|||||||
Reference in New Issue
Block a user