stack/scripts/configure-usenet.sh

173 lines
6.1 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Bootstrap SABnzbd folders + Usenet servers from secrets/.env
# Run on the stack host after: docker compose up -d sabnzbd
#
# ./scripts/configure-usenet.sh
# SECRETS_FILE=./secrets/.env SAB_URL=http://127.0.0.1:8085 ./scripts/configure-usenet.sh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
STACK_DIR="${STACK_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
SECRETS_FILE="${SECRETS_FILE:-$STACK_DIR/secrets/.env}"
SAB_URL="${SAB_URL:-http://127.0.0.1:8085}"
log() { echo "[configure-usenet] $*"; }
die() { log "ERROR: $*"; exit 1; }
[[ -f "$SECRETS_FILE" ]] || die "missing $SECRETS_FILE (see secrets/.env.example)"
# shellcheck disable=SC1090
set -a
# shellcheck disable=SC1091
source "$SECRETS_FILE"
set +a
# Accept clean names AND the variable names used in secrets/.env
# NZBgeek
NZBGEEK_API_KEY="${NZBGEEK_API_KEY:-${NZBKEEPKEY:-${NZBGEEKKEY:-}}}"
NZBGEEK_URL="${NZBGEEK_URL:-${NZBGEEKAPI:-https://api.nzbgeek.info/}}"
NZBGEEK_USERNAME="${NZBGEEK_USERNAME:-${NZBGEEKUSERNAME:-}}"
# Newshosting (provider host often in NEWSHOSTINGAPI)
NEWSHOSTING_HOST="${NEWSHOSTING_HOST:-${NEWSHOSTINGAPI:-news.newshosting.com}}"
NEWSHOSTING_PORT="${NEWSHOSTING_PORT:-${NEWSHOSTINGSSLPORT:-563}}"
[[ "$NEWSHOSTING_PORT" == "653" ]] && NEWSHOSTING_PORT=563 # common typo for 563
NEWSHOSTING_USER="${NEWSHOSTING_USER:-${NEWSHOSTINGUSER:-}}"
NEWSHOSTING_PASS="${NEWSHOSTING_PASS:-${HNEWSHOSTINGPASS:-${NEWSHOSTINGPASS:-${NEWSHOSTINGPASSWORD:-}}}}"
NEWSHOSTING_CONNECTIONS="${NEWSHOSTING_CONNECTIONS:-${NEWSHOSTINGCONNECTIONS:-20}}"
# Tweaknews (secrets use TWEAKNEWSLOGIN / TWEAKNEWSPASSWORD / TWEAKNEWSAPI as host)
TWEAKNEWS_HOST="${TWEAKNEWS_HOST:-${TWEAKNEWSAPI:-${TWEAKNEWSHOST:-news.tweaknews.eu}}}"
TWEAKNEWS_PORT="${TWEAKNEWS_PORT:-${TWEAKNEWSSSLPORT:-${TWEAKNEWSPORT:-563}}}"
TWEAKNEWS_USER="${TWEAKNEWS_USER:-${TWEAKNEWSLOGIN:-${TWEAKNEWSUSER:-${TWEAKNEWSUSERNAME:-}}}}"
TWEAKNEWS_PASS="${TWEAKNEWS_PASS:-${TWEAKNEWSPASSWORD:-${TWEAKNEWSPASS:-}}}"
TWEAKNEWS_CONNECTIONS="${TWEAKNEWS_CONNECTIONS:-${TWEAKNEWSCONNECTIONS:-10}}"
find_api_key() {
local f
for f in \
"${CONFIG_DIR:-$STACK_DIR/config}/sabnzbd/sabnzbd.ini" \
"$STACK_DIR/config/sabnzbd/sabnzbd.ini" \
"/opt/stack/config/sabnzbd/sabnzbd.ini" \
; do
if [[ -f "$f" ]]; then
grep -E '^api_key[[:space:]]*=' "$f" | head -1 | cut -d= -f2- | tr -d '[:space:]'
return 0
fi
done
# docker exec fallback
if command -v docker >/dev/null 2>&1; then
docker exec sabnzbd sh -c 'grep -E "^api_key" /config/sabnzbd.ini 2>/dev/null | head -1' \
| cut -d= -f2- | tr -d '[:space:]' || true
fi
}
log "Waiting for SABnzbd at $SAB_URL ..."
for i in $(seq 1 90); do
if curl -fsS "$SAB_URL/api?mode=version&output=json" >/dev/null 2>&1; then
break
fi
sleep 2
[[ $i -eq 90 ]] && die "SABnzbd not reachable — is the container up? (docker compose up -d sabnzbd)"
done
api_key="$(find_api_key)"
[[ -n "$api_key" ]] || die "no api_key yet — open $SAB_URL once to finish first-run, then re-run this script"
sab_set() {
# set_config: section + keyword + value OR servers with name= + fields
curl -fsS -G "${SAB_URL}/api" \
--data-urlencode "mode=set_config" \
--data-urlencode "apikey=${api_key}" \
--data-urlencode "output=json" \
"$@"
}
log "Folders: incomplete + complete under /data/usenet"
sab_set --data-urlencode "section=misc" --data-urlencode "keyword=download_dir" \
--data-urlencode "value=/data/usenet/incomplete" >/dev/null
sab_set --data-urlencode "section=misc" --data-urlencode "keyword=complete_dir" \
--data-urlencode "value=/data/usenet/complete" >/dev/null
# Relative category folders under complete_dir
add_category() {
local name="$1"
sab_set \
--data-urlencode "section=categories" \
--data-urlencode "name=${name}" \
--data-urlencode "dir=${name}" \
--data-urlencode "pp=3" \
>/dev/null || true
}
add_category movies
add_category tv
add_category music
add_server() {
local name="$1" host="$2" port="$3" user="$4" pass="$5" conns="$6"
if [[ -z "$user" || -z "$pass" ]]; then
log "skip server '$name' (missing user/password in secrets)"
return 0
fi
log "Usenet server: $name$host:$port (ssl, ${conns} conn)"
# https://sabnzbd.org/wiki/configuration/5.0/api — servers via set_config + name=
sab_set \
--data-urlencode "section=servers" \
--data-urlencode "name=${name}" \
--data-urlencode "displayline=${name}" \
--data-urlencode "host=${host}" \
--data-urlencode "port=${port}" \
--data-urlencode "username=${user}" \
--data-urlencode "password=${pass}" \
--data-urlencode "connections=${conns}" \
--data-urlencode "ssl=1" \
--data-urlencode "enable=1" \
--data-urlencode "priority=0" \
--data-urlencode "timeout=60" \
>/dev/null
}
add_server "Newshosting" \
"$NEWSHOSTING_HOST" "$NEWSHOSTING_PORT" \
"$NEWSHOSTING_USER" "$NEWSHOSTING_PASS" \
"$NEWSHOSTING_CONNECTIONS"
add_server "Tweaknews" \
"$TWEAKNEWS_HOST" "$TWEAKNEWS_PORT" \
"$TWEAKNEWS_USER" "$TWEAKNEWS_PASS" \
"$TWEAKNEWS_CONNECTIONS"
log "Restart SABnzbd to pick up servers"
if command -v docker >/dev/null 2>&1 && docker ps --format '{{.Names}}' | grep -qx sabnzbd; then
docker restart sabnzbd >/dev/null
sleep 5
fi
log ""
log "=== SABnzbd ready ==="
log "UI: $SAB_URL"
log "API: (Config → General) — use this key in Prowlarr/*arr"
log ""
log "=== Prowlarr (NZBgeek) ==="
log "Indexers → Add Indexer → NZBgeek"
log " URL: ${NZBGEEK_URL}"
if [[ -n "$NZBGEEK_API_KEY" ]]; then
log " API Key: ${NZBGEEK_API_KEY}"
else
log " API Key: (set NZBKEEPKEY or NZBGEEK_API_KEY in secrets/.env)"
fi
log ""
log "Download Clients → Add → SABnzbd"
log " Host: sabnzbd Port: 8080 API Key: (from SABnzbd)"
log " (sync to apps so Sonarr/Radarr get SABnzbd too, or add per-app)"
log ""
log "=== Sonarr / Radarr / Lidarr ==="
log "Download Clients → SABnzbd → Host sabnzbd Port 8080"
log " Category: tv | movies | music"
log "Root folders still /data/media/{tv,movies,music} (hardlinks on same /data)"
log ""
if [[ -z "$TWEAKNEWS_USER" || -z "$TWEAKNEWS_PASS" ]]; then
log "NOTE: Tweaknews user/pass not in secrets — add TWEAKNEWS_USER / TWEAKNEWS_PASS and re-run."
fi