Compare commits
1 Commits
356cd00772
...
c7e078d758
| Author | SHA1 | Date | |
|---|---|---|---|
| c7e078d758 |
+2
-1
@@ -37,5 +37,6 @@ MAX_PARALLEL_DOWNLOADS=2
|
|||||||
# external services (all optional — backend degrades gracefully if unset)
|
# external services (all optional — backend degrades gracefully if unset)
|
||||||
# ML_SERVICE_URL=http://ml:9000
|
# ML_SERVICE_URL=http://ml:9000
|
||||||
# ACOUSTID_API_KEY=
|
# ACOUSTID_API_KEY=
|
||||||
MUSICBRAINZ_USER_AGENT=mcma-backend/0.1.0 ( https://github.com/your/repo )
|
# Sent to MusicBrainz/AcoustID as part of the User-Agent (MCMA/<version> ( <email> )).
|
||||||
|
# MUSICBRAINZ_OWNER_EMAIL=you@example.com
|
||||||
# YOUTUBE_COOKIES_PATH=/data/cookies.txt
|
# YOUTUBE_COOKIES_PATH=/data/cookies.txt
|
||||||
|
|||||||
+29
-1
@@ -5,12 +5,25 @@ development). Access the cached singleton via :func:`get_settings`.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
from importlib.metadata import PackageNotFoundError, version
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from pydantic import Field, SecretStr, field_validator
|
from pydantic import Field, SecretStr, field_validator
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
# App identity for outbound API calls (e.g. the MusicBrainz/AcoustID
|
||||||
|
# User-Agent). Name is fixed; version comes from the installed package.
|
||||||
|
APP_NAME = "MCMA"
|
||||||
|
_PROJECT_URL = "https://git.ollyhearn.ru/olly/mcma-backend"
|
||||||
|
|
||||||
|
|
||||||
|
def app_version() -> str:
|
||||||
|
try:
|
||||||
|
return version("mcma-backend")
|
||||||
|
except PackageNotFoundError:
|
||||||
|
return "0.0.0"
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
model_config = SettingsConfigDict(
|
model_config = SettingsConfigDict(
|
||||||
@@ -77,7 +90,12 @@ class Settings(BaseSettings):
|
|||||||
ml_service_url: str | None = None
|
ml_service_url: str | None = None
|
||||||
acoustid_api_key: SecretStr | None = None
|
acoustid_api_key: SecretStr | None = None
|
||||||
acoustid_api_url: str = "https://api.acoustid.org/v2/lookup"
|
acoustid_api_url: str = "https://api.acoustid.org/v2/lookup"
|
||||||
musicbrainz_user_agent: str = "mcma-backend/0.1.0 ( https://github.com/your/repo )"
|
# MusicBrainz/AcoustID require a meaningful User-Agent identifying the
|
||||||
|
# application and a way to contact its maintainer (see
|
||||||
|
# https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting). Self-hosted
|
||||||
|
# deployments should set their own contact email; see
|
||||||
|
# ``musicbrainz_user_agent`` below for how it's used.
|
||||||
|
musicbrainz_owner_email: str | None = None
|
||||||
youtube_cookies_path: Path | None = None
|
youtube_cookies_path: Path | None = None
|
||||||
|
|
||||||
# -- enrichment -------------------------------------------------------
|
# -- enrichment -------------------------------------------------------
|
||||||
@@ -96,6 +114,16 @@ class Settings(BaseSettings):
|
|||||||
def is_prod(self) -> bool:
|
def is_prod(self) -> bool:
|
||||||
return self.environment == "prod"
|
return self.environment == "prod"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def musicbrainz_user_agent(self) -> str:
|
||||||
|
"""User-Agent sent to MusicBrainz/AcoustID: ``MCMA/<version> ( <contact> )``.
|
||||||
|
|
||||||
|
Falls back to the project URL if the deployment hasn't set
|
||||||
|
``musicbrainz_owner_email``.
|
||||||
|
"""
|
||||||
|
contact = self.musicbrainz_owner_email or _PROJECT_URL
|
||||||
|
return f"{APP_NAME}/{app_version()} ( {contact} )"
|
||||||
|
|
||||||
|
|
||||||
@lru_cache
|
@lru_cache
|
||||||
def get_settings() -> Settings:
|
def get_settings() -> Settings:
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ from app.api.health import router as health_router
|
|||||||
from app.api.middleware import CorrelationIdMiddleware
|
from app.api.middleware import CorrelationIdMiddleware
|
||||||
from app.api.rest import subsonic_router
|
from app.api.rest import subsonic_router
|
||||||
from app.api.v1 import api_v1_router
|
from app.api.v1 import api_v1_router
|
||||||
from app.core.config import get_settings
|
from app.core.config import app_version, get_settings
|
||||||
from app.core.logging import configure_logging, get_logger
|
from app.core.logging import configure_logging, get_logger
|
||||||
from app.infrastructure.cache import close_redis
|
from app.infrastructure.cache import close_redis
|
||||||
from app.infrastructure.db import dispose_engine
|
from app.infrastructure.db import dispose_engine
|
||||||
@@ -34,7 +34,7 @@ def create_app() -> FastAPI:
|
|||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="mcma-backend",
|
title="mcma-backend",
|
||||||
version="0.1.0",
|
version=app_version(),
|
||||||
summary="Self-hosted, offline-first music service.",
|
summary="Self-hosted, offline-first music service.",
|
||||||
lifespan=lifespan,
|
lifespan=lifespan,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user