mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
Merge pull request #2729 from rommapp/feat/redirect-related-games
feat: Redirect related games to RomM entry if exists
This commit is contained in:
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,7 +2,7 @@
|
||||
<!-- trunk-ignore-all(markdownlint/MD033) -->
|
||||
|
||||
**Description**
|
||||
<sup>Explain the changes or enhancements you are proposing with this pull request.</sup>
|
||||
Explain the changes or enhancements you are proposing with this pull request.
|
||||
|
||||
**Checklist**
|
||||
<sup>Please check all that apply.</sup>
|
||||
@@ -12,4 +12,4 @@
|
||||
- [ ] I've assigned reviewers for this PR
|
||||
- [ ] I've added unit tests that cover the changes
|
||||
|
||||
#### Screenshots
|
||||
#### Screenshots (if applicable)
|
||||
|
||||
@@ -448,6 +448,78 @@ async def download_roms(
|
||||
)
|
||||
|
||||
|
||||
@protected_route(
|
||||
router.get,
|
||||
"/by-metadata-provider",
|
||||
[] if DISABLE_DOWNLOAD_ENDPOINT_AUTH else [Scope.ROMS_READ],
|
||||
responses={status.HTTP_404_NOT_FOUND: {}},
|
||||
)
|
||||
def get_rom_by_metadata(
|
||||
request: Request,
|
||||
igdb: Annotated[int | None, Query(description="IGDB ID to search by")] = None,
|
||||
moby: Annotated[int | None, Query(description="MobyGames ID to search by")] = None,
|
||||
ss: Annotated[
|
||||
int | None, Query(description="ScreenScraper ID to search by")
|
||||
] = None,
|
||||
ra: Annotated[
|
||||
int | None, Query(description="RetroAchievements ID to search by")
|
||||
] = None,
|
||||
launchbox: Annotated[
|
||||
int | None, Query(description="LaunchBox ID to search by")
|
||||
] = None,
|
||||
hasheous: Annotated[
|
||||
int | None, Query(description="Hasheous ID to search by")
|
||||
] = None,
|
||||
tgdb: Annotated[int | None, Query(description="TGDB ID to search by")] = None,
|
||||
flashpoint: Annotated[
|
||||
str | None, Query(description="Flashpoint ID to search by")
|
||||
] = None,
|
||||
hltb: Annotated[int | None, Query(description="HLTB ID to search by")] = None,
|
||||
) -> DetailedRomSchema:
|
||||
"""Retrieve a rom by metadata ID."""
|
||||
|
||||
rom = db_rom_handler.get_rom_by_metadata_id(
|
||||
igdb=igdb,
|
||||
moby=moby,
|
||||
ss=ss,
|
||||
ra=ra,
|
||||
launchbox=launchbox,
|
||||
hasheous=hasheous,
|
||||
tgdb=tgdb,
|
||||
flashpoint=flashpoint,
|
||||
hltb=hltb,
|
||||
)
|
||||
|
||||
if not rom:
|
||||
provided_ids = {
|
||||
"igdb_id": igdb,
|
||||
"moby_id": moby,
|
||||
"ss_id": ss,
|
||||
"ra_id": ra,
|
||||
"launchbox_id": launchbox,
|
||||
"hasheous_id": hasheous,
|
||||
"tgdb_id": tgdb,
|
||||
"flashpoint_id": flashpoint,
|
||||
"hltb_id": hltb,
|
||||
}
|
||||
metadata_info = [
|
||||
f"{key}={value}" for key, value in provided_ids.items() if value is not None
|
||||
]
|
||||
|
||||
if not metadata_info:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="At least one metadata ID must be provided",
|
||||
)
|
||||
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"ROM not found with metadata: {', '.join(metadata_info)}",
|
||||
)
|
||||
|
||||
return DetailedRomSchema.from_orm_with_request(rom, request)
|
||||
|
||||
|
||||
@protected_route(
|
||||
router.get,
|
||||
"/{id}",
|
||||
@@ -938,7 +1010,7 @@ async def update_rom(
|
||||
path_manual = await fs_resource_handler.get_manual(
|
||||
rom=rom,
|
||||
overwrite=True,
|
||||
url_manual=url_manual,
|
||||
url_manual=str(url_manual) if url_manual else None,
|
||||
)
|
||||
cleaned_data.update(
|
||||
{
|
||||
|
||||
@@ -977,3 +977,44 @@ class DBRomsHandler(DBBaseHandler):
|
||||
)
|
||||
)
|
||||
return result.rowcount > 0
|
||||
|
||||
@begin_session
|
||||
@with_details
|
||||
def get_rom_by_metadata_id(
|
||||
self,
|
||||
igdb: int | None = None,
|
||||
moby: int | None = None,
|
||||
ss: int | None = None,
|
||||
ra: int | None = None,
|
||||
launchbox: int | None = None,
|
||||
hasheous: int | None = None,
|
||||
tgdb: int | None = None,
|
||||
flashpoint: str | None = None,
|
||||
hltb: int | None = None,
|
||||
*,
|
||||
query: Query = None,
|
||||
session: Session = None,
|
||||
) -> Rom | None:
|
||||
"""Get a ROM by any metadata ID."""
|
||||
filters = []
|
||||
param_map = [
|
||||
(igdb, Rom.igdb_id),
|
||||
(moby, Rom.moby_id),
|
||||
(ss, Rom.ss_id),
|
||||
(ra, Rom.ra_id),
|
||||
(launchbox, Rom.launchbox_id),
|
||||
(hasheous, Rom.hasheous_id),
|
||||
(tgdb, Rom.tgdb_id),
|
||||
(flashpoint, Rom.flashpoint_id),
|
||||
(hltb, Rom.hltb_id),
|
||||
]
|
||||
|
||||
for value, column in param_map:
|
||||
if value is not None:
|
||||
filters.append(column == value)
|
||||
|
||||
if not filters:
|
||||
return None
|
||||
|
||||
# Use OR to find ROM matching any of the provided metadata IDs
|
||||
return session.scalar(query.filter(or_(*filters)).limit(1))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import type { IGDBRelatedGame } from "@/__generated__";
|
||||
import romApi from "@/services/api/rom";
|
||||
import storeGalleryView from "@/stores/galleryView";
|
||||
import { getMissingCoverImage } from "@/utils/covers";
|
||||
|
||||
@@ -9,15 +10,40 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const galleryViewStore = storeGalleryView();
|
||||
const romId = ref<number | null>(null);
|
||||
|
||||
const missingCoverImage = computed(() => getMissingCoverImage(props.game.name));
|
||||
const computedAspectRatio = computed(() =>
|
||||
galleryViewStore.getAspectRatio({ boxartStyle: "cover_path" }),
|
||||
);
|
||||
|
||||
const gameLink = computed(() => {
|
||||
if (romId.value !== null) {
|
||||
return `/rom/${romId.value}`;
|
||||
}
|
||||
return `https://www.igdb.com/games/${props.game.slug}`;
|
||||
});
|
||||
|
||||
const linkTarget = computed(() => {
|
||||
return romId.value !== null ? "_self" : "_blank";
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await romApi
|
||||
.getRomByMetadataProvider({ provider: "igdb", id: props.game.id })
|
||||
.then((response) => {
|
||||
console.log("Fetched ROM by metadata provider:", response.data);
|
||||
romId.value = response.data.id;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching ROM by metadata provider:", error);
|
||||
// Keep romId.value as null to fall back to IGDB link
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a :href="`https://www.igdb.com/games/${game.slug}`" target="_blank">
|
||||
<a :href="gameLink" :target="linkTarget">
|
||||
<v-card>
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
|
||||
@@ -182,6 +182,19 @@ async function getRom({
|
||||
return api.get(`/roms/${romId}`);
|
||||
}
|
||||
|
||||
async function getRomByMetadataProvider({
|
||||
provider,
|
||||
id,
|
||||
}: {
|
||||
provider: string;
|
||||
id: number;
|
||||
}): Promise<{ data: DetailedRom }> {
|
||||
const params = { [provider]: id };
|
||||
return api.get(`/roms/by-metadata-provider/`, {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
async function searchRom({
|
||||
romId,
|
||||
searchTerm,
|
||||
@@ -483,6 +496,7 @@ export default {
|
||||
getRecentRoms,
|
||||
getRecentPlayedRoms,
|
||||
getRom,
|
||||
getRomByMetadataProvider,
|
||||
downloadRom,
|
||||
bulkDownloadRoms,
|
||||
searchRom,
|
||||
|
||||
Reference in New Issue
Block a user