## About The core functionality of NZBGet can be extended using extensions. NZBGet provides documented entry points for extensions. On certain events the extensions are executed, they receive information about event, do certain work and can communicate with NZBGet to give it instructions for further processing. ## Installation ### Using the Extension Manager On the `SETTINGS` page you can easily find `EXTENSION MANAGER` and use it to install the extensions you need. Make sure that the internet connection is working and the path to the `7z` in `UNPACK->SevenZipCmd`(required for unpacking the extensions) is correct. The list of available extensions can be found in the [nzbget-extensions](https://github.com/nzbgetcom/nzbget-extensions) repository. ### Manually, for your custom extensions Option `ScriptDir` defines the location of extensions. To make an extension available in NZBGet put the extension into this directory. Then go to settings tab in web-interface (if you were already on settings tab switch to downloads tab and then back to settings tab to reread the list of available extensions from the disk). Menu at the left of page should list all extensions found in `ScriptDir`. Select an extension to review or change its options (if it has any). ## Writing extension In general, an extension consists of 2 files: `manifest.json` - with all the meta-data describing the extension and the `executable` file, like `main.py`. `manifest.json` example: ```json { "main": "main.py", "name": "EMail", "homepage": "https://github.com/nzbgetcom/Extension-EMail", "kind": "POST-PROCESSING", "displayName": "My EMail Extension", "version": "2.0", "nzbgetMinVersion": "24", "author": "John Doe", "license": "GNU", "about": "Sends E-Mail notification.", "queueEvents": "", "taskTime": "", "requirements": [ "This script requires Python3.8 to be installed on your system." ], "description": ["This script sends E-Mail notification when the job is done."], "options": [ { "name": "Server", "displayName": "Server", "value": "smtp.gmail.com", "description": ["SMTP server host."], "select": [] }, { "name": "Port", "displayName": "Port", "value": 25, "description": ["SMTP server port (1-65535)"], "select": [1, 65535] }, { "section": "Categories", "name": "SendMail", "displayName": "SendMail", "value": "Always", "description": ["When to send the message."], "select": ["Always", "OnFailure"] } ], "commands": [ { "name": "ConnectionTest", "action": "Send Test E-Mail", "displayName": "ConnectionTest", "description": ["To check connection parameters click the button."] }, { "section": "Feeds", "name": "ConnectionTest", "action": "Send Test E-Mail", "displayName": "ConnectionTest", "description": ["To check connection parameters click the button."] } ], "sections": [ { "name": "Categories", "prefix": "Category", "multi": true }, { "name": "Feeds", "prefix": "Feed", "multi": false } ] } ``` ### `"main"` The name of the executable file. For example: `main.py`, `main.exe`, `MyExt.sh`. ### `"name"` The extension name, identifier and prefix needed to save the extension configuration options to `nzbget.conf`. ### `"homepage"` Just a link to the repository where the extension lives. ### `"kind"` Depending on the purpose of the extension, can be: ``` "kind": "POST-PROCESSING" "kind": "SCAN" "kind": "QUEUE" "kind": "SCHEDULER" "kind": "FEED" ``` If the extension can be used for multiple purposes the `kind` can be mixed, for example: ``` "kind": "SCAN/QUEUE" ``` More information about extension kinds can be found at: - [POST-PROCESSING](POST-PROCESSING.md) - [SCAN](SCAN.md) - [QUEUE](QUEUE.md) - [SCHEDULER](SCHEDULER.md) - [FEED](FEED.md) ### `"displayName"` The name that will be displayed in the web interface. ### `"version"` Extension version. ### `"nzbgetMinVersion" (optional)` NZBGet minimum required version. ### `"author"` Author's name. ### `"license"` Extension license. ### `"about"` Brief description of the extension. ### `"description"` For more detailed description of the extension. ### `"queueEvents"` To describe the events that could be used by the extension, e.g.: ```json "queueEvents": "NZB_ADDED, NZB_DOWNLOADED" ``` More information can be found at [QUEUE](QUEUE.md). ### "`requirements"` To describe the list of requirements, e.g.: ```json "requirements": [ "This script requires Python3.8+ to be installed on your system." ], ``` ### `"options"` Let’s say we are writing an extension to send E-Mail notification. The user needs to configure the extension with options such as SMTP-Server host, port, login and password. To avoid hard-coding of these data in the extension NZBGet allows the extension to define the required options. The options are then made available on the settings page for user to configure. In the provided `manifest.json` example we defined three options: ```json "options": [ { "name": "Server", "displayName": "Server", "value": "smtp.gmail.com", "description": ["SMTP server host."], "select": [] }, { "section": "Categories", "name": "Port", "displayName": "Port", "value": 25, "description": ["SMTP server port (1-65535)"], "select": [1, 65535] }, { "name": "SendMail", "displayName": "SendMail", "value": "Always", "description": ["When to send the message."], "select": ["Always", "OnFailure"] } ], ``` >`"section"` property is optional. Default value is `"options"`. > Required `"nzbgetMinVersion"`: `"24"`. When the user saves settings in web-interface the extension configuration options are saved to NZBGet configuration file using the extension name as prefix. For example: ``` EMail:Server=smtp.gmail.com EMail:Port=25 ``` Extension configuration options are passed using env-vars with prefix `NZBPO_`. There are two env-vars for each option: - one env-var with the name exactly as defined by pp-option; - another env-var with the name written in UPPER CASE and with special characters replaced with underscores. For example, for pp-option `Server.Name` two env-vars are passed: `NZBPO_Server.Name` and `NZBPO_SERVER_NAME`. > In a case the user has installed the extension but have not saved the configuration, the options are not saved to configuration file yet. The extension will not get the options passed. This is a situation your extension must handle. You can either use a default settings or terminate the extension with a proper message asking the user to check and save configuration in web-interface. Example (python): ```python required_options = ('NZBPO_FROM', 'NZBPO_TO', 'NZBPO_SERVER', 'NZBPO_PORT', 'NZBPO_ENCRYPTION', 'NZBPO_USERNAME', 'NZBPO_PASSWORD', 'NZBPO_FILELIST', 'NZBPO_BROKENLOG', 'NZBPO_POSTPROCESSLOG') for optname in required_options: if (not optname in os.environ): print('[ERROR] Option %s is missing in configuration file. Please check script settings' % optname[6:]) sys.exit(POSTPROCESS_ERROR) ``` ### `"commands"` Sometimes it may be helpful to be able to execute extension extensions from settings page. For example pp-extension EMail could use a button "Send test email". For other extensions something like "Validate settings" or "Cleanup database" may be useful too. Starting from v19 it is possible to put buttons on the extension settings page. The buttons are defined as part of extension configuration, almost similar to extension configuration options: ```json "commands": [ { "section": "Categories", "name": "ConnectionTest", "action": "Send Test E-Mail", "displayName": "ConnectionTest", "description": ["To check connection parameters click the button."] } ], ``` This example creates a button with text "Send Test E-Mail" and description "To check connection parameters click the button.". When user presses the button NZBGet executes the extension in a special context passing button name via env. var NZBCP_COMMAND. The extension can check if it runs in command mode by examining this variable (python example): ```python # Exit codes used by NZBGet COMMAND_SUCCESS = 93 COMMAND_ERROR = 94 # Check if the script is executed from settings page with a custom command command = os.environ.get('NZBCP_COMMAND') test_mode = command == 'ConnectionTest' if command != None and not test_mode: print('[ERROR] Invalid command ' + command) sys.exit(COMMAND_ERROR) if test_mode: print('[INFO] Test connection...') sys.exit(COMMAND_SUCCESS)