mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-17 15:43:28 +02:00
switch metadataprovider module to dependency injection and update roadmap
This commit is contained in:
@@ -34,8 +34,8 @@ torrents and authentication.
|
||||
- [x] make API return proper error codes
|
||||
- [x] optimize images for web in the backend
|
||||
- [x] responsive ui
|
||||
- [x] automatically update metadata of shows
|
||||
- [ ] support for movies
|
||||
- [ ] automatically update metadata of shows
|
||||
- [ ] automatically download new seasons/episodes of shows
|
||||
- [ ] expand README with more information and a quickstart guide
|
||||
- [ ] add notification system
|
||||
@@ -43,6 +43,7 @@ torrents and authentication.
|
||||
- [ ] add check at startup if hardlinks work
|
||||
- [ ] add support for deluge and transmission
|
||||
- [ ] make indexer module multithreaded
|
||||
- [ ] improve reliability of scheduled tasks
|
||||
- [ ] _maybe_ rework the logo
|
||||
- [ ] _maybe_ add support for configuration via toml config file
|
||||
|
||||
|
||||
@@ -8,3 +8,9 @@ class NotFoundError(Exception):
|
||||
"""Custom exception for when an entity is not found."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class InvalidConfigError(Exception):
|
||||
"""Custom exception for when an entity is not found."""
|
||||
|
||||
pass
|
||||
@@ -1,37 +0,0 @@
|
||||
import logging
|
||||
from cachetools import TTLCache, cached
|
||||
|
||||
import media_manager.metadataProvider.tmdb as tmdb
|
||||
import media_manager.metadataProvider.tvdb as tvdb
|
||||
from media_manager.metadataProvider.abstractMetaDataProvider import metadata_providers
|
||||
from media_manager.metadataProvider.schemas import MetaDataProviderShowSearchResult
|
||||
from media_manager.tv.schemas import Show
|
||||
|
||||
_ = tvdb, tmdb
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
search_show_cache = TTLCache(maxsize=128, ttl=24 * 60 * 60) # Cache for 24 hours
|
||||
|
||||
|
||||
def get_show_metadata(id: int = None, provider: str = "tmdb") -> Show:
|
||||
if id is None or provider is None:
|
||||
raise ValueError("Show Metadata requires id and provider")
|
||||
return metadata_providers[provider].get_show_metadata(id)
|
||||
|
||||
|
||||
def download_show_poster_image(show: Show) -> bool:
|
||||
"""
|
||||
Downloads the poster image for a show.
|
||||
:param show: The show to download the poster image for.
|
||||
:return: True if the image was downloaded successfully, False otherwise.
|
||||
"""
|
||||
return metadata_providers[show.metadata_provider].download_show_poster_image(show)
|
||||
|
||||
@cached(search_show_cache)
|
||||
def search_show(
|
||||
query: str | None = None, provider: str = "tmdb"
|
||||
) -> list[MetaDataProviderShowSearchResult]:
|
||||
"""
|
||||
If no query is provided, it will return the most popular shows.
|
||||
"""
|
||||
return metadata_providers[provider].search_show(query)
|
||||
|
||||
@@ -18,11 +18,13 @@ class AbstractMetadataProvider(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def get_show_metadata(self, id: int = None) -> Show:
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
@abstractmethod
|
||||
def search_show(self, query) -> list[MetaDataProviderShowSearchResult]:
|
||||
pass
|
||||
def search_show(
|
||||
self, query: str | None = None
|
||||
) -> list[MetaDataProviderShowSearchResult]:
|
||||
raise NotImplementedError()
|
||||
|
||||
@abstractmethod
|
||||
def download_show_poster_image(self, show: Show) -> bool:
|
||||
@@ -31,7 +33,7 @@ class AbstractMetadataProvider(ABC):
|
||||
:param show: The show to download the poster image for.
|
||||
:return: True if the image was downloaded successfully, False otherwise.
|
||||
"""
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
metadata_providers = {}
|
||||
|
||||
36
media_manager/metadataProvider/dependencies.py
Normal file
36
media_manager/metadataProvider/dependencies.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from fastapi import Depends
|
||||
|
||||
from media_manager.exceptions import InvalidConfigError
|
||||
from fastapi.exceptions import HTTPException
|
||||
from media_manager.metadataProvider.tmdb import TmdbMetadataProvider
|
||||
from media_manager.metadataProvider.abstractMetaDataProvider import (
|
||||
AbstractMetadataProvider,
|
||||
)
|
||||
from media_manager.metadataProvider.tvdb import TvdbMetadataProvider
|
||||
|
||||
|
||||
def get_metadata_provider(
|
||||
metadata_provider: Literal["tmdb", "tvdb"] = "tmdb",
|
||||
) -> AbstractMetadataProvider:
|
||||
try:
|
||||
if metadata_provider == "tmdb":
|
||||
return TmdbMetadataProvider()
|
||||
elif metadata_provider == "tvdb":
|
||||
return TvdbMetadataProvider()
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Invalid metadata provider: {metadata_provider}. Supported providers are 'tmdb' and/or 'tvdb'.",
|
||||
)
|
||||
except InvalidConfigError as e:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"Metadata provider '{metadata_provider}' not configured: {str(e)}",
|
||||
)
|
||||
|
||||
|
||||
metadata_provider_dep = Annotated[
|
||||
AbstractMetadataProvider, Depends(get_metadata_provider)
|
||||
]
|
||||
@@ -5,9 +5,9 @@ from pydantic_settings import BaseSettings
|
||||
from tmdbsimple import TV, TV_Seasons
|
||||
|
||||
import media_manager.metadataProvider.utils
|
||||
from media_manager.exceptions import InvalidConfigError
|
||||
from media_manager.metadataProvider.abstractMetaDataProvider import (
|
||||
AbstractMetadataProvider,
|
||||
register_metadata_provider,
|
||||
)
|
||||
from media_manager.metadataProvider.schemas import MetaDataProviderShowSearchResult
|
||||
from media_manager.tv.schemas import Episode, Season, Show, SeasonNumber, EpisodeNumber
|
||||
@@ -19,7 +19,6 @@ class TmdbConfig(BaseSettings):
|
||||
|
||||
ENDED_STATUS = {"Ended", "Canceled"}
|
||||
|
||||
config = TmdbConfig()
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -27,7 +26,10 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
name = "tmdb"
|
||||
|
||||
def __init__(self, api_key: str = None):
|
||||
tmdbsimple.API_KEY = api_key
|
||||
config = TmdbConfig()
|
||||
if config.TMDB_API_KEY is None:
|
||||
raise InvalidConfigError("TMDB_API_KEY is not set")
|
||||
tmdbsimple.API_KEY = config.TMDB_API_KEY
|
||||
|
||||
def download_show_poster_image(self, show: Show) -> bool:
|
||||
show_metadata = TV(show.external_id).info()
|
||||
@@ -150,12 +152,4 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(f"Error processing search result {result}: {e}")
|
||||
return formatted_results
|
||||
|
||||
|
||||
|
||||
if config.TMDB_API_KEY is not None:
|
||||
log.info("Registering TMDB as metadata provider")
|
||||
register_metadata_provider(
|
||||
metadata_provider=TmdbMetadataProvider(config.TMDB_API_KEY)
|
||||
)
|
||||
return formatted_results
|
||||
@@ -6,6 +6,7 @@ import logging
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
import media_manager.metadataProvider.utils
|
||||
from media_manager.exceptions import InvalidConfigError
|
||||
from media_manager.metadataProvider.abstractMetaDataProvider import (
|
||||
AbstractMetadataProvider,
|
||||
register_metadata_provider,
|
||||
@@ -18,7 +19,6 @@ class TvdbConfig(BaseSettings):
|
||||
TVDB_API_KEY: str | None = None
|
||||
|
||||
|
||||
config = TvdbConfig()
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ class TvdbMetadataProvider(AbstractMetadataProvider):
|
||||
tvdb_client: tvdb_v4_official.TVDB
|
||||
|
||||
def __init__(self, api_key: str = None):
|
||||
self.tvdb_client = tvdb_v4_official.TVDB(api_key)
|
||||
config = TvdbConfig()
|
||||
if config.TVDB_API_KEY is None:
|
||||
raise InvalidConfigError("TVDB_API_KEY is not set")
|
||||
self.tvdb_client = tvdb_v4_official.TVDB(config.TVDB_API_KEY)
|
||||
|
||||
def download_show_poster_image(self, show: Show) -> bool:
|
||||
show_metadata = self.tvdb_client.get_series_extended(show.external_id)
|
||||
@@ -122,18 +125,4 @@ class TvdbMetadataProvider(AbstractMetadataProvider):
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(f"Error processing search result {result}: {e}")
|
||||
return formatted_results
|
||||
|
||||
|
||||
if config.TVDB_API_KEY is not None:
|
||||
log.info("Registering TVDB as metadata provider")
|
||||
register_metadata_provider(
|
||||
metadata_provider=TvdbMetadataProvider(config.TVDB_API_KEY)
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
tvdb = TvdbMetadataProvider(config.TVDB_API_KEY)
|
||||
# show_metadata = tvdb.get_show_metadata(id=328724) # Replace with a valid TVDB ID
|
||||
# pprint.pprint(dict(show_metadata))
|
||||
search_results = tvdb.search_show("Simpsons Declassified")
|
||||
pprint.pprint(search_results)
|
||||
return formatted_results
|
||||
Reference in New Issue
Block a user