diff --git a/autoProcessMedia.cfg.spec b/autoProcessMedia.cfg.spec index 15bda31e..3a40ad83 100644 --- a/autoProcessMedia.cfg.spec +++ b/autoProcessMedia.cfg.spec @@ -388,6 +388,35 @@ ##### Set to path where download client places completed downloads locally for this category watch_dir = +[Readarr] + #### autoProcessing for Books + #### raCategory - category that gets called for post-processing with Readarr + [[book]] + enabled = 0 + apikey = + host = localhost + port = 8787 + ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ###### + web_root = + ssl = 0 + delete_failed = 0 + # Enable/Disable linking for Torrents + Torrent_NoLink = 0 + keep_archive = 1 + extract = 1 + nzbExtractionBy = Downloader + # Minutes to wait after triggering the import before checking status + wait_for = 6 + # Set this to minimum required size to consider a media file valid (in MB) + minSize = 0 + # Enable/Disable deleting ignored files (samples and invalid files) + delete_ignored = 0 + ##### Enable if Readarr is on a remote server for this category + remote_path = 0 + ##### Set to path where download client places completed downloads locally for this category + watch_dir = + ##### Set to define import behaviour Move or Copy + importMode = Copy [Network] # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' diff --git a/core/auto_process/books.py b/core/auto_process/books.py index 9c908a94..d0983c62 100644 --- a/core/auto_process/books.py +++ b/core/auto_process/books.py @@ -34,6 +34,49 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', web_root = cfg.get('web_root', '') protocol = 'https://' if ssl else 'http://' remote_path = int(cfg.get('remote_path', 0)) + import_mode = cfg.get('importMode', cfg.get('importmode', 'Copy')) + + if section.lower() == 'readarr': + url = '{0}{1}:{2}{3}/api/v1/command'.format(protocol, host, port, web_root) + if not server_responding(url): + logger.error('Server did not respond. Exiting', section) + return ProcessResult( + message='{0}: Failed to post-process - {0} did not respond.'.format(section), + status_code=1, + ) + + input_name, dir_name = convert_to_ascii(input_name, dir_name) + + payload = { + "name": "DownloadedBooksScan", + "path": remote_dir(dir_name) if remote_path else dir_name, + "importMode": import_mode + } + headers = {"X-Api-Key": apikey} + + logger.debug('POST to {0} with payload: {1}'.format(url, payload), section) + + try: + r = requests.post(url, json=payload, headers=headers, verify=False, timeout=(30, 300)) + except requests.ConnectionError: + logger.error('Unable to connect to Readarr', section) + return ProcessResult( + message='{0}: Failed to post-process - Unable to connect'.format(section), + status_code=1, + ) + + if r.status_code in (200, 201, 202): + logger.postprocess('SUCCESS: Readarr import triggered for {0}'.format(dir_name), section) + return ProcessResult( + message='{0}: Successfully post-processed {1}'.format(section, input_name), + status_code=0, + ) + else: + logger.error('FAILED: Readarr returned status {0}, body: {1}'.format(r.status_code, r.text), section) + return ProcessResult( + message='{0}: Failed to post-process - HTTP {1}'.format(section, r.status_code), + status_code=1, + ) url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root) if not server_responding(url): diff --git a/core/processor/nzb.py b/core/processor/nzb.py index a649654e..81415830 100644 --- a/core/processor/nzb.py +++ b/core/processor/nzb.py @@ -131,7 +131,7 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d result = comics.process(section_name, input_directory, input_name, status, client_agent, input_category) elif section_name == 'Gamez': result = games.process(section_name, input_directory, input_name, status, client_agent, input_category) - elif section_name == 'LazyLibrarian': + elif section_name in ['LazyLibrarian', 'Readarr']: result = books.process(section_name, input_directory, input_name, status, client_agent, input_category) elif section_name == 'UserScript': result = external_script(input_directory, input_name, input_category, section[usercat]) @@ -147,7 +147,7 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d if client_agent != 'manual': # update download status in our DB update_download_info_status(input_name, 1) - if section_name not in ['UserScript', 'NzbDrone', 'Sonarr', 'Radarr', 'Lidarr']: + if section_name not in ['UserScript', 'NzbDrone', 'Sonarr', 'Radarr', 'Lidarr', 'Readarr']: # cleanup our processing folders of any misc unwanted files and empty directories clean_dir(input_directory, section_name, input_category) diff --git a/nzbToReadarr.py b/nzbToReadarr.py new file mode 100644 index 00000000..bd4cafcc --- /dev/null +++ b/nzbToReadarr.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# coding=utf-8 +# +############################################################################## +### NZBGET POST-PROCESSING SCRIPT ### + +# Post-Process to Readarr. +# +# This script sends the download to your automated media management servers. +# +# NOTE: This script requires Python to be installed on your system. + +############################################################################## +### OPTIONS ### + +## General + +# Auto Update nzbToMedia (0, 1). +# +# Set to 1 if you want nzbToMedia to automatically check for and update to the latest version +#auto_update=0 + +# Check Media for corruption (0, 1). +# +# Enable/Disable media file checking using ffprobe. +#check_media=1 + +# Safe Mode protection of DestDir (0, 1). +# +# Enable/Disable a safety check to ensure we don't process all downloads in the default_downloadDirectory by mistake. +#safe_mode=1 + +# Disable additional extraction checks for failed (0, 1). +# +# Turn this on to disable additional extraction attempts for failed downloads. Default = 0 this will attempt to extract and verify if media is present. +#no_extract_failed = 0 + +## Readarr + +# Readarr script category. +# +# category that gets called for post-processing with NzbDrone. +#raCategory=books + +# Readarr host. +# +# The ipaddress for your Readarr server. e.g For the Same system use localhost or 127.0.0.1 +#rahost=localhost + +# Readarr port. +#raport=8787 + +# Readarr API key. +#raapikey= + +# Readarr uses ssl (0, 1). +# +# Set to 1 if using ssl, else set to 0. +#rassl=0 + +# Readarr web_root +# +# set this if using a reverse proxy. +#raweb_root= + +# Readarr wait_for +# +# Set the number of minutes to wait after calling the renamer, to check the episode has changed status. +#rawait_for=6 + +# Readarr import mode (Move, Copy). +# +# set to define import behaviour Move or Copy +#raimportmode=Copy + +# Readarr Delete Failed Downloads (0, 1). +# +# set to 1 to delete failed, or 0 to leave files in place. +#radelete_failed=0 + +# Readarr and NZBGet are a different system (0, 1). +# +# Enable to replace local path with the path as per the mountPoints below. +#raremote_path=0 + +## Network + +# Network Mount Points (Needed for remote path above) +# +# Enter Mount points as LocalPath,RemotePath and separate each pair with '|' +# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ +#mountPoints= + +## Extensions + +# Media Extensions +# +# This is a list of media extensions that are used to verify that the download does contain valid media. +#mediaExtensions=.epub,.azw3,.mobi,.pdf,.docx,.fb2,.htmlz,.lit,.lrf,.pdb,.pmlz,.rb,.rtf,.snb,.tcr,.txt,.txtz,.zip,.flac + +### NZBGET POST-PROCESSING SCRIPT ### +############################################################################## + +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + +import sys + +import nzbToMedia + +section = 'Readarr' +result = nzbToMedia.main(sys.argv, section) +sys.exit(result)