mirror of
https://github.com/barkeser2002/CoomerDL.git
synced 2026-09-25 01:10:11 +03:00
308 lines
10 KiB
Python
308 lines
10 KiB
Python
import os
|
|
import json
|
|
import requests
|
|
|
|
from PySide6.QtCore import Qt, QObject, QThread, Signal
|
|
from PySide6.QtGui import QPixmap
|
|
from PySide6.QtWidgets import (
|
|
QDialog,
|
|
QVBoxLayout,
|
|
QHBoxLayout,
|
|
QGridLayout,
|
|
QLabel,
|
|
QFrame,
|
|
QWidget,
|
|
QScrollArea,
|
|
)
|
|
|
|
|
|
class DonorsWorker(QObject):
|
|
finished = Signal(list)
|
|
error = Signal(str)
|
|
|
|
def run(self):
|
|
try:
|
|
response = requests.get(
|
|
"https://emydevs.com/coomer/donadores.php",
|
|
headers={
|
|
"Accept": "application/json",
|
|
"User-Agent": (
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
|
"Chrome/100.0.4896.127 Safari/537.36"
|
|
),
|
|
},
|
|
timeout=10,
|
|
)
|
|
response.raise_for_status()
|
|
donors = response.json()
|
|
self.finished.emit(donors if isinstance(donors, list) else [])
|
|
except requests.exceptions.RequestException as exc:
|
|
self.error.emit(f"request:{exc}")
|
|
except json.JSONDecodeError as exc:
|
|
self.error.emit(f"json:{exc}")
|
|
except Exception as exc:
|
|
self.error.emit(f"unknown:{exc}")
|
|
|
|
|
|
class DonorsModal(QDialog):
|
|
def __init__(self, parent, tr):
|
|
super().__init__(parent)
|
|
self.parent = parent
|
|
self.tr = tr
|
|
|
|
self.worker_thread = None
|
|
self.worker = None
|
|
self._donor_pixmaps = {}
|
|
|
|
self.setWindowTitle(self.tr("DONORS_WINDOW_TITLE"))
|
|
self.setModal(True)
|
|
self.setFixedSize(600, 600)
|
|
self.setWindowModality(Qt.WindowModal)
|
|
|
|
self.main_card = None
|
|
self.scroll_area = None
|
|
self.scroll_content = None
|
|
self.grid_layout = None
|
|
self.status_label = None
|
|
self.title_label = None
|
|
|
|
self._build_ui()
|
|
self._center_window()
|
|
self._load_donors_async()
|
|
|
|
def _build_ui(self):
|
|
self.setStyleSheet(
|
|
"""
|
|
QDialog {
|
|
background-color: #1f1f1f;
|
|
color: white;
|
|
}
|
|
QFrame#mainCard {
|
|
background-color: #2b2b2b;
|
|
border: 1px solid #3a3a3a;
|
|
border-radius: 14px;
|
|
}
|
|
QLabel {
|
|
color: white;
|
|
background: transparent;
|
|
}
|
|
QLabel[role="title"] {
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
}
|
|
QLabel[role="status"] {
|
|
font-size: 14px;
|
|
color: gray;
|
|
}
|
|
QLabel[role="note"] {
|
|
font-size: 12px;
|
|
color: gray;
|
|
font-style: italic;
|
|
}
|
|
QLabel[role="name"] {
|
|
font-size: 14px;
|
|
color: #E0E0E0;
|
|
}
|
|
QFrame[role="donorCard"] {
|
|
background-color: transparent;
|
|
border: 1px solid #3b3b3b;
|
|
border-radius: 10px;
|
|
}
|
|
QScrollArea {
|
|
border: none;
|
|
background: transparent;
|
|
}
|
|
"""
|
|
)
|
|
|
|
root_layout = QVBoxLayout(self)
|
|
root_layout.setContentsMargins(20, 20, 20, 20)
|
|
root_layout.setSpacing(0)
|
|
|
|
self.main_card = QFrame()
|
|
self.main_card.setObjectName("mainCard")
|
|
main_layout = QVBoxLayout(self.main_card)
|
|
main_layout.setContentsMargins(18, 18, 18, 18)
|
|
main_layout.setSpacing(14)
|
|
|
|
self.title_label = QLabel(self.tr("DONORS_WINDOW_TITLE"))
|
|
self.title_label.setProperty("role", "title")
|
|
self.title_label.setAlignment(Qt.AlignCenter)
|
|
main_layout.addWidget(self.title_label)
|
|
|
|
self.scroll_area = QScrollArea()
|
|
self.scroll_area.setWidgetResizable(True)
|
|
|
|
self.scroll_content = QWidget()
|
|
self.grid_layout = QGridLayout(self.scroll_content)
|
|
self.grid_layout.setContentsMargins(8, 8, 8, 8)
|
|
self.grid_layout.setHorizontalSpacing(12)
|
|
self.grid_layout.setVerticalSpacing(12)
|
|
|
|
self.scroll_area.setWidget(self.scroll_content)
|
|
main_layout.addWidget(self.scroll_area, 1)
|
|
|
|
self.status_label = QLabel(self.tr("LOADING_PATREONS"))
|
|
self.status_label.setProperty("role", "status")
|
|
self.status_label.setAlignment(Qt.AlignCenter)
|
|
self.grid_layout.addWidget(self.status_label, 0, 0, 1, 2)
|
|
|
|
root_layout.addWidget(self.main_card)
|
|
|
|
def _clear_grid(self):
|
|
while self.grid_layout.count():
|
|
item = self.grid_layout.takeAt(0)
|
|
widget = item.widget()
|
|
layout = item.layout()
|
|
if widget is not None:
|
|
widget.deleteLater()
|
|
elif layout is not None:
|
|
self._delete_layout(layout)
|
|
|
|
def _delete_layout(self, layout):
|
|
while layout.count():
|
|
item = layout.takeAt(0)
|
|
widget = item.widget()
|
|
child_layout = item.layout()
|
|
if widget is not None:
|
|
widget.deleteLater()
|
|
elif child_layout is not None:
|
|
self._delete_layout(child_layout)
|
|
|
|
def _load_icon_pixmap(self, filename):
|
|
icon_dir = os.path.join("resources", "img", "iconos", "donors")
|
|
path = os.path.join(icon_dir, filename)
|
|
if not os.path.exists(path):
|
|
return None
|
|
|
|
pixmap = QPixmap(path)
|
|
if pixmap.isNull():
|
|
return None
|
|
|
|
return pixmap.scaled(20, 20, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
|
def _ensure_icons_loaded(self):
|
|
if self._donor_pixmaps:
|
|
return
|
|
|
|
self._donor_pixmaps = {
|
|
"gold": self._load_icon_pixmap("gold.png"),
|
|
"silver": self._load_icon_pixmap("silver.png"),
|
|
"bronze": self._load_icon_pixmap("bronze.png"),
|
|
"default": self._load_icon_pixmap("default.png"),
|
|
}
|
|
|
|
def _load_donors_async(self):
|
|
self.worker_thread = QThread(self)
|
|
self.worker = DonorsWorker()
|
|
self.worker.moveToThread(self.worker_thread)
|
|
|
|
self.worker_thread.started.connect(self.worker.run)
|
|
self.worker.finished.connect(self._show_donors)
|
|
self.worker.error.connect(self._show_error)
|
|
self.worker.finished.connect(self.worker_thread.quit)
|
|
self.worker.error.connect(self.worker_thread.quit)
|
|
self.worker.finished.connect(self.worker.deleteLater)
|
|
self.worker.error.connect(self.worker.deleteLater)
|
|
self.worker_thread.finished.connect(self.worker_thread.deleteLater)
|
|
|
|
self.worker_thread.start()
|
|
|
|
def _show_error(self, raw_error):
|
|
self._clear_grid()
|
|
|
|
if raw_error.startswith("request:"):
|
|
msg = raw_error.split(":", 1)[1]
|
|
text = self.tr("ERROR_FETCHING_DONORS", error=msg)
|
|
elif raw_error.startswith("json:"):
|
|
msg = raw_error.split(":", 1)[1]
|
|
text = self.tr("ERROR_PROCESSING_DONOR_DATA", error=msg)
|
|
else:
|
|
msg = raw_error.split(":", 1)[1] if ":" in raw_error else raw_error
|
|
text = self.tr("ERROR_FETCHING_DONORS", error=msg)
|
|
|
|
self.status_label = QLabel(text)
|
|
self.status_label.setProperty("role", "status")
|
|
self.status_label.setStyleSheet("color: red;")
|
|
self.status_label.setWordWrap(True)
|
|
self.status_label.setAlignment(Qt.AlignCenter)
|
|
self.grid_layout.addWidget(self.status_label, 0, 0, 1, 2)
|
|
|
|
def _show_donors(self, donors):
|
|
self._clear_grid()
|
|
self._ensure_icons_loaded()
|
|
|
|
columns = 2
|
|
|
|
if not donors:
|
|
empty_label = QLabel(self.tr("NO_DONORS_FOUND"))
|
|
empty_label.setProperty("role", "status")
|
|
empty_label.setAlignment(Qt.AlignCenter)
|
|
self.grid_layout.addWidget(empty_label, 0, 0, 1, columns)
|
|
return
|
|
|
|
def to_float(value):
|
|
try:
|
|
return float(value)
|
|
except Exception:
|
|
return 0.0
|
|
|
|
donors.sort(key=lambda x: to_float(x.get("donated_amount", 0)), reverse=True)
|
|
|
|
info_label = QLabel(self.tr("DONORS_INFO_NOTE"))
|
|
info_label.setProperty("role", "note")
|
|
info_label.setAlignment(Qt.AlignCenter)
|
|
info_label.setWordWrap(True)
|
|
self.grid_layout.addWidget(info_label, 0, 0, 1, columns)
|
|
|
|
for index, donor in enumerate(donors):
|
|
donor_name = donor.get("name", self.tr("UNKNOWN_DONOR"))
|
|
|
|
icon_key = "default"
|
|
icon_pixmap = self._donor_pixmaps.get(icon_key)
|
|
|
|
card = QFrame()
|
|
card.setProperty("role", "donorCard")
|
|
card_layout = QHBoxLayout(card)
|
|
card_layout.setContentsMargins(10, 10, 10, 10)
|
|
card_layout.setSpacing(10)
|
|
|
|
icon_label = QLabel()
|
|
icon_label.setFixedSize(24, 24)
|
|
icon_label.setAlignment(Qt.AlignCenter)
|
|
if icon_pixmap is not None:
|
|
icon_label.setPixmap(icon_pixmap)
|
|
|
|
name_label = QLabel(donor_name)
|
|
name_label.setProperty("role", "name")
|
|
name_label.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
|
|
name_label.setWordWrap(True)
|
|
|
|
card_layout.addWidget(icon_label, 0, Qt.AlignTop)
|
|
card_layout.addWidget(name_label, 1)
|
|
|
|
row = (index // columns) + 1
|
|
col = index % columns
|
|
self.grid_layout.addWidget(card, row, col)
|
|
|
|
def update_donor_data(self, new_donors):
|
|
self._show_donors(new_donors)
|
|
|
|
def _center_window(self):
|
|
if self.parent is not None:
|
|
parent_geometry = self.parent.frameGeometry()
|
|
dialog_geometry = self.frameGeometry()
|
|
dialog_geometry.moveCenter(parent_geometry.center())
|
|
self.move(dialog_geometry.topLeft())
|
|
return
|
|
|
|
screen = self.screen()
|
|
if screen is not None:
|
|
available = screen.availableGeometry()
|
|
dialog_geometry = self.frameGeometry()
|
|
dialog_geometry.moveCenter(available.center())
|
|
self.move(dialog_geometry.topLeft())
|
|
|
|
def show_modal(self):
|
|
self.exec() |