mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
Merge pull request #2636 from rommapp/hotfix-media-import-gamelist-xml
[HOTFIX] Fix importing media from gamelist.xml
This commit is contained in:
@@ -276,7 +276,7 @@ class FSHandler:
|
||||
# Async thread-safe directory listing
|
||||
lock = await self._get_file_lock(str(target_directory))
|
||||
async with lock:
|
||||
if not target_directory.exists() or not target_directory.is_dir():
|
||||
if not target_directory.is_dir():
|
||||
raise FileNotFoundError(
|
||||
f"Path does not exist or is not a directory: {str(target_directory)}"
|
||||
)
|
||||
@@ -300,7 +300,7 @@ class FSHandler:
|
||||
# Async thread-safe directory removal
|
||||
lock = await self._get_file_lock(str(target_directory))
|
||||
async with lock:
|
||||
if not target_directory.exists() or not target_directory.is_dir():
|
||||
if not target_directory.is_dir():
|
||||
raise FileNotFoundError(
|
||||
f"Path does not exist or is not a directory: {str(target_directory)}"
|
||||
)
|
||||
@@ -414,7 +414,7 @@ class FSHandler:
|
||||
# Async thread-safe file read
|
||||
lock = await self._get_file_lock(str(full_path))
|
||||
async with lock:
|
||||
if not full_path.exists() or not full_path.is_file():
|
||||
if not full_path.is_file():
|
||||
raise FileNotFoundError(f"File not found: {full_path}")
|
||||
|
||||
async with await open_file(full_path, "rb") as f:
|
||||
@@ -442,11 +442,42 @@ class FSHandler:
|
||||
# Async thread-safe file stream
|
||||
lock = await self._get_file_lock(str(full_path))
|
||||
async with lock:
|
||||
if not full_path.exists() or not full_path.is_file():
|
||||
if not full_path.is_file():
|
||||
raise FileNotFoundError(f"File not found: {full_path}")
|
||||
|
||||
return await open_file(full_path, "rb")
|
||||
|
||||
async def copy_file(self, source_full_path: Path, dest_path: str) -> None:
|
||||
"""
|
||||
Copy a file from source to destination.
|
||||
|
||||
Args:
|
||||
source_full_path: Absolute path to the source file
|
||||
dest_path: Relative path to the destination file
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: If source file does not exist
|
||||
ValueError: If destination path is invalid
|
||||
"""
|
||||
if not source_full_path or not dest_path:
|
||||
raise ValueError("Source and destination paths cannot be empty")
|
||||
|
||||
# Validate and normalize path
|
||||
dest_full_path = self.validate_path(dest_path)
|
||||
|
||||
# Use locks for both source and destination
|
||||
source_lock = await self._get_file_lock(str(source_full_path))
|
||||
dest_lock = await self._get_file_lock(str(dest_full_path))
|
||||
|
||||
# Async thread-safe file copy
|
||||
async with source_lock, dest_lock:
|
||||
if not source_full_path.is_file():
|
||||
raise FileNotFoundError(f"Source file not found: {source_full_path}")
|
||||
|
||||
# Create destination directory if needed
|
||||
dest_full_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(str(source_full_path), str(dest_full_path))
|
||||
|
||||
async def move_file_or_folder(self, source_path: str, dest_path: str) -> None:
|
||||
"""
|
||||
Move a file from source to destination.
|
||||
@@ -479,7 +510,6 @@ class FSHandler:
|
||||
|
||||
# Create destination directory if needed
|
||||
dest_full_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
shutil.move(str(source_full_path), str(dest_full_path))
|
||||
|
||||
async def remove_file(self, file_path: str) -> None:
|
||||
@@ -528,7 +558,7 @@ class FSHandler:
|
||||
# Async thread-safe directory listing
|
||||
lock = await self._get_file_lock(str(full_path))
|
||||
async with lock:
|
||||
if not full_path.exists() or not full_path.is_dir():
|
||||
if not full_path.is_dir():
|
||||
raise FileNotFoundError(f"Directory not found: {full_path}")
|
||||
|
||||
return [f for _, f in iter_files(str(full_path), recursive=False)]
|
||||
@@ -552,7 +582,7 @@ class FSHandler:
|
||||
# Async thread-safe existence check
|
||||
lock = await self._get_file_lock(str(full_path))
|
||||
async with lock:
|
||||
return full_path.exists() and full_path.is_file()
|
||||
return full_path.is_file()
|
||||
|
||||
async def get_file_size(self, file_path: str) -> int:
|
||||
"""
|
||||
@@ -576,7 +606,7 @@ class FSHandler:
|
||||
# Async thread-safe file size retrieval
|
||||
lock = await self._get_file_lock(str(full_path))
|
||||
async with lock:
|
||||
if not full_path.exists() or not full_path.is_file():
|
||||
if not full_path.is_file():
|
||||
raise FileNotFoundError(f"File not found: {full_path}")
|
||||
|
||||
return full_path.stat().st_size
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import gzip
|
||||
import os
|
||||
import shutil
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
|
||||
@@ -69,7 +68,7 @@ class FSResourcesHandler(FSHandler):
|
||||
size: size of the cover
|
||||
"""
|
||||
cover_file = f"{entity.fs_resources_path}/cover"
|
||||
await self.make_directory(f"{cover_file}")
|
||||
await self.make_directory(cover_file)
|
||||
|
||||
# Handle file:// URLs for gamelist.xml
|
||||
if url_cover.startswith("file://"):
|
||||
@@ -77,13 +76,16 @@ class FSResourcesHandler(FSHandler):
|
||||
file_path = Path(url_cover[7:]) # Remove "file://" prefix
|
||||
if file_path.exists():
|
||||
# Copy the file to the resources directory
|
||||
dest_path = self.validate_path(f"{cover_file}/{size.value}.png")
|
||||
shutil.copy2(file_path, dest_path)
|
||||
dest_path = f"{cover_file}/{size.value}.png"
|
||||
await self.copy_file(file_path, dest_path)
|
||||
|
||||
if ENABLE_SCHEDULED_CONVERT_IMAGES_TO_WEBP:
|
||||
self.image_converter.convert_to_webp(dest_path, force=True)
|
||||
self.image_converter.convert_to_webp(
|
||||
self.validate_path(f"{cover_file}/{size.value}.png"),
|
||||
force=True,
|
||||
)
|
||||
else:
|
||||
log.warning(f"File not found: {file_path}")
|
||||
log.warning(f"Cover file not found: {file_path}")
|
||||
return None
|
||||
except Exception as exc:
|
||||
log.error(f"Unable to copy cover file {url_cover}: {str(exc)}")
|
||||
@@ -245,8 +247,7 @@ class FSResourcesHandler(FSHandler):
|
||||
file_path = Path(url_screenhot[7:]) # Remove "file://" prefix
|
||||
if file_path.exists():
|
||||
# Copy the file to the resources directory
|
||||
dest_path = self.validate_path(f"{screenshot_path}/{idx}.jpg")
|
||||
shutil.copy2(file_path, dest_path)
|
||||
await self.copy_file(file_path, f"{screenshot_path}/{idx}.jpg")
|
||||
else:
|
||||
log.warning(f"Screenshot file not found: {file_path}")
|
||||
return None
|
||||
@@ -357,8 +358,7 @@ class FSResourcesHandler(FSHandler):
|
||||
file_path = Path(url_manual[7:]) # Remove "file://" prefix
|
||||
if file_path.exists():
|
||||
# Copy the file to the resources directory
|
||||
dest_path = self.validate_path(f"{manual_path}/{rom.id}.pdf")
|
||||
shutil.copy2(file_path, dest_path)
|
||||
await self.copy_file(file_path, f"{manual_path}/{rom.id}.pdf")
|
||||
else:
|
||||
log.warning(f"Manual file not found: {file_path}")
|
||||
return None
|
||||
@@ -466,12 +466,12 @@ class FSResourcesHandler(FSHandler):
|
||||
) -> str:
|
||||
return os.path.join("roms", str(platform_id), str(rom_id), media_type.value)
|
||||
|
||||
async def store_media_file(self, url: str, path: str) -> None:
|
||||
async def store_media_file(self, url: str, dest_path: str) -> None:
|
||||
httpx_client = ctx_httpx_client.get()
|
||||
directory, filename = os.path.split(path)
|
||||
directory, filename = os.path.split(dest_path)
|
||||
|
||||
if await self.file_exists(path):
|
||||
log.debug(f"Media file {path} already exists, skipping download")
|
||||
if await self.file_exists(dest_path):
|
||||
log.debug(f"Media file {dest_path} already exists, skipping download")
|
||||
return
|
||||
|
||||
# Ensure destination directory exists
|
||||
@@ -482,9 +482,7 @@ class FSResourcesHandler(FSHandler):
|
||||
try:
|
||||
file_path = Path(url[7:]) # Remove "file://" prefix
|
||||
if file_path.exists():
|
||||
# Validate the destination path
|
||||
dest_path = self.validate_path(path)
|
||||
shutil.copy2(file_path, dest_path)
|
||||
await self.copy_file(file_path, dest_path)
|
||||
except Exception as exc:
|
||||
log.error(f"Unable to copy media file {url}: {str(exc)}")
|
||||
return None
|
||||
|
||||
@@ -326,27 +326,15 @@ class GamelistHandler(MetadataHandler):
|
||||
gamelist_metadata=rom_metadata,
|
||||
)
|
||||
|
||||
platform_dir = fs_platform_handler.get_plaform_fs_structure(
|
||||
platform.fs_slug
|
||||
)
|
||||
|
||||
# Choose which cover style to use
|
||||
cover_path = rom_metadata["box2d_url"] or rom_metadata["image_url"]
|
||||
if cover_path:
|
||||
cover_path_path = fs_platform_handler.validate_path(
|
||||
f"{platform_dir}/{cover_path}"
|
||||
)
|
||||
rom_data["url_cover"] = f"file://{str(cover_path_path)}"
|
||||
cover_url = rom_metadata["box2d_url"] or rom_metadata["image_url"]
|
||||
if cover_url:
|
||||
rom_data["url_cover"] = cover_url
|
||||
|
||||
# Grab the manual
|
||||
if (
|
||||
rom_metadata["manual_url"]
|
||||
and MetadataMediaType.MANUAL in preferred_media_types
|
||||
):
|
||||
manual_path = fs_platform_handler.validate_path(
|
||||
f"{platform_dir}/{rom_metadata['manual_url']}"
|
||||
)
|
||||
rom_data["url_manual"] = f"file://{str(manual_path)}"
|
||||
manual_url = rom_metadata["manual_url"]
|
||||
if manual_url and MetadataMediaType.MANUAL in preferred_media_types:
|
||||
rom_data["url_manual"] = manual_url
|
||||
|
||||
# Build list of screenshot URLs
|
||||
url_screenshots = []
|
||||
@@ -354,18 +342,12 @@ class GamelistHandler(MetadataHandler):
|
||||
rom_metadata["screenshot_url"]
|
||||
and MetadataMediaType.SCREENSHOT in preferred_media_types
|
||||
):
|
||||
screenshot_path = fs_platform_handler.validate_path(
|
||||
f"{platform_dir}/{rom_metadata['screenshot_url']}"
|
||||
)
|
||||
url_screenshots.append(f"file://{str(screenshot_path)}")
|
||||
url_screenshots.append(rom_metadata["screenshot_url"])
|
||||
if (
|
||||
rom_metadata["title_screen_url"]
|
||||
and MetadataMediaType.TITLE_SCREEN in preferred_media_types
|
||||
):
|
||||
title_screen_path = fs_platform_handler.validate_path(
|
||||
f"{platform_dir}/{rom_metadata['title_screen_url']}"
|
||||
)
|
||||
url_screenshots.append(f"file://{str(title_screen_path)}")
|
||||
url_screenshots.append(rom_metadata["title_screen_url"])
|
||||
rom_data["url_screenshots"] = url_screenshots
|
||||
|
||||
# Store by filename for matching
|
||||
|
||||
@@ -276,7 +276,9 @@ async function stopScan() {
|
||||
:fs-slug="item.raw.fs_slug"
|
||||
:size="20"
|
||||
/>
|
||||
{{ item.raw.name }}
|
||||
<div class="ml-1">
|
||||
{{ item.raw.name }}
|
||||
</div>
|
||||
</v-chip>
|
||||
</template>
|
||||
</v-select>
|
||||
|
||||
Reference in New Issue
Block a user