Skip to content

Commit

Permalink
Merge pull request #661 from rommapp/mobygames-new-api
Browse files Browse the repository at this point in the history
Mobygames API support
  • Loading branch information
zurdi15 authored Mar 26, 2024
2 parents 862c210 + c83295b commit 1f09eb4
Show file tree
Hide file tree
Showing 61 changed files with 112,610 additions and 895 deletions.
4 changes: 2 additions & 2 deletions DEVELOPER_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ npm install
### - Create symlink to library and resources
```sh
mkdir assets/romm
ln -s ../../../romm_mock/resources assets/romm/resources
ln -s ../../../romm_mock/assets assets/romm/assets
ln -s ../backend/romm_mock/resources assets/romm/resources
ln -s ../backend/romm_mock/assets assets/romm/assets
```

### - Run the frontend
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
</div>
</div>

# ⚠️ Breaking changes in version 3.0 ⚠️

Version 3.0 introduces exciting new fetures that require some changes to how RomM is setup and configured. **If you're currently running a 2.x version, please review the [migration guide](https://github.com/rommapp/romm/wiki/Upgrading-to-3.0) before upgrading.**
> [!WARNING]
> Version 3.0 introduces exciting new fetures that require some changes to how RomM is setup and configured. **If you're currently running a 2.x version, please review the [migration guide](https://github.com/rommapp/romm/wiki/Upgrading-to-3.0) before upgrading.**
# Overview

Expand Down Expand Up @@ -52,9 +51,8 @@ Before running the [image][docker-tags], ensure that Docker is installed and run
3. Create a docker-compose.yml file by referring to the example [docker-compose.yml][docker-compose-example] file for guidance, and customize it for your setup with [the available environment variables](wiki-env-variables).
4. Launch the container(s) with `docker-compose up -d`.

### Troubleshooting

If you are having issues with RomM, please review the [wiki page][wiki-troubleshooting-url] for troubleshooting steps and common issues.
> [!NOTE]
> **If you are having issues with RomM, please review the [wiki page][wiki-troubleshooting-url] for troubleshooting steps and common issues.**
# Configuration

Expand Down Expand Up @@ -121,11 +119,12 @@ As mentioned in the installation section, RomM requires a specific folder struct
</tr>
</table>

For folder naming conventions, review the [Platform Support][platform-support] section. To override default system names in the folder structure (if your directories are named differently), see the [Configuration File][configuration-file] section.
> [!TIP]
> For folder naming conventions, review the [Platform Support][platform-support] section. To override default system names in the folder structure (if your directories are named differently), see the [Configuration File][configuration-file] section.
## Configuration File

RomM's "understanding" of your library can be configured with a `config.yaml` file. Anytime that file is change, **you must restart the container for changes to take effect.** Refer to the [example config.yml][configuration-file-example] file for guidance on how to configure it, and the [example docker-compose.yml][docker-compose-example] file on how to mount it into the container.
RomM's "understanding" of your library can be configured with a `config.yaml` file or through the `config` tab in the `Control Panel` under `Settings` section. Refer to the [example config.yml][configuration-file-example] file for guidance on how to configure it, and the [example docker-compose.yml][docker-compose-example] file on how to mount it into the container.

## Scheduler

Expand Down
43 changes: 43 additions & 0 deletions backend/alembic/versions/0015_mobygames_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""empty message
Revision ID: 0015_mobygames_data
Revises: 0014_asset_files
Create Date: 2024-02-13 17:57:25.936825
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = "0015_mobygames_data"
down_revision = "0014_asset_files"
branch_labels = None
depends_on = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("platforms", schema=None) as batch_op:
batch_op.add_column(sa.Column("moby_id", sa.Integer(), nullable=True))

with op.batch_alter_table("roms", schema=None) as batch_op:
batch_op.add_column(sa.Column("moby_id", sa.Integer(), nullable=True))
batch_op.add_column(sa.Column("moby_metadata", mysql.JSON(), nullable=True))

with op.batch_alter_table("roms", schema=None) as batch_op:
batch_op.execute("update roms set moby_metadata = '\\{\\}'")

# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("roms", schema=None) as batch_op:
batch_op.drop_column("moby_metadata")
batch_op.drop_column("moby_id")

with op.batch_alter_table("platforms", schema=None) as batch_op:
batch_op.drop_column("moby_id")

# ### end Alembic commands ###
6 changes: 6 additions & 0 deletions backend/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
# STEAMGRIDDB
STEAMGRIDDB_API_KEY: Final = os.environ.get("STEAMGRIDDB_API_KEY", "")

# MOBYGAMES
MOBYGAMES_API_KEY: Final = os.environ.get("MOBYGAMES_API_KEY", "")

# DB DRIVERS
ROMM_DB_DRIVER: Final = os.environ.get("ROMM_DB_DRIVER", "mariadb")

Expand All @@ -52,6 +55,9 @@
)
DISABLE_CSRF_PROTECTION = os.environ.get("DISABLE_CSRF_PROTECTION", "false") == "true"

# SCANS
SCAN_TIMEOUT: Final = int(os.environ.get("SCAN_TIMEOUT", 60 * 60 * 4)) # 4 hours

# TASKS
ENABLE_RESCAN_ON_FILESYSTEM_CHANGE: Final = (
os.environ.get("ENABLE_RESCAN_ON_FILESYSTEM_CHANGE", "false") == "true"
Expand Down
2 changes: 1 addition & 1 deletion backend/config/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def get_db_engine() -> str:
if ROMM_DB_DRIVER == "mariadb":
if not DB_USER or not DB_PASSWD:
log.critical(
"Missing database credentials. Please check your configuration file"
"Missing database credentials, check your environment variables!"
)
sys.exit(3)

Expand Down
7 changes: 7 additions & 0 deletions backend/endpoints/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
SCHEDULED_UPDATE_SWITCH_TITLEDB_CRON,
)
from endpoints.responses.heartbeat import HeartbeatResponse
from handler.metadata_handler.igdb_handler import IGDB_API_ENABLED
from handler.metadata_handler.moby_handler import MOBY_API_ENABLED
from fastapi import APIRouter
from handler import github_handler

Expand All @@ -26,6 +28,11 @@ def heartbeat() -> HeartbeatResponse:
return {
"VERSION": github_handler.get_version(),
"NEW_VERSION": github_handler.check_new_version(),
"ANY_SOURCE_ENABLED": IGDB_API_ENABLED or MOBY_API_ENABLED,
"METADATA_SOURCES": {
"IGDB_API_ENABLED": IGDB_API_ENABLED,
"MOBY_API_ENABLED": MOBY_API_ENABLED,
},
"WATCHER": {
"ENABLED": ENABLE_RESCAN_ON_FILESYSTEM_CHANGE,
"TITLE": "Rescan on filesystem change",
Expand Down
7 changes: 7 additions & 0 deletions backend/endpoints/responses/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,15 @@ class SchedulerDict(TypedDict):
MAME_XML: TaskDict


class MetadataSourcesDict(TypedDict):
IGDB_API_ENABLED: bool
MOBY_API_ENABLED: bool


class HeartbeatResponse(TypedDict):
VERSION: str
NEW_VERSION: str
WATCHER: WatcherDict
SCHEDULER: SchedulerDict
ANY_SOURCE_ENABLED: bool
METADATA_SOURCES: MetadataSourcesDict
1 change: 1 addition & 0 deletions backend/endpoints/responses/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class PlatformSchema(BaseModel):
fs_slug: str
igdb_id: Optional[int] = None
sgdb_id: Optional[int] = None
moby_id: Optional[int] = None
name: Optional[str]
logo_path: str
rom_count: int
Expand Down
32 changes: 17 additions & 15 deletions backend/endpoints/responses/rom.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import re
from typing import Optional
from typing import Optional, get_type_hints
from typing_extensions import TypedDict, NotRequired

from endpoints.responses.assets import SaveSchema, ScreenshotSchema, StateSchema
from fastapi import Request
from fastapi.responses import StreamingResponse
from handler import socket_handler
from handler.igdb_handler import IGDBRelatedGame
from handler.metadata_handler.igdb_handler import IGDBMetadata
from handler.metadata_handler.moby_handler import MobyMetadata
from pydantic import BaseModel, computed_field, Field
from models.rom import Rom
from typing_extensions import TypedDict, NotRequired


SORT_COMPARE_REGEX = r"^([Tt]he|[Aa]|[Aa]nd)\s"


class RomMetadata(TypedDict):
expansions: NotRequired[list[IGDBRelatedGame]]
dlcs: NotRequired[list[IGDBRelatedGame]]
remasters: NotRequired[list[IGDBRelatedGame]]
remakes: NotRequired[list[IGDBRelatedGame]]
expanded_games: NotRequired[list[IGDBRelatedGame]]
ports: NotRequired[list[IGDBRelatedGame]]
similar_games: NotRequired[list[IGDBRelatedGame]]
RomIGDBMetadata = TypedDict(
"RomIGDBMetadata",
{k: NotRequired[v] for k, v in get_type_hints(IGDBMetadata).items()},
total=False,
)
RomMobyMetadata = TypedDict(
"RomMobyMetadata",
{k: NotRequired[v] for k, v in get_type_hints(MobyMetadata).items()},
total=False,
)


class RomSchema(BaseModel):
id: int
igdb_id: Optional[int]
sgdb_id: Optional[int]
moby_id: Optional[int]

platform_id: int
platform_slug: str
Expand All @@ -45,16 +48,15 @@ class RomSchema(BaseModel):
summary: Optional[str]

# Metadata fields
total_rating: Optional[str]
aggregated_rating: Optional[str]
first_release_date: Optional[int]
alternative_names: list[str]
genres: list[str]
franchises: list[str]
collections: list[str]
companies: list[str]
game_modes: list[str]
igdb_metadata: Optional[RomMetadata]
igdb_metadata: Optional[RomIGDBMetadata]
moby_metadata: Optional[RomMobyMetadata]

path_cover_s: Optional[str]
path_cover_l: Optional[str]
Expand Down
13 changes: 9 additions & 4 deletions backend/endpoints/responses/search.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from handler.igdb_handler import IGDBRom
from pydantic import BaseModel


class SearchRomSchema(IGDBRom):
pass
class SearchRomSchema(BaseModel):
igdb_id: int | None = None
moby_id: int | None = None
slug: str
name: str
summary: str
url_cover: str
url_screenshots: list[str]
19 changes: 15 additions & 4 deletions backend/endpoints/rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
fs_resource_handler,
fs_rom_handler,
igdb_handler,
moby_handler,
)
from handler.fs_handler import CoverSize
from logger.logger import log
Expand Down Expand Up @@ -185,9 +186,11 @@ def get_rom_content(

if not rom.multi:
return FileResponse(path=rom_path, filename=rom.file_name)

if len(files_to_download) == 1:
return FileResponse(path=f"{rom_path}/{files_to_download[0]}", filename=files_to_download[0])
return FileResponse(
path=f"{rom_path}/{files_to_download[0]}", filename=files_to_download[0]
)

# Builds a generator of tuples for each member file
def local_files():
Expand All @@ -200,7 +203,10 @@ def contents(f):
log.error(f"File {rom_path}/{f} not found!")
raise

m3u_file = [str.encode(f"{files_to_download[i]}\n") for i in range(len(files_to_download))]
m3u_file = [
str.encode(f"{files_to_download[i]}\n")
for i in range(len(files_to_download))
]
return [
(
f,
Expand Down Expand Up @@ -260,6 +266,11 @@ async def update_rom(

cleaned_data = {}
cleaned_data["igdb_id"] = data.get("igdb_id", db_rom.igdb_id) or None
cleaned_data["moby_id"] = data.get("moby_id", db_rom.moby_id) or None

if cleaned_data["moby_id"]:
moby_rom = moby_handler.get_rom_by_id(cleaned_data["moby_id"])
cleaned_data.update(moby_rom)

if cleaned_data["igdb_id"]:
igdb_rom = igdb_handler.get_rom_by_id(cleaned_data["igdb_id"])
Expand All @@ -275,7 +286,7 @@ async def update_rom(

if rename_as_igdb:
fs_safe_file_name = db_rom.file_name.replace(
db_rom.file_name_no_tags, fs_safe_name
db_rom.file_name_no_tags or db_rom.file_name_no_ext, fs_safe_name
)

try:
Expand Down
Loading

0 comments on commit 1f09eb4

Please sign in to comment.