CI / test (push) Failing after 39s
Hjernen (party/brain) skriver kommentarer til løgnene, dømmer løgne (sandheden eller upassende), personlige drillerier og en slut-anmeldelse, alt i baggrunden med faste replikker som fallback. Udbyderen vælges med BRAIN_PROVIDER: anthropic (Claude), openai (OpenAI-kompatibel, fx Codex) eller ollama (fx Gemma). Rummets mikrofon er eksperimentel: storskærmen sender korte lydstumper til talegenkendelse (STT_PROVIDER), og kun et kort resumé af latter og udsagn huskes til hjernen. Musikken er nu lavet med en musikmodel. Claude-Session: https://claude.ai/code/session_01JmhJG6JnhXfzNiKv8f2vHu
125 lines
4.5 KiB
Python
125 lines
4.5 KiB
Python
"""Indstillinger. Alt der varierer mellem dev og drift kommer fra miljøvariabler."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def env(name, default=None):
|
|
return os.environ.get(name, default)
|
|
|
|
|
|
DEBUG = env("DJANGO_DEBUG", "false").lower() == "true"
|
|
SECRET_KEY = env("DJANGO_SECRET_KEY") or ("dev-only-not-secret" if DEBUG else None)
|
|
if not SECRET_KEY:
|
|
raise RuntimeError("DJANGO_SECRET_KEY skal sættes, når DEBUG er slået fra.")
|
|
|
|
PUBLIC_URL = env("PUBLIC_URL", "http://localhost:8000").rstrip("/")
|
|
ALLOWED_HOSTS = [h for h in env("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",") if h]
|
|
CSRF_TRUSTED_ORIGINS = [PUBLIC_URL]
|
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
|
USE_X_FORWARDED_HOST = True
|
|
SESSION_COOKIE_SECURE = CSRF_COOKIE_SECURE = PUBLIC_URL.startswith("https://")
|
|
|
|
# Authentik: forward-auth i NPMplus sætter X-authentik-*-headers på /host og /admin.
|
|
# Headerne stoles kun på, når forespørgslen kommer fra disse adresser.
|
|
TRUSTED_PROXIES = [h for h in env("TRUSTED_PROXIES", "127.0.0.1").split(",") if h]
|
|
HOST_ADMIN_GROUP = env("HOST_ADMIN_GROUP", "authentik Admins")
|
|
# Speaker (ElevenLabs). Uden nøgle kører spillet uden stemme.
|
|
ELEVENLABS_API_KEY = env("ELEVENLABS_API_KEY", "")
|
|
ELEVENLABS_VOICE_ID = env("ELEVENLABS_VOICE_ID", "")
|
|
ELEVENLABS_MODEL = env("ELEVENLABS_MODEL", "eleven_v4")
|
|
TTS_CACHE_DIR = env("TTS_CACHE_DIR", str(BASE_DIR / "tts-cache"))
|
|
|
|
# Spilhjernen (valgfri, udbyder-agnostisk, se party/brain/providers.py): anthropic | openai | ollama
|
|
BRAIN_PROVIDER = env("BRAIN_PROVIDER", "")
|
|
BRAIN_MODEL = env("BRAIN_MODEL", "")
|
|
BRAIN_API_KEY = env("BRAIN_API_KEY", "")
|
|
BRAIN_BASE_URL = env("BRAIN_BASE_URL", "")
|
|
BRAIN_EFFORT = env("BRAIN_EFFORT", "low") # kun Anthropic
|
|
BRAIN_TIMEOUT_FAST = float(env("BRAIN_TIMEOUT_FAST", "6")) # dommer, drillerier
|
|
BRAIN_TIMEOUT_SLOW = float(env("BRAIN_TIMEOUT_SLOW", "25")) # kommentarer, anmeldelse
|
|
|
|
# Rummets mikrofon (eksperimentel, slås til på storskærmen): elevenlabs | openai (Whisper-kompatibel)
|
|
STT_PROVIDER = env("STT_PROVIDER", "elevenlabs")
|
|
STT_API_KEY = env("STT_API_KEY", "") # tom = genbrug ELEVENLABS_API_KEY for elevenlabs
|
|
STT_BASE_URL = env("STT_BASE_URL", "")
|
|
STT_MODEL = env("STT_MODEL", "")
|
|
|
|
# Kun til lokal udvikling: lader som om denne bruger er logget ind som vært.
|
|
DEV_HOST_USER = env("DEV_HOST_USER") if DEBUG else None
|
|
|
|
INSTALLED_APPS = [
|
|
"django.contrib.admin",
|
|
"django.contrib.auth",
|
|
"django.contrib.contenttypes",
|
|
"django.contrib.sessions",
|
|
"django.contrib.messages",
|
|
"django.contrib.staticfiles",
|
|
"channels",
|
|
"fupogfakta",
|
|
"party",
|
|
]
|
|
|
|
MIDDLEWARE = [
|
|
"django.middleware.security.SecurityMiddleware",
|
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
"django.middleware.common.CommonMiddleware",
|
|
"django.middleware.csrf.CsrfViewMiddleware",
|
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
"party.auth.AuthentikHeaderMiddleware",
|
|
"django.contrib.messages.middleware.MessageMiddleware",
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
]
|
|
|
|
ROOT_URLCONF = "partyhub.urls"
|
|
ASGI_APPLICATION = "partyhub.asgi.application"
|
|
CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}}
|
|
|
|
TEMPLATES = [
|
|
{
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
"DIRS": [],
|
|
"APP_DIRS": True,
|
|
"OPTIONS": {
|
|
"context_processors": [
|
|
"django.template.context_processors.request",
|
|
"django.contrib.auth.context_processors.auth",
|
|
"django.contrib.messages.context_processors.messages",
|
|
],
|
|
},
|
|
},
|
|
]
|
|
|
|
DATABASES = {
|
|
"default": {
|
|
"ENGINE": "django.db.backends.sqlite3",
|
|
"NAME": env("DB_PATH", str(BASE_DIR / "db.sqlite3")),
|
|
}
|
|
}
|
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
|
|
LANGUAGE_CODE = "da"
|
|
TIME_ZONE = "Europe/Copenhagen"
|
|
USE_I18N = True
|
|
USE_TZ = True
|
|
|
|
STATIC_URL = "/static/"
|
|
STATIC_ROOT = env("STATIC_ROOT", str(BASE_DIR / "staticfiles"))
|
|
STORAGES = {
|
|
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
|
|
"staticfiles": {
|
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"
|
|
if DEBUG else "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
|
},
|
|
}
|
|
|
|
LOGGING = {
|
|
"version": 1,
|
|
"disable_existing_loggers": False,
|
|
"handlers": {"console": {"class": "logging.StreamHandler"}},
|
|
"root": {"handlers": ["console"], "level": "INFO"},
|
|
}
|