Skip to content

Latest commit

 

History

History
300 lines (237 loc) · 9.05 KB

File metadata and controls

300 lines (237 loc) · 9.05 KB

Custom Event Scripts

This directory contains an example script for the Custom Event Script feature, which allows power users to run custom commands when download events occur.

Note: For most users, the Notifications page in the web UI is the recommended way to set up notifications. It provides a simple form-based interface for configuring Discord, Telegram, Slack, and many other services via Apprise.

Files

  • custom.sh - Example script showing how to handle events
  • log-to-file.sh - Debug script that logs all received data to server/logs/events.log

When to Use Custom Scripts

Custom scripts are useful when you need to:

  • Run post-processing commands (e.g., extract archives, convert files)
  • Integrate with systems not supported by Apprise
  • Implement complex conditional logic
  • Log events to a custom format or location
  • Trigger home automation actions

Quick Start

1. Edit the Script

Modify scripts/custom.sh (or create your own script) to handle events:

#!/bin/bash
EVENT_TYPE="$1"
EVENT_JSON=$(cat)

if [ "$EVENT_TYPE" = "downloadFinished" ]; then
    FILENAME=$(echo "$EVENT_JSON" | jq -r '.filename')
    # Your custom logic here
    echo "Download complete: $FILENAME"
fi

2. Make Script Executable

chmod +x scripts/custom.sh

3. Enable in Settings

Go to Settings → Custom Event Script:

  • Toggle "Enable Custom Event Script" to ON
  • Set the script path to scripts/custom.sh
  • Click "Test Script Path" to verify

Script Invocation

When an event occurs, your script receives:

Source Description
$1 (first argument) Event type (e.g., downloadFinished)
Environment variables Common fields as individual variables
Stdin Full event data as JSON

Environment Variables

Variable Description
EVENT_TYPE Event type (same as $1)
EVENT_HASH Download hash/ID
EVENT_FILENAME File name
EVENT_CLIENT_TYPE Client type (amule, qbittorrent, rtorrent, deluge)
EVENT_INSTANCE_ID Client instance identifier
EVENT_INSTANCE_NAME Display name of the client instance
EVENT_OWNER Username of the file owner (empty if untracked or no multi-user)
EVENT_TRIGGERED_BY Username who triggered the action (empty for system events)
EVENT_STATUS Client health status: available or unavailable (health events only)
EVENT_PREVIOUS_STATUS Previous health status (health events only)
EVENT_ERROR Error message that caused the outage (health events only)
EVENT_DOWNTIME_DURATION Duration of outage in milliseconds (clientAvailable events only)

Event Types

Event Trigger Additional JSON Fields
downloadAdded New download started size, username, category
downloadFinished Download completed size, downloaded, uploaded, ratio, trackerDomain, category, path, multiFile
categoryChanged Category changed oldCategory, newCategory, path, multiFile
fileMoved File moved category, sourcePath, destPath
fileDeleted File deleted deletedFromDisk, category, path, multiFile
clientUnavailable Client went offline status, previousStatus, error
clientAvailable Client came back online status, previousStatus, downtimeDuration

Common fields (present in all download events): hash, filename, clientType, instanceId, instanceName, owner, triggeredBy

Common fields (present in all health events): clientType, instanceId, instanceName, status, previousStatus, timestamp

Note: Client health events are debounced (3 consecutive failures before declaring offline), but unlike push notifications, custom scripts receive every health event without flood suppression. If you need throttling in your script, implement it yourself (e.g., check a timestamp file).

User fields (owner and triggeredBy) are populated when multi-user authentication is enabled:

  • owner — the username who owns the download (looked up from the ownership table)
  • triggeredBy — the username who initiated the action; empty for system-detected events like downloadFinished and fileMoved

The category field contains the item's category name (e.g., "Movies", "TV Shows"), or null if uncategorized/Default.

The path field contains the full path to the file (or the content directory for multi-file torrents). When multiFile is true, path points to a directory containing multiple files.

JSON Payload Examples

downloadAdded

{
  "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "filename": "ubuntu-24.04-desktop-amd64.iso",
  "size": 6114770944,
  "username": "admin",
  "clientType": "qbittorrent",
  "instanceId": "qbittorrent-localhost-8080",
  "instanceName": "qBittorrent",
  "category": "Linux ISOs",
  "owner": "admin",
  "triggeredBy": "admin"
}

downloadFinished

{
  "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "filename": "ubuntu-24.04-desktop-amd64.iso",
  "size": 6114770944,
  "clientType": "qbittorrent",
  "instanceId": "qbittorrent-localhost-8080",
  "instanceName": "qBittorrent",
  "downloaded": 6114770944,
  "uploaded": 1528692736,
  "ratio": 0.25,
  "trackerDomain": "torrent.ubuntu.com",
  "category": "Linux ISOs",
  "path": "/downloads/ubuntu-24.04-desktop-amd64.iso",
  "multiFile": false,
  "owner": "admin",
  "triggeredBy": ""
}

Multi-file torrent example (path points to the content directory):

{
  "hash": "b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3",
  "filename": "My.Series.S01.Complete",
  "size": 15032385536,
  "clientType": "rtorrent",
  "instanceId": "rtorrent-localhost-8000",
  "instanceName": "rTorrent",
  "downloaded": 15032385536,
  "uploaded": 7516192768,
  "ratio": 0.5,
  "trackerDomain": "tracker.example.com",
  "category": "TV Shows",
  "path": "/downloads/My.Series.S01.Complete",
  "multiFile": true,
  "owner": "john",
  "triggeredBy": ""
}

categoryChanged

{
  "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "filename": "ubuntu-24.04-desktop-amd64.iso",
  "clientType": "rtorrent",
  "instanceId": "rtorrent-localhost-8000",
  "instanceName": "rTorrent",
  "oldCategory": "Default",
  "newCategory": "Linux ISOs",
  "path": "/downloads/ubuntu-24.04-desktop-amd64.iso",
  "multiFile": false,
  "owner": "john",
  "triggeredBy": "admin"
}

fileDeleted

{
  "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "filename": "old-file.zip",
  "clientType": "qbittorrent",
  "instanceId": "qbittorrent-localhost-8080",
  "instanceName": "qBittorrent",
  "deletedFromDisk": true,
  "category": "Movies",
  "path": "/downloads/old-file.zip",
  "multiFile": false,
  "owner": "john",
  "triggeredBy": "admin"
}

fileMoved

{
  "hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "filename": "movie.mkv",
  "clientType": "rtorrent",
  "instanceId": "rtorrent-localhost-8000",
  "instanceName": "rTorrent",
  "category": "Movies",
  "sourcePath": "/downloads/movie.mkv",
  "destPath": "/media/movies/movie.mkv",
  "owner": "john",
  "triggeredBy": ""
}

Examples

Parse JSON with jq

#!/bin/bash
EVENT_TYPE="$1"
EVENT_JSON=$(cat)

FILENAME=$(echo "$EVENT_JSON" | jq -r '.filename')
SIZE=$(echo "$EVENT_JSON" | jq -r '.size')

echo "[$EVENT_TYPE] $FILENAME ($SIZE bytes)"

Post-Processing on Download Complete

#!/bin/bash
if [ "$1" = "downloadFinished" ]; then
    EVENT_JSON=$(cat)
    FILEPATH=$(echo "$EVENT_JSON" | jq -r '.path')
    MULTI=$(echo "$EVENT_JSON" | jq -r '.multiFile')

    # Extract archives (single-file only)
    if [ "$MULTI" = "false" ] && [ "$FILEPATH" != "null" ]; then
        case "$FILEPATH" in
            *.rar) unrar x "$FILEPATH" /extracted/ ;;
            *.zip) unzip "$FILEPATH" -d /extracted/ ;;
        esac
    fi
fi

Send to Custom Webhook

#!/bin/bash
EVENT_JSON=$(cat)

curl -X POST "https://your-webhook.example.com/notify" \
    -H "Content-Type: application/json" \
    -d "$EVENT_JSON"

Log Events to File

#!/bin/bash
echo "$(date -Iseconds) [$1] $EVENT_FILENAME" >> /var/log/downloads.log

Testing

Test Script Manually

echo '{"hash":"abc123","filename":"test.mkv","clientType":"qbittorrent","instanceId":"qbittorrent-localhost-8080","instanceName":"qBittorrent","path":"/downloads/test.mkv","multiFile":false,"owner":"admin","triggeredBy":""}' | \
    EVENT_OWNER=admin EVENT_TRIGGERED_BY="" ./scripts/custom.sh downloadFinished

Test from Settings

Use the "Test Script Path" button in Settings → Custom Event Script.

Troubleshooting

Script not executing:

  • Verify the script is executable: chmod +x scripts/custom.sh
  • Check the script path in Settings matches exactly
  • Look at application logs for [EventScript] messages

jq not found (non-Docker only):

  • Debian/Ubuntu: apt install jq
  • macOS: brew install jq
  • Alpine: apk add jq

Docker path issues:

  • The default path scripts/custom.sh is relative to the app directory
  • For custom locations, use absolute paths like /usr/src/app/scripts/my-script.sh