Fix quality profile setup and split Recyclarr into include packs

Always sync HD/UHD (and Sonarr WEB) as include packs, name them with
an assemblrr prefix, soften blocking CF scores, zero quality minSize,
relax minimumSeeders, and update Seerr on reconfigure. Document TRaSH
guide drift and tighten comments and uninstall messaging.
This commit is contained in:
soulis-1256 2026-08-05 16:12:47 +03:00
parent a381de1f8f
commit bd126b704e
No known key found for this signature in database
19 changed files with 439 additions and 410 deletions

View file

@ -95,6 +95,35 @@ Configuration lives in your installation directory (default: `~/assemblrr`).
- `compose/custom.yaml`: Optional services (from the example under `compose/examples/`).
- `config/`: Persistent service data.
## Quality Profiles & TRaSH Guides
assemblrr uses [Recyclarr](https://recyclarr.dev/) to sync [TRaSH Guides](https://trash-guides.info/) quality profiles and custom formats into Radarr and Sonarr.
**Both resolutions are always installed** as assemblrr-named profiles (movies: **assemblrr HD Bluray + WEB** + **assemblrr UHD Bluray + WEB**; TV: **assemblrr WEB-1080p** + **assemblrr WEB-2160p**). The setup question only picks Seerr’s *default* for movie requests — the other profile stays available in the quality dropdown. Stock Radarr/Sonarr profiles (Any, HD-1080p, …) also appear there; that is normal.
assemblrr deliberately **does not** apply TRaSH quality min-size limits (they can reject smaller legitimate releases), and softens hard-block custom formats (LQ / x265 / 3D scores set to 0). Tier preferences from the guides still apply when better releases exist.
**Those guides change over time.** Trash IDs, profile names, and Recyclarr YAML schema can all break without warning. When that happens you may see:
- Recyclarr sync errors (`Invalid quality profile trash_id`, `YAML error`, etc.)
- Seerr defaulting to **Any** instead of your chosen quality
- Missing Recyclarr profiles in Radarr/Sonarr (only stock profiles like Any / HD-1080p)
That is expected community-guide churn — not a VPN or Docker failure.
### What to do when it breaks
1. Check Recyclarr: `docker logs recyclarr` and/or `docker exec recyclarr recyclarr sync`
2. List current guide IDs from inside the container:
```bash
docker exec recyclarr recyclarr list quality-profiles radarr
docker exec recyclarr recyclarr list quality-profiles sonarr
```
3. Update the relevant pack under `templates/recyclarr/includes/` (or the live copies in your install’s `config/recyclarr/includes/`) with the new trash IDs. Root config is `templates/recyclarr/recyclarr.yml`.
4. Re-run sync, then refresh Seerr: `assemblrr configure`
We try to keep templates current, but **plan on occasional manual updates** if you rely on TRaSH-backed profiles long-term. Official docs: [Recyclarr](https://recyclarr.dev/) · [TRaSH Guides](https://trash-guides.info/).
## Development
### Windows (powershell)

View file

@ -337,7 +337,7 @@ uninstall_app() {
log_info "Media directory preserved at $MEDIA_DIRECTORY"
fi
else
log_info "Media directory preserved at $MEDIA_DIRECTORY (pass --media with --force to delete it)"
log_info "Media directory preserved at $MEDIA_DIRECTORY"
fi
echo "Removing CLI..."

View file

@ -146,6 +146,16 @@ fi
# Configure Recyclarr (must run before Seerr so quality profiles exist in Radarr/Sonarr)
configure_recyclarr || true
# Enforce minSize=0 and record preferred quality profiles after Recyclarr sync.
if [ -n "$RADARR_API_KEY" ]; then
relax_quality_sizes "Radarr" "7878" "$RADARR_API_KEY" || true
set_default_quality_profile "Radarr" "7878" "$RADARR_API_KEY" "lookup_radarr_profile" || true
fi
if [ -n "$SONARR_API_KEY" ]; then
relax_quality_sizes "Sonarr" "8989" "$SONARR_API_KEY" || true
set_default_quality_profile "Sonarr" "8989" "$SONARR_API_KEY" "lookup_sonarr_profile" || true
fi
# Configure Seerr (must run after media server is configured AND Recyclarr has synced profiles)
configure_seerr || true

View file

@ -239,8 +239,13 @@ copy_configuration_files() {
["compose/vpn.yaml"]="compose/vpn.yaml"
["compose/examples/custom.yaml.example"]="compose/examples/custom.yaml.example"
[".env.example"]=".env.example"
["templates/recyclarr-ultra_hd.yml"]="templates/recyclarr-ultra_hd.yml"
["templates/recyclarr-full_hd.yml"]="templates/recyclarr-full_hd.yml"
["templates/recyclarr/recyclarr.yml"]="templates/recyclarr/recyclarr.yml"
["templates/recyclarr/includes/radarr-hd.yml"]="templates/recyclarr/includes/radarr-hd.yml"
["templates/recyclarr/includes/radarr-uhd.yml"]="templates/recyclarr/includes/radarr-uhd.yml"
["templates/recyclarr/includes/radarr-soft-cfs.yml"]="templates/recyclarr/includes/radarr-soft-cfs.yml"
["templates/recyclarr/includes/sonarr-web-1080.yml"]="templates/recyclarr/includes/sonarr-web-1080.yml"
["templates/recyclarr/includes/sonarr-web-2160.yml"]="templates/recyclarr/includes/sonarr-web-2160.yml"
["templates/recyclarr/includes/sonarr-soft-cfs.yml"]="templates/recyclarr/includes/sonarr-soft-cfs.yml"
["branding.conf"]="branding.conf"
["bin/cli.sh"]="cli.sh"
["bin/configure.sh"]="configure.sh"

View file

@ -48,14 +48,13 @@ set_arr_auth() {
# --- qBittorrent helpers ---
# Set qBittorrent credentials and save path using the temp password from container logs
# Called once before configuring any *arr service.
# On re-runs, tries the final credentials first to avoid triggering brute-force bans.
# Set qBittorrent WebUI credentials and default save paths.
# Prefer final credentials when already configured (avoids brute-force lockouts).
qbit_set_credentials() {
local qbit_port=8081
local qbit_cookie_jar="/tmp/qb_cookie_jar_init_$$_${qbit_port}"
# Try logging in with the final credentials first (already set from a previous run)
# Idempotent: succeed if final credentials already work
if [ -n "$AUTH_USERNAME" ] && [ -n "$AUTH_PASSWORD" ]; then
curl -s --connect-timeout 5 -c "$qbit_cookie_jar" \
-H "Referer: http://${API_HOST}:${qbit_port}" \
@ -64,7 +63,6 @@ qbit_set_credentials() {
local qbit_sid
qbit_sid=$(qbit_cookie_sid "$qbit_cookie_jar")
if [ -n "$qbit_sid" ]; then
# Credentials already set — ensure save path is configured
curl -s --connect-timeout 5 \
"http://${API_HOST}:${qbit_port}/api/v2/app/setPreferences" \
-b "$qbit_cookie_jar" \
@ -77,7 +75,7 @@ qbit_set_credentials() {
fi
fi
# Credentials not set yet — use temp password from container logs
# First-time setup: temporary password from container logs
local wait_time=0
local max_wait=60
@ -116,7 +114,7 @@ qbit_set_credentials() {
return 1
}
# Create a qBittorrent category with a save path
# Create or update a qBittorrent category with a save path
qbit_create_category() {
local service_name="$1"
local category="$2"
@ -131,13 +129,20 @@ qbit_create_category() {
local qbit_sid
qbit_sid=$(qbit_cookie_sid "$qbit_cookie_jar")
if [ -n "$qbit_sid" ]; then
# createCategory + editCategory so savePath is set whether the category is new or existing
curl -s --connect-timeout 10 \
"http://${API_HOST}:${qbit_port}/api/v2/torrents/createCategory" \
-b "$qbit_cookie_jar" \
-H "Referer: http://${API_HOST}:${qbit_port}" \
-d "category=${category}&savePath=${save_path}" \
2>/dev/null >/dev/null || true
log_step "${service_name}: created qBittorrent '${category}' category (${save_path})"
curl -s --connect-timeout 10 \
"http://${API_HOST}:${qbit_port}/api/v2/torrents/editCategory" \
-b "$qbit_cookie_jar" \
-H "Referer: http://${API_HOST}:${qbit_port}" \
-d "category=${category}&savePath=${save_path}" \
2>/dev/null >/dev/null || true
log_step "${service_name}: qBittorrent '${category}' category → ${save_path}"
else
log_step_fail "${service_name}: could not login to qBittorrent to create categories"
fi
@ -184,16 +189,16 @@ configure_arr_service() {
log_step "${service_name}: root folder ${root_path} already exists"
fi
# 1b. Remove stale auto-detected root folders
# Keep only the configured root folder
local all_root_folders
all_root_folders=$(api_get "$port" "/api/v3/rootfolder" "$apikey")
local stale_ids
stale_ids=$(echo "$all_root_folders" | jq -r --arg rp "$root_path" '.[] | select(.path != $rp) | .id' 2>/dev/null || echo "")
local extra_ids
extra_ids=$(echo "$all_root_folders" | jq -r --arg rp "$root_path" '.[] | select(.path != $rp) | .id' 2>/dev/null || echo "")
for stale_id in $stale_ids; do
if [ -n "$stale_id" ]; then
api_delete "$port" "/api/v3/rootfolder/${stale_id}" "$apikey" >/dev/null || true
log_step "${service_name}: removed stale root folder (id: ${stale_id})"
for extra_id in $extra_ids; do
if [ -n "$extra_id" ]; then
api_delete "$port" "/api/v3/rootfolder/${extra_id}" "$apikey" >/dev/null || true
log_step "${service_name}: removed extra root folder (id: ${extra_id})"
fi
done
@ -296,6 +301,81 @@ configure_arr_service() {
set_arr_auth "$service_name" "$port" "$apikey"
}
# --- Quality sizes & default profiles ---
# Set minSize=0 on every quality definition (no minimum file-size filter).
# Values live in the *arr DB; they only change when written via this API.
relax_quality_sizes() {
local service_name="$1"
local port="$2"
local apikey="$3"
local defs
defs=$(api_get "$port" "/api/v3/qualitydefinition" "$apikey")
if [ -z "$defs" ] || [ "$defs" = "[]" ]; then
log_step_fail "${service_name}: no quality definitions to update"
return 1
fi
# Only minSize is cleared; leave max/preferred alone (bulk update is picky about nulls).
local payload
payload=$(echo "$defs" | jq '[.[] | .minSize = 0]' 2>/dev/null || echo "")
if [ -z "$payload" ]; then
log_step_fail "${service_name}: failed to build quality definition payload"
return 1
fi
local result
result=$(api_put "$port" "/api/v3/qualitydefinition/update" "$apikey" "$payload")
if echo "$result" | jq -e 'type == "array"' >/dev/null 2>&1; then
log_step "${service_name}: quality minSize set to 0"
return 0
fi
# Fallback: one PUT per definition
local ok=0 total=0
while IFS= read -r row; do
[ -z "$row" ] && continue
total=$((total + 1))
local id
id=$(echo "$row" | jq -r '.id // empty')
[ -z "$id" ] && continue
if api_put "$port" "/api/v3/qualitydefinition/${id}" "$apikey" "$row" >/dev/null 2>&1; then
ok=$((ok + 1))
fi
done < <(echo "$payload" | jq -c '.[]' 2>/dev/null || true)
if [ "$ok" -gt 0 ]; then
log_step "${service_name}: quality minSize set to 0 (${ok}/${total})"
return 0
fi
log_step_fail "${service_name}: failed to update quality definitions"
return 1
}
# Record the preferred quality profile id/name for this install (setup choice).
set_default_quality_profile() {
local service_name="$1"
local port="$2"
local apikey="$3"
local profile_func="$4"
local profile profile_id
profile=$($profile_func "$apikey")
profile_id="${profile%%:*}"
local profile_name="${profile##*:}"
if [ -z "$profile_id" ] || [ "$profile_id" = "1" ] && [ "$profile_name" = "Any" ]; then
log_step "${service_name}: preferred quality profile → Any"
return 0
fi
if [ -n "${INSTALL_DIR:-}" ]; then
mkdir -p "$INSTALL_DIR/config"
echo "${profile_id}:${profile_name}" > "$INSTALL_DIR/config/.${service_name,,}-default-quality-profile" 2>/dev/null || true
fi
log_step "${service_name}: preferred quality profile → ${profile_name} (id ${profile_id})"
}
# --- Quality profile lookup ---
lookup_radarr_profile() {
@ -308,27 +388,42 @@ lookup_radarr_profile() {
return
fi
# Recyclarr creates profiles with names like "Ultra-HD" or "HD Bluray + WEB"
# Match by keyword since the exact name depends on TRaSH Guide version
# Default Radarr profiles to skip: Any, SD, HD-720p, HD-1080p, HD - 720p/1080p
local target_keyword
# Prefer assemblrr-named Recyclarr profiles; fall back to stock *arr names.
local target_name=""
local stock_fallback=""
if [ "${SEERR_IS_4K:-false}" = "true" ]; then
target_keyword="Ultra"
target_name="assemblrr UHD Bluray + WEB"
stock_fallback="Ultra-HD"
elif [ "${SEERR_DEFAULT_PROFILE:-1}" != "1" ]; then
target_keyword="Bluray + WEB"
target_name="assemblrr HD Bluray + WEB"
stock_fallback="HD-1080p"
else
echo "1:Any"
return
fi
local matched
matched=$(echo "$profiles_json" | jq -r --arg kw "$target_keyword" '.[] | select(.name | contains($kw)) | select(.name as $n | ["Any","SD","HD-720p","HD-1080p","HD - 720p/1080p"] | index($n) | not) | "\(.id):\(.name)"' 2>/dev/null | head -1 || echo "")
matched=$(echo "$profiles_json" | jq -r --arg name "$target_name" '
.[] | select(.name == $name) | "\(.id):\(.name)"
' 2>/dev/null | head -1 || echo "")
if [ -n "$matched" ]; then
echo "$matched"
else
echo "1:Any"
return
fi
if [ -n "$stock_fallback" ]; then
matched=$(echo "$profiles_json" | jq -r --arg name "$stock_fallback" '
.[] | select(.name == $name) | "\(.id):\(.name)"
' 2>/dev/null | head -1 || echo "")
if [ -n "$matched" ]; then
echo "$matched"
return
fi
fi
echo "1:Any"
}
lookup_sonarr_profile() {
@ -337,28 +432,43 @@ lookup_sonarr_profile() {
profiles_json=$(api_get "8989" "/api/v3/qualityprofile" "$apikey")
if [ -z "$profiles_json" ]; then
echo "1:Default"
echo "1:Any"
return
fi
# Recyclarr creates profiles with names like "Ultra-HD" or "WEB-1080p"
# Match by keyword since the exact name depends on TRaSH Guide version
# Default Sonarr profiles to skip: Any, SD, HD-720p, HD-1080p, HD - 720p/1080p
local target_keyword
if [ "${SEERR_IS_4K:-false}" = "true" ]; then
target_keyword="Ultra"
else
target_keyword="WEB"
fi
# Default TV profile is assemblrr WEB-1080p (movies 4K choice does not change this).
local target_name="assemblrr WEB-1080p"
local stock_fallback="HD-1080p"
local matched
matched=$(echo "$profiles_json" | jq -r --arg kw "$target_keyword" '.[] | select(.name | contains($kw)) | select(.name as $n | ["Any","SD","HD-720p","HD-1080p","HD - 720p/1080p"] | index($n) | not) | "\(.id):\(.name)"' 2>/dev/null | head -1 || echo "")
matched=$(echo "$profiles_json" | jq -r --arg name "$target_name" '
.[] | select(.name == $name) | "\(.id):\(.name)"
' 2>/dev/null | head -1 || echo "")
if [ -n "$matched" ]; then
echo "$matched"
else
echo "1:Default"
return
fi
matched=$(echo "$profiles_json" | jq -r '
.[] | select(.name | test("^assemblrr.*WEB.*1080"; "i")) | "\(.id):\(.name)"
' 2>/dev/null | head -1 || echo "")
if [ -n "$matched" ]; then
echo "$matched"
return
fi
if [ -n "$stock_fallback" ]; then
matched=$(echo "$profiles_json" | jq -r --arg name "$stock_fallback" '
.[] | select(.name == $name) | "\(.id):\(.name)"
' 2>/dev/null | head -1 || echo "")
if [ -n "$matched" ]; then
echo "$matched"
return
fi
fi
echo "1:Any"
}
# --- Radarr configuration ---
@ -374,6 +484,58 @@ configure_radarr() {
# --- Prowlarr configuration ---
# Set minimumSeeders=0 on Prowlarr app profiles and *arr indexers.
# Peer counts from indexers are often incomplete; requiring seeders>=1 blocks valid grabs.
relax_minimum_seeders() {
local prowlarr_key="$1"
local radarr_key="${2:-}"
local sonarr_key="${3:-}"
local profiles
profiles=$(api_get "9696" "/api/v1/appprofile" "$prowlarr_key")
if [ -n "$profiles" ] && [ "$profiles" != "[]" ]; then
local profile_id profile_payload
while IFS= read -r row; do
[ -z "$row" ] && continue
profile_id=$(echo "$row" | jq -r '.id // empty')
[ -z "$profile_id" ] && continue
profile_payload=$(echo "$row" | jq '.minimumSeeders = 0' 2>/dev/null || echo "")
[ -z "$profile_payload" ] && continue
if api_put "9696" "/api/v1/appprofile/${profile_id}" "$prowlarr_key" "$profile_payload" >/dev/null 2>&1; then
log_step "Prowlarr: app profile '${profile_id}' minimumSeeders → 0"
fi
done < <(echo "$profiles" | jq -c '.[]' 2>/dev/null || true)
fi
local port key name
for port_key_name in "7878:${radarr_key}:Radarr" "8989:${sonarr_key}:Sonarr"; do
port="${port_key_name%%:*}"
rest="${port_key_name#*:}"
key="${rest%%:*}"
name="${rest#*:}"
[ -z "$key" ] && continue
local indexers
indexers=$(api_get "$port" "/api/v3/indexer" "$key")
[ -z "$indexers" ] || [ "$indexers" = "[]" ] && continue
while IFS= read -r idx; do
[ -z "$idx" ] && continue
local idx_id idx_payload
idx_id=$(echo "$idx" | jq -r '.id // empty')
[ -z "$idx_id" ] && continue
idx_payload=$(echo "$idx" | jq '
.fields = [.fields[] |
if .name == "minimumSeeders" then .value = 0 else . end
]
' 2>/dev/null || echo "")
[ -z "$idx_payload" ] && continue
api_put "$port" "/api/v3/indexer/${idx_id}" "$key" "$idx_payload" >/dev/null 2>&1 || true
done < <(echo "$indexers" | jq -c '.[]' 2>/dev/null || true)
log_step "${name}: indexer minimumSeeders → 0"
done
}
configure_prowlarr() {
local apikey="$1"
local radarr_apikey="$2"
@ -436,8 +598,8 @@ configure_prowlarr() {
fi
fi
# 2. Add public indexers
echo "Adding ${#PUBLIC_INDEXERS[@]} indexer(s) to Prowlarr" >&2
# 2. Add selected indexers
echo "Adding ${#SELECTED_INDEXERS[@]} indexer(s) to Prowlarr" >&2
local indexer_schemas
indexer_schemas=$(api_get "9696" "/api/v1/indexer/schema" "$apikey")
@ -452,7 +614,7 @@ configure_prowlarr() {
local existing_names
existing_names=$(jq_json_list_values "$existing_indexers" "name")
for indexer_name in ${PUBLIC_INDEXERS[@]+"${PUBLIC_INDEXERS[@]}"}; do
for indexer_name in ${SELECTED_INDEXERS[@]+"${SELECTED_INDEXERS[@]}"}; do
# Skip if already added
if echo "$existing_names" | grep -q -F -x "$indexer_name"; then
log_step "Prowlarr: ${indexer_name} indexer already exists"
@ -502,7 +664,9 @@ configure_prowlarr() {
echo >&2
log_success "Indexers added to Prowlarr!" >&2
# 3. Set authentication
relax_minimum_seeders "$apikey" "$radarr_apikey" "${sonarr_apikey:-}"
# 4. Set authentication
set_arr_auth "Prowlarr" "9696" "$apikey" "v1"
}

View file

@ -245,7 +245,7 @@ prepare_install_dirs() {
"scripts"
)
# Reclaim install root if a previous run left it root-owned
# Ensure install root is owned by the target user
if [ -d "$install_dir" ] && [ ! -w "$install_dir" ]; then
ensure_owned "$install_dir" "$(id -u)" "$(id -g)"
fi

View file

@ -1,12 +1,12 @@
#!/bin/bash
# fzf-based TUI for selections (Prowlarr indexers, Jellyfin languages)
# Provides reusable fzf selection patterns for assemblrr.
# Sets PUBLIC_INDEXERS array for indexers.
# Sets SELECTED_INDEXERS array for Prowlarr.
# Usage: source lib/fzf-tui.sh; configure_indexers "$api_key"
set -euo pipefail
PUBLIC_INDEXERS=()
SELECTED_INDEXERS=()
# --- TTY detection (reused across functions) ---
_fzf_has_tty() {
@ -73,8 +73,8 @@ fzf_single_select() {
}
# --- Generic multi-select fzf (for indexers) ---
# Args: $1 = data_source (jq expression or curl), $2 = awk filter
# Sets PUBLIC_INDEXERS array
# Args: $1 = tab-separated list lines
# Sets SELECTED_INDEXERS array
fzf_multi_select() {
local data="$1"
local has_tty=false
@ -104,20 +104,20 @@ fzf_multi_select() {
if [ -n "$selected" ]; then
while IFS= read -r idx; do
[ -n "$idx" ] && PUBLIC_INDEXERS+=("$idx")
[ -n "$idx" ] && SELECTED_INDEXERS+=("$idx")
done <<< "$selected"
echo "Selected ${#PUBLIC_INDEXERS[@]} indexer(s): $(IFS=,; echo "${PUBLIC_INDEXERS[*]}")" >&2
echo "Selected ${#SELECTED_INDEXERS[@]} indexer(s): $(IFS=,; echo "${SELECTED_INDEXERS[*]}")" >&2
else
echo "No indexers selected." >&2
fi
else
# No TTY or no fzf — show top public indexers and prompt
echo "No interactive terminal available — listing popular public indexers." >&2
echo "$data" | jq -r 'sort_by(.name | ascii_downcase) | .[0:20][] | " \(.name)"' 2>/dev/null >&2
# No TTY or no fzf — list options and prompt
echo "No interactive terminal available — listing available indexers." >&2
echo "$data" | cut -f1 | head -20 | sed 's/^/ /' >&2
echo "Enter indexer names separated by spaces (or blank to skip):" >&2
read -r input_line || true
for idx in $input_line; do
PUBLIC_INDEXERS+=("$idx")
SELECTED_INDEXERS+=("$idx")
done
fi
}

View file

@ -7,8 +7,9 @@
set -euo pipefail
# --- Shared helper: connect a service (Radarr/Sonarr) to Seerr ---
# Usage: seerr_connect_service <service_type> <port> <api_key> <profile_func> <active_dir> <is_4k> <cookie_jar>
# --- Shared helper: connect or update a service (Radarr/Sonarr) in Seerr ---
# Usage: seerr_connect_service <service_type> <port> <api_key> <profile_func> <active_dir> <is_4k> <cookie_jar> [existing_id]
# With existing_id: PUT update; without: POST create.
# Example: seerr_connect_service "radarr" 7878 "$RADARR_API_KEY" "lookup_radarr_profile" "/data/media/movies" "true" "$cookie_jar"
seerr_connect_service() {
local service_type="$1"
@ -18,6 +19,7 @@ seerr_connect_service() {
local active_dir="$5"
local is_4k="$6"
local cookie_jar="$7"
local existing_id="${8:-}"
if [ -z "$api_key" ]; then
log_step_fail "Seerr: ${service_type} API key not provided"
@ -29,13 +31,12 @@ seerr_connect_service() {
return 1
fi
# Look up quality profile from the service (created by Recyclarr)
local profile
profile=$($profile_func "$api_key")
local profile_id="${profile%%:*}"
local profile_name="${profile##*:}"
# Build the service payload
# id is read-only on PUT — omit it from the body
local payload
payload=$(cat <<EOF
{
@ -62,15 +63,29 @@ EOF
payload=$(echo "$payload" | jq '.enableSeasonFolders = true' 2>/dev/null || echo "$payload")
fi
# POST to Seerr
local http_code
if [ -n "$existing_id" ]; then
http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 -X PUT -b "$cookie_jar" \
-H "Content-Type: application/json" \
-d "$payload" \
"http://${API_HOST}:5055/api/v1/settings/${service_type}/${existing_id}" 2>/dev/null || echo "000")
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
log_step "Seerr: updated ${service_type^} profile → ${profile_name}"
return 0
else
log_step_fail "Seerr: failed to update ${service_type} (HTTP $http_code)"
return 1
fi
fi
# POST new connection
http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 -X POST -b "$cookie_jar" \
-H "Content-Type: application/json" \
-d "$payload" \
"http://${API_HOST}:5055/api/v1/settings/${service_type}" 2>/dev/null || echo "000")
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
log_step "Seerr: connected ${service_type^}"
log_step "Seerr: connected ${service_type^} (profile: ${profile_name})"
return 0
else
log_step_fail "Seerr: failed to connect ${service_type} (HTTP $http_code)"
@ -99,6 +114,24 @@ seerr_service_connected() {
return 0
}
# --- Shared helper: first existing Seerr server id for a service (or empty) ---
# Usage: seerr_service_id <service_type> <cookie_jar>
seerr_service_id() {
local service_type="$1"
local cookie_jar="$2"
local settings
settings=$(curl -sf --connect-timeout 5 -b "$cookie_jar" \
"http://${API_HOST}:5055/api/v1/settings/${service_type}" 2>/dev/null || echo "")
if [ -z "$settings" ] || [ "$settings" = "[]" ]; then
echo ""
return 1
fi
echo "$settings" | jq -r '.[0].id // empty' 2>/dev/null || echo ""
}
# --- Shared helper: get Seerr session cookie ---
# Usage: seerr_get_cookie <cookie_jar> <include_hostname>
# Returns 0 on success, cookie file will be populated
@ -158,42 +191,60 @@ EOF
configure_recyclarr() {
local recyclarr_config_dir="$INSTALL_DIR/config/recyclarr"
mkdir -p "$recyclarr_config_dir"
local template_root="$INSTALL_DIR/templates/recyclarr"
mkdir -p "$recyclarr_config_dir/includes"
if [ ! -w "$recyclarr_config_dir" ]; then
log_step_fail "Recyclarr: config directory not writable (${recyclarr_config_dir})"
return 1
fi
# Export variables for envsubst
# Only substitute known vars so $schema in YAML comments is left alone
export RADARR_API_KEY SONARR_API_KEY
# Pick the right template based on user's 4K choice
local template_file="recyclarr-full_hd.yml" # default: 1080p
local profile_label="HD Bluray + WEB"
local default_label="assemblrr HD Bluray + WEB"
if [ "${SEERR_IS_4K}" = "true" ]; then
template_file="recyclarr-ultra_hd.yml" # 4K
profile_label="UHD Bluray + WEB"
default_label="assemblrr UHD Bluray + WEB"
fi
if [ -f "$INSTALL_DIR/templates/${template_file}" ]; then
if envsubst < "$INSTALL_DIR/templates/${template_file}" > "$recyclarr_config_dir/recyclarr.yml"; then
log_step "Recyclarr: generated config (${profile_label} profile)"
else
if [ ! -f "$template_root/recyclarr.yml" ]; then
log_step_fail "Recyclarr: template root not found (${template_root}/recyclarr.yml)"
return 1
fi
if ! envsubst '${RADARR_API_KEY} ${SONARR_API_KEY}' \
< "$template_root/recyclarr.yml" \
> "$recyclarr_config_dir/recyclarr.yml"; then
log_step_fail "Recyclarr: failed to write config (${recyclarr_config_dir}/recyclarr.yml)"
return 1
fi
else
log_step_fail "Recyclarr: template ${template_file} not found"
# Include packs (no secrets). Replace the directory contents with the template set.
local include_src="$template_root/includes"
if [ ! -d "$include_src" ]; then
log_step_fail "Recyclarr: includes directory not found (${include_src})"
return 1
fi
rm -f "$recyclarr_config_dir/includes"/*.yml 2>/dev/null || true
if ! cp "$include_src"/*.yml "$recyclarr_config_dir/includes/"; then
log_step_fail "Recyclarr: failed to copy include packs"
return 1
fi
# Trigger a sync
local pack_count
pack_count=$(find "$recyclarr_config_dir/includes" -maxdepth 1 -name '*.yml' | wc -l | tr -d ' ')
log_step "Recyclarr: generated config (${pack_count} include packs; Seerr default: ${default_label})"
_cfg_log_info "Recyclarr: syncing TRaSH Guides to Radarr and Sonarr... this might take a moment"
if docker exec recyclarr recyclarr sync > /dev/null 2>&1; then
local sync_out
if sync_out=$(docker exec recyclarr recyclarr sync 2>&1); then
log_step "Recyclarr: synced Custom Formats and Quality Profiles successfully"
else
log_step_fail "Recyclarr: failed to sync to Radarr/Sonarr (check docker logs recyclarr)"
log_step_fail "Recyclarr: failed to sync to Radarr/Sonarr"
echo "$sync_out" | grep -E '•|Error|error|Invalid|YAML' | head -5 | while IFS= read -r line; do
_cfg_log_info " $line"
done
return 1
fi
}
@ -245,31 +296,21 @@ configure_seerr() {
echo "Connecting Seerr services" >&2
# Connect Radarr if not already connected
if [ -n "$RADARR_API_KEY" ]; then
local radarr_count
radarr_count=$(seerr_service_connected "radarr" "$seerr_cookie_jar") || radarr_count=0
if [ "$radarr_count" -eq 0 ]; then
local radarr_id
radarr_id=$(seerr_service_id "radarr" "$seerr_cookie_jar" || true)
if ! seerr_connect_service "radarr" 7878 "$RADARR_API_KEY" "lookup_radarr_profile" \
"/data/media/movies" "${SEERR_IS_4K:-false}" "$seerr_cookie_jar"; then
log_step_fail "Seerr: failed to connect Radarr (re-run to retry)"
fi
else
log_step "Seerr: Radarr already connected"
"/data/media/movies" "${SEERR_IS_4K:-false}" "$seerr_cookie_jar" "$radarr_id"; then
log_step_fail "Seerr: failed to configure Radarr (re-run to retry)"
fi
fi
# Connect Sonarr if not already connected
if [ -n "$SONARR_API_KEY" ]; then
local sonarr_count
sonarr_count=$(seerr_service_connected "sonarr" "$seerr_cookie_jar") || sonarr_count=0
if [ "$sonarr_count" -eq 0 ]; then
local sonarr_id
sonarr_id=$(seerr_service_id "sonarr" "$seerr_cookie_jar" || true)
if ! seerr_connect_service "sonarr" 8989 "$SONARR_API_KEY" "lookup_sonarr_profile" \
"/data/media/tv" "false" "$seerr_cookie_jar"; then
log_step_fail "Seerr: failed to connect Sonarr (re-run to retry)"
fi
else
log_step "Seerr: Sonarr already connected"
"/data/media/tv" "false" "$seerr_cookie_jar" "$sonarr_id"; then
log_step_fail "Seerr: failed to configure Sonarr (re-run to retry)"
fi
fi
@ -350,8 +391,7 @@ EOF
return 1
fi
# Check for error in response — "hostname already configured" means media server
# was connected by a previous run, which is fine (admin user already exists)
# "already configured" is success when re-running against an initialized Seerr
local auth_error
auth_error=$(echo "$auth_response" | jq -r '.error // ""' 2>/dev/null || echo "")
if [ -n "$auth_error" ]; then
@ -365,7 +405,6 @@ EOF
return 1
fi
else
# Successful auth — verify admin user was created
local auth_id
auth_id=$(echo "$auth_response" | jq -r '.id // ""' 2>/dev/null || echo "")
if [ -n "$auth_id" ]; then
@ -377,12 +416,10 @@ EOF
fi
fi
# Step 5: Get a session cookie for subsequent API calls
# Step 5: session cookie for subsequent API calls
local seerr_cookie_jar="/tmp/seerr_cookie_jar_$$_${seerr_port}"
# Get session cookie (with hostname for initial setup)
if ! seerr_get_cookie "$seerr_cookie_jar" "true"; then
# Retry with login-only if first attempt fails (hostname already configured)
if ! seerr_get_cookie "$seerr_cookie_jar" "false"; then
log_step_fail "Seerr: failed to get session cookie"
rm -f "$seerr_cookie_jar"
@ -390,10 +427,7 @@ EOF
fi
fi
# Note: Library sync is skipped here — Jellyfin hasn't indexed anything yet on first setup.
# Seerr will auto-sync libraries periodically (every 24h) once content exists.
# Step 6: Initialize Seerr (mark setup as complete)
# Step 6: mark setup complete
local init_code
init_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 -X POST -b "$seerr_cookie_jar" \
-H "Content-Type: application/json" \

View file

@ -250,7 +250,9 @@ cp /tmp/$AppName/compose/base.yaml /tmp/$AppName/compose/vpn.yaml /tmp/$AppName/
mkdir -p "`$INSTALL_DIR/compose/examples"
cp /tmp/$AppName/compose/examples/custom.yaml.example "`$INSTALL_DIR/compose/examples/" 2>/dev/null || true
cp /tmp/$AppName/.env.example "`$INSTALL_DIR/" 2>/dev/null || true
cp /tmp/$AppName/templates/recyclarr-full_hd.yml /tmp/$AppName/templates/recyclarr-ultra_hd.yml "`$INSTALL_DIR/templates/"
mkdir -p "`$INSTALL_DIR/templates/recyclarr/includes"
cp /tmp/$AppName/templates/recyclarr/recyclarr.yml "`$INSTALL_DIR/templates/recyclarr/"
cp /tmp/$AppName/templates/recyclarr/includes/*.yml "`$INSTALL_DIR/templates/recyclarr/includes/"
mkdir -p "`$INSTALL_DIR/scripts"
cp /tmp/$AppName/scripts/* "`$INSTALL_DIR/scripts/"
echo "Files synced to install directory"

View file

@ -1,146 +0,0 @@
# yaml-language-server: $schema=https://schemas.recyclarr.dev/v8/config-schema.json
# HD Bluray + WEB profile (1080p) — used when user chooses non-4K
# Template: recyclarr-full_hd.yml
radarr:
radarr-instance:
base_url: http://radarr:7878
api_key: ${RADARR_API_KEY}
quality_definition:
type: movie
quality_profiles:
- name: HD Bluray + WEB
reset_unmatched_scores:
enabled: true
upgrade:
allowed: true
until_quality: Bluray-1080p
until_score: 10000
min_format_score: 0
quality_sort: top
qualities:
- name: Bluray-1080p
- name: WEB 1080p
qualities:
- WEBDL-1080p
- WEBRip-1080p
- name: Bluray-720p
custom_formats:
# HQ Release Groups + Misc + Unwanted
- trash_ids:
- ed27ebfef2f323e964fb1f61391bcb35 # HD Bluray Tier 01
- c20c8647f2746a1f4c4262b0fbbeeeae # HD Bluray Tier 02
- 5608c71bcebba0a5e666223bae8c9227 # HD Bluray Tier 03
- c20f169ef63c5f40c2def54abaf4438e # WEB Tier 01
- 403816d65392c79236dcb6dd591aeda4 # WEB Tier 02
- af94e0fe497124d1f9ce732069ec8c3b # WEB Tier 03
- e7718d7a3ce595f289bfee26adc178f5 # Repack/Proper
- ae43b294509409a6a13919dedd4764c4 # Repack2
- 5caaaa1c08c1742aa4342d8c4cc463f2 # Repack3
- ed38b889b31be83fda192888e2286d83 # BR-DISK
- e6886871085226c3da1830830146846c # Generated Dynamic HDR
- 90a6f9a284dff5103f6346090e6280c8 # LQ
- e204b80c87be9497a8a6eaff48f72905 # LQ (Release Title)
- dc98083864ea246d05a42df0d05f81cc # x265 (HD)
- b8cd450cbfa689c0259a01d9e29ba3d6 # 3D
- bfd8eb01832d646a0a89c4deb46f8564 # Upscaled
- 0a3f082873eb454bde444150b70253cc # Extras
- 712d74cd88bceb883ee32f773656b1f5 # Sing-Along Versions
- cae4ca30163749b891686f95532519bd # AV1
- cc5e51a9e85a6296ceefe097a77f12f4 # BCORE
- 16622a6911d1ab5d5b8b713d5b0036d4 # CRiT
- 2a6039655313bf5dab1e43523b62c374 # MA
assign_scores_to:
- name: HD Bluray + WEB
# Streaming Services
- trash_ids:
- b3b3a6ac74ecbd56bcdbefa4799fb9df # AMZN
- 40e9380490e748672c2522eaaeb692f7 # ATVP
- 84272245b2988854bfb76a16e60baea5 # DSNP
- 509e5f41146e278f9eab1ddaceb34515 # HBO
- 5763d1b0ce84aff3b21038eea8e9b8ad # HMAX
- 526d445d4c16214309f0fd2b3be18a89 # Hulu
- e0ec9672be6cac914ffad34a6b077209 # iT
- 6a061313d22e51e0f25b7cd4dc065233 # MAX
- 170b1d363bd8516fbf3a3eb05d4faff6 # NF
- c9fd353f8f5f1baf56dc601c4cb29920 # PCOK
- e36a0ba1bc902b26ee40818a1d59b8bd # PMTP
- c2863d2a50c9acad1fb50e53ece60817 # STAN
assign_scores_to:
- name: HD Bluray + WEB
# Audio - Uncomment to enable Advanced Audio Formats
- trash_ids:
# - 496f355514737f7d83bf7aa4d24f8169 # TrueHD Atmos
# - 2f22d89048b01681dde8afe203bf2e95 # DTS X
# - 417804f7f2c4308c1f4c5d380d4c4475 # ATMOS (undefined)
# - 1af239278386be2919e1bcee0bde047e # DD+ ATMOS
# - 3cafb66171b47f226146a0770576870f # TrueHD
# - dcf3ec6938fa32445f590a4da84256cd # DTS-HD MA
# - a570d4a0e56a2874b64e5bfa55202a1b # FLAC
# - e7c2fcae07cbada050a0af3357491d7b # PCM
# - 8e109e50e0a0b83a5098b056e13bf6db # DTS-HD HRA
# - 185f1dd7264c4562b9022d963ac37424 # DD+
# - f9f847ac70a0af62ea4a08280b859636 # DTS-ES
# - 1c1a4c5e823891c75bc50380a6866f73 # DTS
# - 240770601cc226190c367ef59aba7463 # AAC
# - c2998bd0d90ed5621d8df281e839436e # DD
assign_scores_to:
- name: HD Bluray + WEB
# Movie Versions - Uncomment to prefer specific versions
- trash_ids:
# - 570bc9ebecd92723d2d21500f4be314c # Remaster
# - eca37840c13c6ef2dd0262b141a5482f # 4K Remaster
# - e0c07d59beb37348e975a930d5e50319 # Criterion Collection
# - 9d27d9d2181838f76dee150882bdc58c # Masters of Cinema
# - db9b4c4b53d312a3ca5f1378f6440fc9 # Vinegar Syndrome
# - 957d0f44b592285f26449575e8b1167e # Special Edition
# - eecf3a857724171f968a66cb5719e152 # IMAX
# - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced
assign_scores_to:
- name: HD Bluray + WEB
# Optional Unwanted
- trash_ids:
# - b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups
# - cc444569854e9de0b084ab2b8b1532b2 # Black and White Editions
# - ae9b7c9ebde1f3bd336a8cbd1ec4c5e5 # No-RlsGroup
# - 7357cf5161efbf8c4d5d0c30b4815ee2 # Obfuscated
# - 5c44f52a8714fdd79bb4d98e2673be1f # Retags
# - f537cf427b64c38c8e36298f657e4828 # Scene
assign_scores_to:
- name: HD Bluray + WEB
sonarr:
sonarr-instance:
base_url: http://sonarr:8989
api_key: ${SONARR_API_KEY}
quality_definition:
type: series
quality_profiles:
- trash_id: a5ffae4bbda71217e132ce4ed37367c0 # WEB-1080p
reset_unmatched_scores:
enabled: true
custom_format_groups:
add:
- trash_id: 7a2ba4144a594826d4ac03515b371937 # [Optional] Streaming Services
select_all: true
custom_formats:
# Optional
- trash_ids:
# - 32b367365729d530ca1c124a0b180c64 # Bad Dual Groups
# - 82d40da2bc6923f41e14394075dd4b03 # No-RlsGroup
# - e1a997ddb54e3ecbfe06341ad323c458 # Obfuscated
# - 06d66ab109d4d2eddb2794d21526d140 # Retags
# - 1b3994c551cbb92a2c781af061f4ab44 # Scene
assign_scores_to:
- name: WEB-1080p

View file

@ -1,152 +0,0 @@
# yaml-language-server: $schema=https://schemas.recyclarr.dev/v8/config-schema.json
# UHD Bluray + WEB profile (4K) — used when user chooses Ultra-HD
# Template: recyclarr-ultra_hd.yml
radarr:
radarr-instance:
base_url: http://radarr:7878
api_key: ${RADARR_API_KEY}
quality_definition:
type: movie
quality_profiles:
- trash_id: 64fb5f9858489bdac2af690e27c8f42f # UHD Bluray + WEB
reset_unmatched_scores:
enabled: true
custom_format_groups:
add:
- trash_id: ff204bbcecdd487d1cefcefdbf0c278d # [Optional] Golden Rule UHD
select:
- dc98083864ea246d05a42df0d05f81cc # x265 (HD)
- 839bea857ed2c0a8e084f3cbdbd65ecb # x265 (no HDR/DV)
- trash_id: a3ac6af01d78e4f21fcb75f601ac96df # [Unwanted] Unwanted Formats
select:
- b8cd450cbfa689c0259a01d9e29ba3d6 # 3D
- cae4ca30163749b891686f95532519bd # AV1
- b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups
- cc444569854e9de0b084ab2b8b1532b2 # Black and White Editions
- ed38b889b31be83fda192888e2286d83 # BR-DISK
- 0a3f082873eb454bde444150b70253cc # Extras
- e6886871085226c3da1830830146846c # Generated Dynamic HDR
- 90a6f9a284dff5103f6346090e6280c8 # LQ
- e204b80c87be9497a8a6eaff48f72905 # LQ (Release Title)
- 712d74cd88bceb883ee32f773656b1f5 # Sing-Along Versions
- bfd8eb01832d646a0a89c4deb46f8564 # Upscaled
custom_formats:
# Audio - Uncomment to enable Advanced Audio Formats
- trash_ids:
# - 496f355514737f7d83bf7aa4d24f8169 # TrueHD Atmos
# - 2f22d89048b01681dde8afe203bf2e95 # DTS X
# - 417804f7f2c4308c1f4c5d380d4c4475 # ATMOS (undefined)
# - 1af239278386be2919e1bcee0bde047e # DD+ ATMOS
# - 3cafb66171b47f226146a0770576870f # TrueHD
# - dcf3ec6938fa32445f590a4da84256cd # DTS-HD MA
# - a570d4a0e56a2874b64e5bfa55202a1b # FLAC
# - e7c2fcae07cbada050a0af3357491d7b # PCM
# - 8e109e50e0a0b83a5098b056e13bf6db # DTS-HD HRA
# - 185f1dd7264c4562b9022d963ac37424 # DD+
# - f9f847ac70a0af62ea4a08280b859636 # DTS-ES
# - 1c1a4c5e823891c75bc50380a6866f73 # DTS
# - 240770601cc226190c367ef59aba7463 # AAC
# - c2998bd0d90ed5621d8df281e839436e # DD
assign_scores_to:
- name: UHD Bluray + WEB
# Movie Versions - Uncomment to prefer specific versions
- trash_ids:
# - 570bc9ebecd92723d2d21500f4be314c # Remaster
# - eca37840c13c6ef2dd0262b141a5482f # 4K Remaster
# - e0c07d59beb37348e975a930d5e50319 # Criterion Collection
# - 9d27d9d2181838f76dee150882bdc58c # Masters of Cinema
# - db9b4c4b53d312a3ca5f1378f6440fc9 # Vinegar Syndrome
# - 957d0f44b592285f26449575e8b1167e # Special Edition
# - eecf3a857724171f968a66cb5719e152 # IMAX
# - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced
assign_scores_to:
- name: UHD Bluray + WEB
# Optional Unwanted
- trash_ids:
# - b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups
# - cc444569854e9de0b084ab2b8b1532b2 # Black and White Editions
# - ae9b7c9ebde1f3bd336a8cbd1ec4c5e5 # No-RlsGroup
# - 7357cf5161efbf8c4d5d0c30b4815ee2 # Obfuscated
# - 5c44f52a8714fdd79bb4d98e2673be1f # Retags
# - f537cf427b64c38c8e36298f657e4828 # Scene
assign_scores_to:
- name: UHD Bluray + WEB
# HDR/DV Preferences
- trash_ids:
# Uncomment to allow x265 HD releases with HDR/DV
# - dc98083864ea246d05a42df0d05f81cc # x265 (HD)
# assign_scores_to:
# - name: UHD Bluray + WEB
# score: 0
# - trash_ids:
# - 839bea857ed2c0a8e084f3cbdbd65ecb # x265 (no HDR/DV)
assign_scores_to:
- name: UHD Bluray + WEB
- trash_ids:
# Comment out the next line if all your setups are fully DV compatible
- 923b6abef9b17f937fab56cfcf89e1f1 # DV (w/o HDR fallback)
# HDR10+ Boost - Uncomment if you want to prefer HDR10+ releases
# DV Boost - Uncomment if you want to prefer DV releases
# Uncomment both if you want to prefer both (DV HDR10+)
# - b337d6812e06c200ec9a2d3cfa9d20a7 # DV Boost
# - caa37d0df9c348912df1fb1d88f9273a # HDR10+ Boost
assign_scores_to:
- name: UHD Bluray + WEB
# SDR Blocking - Only use ONE of the following
- trash_ids:
- 9c38ebb7384dada637be8899efa68e6f # SDR (block ALL SDR releases)
# - 25c12f78430a3a23413652cbd1d48d77 # SDR (no WEBDL) - allow SDR WEB only
assign_scores_to:
- name: UHD Bluray + WEB
sonarr:
sonarr-instance:
base_url: http://sonarr:8989
api_key: ${SONARR_API_KEY}
quality_definition:
type: series
quality_profiles:
- trash_id: a5ffae4bbda71217e132ce4ed37367c0 # WEB-1080p
reset_unmatched_scores:
enabled: true
custom_format_groups:
add:
- trash_id: 7a2ba4144a594826d4ac03515b371937 # [Optional] Streaming Services
select_all: true
custom_formats:
# Optional
- trash_ids:
# - 32b367365729d530ca1c124a0b180c64 # Bad Dual Groups
# - 82d40da2bc6923f41e14394075dd4b03 # No-RlsGroup
# - e1a997ddb54e3ecbfe06341ad323c458 # Obfuscated
# - 06d66ab109d4d2eddb2794d21526d140 # Retags
# - 1b3994c551cbb92a2c781af061f4ab44 # Scene
assign_scores_to:
- name: WEB-1080p
# x265 HD handling
- trash_ids:
# Uncomment to allow x265 HD releases with HDR/DV
# - 47435ece6b99a0b477caf360e79ba0bb # x265 (HD)
# assign_scores_to:
# - name: WEB-1080p
# score: 0
# - trash_ids:
# - 9b64dff695c2115facf1b6ea59c9bd07 # x265 (no HDR/DV)
assign_scores_to:
- name: WEB-1080p

View file

@ -0,0 +1,8 @@
# Include: Radarr 1080p profile (guide-backed HD Bluray + WEB)
quality_profiles:
- trash_id: d1d67249d3890e49bc12e275d989a7e9 # HD Bluray + WEB
name: assemblrr HD Bluray + WEB
reset_unmatched_scores:
enabled: true
min_format_score: -1000

View file

@ -0,0 +1,14 @@
# Soften hard-block custom formats on assemblrr Radarr profiles
custom_formats:
- trash_ids:
- 90a6f9a284dff5103f6346090e6280c8 # LQ
- e204b80c87be9497a8a6eaff48f72905 # LQ (Release Title)
- dc98083864ea246d05a42df0d05f81cc # x265 (HD)
- 839bea857ed2c0a8e084f3cbdbd65ecb # x265 (no HDR/DV)
- b8cd450cbfa689c0259a01d9e29ba3d6 # 3D
assign_scores_to:
- name: assemblrr HD Bluray + WEB
score: 0
- name: assemblrr UHD Bluray + WEB
score: 0

View file

@ -0,0 +1,8 @@
# Include: Radarr 4K profile (guide-backed UHD Bluray + WEB)
quality_profiles:
- trash_id: 64fb5f9858489bdac2af690e27c8f42f # UHD Bluray + WEB
name: assemblrr UHD Bluray + WEB
reset_unmatched_scores:
enabled: true
min_format_score: -1000

View file

@ -0,0 +1,14 @@
# Soften hard-block custom formats on assemblrr Sonarr profiles
custom_formats:
- trash_ids:
- 9c11cd3f07101cdba90a2d81cf0e56b4 # LQ
- e2315f990da2e2cbfc9fa5b7a6fcfe48 # LQ (Release Title)
- 47435ece6b99a0b477caf360e79ba0bb # x265 (HD)
- 9b64dff695c2115facf1b6ea59c9bd07 # x265 (no HDR/DV)
- c9eafd50846d299b862ca9bb6ea91950 # x265
assign_scores_to:
- name: assemblrr WEB-1080p
score: 0
- name: assemblrr WEB-2160p
score: 0

View file

@ -0,0 +1,8 @@
# Include: Sonarr 1080p profile (guide-backed WEB-1080p)
quality_profiles:
- trash_id: 72dae194fc92bf828f32cde7744e51a1 # WEB-1080p
name: assemblrr WEB-1080p
reset_unmatched_scores:
enabled: true
min_format_score: -1000

View file

@ -0,0 +1,8 @@
# Include: Sonarr 4K profile (guide-backed WEB-2160p)
quality_profiles:
- trash_id: d1498e7d189fbe6c7110ceaabb7473e6 # WEB-2160p
name: assemblrr WEB-2160p
reset_unmatched_scores:
enabled: true
min_format_score: -1000

View file

@ -0,0 +1,23 @@
# yaml-language-server: $schema=https://schemas.recyclarr.dev/v8/config-schema.json
# Root: instance URLs/keys + include list. Profile packs are under includes/.
# All packs listed here are synced; Seerr's default is chosen at setup.
# See README "Quality Profiles & TRaSH Guides".
radarr:
radarr-instance:
base_url: http://radarr:7878
api_key: ${RADARR_API_KEY}
# No quality_definition → no min/max size filters from Recyclarr.
include:
- config: radarr-hd.yml
- config: radarr-uhd.yml
- config: radarr-soft-cfs.yml
sonarr:
sonarr-instance:
base_url: http://sonarr:8989
api_key: ${SONARR_API_KEY}
include:
- config: sonarr-web-1080.yml
- config: sonarr-web-2160.yml
- config: sonarr-soft-cfs.yml

View file

@ -7,7 +7,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/../helpers.sh"
# Ubuntu 22.04 desktop infohash + public trackers
# Ubuntu 22.04 desktop infohash (official FOSS image)
TARGET_HASH="3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0"
MAGNET="magnet:?xt=urn:btih:${TARGET_HASH}&dn=ubuntu-22.04.4-desktop-amd64.iso&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A6969%2Fannounce"