mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-19 00:23:28 +02:00
Compare commits
6 Commits
fix-docker
...
make-conta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5761bc661 | ||
|
|
c45c9e5873 | ||
|
|
24fcba6bee | ||
|
|
d5994a9037 | ||
|
|
9e0d0c03c0 | ||
|
|
70ff8f6ace |
@@ -13,7 +13,7 @@ RUN env PUBLIC_VERSION=${VERSION} PUBLIC_API_URL=${BASE_PATH} BASE_PATH=${BASE_P
|
||||
FROM ghcr.io/astral-sh/uv:python3.13-trixie-slim AS base
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y ca-certificates bash libtorrent21 gcc bc locales postgresql media-types mailcap curl gzip unzip tar 7zip bzip2 unar && \
|
||||
apt-get install -y ca-certificates bash libtorrent21 gcc bc locales postgresql media-types mailcap curl gzip unzip tar 7zip bzip2 unar gosu && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -33,7 +33,6 @@ RUN chown -R mediamanager:mediamanager /app
|
||||
|
||||
USER mediamanager
|
||||
|
||||
# Set uv cache to a writable home directory and use copy mode for volume compatibility
|
||||
ENV UV_CACHE_DIR=/home/mediamanager/.cache/uv \
|
||||
UV_LINK_MODE=copy
|
||||
|
||||
@@ -47,6 +46,7 @@ ARG BASE_PATH=""
|
||||
LABEL author="github.com/maxdorninger"
|
||||
LABEL version=${VERSION}
|
||||
LABEL description="Docker image for MediaManager"
|
||||
USER root
|
||||
|
||||
ENV PUBLIC_VERSION=${VERSION} \
|
||||
CONFIG_DIR="/app/config" \
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* [Metadata Provider Configuration](advanced-features/metadata-provider-configuration.md)
|
||||
* [Custom port](advanced-features/custom-port.md)
|
||||
* [Follow symlinks in frontend files](advanced-features/follow-symlinks-in-frontend-files.md)
|
||||
* [Disable startup ascii art](advanced-featured/disable-startup-ascii-art.md)
|
||||
* [Disable startup ascii art](advanced-features/disable-startup-ascii-art.md)
|
||||
* [Troubleshooting](troubleshooting.md)
|
||||
* [API Reference](api-reference.md)
|
||||
* [Screenshots](screenshots.md)
|
||||
|
||||
@@ -21,13 +21,20 @@ LOG_FILE = Path(os.getenv("LOG_FILE", "/app/config/media_manager.log"))
|
||||
LOGGING_CONFIG = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"filters": {
|
||||
"correlation_id": {
|
||||
"()": "asgi_correlation_id.CorrelationIdFilter",
|
||||
"uuid_length": 32,
|
||||
"default_value": "-",
|
||||
},
|
||||
},
|
||||
"formatters": {
|
||||
"default": {
|
||||
"format": "%(asctime)s - %(levelname)s - %(name)s - %(funcName)s(): %(message)s"
|
||||
"format": "%(asctime)s - [%(correlation_id)s] %(levelname)s - %(name)s - %(funcName)s(): %(message)s"
|
||||
},
|
||||
"json": {
|
||||
"()": ISOJsonFormatter,
|
||||
"format": "%(asctime)s %(levelname)s %(name)s %(message)s",
|
||||
"format": "%(asctime)s %(correlation_id)s %(levelname)s %(name)s %(message)s",
|
||||
"rename_fields": {
|
||||
"levelname": "level",
|
||||
"asctime": "timestamp",
|
||||
@@ -39,11 +46,13 @@ LOGGING_CONFIG = {
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "default",
|
||||
"filters": ["correlation_id"],
|
||||
"stream": sys.stdout,
|
||||
},
|
||||
"file": {
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"formatter": "json",
|
||||
"filters": ["correlation_id"],
|
||||
"filename": str(LOG_FILE),
|
||||
"maxBytes": 10485760,
|
||||
"backupCount": 5,
|
||||
|
||||
@@ -2,6 +2,7 @@ import logging
|
||||
import os
|
||||
|
||||
import uvicorn
|
||||
from asgi_correlation_id import CorrelationIdMiddleware
|
||||
from fastapi import APIRouter, FastAPI, Request, Response
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
@@ -71,6 +72,7 @@ app.add_middleware(
|
||||
allow_credentials=True,
|
||||
allow_methods=["GET", "PUT", "POST", "DELETE", "PATCH", "HEAD", "OPTIONS"],
|
||||
)
|
||||
app.add_middleware(CorrelationIdMiddleware, header_name="X-Correlation-ID")
|
||||
api_app = APIRouter(prefix="/api/v1")
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import bencoder
|
||||
import libtorrent
|
||||
import patoolib
|
||||
import requests
|
||||
from pathvalidate import sanitize_filename
|
||||
from requests.exceptions import InvalidSchema
|
||||
|
||||
from media_manager.config import MediaManagerConfig
|
||||
@@ -132,7 +133,7 @@ def get_torrent_hash(torrent: IndexerQueryResult) -> str:
|
||||
:return: The hash of the torrent.
|
||||
"""
|
||||
torrent_filepath = (
|
||||
MediaManagerConfig().misc.torrent_directory / f"{torrent.title}.torrent"
|
||||
MediaManagerConfig().misc.torrent_directory / f"{sanitize_filename(torrent.title)}.torrent"
|
||||
)
|
||||
if torrent_filepath.exists():
|
||||
log.warning(f"Torrent file already exists at: {torrent_filepath}")
|
||||
|
||||
@@ -145,8 +145,30 @@ else
|
||||
echo "Config file found at: $CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# check if running as root, if yes, fix permissions
|
||||
if [ "$(id -u)" = '0' ]; then
|
||||
echo "Running as root. Ensuring file permissions for mediamanager user..."
|
||||
chown -R mediamanager:mediamanager "$CONFIG_DIR"
|
||||
|
||||
if [ -d "/data" ]; then
|
||||
if [ "$(stat -c '%U' /data)" != "mediamanager" ]; then
|
||||
echo "Fixing ownership of /data (this may take a while for large media libraries)..."
|
||||
chown -R mediamanager:mediamanager /data
|
||||
else
|
||||
echo "/data ownership is already correct."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Running as non-root user ($(id -u)). Skipping permission fixes."
|
||||
echo "Note: Ensure your host volumes are manually set to the correct permissions."
|
||||
fi
|
||||
|
||||
echo "Running DB migrations..."
|
||||
uv run alembic upgrade head
|
||||
if [ "$(id -u)" = '0' ]; then
|
||||
gosu mediamanager uv run alembic upgrade head
|
||||
else
|
||||
uv run alembic upgrade head
|
||||
fi
|
||||
|
||||
echo "Starting MediaManager backend service..."
|
||||
echo ""
|
||||
@@ -159,9 +181,16 @@ echo ""
|
||||
|
||||
DEVELOPMENT_MODE=${MEDIAMANAGER_MISC__DEVELOPMENT:-FALSE}
|
||||
PORT=${PORT:-8000}
|
||||
|
||||
if [ "$DEVELOPMENT_MODE" == "TRUE" ]; then
|
||||
echo "Development mode is enabled, enabling auto-reload..."
|
||||
uv run fastapi run /app/media_manager/main.py --port "$PORT" --proxy-headers --reload
|
||||
DEV_OPTIONS="--reload"
|
||||
else
|
||||
uv run fastapi run /app/media_manager/main.py --port "$PORT" --proxy-headers
|
||||
DEV_OPTIONS=""
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" = '0' ]; then
|
||||
exec gosu mediamanager uv run fastapi run /app/media_manager/main.py --port "$PORT" --proxy-headers $DEV_OPTIONS
|
||||
else
|
||||
exec uv run fastapi run /app/media_manager/main.py --port "$PORT" --proxy-headers $DEV_OPTIONS
|
||||
fi
|
||||
@@ -8,23 +8,25 @@ RUN apt-get update && apt-get install -y ca-certificates && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create a non-root user and group
|
||||
RUN groupadd -g 1000 mediamanager && \
|
||||
useradd -m -u 1000 -g mediamanager mediamanager
|
||||
|
||||
WORKDIR /app
|
||||
# Ensure mediamanager owns the app directory
|
||||
RUN chown -R mediamanager:mediamanager /app
|
||||
|
||||
USER mediamanager
|
||||
|
||||
# Set uv cache to a writable home directory and use copy mode for volume compatibility
|
||||
ENV UV_CACHE_DIR=/home/mediamanager/.cache/uv \
|
||||
UV_LINK_MODE=copy
|
||||
UV_LINK_MODE=copy \
|
||||
UV_COMPILE_BYTECODE=1
|
||||
|
||||
COPY --chown=mediamanager:mediamanager pyproject.toml uv.lock ./
|
||||
|
||||
USER mediamanager
|
||||
RUN --mount=type=cache,target=/home/mediamanager/.cache/uv,uid=1000,gid=1000 \
|
||||
uv sync --frozen --no-install-project --no-dev
|
||||
|
||||
COPY --chown=mediamanager:mediamanager . .
|
||||
RUN --mount=type=cache,target=/home/mediamanager/.cache/uv,uid=1000,gid=1000 \
|
||||
uv sync --locked
|
||||
|
||||
RUN uv sync --frozen --no-dev
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["uv", "run", "fastapi", "run", "/app/main.py"]
|
||||
CMD ["uv", "run", "fastapi", "run", "/app/main.py", "--port", "8000", "--proxy-headers"]
|
||||
@@ -33,6 +33,8 @@ dependencies = [
|
||||
"sabnzbd-api>=0.1.2",
|
||||
"transmission-rpc>=7.0.11",
|
||||
"libtorrent>=2.0.11",
|
||||
"pathvalidate>=3.3.1",
|
||||
"asgi-correlation-id>=4.3.4",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
|
||||
26
uv.lock
generated
26
uv.lock
generated
@@ -105,6 +105,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asgi-correlation-id"
|
||||
version = "4.3.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "packaging" },
|
||||
{ name = "starlette" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f4/ff/a6538245ac1eaa7733ec6740774e9d5add019e2c63caa29e758c16c0afdd/asgi_correlation_id-4.3.4.tar.gz", hash = "sha256:ea6bc310380373cb9f731dc2e8b2b6fb978a76afe33f7a2384f697b8d6cd811d", size = 20075, upload-time = "2024-10-17T11:44:30.324Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/ab/6936e2663c47a926e0659437b9333ad87d1ff49b1375d239026e0a268eba/asgi_correlation_id-4.3.4-py3-none-any.whl", hash = "sha256:36ce69b06c7d96b4acb89c7556a4c4f01a972463d3d49c675026cbbd08e9a0a2", size = 15262, upload-time = "2024-10-17T11:44:28.739Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "25.4.0"
|
||||
@@ -854,6 +867,7 @@ source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "alembic" },
|
||||
{ name = "apscheduler" },
|
||||
{ name = "asgi-correlation-id" },
|
||||
{ name = "bencoder" },
|
||||
{ name = "cachetools" },
|
||||
{ name = "fastapi", extra = ["standard"] },
|
||||
@@ -864,6 +878,7 @@ dependencies = [
|
||||
{ name = "httpx-oauth" },
|
||||
{ name = "jsonschema" },
|
||||
{ name = "libtorrent" },
|
||||
{ name = "pathvalidate" },
|
||||
{ name = "patool" },
|
||||
{ name = "pillow" },
|
||||
{ name = "psycopg", extra = ["binary"] },
|
||||
@@ -893,6 +908,7 @@ dev = [
|
||||
requires-dist = [
|
||||
{ name = "alembic", specifier = ">=1.16.1" },
|
||||
{ name = "apscheduler", specifier = ">=3.11.0" },
|
||||
{ name = "asgi-correlation-id", specifier = ">=4.3.4" },
|
||||
{ name = "bencoder", specifier = ">=0.2.0" },
|
||||
{ name = "cachetools", specifier = ">=6.0.0" },
|
||||
{ name = "fastapi", extras = ["standard"], specifier = ">=0.115.12" },
|
||||
@@ -903,6 +919,7 @@ requires-dist = [
|
||||
{ name = "httpx-oauth", specifier = ">=0.16.1" },
|
||||
{ name = "jsonschema", specifier = ">=4.24.0" },
|
||||
{ name = "libtorrent", specifier = ">=2.0.11" },
|
||||
{ name = "pathvalidate", specifier = ">=3.3.1" },
|
||||
{ name = "patool", specifier = ">=4.0.1" },
|
||||
{ name = "pillow", specifier = ">=11.3.0" },
|
||||
{ name = "psycopg", extras = ["binary"], specifier = ">=3.2.9" },
|
||||
@@ -946,6 +963,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathvalidate"
|
||||
version = "3.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fa/2a/52a8da6fe965dea6192eb716b357558e103aea0a1e9a8352ad575a8406ca/pathvalidate-3.3.1.tar.gz", hash = "sha256:b18c07212bfead624345bb8e1d6141cdcf15a39736994ea0b94035ad2b1ba177", size = 63262, upload-time = "2025-06-15T09:07:20.736Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/70/875f4a23bfc4731703a5835487d0d2fb999031bd415e7d17c0ae615c18b7/pathvalidate-3.3.1-py3-none-any.whl", hash = "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f", size = 24305, upload-time = "2025-06-15T09:07:19.117Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "patool"
|
||||
version = "4.0.3"
|
||||
|
||||
92
web/package-lock.json
generated
92
web/package-lock.json
generated
@@ -146,6 +146,7 @@
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -163,6 +164,7 @@
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -180,6 +182,7 @@
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -197,6 +200,7 @@
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -214,6 +218,7 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -231,6 +236,7 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -248,6 +254,7 @@
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -265,6 +272,7 @@
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -282,6 +290,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -299,6 +308,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -316,6 +326,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -333,6 +344,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -350,6 +362,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -367,6 +380,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -384,6 +398,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -401,6 +416,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -418,6 +434,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -435,6 +452,7 @@
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -452,6 +470,7 @@
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -469,6 +488,7 @@
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -486,6 +506,7 @@
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -503,6 +524,7 @@
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -520,6 +542,7 @@
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -537,6 +560,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -554,6 +578,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -571,6 +596,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -1974,7 +2000,6 @@
|
||||
"integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@sveltejs/acorn-typescript": "^1.0.5",
|
||||
@@ -2014,7 +2039,6 @@
|
||||
"integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
|
||||
"debug": "^4.4.1",
|
||||
@@ -2485,7 +2509,6 @@
|
||||
"integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.49.0",
|
||||
"@typescript-eslint/types": "8.49.0",
|
||||
@@ -2732,7 +2755,6 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -2973,7 +2995,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.9.0",
|
||||
"caniuse-lite": "^1.0.30001759",
|
||||
@@ -3086,7 +3107,6 @@
|
||||
"integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/validator": "^13.15.3",
|
||||
"libphonenumber-js": "^1.11.1",
|
||||
@@ -3270,8 +3290,7 @@
|
||||
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz",
|
||||
"integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/embla-carousel-reactive-utils": {
|
||||
"version": "8.6.0",
|
||||
@@ -3311,6 +3330,50 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
|
||||
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.27.2",
|
||||
"@esbuild/android-arm": "0.27.2",
|
||||
"@esbuild/android-arm64": "0.27.2",
|
||||
"@esbuild/android-x64": "0.27.2",
|
||||
"@esbuild/darwin-arm64": "0.27.2",
|
||||
"@esbuild/darwin-x64": "0.27.2",
|
||||
"@esbuild/freebsd-arm64": "0.27.2",
|
||||
"@esbuild/freebsd-x64": "0.27.2",
|
||||
"@esbuild/linux-arm": "0.27.2",
|
||||
"@esbuild/linux-arm64": "0.27.2",
|
||||
"@esbuild/linux-ia32": "0.27.2",
|
||||
"@esbuild/linux-loong64": "0.27.2",
|
||||
"@esbuild/linux-mips64el": "0.27.2",
|
||||
"@esbuild/linux-ppc64": "0.27.2",
|
||||
"@esbuild/linux-riscv64": "0.27.2",
|
||||
"@esbuild/linux-s390x": "0.27.2",
|
||||
"@esbuild/linux-x64": "0.27.2",
|
||||
"@esbuild/netbsd-arm64": "0.27.2",
|
||||
"@esbuild/netbsd-x64": "0.27.2",
|
||||
"@esbuild/openbsd-arm64": "0.27.2",
|
||||
"@esbuild/openbsd-x64": "0.27.2",
|
||||
"@esbuild/openharmony-arm64": "0.27.2",
|
||||
"@esbuild/sunos-x64": "0.27.2",
|
||||
"@esbuild/win32-arm64": "0.27.2",
|
||||
"@esbuild/win32-ia32": "0.27.2",
|
||||
"@esbuild/win32-x64": "0.27.2"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-runner": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-runner/-/esbuild-runner-2.2.2.tgz",
|
||||
@@ -3366,7 +3429,6 @@
|
||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -4815,7 +4877,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -4956,7 +5017,6 @@
|
||||
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -4973,7 +5033,6 @@
|
||||
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"prettier": "^3.0.0",
|
||||
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
|
||||
@@ -5133,7 +5192,6 @@
|
||||
"integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
@@ -5386,7 +5444,6 @@
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.45.8.tgz",
|
||||
"integrity": "sha512-1Jh7FwVh/2Uxg0T7SeE1qFKMhwYH45b2v53bcZpW7qHa6O8iU1ByEj56PF0IQ6dU4HE5gRkic6h+vx+tclHeiw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.4",
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
@@ -5560,7 +5617,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"devalue": "^5.3.2",
|
||||
"memoize-weak": "^1.0.2",
|
||||
@@ -5767,8 +5823,7 @@
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz",
|
||||
"integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.3.0",
|
||||
@@ -5913,7 +5968,6 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -6056,7 +6110,6 @@
|
||||
"integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -6739,7 +6792,6 @@
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -127,13 +127,27 @@
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
{#if isShow}
|
||||
{getFullyQualifiedMediaName(
|
||||
(request as components['schemas']['RichSeasonRequest']).show
|
||||
)}
|
||||
<a
|
||||
href={resolve('/dashboard/tv/[showId]', {
|
||||
showId: (request as components['schemas']['RichSeasonRequest']).show.id!
|
||||
})}
|
||||
class="text-primary hover:underline"
|
||||
>
|
||||
{getFullyQualifiedMediaName(
|
||||
(request as components['schemas']['RichSeasonRequest']).show
|
||||
)}
|
||||
</a>
|
||||
{:else}
|
||||
{getFullyQualifiedMediaName(
|
||||
(request as components['schemas']['RichMovieRequest']).movie
|
||||
)}
|
||||
<a
|
||||
href={resolve('/dashboard/movies/[movieId]', {
|
||||
movieId: (request as components['schemas']['RichMovieRequest']).movie.id!
|
||||
})}
|
||||
class="text-primary hover:underline"
|
||||
>
|
||||
{getFullyQualifiedMediaName(
|
||||
(request as components['schemas']['RichMovieRequest']).movie
|
||||
)}
|
||||
</a>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if isShow}
|
||||
|
||||
@@ -14,14 +14,19 @@
|
||||
import DeleteTorrentDialog from '$lib/components/torrents/delete-torrent-dialog.svelte';
|
||||
import EditTorrentDialog from '$lib/components/torrents/edit-torrent-dialog.svelte';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
let {
|
||||
torrents,
|
||||
isShow = true
|
||||
isShow = true,
|
||||
showId,
|
||||
movieId
|
||||
}: {
|
||||
torrents:
|
||||
| components['schemas']['MovieTorrent'][]
|
||||
| components['schemas']['RichSeasonTorrent'][];
|
||||
isShow: boolean;
|
||||
showId?: string;
|
||||
movieId?: string;
|
||||
} = $props();
|
||||
|
||||
let user: () => components['schemas']['UserRead'] = getContext('user');
|
||||
@@ -68,7 +73,23 @@
|
||||
{#each torrents as torrent (torrent.torrent_id)}
|
||||
<Table.Row>
|
||||
<Table.Cell class="font-medium">
|
||||
{torrent.torrent_title}
|
||||
{#if isShow && showId}
|
||||
<a
|
||||
href={resolve('/dashboard/tv/[showId]', { showId })}
|
||||
class="text-primary hover:underline"
|
||||
>
|
||||
{torrent.torrent_title}
|
||||
</a>
|
||||
{:else if !isShow && movieId}
|
||||
<a
|
||||
href={resolve('/dashboard/movies/[movieId]', { movieId })}
|
||||
class="text-primary hover:underline"
|
||||
>
|
||||
{torrent.torrent_title}
|
||||
</a>
|
||||
{:else}
|
||||
{torrent.torrent_title}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if isShow}
|
||||
<Table.Cell>
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
<Card.Description>A list of all torrents associated with this movie.</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col gap-4">
|
||||
<TorrentTable isShow={false} torrents={movie.torrents} />
|
||||
<TorrentTable isShow={false} torrents={movie.torrents} movieId={movie.id} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<TorrentTable isShow={false} torrents={movie.torrents} />
|
||||
<TorrentTable isShow={false} torrents={movie.torrents} movieId={movie.movie_id} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
</Card.Header>
|
||||
|
||||
<Card.Content class="w-full overflow-x-auto">
|
||||
<TorrentTable isShow={true} torrents={torrents.torrents} />
|
||||
<TorrentTable isShow={true} torrents={torrents.torrents} showId={show.id} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<TorrentTable isShow={true} torrents={show.torrents} />
|
||||
<TorrentTable isShow={true} torrents={show.torrents} showId={show.show_id} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user