Notification Scripts - shitwolfymakes/automatic-ripping-machine GitHub Wiki
A Bash script notification channel (a "hook") runs a script of yours when
a subscribed event fires. It is the v3 successor of v2's BASH_SCRIPT
setting with the same calling convention, plus declared inputs, per-event
overrides, and a test panel.
Put executable files in arm/scripts/ under the install prefix (next to
arm/media and arm/raw). The backend sees the directory read-only at
/scripts. In Settings > Notifications, add a channel of type Bash script
and pick the file. Files without the execute bit are listed but cannot be
picked.
cp docs/user/examples/send-email.sh arm/scripts/
chmod +x arm/scripts/send-email.sh
devtools/setup-dev.sh and armctl install create the scripts/ directory,
and the compose template (docker-compose.yml.example) mounts it into
arm-backend read-only. Until the directory exists with your files in it, the
picker shows "No scripts found".
/usr/bin/env bash /scripts/<script> "<title>" "<body>"
$1 is the rendered title and $2 the rendered body after the channel's
per-event overrides. That is exactly what v2 passed.
Every render-context variable is also exported as an ARM_* variable:
| Variable | Meaning |
|---|---|
ARM_EVENT_TYPE |
rip.completed, rip.partial, rip.failed, rip.needs_user_input, session.completed, session.partial, session.failed
|
ARM_JOB_ID, ARM_JOB_TITLE, ARM_JOB_YEAR, ARM_JOB_DISC_TYPE, ARM_DRIVE_ID, ARM_OCCURRED_AT
|
job and event envelope |
ARM_STATUS, ARM_TRACKS_DONE, ARM_TRACKS_FAILED, ARM_TRACKS_TOTAL
|
rip.* events |
ARM_STATUS, ARM_SESSION_ID, ARM_SESSION_APPLICATION_ID
|
session.* events |
ARM_VOLUME_LABEL, ARM_DISC_TYPE
|
rip.needs_user_input |
ARM_TITLE, ARM_BODY
|
same values as $1 and $2
|
ARM_MEDIA_ROOT, ARM_RAW_ROOT
|
/media and /raw inside the container |
Unknown values are empty strings. GET /api/notifications/event-types is
the authoritative per-event list. The Test panel in the UI shows the exact
values for a chosen event.
Add comment lines to the top of the script (first 60 lines):
# arm-hook: Send an email through an SMTP relay
# arm-input: TO label="Recipient" required
# arm-input: SUBJECT label="Subject" default="ARM {event_type}: {job_title}"
# arm-input: PRIORITY label="Priority" values=low,normal,high default=normal
# arm-input: SMTP_PASS label="SMTP password" secret
The UI renders one field per arm-input line, and the value reaches the
script as an environment variable with that exact name ($TO, $SUBJECT).
-
KEYmust be upper-case letters, digits, and underscores, and must not start withARM_(reserved). A few shell-sensitive names are refused too (PATH,HOME,LANG,LC_ALL,BASH_ENV,ENV,LD_PRELOAD,LD_LIBRARY_PATH,SHELLOPTS,BASHOPTS,IFS,PS4,CDPATH,GLOBIGNORE); a line declaring one of them is ignored. -
label="..."is the field label (defaults to the key). -
default="..."is used when the field is left blank. Values may use the same{variables}as title and body. -
values=a,b,crenders a select and rejects anything else. -
requiredfails the run when the value is empty. -
secretrenders a password field, stores the value masked, and cannot be overridden per event.
Only declared inputs reach the script. A stored or per-event value whose key
no script header declares is ignored, so a script with no arm-input lines
still works and gets $1, $2, and the ARM_* variables, and nothing else.
Each subscribed event can override the title, the body, and every non-secret
input. Blank fields inherit the hook's values. Typical use: one email hook
subscribed to rip.completed and rip.failed, with rip.failed sending to
an on-call address with PRIORITY=high.
Inside the arm-backend container, as the PUID user:
- tools: bash, coreutils,
curl. Norsync,rclone,ffmpeg, ormkvpropeditunless you add them (see below) - paths:
/scripts(read-only),/media,/raw,/logs - network: the compose network and outbound internet
- not available: host binaries,
systemctl,eject, host paths that are not mounted
To use extra tools or paths, extend the backend image or add a bind mount in
docker-compose.override.yml:
services:
arm-backend:
volumes:
- /mnt/nas/movies:/mnt/nas/movies
The backend's own environment (database URL, service token) is never passed
to the script. Only PATH, HOME, LANG, LC_ALL, the ARM_* variables,
and the declared inputs are.
The script must exit 0 within the channel's timeout (default 30 seconds,
maximum 600). A non-zero exit, a timeout, a missing file, a missing execute
bit, a missing required input, or a template error is recorded on the
channel and in the dispatch log with the reason and the first 200 characters
of stderr, with any secret input value replaced by <hidden>. There is no
retry. The Test panel shows the full stdout and stderr (up to 4 KB each) of a
test run.
The run is finished when the script itself exits. A job it starts in the
background (long-task &) keeps running, and its output after that point
is not captured. A timeout kills the script and everything it started.
- send-email.sh: email through an SMTP relay with curl; recipient, subject, and priority per event.
-
plex-refresh.sh: refresh a Plex library section
on
session.completed.
Copy the file into arm/scripts/, make it executable, add a Bash script
channel that points at it, and subscribe it to every event. $1 and $2
are unchanged. v2's [ARM_NAME] prefix and NOTIFY_JOBID suffix are not
applied; set them in the per-event title template instead.