Init
This commit is contained in:
91
windows/main_window.py
Normal file
91
windows/main_window.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import logging
|
||||
import base64
|
||||
|
||||
from PySide6.QtCore import QTimer
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtWidgets import QMainWindow
|
||||
|
||||
from src.conf import ConfManager
|
||||
from src.download import DownloadManager
|
||||
from src.handler import WebHandler
|
||||
from windows.site_window import SiteWindow
|
||||
|
||||
import resources_rc
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
# Création d'un logger spécifique pour cette classe
|
||||
self.logger = logging.getLogger("MainWindow")
|
||||
self.logger.info("Initialisation de la fenêtre principale")
|
||||
|
||||
# initialise main app
|
||||
self.setWindowTitle("Oxpanel")
|
||||
self.setMinimumSize(1024, 768)
|
||||
self.setWindowIcon(QIcon(":/oxpanel.ico"))
|
||||
self.url = "http://127.0.0.1:8000/" if "--dev" in sys.argv else "https://oxpanel.com/"
|
||||
self.logger.debug(f"URL configurée: {self.url}")
|
||||
|
||||
# initialise every module
|
||||
self.logger.debug("Initialisation des modules")
|
||||
self.conf = ConfManager(self)
|
||||
self.download_manager = DownloadManager(self)
|
||||
self.web_handler = WebHandler(self.download_manager, self)
|
||||
|
||||
# initialise windows
|
||||
self.logger.debug("Initialisation des fenêtres")
|
||||
self.site_window = SiteWindow(self)
|
||||
self.setCentralWidget(self.site_window)
|
||||
|
||||
# connection des signaux
|
||||
self.site_window.on_cookie_added.connect(lambda cookie: asyncio.ensure_future(self.download_manager.add_cookie(cookie)))
|
||||
self.logger.debug("Signaux connectés")
|
||||
|
||||
# initialisation du gestionnaire de téléchargement
|
||||
self.dm_loop = None
|
||||
QTimer.singleShot(0, self.setup_async_tasks)
|
||||
|
||||
self.logger.info("Fenêtre principale initialisée avec succès")
|
||||
|
||||
def setup_async_tasks(self):
|
||||
# Lancer les tâches asyncio une fois que l'application est prête
|
||||
self.logger.debug("Configuration des tâches asynchrones")
|
||||
self.dm_loop = asyncio.ensure_future(self.download_manager.loop_queue())
|
||||
self.logger.debug("File d'attente de téléchargement démarrée")
|
||||
|
||||
def handle_files(self, file_paths):
|
||||
"""
|
||||
Traite les fichiers reçus via "Ouvrir avec" ou d'une autre instance.
|
||||
|
||||
Args:
|
||||
file_paths (list): Liste des chemins de fichiers à traiter
|
||||
"""
|
||||
if not self.web_handler.site_ready:
|
||||
QTimer.singleShot(100, lambda: self.handle_files(file_paths))
|
||||
self.logger.info("Site pas prêt, report de l'envoie des fichiers")
|
||||
return
|
||||
|
||||
self.logger.info(f"Traitement de {len(file_paths)} fichiers reçus")
|
||||
for file_path in file_paths:
|
||||
file_path = Path(file_path)
|
||||
self.logger.debug(f"Traitement du fichier : {file_path}")
|
||||
|
||||
# Exemple: vérifier si le fichier existe
|
||||
if file_path.exists():
|
||||
self.logger.debug(f"Le fichier {file_path} existe")
|
||||
try:
|
||||
with file_path.open("rb") as file:
|
||||
file_content = file.read()
|
||||
encoded_content = base64.b64encode(file_content).decode("utf-8")
|
||||
self.web_handler.on_message.emit({
|
||||
"context": "upload_torrent",
|
||||
"content": encoded_content
|
||||
})
|
||||
except Exception as e:
|
||||
self.logger.error(f"Erreur lors de la lecture ou de l'encodage du fichier {file_path}: {e}")
|
||||
else:
|
||||
self.logger.warning(f"Le fichier {file_path} n'existe pas")
|
||||
157
windows/site_window.py
Normal file
157
windows/site_window.py
Normal file
@@ -0,0 +1,157 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
|
||||
from PySide6.QtWebEngineCore import QWebEngineSettings, QWebEngineProfile, QWebEnginePage, QWebEngineCookieStore
|
||||
from PySide6.QtWidgets import QWidget
|
||||
from PySide6.QtWebEngineWidgets import QWebEngineView
|
||||
from PySide6.QtWebChannel import QWebChannel
|
||||
from PySide6.QtCore import Slot, QFile, QIODevice, Signal, Qt, QStandardPaths, QTimer, QDateTime
|
||||
from PySide6.QtNetwork import QNetworkCookie
|
||||
|
||||
import sys
|
||||
|
||||
from src.conf import ConfManager
|
||||
from src.handler import WebHandler
|
||||
|
||||
|
||||
# https://gitea.devpanel.fr/oxpanel/app/src/branch/master/window/site.py
|
||||
class SiteWindow(QWebEngineView):
|
||||
on_cookie_added = Signal(QNetworkCookie)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.conf = parent.conf
|
||||
self.web_handler = parent.web_handler
|
||||
|
||||
self.page().profile().cookieStore().deleteAllCookies()
|
||||
|
||||
storage_path = Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation))
|
||||
if not storage_path.exists():
|
||||
storage_path.mkdir(parents=True)
|
||||
|
||||
self.persistent_profile = QWebEngineProfile("OxAppProfile", parent=self)
|
||||
self.cookie_store = self.persistent_profile.cookieStore()
|
||||
self.cookie_store.cookieAdded.connect(self.on_cookie_added.emit)
|
||||
self.cookie_store.cookieAdded.connect(self.test_cookie)
|
||||
self.persistent_profile.setHttpCacheType(QWebEngineProfile.HttpCacheType.MemoryHttpCache)
|
||||
self.persistent_profile.setPersistentStoragePath(str(self.conf.app_config_path / "web_cache"))
|
||||
self.persistent_profile.setPersistentCookiesPolicy(QWebEngineProfile.PersistentCookiesPolicy.AllowPersistentCookies)
|
||||
self.persistent_profile.setHttpUserAgent("oxapp25")
|
||||
|
||||
custom_page = QWebEnginePage(self.persistent_profile, parent=self)
|
||||
self.setPage(custom_page)
|
||||
|
||||
self.settings().setAttribute(QWebEngineSettings.WebAttribute.Accelerated2dCanvasEnabled, True)
|
||||
self.settings().setAttribute(QWebEngineSettings.WebAttribute.ScrollAnimatorEnabled, True)
|
||||
self.settings().setAttribute(QWebEngineSettings.WebAttribute.WebGLEnabled, True)
|
||||
# self.settings().setAttribute(QWebEngineSettin gs.WebAttribute.LocalStorageEnabled, False)
|
||||
# self.settings().setAttribute(QWebEngineSettings.WebAttribute.AutoLoadImages, True)
|
||||
# self.settings().setAttribute(QWebEngineSettings.WebAttribute.PluginsEnabled, False)
|
||||
self.settings().setAttribute(QWebEngineSettings.WebAttribute.ShowScrollBars, True)
|
||||
self.page().setBackgroundColor(Qt.GlobalColor.white)
|
||||
|
||||
self.web_channel = QWebChannel(self)
|
||||
self.web_channel.registerObject("handler", self.web_handler)
|
||||
self.page().setWebChannel(self.web_channel)
|
||||
|
||||
self.loadFinished.connect(self.on_load_finished)
|
||||
|
||||
self.load(parent.url)
|
||||
|
||||
def test_cookie(self, *args, **kwargs):
|
||||
print("cook", *args, **kwargs)
|
||||
# self.cookie_store.loadAllCookies()
|
||||
|
||||
|
||||
@Slot(bool)
|
||||
def on_load_finished(self, is_success):
|
||||
print("load finished")
|
||||
if is_success:
|
||||
api_file = QFile(":/qtwebchannel/qwebchannel.js")
|
||||
api_file.open(QIODevice.OpenModeFlag.ReadOnly)
|
||||
api_content = api_file.readAll().data().decode("utf-8")
|
||||
api_file.close()
|
||||
self.page().runJavaScript(api_content)
|
||||
|
||||
# fix main scrollbar
|
||||
css = """
|
||||
html::-webkit-scrollbar,
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
html, body {
|
||||
scrollbar-width: none; /* Pour Firefox */
|
||||
-ms-overflow-style: none; /* Pour Internet Explorer et Edge */
|
||||
overflow: auto; /* Conserver la capacité de défilement */
|
||||
}
|
||||
"""
|
||||
js_code = f"var style = document.createElement('style'); style.textContent = `{css}`; document.head.appendChild(style);"
|
||||
self.page().runJavaScript(js_code)
|
||||
|
||||
self.recreate_sessionid_cookie()
|
||||
|
||||
def sessionid_from_cookie_store(self) -> None|sqlite3.Row:
|
||||
# Cette approche est expérimentale et dépend de l'implémentation interne
|
||||
profile_path = self.persistent_profile.persistentStoragePath()
|
||||
cookies_db_path = os.path.join(profile_path, "Cookies")
|
||||
|
||||
if os.path.exists(cookies_db_path):
|
||||
try:
|
||||
conn = sqlite3.connect(cookies_db_path)
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM cookies WHERE name='sessionid'")
|
||||
result = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
if result:
|
||||
return result # La valeur du cookie
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'accès au fichier de cookies: {e}")
|
||||
return None
|
||||
|
||||
def recreate_sessionid_cookie(self):
|
||||
cookie_info = self.sessionid_from_cookie_store()
|
||||
if cookie_info is None:
|
||||
return
|
||||
# Créer un nouveau cookie avec le nom et la valeur
|
||||
cookie = QNetworkCookie(b"sessionid", cookie_info['value'].encode())
|
||||
|
||||
# Configurer toutes les propriétés disponibles
|
||||
cookie.setDomain(cookie_info['host_key'])
|
||||
cookie.setPath(cookie_info['path'])
|
||||
|
||||
# Gérer les dates d'expiration (conversion du format si nécessaire)
|
||||
if cookie_info['has_expires']:
|
||||
# Convertir depuis le format UNIX en QDateTime
|
||||
# Attention: Chromium stocke les dates en microseconds depuis 1601-01-01 UTC
|
||||
# Vous devrez peut-être ajuster cette conversion selon le format exact
|
||||
expires = QDateTime.fromSecsSinceEpoch(int(cookie_info['expires_utc'] / 1000000) - 11644473600)
|
||||
cookie.setExpirationDate(expires)
|
||||
|
||||
# Configurer les attributs de sécurité
|
||||
cookie.setSecure(bool(cookie_info['is_secure']))
|
||||
cookie.setHttpOnly(bool(cookie_info['is_httponly']))
|
||||
|
||||
# Configurer SameSite si disponible dans votre version de PySide6
|
||||
# Vérifier si l'attribut est disponible (PySide6 ≥ 6.2.0)
|
||||
if hasattr(cookie, 'setSameSitePolicy'):
|
||||
# Conversion des valeurs numériques en constantes SameSite
|
||||
samesite_value = cookie_info['samesite']
|
||||
samesite_map = {
|
||||
0: QNetworkCookie.SameSite.None_, # None
|
||||
1: QNetworkCookie.SameSite.Lax, # Lax
|
||||
2: QNetworkCookie.SameSite.Strict # Strict
|
||||
}
|
||||
if samesite_value in samesite_map:
|
||||
cookie.setSameSitePolicy(samesite_map[samesite_value])
|
||||
|
||||
# Ajouter le cookie au store - cela va déclencher le signal cookieAdded
|
||||
self.cookie_store.setCookie(cookie)
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
# Ignorer l'événement pour empêcher l'affichage du menu contextuel
|
||||
event.ignore()
|
||||
|
||||
Reference in New Issue
Block a user