Skip to content
Ben Adrian Sarmiento edited this page Jan 28, 2024 · 7 revisions

zurg Configuration Documentation

Welcome to the zurg Configuration guide. This document will help you set up and understand the config.yaml file for configuring your media library directory structure.

Table of Contents

  1. Basic Configuration
  2. Directory Definitions and Filters
  3. Advanced Filtering
  4. Regex
  5. Library Update Trigger

Here's a sample version of a zurg configuration:

# Zurg configuration version
zurg: v1

# Provide your Real-Debrid API token
token: YOUR_RD_API_TOKEN # https://real-debrid.com/apitoken

# Host and port settings
host: "[::]"
port: 9999

# Authentication (if required)
# username:
# password:

# Proxy settings (if needed)
# proxy:

# concurrent_workers: 32

# Checking for changes in Real-Debrid API more frequently (every 60 seconds)
# check_for_changes_every_secs: 60

# File handling and renaming settings
retain_rd_torrent_name: false
retain_folder_name_extension: false
expose_full_path: true

# Torrent management settings
enable_repair: true
auto_delete_rar_torrents: true

# Streaming and download link verification settings
serve_from_rclone: false
verify_download_link: false

# Network and API settings
force_ipv6: false

# Library update script configuration
on_library_update: sh plex_update.sh "$@"

# Directories configuration with specific filters for anime, shows, and movies
directories:
  anime:
    group_order: 10
    group: media
    filters:
      - regex: /\b[a-fA-F0-9]{8}\b/
      - any_file_inside_regex: /\b[a-fA-F0-9]{8}\b/

  shows:
    group_order: 20
    group: media
    filters:
      - has_episodes: true

  movies:
    group_order: 30
    group: media
    only_show_the_biggest_file: true
    filters:
      - regex: /.*/

In this configuration:

  • zurg: This represents the configuration version. For this example, it's set to v1.
  • token: This is where you place your Real-Debrid API token. Replace YOUR_RD_API_TOKEN with your actual token.
  • host: This is the host to bind to, the default is [::], which represents all available interfaces.
  • port: This is the port number that zurg will listen on. The default is 9999.
  • username and password: You can protect your zurg endpoints by setting a username+password credential.
  • proxy: If you want all zurg traffic to go through a network proxy.
  • concurrent_workers: This sets the number of concurrent workers that zurg will utilize. In this example, it's set to 20.
  • check_for_changes_every_secs: This is the time interval in seconds for checking for changes. The default is 15 seconds.
  • retain_rd_torrent_name: If set to true, the original name of the torrent file from Real-Debrid will be retained. This is useful if you want to preserve the original file names for any reason. The default is false.
  • retain_folder_name_extension: If true, torrent folder names will contain file extension suffixes when they contain a single file. This is useful for those using a third-party symlinking tool like rdt-client as it requires the integrity of the filename. The default is false.
  • expose_full_path: If true, the files inside torrents will include the subfolders in the path part of the filename. This improves accuracy of media scanners on identifying content.
  • auto_delete_rar_torrents: When zurg encounters a torrent that is archived by Real-Debrid in a RAR file, this option will decide to delete the torrent or not (since rar'ed torrents are unplayable anyway)
  • enable_download_mount: All your links in this page will be stored in memory and mounted to a directory __downloads__
  • enable_repair: If set to true, zurg will attempt to repair your torrents. It's important that only one instance of zurg has this enabled.
  • on_library_update: This is a script that runs when a library update is detected. In this example, the script simply logs the directories that have been updated.
  • network_buffer_size: This sets the network buffer size. You can experiment with this value to see if it affects performance when streaming files. Common values are 16384 for 16KB and 32768 for 32KB (which is the default).
  • serve_from_rclone: If set to true, zurg will send the URL for rclone to download, and rclone will handle the file download and transmission. This means that zurg doesn't directly download the file and serve the bytes to rclone. The default is false.
  • verify_download_link: This is only relevant if serve_from_rclone is set to true. It will check if a given download link works before passing it to rclone.
  • force_ipv6: If set to true, zurg will only connect to the IPv6 addresses of Real-Debrid hosts. This can be useful if you're experiencing issues with IPv4 connectivity. However, it's important to note that not all networks fully support IPv6 yet, so this option should only be used if you're sure your network supports it. The default is false.
  • rate_limit_sleep_secs: The amount of time zurg will stop sending requests to Real-Debrid API when it encounters a HTTP 429 response.
  • api_timeout_secs: The amount of time zurg will wait for Real-Debrid API to return a response.
  • download_timeout_secs: The amount of time zurg will wait for Real-Debrid file download to return a response.
  • retries_until_failed: The maximum number of retries zurg will do before considering it a failure.

Directory Definitions and Filters

Define directories and their filtering rules under the directories key.

Each directory can have:

  • group: Directories in the same group might have duplicates of the same torrent. It's a way to categorize your directories.
  • group_order: Determines the order within the group. Directories with lower numbers get priority.
  • filters: List of filtering conditions.
  • only_show_the_biggest_file: This sets the directory to only show 1 file, the largest file based on file size.
  • only_show_files_with_size_lte: This filters the files inside the directory and only shows files with size less than or equal to value
  • only_show_files_with_size_gte: This filters the files inside the directory and only shows files with size greater than or equal to value

For example, for TV shows:

# List of directory definitions and their filtering rules
directories:
  # Configuration for anime shows
  anime:
    group: media # directories on different groups have duplicates of the same torrent
    group_order: 10 # group order = priority, it defines who eats first on a group
    filters:
      - and: # you can use nested 'and' & 'or' conditions
        - has_episodes: true # intelligent detection of episode files inside a torrent
        - any_file_inside_regex: /^\[/ # usually anime starts with [ e.g. [SubsPlease]
        - any_file_inside_not_regex: /s\d\de\d\d/i # and usually anime doesn't use SxxExx

  shows:
    group: media
    group_order: 20
    filters:
      - has_episodes: true  # intelligent detection of episode files inside a torrent

  movies:
    group: media  # because anime, shows and movies are in the same group,
    group_order: 30 # and anime and shows has a lower group_order number than movies, all torrents that doesn't fall into the previous 2 will fall into movies
    only_show_the_biggest_file: true # let's not show the other files besides the movie itself
    filters:
      - regex: /.*/ # you cannot leave a directory without filters because it will not have any torrents in it
      ...

Filter Types

You can use the following filters:

  • id: Matches the unique identifier of a torrent.
  • regex: Regular expression matching.
  • not_regex: Regular expression that should not match.
  • contains: Checks if the string contains the specified substring.
  • contains_strict: Same as contains, but case-sensitive.
  • not_contains: Opposite of contains.
  • not_contains_strict: Opposite of contains_strict.
  • any_file_inside_regex: Matches file names inside the torrent using regex.
  • any_file_inside_not_regex: Matches file names inside the torrent that should not match the regex.
  • any_file_inside_contains: Checks if any file inside the torrent contains the specified substring.
  • any_file_inside_contains_strict: Same as above, but case-sensitive.
  • any_file_inside_not_contains: Checks if any file inside the torrent does not contain the specified substring.
  • any_file_inside_not_contains_strict: Same as above, but case-sensitive.
  • has_episodes: If true, matches torrents that contain a sequence of episodes.
  • size_gte: Accepts a number in bytes (e.g. 1073741824 for 1GB) and all torrents greater than or equal to this value will be assigned to this directory.
  • size_lte: Accepts a number in bytes (e.g. 1073741824 for 1GB) and all torrents less than or equal to this value will be assigned to this directory.
  • any_file_inside_size_gte: Accepts a number in bytes (e.g. 1073741824 for 1GB) and all torrents greater than or equal to this value will be assigned to this directory.
  • any_file_inside_size_lte: Accepts a number in bytes (e.g. 1073741824 for 1GB) and all torrents less than or equal to this value will be assigned to this directory.

Advanced Filtering

For more complex conditions, use the and & or filters:

  • and: All conditions inside must be true.
  • or: At least one condition inside must be true.
filters:
  - id: torrentID
  - regex: /example/i
  - not_regex: /notexample/i
  - and:
    - contains: keyword1
    - not_contains: keyword2
  - or:
    - contains_strict: Keyword3
    - any_file_inside_regex: /pattern/i
    - any_file_inside_not_regex: /notpattern/i

Important Considerations

  1. Unexpected Results with any_file_inside_* Filters: Such filters can occasionally lead to unexpected outcomes. For instance, imagine two torrents named The Simpsons. One might contain files labeled *s17* episodes, while the other has *s19*. If one torrent aligns with the criteria of an any_file_inside_* filter and the other does not, the directory will display the torrent and incorporate files from both torrents - *s17* and *s19*.

  2. Interactions of not_contains or not_contains_strict in or Context: When not_contains or not_contains_strict are used within an or context in combination with regex, contains, or contains_strict, it can lead to unanticipated results. For example:

filters:
   - not_contains: keyword1
   - regex: /pattern/i
   - contains: keyword2
   - contains_strict: Keyword3

In this scenario, a torrent might match if it doesn't contain keyword1 or if it matches the regex pattern, or if it contains keyword2, or if it strictly contains Keyword3. This can lead to torrents being included that you might not have anticipated.

It's essential to test your filters thoroughly to ensure they behave as intended and make necessary adjustments.

Regex

In zurg, you can use regular expressions (often referred to as "regex") to define patterns for filtering. A regex pattern is wrapped between slashes /. For example, /season[\s\.]?\d/i is a regex pattern. The main part of this pattern is season[\s\.]?\d, which matches strings like "season 1", "season.2", or "season 3". The trailing i after the last slash is a flag that makes the pattern case-insensitive. This means "SEASON 1", "SeAsOn 2", and "season 3" would all match this pattern.

You can append flags after the pattern to change how the pattern behaves:

  • i: Case-Insensitive. It allows the pattern to match strings regardless of their case. For example, /abc/i matches "abc", "ABC", "aBc", etc.

  • x: Extended mode. It allows you to add whitespace and comments within your regex for better readability.

For example, the pattern /abc/i would match the string "ABC" because of the i flag, which makes the matching case-insensitive. The extended mode flag x, if used, would allow for adding whitespace and comments within the regex for better readability.

Library Update Trigger

Using the on_library_update directive, you can configure a trigger to refresh your Plex library whenever changes are detected:

on_library_update: |
  token="Your X-Plex-Token Here"
  plex_url="http://plex.ip"
  email="your-email@example.com"

  # Log the updated directories and send refresh request
  for arg in "$@"
  do
      echo "Detected update on: $arg"
      # URL encode the directory path
      encoded_arg=$(python -c "import urllib.parse; print(urllib.parse.quote_plus('$arg'))")
      curl -s -X GET "$plex_url/library/sections/all/refresh?path=$encoded_arg" -H "X-Plex-Token: $token"
  done

  echo "All updated sections refreshed."

  # Send an email notification
  echo "Plex library has been updated with these content: $@" | mail -s "zurg: Library Update" $email

Ensure you replace the placeholders (Your X-Plex-Token Here and http://plex.box) with the appropriate values for your setup.

This is just an example usage but you can also use it for notifications, etc.

Happy organizing!