Add Sonarr discovery; wire search commands to all arr adds

- New: Media/playback_aware_sonarr_discovery.sh — two-stage TV show
  discovery using Emby episode play history → TMDB TV recommendations.
  Multi-user aware: diversity score (0-50) is primary seed driver so one
  user binge-watching alone cannot dominate. Per-user episode cap (default 8)
  limits single-user volume contribution. TMDB→TVDB via external_ids for
  reliable Sonarr lookup. monitor=future by default.

- Add to WEEKLY_MAINTENANCE_SCRIPTS; Sonarr discovery config block in
  master.conf (threshold=52, lookback=14d, max_adds=3, user_ep_cap=8).

- Fix: all arr add scripts were not triggering searches after adding.
  Added _radarr_command/_lidarr_command/_sonarr_command helpers and fire
  MoviesSearch/ArtistSearch/SeriesSearch immediately after each successful
  add. Affects: playback_aware_radarr_discovery.sh, emby_to_lidarr_sync.sh,
  emby_to_radarr_sync.sh, emby_to_sonarr_sync.sh.
This commit is contained in:
Gmer4Lfe
2026-05-20 17:27:07 -04:00
parent 9d371f6e27
commit 6ffe5bea70
6 changed files with 879 additions and 0 deletions
+10
View File
@@ -102,6 +102,14 @@ _lidarr_post() {
"${LIDARR_URL}/api/v1/artist" 2>/dev/null
}
_lidarr_command() {
curl -sf --max-time 20 -X POST \
-H "X-Api-Key: $LIDARR_API_KEY" \
-H "Content-Type: application/json" \
-d "$1" \
"${LIDARR_URL}/api/v1/command" 2>/dev/null
}
_is_placeholder_artist() {
local a="${1,,}"
[[ "$a" =~ ^(va|various|various artists|unknown artist|unknown|soundtrack|original soundtrack|ost)$ ]]
@@ -267,6 +275,8 @@ for artist in "${MISSING[@]}"; do
RESULT=$(_lidarr_post "$PAYLOAD")
if echo "$RESULT" | jq -e '.id' >/dev/null 2>&1; then
ARTIST_ID=$(echo "$RESULT" | jq -r '.id')
_lidarr_command "{\"name\":\"ArtistSearch\",\"artistId\":${ARTIST_ID}}" >/dev/null
log " $ICON_DONE Added: $LIDARR_NAME"
(( ADDED++ ))
else
+10
View File
@@ -100,6 +100,14 @@ _radarr_post() {
"${RADARR_URL}/api/v3/movie" 2>/dev/null
}
_radarr_command() {
curl -sf --max-time 20 -X POST \
-H "X-Api-Key: $RADARR_API_KEY" \
-H "Content-Type: application/json" \
-d "$1" \
"${RADARR_URL}/api/v3/command" 2>/dev/null
}
# Episode/garbage title filter — catches anime episodes stored as individual files
# in the Movies library, fansub release names, and codec metadata strings.
_is_episode_title() {
@@ -272,6 +280,8 @@ for name in "${SORTED_MISSING[@]}"; do
RESULT=$(_radarr_post "$PAYLOAD")
if echo "$RESULT" | jq -e '.id' >/dev/null 2>&1; then
MOVIE_ID=$(echo "$RESULT" | jq -r '.id')
_radarr_command "{\"name\":\"MoviesSearch\",\"movieIds\":[${MOVIE_ID}]}" >/dev/null
log " $ICON_DONE Added: $RADARR_TITLE"
(( ADDED++ ))
else
+10
View File
@@ -100,6 +100,14 @@ _sonarr_post() {
"${SONARR_URL}/api/v3/series" 2>/dev/null
}
_sonarr_command() {
curl -sf --max-time 20 -X POST \
-H "X-Api-Key: $SONARR_API_KEY" \
-H "Content-Type: application/json" \
-d "$1" \
"${SONARR_URL}/api/v3/command" 2>/dev/null
}
# Garbage title filter — catches multi-season folder names and bare fansub tags.
_is_garbage_title() {
local t="$1"
@@ -283,6 +291,8 @@ for name in "${SORTED_MISSING[@]}"; do
RESULT=$(_sonarr_post "$PAYLOAD")
if echo "$RESULT" | jq -e '.id' >/dev/null 2>&1; then
SERIES_ID=$(echo "$RESULT" | jq -r '.id')
_sonarr_command "{\"name\":\"SeriesSearch\",\"seriesId\":${SERIES_ID}}" >/dev/null
log " $ICON_DONE Added: $SONARR_TITLE"
(( ADDED++ ))
else