create metadataProvider Module and fix different logging formats

This commit is contained in:
maxDorninger
2025-03-25 22:28:04 +01:00
parent eb044c9d6b
commit f347a36767
5 changed files with 168 additions and 39 deletions

View File

@@ -1,4 +1,3 @@
import logging
import os
from typing import Literal
@@ -7,7 +6,7 @@ from pydantic import BaseModel
class DbConfig(BaseModel):
host: str = os.getenv("DB_HOST") or "localhost"
port: int = int(os.getenv("DB_PORT")) or 5432
port: int = int(os.getenv("DB_PORT") or 5432)
user: str = os.getenv("DB_USERNAME") or "MediaManager"
_password: str = os.getenv("DB_PASSWORD") or "MediaManager"
dbname: str = os.getenv("DB_NAME") or "MediaManager"
@@ -17,17 +16,15 @@ class DbConfig(BaseModel):
return self._password
class TvConfig(BaseModel):
api_key: str = os.getenv("TMDB_API_KEY")
class TmdbConfig(BaseModel):
api_key: str = os.getenv("TMDB_API_KEY") or None
class IndexerConfig(BaseModel):
default_indexer: Literal["tmdb"] = os.getenv("INDEXER") or "tmdb"
_default_indexer_api_key: str = os.getenv("INDEXER_API_KEY")
class BasicConfig(BaseModel):
storage_directory: str = os.getenv("STORAGE_FILE_PATH") or "."
class ProwlarrConfig(BaseModel):
enabled: bool = bool(os.getenv("PROWLARR_ENABLED")) or True
enabled: bool = bool(os.getenv("PROWLARR_ENABLED") or True)
api_key: str = os.getenv("PROWLARR_API_KEY")
url: str = os.getenv("PROWLARR_URL")
@@ -37,7 +34,7 @@ class AuthConfig(BaseModel):
# openssl rand -hex 32
_jwt_signing_key: str = os.getenv("JWT_SIGNING_KEY")
jwt_signing_algorithm: str = "HS256"
jwt_access_token_lifetime: int = int(os.getenv("JWT_ACCESS_TOKEN_LIFETIME")) or 60 * 24 * 30
jwt_access_token_lifetime: int = int(os.getenv("JWT_ACCESS_TOKEN_LIFETIME") or 60 * 24 * 30)
@property
def jwt_signing_key(self):
@@ -61,23 +58,3 @@ class MachineLearningConfig(BaseModel):
def get_db_config() -> DbConfig:
return DbConfig()
log = logging.getLogger(__name__)
def load_config():
log.info(f"loaded config: DbConfig: {DbConfig().__str__()}")
log.info(f"loaded config: IndexerConfig: {IndexerConfig().__str__()}")
log.info(f"loaded config: AuthConfig: {AuthConfig().__str__()}")
log.info(f"loaded config: TvConfig: {TvConfig().__str__()}")
if __name__ == "__main__":
db: DbConfig = DbConfig()
indexer: IndexerConfig = IndexerConfig()
auth: AuthConfig = AuthConfig()
print(db.__str__())
print(indexer.__str__())
print(auth.__str__())

View File

@@ -1,28 +1,52 @@
import logging
import sys
from logging.config import dictConfig
logging.basicConfig(level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(name)s - %(funcName)s(): %(message)s",
stream=sys.stdout,
)
log = logging.getLogger(__name__)
import uvicorn
from fastapi import FastAPI
import config
import database.users
import tv.router
from auth import password
from routers import users
logging.basicConfig(level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(name)s - %(funcName)s(): %(message)s",
stream=sys.stdout)
LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": True,
"formatters": {
"default": {
"format": "%(asctime)s - %(levelname)s - %(name)s - %(funcName)s(): %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "default",
"stream": sys.stdout,
},
},
"loggers": {
"uvicorn": {"handlers": ["console"], "level": "DEBUG"},
"uvicorn.access": {"handlers": ["console"], "level": "DEBUG"},
"fastapi": {"handlers": ["console"], "level": "DEBUG"},
"__main__": {"handlers": ["console"], "level": "DEBUG"},
},
}
# Apply logging config
dictConfig(LOGGING_CONFIG)
config.load_config()
database.init_db()
app = FastAPI(root_path="/api/v1")
app.include_router(users.router, tags=["users"])
app.include_router(password.router, tags=["authentication"])
app.include_router(tv.router.router, tags=["tv"])
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=5049)
uvicorn.run(app, host="127.0.0.1", port=5049, log_config=LOGGING_CONFIG)

View File

@@ -0,0 +1,13 @@
import logging
import metadataProvider.tmdb
from database.tv import Show
from metadataProvider.abstractMetaDataProvider import metadata_providers
log = logging.getLogger(__name__)
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)

View File

@@ -0,0 +1,27 @@
import logging
from abc import ABC, abstractmethod
import config
from database.tv import Show
log = logging.getLogger(__name__)
class MetadataProvider(ABC):
storage_path = config.BasicConfig().storage_directory
@property
@abstractmethod
def name(self) -> str:
pass
@abstractmethod
def get_show_metadata(self, id: int = None) -> Show:
pass
metadata_providers = {}
def register_metadata_provider(metadata_provider: MetadataProvider):
log.info("Registering metadata provider:" + metadata_provider.name)
metadata_providers[metadata_provider.name] = metadata_provider

View File

@@ -0,0 +1,88 @@
import logging
import mimetypes
import requests
import tmdbsimple
from tmdbsimple import TV, TV_Seasons
import config
from database.tv import Episode, Season, Show
from metadataProvider.abstractMetaDataProvider import MetadataProvider, register_metadata_provider
config = config.TmdbConfig()
log = logging.getLogger(__name__)
class TmdbMetadataProvider(MetadataProvider):
name = "tmdb"
def get_show_metadata(self, id: int = None) -> Show:
"""
:param id: the external id of the show
:type id: int
:return: returns a ShowMetadata object
:rtype: ShowMetadata
"""
show_metadata = TV(id).info()
season_list = []
# inserting all the metadata into the objects
for season in show_metadata["seasons"]:
season_metadata = TV_Seasons(tv_id=show_metadata["id"], season_number=season["season_number"]).info()
episode_list = []
for episode in season_metadata["episodes"]:
episode_list.append(
Episode(
external_id=int(episode["id"]),
title=episode["name"],
number=int(episode["episode_number"])
)
)
season_list.append(
Season(
external_id=int(season_metadata["id"]),
name=season_metadata["name"],
overview=season_metadata["overview"],
number=int(season_metadata["season_number"]),
episodes=episode_list
)
)
year: str | None = show_metadata["first_air_date"]
if year:
year: int = int(year.split('-')[0])
else:
year = None
show = Show(
external_id=id,
name=show_metadata["name"],
overview=show_metadata["overview"],
year=year,
seasons=season_list,
metadata_provider=self.name,
)
# downloading the poster
poster_url = "https://image.tmdb.org/t/p/original" + show_metadata["poster_path"]
res = requests.get(poster_url, stream=True)
content_type = res.headers["content-type"]
file_extension = mimetypes.guess_extension(content_type)
if res.status_code == 200:
with open(f"{self.storage_path}/images/{show.id}{file_extension}", 'wb') as f:
f.write(res.content)
log.info(f"image for show {show.name} successfully downloaded")
else:
log.warning(f"image for show {show.name} could not be downloaded")
return show
def __init__(self, api_key: str = None):
tmdbsimple.API_KEY = api_key
if config.api_key is not None:
log.info("Registerng TMDB as metadata provider")
register_metadata_provider(metadata_provider=TmdbMetadataProvider(config.api_key))