Compare commits

...

10 Commits

10 changed files with 133 additions and 78 deletions
-5
View File
@@ -126,7 +126,6 @@ jobs:
--enable-plugin=upx \ --enable-plugin=upx \
--upx-binary="${{ env.UPX_BINARY }}" \ --upx-binary="${{ env.UPX_BINARY }}" \
--noinclude-qt-translations \ --noinclude-qt-translations \
--include-data-dir=src/core/interface/assets=src/core/interface/assets \
--include-data-files=build_info.json=build_info.json \ --include-data-files=build_info.json=build_info.json \
--include-data-files=build_info.json=src/build_info.json \ --include-data-files=build_info.json=src/build_info.json \
--include-data-files=build_info.json=src/core/interface/build_info.json \ --include-data-files=build_info.json=src/core/interface/build_info.json \
@@ -141,8 +140,6 @@ jobs:
--add-data "build_info.json:." \ --add-data "build_info.json:." \
--add-data "build_info.json:src/core" \ --add-data "build_info.json:src/core" \
--add-data "build_info.json:src/core/interface" \ --add-data "build_info.json:src/core/interface" \
--add-data "src/core/interface/assets:src/core/interface/assets" \
--icon "src/core/interface/assets/logo.png" \
--exclude-module PyQt6 \ --exclude-module PyQt6 \
--exclude-module PyQt5 \ --exclude-module PyQt5 \
--hidden-import=backports.tarfile \ --hidden-import=backports.tarfile \
@@ -161,8 +158,6 @@ jobs:
--add-data "build_info.json:." \ --add-data "build_info.json:." \
--add-data "build_info.json:src/core" \ --add-data "build_info.json:src/core" \
--add-data "build_info.json:src/core/interface" \ --add-data "build_info.json:src/core/interface" \
--add-data "src/core/interface/assets:src/core/interface/assets" \
--icon "src/core/interface/assets/fr logo.png" \
--exclude-module PyQt6 \ --exclude-module PyQt6 \
--exclude-module PyQt5 \ --exclude-module PyQt5 \
--hidden-import=backports.tarfile \ --hidden-import=backports.tarfile \
+34 -5
View File
@@ -1,16 +1,29 @@
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import requests import requests
import time
from core.utils.general.logs import consoleLog from core.utils.general.logs import consoleLog
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 +38,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 +52,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_monkrus_telegram(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
View File
@@ -1,5 +1,4 @@
import requests import requests
import asyncio
import threading import threading
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from core.utils.data.state import state from core.utils.data.state import state
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

+4
View File
@@ -5,6 +5,7 @@ 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
from PySide6 import QtWidgets from PySide6 import QtWidgets
from PySide6.QtCore import Qt
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QLineEdit, QLineEdit,
QPushButton, QPushButton,
@@ -31,6 +32,9 @@ def settings_dialog(self):
dialog.setLayout(QVBoxLayout()) dialog.setLayout(QVBoxLayout())
if state.window_transparency and platform.system() != "Windows" and dialog:
dialog.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
def close_settings(): def close_settings():
dialog.reject() dialog.reject()
+60 -45
View File
@@ -1,4 +1,4 @@
from PySide6 import QtWidgets from PySide6 import QtWidgets, QtCore, QtGui
from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent, QSize from PySide6.QtCore import Qt, QTimer, QModelIndex, QAbstractTableModel, Signal, QEvent, QSize
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QLineEdit, QLineEdit,
@@ -29,7 +29,7 @@ import libtorrent as lt
import time import time
import sys import sys
import json import json
import asyncio import base64
from core.utils.general.logs import consoleLog, remove_download_log, flush_log_buffer from core.utils.general.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
@@ -38,6 +38,9 @@ from core.utils.network.update_checker import check_for_updates
from core.interface.utils.tabhelper import create_tab from core.interface.utils.tabhelper import create_tab
from core.interface.utils.searchhelper import return_pressed from core.interface.utils.searchhelper import return_pressed
from core.interface.dialogs.settings import settings_dialog 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_white_base64
from core.interface.assets.base64_icons import logo_base64
from core.network.libtorrent_misc import cleanup_session from core.network.libtorrent_misc import cleanup_session
from core.utils.general.shutdown import closehelper from core.utils.general.shutdown import closehelper
@@ -73,21 +76,10 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
MainWindow._instance = self MainWindow._instance = self
self.log_signal.connect(self._on_log_signal) self.log_signal.connect(self._on_log_signal)
def get_asset_path(filename): pixmap = QPixmap()
base_path = os.path.dirname(os.path.abspath(__file__)) image_data = base64.b64decode(logo_base64)
asset_path = os.path.join(base_path, 'assets', filename) pixmap.loadFromData(image_data)
if os.path.exists(asset_path): self.setWindowIcon(QIcon(pixmap))
return asset_path
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
asset_path = os.path.join(sys._MEIPASS, 'src', 'core', 'interface', 'assets', filename)
if os.path.exists(asset_path):
return asset_path
return os.path.join('src', 'core', 'interface', 'assets', filename)
self.setWindowIcon(QIcon(get_asset_path("logo.png")))
if platform.system() == "Windows": if platform.system() == "Windows":
try: try:
@@ -153,32 +145,38 @@ 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))
self.qtablewidget.setColumnCount(4) table.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.qtablewidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) table.verticalHeader().setVisible(False)
self.qtablewidget.verticalHeader().setVisible(False) table.setHorizontalHeaderLabels(headers)
self.qtablewidget.setHorizontalHeaderLabels(["Post Title", "Author", "Seeders", "Leechers"])
header = table.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
header.resizeSection(1, 500)
header.setStretchLastSection(False)
header = self.qtablewidget.horizontalHeader() return table
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
header.setStretchLastSection(False)
self.qtablewidget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.rutrackerlist = create_tracker_table(["Post Title", "Author", "Seeders", "Leechers"])
self.qtablewidget.viewport().setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.uztrackerlist = create_tracker_table(["Post Title", "Author"])
self.monkruslist = create_tracker_table(["Post Title", "Author"])
header = self.qtablewidget.horizontalHeader() state.tracker_list.update({"rutracker": self.rutrackerlist, "uztracker": self.uztrackerlist, "m0nkrus": self.monkruslist})
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
header.resizeSection(1, 500) 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):
@@ -359,7 +357,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)
@@ -379,15 +377,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)
@@ -418,10 +417,18 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.settings_btn = QtWidgets.QToolButton() self.settings_btn = QtWidgets.QToolButton()
self.settings_btn.setIconSize(QSize(21, 21)) self.settings_btn.setIconSize(QSize(21, 21))
self.settings_btn.setStyleSheet("background: transparent;") self.settings_btn.setStyleSheet("background: transparent;")
if darkdetect.isDark(): if darkdetect.isDark():
self.settings_btn.setIcon(QIcon(get_asset_path("settings_white.png"))) settings_white_pixmap = QPixmap()
settings_white = base64.b64decode(settings_white_base64)
settings_white_pixmap.loadFromData(settings_white)
self.settings_btn.setIcon(QIcon(settings_white_pixmap))
else: else:
self.settings_btn.setIcon(QIcon(get_asset_path("settings_black.png"))) settings_black_pixmap = QPixmap()
settings_black = base64.b64decode(settings_black_base64)
settings_black_pixmap.loadFromData(settings_black)
self.settings_btn.setIcon(QIcon(settings_black_pixmap))
self.settings_btn.setToolTip("Settings") self.settings_btn.setToolTip("Settings")
self.settings_btn.setCursor(Qt.CursorShape.PointingHandCursor) self.settings_btn.setCursor(Qt.CursorShape.PointingHandCursor)
self.settings_btn.clicked.connect(lambda: settings_dialog(self)) self.settings_btn.clicked.connect(lambda: settings_dialog(self))
@@ -506,12 +513,20 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
def set_tracker(self, _): def set_tracker(self, _):
state.tracker = self.tracker_list.currentText() state.tracker = self.tracker_list.currentText()
while self.horizontal_layout.count():
item = self.horizontal_layout.takeAt(0)
if item.widget():
item.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 +540,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():
+22 -22
View File
@@ -17,22 +17,22 @@ def return_pressed(self):
response = scrape_uztracker(search_text) response = scrape_uztracker(search_text)
if response: if response:
state.post_titles, state.post_urls = response state.post_titles, state.post_urls = response
self.qtablewidget.clear() state.tracker_list[state.tracker].clear()
if state.post_titles and len(state.post_titles) > 0: if state.post_titles and len(state.post_titles) > 0:
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))
self.show_empty_results(False) self.show_empty_results(False)
else: else:
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:
consoleLog(f"No response from uztracker") consoleLog(f"No response from uztracker")
self.qtablewidget.clear() state.tracker_list[state.tracker].clear()
self.show_empty_results(True) self.show_empty_results(True)
elif state.tracker == "rutracker": elif state.tracker == "rutracker":
@@ -41,27 +41,27 @@ def return_pressed(self):
_, 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 == "m0nkrus":
@@ -69,15 +69,15 @@ def return_pressed(self):
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_titles, _, state.post_author = format_data_m0nkrus(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))
+2
View File
@@ -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
@@ -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