Skip to main content

Plugin Runners

This page outlines the various Plugin types and their runners.


Library Management - File test

Executed:

After Unmanic carries out tests on a file to determine if it should be added to the task queue. Prior to returning a result of said tests.

Function:

on_library_management_file_test(data)

Provided data:
  • library_id [integer] - The library that the current task is associated with
  • path [string] - String containing the full path to the file being tested.
  • issues [list] - List of currently found issues for not processing the file.
  • add_file_to_pending_tasks [boolean] - Boolean, is the file currently marked to be added to the queue for processing.
  • priority_score [integer] - An additional score that can be added to set the position of the new task in the task queue.
  • shared_info [dictionary] - Information provided by previous plugin runners. This can be appended to for subsequent runners.
Example:
plugin.py

For an up-to-date example, see the Example Plugins Repo

import os


def on_library_management_file_test(data):
"""
Runner function - enables additional actions during the library management file tests.
The 'data' object argument includes:
library_id - The library that the current task is associated with
path - String containing the full path to the file being tested.
issues - List of currently found issues for not processing the file.
add_file_to_pending_tasks - Boolean, is the file currently marked to be added to the queue for processing.
priority_score - Integer, an additional score that can be added to set the position of the new task in the task queue.
shared_info - Dictionary, information provided by previous plugin runners. This can be appended to for subsequent runners.
:param data:
:return:
"""

# Get the file extension
file_extension = os.path.splitext(data.get('path'))[-1][1:]

# Ensure the file's extension is lowercase
file_extension = file_extension.lower()

# If this is flash video file, add it to pending tasks
if file_extension.lower() in ['flv']:
data['add_file_to_pending_tasks'] = True

return
Details:

This Plugin runner should be used when you wish to create custom actions or tests to be carried out on a file during the file test triggered by either the Library scan or the Library event watcher.

When you fail a test, you should also update the issues list provided in the data dictionary.

For example:

data['issues'].append({
'id': '<PLUGIN NAME>',
'message': "File should be ignored because <X>",
})

Worker - Processing file

Executed:

Just prior to the execution of the command subprocess within an Unmanic Worker process.

Function:

on_worker_process(data)

Provided data:
  • worker_log [list] - The log lines that are being tailed by the frontend (can be empty).
  • library_id [integer] - The library that the current task is associated with.
  • exec_command [list] - A command that Unmanic should execute (can be empty).
  • command_progress_parser [callable] - A function that Unmanic can use to parse the STDOUT of the command to collect progress stats (can be empty).
  • file_in [string] - The source file to be processed by the command.
  • file_out [string] - The destination that the command should output (can be the same as the file_in if necessary).
  • original_file_path [string] - The absolute path to the original library file.
  • repeat [boolean] - Sets if this runner should be executed again once completed with the same variables.
Example:
plugin.py

For an up-to-date example, see the Example Plugins Repo

from unmanic.libs.unplugins.settings import PluginSettings
from unmanic.libs.system import System


class Settings(PluginSettings):
"""
An object to hold a dictionary of settings accessible to the Plugin
class and able to be configured by users from within the Unmanic WebUI.

This class has a number of methods available to it for accessing these settings:

> get_setting(<key>) - Fetch a single setting value. Or leave the
key argument empty and return the full dictionary.
> set_setting(<key>, <value>) - Set a singe setting value.
Used by the Unmanic WebUI to save user settings.
Settings are stored on disk in order to be persistent.

"""
settings = {
"Execute Command": True,
"Insert string into cache file name": "custom-string"
}


def on_worker_process(data):
"""
Runner function - enables additional configured processing jobs during the worker stages of a task.

The 'data' object argument includes:
worker_log - Array, the log lines that are being tailed by the frontend. Can be left empty.
library_id - Number, the library that the current task is associated with.
exec_command - Array, a subprocess command that Unmanic should execute. Can be empty.
command_progress_parser - Function, a function that Unmanic can use to parse the STDOUT of the command to collect progress stats. Can be empty.
file_in - String, the source file to be processed by the command.
file_out - String, the destination that the command should output (may be the same as the file_in if necessary).
original_file_path - String, the absolute path to the original file.
repeat - Boolean, should this runner be executed again once completed with the same variables.

:param data:
:return:
"""
settings = Settings(library_id=data.get('library_id'))
system = System()
system_info = system.info()

custom_string = settings.get_setting('Insert string into cache file name')
if custom_string:
tmp_file_out = os.path.splitext(data['file_out'])
data['file_out'] = "{}-{}-{}{}".format(tmp_file_out[0], custom_string, tmp_file_out[1])

if not settings.get_setting('Execute Command'):
data['exec_command'] = False



return
Details:

This Plugin runner should be used for carrying any custom command execution stages. The runner itself is only required to configure the parameters of the command execution. The main Unmanic process will take the data dictionary returned from this runner and execute the command within it's own shell.


Post-processor - File movements

Executed:

Just prior to file copy operation from cached output file to source file's directory.

Function:

on_postprocessor_file_movement(data)

Provided data:
  • source_data [dictionary] - Data pertaining to the original source file.
  • remove_source_file [boolean] - Sets if Unmanic should remove the original source file after all copy operations are complete.
  • copy_file [boolean] - Sets if Unmanic should run a copy operation with the returned data variables.
  • file_in [string] - The converted cache file to be copied by the postprocessor.
  • file_out [string] - The destination file that the file will be copied to.
  • run_default_file_copy [boolean] - Whether Unmanic should perform the default file copy.
Example:
plugin.py

For an up-to-date example, see the Example Plugins Repo

def on_postprocessor_file_movement(data):
"""
Runner function - configures additional postprocessor file movements during the postprocessor stage of a task.

The 'data' object argument includes:
source_data - Dictionary containing data pertaining to the original source file ('abspath' and 'basename').
remove_source_file - Boolean, should Unmanic remove the original source file after all copy operations are complete.
copy_file - Boolean, should Unmanic run a copy operation with the returned data variables.
file_in - The converted cache file to be copied by the postprocessor.
file_out - The destination file that the file will be copied to.
run_default_file_copy - Whether Unmanic should perform the default file copy.

:param data:
:return:
"""

return
Details:

This Plugin runner should be used for executing additional file movements of a completed task.

note

This Plugin runner is only executed on a successfully completed task.


Post-processor - Marking task success/failure

Executed:

Just prior to the task cache directory cleanup.

Function:

on_postprocessor_task_results(data)

Provided data:
  • final_cache_path [string] - The path to the final cache file that was then used as the source for all destination files.
  • library_id [integer] - The library that the current task is associated with.
  • task_processing_success [boolean] - Specifies if all task processes complete successfully.
  • file_move_processes_success [boolean] - Specifies if all postprocessor movement tasks complete successfully.
  • destination_files [list] - All file paths created by postprocessor file movements.
  • source_data [dictionary] - Data pertaining to the original source file.
Example:
plugin.py

For an up-to-date example, see the Example Plugins Repo

def on_postprocessor_task_results(data):
"""
Runner function - provides a means for additional postprocessor functions based on the task success.

The 'data' object argument includes:
final_cache_path - The path to the final cache file that was then used as the source for all destination files.
library_id - The library that the current task is associated with.
task_processing_success - Boolean, did all task processes complete successfully.
file_move_processes_success - Boolean, did all postprocessor movement tasks complete successfully.
destination_files - List containing all file paths created by postprocessor file movements.
source_data - Dictionary containing data pertaining to the original source file.

:param data:
:return:
"""
return

Frontend - Data Panel

(since v0.1.0)

Executed:

From front-end URL

Function:

render_frontend_panel(data)

Provided data:
  • content_type [string] - The content type to be set when writing back to the browser.
  • content [string] - The content to print to the browser.
  • path [string] - The path received after the '/unmanic/panel' path.
  • arguments [dictionary] - A dictionary of GET arguments received.
Example:
plugin.py
def render_frontend_panel(data):
"""
Runner function - display a custom data panel in the frontend.

The 'data' object argument includes:
content_type - The content type to be set when writing back to the browser.
content - The content to print to the browser.
path - The path received after the '/unmanic/panel' path.
arguments - A dictionary of GET arguments received.

:param data:
:return:
"""

with open(os.path.abspath(os.path.join(os.path.dirname(__file__), 'static', 'index.html'))) as f:
content = f.read()
data['content'] = content.replace("{cache_buster}", str(uuid.uuid4()))

return
Details:

This Plugin runner type provides a Data Panel which will be displayed to the front-end.

Pages will be served from /unmanic/ui/data-panels?pluginId={plugin ID}.

Pages will be provided with a GET parameter either ?theme=light or ?theme=dark to assist with theme mapping with the main frontend.

Static assets stored in the plugins static directory will made available via the webserver at /unmanic/panel/{plugin ID}/static/(.*)


Frontend - Plugin API

(since v0.2.0)

Executed:

From front-end URL

Function:

render_plugin_api(data)

Provided data:
  • content_type [string] - The content type to be set when writing back to the browser.
  • content [string] - The content to print to the browser.
  • path [string] - The path received after the '/unmanic/panel' path.
  • uri [string] - The request uri.
  • query [string] - The request query.
  • arguments [dictionary] - A dictionary of GET arguments received.
  • body [dictionary] - A dictionary of body arguments received.
Example:
plugin.py
def render_plugin_api(data):
"""
Runner function - display a custom data panel in the frontend.

The 'data' object argument includes:
content_type - The content type to be set when writing back to the browser.
content - The content to print to the browser.
path - The path received after the '/unmanic/panel' path.
uri - The request uri.
query - The request query.
arguments - A dictionary of GET arguments received.
body - A dictionary of body arguments received.

:param data:
:return:
"""

# Store webhook content
settings = Settings()
profile_directory = settings.get_profile_directory()
time_now = time.time()
request_body = json.loads(data.get('body', '{}'))
with open(os.path.join(profile_directory, 'sonarr_webhook_{}.json'.format(time_now)), 'w') as outfile:
json.dump(request_body, outfile, indent=2)

return
Details:

This Plugin runner type provides an API endpoint which may be used to receive webhook requests or function as a REST API for the plugin.

Pages will be served from /unmanic/plugin_api/{plugin ID}.