mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2025-12-23 14:08:42 -05:00
Merge pull request #270 from aasmoe/feat/multi-language-metadata
Add Feature: multi language metadata
This commit is contained in:
@@ -17,6 +17,26 @@ If you want to use your own TMDB relay service, set this to the URL of your own
|
||||
- **Default:** `https://metadata-relay.dorninger.co/tmdb`
|
||||
- **Example:** `https://your-own-relay.example.com/tmdb`
|
||||
|
||||
### `primary_languages`
|
||||
|
||||
If a TV show/movie's original language is in this list, metadata will be displayed and fetched in that language. Torrent searches done in Standard Mode uses the same fetched metadata, so if you use any language-specific tracker, you may enter the language here to get the desired search results.
|
||||
Otherwise, `default_language` will be used.
|
||||
|
||||
**Format: ISO 639-1 codes (2 letters). Full list: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes**
|
||||
|
||||
- **Default:** `[]`
|
||||
- **Example:** `["no", "de", "es"]`
|
||||
|
||||
### `default_language`
|
||||
|
||||
<warning>
|
||||
`default_language` sets the TMDB `language` paramater when searching and adding TV shows and movies. If TMDB does not find a matching translation, metadata in the <strong>original language</strong> will be fetched with no option for a fallback language. It is therefore highly advised to only use "broad" languages. For most use cases, the default setting is safest.
|
||||
</warning>
|
||||
|
||||
**Format: ISO 639-1 codes (2 letters).**
|
||||
|
||||
- **Default:** `en`
|
||||
|
||||
## TVDB Settings (`[metadata.tvdb]`)
|
||||
|
||||
<warning>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
"""add original_language columns to show and movie tables
|
||||
|
||||
Revision ID: 16e78af9e5bf
|
||||
Revises: eb0bd3cc1852
|
||||
Create Date: 2025-12-13 18:47:02.146038
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '16e78af9e5bf'
|
||||
down_revision: Union[str, None] = 'eb0bd3cc1852'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# Add original_language column to show table
|
||||
op.add_column(
|
||||
'show',
|
||||
sa.Column('original_language', sa.String(10), nullable=True)
|
||||
)
|
||||
|
||||
# Add original_language column to movie table
|
||||
op.add_column(
|
||||
'movie',
|
||||
sa.Column('original_language', sa.String(10), nullable=True)
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# Remove original_language column from movie table
|
||||
op.drop_column('movie', 'original_language')
|
||||
|
||||
# Remove original_language column from show table
|
||||
op.drop_column('show', 'original_language')
|
||||
@@ -172,6 +172,8 @@ rule_names = ["prefer_h265", "avoid_cam", "reject_non_freeleech"]
|
||||
[metadata]
|
||||
[metadata.tmdb]
|
||||
tmdb_relay_url = "https://metadata-relay.dorninger.co/tmdb"
|
||||
primary_languages = [""]
|
||||
default_language = "en"
|
||||
|
||||
[metadata.tvdb]
|
||||
tvdb_relay_url = "https://metadata-relay.dorninger.co/tvdb"
|
||||
@@ -3,7 +3,8 @@ from pydantic_settings import BaseSettings
|
||||
|
||||
class TmdbConfig(BaseSettings):
|
||||
tmdb_relay_url: str = "https://metadata-relay.dorninger.co/tmdb"
|
||||
|
||||
primary_languages: list[str] = [] # ISO 639-1 language codes
|
||||
default_language: str = "en" # ISO 639-1 language codes
|
||||
|
||||
class TvdbConfig(BaseSettings):
|
||||
tvdb_relay_url: str = "https://metadata-relay.dorninger.co/tvdb"
|
||||
|
||||
@@ -12,4 +12,5 @@ class MetaDataProviderSearchResult(BaseModel):
|
||||
metadata_provider: str
|
||||
added: bool
|
||||
vote_average: float | None = None
|
||||
original_language: str | None = None
|
||||
id: MovieId | ShowId | None = None # Internal ID if already added
|
||||
|
||||
@@ -25,10 +25,29 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
def __init__(self):
|
||||
config = AllEncompassingConfig().metadata.tmdb
|
||||
self.url = config.tmdb_relay_url
|
||||
self.primary_languages = config.primary_languages
|
||||
self.default_language = config.default_language
|
||||
|
||||
def __get_show_metadata(self, id: int) -> dict:
|
||||
def __get_language_param(self, original_language: str | None) -> str:
|
||||
"""
|
||||
Determine the language parameter to use for TMDB API calls.
|
||||
Returns the original language if it's in primary_languages, otherwise returns default_language.
|
||||
|
||||
:param original_language: The original language code (ISO 639-1) of the media
|
||||
:return: Language parameter (ISO 639-1 format, e.g., 'en', 'no')
|
||||
"""
|
||||
if original_language and original_language in self.primary_languages:
|
||||
return original_language
|
||||
return self.default_language
|
||||
|
||||
def __get_show_metadata(self, id: int, language: str | None = None) -> dict:
|
||||
if language is None:
|
||||
language = self.default_language
|
||||
try:
|
||||
response = requests.get(url=f"{self.url}/tv/shows/{id}")
|
||||
response = requests.get(
|
||||
url=f"{self.url}/tv/shows/{id}",
|
||||
params={"language": language}
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
@@ -40,10 +59,13 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
)
|
||||
raise
|
||||
|
||||
def __get_season_metadata(self, show_id: int, season_number: int) -> dict:
|
||||
def __get_season_metadata(self, show_id: int, season_number: int, language: str | None = None) -> dict:
|
||||
if language is None:
|
||||
language = self.default_language
|
||||
try:
|
||||
response = requests.get(
|
||||
url=f"{self.url}/tv/shows/{show_id}/{season_number}"
|
||||
url=f"{self.url}/tv/shows/{show_id}/{season_number}",
|
||||
params={"language": language}
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
@@ -80,7 +102,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
|
||||
def __get_trending_tv(self) -> dict:
|
||||
try:
|
||||
response = requests.get(url=f"{self.url}/tv/trending")
|
||||
response = requests.get(url=f"{self.url}/tv/trending", params={"language": self.default_language})
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
@@ -92,9 +114,14 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
)
|
||||
raise
|
||||
|
||||
def __get_movie_metadata(self, id: int) -> dict:
|
||||
def __get_movie_metadata(self, id: int, language: str | None = None) -> dict:
|
||||
if language is None:
|
||||
language = self.default_language
|
||||
try:
|
||||
response = requests.get(url=f"{self.url}/movies/{id}")
|
||||
response = requests.get(
|
||||
url=f"{self.url}/movies/{id}",
|
||||
params={"language": language}
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
@@ -128,7 +155,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
|
||||
def __get_trending_movies(self) -> dict:
|
||||
try:
|
||||
response = requests.get(url=f"{self.url}/movies/trending")
|
||||
response = requests.get(url=f"{self.url}/movies/trending", params={"language": self.default_language})
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
@@ -141,7 +168,12 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
raise
|
||||
|
||||
def download_show_poster_image(self, show: Show) -> bool:
|
||||
show_metadata = self.__get_show_metadata(show.external_id)
|
||||
# Determine which language to use based on show's original_language
|
||||
language = self.__get_language_param(show.original_language)
|
||||
|
||||
# Fetch metadata in the appropriate language to get localized poster
|
||||
show_metadata = self.__get_show_metadata(show.external_id, language=language)
|
||||
|
||||
# downloading the poster
|
||||
# all pictures from TMDB should already be jpeg, so no need to convert
|
||||
if show_metadata["poster_path"] is not None:
|
||||
@@ -160,20 +192,34 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_show_metadata(self, id: int = None) -> Show:
|
||||
def get_show_metadata(self, id: int = None, language: str | None = None) -> Show:
|
||||
"""
|
||||
|
||||
:param id: the external id of the show
|
||||
:type id: int
|
||||
:return: returns a ShowMetadata object
|
||||
:rtype: ShowMetadata
|
||||
:param language: optional language code (ISO 639-1) to fetch metadata in
|
||||
:type language: str | None
|
||||
:return: returns a Show object
|
||||
:rtype: Show
|
||||
"""
|
||||
show_metadata = self.__get_show_metadata(id)
|
||||
# If language not provided, fetch once to determine original language
|
||||
if language is None:
|
||||
show_metadata = self.__get_show_metadata(id)
|
||||
language = show_metadata.get("original_language")
|
||||
|
||||
# Determine which language to use for metadata
|
||||
language = self.__get_language_param(language)
|
||||
|
||||
# Fetch show metadata in the appropriate language
|
||||
show_metadata = self.__get_show_metadata(id, language=language)
|
||||
|
||||
season_list = []
|
||||
# inserting all the metadata into the objects
|
||||
for season in show_metadata["seasons"]:
|
||||
season_metadata = self.__get_season_metadata(
|
||||
show_id=show_metadata["id"], season_number=season["season_number"]
|
||||
show_id=show_metadata["id"],
|
||||
season_number=season["season_number"],
|
||||
language=language
|
||||
)
|
||||
episode_list = []
|
||||
|
||||
@@ -208,6 +254,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
seasons=season_list,
|
||||
metadata_provider=self.name,
|
||||
ended=show_metadata["status"] in ENDED_STATUS,
|
||||
original_language=show_metadata.get("original_language"),
|
||||
)
|
||||
|
||||
return show
|
||||
@@ -240,11 +287,24 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
)
|
||||
else:
|
||||
poster_url = None
|
||||
|
||||
# Determine which name to use based on primary_languages
|
||||
original_language = result.get("original_language")
|
||||
original_name = result.get("original_name")
|
||||
display_name = result["name"]
|
||||
|
||||
overview = result["overview"]
|
||||
# Use original name if language is in primary_languages and skip overview
|
||||
if original_language and original_language in self.primary_languages:
|
||||
display_name = original_name
|
||||
overview = None
|
||||
|
||||
|
||||
formatted_results.append(
|
||||
MetaDataProviderSearchResult(
|
||||
poster_path=poster_url,
|
||||
overview=result["overview"],
|
||||
name=result["name"],
|
||||
overview=overview,
|
||||
name=display_name,
|
||||
external_id=result["id"],
|
||||
year=media_manager.metadataProvider.utils.get_year_from_date(
|
||||
result["first_air_date"]
|
||||
@@ -252,21 +312,35 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
metadata_provider=self.name,
|
||||
added=False,
|
||||
vote_average=result["vote_average"],
|
||||
original_language=original_language,
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(f"Error processing search result: {e}")
|
||||
return formatted_results
|
||||
|
||||
def get_movie_metadata(self, id: int = None) -> Movie:
|
||||
def get_movie_metadata(self, id: int = None, language: str | None = None) -> Movie:
|
||||
"""
|
||||
Get movie metadata with language-aware fetching.
|
||||
|
||||
:param id: the external id of the show
|
||||
:param id: the external id of the movie
|
||||
:type id: int
|
||||
:return: returns a ShowMetadata object
|
||||
:rtype: ShowMetadata
|
||||
:param language: optional language code (ISO 639-1) to fetch metadata in
|
||||
:type language: str | None
|
||||
:return: returns a Movie object
|
||||
:rtype: Movie
|
||||
"""
|
||||
movie_metadata = self.__get_movie_metadata(id=id)
|
||||
# If language not provided, fetch once to determine original language
|
||||
if language is None:
|
||||
movie_metadata = self.__get_movie_metadata(id=id)
|
||||
language = movie_metadata.get("original_language")
|
||||
|
||||
# Determine which language to use for metadata
|
||||
language = self.__get_language_param(language)
|
||||
|
||||
# Fetch movie metadata in the appropriate language
|
||||
movie_metadata = self.__get_movie_metadata(id=id, language=language)
|
||||
|
||||
year = media_manager.metadataProvider.utils.get_year_from_date(
|
||||
movie_metadata["release_date"]
|
||||
)
|
||||
@@ -277,6 +351,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
overview=movie_metadata["overview"],
|
||||
year=year,
|
||||
metadata_provider=self.name,
|
||||
original_language=movie_metadata.get("original_language"),
|
||||
)
|
||||
|
||||
return movie
|
||||
@@ -309,11 +384,23 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
)
|
||||
else:
|
||||
poster_url = None
|
||||
|
||||
# Determine which name to use based on primary_languages
|
||||
original_language = result.get("original_language")
|
||||
original_title = result.get("original_title")
|
||||
display_name = result["title"]
|
||||
|
||||
overview = result["overview"]
|
||||
# Use original name if language is in primary_languages and skip overview
|
||||
if original_language and original_language in self.primary_languages:
|
||||
display_name = original_title
|
||||
overview = None
|
||||
|
||||
formatted_results.append(
|
||||
MetaDataProviderSearchResult(
|
||||
poster_path=poster_url,
|
||||
overview=result["overview"],
|
||||
name=result["title"],
|
||||
overview=overview,
|
||||
name=display_name,
|
||||
external_id=result["id"],
|
||||
year=media_manager.metadataProvider.utils.get_year_from_date(
|
||||
result["release_date"]
|
||||
@@ -321,6 +408,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
metadata_provider=self.name,
|
||||
added=False,
|
||||
vote_average=result["vote_average"],
|
||||
original_language=original_language,
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
@@ -328,7 +416,12 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
return formatted_results
|
||||
|
||||
def download_movie_poster_image(self, movie: Movie) -> bool:
|
||||
movie_metadata = self.__get_movie_metadata(id=movie.external_id)
|
||||
# Determine which language to use based on movie's original_language
|
||||
language = self.__get_language_param(movie.original_language)
|
||||
|
||||
# Fetch metadata in the appropriate language to get localized poster
|
||||
movie_metadata = self.__get_movie_metadata(id=movie.external_id, language=language)
|
||||
|
||||
# downloading the poster
|
||||
# all pictures from TMDB should already be jpeg, so no need to convert
|
||||
if movie_metadata["poster_path"] is not None:
|
||||
@@ -338,11 +431,11 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
if media_manager.metadataProvider.utils.download_poster_image(
|
||||
storage_path=self.storage_path, poster_url=poster_url, id=movie.id
|
||||
):
|
||||
log.info("Successfully downloaded poster image for show " + movie.name)
|
||||
log.info("Successfully downloaded poster image for movie " + movie.name)
|
||||
else:
|
||||
log.warning(f"download for image of show {movie.name} failed")
|
||||
log.warning(f"download for image of movie {movie.name} failed")
|
||||
return False
|
||||
else:
|
||||
log.warning(f"image for show {movie.name} could not be downloaded")
|
||||
log.warning(f"image for movie {movie.name} could not be downloaded")
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -19,6 +19,7 @@ class Movie(Base):
|
||||
overview: Mapped[str]
|
||||
year: Mapped[int | None]
|
||||
library: Mapped[str] = mapped_column(default="")
|
||||
original_language: Mapped[str | None] = mapped_column(default=None)
|
||||
movie_requests: Mapped[list["MovieRequest"]] = relationship(
|
||||
"MovieRequest", back_populates="movie", cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
@@ -115,6 +115,7 @@ class MovieRepository:
|
||||
db_movie.name = movie.name
|
||||
db_movie.overview = movie.overview
|
||||
db_movie.year = movie.year
|
||||
db_movie.original_language = movie.original_language
|
||||
else: # Insert new movie
|
||||
log.debug(f"Creating new movie: {movie.name}")
|
||||
db_movie = Movie(**movie.model_dump())
|
||||
|
||||
@@ -56,11 +56,13 @@ def add_a_movie(
|
||||
movie_service: movie_service_dep,
|
||||
metadata_provider: metadata_provider_dep,
|
||||
movie_id: int,
|
||||
language: str | None = None,
|
||||
):
|
||||
try:
|
||||
movie = movie_service.add_movie(
|
||||
external_id=movie_id,
|
||||
metadata_provider=metadata_provider,
|
||||
language=language,
|
||||
)
|
||||
except ValueError:
|
||||
movie = movie_service.get_movie_by_external_id(
|
||||
|
||||
@@ -23,6 +23,7 @@ class Movie(BaseModel):
|
||||
external_id: int
|
||||
metadata_provider: str
|
||||
library: str = "Default"
|
||||
original_language: str | None = None
|
||||
|
||||
|
||||
class MovieFile(BaseModel):
|
||||
|
||||
@@ -63,15 +63,16 @@ class MovieService:
|
||||
self.notification_service = notification_service
|
||||
|
||||
def add_movie(
|
||||
self, external_id: int, metadata_provider: AbstractMetadataProvider
|
||||
self, external_id: int, metadata_provider: AbstractMetadataProvider, language: str | None = None
|
||||
) -> Movie | None:
|
||||
"""
|
||||
Add a new movie to the database.
|
||||
|
||||
:param external_id: The ID of the movie in the metadata provider's system.
|
||||
:param metadata_provider: The name of the metadata provider.
|
||||
:param language: Optional language code (ISO 639-1) to fetch metadata in.
|
||||
"""
|
||||
movie_with_metadata = metadata_provider.get_movie_metadata(id=external_id)
|
||||
movie_with_metadata = metadata_provider.get_movie_metadata(id=external_id, language=language)
|
||||
saved_movie = self.movie_repository.save_movie(movie=movie_with_metadata)
|
||||
metadata_provider.download_movie_poster_image(movie=saved_movie)
|
||||
return saved_movie
|
||||
@@ -697,7 +698,8 @@ class MovieService:
|
||||
"""
|
||||
log.debug(f"Found movie: {db_movie.name} for metadata update.")
|
||||
|
||||
fresh_movie_data = metadata_provider.get_movie_metadata(id=db_movie.external_id)
|
||||
# Use stored original_language preference for metadata fetching
|
||||
fresh_movie_data = metadata_provider.get_movie_metadata(id=db_movie.external_id, language=db_movie.original_language)
|
||||
if not fresh_movie_data:
|
||||
log.warning(
|
||||
f"Could not fetch fresh metadata for movie {db_movie.name} (External ID: {db_movie.external_id}) from {db_movie.metadata_provider}."
|
||||
|
||||
@@ -21,6 +21,7 @@ class Show(Base):
|
||||
ended: Mapped[bool] = mapped_column(default=False)
|
||||
continuous_download: Mapped[bool] = mapped_column(default=False)
|
||||
library: Mapped[str] = mapped_column(default="")
|
||||
original_language: Mapped[str | None] = mapped_column(default=None)
|
||||
|
||||
seasons: Mapped[list["Season"]] = relationship(
|
||||
back_populates="show", cascade="all, delete"
|
||||
|
||||
@@ -135,6 +135,7 @@ class TvRepository:
|
||||
db_show.name = show.name
|
||||
db_show.overview = show.overview
|
||||
db_show.year = show.year
|
||||
db_show.original_language = show.original_language
|
||||
else: # Insert new show
|
||||
db_show = Show(
|
||||
id=show.id,
|
||||
@@ -144,6 +145,7 @@ class TvRepository:
|
||||
overview=show.overview,
|
||||
year=show.year,
|
||||
ended=show.ended,
|
||||
original_language=show.original_language,
|
||||
seasons=[
|
||||
Season(
|
||||
id=season.id,
|
||||
|
||||
@@ -58,12 +58,13 @@ router = APIRouter()
|
||||
},
|
||||
)
|
||||
def add_a_show(
|
||||
tv_service: tv_service_dep, metadata_provider: metadata_provider_dep, show_id: int
|
||||
tv_service: tv_service_dep, metadata_provider: metadata_provider_dep, show_id: int, language: str | None = None
|
||||
):
|
||||
try:
|
||||
show = tv_service.add_show(
|
||||
external_id=show_id,
|
||||
metadata_provider=metadata_provider,
|
||||
language=language,
|
||||
)
|
||||
except MediaAlreadyExists:
|
||||
show = tv_service.get_show_by_external_id(
|
||||
|
||||
@@ -55,6 +55,7 @@ class Show(BaseModel):
|
||||
|
||||
continuous_download: bool = False
|
||||
library: str = "Default"
|
||||
original_language: str | None = None
|
||||
|
||||
seasons: list[Season]
|
||||
|
||||
|
||||
@@ -69,15 +69,16 @@ class TvService:
|
||||
self.notification_service = notification_service
|
||||
|
||||
def add_show(
|
||||
self, external_id: int, metadata_provider: AbstractMetadataProvider
|
||||
self, external_id: int, metadata_provider: AbstractMetadataProvider, language: str | None = None
|
||||
) -> Show | None:
|
||||
"""
|
||||
Add a new show to the database.
|
||||
|
||||
:param external_id: The ID of the show in the metadata provider\\\'s system.
|
||||
:param external_id: The ID of the show in the metadata provider\'s system.
|
||||
:param metadata_provider: The name of the metadata provider.
|
||||
:param language: Optional language code (ISO 639-1) to fetch metadata in.
|
||||
"""
|
||||
show_with_metadata = metadata_provider.get_show_metadata(id=external_id)
|
||||
show_with_metadata = metadata_provider.get_show_metadata(id=external_id, language=language)
|
||||
saved_show = self.tv_repository.save_show(show=show_with_metadata)
|
||||
metadata_provider.download_show_poster_image(show=saved_show)
|
||||
return saved_show
|
||||
@@ -756,7 +757,8 @@ class TvService:
|
||||
log.debug(f"Found show: {db_show.name} for metadata update.")
|
||||
# old_poster_url = db_show.poster_url # poster_url removed from db_show
|
||||
|
||||
fresh_show_data = metadata_provider.get_show_metadata(id=db_show.external_id)
|
||||
# Use stored original_language preference for metadata fetching
|
||||
fresh_show_data = metadata_provider.get_show_metadata(id=db_show.external_id, language=db_show.original_language)
|
||||
if not fresh_show_data:
|
||||
log.warning(
|
||||
f"Could not fetch fresh metadata for show {db_show.name} (External ID: {db_show.external_id}) from {db_show.metadata_provider}."
|
||||
|
||||
@@ -16,29 +16,29 @@ else:
|
||||
tmdbsimple.API_KEY = tmdb_api_key
|
||||
|
||||
@router.get("/tv/trending")
|
||||
async def get_tmdb_trending_tv():
|
||||
return Trending(media_type="tv").info()
|
||||
async def get_tmdb_trending_tv(language: str = "en"):
|
||||
return Trending(media_type="tv").info(language=language)
|
||||
|
||||
@router.get("/tv/search")
|
||||
async def search_tmdb_tv(query: str, page: int = 1):
|
||||
return Search().tv(page=page, query=query)
|
||||
async def search_tmdb_tv(query: str, page: int = 1, language: str = "en"):
|
||||
return Search().tv(page=page, query=query, language=language)
|
||||
|
||||
@router.get("/tv/shows/{show_id}")
|
||||
async def get_tmdb_show(show_id: int):
|
||||
return TV(show_id).info()
|
||||
async def get_tmdb_show(show_id: int, language: str = "en"):
|
||||
return TV(show_id).info(language=language)
|
||||
|
||||
@router.get("/tv/shows/{show_id}/{season_number}")
|
||||
async def get_tmdb_season(season_number: int, show_id: int):
|
||||
return TV_Seasons(season_number=season_number, tv_id=show_id).info()
|
||||
async def get_tmdb_season(season_number: int, show_id: int, language: str = "en"):
|
||||
return TV_Seasons(season_number=season_number, tv_id=show_id).info(language=language)
|
||||
|
||||
@router.get("/movies/trending")
|
||||
async def get_tmdb_trending_movies():
|
||||
return Trending(media_type="movie").info()
|
||||
async def get_tmdb_trending_movies(language: str = "en"):
|
||||
return Trending(media_type="movie").info(language=language)
|
||||
|
||||
@router.get("/movies/search")
|
||||
async def search_tmdb_movies(query: str, page: int = 1):
|
||||
return Search().movie(page=page, query=query)
|
||||
async def search_tmdb_movies(query: str, page: int = 1, language: str = "en"):
|
||||
return Search().movie(page=page, query=query, language=language)
|
||||
|
||||
@router.get("/movies/{movie_id}")
|
||||
async def get_tmdb_movie(movie_id: int):
|
||||
return Movies(movie_id).info()
|
||||
async def get_tmdb_movie(movie_id: int, language: str = "en"):
|
||||
return Movies(movie_id).info(language=language)
|
||||
|
||||
10
web/src/lib/api/api.d.ts
vendored
10
web/src/lib/api/api.d.ts
vendored
@@ -1309,6 +1309,8 @@ export interface components {
|
||||
added: boolean;
|
||||
/** Vote Average */
|
||||
vote_average?: number | null;
|
||||
/** Original Language */
|
||||
original_language?: string | null;
|
||||
/** Id */
|
||||
id?: string | null;
|
||||
};
|
||||
@@ -1334,6 +1336,8 @@ export interface components {
|
||||
* @default Default
|
||||
*/
|
||||
library: string;
|
||||
/** Original Language */
|
||||
original_language?: string | null;
|
||||
};
|
||||
/** MovieRequest */
|
||||
MovieRequest: {
|
||||
@@ -1433,6 +1437,8 @@ export interface components {
|
||||
* @default Default
|
||||
*/
|
||||
library: string;
|
||||
/** Original Language */
|
||||
original_language?: string | null;
|
||||
/**
|
||||
* Downloaded
|
||||
* @default false
|
||||
@@ -1689,6 +1695,8 @@ export interface components {
|
||||
* @default Default
|
||||
*/
|
||||
library: string;
|
||||
/** Original Language */
|
||||
original_language?: string | null;
|
||||
/** Seasons */
|
||||
seasons: components['schemas']['Season'][];
|
||||
};
|
||||
@@ -2565,6 +2573,7 @@ export interface operations {
|
||||
parameters: {
|
||||
query: {
|
||||
show_id: number;
|
||||
language?: string | null;
|
||||
metadata_provider?: 'tmdb' | 'tvdb';
|
||||
};
|
||||
header?: never;
|
||||
@@ -3417,6 +3426,7 @@ export interface operations {
|
||||
parameters: {
|
||||
query: {
|
||||
movie_id: number;
|
||||
language?: string | null;
|
||||
metadata_provider?: 'tmdb' | 'tvdb';
|
||||
};
|
||||
header?: never;
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
params: {
|
||||
query: {
|
||||
show_id: result.external_id,
|
||||
metadata_provider: result.metadata_provider as 'tmdb' | 'tvdb'
|
||||
metadata_provider: result.metadata_provider as 'tmdb' | 'tvdb',
|
||||
language: result.original_language ?? undefined
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -32,7 +33,8 @@
|
||||
params: {
|
||||
query: {
|
||||
movie_id: result.external_id,
|
||||
metadata_provider: result.metadata_provider as 'tmdb' | 'tvdb'
|
||||
metadata_provider: result.metadata_provider as 'tmdb' | 'tvdb',
|
||||
language: result.original_language ?? undefined
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user