Remove private deployment details

This commit is contained in:
2026-07-29 14:13:22 +02:00
parent 67335a37b9
commit 2f996600c6
10 changed files with 63 additions and 212 deletions
+1
View File
@@ -5,3 +5,4 @@ __pycache__/
*.pyc *.pyc
*.db *.db
*.partial *.partial
AGENTS.local.md
-104
View File
@@ -1,104 +0,0 @@
# Importarr Agent Instructions
Importarr is owned as a Linux-ops-managed service repository. Treat this checkout as the source of truth for application code, deployment files, and local service installs.
## Repository Source Of Truth
- Work from `/srv/opencode-workspace/importarr` for Importarr code and deploy changes.
- The live service is installed on `dgsserver1` from a repo checkout at `/opt/importarr/repo`; gmk1 installs are not the public Importarr service.
- Do not edit host-local legacy scripts as the normal workflow:
- `/usr/local/sbin/importarr-status.py`
- `/usr/local/sbin/manual-media-import.py`
- If an emergency hotfix is made outside the repo, backport it here immediately and reinstall from the repo.
## Seamless Feature Workflow
When asked to implement an Importarr feature, fix, UI change, deployment change, or operational behavior change:
1. Inspect `git status --short --branch` before editing.
2. Implement the smallest correct repo change.
3. Run the narrowest useful verification, normally:
```sh
.venv/bin/pytest -q
```
If shell deploy scripts changed, also run:
```sh
sh -n deploy/systemd-install.sh && sh -n deploy/repo-upgrade.sh
```
4. Inspect `git diff` and ensure no secrets, raw `.env`, tokens, databases, or private material are included.
5. Commit and push completed Importarr changes by default unless the user explicitly asks not to publish or verification is blocked.
6. Install/restart on `dgsserver1` from the repository so the public service matches the repo:
```sh
ssh -p 2222 opencode@dgsserver1 'sudo -n sh /opt/importarr/repo-upgrade.sh'
```
7. Verify the live service:
```sh
make verify-live
```
8. If the live install fails, inspect `systemctl status importarr.service` and `journalctl -u importarr.service`; fix the repo, commit/push the fix, reinstall, and verify again.
## Gitea Issue Completion Workflow
When the user points an agent at an Importarr Gitea issue and asks to solve it, the expected end-to-end flow is mandatory unless the user explicitly says not to deploy:
1. Read the issue first, including comments and acceptance criteria.
2. Implement the smallest correct repo change on a dedicated issue branch when appropriate.
3. Run the narrowest useful tests/checks.
4. Commit and push the completed change to `main` or merge/push the issue branch as instructed.
5. Update the Gitea issue with what changed and the verification that ran, then close it when solved.
6. Update the `dgsserver1` install from the pushed repo state:
```sh
ssh -p 2222 opencode@dgsserver1 'sudo -n sh /opt/importarr/repo-upgrade.sh'
```
7. Restart/verify the `dgsserver1` service from the repo-managed install and confirm the public URL:
```sh
ssh -p 2222 opencode@dgsserver1 'sudo -n systemctl status importarr.service --no-pager -l'
curl -fsS https://importarr.delphas.dk/health
```
If the worker timer is intentionally paused, do not re-enable it unless the issue explicitly includes worker scheduling or the user approves.
## Install Model
- The service virtualenv lives at `/opt/importarr/venv` on `dgsserver1`.
- The status UI systemd unit runs `/opt/importarr/venv/bin/importarr-status` from the packaged repo install.
- The manual worker systemd unit runs `/opt/importarr/venv/bin/manual-media-import` from the packaged repo install.
- The package is installed from the repository into the venv using normal wheel/package install, not editable install.
- Do **not** use editable install for the system service: the unprivileged `importarr` user may not be able to read `/srv/opencode-workspace/importarr`, causing `ModuleNotFoundError` at startup.
- `/opt/importarr/repo-upgrade.sh` is the pull-and-reinstall helper for machines that should follow pushed `main`.
## Local Commands
```sh
make test
make install-systemd
make upgrade-local
make repo-upgrade
make verify-live
```
`make repo-upgrade` is for pulling already-pushed changes with `git pull --ff-only`. It refuses to run with uncommitted repo changes.
## Runtime Defaults On This Host
- Public URL: `https://importarr.delphas.dk/`
- dgsserver1 local URL: `http://127.0.0.1:8095/`
- Health: `http://127.0.0.1:8095/health`
- Status: `http://127.0.0.1:8095/api/status`
- Systemd service: `importarr.service`
- Env file: `/etc/importarr/importarr.env`
- SQLite state: `/var/lib/importarr/importarr.db`
## Secret Handling
- Prefer `*_FILE` settings for secrets, for example:
- `IMPORTARR_SAB_API_KEY_FILE`
- `IMPORTARR_AUTH_TOKEN_FILE`
- `IMPORTARR_RADARR_API_KEY_FILE`
- `IMPORTARR_SONARR_API_KEY_FILE`
- Never commit real env files, API keys, tokens, private keys, service databases, or backup data.
- Template files may list variable names with placeholder values or commented examples only.
## Linux Ops Follow-Through
For changes that materially alter the live service setup, ports, routes, monitoring, backup coverage, or host ownership, also follow the linux-ops documentation/systems-overview update rules. Do not mix unrelated pre-existing uncommitted changes from `linux-ops-docs` or `systems-overview` into Importarr commits.
+10 -12
View File
@@ -1,9 +1,11 @@
PYTHON ?= .venv/bin/python PYTHON ?= .venv/bin/python
PIP ?= .venv/bin/pip PIP ?= .venv/bin/pip
SERVICE ?= importarr.service SERVICE ?= importarr.service
LIVE_URL ?= http://127.0.0.1:8095 IMPORTARR_PREFIX ?= /opt/importarr
IMPORTARR_REPO_DIR ?= $(CURDIR)
IMPORTARR_URL ?= http://127.0.0.1:8765
.PHONY: test install-systemd install-from-repo upgrade-local repo-upgrade verify-live .PHONY: test install-systemd install-from-repo repo-upgrade verify
test: test:
$(PYTHON) -m pytest $(PYTHON) -m pytest
@@ -12,16 +14,12 @@ install-systemd:
sudo -n sh deploy/systemd-install.sh sudo -n sh deploy/systemd-install.sh
install-from-repo: install-from-repo:
sudo -n /opt/importarr/venv/bin/pip install --upgrade /srv/opencode-workspace/importarr sudo -n $(IMPORTARR_PREFIX)/venv/bin/pip install --upgrade $(IMPORTARR_REPO_DIR)
upgrade-local:
sudo -n /opt/importarr/venv/bin/pip install --upgrade /srv/opencode-workspace/importarr
sudo -n systemctl restart $(SERVICE)
repo-upgrade: repo-upgrade:
sudo -n sh /opt/importarr/repo-upgrade.sh sudo -n IMPORTARR_PREFIX=$(IMPORTARR_PREFIX) IMPORTARR_REPO_DIR=$(IMPORTARR_REPO_DIR) sh deploy/repo-upgrade.sh
verify-live: verify:
curl -fsS $(LIVE_URL)/health curl -fsS $(IMPORTARR_URL)/health
curl -fsS $(LIVE_URL)/api/status curl -fsS $(IMPORTARR_URL)/api/status
curl -fsS $(LIVE_URL)/api/preview curl -fsS $(IMPORTARR_URL)/api/preview
+14 -56
View File
@@ -2,17 +2,17 @@
Importarr is an Arr-style service for importing manually categorized SABnzbd downloads after SAB reports final completion. It owns one SAB category, defaults to `manual`, and refuses to import transient Direct Unpack paths or jobs still in SAB queue/post-processing. Importarr is an Arr-style service for importing manually categorized SABnzbd downloads after SAB reports final completion. It owns one SAB category, defaults to `manual`, and refuses to import transient Direct Unpack paths or jobs still in SAB queue/post-processing.
## New-machine install ## Install
Importarr is intended to feel like a small Arr service: deploy the container or systemd service, edit one env file, point SABnzbd category `manual` at the same completed-download path, then open the web UI. Importarr is intended to feel like a small Arr service: deploy the container or systemd service, edit one env file, point SABnzbd category `manual` at the same completed-download path, then open the web UI.
### Docker Compose, recommended ### Docker Compose, recommended
```sh ```sh
mkdir -p /opt/importarr/config mkdir -p importarr/config
cd /opt/importarr cd importarr
curl -fsSLO https://gitea.delphas.dk/daniels/importarr/raw/branch/main/deploy/docker-compose.example.yml curl -fsSLO https://example.com/importarr/deploy/docker-compose.example.yml
curl -fsSLo importarr.env https://gitea.delphas.dk/daniels/importarr/raw/branch/main/deploy/importarr.env.example curl -fsSLo importarr.env https://example.com/importarr/deploy/importarr.env.example
${EDITOR:-vi} importarr.env ${EDITOR:-vi} importarr.env
docker compose -f docker-compose.example.yml --env-file importarr.env up -d docker compose -f docker-compose.example.yml --env-file importarr.env up -d
``` ```
@@ -26,25 +26,14 @@ docker build -t importarr:local .
### systemd / pip install ### systemd / pip install
```sh ```sh
git clone https://gitea.delphas.dk/daniels/importarr.git git clone https://example.com/importarr.git
cd importarr cd importarr
sudo sh deploy/systemd-install.sh sudo sh deploy/systemd-install.sh
sudo ${EDITOR:-vi} /etc/importarr/importarr.env sudo ${EDITOR:-vi} /etc/importarr/importarr.env
sudo systemctl start importarr.service sudo systemctl start importarr.service
``` ```
The installer creates the `importarr` system user when needed, installs a virtualenv at `/opt/importarr/venv`, and installs the package from the checked-out repository. The repository is therefore the source of truth: pull or edit the repo, reinstall/restart from the repo, and the service runs the package built from that code. The installer creates the `importarr` system user when needed, installs a virtualenv, and installs the package from the checked-out repository. Override install paths with `IMPORTARR_*` variables if the defaults do not fit your environment.
For local upgrades from a checked-out repo on dgsserver1, use the repo workflow instead of editing live scripts:
```sh
cd /srv/opencode-workspace/importarr
.venv/bin/python -m pytest
git status --short --branch
sudo -n /opt/importarr/venv/bin/pip install --upgrade /srv/opencode-workspace/importarr
sudo -n systemctl restart importarr.service
make verify-live
```
For a machine that should stay current with the repository, use the installed repo-upgrade helper: For a machine that should stay current with the repository, use the installed repo-upgrade helper:
@@ -54,7 +43,7 @@ sudo -n sh /opt/importarr/repo-upgrade.sh
The helper refuses to run when the checkout has uncommitted changes, then performs `git pull --ff-only`, reinstalls the package from the repo, restarts `importarr.service`, and prints service status. Use it after changes have been committed and pushed to `main`. The helper refuses to run when the checkout has uncommitted changes, then performs `git pull --ff-only`, reinstalls the package from the repo, restarts `importarr.service`, and prints service status. Use it after changes have been committed and pushed to `main`.
Release-worthy changes should be committed, tagged with SemVer (`v0.1.1`, `v0.2.0`, ...), pushed with tags, then reinstalled from the tagged checkout or artifact. Do not hand-edit `/usr/local/sbin/importarr-status.py` or `/usr/local/sbin/manual-media-import.py` except for a documented emergency hotfix that is immediately backported here. Release-worthy changes should be committed, tagged with SemVer (`v0.1.1`, `v0.2.0`, ...), pushed with tags, then installed from the tagged checkout or artifact.
### Required setup ### Required setup
@@ -96,46 +85,15 @@ pytest
uvicorn importarr.main:app --reload uvicorn importarr.main:app --reload
``` ```
## Migration notes for dgsserver1 ## Operations
Export the existing script settings into `IMPORTARR_*` env vars, add historical folders as explicit manual batches, run a dry-run/inspection through `/api/preview`, then switch the systemd service or Compose route after the ready set matches expectations. Importarr intentionally does not document private deployment topology, hostnames, reverse proxies, monitoring, backups, or operator workflows in this repository. Keep those details in your own ops runbooks.
On dgsserver1, the packaged service is the only intended active entrypoint after cutover. Keep `manual-media-import.timer` disabled unless a repo-managed worker/timer replaces it later. For a systemd install, prefer a normal package install from the checked-out repo over an editable install so the service user does not need read access to your development checkout.
## Repository-as-install workflow If the service fails, standard systemd diagnostics are usually enough:
Importarr should not drift into host-local scripts. Treat the checked-out repository as the install source:
1. Make changes in `/srv/opencode-workspace/importarr`.
2. Run tests: `make test`.
3. Commit and push the repo change.
4. Install/restart from the same repo: `make upgrade-local` for local changes, or `make repo-upgrade` to pull the latest pushed `main` and restart.
5. Verify the live service: `make verify-live`.
Do not edit `/usr/local/sbin/importarr-status.py`, `/usr/local/sbin/manual-media-import.py`, or files copied out of the repo as the normal workflow. If an emergency live hotfix is unavoidable, backport it to this repository immediately and run the repo install workflow again.
### Local install lessons learned
- The live systemd service runs as the unprivileged `importarr` user.
- Do not install the system service with `pip install --editable /srv/opencode-workspace/importarr`; that can fail at startup if the service user cannot read the workspace checkout.
- The supported local service install is a normal package install from the repo into `/opt/importarr/venv`:
```sh ```sh
sudo -n /opt/importarr/venv/bin/pip install --upgrade /srv/opencode-workspace/importarr sudo systemctl --no-pager --full status importarr.service
sudo -n systemctl restart importarr.service sudo journalctl -u importarr.service -n 120 --no-pager
```
- `deploy/systemd-install.sh`, `make upgrade-local`, and `/opt/importarr/repo-upgrade.sh` already use this supported model.
- After every implementation task that should affect the live local service, run:
```sh
make upgrade-local
make verify-live
```
- If `make verify-live` fails, check:
```sh
sudo -n systemctl --no-pager --full status importarr.service
sudo -n journalctl -u importarr.service -n 120 --no-pager
``` ```
+1 -1
View File
@@ -6,7 +6,7 @@ services:
- "8765:8765" - "8765:8765"
volumes: volumes:
- ./config:/config - ./config:/config
- /srv/scrypted/sabnzbd-data/downloads/manual:/data/downloads/manual - /path/to/downloads/manual:/data/downloads/manual
- /path/to/movies:/data/movies - /path/to/movies:/data/movies
- /path/to/tv:/data/tv - /path/to/tv:/data/tv
restart: unless-stopped restart: unless-stopped
+7 -7
View File
@@ -1,16 +1,16 @@
IMPORTARR_SAB_URL=http://127.0.0.1:8080 IMPORTARR_SAB_URL=http://sabnzbd:8080
# Prefer *_FILE for secrets. Plain env vars still work for local/dev installs. # Prefer *_FILE for secrets. Plain env vars still work for local/dev installs.
# IMPORTARR_SAB_API_KEY=change-me # IMPORTARR_SAB_API_KEY=change-me
# IMPORTARR_SAB_API_KEY_FILE=/etc/importarr/sab-api-key # IMPORTARR_SAB_API_KEY_FILE=/etc/importarr/sab-api-key
IMPORTARR_SAB_CATEGORY=manual IMPORTARR_SAB_CATEGORY=manual
IMPORTARR_DOWNLOAD_ROOT=/srv/scrypted/sabnzbd-data/downloads/manual IMPORTARR_DOWNLOAD_ROOT=/data/downloads/manual
IMPORTARR_MOVIES_ROOT=/srv/media/movies IMPORTARR_MOVIES_ROOT=/data/movies
IMPORTARR_TV_ROOT=/srv/media/tv IMPORTARR_TV_ROOT=/data/tv
IMPORTARR_STATE_PATH=/var/lib/importarr/importarr.db IMPORTARR_STATE_PATH=/config/importarr.db
IMPORTARR_LOG_LEVEL=info IMPORTARR_LOG_LEVEL=info
# IMPORTARR_AUTH_TOKEN=change-me # IMPORTARR_AUTH_TOKEN=change-me
# IMPORTARR_AUTH_TOKEN_FILE=/etc/importarr/auth-token # IMPORTARR_AUTH_TOKEN_FILE=/etc/importarr/auth-token
IMPORTARR_BIND_HOST=0.0.0.0 IMPORTARR_BIND_HOST=0.0.0.0
IMPORTARR_BIND_PORT=8095 IMPORTARR_BIND_PORT=8765
IMPORTARR_POLL_SECONDS=60 IMPORTARR_POLL_SECONDS=60
IMPORTARR_REPO_DIR=/srv/opencode-workspace/importarr # IMPORTARR_REPO_DIR=/path/to/importarr
+1 -1
View File
@@ -3,4 +3,4 @@ Description=Critical alert when manual media importer fails
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/bin/python3 /usr/local/sbin/ha-critical-notify.py service-recovery "manual-media-import.service failed" --host dgsserver1 --resource manual-media-import --details "Check journalctl -u manual-media-import.service and /var/log/manual-media-import.log" ExecStart=/usr/bin/logger -t importarr "manual-media-import.service failed; check journalctl -u manual-media-import.service"
+4 -3
View File
@@ -12,9 +12,10 @@ if [ -f "$ENV_FILE" ]; then
. "$ENV_FILE" . "$ENV_FILE"
fi fi
REPO_DIR=${IMPORTARR_REPO_DIR:-/srv/opencode-workspace/importarr} PREFIX=${IMPORTARR_PREFIX:-/opt/importarr}
REPO_DIR=${IMPORTARR_REPO_DIR:-$(pwd)}
SERVICE=${IMPORTARR_SERVICE:-importarr.service} SERVICE=${IMPORTARR_SERVICE:-importarr.service}
VENV=${IMPORTARR_VENV:-/opt/importarr/venv} VENV=${IMPORTARR_VENV:-$PREFIX/venv}
if [ ! -d "$REPO_DIR/.git" ]; then if [ ! -d "$REPO_DIR/.git" ]; then
echo "Importarr repo not found at $REPO_DIR" >&2 echo "Importarr repo not found at $REPO_DIR" >&2
@@ -33,7 +34,7 @@ git pull --ff-only
"$VENV/bin/pip" install --upgrade "$REPO_DIR" "$VENV/bin/pip" install --upgrade "$REPO_DIR"
GIT_SHA="$(git rev-parse --short=12 HEAD 2>/dev/null || printf development)" GIT_SHA="$(git rev-parse --short=12 HEAD 2>/dev/null || printf development)"
BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
cat > /opt/importarr/build.env <<EOF cat > "$PREFIX/build.env" <<EOF
IMPORTARR_GIT_SHA=$GIT_SHA IMPORTARR_GIT_SHA=$GIT_SHA
IMPORTARR_BUILD_DATE=$BUILD_DATE IMPORTARR_BUILD_DATE=$BUILD_DATE
EOF EOF
+4 -4
View File
@@ -18,12 +18,12 @@ LOG = Path("/var/log/manual-media-import.log")
IMPORTER_STATUS = Path("/run/manual-media-import/status.json") IMPORTER_STATUS = Path("/run/manual-media-import/status.json")
MANUAL_BATCHES = Path("/var/lib/importarr/manual-batches.json") MANUAL_BATCHES = Path("/var/lib/importarr/manual-batches.json")
QUEUE_ROOTS = { QUEUE_ROOTS = {
"manual": Path("/srv/scrypted/sabnzbd-data/downloads/manual"), "manual": Path(os.getenv("IMPORTARR_DOWNLOAD_ROOT", "/data/downloads/manual")),
"danish_legacy": Path("/srv/scrypted/sabnzbd-data/downloads/danish"), "legacy": Path(os.getenv("IMPORTARR_LEGACY_DOWNLOAD_ROOT", "/data/downloads/legacy")),
} }
VIDEO_EXT = {".mkv", ".mp4", ".m4v", ".avi", ".mov", ".wmv", ".mpg", ".mpeg", ".ts", ".m2ts", ".webm"} VIDEO_EXT = {".mkv", ".mp4", ".m4v", ".avi", ".mov", ".wmv", ".mpg", ".mpeg", ".ts", ".m2ts", ".webm"}
SAB_CONFIG = Path("/opt/stacks/media-transform/sabnzbd/config/sabnzbd.ini") SAB_CONFIG = Path(os.getenv("IMPORTARR_SABNZBD_CONFIG", "/config/sabnzbd/sabnzbd.ini"))
SAB_API = "http://127.0.0.1:8080/api" SAB_API = os.getenv("IMPORTARR_SABNZBD_URL", "http://sabnzbd:8080/api")
LONG_RUNTIME_SECONDS = 25 * 60 LONG_RUNTIME_SECONDS = 25 * 60
HIGH_MEMORY_BYTES = 8 * 1024**3 HIGH_MEMORY_BYTES = 8 * 1024**3
STALE_QUEUE_SECONDS = 6 * 60 * 60 STALE_QUEUE_SECONDS = 6 * 60 * 60
+21 -24
View File
@@ -1,10 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Import manual SABnzbd downloads into Jellyfin movie/TV library roots. """Import manual SABnzbd downloads into Jellyfin movie/TV library roots."""
Run on dgsserver1. Intended live install path:
`/usr/local/sbin/manual-media-import.py`, managed by
`manual-media-import.timer`.
"""
from __future__ import annotations from __future__ import annotations
@@ -25,38 +20,38 @@ from collections import Counter
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
MANUAL_DOWNLOADS = Path("/srv/scrypted/sabnzbd-data/downloads/manual") MANUAL_DOWNLOADS = Path(os.getenv("IMPORTARR_DOWNLOAD_ROOT", "/data/downloads/manual"))
LEGACY_DANISH_DOWNLOADS = Path("/srv/scrypted/sabnzbd-data/downloads/danish") LEGACY_DANISH_DOWNLOADS = Path(os.getenv("IMPORTARR_LEGACY_DOWNLOAD_ROOT", "/data/downloads/legacy"))
DOWNLOAD_ROOTS = [MANUAL_DOWNLOADS, LEGACY_DANISH_DOWNLOADS] DOWNLOAD_ROOTS = [MANUAL_DOWNLOADS, LEGACY_DANISH_DOWNLOADS]
SAB_TRANSIENT_PREFIXES = ("_UNPACK_", "__UNPACK__", "_FAILED_", "_ADMIN_") SAB_TRANSIENT_PREFIXES = ("_UNPACK_", "__UNPACK__", "_FAILED_", "_ADMIN_")
HOST_MEDIA_PREFIX = "/srv/media" HOST_MEDIA_PREFIX = os.getenv("IMPORTARR_HOST_MEDIA_PREFIX", "/data")
MOVIES_ROOT = Path("/srv/media/movies") MOVIES_ROOT = Path(os.getenv("IMPORTARR_MOVIES_ROOT", "/data/movies"))
TV_ROOT = Path("/srv/media/tv") TV_ROOT = Path(os.getenv("IMPORTARR_TV_ROOT", "/data/tv"))
LOG = Path("/var/log/manual-media-import.log") LOG = Path("/var/log/manual-media-import.log")
LOCK = Path("/run/manual-media-import.lock") LOCK = Path("/run/manual-media-import.lock")
STATUS = Path("/run/manual-media-import/status.json") STATUS = Path("/run/manual-media-import/status.json")
MANUAL_BATCHES = Path("/var/lib/importarr/manual-batches.json") MANUAL_BATCHES = Path("/var/lib/importarr/manual-batches.json")
HOME_ASSISTANT_WEBHOOK = "https://hass.delphas.dk/api/webhook/jellyfin_event" HOME_ASSISTANT_WEBHOOK = os.getenv("IMPORTARR_HOME_ASSISTANT_WEBHOOK", "")
RADARR_CONFIG = Path("/opt/stacks/media-transform/radarr/config/config.xml") RADARR_CONFIG = Path(os.getenv("IMPORTARR_RADARR_CONFIG", "/config/radarr/config.xml"))
RADARR_URL = "http://127.0.0.1:7878" RADARR_URL = os.getenv("IMPORTARR_RADARR_URL", "http://radarr:7878")
RADARR_DB = Path("/opt/stacks/media-transform/radarr/config/radarr.db") RADARR_DB = Path(os.getenv("IMPORTARR_RADARR_DB", "/config/radarr/radarr.db"))
SONARR_CONFIG = Path("/opt/stacks/media-transform/sonarr/config/config.xml") SONARR_CONFIG = Path(os.getenv("IMPORTARR_SONARR_CONFIG", "/config/sonarr/config.xml"))
SONARR_URL = "http://127.0.0.1:8989" SONARR_URL = os.getenv("IMPORTARR_SONARR_URL", "http://sonarr:8989")
SONARR_DB = Path("/opt/stacks/media-transform/sonarr/config/sonarr.db") SONARR_DB = Path(os.getenv("IMPORTARR_SONARR_DB", "/config/sonarr/sonarr.db"))
SABNZBD_CONFIG = Path("/opt/stacks/media-transform/sabnzbd/config/sabnzbd.ini") SABNZBD_CONFIG = Path(os.getenv("IMPORTARR_SABNZBD_CONFIG", "/config/sabnzbd/sabnzbd.ini"))
SABNZBD_URL = "http://127.0.0.1:8080/api" SABNZBD_URL = os.getenv("IMPORTARR_SABNZBD_URL", "http://sabnzbd:8080/api")
ARR_API_TIMEOUT = 10 ARR_API_TIMEOUT = 10
VIDEO_EXT = {".mkv", ".mp4", ".m4v", ".avi", ".mov", ".wmv", ".mpg", ".mpeg", ".ts", ".m2ts", ".webm"} VIDEO_EXT = {".mkv", ".mp4", ".m4v", ".avi", ".mov", ".wmv", ".mpg", ".mpeg", ".ts", ".m2ts", ".webm"}
SIDECAR_EXT = {".srt", ".ass", ".sub", ".idx", ".nfo"} SIDECAR_EXT = {".srt", ".ass", ".sub", ".idx", ".nfo"}
MIN_SIZE = 100 * 1024 * 1024 MIN_SIZE = 100 * 1024 * 1024
IMDB_DATASET_CANDIDATES = [ IMDB_DATASET_CANDIDATES = [
Path("/srv/media/imdb"), Path("/data/imdb"),
Path("/srv/media/imdb-datasets"), Path("/data/imdb-datasets"),
Path("/srv/media/.cache/imdb"), Path("/data/.cache/imdb"),
Path("/var/lib/imdb"), Path("/var/lib/imdb"),
Path("/opt/imdb"), Path("/opt/imdb"),
] ]
@@ -869,6 +864,8 @@ def copy_then_remove(src: Path, dest: Path, *, media_type: str | None = None, so
def notify_home_assistant(item: dict[str, object], dest: Path, source_tag: str) -> None: def notify_home_assistant(item: dict[str, object], dest: Path, source_tag: str) -> None:
if not HOME_ASSISTANT_WEBHOOK:
return
item_type = str(item.get("item_type") or "Movie") item_type = str(item.get("item_type") or "Movie")
name = item.get("title") or dest.parent.name name = item.get("title") or dest.parent.name
payload_body: dict[str, object] = { payload_body: dict[str, object] = {
@@ -906,7 +903,7 @@ def source_tag_for(path: Path) -> str:
for root in DOWNLOAD_ROOTS: for root in DOWNLOAD_ROOTS:
try: try:
path.relative_to(root) path.relative_to(root)
return "manual" if root == MANUAL_DOWNLOADS else "danish-legacy" return "manual" if root == MANUAL_DOWNLOADS else "legacy"
except ValueError: except ValueError:
continue continue
return "manual" return "manual"