Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SteamGridDB integration #960

Merged
merged 16 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions backend/alembic/versions/0020_created_and_updated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
"""empty message

Revision ID: 0020_created_and_updated
Revises: 0019_resources_refactor
Create Date: 2024-06-27 12:08:13.886766

"""

import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = "0020_created_and_updated"
down_revision = "0019_resources_refactor"
branch_labels = None
depends_on = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("firmware", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"created_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)
batch_op.add_column(
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)

with op.batch_alter_table("platforms", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"created_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)
batch_op.add_column(
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)

with op.batch_alter_table("rom_notes", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)
batch_op.drop_column("last_edited_at")

with op.batch_alter_table("roms", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"created_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)
batch_op.add_column(
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)

with op.batch_alter_table("users", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"created_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)
batch_op.add_column(
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.text("now()"),
nullable=False,
)
)

# ### end Alembic commands ###


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

with op.batch_alter_table("roms", schema=None) as batch_op:
batch_op.drop_column("updated_at")
batch_op.drop_column("created_at")

with op.batch_alter_table("rom_notes", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"last_edited_at",
mysql.DATETIME(),
server_default=sa.text("current_timestamp()"),
nullable=False,
)
)
batch_op.drop_column("updated_at")

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

with op.batch_alter_table("firmware", schema=None) as batch_op:
batch_op.drop_column("updated_at")
batch_op.drop_column("created_at")

# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions backend/endpoints/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from handler.filesystem import fs_platform_handler
from handler.metadata.igdb_handler import IGDB_API_ENABLED
from handler.metadata.moby_handler import MOBY_API_ENABLED
from handler.metadata.sgdb_handler import STEAMGRIDDB_API_ENABLED
from utils import get_version

router = APIRouter()
Expand All @@ -27,6 +28,7 @@ def heartbeat() -> HeartbeatResponse:
return {
"VERSION": get_version(),
"ANY_SOURCE_ENABLED": IGDB_API_ENABLED or MOBY_API_ENABLED,
"STEAMGRIDDB_ENABLED": STEAMGRIDDB_API_ENABLED,
"METADATA_SOURCES": {
"IGDB_API_ENABLED": IGDB_API_ENABLED,
"MOBY_API_ENABLED": MOBY_API_ENABLED,
Expand Down
5 changes: 5 additions & 0 deletions backend/endpoints/responses/firmware.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from pydantic import BaseModel
from typing_extensions import TypedDict

Expand All @@ -18,6 +20,9 @@ class FirmwareSchema(BaseModel):
md5_hash: str
sha1_hash: str

created_at: datetime
updated_at: datetime

class Config:
from_attributes = True

Expand Down
1 change: 1 addition & 0 deletions backend/endpoints/responses/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ class HeartbeatResponse(TypedDict):
SCHEDULER: SchedulerDict
ANY_SOURCE_ENABLED: bool
METADATA_SOURCES: MetadataSourcesDict
STEAMGRIDDB_ENABLED: bool
FS_PLATFORMS: list
3 changes: 3 additions & 0 deletions backend/endpoints/responses/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ class UserSchema(BaseModel):
last_login: datetime | None
last_active: datetime | None

created_at: datetime
updated_at: datetime

class Config:
from_attributes = True
5 changes: 5 additions & 0 deletions backend/endpoints/responses/platform.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from pydantic import BaseModel, Field

from .firmware import FirmwareSchema
Expand All @@ -15,5 +17,8 @@ class PlatformSchema(BaseModel):
logo_path: str | None = ""
firmware: list[FirmwareSchema] = Field(default_factory=list)

created_at: datetime
updated_at: datetime
zurdi15 marked this conversation as resolved.
Show resolved Hide resolved

class Config:
from_attributes = True
5 changes: 4 additions & 1 deletion backend/endpoints/responses/rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RomNoteSchema(BaseModel):
id: int
user_id: int
rom_id: int
last_edited_at: datetime
updated_at: datetime
raw_markdown: str
is_public: bool
user__username: str
Expand Down Expand Up @@ -94,6 +94,9 @@ class RomSchema(BaseModel):
files: list[str]
full_path: str

created_at: datetime
updated_at: datetime

class Config:
from_attributes = True

Expand Down
5 changes: 5 additions & 0 deletions backend/endpoints/responses/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ class SearchRomSchema(BaseModel):
summary: str
igdb_url_cover: str = ""
moby_url_cover: str = ""


class SearchCoverSchema(BaseModel):
name: str
resources: list
13 changes: 11 additions & 2 deletions backend/endpoints/search.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import emoji
from decorators.auth import protected_route
from endpoints.responses.search import SearchRomSchema
from endpoints.responses.search import SearchCoverSchema, SearchRomSchema
from fastapi import APIRouter, HTTPException, Request, status
from handler.database import db_rom_handler
from handler.metadata import meta_igdb_handler, meta_moby_handler
from handler.metadata import meta_igdb_handler, meta_moby_handler, meta_sgdb_handler
from handler.metadata.igdb_handler import IGDB_API_ENABLED
from handler.metadata.moby_handler import MOBY_API_ENABLED
from handler.scan_handler import _get_main_platform_igdb_id
Expand Down Expand Up @@ -107,3 +107,12 @@ async def search_rom(
log.info(f"\t - {m_rom['name']}")

return matched_roms


@protected_route(router.get, "/search/cover", ["roms.read"])
async def search_cover(
request: Request,
search_term: str | None = None,
) -> list[SearchCoverSchema]:

return meta_sgdb_handler.get_details(search_term)
8 changes: 6 additions & 2 deletions backend/handler/filesystem/resources_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ def _cover_exists(rom: Rom, size: CoverSize):
def resize_cover_to_small(cover_path: str):
"""Path of the cover image to resize"""
cover = Image.open(cover_path)
small_width = int(cover.width * 0.1)
small_height = int(cover.height * 0.1)
if cover.height >= 1000:
ratio = 0.2
else:
ratio = 0.4
small_width = int(cover.width * ratio)
small_height = int(cover.height * ratio)
small_size = (small_width, small_height)
small_img = cover.resize(small_size)
small_img.save(cover_path)
Expand Down
17 changes: 11 additions & 6 deletions backend/handler/metadata/igdb_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,14 @@ def extract_metadata_from_igdb_rom(rom: dict) -> IGDBMetadata:

class IGDBBaseHandler(MetadataHandler):
def __init__(self) -> None:
self.platform_endpoint = "https://api.igdb.com/v4/platforms"
self.platform_version_endpoint = "https://api.igdb.com/v4/platform_versions"
self.platforms_fields = ["id", "name"]
self.games_endpoint = "https://api.igdb.com/v4/games"
self.BASE_URL = "https://api.igdb.com/v4"
self.platform_endpoint = f"{self.BASE_URL}/platforms"
self.platform_version_endpoint = f"{self.BASE_URL}/platform_versions"
self.platforms_fields = PLATFORMS_FIELDS
self.games_endpoint = f"{self.BASE_URL}/games"
self.games_fields = GAMES_FIELDS
self.search_endpoint = "https://api.igdb.com/v4/search"
self.search_fields = ["game.id", "name"]
self.search_endpoint = f"{self.BASE_URL}/search"
self.search_fields = SEARCH_FIELDS
self.pagination_limit = 200
self.twitch_auth = TwitchAuth()
self.headers = {
Expand Down Expand Up @@ -617,6 +618,8 @@ def get_oauth_token(self) -> str:
return token


PLATFORMS_FIELDS = ["id", "name"]

GAMES_FIELDS = [
"id",
"name",
Expand Down Expand Up @@ -667,6 +670,8 @@ def get_oauth_token(self) -> str:
"similar_games.cover.url",
]

SEARCH_FIELDS = ["game.id", "name"]

# Generated from the following code on https://www.igdb.com/platforms/:
# Array.from(document.querySelectorAll(".media-body a")).map(a => ({
# slug: a.href.split("/")[4],
Expand Down
Loading
Loading