Merge Library and Status into a unified Games tab
This commit is contained in:
+30
-21
@@ -1,7 +1,7 @@
|
||||
"""Installer file downloader with progress reporting and resume support."""
|
||||
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
from datetime import UTC, datetime
|
||||
from typing import Protocol
|
||||
|
||||
import requests
|
||||
@@ -51,7 +51,7 @@ class InstallerDownloader:
|
||||
If single_language is True, the language subfolder is skipped
|
||||
(game only available in one language).
|
||||
"""
|
||||
game_name = sanitize_folder_name(game_name)
|
||||
folder = self._folder_for(installer.game_id, game_name)
|
||||
# Resolve actual download URL and real filename
|
||||
resolved = self.api.resolve_download_url(installer.download_url)
|
||||
if not resolved:
|
||||
@@ -64,10 +64,10 @@ class InstallerDownloader:
|
||||
|
||||
version = installer.version if installer.version else "unknown"
|
||||
if single_language:
|
||||
target_dir = self.metadata.base_path / game_name / version
|
||||
target_dir = self.metadata.base_path / folder / version
|
||||
else:
|
||||
lang_folder = language_folder_name(installer.language)
|
||||
target_dir = self.metadata.base_path / game_name / version / lang_folder
|
||||
target_dir = self.metadata.base_path / folder / version / lang_folder
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
target_file = target_dir / real_filename
|
||||
|
||||
@@ -88,7 +88,7 @@ class InstallerDownloader:
|
||||
|
||||
if response.status_code == 416:
|
||||
logger.info(f"Already fully downloaded: {real_filename}")
|
||||
self._record_download(installer, game_name, real_filename)
|
||||
self._record_download(installer, folder, real_filename)
|
||||
if callback:
|
||||
callback.on_finished(True, "Already downloaded")
|
||||
return True
|
||||
@@ -141,7 +141,7 @@ class InstallerDownloader:
|
||||
callback.on_finished(False, f"Write error: {e}")
|
||||
return False
|
||||
|
||||
self._record_download(installer, game_name, real_filename)
|
||||
self._record_download(installer, folder, real_filename)
|
||||
logger.info(f"Downloaded {real_filename} ({downloaded} bytes)")
|
||||
if callback:
|
||||
callback.on_finished(True, "Download complete")
|
||||
@@ -154,7 +154,7 @@ class InstallerDownloader:
|
||||
callback: DownloadProgressCallback | None = None,
|
||||
) -> bool:
|
||||
"""Download a bonus content file to GameName/Bonus/ directory."""
|
||||
game_name = sanitize_folder_name(game_name)
|
||||
folder = self._folder_for(bonus.game_id, game_name)
|
||||
resolved = self.api.resolve_download_url(bonus.download_url)
|
||||
if not resolved:
|
||||
logger.error(f"Could not resolve download URL for bonus '{bonus.name}'")
|
||||
@@ -164,14 +164,14 @@ class InstallerDownloader:
|
||||
|
||||
actual_url, real_filename = resolved
|
||||
|
||||
target_dir = self.metadata.base_path / game_name / "Bonus"
|
||||
target_dir = self.metadata.base_path / folder / "Bonus"
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
target_file = target_dir / real_filename
|
||||
|
||||
# Skip if already downloaded with same size
|
||||
if target_file.exists() and target_file.stat().st_size == bonus.size:
|
||||
logger.info(f"Bonus already downloaded: {real_filename}")
|
||||
self._record_bonus(bonus, game_name, real_filename)
|
||||
self._record_bonus(bonus, folder, real_filename)
|
||||
if callback:
|
||||
callback.on_finished(True, "Already downloaded")
|
||||
return True
|
||||
@@ -192,7 +192,7 @@ class InstallerDownloader:
|
||||
|
||||
if response.status_code == 416:
|
||||
logger.info(f"Bonus already fully downloaded: {real_filename}")
|
||||
self._record_bonus(bonus, game_name, real_filename)
|
||||
self._record_bonus(bonus, folder, real_filename)
|
||||
if callback:
|
||||
callback.on_finished(True, "Already downloaded")
|
||||
return True
|
||||
@@ -244,45 +244,54 @@ class InstallerDownloader:
|
||||
callback.on_finished(False, f"Write error: {e}")
|
||||
return False
|
||||
|
||||
self._record_bonus(bonus, game_name, real_filename)
|
||||
self._record_bonus(bonus, folder, real_filename)
|
||||
logger.info(f"Downloaded bonus {real_filename} ({downloaded} bytes)")
|
||||
if callback:
|
||||
callback.on_finished(True, "Download complete")
|
||||
return True
|
||||
|
||||
def _record_bonus(self, bonus: BonusContent, game_name: str, real_filename: str) -> None:
|
||||
def _folder_for(self, game_id: str, game_name: str) -> str:
|
||||
"""Pinned download folder for a game: its recorded folder, else the sanitized title."""
|
||||
record = self.metadata.get_game(game_id)
|
||||
if record and record.folder:
|
||||
return record.folder
|
||||
return sanitize_folder_name(game_name)
|
||||
|
||||
def _record_bonus(self, bonus: BonusContent, folder: str, real_filename: str) -> None:
|
||||
"""Record the bonus download in metadata store."""
|
||||
game_name = sanitize_folder_name(game_name)
|
||||
record = self.metadata.get_game(bonus.game_id)
|
||||
if not record:
|
||||
record = GameRecord(
|
||||
game_id=bonus.game_id,
|
||||
name=game_name,
|
||||
name=folder,
|
||||
)
|
||||
if not record.folder:
|
||||
record.folder = folder
|
||||
|
||||
downloaded = DownloadedBonus(
|
||||
filename=real_filename,
|
||||
name=bonus.name,
|
||||
bonus_type=bonus.bonus_type,
|
||||
size=bonus.size,
|
||||
downloaded_at=datetime.now(timezone.utc).isoformat(),
|
||||
downloaded_at=datetime.now(UTC).isoformat(),
|
||||
)
|
||||
|
||||
record.bonuses = [b for b in record.bonuses if b.filename != real_filename]
|
||||
record.bonuses.append(downloaded)
|
||||
record.last_checked = datetime.now(timezone.utc).isoformat()
|
||||
record.last_checked = datetime.now(UTC).isoformat()
|
||||
self.metadata.update_game(record)
|
||||
|
||||
def _record_download(self, installer: InstallerInfo, game_name: str, real_filename: str) -> None:
|
||||
def _record_download(self, installer: InstallerInfo, folder: str, real_filename: str) -> None:
|
||||
"""Record the download in metadata store."""
|
||||
game_name = sanitize_folder_name(game_name)
|
||||
record = self.metadata.get_game(installer.game_id)
|
||||
if not record:
|
||||
record = GameRecord(
|
||||
game_id=installer.game_id,
|
||||
name=game_name,
|
||||
name=folder,
|
||||
latest_version=installer.version,
|
||||
)
|
||||
if not record.folder:
|
||||
record.folder = folder
|
||||
|
||||
downloaded = DownloadedInstaller(
|
||||
filename=real_filename,
|
||||
@@ -290,12 +299,12 @@ class InstallerDownloader:
|
||||
version=installer.version,
|
||||
language=installer.language,
|
||||
installer_type=installer.installer_type,
|
||||
downloaded_at=datetime.now(timezone.utc).isoformat(),
|
||||
downloaded_at=datetime.now(UTC).isoformat(),
|
||||
)
|
||||
|
||||
# Replace existing entry for same file, or add new
|
||||
record.installers = [i for i in record.installers if i.filename != real_filename]
|
||||
record.installers.append(downloaded)
|
||||
record.latest_version = installer.version
|
||||
record.last_checked = datetime.now(timezone.utc).isoformat()
|
||||
record.last_checked = datetime.now(UTC).isoformat()
|
||||
self.metadata.update_game(record)
|
||||
|
||||
Reference in New Issue
Block a user