Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ ARG USER=nobody

LABEL maintainer="Georgiy Sitnikov <g.shseekarr@sitnikov.eu>" \
org.opencontainers.image.title="sh-seekarr" \
org.opencontainers.image.description="SH implementation of Seekarr as alternative to Huntarr. A lightweight tool that triggers manual searches in Sonarr and Radarr to find missing items and upgrade existing ones to better quality. No UI. No exposed ports. Queries Sonarr and/or Radarr for missing and/or cutoff-unmet items" \
org.opencontainers.image.description="SH implementation of Seekarr as alternative to Huntarr. A lightweight tool that triggers manual searches in Sonarr and Radarr to find missing items and upgrade existing ones to better quality. No UI. No exposed ports. Queries Sonarr and/or Radarr for missing and/or cutoff-unmet items. Minimal CPU and RAM footprint." \
org.opencontainers.image.source="https://github.com/GAS85/sh-seekarr" \
org.opencontainers.image.url="https://hub.docker.com/r/gas85/sh-seekarr" \
org.opencontainers.image.documentation="https://github.com/GAS85/sh-seekarr#" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.version=$VERSION \
org.opencontainers.image.revision=$VCS_REF
org.opencontainers.image.revision=$VCS_REF \
org.opencontainers.image.created=$BUILD_DATE

ENV VERSION=$VERSION
ENV VCS_REF=$VCS_REF
ENV BUILD_DATE=$BUILD_DATE
ENV TZ=Europe/Zurich

RUN apk add --no-cache curl jq coreutils
Expand Down
34 changes: 21 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,23 +79,26 @@ All configuration is via environment variables, prefixed `SHSEEKARR_`.

| Variable | Required | Default | Description |
|----------|:--------:|---------|-------------|
| `SHSEEKARR_APPS` | `sonarr,radarr` | `sonarr,radarr` | Comma-separated list of apps to run. Any combination of `sonarr` and `radarr`. |
| `SHSEEKARR_SONARR_URL` | If using Sonarr | *(empty)* | Base URL of your Sonarr instance. E.g.: `http://sonarr:8989` |
| `SHSEEKARR_SONARR_APIKEY` | If using Sonarr | *(empty)* | Sonarr API key (Settings → General). |
| `SHSEEKARR_APPS` | `sonarr,radarr,sonarr_seasons` | `sonarr,radarr` | Comma-separated list of apps to run. Any combination of `sonarr`, `sonarr_seasons` and `radarr`.<br>`sonarr` will request random Episodes from a different Series and Seasons.<br>`sonarr_seasons` will request whole Season from random Series if at least 1 episode is missing from it. |
| `SHSEEKARR_SONARR_URL` | If using Sonarr | *(empty)* | Base URL of your Sonarr instance. E.g.: `http://sonarr:8989`. It is needed for `sonarr` and `sonarr_seasons` apps. |
| `SHSEEKARR_SONARR_APIKEY` | If using Sonarr | *(empty)* | Sonarr API key (Settings → General). It is needed for `sonarr` and `sonarr_seasons` apps. |
| `SHSEEKARR_RADARR_URL` | If using Radarr | *(empty)* | Base URL of your Radarr instance. E.g.: `http://radarr:7878`|
| `SHSEEKARR_RADARR_APIKEY` | If using Radarr | *(empty)* | Radarr API key (Settings → General). |

If an app's URL or API key isn't set, that app is skipped with a log message rather than causing an error — so `SHSEEKARR_APPS` can safely list an app you haven't configured yet.

Why `sonarr` and `sonarr_seasons` exist, are they doing same job? Sometimes, especially when Season was fully released it is easer to search for a whole season, instead of particular episode, this is not covered by `sonarr` only.

### Search behavior

| Variable | Default | Description |
|----------|---------|-------------|
| `SHSEEKARR_SEARCH_MODE` | `missing` | `missing` — only unaired/missing items (`wanted/missing`).<br>`upgrades` — only cutoff-unmet items (`wanted/cutoff`).<br>`both` / `all` — union of both, deduplicated by id. |
| `SHSEEKARR_MONITORED_ONLY` | `true` | `true`/`false` (also accepts `1`/`0`, `yes`/`no`). If `true`, only monitored items are considered. |
| `SHSEEKARR_MONITORED_ONLY` | `true` | `true`/`false` (also accepts `1`/`0`, `yes`/`no`). If `true`, only monitored items are considered. Usually it is not needed to set it to `false`, in this case we will search over the whole catalog of series and movies, even they are not monitored (probable already watched). |
| `SHSEEKARR_LIMIT` | `10` | Max number of items to search, **per app**, after random selection. |
| `SHSEEKARR_SONARR_LIMIT` | *(unset)* | If set, overrides `SHSEEKARR_LIMIT` for Sonarr only. |
| `SHSEEKARR_RADARR_LIMIT` | *(unset)* | If set, overrides `SHSEEKARR_LIMIT` for Radarr only. |
| `SHSEEKARR_SONARR_SEASONS_LIMIT` | *(unset)* | If set, overrides `SHSEEKARR_SONARR_SEASONS_LIMIT` for Sonarr only, when requesting whole seasons instead of episodes. |
| `SHSEEKARR_PAGE_SIZE` | `200` | Page size used when paging the `wanted/*` endpoints. Larger values mean fewer HTTP round-trips but bigger individual responses. |

**Note on limits:** `SHSEEKARR_LIMIT` and its per-app overrides are applied *independently* per app — e.g. `SHSEEKARR_LIMIT=10` with both Sonarr and Radarr enabled can trigger up to 10 searches on Sonarr **and** up to 10 on Radarr, not 10 combined.
Expand All @@ -121,7 +124,7 @@ SHSEEKARR_APPS="sonarr" \
SHSEEKARR_SONARR_URL="http://localhost:8989" \
SHSEEKARR_SONARR_APIKEY="xxxx" \
SHSEEKARR_SEARCH_MODE="upgrades" \
SHSEEKARR_LIMIT="10" \
SHSEEKARR_LIMIT="15" \
./seekarr.sh
```

Expand Down Expand Up @@ -174,13 +177,14 @@ Don't hardcode API keys directly in the script. Keep them in environment variabl
### cron

```cron
# Every 4 hours
0 */4 * * * /path/to/seekarr.sh >> /var/log/seekarr.log 2>&1
# Every 6 hours
0 */6 * * * /path/to/seekarr.sh >> /var/log/seekarr.log 2>&1
```

### systemd timer

`seekarr.service`:

```ini
[Unit]
Description=seekarr search trigger
Expand All @@ -192,20 +196,22 @@ ExecStart=/path/to/seekarr.sh
```

`seekarr.timer`:

```ini
[Unit]
Description=Run seekarr every 4 hours
Description=Run seekarr every 6 hours

[Timer]
OnCalendar=*-*-* 0/4:00:00
OnCalendar=*-*-* 0/6:00:00
Persistent=true

[Install]
WantedBy=timers.target
```

`/etc/seekarr.env`:
```

```bash
SHSEEKARR_SONARR_URL=http://localhost:8989
SHSEEKARR_SONARR_APIKEY=xxxx
SHSEEKARR_RADARR_URL=http://localhost:7878
Expand All @@ -219,22 +225,24 @@ export SHSEEKARR_SONARR_URL="http://localhost:8989"
export SHSEEKARR_SONARR_APIKEY="your-sonarr-api-key"
export SHSEEKARR_RADARR_URL="http://localhost:7878"
export SHSEEKARR_RADARR_APIKEY="your-radarr-api-key"
export SHSEEKARR_SCHEDULE_INTERVAL="4h"
export SHSEEKARR_SCHEDULE_INTERVAL="6h"
./seekarr.sh
```

### Docker
### Docker internal scheduler

```bash
docker run --name sh-seekarr \
-e SHSEEKARR_SONARR_URL=http://sonarr:8989/ \
-e "SHSEEKARR_SONARR_APIKEY=your key" \
-e SHSEEKARR_RADARR_URL=http://radarr:7878/ \
-e "SHSEEKARR_RADARR_APIKEY=your key" \
-e "SHSEEKARR_SCHEDULE_INTERVAL=4h" \
-e "SHSEEKARR_SCHEDULE_INTERVAL=6h" \
gas85/sh-seekarr:latest
```

For docker compose, pleaser refer to [docker-compose.yml](https://github.com/GAS85/sh-seekarr/blob/main/docker-compose.yml).

## Troubleshooting

- **"Missing required dependency: jq"** — install `jq` (e.g. `apt install jq`, `brew install jq`).
Expand Down
25 changes: 13 additions & 12 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ services:
image: gas85/sh-seekarr:latest
container_name: sh-seekarr
environment:
- SHSEEKARR_APPS=sonarr,radarr
- SHSEEKARR_SEARCH_MODE=missing
- SHSEEKARR_MONITORED_ONLY=true
- SHSEEKARR_LIMIT=10
- SHSEEKARR_PAGE_SIZE=200
- SHSEEKARR_DRY_RUN=false
- SHSEEKARR_LOG_FORMAT=text
- SHSEEKARR_SCHEDULE_INTERVAL=6h
- SHSEEKARR_SCHEDULE_RANDOMIZER=true
- SHSEEKARR_SONARR_LIMIT=10
- SHSEEKARR_RADARR_LIMIT=1
- SHSEEKARR_SONARR_URL=http://sonarr:8989/
- SHSEEKARR_SONARR_APIKEY=your key
- SHSEEKARR_RADARR_URL=http://radarr:7878/
- SHSEEKARR_RADARR_APIKEY=your key
restart: no
# - SHSEEKARR_APPS=sonarr,radarr,sonarr_seasons
# - SHSEEKARR_SEARCH_MODE=missing
# - SHSEEKARR_MONITORED_ONLY=true
# - SHSEEKARR_LIMIT=10
# - SHSEEKARR_PAGE_SIZE=200
# - SHSEEKARR_DRY_RUN=true
# - SHSEEKARR_LOG_FORMAT=text
# - SHSEEKARR_SCHEDULE_INTERVAL=6h
# - SHSEEKARR_SCHEDULE_RANDOMIZER=true
# - SHSEEKARR_SONARR_LIMIT=10
# - SHSEEKARR_SONARR_SEASONS_LIMIT=2
# - SHSEEKARR_RADARR_LIMIT=1
restart: no # Set to "unless-stopped" if you using SHSEEKARR_SCHEDULE_INTERVAL
Loading