make all var names lower case and fix circular imports

This commit is contained in:
maxDorninger
2025-07-11 00:47:29 +02:00
parent 9173c3ad83
commit 9db9c85fc6
19 changed files with 119 additions and 110 deletions

View File

@@ -53,7 +53,7 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
async def on_after_forgot_password(
self, user: User, token: str, request: Optional[Request] = None
):
link = f"{AllEncompassingConfig().misc.FRONTEND_URL}login/reset-password?token={token}"
link = f"{AllEncompassingConfig().misc.frontend_url}login/reset-password?token={token}"
log.info(f"User {user.id} has forgot their password. Reset Link: {link}")
if not config.email_password_resets:
@@ -109,7 +109,7 @@ def get_jwt_strategy() -> JWTStrategy[models.UP, models.ID]:
class RedirectingCookieTransport(CookieTransport):
async def get_login_response(self, token: str) -> Response:
response = RedirectResponse(
str(AllEncompassingConfig().misc.FRONTEND_URL) + "dashboard",
str(AllEncompassingConfig().misc.frontend_url) + "dashboard",
status_code=status.HTTP_302_FOUND,
)
return self._set_login_cookie(response, token)

View File

@@ -1,10 +1,14 @@
import logging
import os
from pathlib import Path
from typing import Type, Tuple
from pydantic import AnyHttpUrl
from pydantic_settings import (
BaseSettings,
SettingsConfigDict,
PydanticBaseSettingsSource,
TomlConfigSettingsSource,
)
from media_manager.auth.config import AuthConfig
@@ -14,6 +18,18 @@ from media_manager.metadataProvider.config import MetadataProviderConfig
from media_manager.notification.config import NotificationConfig
from media_manager.torrent.config import TorrentConfig
log = logging.getLogger(__name__)
config_path = os.getenv("CONFIG_FILE")
if config_path is None:
log.info("No CONFIG_FILE environment variable set, using default config file path.")
config_path = Path(__file__).parent.parent / "data" / "config.toml"
else:
config_path = Path(config_path)
print("SERVAS CONFIG PATH: ", config_path)
log.info("Using config file path: %s", config_path)
class BasicConfig(BaseSettings):
image_directory: Path = Path(__file__).parent.parent / "data" / "images"
@@ -21,15 +37,15 @@ class BasicConfig(BaseSettings):
movie_directory: Path = Path(__file__).parent.parent / "data" / "movies"
torrent_directory: Path = Path(__file__).parent.parent / "data" / "torrents"
FRONTEND_URL: AnyHttpUrl = "http://localhost:3000/"
CORS_URLS: list[str] = []
DEVELOPMENT: bool = False
frontend_url: AnyHttpUrl = "http://localhost:3000/"
cors_urls: list[str] = []
development: bool = False
api_base_path: str = "/api/v1"
class AllEncompassingConfig(BaseSettings):
model_config = SettingsConfigDict(
toml_file=os.getenv("CONFIG_FILE", "./config.toml")
toml_file=config_path,
case_sensitive=False,
)
"""
This class is used to load all configurations from the environment variables.
@@ -42,3 +58,15 @@ class AllEncompassingConfig(BaseSettings):
indexers: IndexerConfig = IndexerConfig()
database: DbConfig = DbConfig()
auth: AuthConfig = AuthConfig()
@classmethod
def settings_customise_sources(
cls,
settings_cls: Type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
) -> Tuple[PydanticBaseSettingsSource, ...]:
return (TomlConfigSettingsSource(settings_cls),)

View File

@@ -14,15 +14,15 @@ config = AllEncompassingConfig().database
db_url = (
"postgresql+psycopg"
+ "://"
+ config.USER
+ config.user
+ ":"
+ config.PASSWORD
+ config.password
+ "@"
+ config.HOST
+ config.host
+ ":"
+ str(config.PORT)
+ str(config.port)
+ "/"
+ config.DBNAME
+ config.dbname
)
engine = create_engine(db_url, echo=False)

View File

@@ -2,8 +2,8 @@ from pydantic_settings import BaseSettings
class DbConfig(BaseSettings):
HOST: str = "localhost"
PORT: int = 5432
USER: str = "MediaManager"
PASSWORD: str = "MediaManager"
DBNAME: str = "MediaManager"
host: str
port: int = 5432
user: str = "MediaManager"
password: str = "MediaManager"
dbname: str = "MediaManager"

View File

@@ -1,16 +1,3 @@
import logging
from media_manager.config import AllEncompassingConfig
from media_manager.indexer.indexers.jackett import Jackett
from media_manager.indexer.indexers.generic import GenericIndexer
from media_manager.indexer.indexers.prowlarr import Prowlarr
log = logging.getLogger(__name__)
indexers: list[GenericIndexer] = []
config = AllEncompassingConfig()
if config.indexers.prowlarr.enabled:
indexers.append(Prowlarr())
if config.indexers.jackett.enabled:
indexers.append(Jackett())

View File

@@ -1,12 +1,26 @@
from media_manager.indexer import log, indexers
import logging
from media_manager.config import AllEncompassingConfig
from media_manager.indexer.indexers.generic import GenericIndexer
from media_manager.indexer.indexers.jackett import Jackett
from media_manager.indexer.indexers.prowlarr import Prowlarr
from media_manager.indexer.schemas import IndexerQueryResultId, IndexerQueryResult
from media_manager.indexer.repository import IndexerRepository
from media_manager.notification.manager import notification_manager
log = logging.getLogger(__name__)
class IndexerService:
def __init__(self, indexer_repository: IndexerRepository):
config = AllEncompassingConfig()
self.repository = indexer_repository
self.indexers: list[GenericIndexer] = []
if config.indexers.prowlarr.enabled:
self.indexers.append(Prowlarr())
if config.indexers.jackett.enabled:
self.indexers.append(Jackett())
def get_result(self, result_id: IndexerQueryResultId) -> IndexerQueryResult:
return self.repository.get_result(result_id=result_id)
@@ -24,7 +38,7 @@ class IndexerService:
results = []
failed_indexers = []
for indexer in indexers:
for indexer in self.indexers:
try:
indexer_results = indexer.search(query, is_tv=is_tv)
results.extend(indexer_results)

View File

@@ -100,7 +100,7 @@ from apscheduler.triggers.cron import CronTrigger # noqa: E402
init_db()
log.info("Database initialized")
config = AllEncompassingConfig()
if config.misc.DEVELOPMENT:
if config.misc.development:
config.misc.torrent_directory.mkdir(parents=True, exist_ok=True)
config.misc.tv_directory.mkdir(parents=True, exist_ok=True)
config.misc.movie_directory.mkdir(parents=True, exist_ok=True)
@@ -149,7 +149,7 @@ base_path = config.misc.api_base_path
log.info("Base Path for API: %s", base_path)
app = FastAPI(root_path=base_path, lifespan=lifespan)
origins = config.misc.CORS_URLS
origins = config.misc.cors_urls
log.info("CORS URLs activated for following origins:")
for origin in origins:
log.info(f" - {origin}")

View File

@@ -1,7 +1,12 @@
from pydantic_settings import BaseSettings
from media_manager.metadataProvider.tmdb import TmdbConfig
from media_manager.metadataProvider.tvdb import TvdbConfig
class TmdbConfig(BaseSettings):
tmdb_relay_url: str = "https://metadata-relay.maxid.me/tmdb"
class TvdbConfig(BaseSettings):
tvdb_relay_url: str = "https://metadata-relay.maxid.me/tvdb"
class MetadataProviderConfig(BaseSettings):

View File

@@ -1,7 +1,6 @@
import logging
import requests
from pydantic_settings import BaseSettings
import media_manager.metadataProvider.utils
from media_manager.config import AllEncompassingConfig
@@ -14,10 +13,6 @@ from media_manager.movies.schemas import Movie
from media_manager.notification.manager import notification_manager
class TmdbConfig(BaseSettings):
TMDB_RELAY_URL: str = "https://metadata-relay.maxid.me/tmdb"
ENDED_STATUS = {"Ended", "Canceled"}
log = logging.getLogger(__name__)
@@ -28,7 +23,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
def __init__(self):
config = AllEncompassingConfig().metadata.tmdb
self.url = config.TMDB_RELAY_URL
self.url = config.tmdb_relay_url
def __get_show_metadata(self, id: int) -> dict:
try:

View File

@@ -1,7 +1,6 @@
import requests
import logging
from pydantic_settings import BaseSettings
import media_manager.metadataProvider.utils
from media_manager.config import AllEncompassingConfig
@@ -13,10 +12,6 @@ from media_manager.tv.schemas import Episode, Season, Show, SeasonNumber
from media_manager.movies.schemas import Movie
class TvdbConfig(BaseSettings):
TVDB_RELAY_URL: str = "https://metadata-relay.maxid.me/tvdb"
log = logging.getLogger(__name__)
@@ -25,7 +20,7 @@ class TvdbMetadataProvider(AbstractMetadataProvider):
def __init__(self):
config = AllEncompassingConfig().metadata.tvdb
self.url = config.TVDB_RELAY_URL
self.url = config.tvdb_relay_url
def __get_show(self, id: int) -> dict:
return requests.get(f"{self.url}/tv/shows/{id}").json()

View File

@@ -1,10 +1,5 @@
from pydantic_settings import BaseSettings
from media_manager.notification.service_providers.email import EmailNotificationsConfig
from media_manager.notification.service_providers.gotify import GotifyConfig
from media_manager.notification.service_providers.ntfy import NtfyConfig
from media_manager.notification.service_providers.pushover import PushoverConfig
class EmailConfig(BaseSettings):
smtp_host: str = ""
@@ -15,6 +10,32 @@ class EmailConfig(BaseSettings):
use_tls: bool = False
class EmailNotificationsConfig(BaseSettings):
enabled: bool = False
emails: list[str] = [] # the email addresses to send notifications to
class GotifyConfig(BaseSettings):
enabled: bool = False
api_key: str | None = None
url: str | None = (
None # e.g. https://gotify.example.com (note lack of trailing slash)
)
class NtfyConfig(BaseSettings):
enabled: bool = False
url: str | None = (
None # e.g. https://ntfy.sh/your-topic (note lack of trailing slash)
)
class PushoverConfig(BaseSettings):
enabled: bool = False
api_key: str | None = None
user: str | None = None
class NotificationConfig(BaseSettings):
smtp_config: EmailConfig = EmailConfig()
email_notifications: EmailNotificationsConfig = EmailNotificationsConfig()

View File

@@ -37,7 +37,7 @@ class NotificationManager:
def _initialize_providers(self) -> None:
# Email provider
if self.config.email:
if self.config.email_notifications.enabled:
try:
self.providers.append(EmailNotificationServiceProvider())
logger.info("Email notification provider initialized")
@@ -45,7 +45,7 @@ class NotificationManager:
logger.error(f"Failed to initialize Email provider: {e}")
# Gotify provider
if self.config.gotify_api_key and self.config.gotify_url:
if self.config.gotify.enabled:
try:
self.providers.append(GotifyNotificationServiceProvider())
logger.info("Gotify notification provider initialized")
@@ -53,7 +53,7 @@ class NotificationManager:
logger.error(f"Failed to initialize Gotify provider: {e}")
# Ntfy provider
if self.config.ntfy_url:
if self.config.ntfy.enabled:
try:
self.providers.append(NtfyNotificationServiceProvider())
logger.info("Ntfy notification provider initialized")
@@ -61,7 +61,7 @@ class NotificationManager:
logger.error(f"Failed to initialize Ntfy provider: {e}")
# Pushover provider
if self.config.pushover_api_key and self.config.pushover_user:
if self.config.pushover.enabled:
try:
self.providers.append(PushoverNotificationServiceProvider())
logger.info("Pushover notification provider initialized")

View File

@@ -1,5 +1,3 @@
from pydantic_settings import BaseSettings
import media_manager.notification.utils
from media_manager.notification.schemas import MessageNotification
from media_manager.notification.service_providers.abstractNotificationServiceProvider import (
@@ -8,11 +6,6 @@ from media_manager.notification.service_providers.abstractNotificationServicePro
from media_manager.config import AllEncompassingConfig
class EmailNotificationsConfig(BaseSettings):
enabled: bool = False
emails: list[str] = [] # the email addresses to send notifications to
class EmailNotificationServiceProvider(AbstractNotificationServiceProvider):
def __init__(self):
self.config = AllEncompassingConfig().notifications.email_notifications

View File

@@ -1,5 +1,4 @@
import requests
from pydantic_settings import BaseSettings
from media_manager.config import AllEncompassingConfig
from media_manager.notification.schemas import MessageNotification
@@ -8,14 +7,6 @@ from media_manager.notification.service_providers.abstractNotificationServicePro
)
class GotifyConfig(BaseSettings):
enabled: bool = False
api_key: str | None = None
url: str | None = (
None # e.g. https://gotify.example.com (note lack of trailing slash)
)
class GotifyNotificationServiceProvider(AbstractNotificationServiceProvider):
"""
Gotify Notification Service Provider

View File

@@ -1,5 +1,4 @@
import requests
from pydantic_settings import BaseSettings
from media_manager.config import AllEncompassingConfig
from media_manager.notification.schemas import MessageNotification
@@ -8,13 +7,6 @@ from media_manager.notification.service_providers.abstractNotificationServicePro
)
class NtfyConfig(BaseSettings):
enabled: bool = False
url: str | None = (
None # e.g. https://ntfy.sh/your-topic (note lack of trailing slash)
)
class NtfyNotificationServiceProvider(AbstractNotificationServiceProvider):
"""
Ntfy Notification Service Provider

View File

@@ -1,5 +1,4 @@
import requests
from pydantic_settings import BaseSettings
from media_manager.config import AllEncompassingConfig
from media_manager.notification.schemas import MessageNotification
@@ -8,12 +7,6 @@ from media_manager.notification.service_providers.abstractNotificationServicePro
)
class PushoverConfig(BaseSettings):
enabled: bool = False
api_key: str | None = None
user: str | None = None
class PushoverNotificationServiceProvider(AbstractNotificationServiceProvider):
def __init__(self):
self.config = AllEncompassingConfig().notifications.pushover

View File

@@ -1,7 +1,21 @@
from pydantic_settings import BaseSettings
from pydantic_settings import BaseSettings, SettingsConfigDict
from media_manager.torrent.download_clients.qbittorrent import QbittorrentConfig
from media_manager.torrent.download_clients.sabnzbd import SabnzbdConfig
class QbittorrentConfig(BaseSettings):
model_config = SettingsConfigDict(env_prefix="QBITTORRENT_")
host: str = "localhost"
port: int = 8080
username: str = "admin"
password: str = "admin"
enabled: bool = False
class SabnzbdConfig(BaseSettings):
model_config = SettingsConfigDict(env_prefix="SABNZBD_")
host: str = "localhost"
port: int = 8080
api_key: str = ""
enabled: bool = False
class TorrentConfig(BaseSettings):

View File

@@ -4,7 +4,6 @@ import logging
import bencoder
import qbittorrentapi
import requests
from pydantic_settings import BaseSettings, SettingsConfigDict
from media_manager.config import AllEncompassingConfig
from media_manager.indexer.schemas import IndexerQueryResult
@@ -16,15 +15,6 @@ from media_manager.torrent.schemas import TorrentStatus, Torrent
log = logging.getLogger(__name__)
class QbittorrentConfig(BaseSettings):
model_config = SettingsConfigDict(env_prefix="QBITTORRENT_")
host: str = "localhost"
port: int = 8080
username: str = "admin"
password: str = "admin"
enabled: bool = False
class QbittorrentDownloadClient(AbstractDownloadClient):
DOWNLOADING_STATE = (
"allocating",

View File

@@ -1,5 +1,4 @@
import logging
from pydantic_settings import BaseSettings, SettingsConfigDict
from media_manager.config import AllEncompassingConfig
from media_manager.indexer.schemas import IndexerQueryResult
@@ -12,14 +11,6 @@ import sabnzbd_api
log = logging.getLogger(__name__)
class SabnzbdConfig(BaseSettings):
model_config = SettingsConfigDict(env_prefix="SABNZBD_")
host: str = "localhost"
port: int = 8080
api_key: str = ""
enabled: bool = False
class SabnzbdDownloadClient(AbstractDownloadClient):
DOWNLOADING_STATE = (
"Downloading",