You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
5.5 KiB
151 lines
5.5 KiB
import requests
|
|
import re
|
|
from pathlib import Path
|
|
import yaml
|
|
|
|
from app import guide
|
|
from app.api.sonarr import Sonarr
|
|
from app.guide import anime, utils, quality
|
|
from app.cmd import setup_and_parse_args
|
|
from app.logger import Logger
|
|
|
|
def process_sonarr_profile(args, logger):
|
|
profiles = anime.parse_markdown(args, logger, anime.get_trash_anime_markdown())
|
|
|
|
# A few false-positive profiles are added sometimes. We filter these out by checking if they
|
|
# actually have meaningful data attached to them, such as preferred terms. If they are mostly empty,
|
|
# we remove them here.
|
|
utils.filter_profiles(profiles)
|
|
|
|
if args.preview:
|
|
utils.print_terms_and_scores(profiles)
|
|
exit(0)
|
|
|
|
sonarr = Sonarr(args, logger)
|
|
|
|
# If tags were provided, ensure they exist. Tags that do not exist are added first, so that we
|
|
# may specify them with the release profile request payload.
|
|
tag_ids = []
|
|
if args.tags:
|
|
tags = sonarr.get_tags()
|
|
tags = sonarr.create_missing_tags(tags, args.tags[:])
|
|
logger.debug(f'Tags JSON: {tags}')
|
|
|
|
# Get a list of IDs that we can pass along with the request to update/create release
|
|
# profiles
|
|
tag_ids = [t['id'] for t in tags if t['label'] in args.tags]
|
|
logger.debug(f'Tag IDs: {tag_ids}')
|
|
|
|
# Obtain all of the existing release profiles first. If any were previously created by our script
|
|
# here, we favor replacing those instead of creating new ones, which would just be mostly duplicates
|
|
# (but with some differences, since there have likely been updates since the last run).
|
|
existing_profiles = sonarr.get_release_profiles()
|
|
|
|
for name, profile in profiles.items():
|
|
new_profile_name = f'[Trash] Anime - {name}'
|
|
profile_to_update = guide.utils.find_existing_profile(new_profile_name, existing_profiles)
|
|
|
|
if profile_to_update:
|
|
logger.info(f'Updating existing profile: {new_profile_name}')
|
|
sonarr.update_existing_profile(profile_to_update, profile, tag_ids)
|
|
else:
|
|
logger.info(f'Creating new profile: {new_profile_name}')
|
|
sonarr.create_release_profile(new_profile_name, profile, tag_ids)
|
|
|
|
def process_sonarr_quality(args, logger):
|
|
guide_definitions = quality.parse_markdown(logger, quality.get_markdown())
|
|
|
|
if args.type == 'sonarr:hybrid':
|
|
hybrid_quality_regex = re.compile(r'720|1080')
|
|
anime = guide_definitions.get('sonarr:anime')
|
|
nonanime = guide_definitions.get('sonarr:non-anime')
|
|
if len(anime) != len(nonanime):
|
|
raise RuntimeError('For some reason the anime and non-anime quality definitions are not the same length')
|
|
|
|
logger.info('Notice: Hybrid only functions on 720/1080 qualities and uses non-anime values for the rest (e.g. 2160)')
|
|
|
|
hybrid = []
|
|
for i in range(len(nonanime)):
|
|
left = nonanime[i]
|
|
if not hybrid_quality_regex.search(left[0]):
|
|
logger.debug('Ignored Quality: ' + left[0])
|
|
hybrid.append(left)
|
|
else:
|
|
right = None
|
|
for r in anime:
|
|
if r[0] == left[0]:
|
|
right = r
|
|
|
|
if right is None:
|
|
raise RuntimeError(f'Could not find matching anime quality for non-anime quality named: {left[0]}')
|
|
|
|
hybrid.append((left[0], min(left[1], right[1]), max(left[2], right[2])))
|
|
|
|
guide_definitions['sonarr:hybrid'] = hybrid
|
|
|
|
selected_definition = guide_definitions.get(args.type)
|
|
|
|
if args.preview:
|
|
utils.quality_preview(selected_definition)
|
|
exit(0)
|
|
|
|
print(f'Updating quality definition using {args.type}')
|
|
sonarr = Sonarr(args, logger)
|
|
definition = sonarr.get_quality_definition()
|
|
sonarr.update_quality_definition(definition, selected_definition)
|
|
|
|
def load_config(args, logger):
|
|
if args.config_file:
|
|
config_path = Path(args.config_file)
|
|
else:
|
|
# Look for `trash.yml` in the same directory as the python script.
|
|
config_path = Path(__name__).parent / 'trash.yml'
|
|
|
|
logger.debug(f'Using configuration file: {config_path}')
|
|
|
|
if config_path.exists():
|
|
config = None
|
|
with open(config_path, 'r') as f:
|
|
config = yaml.load(f, Loader=yaml.Loader)
|
|
|
|
# TODO: Determine whether to use sonarr or radarr configs?
|
|
sonarr_config = config['sonarr']
|
|
|
|
if not args.base_uri:
|
|
args.base_uri = sonarr_config['base_uri']
|
|
|
|
if not args.api_key:
|
|
args.api_key = sonarr_config['api_key']
|
|
else:
|
|
logger.debug('Config file could not be loaded because it does not exist')
|
|
|
|
def main():
|
|
args = setup_and_parse_args()
|
|
logger = Logger(args)
|
|
|
|
load_config(args, logger)
|
|
|
|
if args.subcommand == 'profile':
|
|
if args.type.startswith('sonarr:'):
|
|
process_sonarr_profile(args, logger)
|
|
elif args.type.startswith('radarr:'):
|
|
raise NotImplementedError('Radarr guide support is not implemented yet')
|
|
|
|
elif args.subcommand == 'quality':
|
|
if args.type.startswith('sonarr:'):
|
|
process_sonarr_quality(args, logger)
|
|
elif args.type.startswith('radarr:'):
|
|
raise NotImplementedError('Radarr quality support is not implemented yet')
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
main()
|
|
except requests.exceptions.HTTPError as e:
|
|
print(e)
|
|
if error_msg := Sonarr.get_error_message(e.response):
|
|
print(f'Response Message: {error_msg}')
|
|
exit(1)
|
|
except Exception as e:
|
|
print(f'ERROR: {e}')
|
|
exit(1)
|