- Python 99%
- Dockerfile 1%
|
All checks were successful
Test and Build ntfy-downloader Image / build-image (push) Successful in 9s
|
||
|---|---|---|
| .forgejo/workflows | ||
| ntfy_downloader | ||
| releases | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| compose.image.yaml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
ntfy yt-dlp Downloader
Ein kleiner Python-Dienst, der auf einem ntfy-Kanal lauscht. Sobald eine Nachricht mit einer URL eintrifft, wird diese mit yt-dlp heruntergeladen. Erfolg und Fehler werden als Nachricht auf denselben Kanal zurueckgemeldet. Der Zugriff auf den ntfy-Server erfolgt mit HTTP Basic Auth (Username/Passwort).
Funktionsweise
ntfy Topic --(JSON-Stream, Basic Auth)--> Listener
Listener --(URL erkannt)--> yt-dlp --> DOWNLOAD_DIR
Listener --(POST Statusmeldung)--> ntfy Topic
- Abonniert
GET <NTFY_BASE_URL>/<NTFY_TOPIC>/jsonund verarbeitetmessage-Events. - Extrahiert die erste
http(s)://-URL aus dem Nachrichtentext. - Laedt sie per
yt-dlpins konfigurierte Verzeichnis. - Speichert Auftraege vor dem Download in einer persistenten SQLite-Warteschlange.
- Setzt einen unterbrochenen ntfy-Stream am letzten gespeicherten Zeitpunkt fort und dedupliziert wiederholte Nachrichten anhand ihrer ntfy-ID.
- Loest
pornkai.com-Links automatisch auf die eingebettete Video-URL (iframe) auf, bevoryt-dlpstartet. - Meldet
Download gestartet(optional),Download erfolgreichoderDownload fehlgeschlagenzurueck. Bei Erfolg optional ein Link zur Web-Galerie (/watch?f=...), wennWEBUI_PUBLIC_URLgesetzt ist. - Ignoriert seine eigenen Statusmeldungen (verhindert Rueckkopplungsschleifen).
- Laeuft dauerhaft weiter: Ein fehlgeschlagener Download wird gemeldet, der Dienst lauscht danach aber normal weiter (es wird nichts erneut versucht).
- Verbindet bei Stream-Abbruch automatisch mit Backoff neu. Nur bei falschen Zugangsdaten (401/403) wird der Dienst beendet.
Konfiguration
Alle Einstellungen erfolgen ueber Umgebungsvariablen (bzw. .env). Kopiere
.env.example nach .env und passe die Werte an:
cp .env.example .env
| Variable | Pflicht | Beschreibung |
|---|---|---|
NTFY_BASE_URL |
ja | URL des ntfy-Servers, z.B. https://ntfy.example.com |
NTFY_TOPIC |
ja | Kanal/Topic zum Lauschen und Zurueckmelden |
NTFY_USERNAME |
ja | Benutzername (Basic Auth) |
NTFY_PASSWORD |
ja | Passwort (Basic Auth) |
DOWNLOAD_DIR |
nein | Zielverzeichnis der Downloads. Bei Docker der Host-Pfad, der nach /downloads gemappt wird (z.B. ein SMB-Mount /mnt/smb/XXX); ohne Docker der direkte Pfad. Default ./downloads |
JOB_DATABASE |
nein | SQLite-Datei der persistenten Jobqueue. Default ./state/jobs.sqlite3; Docker verwendet /state/jobs.sqlite3 |
YTDLP_FORMAT |
nein | yt-dlp Format-String, leer = Default |
YTDLP_OUTPUT_TEMPLATE |
nein | Ausgabe-Template (Default %(title).120B [%(id)s].%(ext)s; begrenzt lange Dateinamen) |
YTDLP_IMPERSONATE |
nein | Browser-TLS-Fingerprint fuer yt-dlp --impersonate (z.B. chrome, firefox). Umgeht TLS-Fingerprinting (z.B. Pornhub). Leer = aus. Default chrome |
NOTIFY_ON_START |
nein | true/false, Startmeldung senden (Default true) |
DOWNLOAD_TIMEOUT |
nein | Max. Laufzeit pro Download in Sekunden (Default 3600) |
LOG_LEVEL |
nein | DEBUG/INFO/WARNING/ERROR (Default INFO) |
WEBUI_USERNAME |
fuer Web-UI | Login-Benutzer der Galerie (Basic Auth) |
WEBUI_PASSWORD |
fuer Web-UI | Login-Passwort der Galerie (Basic Auth) |
WEBUI_PORT |
nein | Host-Port der Galerie (Default 2310) |
WEBUI_PUBLIC_URL |
nein | Oeffentliche Basis-URL der Galerie fuer Links in Erfolgsmeldungen (z.B. http://server:2310). Leer = kein Link |
WEBUI_DEFAULT_TAG |
nein | Zeigt beim Aufruf der Startseite nur Videos mit diesem Tag. Leer = alle Videos |
THUMB_MAX_AGE_DAYS |
nein | Entfernt beim Web-UI-Start aeltere Thumbnail-Cachedateien. Default 30, 0 deaktiviert die Bereinigung |
CLIPS_SUBDIR |
nein | Unterverzeichnis fuer erzeugte Videoausschnitte. Default clips |
CLIP_MAX_DURATION |
nein | Maximale Laenge eines Ausschnitts in Sekunden. Default 600 |
CLIP_TIMEOUT |
nein | Maximale ffmpeg-Laufzeit fuer einen Ausschnitt in Sekunden. Default 120 |
Lokaler Start mit Docker Build
Diese Variante baut das Image direkt aus dem Checkout und eignet sich fuer Entwicklung und lokale Tests:
cp .env.example .env # Werte anpassen
mkdir -p ./downloads # oder vorhandenen DOWNLOAD_DIR-Pfad vorbereiten
docker compose up -d --build
docker compose logs -f
Die heruntergeladenen Dateien landen im Host-Verzeichnis, das in DOWNLOAD_DIR
(in der .env) steht, und das nach /downloads im Container gemappt wird.
Ist DOWNLOAD_DIR nicht gesetzt, wird ./downloads verwendet. Beispiel fuer
einen SMB-Mount:
DOWNLOAD_DIR=/mnt/smb/XXX
Der Container laeuft ohne Root-Rechte als UID/GID 1000. Der konfigurierte
Host-Pfad muss bereits existieren und fuer diesen Benutzer beschreibbar sein.
SQLite-Zustand, Thumbnail-Cache und Web-UI-Metadaten liegen in den Docker-Volumes
ntfy-state, ntfy-thumbs und ntfy-metadata.
CPU- und Speicherlimits koennen ueber die Variablen in .env.example angepasst
werden. Beide Dienste besitzen einen Docker-Healthcheck.
Betrieb mit dem Registry-Image
Forgejo Actions baut bei jedem Push auf main zuerst die Test-Stage und
veroeffentlicht danach das Runtime-Image unter:
git.home.schumbi.de/ralf/ntfy-downloader
Es werden die Tags latest und der vollstaendige Commit-SHA veroeffentlicht.
Fuer einen reproduzierbaren Betrieb auf dem Host sollte ein Commit-SHA statt
latest verwendet werden.
Auf dem Zielhost werden nur diese Dinge benoetigt:
compose.image.yaml- eine ausgefuellte
.env - das in
DOWNLOAD_DIRangegebene, fuer die konfigurierte Downloader-UID/GID beschreibbare Verzeichnis
Der Quellcode, die Tests und der Dockerfile werden auf dem Host nicht benoetigt.
Falls das Downloadverzeichnis einer anderen numerischen Identitaet gehoert,
koennen DOWNLOADER_UID und DOWNLOADER_GID in .env passend gesetzt werden.
Downloader und Web-UI verwenden beide diese Identitaet. Bereits vorhandene
Volumes fuer Jobzustand und Thumbnails muessen bei einer abweichenden UID
einmalig passende Eigentumsrechte erhalten. Das neue Metadaten-Volume wird beim
ersten Start automatisch vorbereitet. Beispiel fuer UID/GID 1000:1000:
docker run --rm --user 0:0 \
-v ntfy-downloader_ntfy-thumbs:/thumbs \
git.home.schumbi.de/ralf/ntfy-downloader:<TAG> \
chown -R 1000:1000 /thumbs
Einmalige Einrichtung:
mkdir -p /opt/ntfy-downloader
cd /opt/ntfy-downloader
# compose.image.yaml und eine angepasste .env hier ablegen
mkdir -p ./downloads # falls DOWNLOAD_DIR=./downloads verwendet wird
docker login git.home.schumbi.de
docker compose -f compose.image.yaml config -q
docker compose -f compose.image.yaml pull
docker compose -f compose.image.yaml up -d
docker compose -f compose.image.yaml ps
Falls die Registry fuer Downloads ohne Anmeldung freigegeben ist, kann
docker login entfallen. Status und Logs:
docker compose -f compose.image.yaml ps
docker compose -f compose.image.yaml logs -f
Fuer ein reproduzierbares Update zuerst NTFY_DOWNLOADER_IMAGE_TAG in .env
auf den neuen vollstaendigen Commit-SHA setzen und danach ausfuehren:
docker compose -f compose.image.yaml pull
docker compose -f compose.image.yaml up -d
docker compose -f compose.image.yaml ps
Zum Stoppen beziehungsweise Entfernen der Container:
docker compose -f compose.image.yaml stop
docker compose -f compose.image.yaml down
down entfernt die persistenten Named Volumes nicht. Jobdatenbank,
Thumbnail-Cache und Video-Tags bleiben deshalb erhalten.
Start ohne Docker
Voraussetzungen: Python 3.12+, ffmpeg im PATH.
python -m venv .venv
. .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
# Konfiguration als Umgebungsvariablen setzen (oder .env per Tool laden)
export NTFY_BASE_URL=https://ntfy.example.com
export NTFY_TOPIC=downloads
export NTFY_USERNAME=meinuser
export NTFY_PASSWORD=meinpasswort
export DOWNLOAD_DIR=./downloads
python -m ntfy_downloader.listener
Verwendung / Test
Eine URL auf den Kanal senden (loest einen Download aus):
curl -u meinuser:meinpasswort \
-d "https://www.youtube.com/watch?v=dQw4w9WgXcQ" \
https://ntfy.example.com/downloads
Anschliessend erscheinen die Statusmeldungen (Download erfolgreich /
Download fehlgeschlagen) auf demselben Kanal, und die Datei liegt im
Downloadverzeichnis.
Die automatisierten Unit-Tests laufen mit:
python -m unittest discover -v
Web-UI / Video-Galerie
Das docker compose-Setup startet zusaetzlich den Dienst ntfy-webui: eine
kleine Galerie, die die heruntergeladenen Videos mit Thumbnails und einem
HTML5-Player im Browser anzeigt. Sie ist im internen Netz unter
http://<server>:2310 erreichbar (Port via WEBUI_PORT aenderbar) und per
Basic Auth geschuetzt (WEBUI_USERNAME / WEBUI_PASSWORD).
- Videos werden rekursiv auch aus Unterverzeichnissen angezeigt.
- Videos koennen mit frei waehlbaren Tags versehen und danach gefiltert werden.
WEBUI_DEFAULT_TAGbegrenzt die ungefilterte Startseite auf ein bestimmtes Tag; ueberAllebleiben saemtliche Videos erreichbar. - Die Detailseite kann Videos in vorhandene oder neue Unterverzeichnisse verschieben und nach Bestaetigung dauerhaft loeschen. Tags folgen einer verschobenen Datei automatisch.
- Zeitstempel-Links koennen direkt aus der aktuellen Abspielposition erstellt
werden. Ein Start-/Endbereich laesst sich ausserdem per ffmpeg als neue Datei
unter
CLIPS_SUBDIRextrahieren und anschliessend abspielen oder herunterladen. Die Extraktion verwendet Stream-Copy, ist daher schnell, kann aber je nach Videoformat am naechsten Keyframe beginnen. - Fuer diese Dateioperationen wird das Download-Verzeichnis schreibbar in die Web-UI eingebunden. Alle Aenderungsaktionen verwenden authentifizierte POST-Formulare mit CSRF-Schutz.
- Thumbnails werden bei Bedarf per
ffmpegerzeugt und im konfigurierten Cacheverzeichnis beziehungsweise im Docker-Volumentfy-thumbsgespeichert. - Tags werden unabhaengig vom Download-Verzeichnis im Docker-Volume
ntfy-metadatagespeichert. .mp4/.webmlaufen nativ im Browser;.mkv/.avilassen sich evtl. nicht direkt abspielen, koennen aber heruntergeladen werden.
Sicherheit
- Basic Auth verschluesselt die Zugangsdaten nicht. ntfy und Galerie sollten ausserhalb eines vollstaendig vertrauenswuerdigen Netzes nur ueber HTTPS erreichbar sein, beispielsweise hinter einem Reverse Proxy.
- Das ntfy-Topic ist eine Ausfuehrungsschnittstelle fuer Downloads und muss so konfiguriert sein, dass nur vertrauenswuerdige Benutzer darauf schreiben duerfen.
- Akzeptierte URLs koennen ausgehende Verbindungen des Containers ausloesen, auch zu internen Netzwerkzielen. Falls das Topic nicht vollstaendig vertrauenswuerdig ist, muss der Container zusaetzlich per Firewall oder separatem Docker-Netz von internen Diensten isoliert werden.
- Die Beispiel-Zugangsdaten in
.env.examplemuessen vor dem Start ersetzt werden. - Der Web-UI-Container besitzt absichtlich Schreibrechte im Download-Verzeichnis. Das verwendete Basic-Auth-Passwort muss deshalb stark sein und die Galerie darf nur ueber HTTPS beziehungsweise ein vertrauenswuerdiges Netz erreichbar sein.