diff --git a/CHANGELOG.md b/CHANGELOG.md index 86371bc520..fdcf999b03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## Unreleased +#### New Features + +#### Improvements +- Updated `guessit` to version 3.0.0 ([#4244](https://github.com/pymedusa/Medusa/pull/4244)) + +#### Fixes +- Fixed many release name parsing issues as a result of updating `guessit` ([#4244](https://github.com/pymedusa/Medusa/pull/4244)) + ----- ## 0.2.9 (2018-09-06) diff --git a/ext/guessit/__init__.py b/ext/guessit/__init__.py index 22e9dbb07c..365935eb0a 100644 --- a/ext/guessit/__init__.py +++ b/ext/guessit/__init__.py @@ -5,5 +5,6 @@ """ from .api import guessit, GuessItApi from .options import ConfigurationException +from .rules.common.quantity import Size from .__version__ import __version__ diff --git a/ext/guessit/__main__.py b/ext/guessit/__main__.py index 79c26617b3..3b4e815fa2 100644 --- a/ext/guessit/__main__.py +++ b/ext/guessit/__main__.py @@ -20,6 +20,12 @@ from guessit.options import argument_parser, parse_options, load_config +try: + from collections import OrderedDict +except ImportError: # pragma: no-cover + from ordereddict import OrderedDict # pylint:disable=import-error + + def guess_filename(filename, options): """ Guess a single filename using given options @@ -45,7 +51,7 @@ def guess_filename(filename, options): import yaml from guessit import yamlutils - ystr = yaml.dump({filename: dict(guess)}, Dumper=yamlutils.CustomDumper, default_flow_style=False, + ystr = yaml.dump({filename: OrderedDict(guess)}, Dumper=yamlutils.CustomDumper, default_flow_style=False, allow_unicode=True) i = 0 for yline in ystr.splitlines(): diff --git a/ext/guessit/__version__.py b/ext/guessit/__version__.py index 703c455a80..4f64b22111 100644 --- a/ext/guessit/__version__.py +++ b/ext/guessit/__version__.py @@ -4,4 +4,4 @@ Version module """ # pragma: no cover -__version__ = '2.1.4' +__version__ = '3.0.0' diff --git a/ext/guessit/api.py b/ext/guessit/api.py index 3194af88a5..555b8d865c 100644 --- a/ext/guessit/api.py +++ b/ext/guessit/api.py @@ -3,11 +3,13 @@ """ API functions that can be used by external software """ + try: from collections import OrderedDict except ImportError: # pragma: no-cover from ordereddict import OrderedDict # pylint:disable=import-error +import os import traceback import six @@ -15,7 +17,7 @@ from rebulk.introspector import introspect from .rules import rebulk_builder -from .options import parse_options +from .options import parse_options, load_config from .__version__ import __version__ @@ -41,12 +43,25 @@ def __init__(self, string, options): self.options = options +def configure(options, rules_builder=rebulk_builder): + """ + Load rebulk rules according to advanced configuration in options dictionary. + + :param options: + :type options: dict + :param rules_builder: + :type rules_builder: + :return: + """ + default_api.configure(options, rules_builder=rules_builder, force=True) + + def guessit(string, options=None): """ Retrieves all matches from string as a dict :param string: the filename or release name :type string: str - :param options: the filename or release name + :param options: :type options: str|dict :return: :rtype: @@ -58,7 +73,7 @@ def properties(options=None): """ Retrieves all properties with possible values that can be guessed :param options: - :type options: + :type options: str|dict :return: :rtype: """ @@ -70,53 +85,88 @@ class GuessItApi(object): An api class that can be configured with custom Rebulk configuration. """ - def __init__(self, rebulk): - """ - :param rebulk: Rebulk instance to use. - :type rebulk: Rebulk - :return: - :rtype: - """ - self.rebulk = rebulk + def __init__(self): + """Default constructor.""" + self.rebulk = None - @staticmethod - def _fix_option_encoding(value): + @classmethod + def _fix_encoding(cls, value): if isinstance(value, list): - return [GuessItApi._fix_option_encoding(item) for item in value] + return [cls._fix_encoding(item) for item in value] + if isinstance(value, dict): + return {cls._fix_encoding(k): cls._fix_encoding(v) for k, v in value.items()} if six.PY2 and isinstance(value, six.text_type): - return value.encode("utf-8") + return value.encode('utf-8') if six.PY3 and isinstance(value, six.binary_type): return value.decode('ascii') return value - def guessit(self, string, options=None): + def configure(self, options, rules_builder=rebulk_builder, force=False): + """ + Load rebulk rules according to advanced configuration in options dictionary. + + :param options: + :type options: str|dict + :param rules_builder: + :type rules_builder: + :param force: + :return: + :rtype: dict + """ + options = parse_options(options, True) + should_load = force or not self.rebulk + advanced_config = options.pop('advanced_config', None) + + if should_load and not advanced_config: + advanced_config = load_config(options)['advanced_config'] + + options = self._fix_encoding(options) + + if should_load: + advanced_config = self._fix_encoding(advanced_config) + self.rebulk = rules_builder(advanced_config) + + return options + + def guessit(self, string, options=None): # pylint: disable=too-many-branches """ Retrieves all matches from string as a dict :param string: the filename or release name - :type string: str - :param options: the filename or release name + :type string: str|Path + :param options: :type options: str|dict :return: :rtype: """ try: - options = parse_options(options, True) + from pathlib import Path + if isinstance(string, Path): + try: + # Handle path-like object + string = os.fspath(string) + except AttributeError: + string = str(string) + except ImportError: + pass + + try: + options = self.configure(options) result_decode = False result_encode = False - fixed_options = {} - for (key, value) in options.items(): - key = GuessItApi._fix_option_encoding(key) - value = GuessItApi._fix_option_encoding(value) - fixed_options[key] = value - options = fixed_options - - if six.PY2 and isinstance(string, six.text_type): - string = string.encode("utf-8") - result_decode = True - if six.PY3 and isinstance(string, six.binary_type): - string = string.decode('ascii') - result_encode = True + if six.PY2: + if isinstance(string, six.text_type): + string = string.encode("utf-8") + result_decode = True + elif isinstance(string, six.binary_type): + string = six.binary_type(string) + if six.PY3: + if isinstance(string, six.binary_type): + string = string.decode('ascii') + result_encode = True + elif isinstance(string, six.text_type): + string = six.text_type(string) + matches = self.rebulk.matches(string, options) if result_decode: for match in matches: @@ -139,6 +189,7 @@ def properties(self, options=None): :return: :rtype: """ + options = self.configure(options) unordered = introspect(self.rebulk, options).properties ordered = OrderedDict() for k in sorted(unordered.keys(), key=six.text_type): @@ -148,4 +199,4 @@ def properties(self, options=None): return ordered -default_api = GuessItApi(rebulk_builder()) +default_api = GuessItApi() diff --git a/ext/guessit/config/options.json b/ext/guessit/config/options.json index 11b4774811..0fe274b16e 100644 --- a/ext/guessit/config/options.json +++ b/ext/guessit/config/options.json @@ -1,5 +1,363 @@ { "expected_title": [ "OSS 117" - ] + ], + "allowed_countries": [ + "au", + "us", + "gb" + ], + "allowed_languages": [ + "de", + "en", + "es", + "ca", + "cs", + "fr", + "he", + "hi", + "hu", + "it", + "ja", + "ko", + "nl", + "pl", + "pt", + "ro", + "ru", + "sv", + "te", + "uk", + "mul", + "und" + ], + "advanced_config": { + "common_words": [ + "de", + "it" + ], + "groups": { + "starting": "([{", + "ending": ")]}" + }, + "container": { + "subtitles": [ + "srt", + "idx", + "sub", + "ssa", + "ass" + ], + "info": [ + "nfo" + ], + "videos": [ + "3g2", + "3gp", + "3gp2", + "asf", + "avi", + "divx", + "flv", + "m4v", + "mk2", + "mka", + "mkv", + "mov", + "mp4", + "mp4a", + "mpeg", + "mpg", + "ogg", + "ogm", + "ogv", + "qt", + "ra", + "ram", + "rm", + "ts", + "wav", + "webm", + "wma", + "wmv", + "iso", + "vob" + ], + "torrent": [ + "torrent" + ], + "nzb": [ + "nzb" + ] + }, + "country": { + "synonyms": { + "ES": [ + "españa" + ], + "GB": [ + "UK" + ], + "BR": [ + "brazilian", + "bra" + ], + "CA": [ + "québec", + "quebec", + "qc" + ], + "MX": [ + "Latinoamérica", + "latin america" + ] + } + }, + "episodes": { + "season_max_range": 100, + "episode_max_range": 100, + "max_range_gap": 1, + "season_markers": [ + "s" + ], + "season_ep_markers": [ + "x" + ], + "disc_markers": [ + "d" + ], + "episode_markers": [ + "xe", + "ex", + "ep", + "e", + "x" + ], + "range_separators": [ + "-", + "~", + "to", + "a" + ], + "discrete_separators": [ + "+", + "&", + "and", + "et" + ], + "season_words": [ + "season", + "saison", + "seizoen", + "serie", + "seasons", + "saisons", + "series", + "tem", + "temp", + "temporada", + "temporadas", + "stagione" + ], + "episode_words": [ + "episode", + "episodes", + "eps", + "ep", + "episodio", + "episodios", + "capitulo", + "capitulos" + ], + "of_words": [ + "of", + "sur" + ], + "all_words": [ + "All" + ] + }, + "language": { + "synonyms": { + "ell": [ + "gr", + "greek" + ], + "spa": [ + "esp", + "español", + "espanol" + ], + "fra": [ + "français", + "vf", + "vff", + "vfi", + "vfq" + ], + "swe": [ + "se" + ], + "por_BR": [ + "po", + "pb", + "pob", + "ptbr", + "br", + "brazilian" + ], + "deu_CH": [ + "swissgerman", + "swiss german" + ], + "nld_BE": [ + "flemish" + ], + "cat": [ + "català", + "castellano", + "espanol castellano", + "español castellano" + ], + "ces": [ + "cz" + ], + "ukr": [ + "ua" + ], + "zho": [ + "cn" + ], + "jpn": [ + "jp" + ], + "hrv": [ + "scr" + ], + "mul": [ + "multi", + "dl" + ] + }, + "subtitle_affixes": [ + "sub", + "subs", + "esub", + "esubs", + "subbed", + "custom subbed", + "custom subs", + "custom sub", + "customsubbed", + "customsubs", + "customsub", + "soft subtitles", + "soft subs" + ], + "subtitle_prefixes": [ + "st", + "v", + "vost", + "subforced", + "fansub", + "hardsub", + "legenda", + "legendas", + "legendado", + "subtitulado", + "soft", + "subtitles" + ], + "subtitle_suffixes": [ + "subforced", + "fansub", + "hardsub" + ], + "language_affixes": [ + "dublado", + "dubbed", + "dub" + ], + "language_prefixes": [ + "true" + ], + "language_suffixes": [ + "audio" + ], + "weak_affixes": [ + "v", + "audio", + "true" + ] + }, + "part": { + "prefixes": [ + "pt", + "part" + ] + }, + "release_group": { + "forbidden_names": [ + "rip", + "by", + "for", + "par", + "pour", + "bonus" + ], + "ignored_seps": "[]{}()" + }, + "screen_size": { + "frame_rates": [ + "23.976", + "24", + "25", + "30", + "48", + "50", + "60", + "120" + ], + "min_ar": 1.333, + "max_ar": 1.898, + "interlaced": [ + "360", + "480", + "576", + "900", + "1080" + ], + "progressive": [ + "360", + "480", + "576", + "900", + "1080", + "368", + "720", + "1440", + "2160", + "4320" + ] + }, + "website": { + "safe_tlds": [ + "com", + "org", + "net" + ], + "safe_subdomains": [ + "www" + ], + "safe_prefixes": [ + "co", + "com", + "org", + "net" + ], + "prefixes": [ + "from" + ] + } + } } \ No newline at end of file diff --git a/ext/guessit/jsonutils.py b/ext/guessit/jsonutils.py index 7d6ff7055c..a8bb24e6e6 100644 --- a/ext/guessit/jsonutils.py +++ b/ext/guessit/jsonutils.py @@ -4,6 +4,9 @@ JSON Utils """ import json + +from six import text_type + try: from collections import OrderedDict except ImportError: # pragma: no-cover @@ -27,6 +30,6 @@ def default(self, o): # pylint:disable=method-hidden ret['end'] = o.end return ret elif hasattr(o, 'name'): # Babelfish languages/countries long name - return str(o.name) + return text_type(o.name) else: # pragma: no cover - return str(o) + return text_type(o) diff --git a/ext/guessit/options.py b/ext/guessit/options.py index fcf39e8a70..e39df3650b 100644 --- a/ext/guessit/options.py +++ b/ext/guessit/options.py @@ -42,6 +42,10 @@ def build_argument_parser(): help='Expected title to parse (can be used multiple times)') naming_opts.add_argument('-G', '--expected-group', action='append', dest='expected_group', default=None, help='Expected release group (can be used multiple times)') + naming_opts.add_argument('--includes', action='append', dest='includes', default=None, + help='List of properties to be detected') + naming_opts.add_argument('--excludes', action='append', dest='excludes', default=None, + help='List of properties to be ignored') input_opts = opts.add_argument_group("Input") input_opts.add_argument('-f', '--input-file', dest='input_file', default=None, @@ -92,7 +96,7 @@ def parse_options(options=None, api=False): :param options: :type options: :param api - :type boolean + :type api: boolean :return: :rtype: """ @@ -157,10 +161,12 @@ def load_config(options): if config_file_options: configurations.append(config_file_options) + embedded_options_data = pkgutil.get_data('guessit', 'config/options.json').decode("utf-8") + embedded_options = json.loads(embedded_options_data) if not options.get('no_embedded_config'): - embedded_options_data = pkgutil.get_data('guessit', 'config/options.json').decode("utf-8") - embedded_options = json.loads(embedded_options_data) configurations.append(embedded_options) + else: + configurations.append({'advanced_config': embedded_options['advanced_config']}) if configurations: configurations.append(options) diff --git a/ext/guessit/rules/__init__.py b/ext/guessit/rules/__init__.py index d01bc6b28a..f16bc4e0fb 100644 --- a/ext/guessit/rules/__init__.py +++ b/ext/guessit/rules/__init__.py @@ -10,7 +10,7 @@ from .properties.episodes import episodes from .properties.container import container -from .properties.format import format_ +from .properties.source import source from .properties.video_codec import video_codec from .properties.audio_codec import audio_codec from .properties.screen_size import screen_size @@ -24,6 +24,7 @@ from .properties.streaming_service import streaming_service from .properties.other import other from .properties.size import size +from .properties.bit_rate import bit_rate from .properties.edition import edition from .properties.cds import cds from .properties.bonus import bonus @@ -36,44 +37,50 @@ from .processors import processors -def rebulk_builder(): +def rebulk_builder(config): """ Default builder for main Rebulk object used by api. :return: Main Rebulk object :rtype: Rebulk """ + def _config(name): + return config.get(name, {}) + rebulk = Rebulk() - rebulk.rebulk(path()) - rebulk.rebulk(groups()) - - rebulk.rebulk(episodes()) - rebulk.rebulk(container()) - rebulk.rebulk(format_()) - rebulk.rebulk(video_codec()) - rebulk.rebulk(audio_codec()) - rebulk.rebulk(screen_size()) - rebulk.rebulk(website()) - rebulk.rebulk(date()) - rebulk.rebulk(title()) - rebulk.rebulk(episode_title()) - rebulk.rebulk(language()) - rebulk.rebulk(country()) - rebulk.rebulk(release_group()) - rebulk.rebulk(streaming_service()) - rebulk.rebulk(other()) - rebulk.rebulk(size()) - rebulk.rebulk(edition()) - rebulk.rebulk(cds()) - rebulk.rebulk(bonus()) - rebulk.rebulk(film()) - rebulk.rebulk(part()) - rebulk.rebulk(crc()) - - rebulk.rebulk(processors()) - - rebulk.rebulk(mimetype()) - rebulk.rebulk(type_()) + common_words = frozenset(_config('common_words')) + + rebulk.rebulk(path(_config('path'))) + rebulk.rebulk(groups(_config('groups'))) + + rebulk.rebulk(episodes(_config('episodes'))) + rebulk.rebulk(container(_config('container'))) + rebulk.rebulk(source(_config('source'))) + rebulk.rebulk(video_codec(_config('video_codec'))) + rebulk.rebulk(audio_codec(_config('audio_codec'))) + rebulk.rebulk(screen_size(_config('screen_size'))) + rebulk.rebulk(website(_config('website'))) + rebulk.rebulk(date(_config('date'))) + rebulk.rebulk(title(_config('title'))) + rebulk.rebulk(episode_title(_config('episode_title'))) + rebulk.rebulk(language(_config('language'), common_words)) + rebulk.rebulk(country(_config('country'), common_words)) + rebulk.rebulk(release_group(_config('release_group'))) + rebulk.rebulk(streaming_service(_config('streaming_service'))) + rebulk.rebulk(other(_config('other'))) + rebulk.rebulk(size(_config('size'))) + rebulk.rebulk(bit_rate(_config('bit_rate'))) + rebulk.rebulk(edition(_config('edition'))) + rebulk.rebulk(cds(_config('cds'))) + rebulk.rebulk(bonus(_config('bonus'))) + rebulk.rebulk(film(_config('film'))) + rebulk.rebulk(part(_config('part'))) + rebulk.rebulk(crc(_config('crc'))) + + rebulk.rebulk(processors(_config('processors'))) + + rebulk.rebulk(mimetype(_config('mimetype'))) + rebulk.rebulk(type_(_config('type'))) def customize_properties(properties): """ diff --git a/ext/guessit/rules/common/comparators.py b/ext/guessit/rules/common/comparators.py index ee104ba686..f46f0c1196 100644 --- a/ext/guessit/rules/common/comparators.py +++ b/ext/guessit/rules/common/comparators.py @@ -13,9 +13,12 @@ def marker_comparator_predicate(match): """ Match predicate used in comparator """ - return not match.private and \ - match.name not in ['proper_count', 'title', 'episode_title', 'alternative_title'] and \ - not (match.name == 'container' and 'extension' in match.tags) + return ( + not match.private + and match.name not in ('proper_count', 'title') + and not (match.name == 'container' and 'extension' in match.tags) + and not (match.name == 'other' and match.value == 'Rip') + ) def marker_weight(matches, marker, predicate): @@ -50,9 +53,8 @@ def comparator(marker1, marker2): matches_count = marker_weight(matches, marker2, predicate) - marker_weight(matches, marker1, predicate) if matches_count: return matches_count - len_diff = len(marker2) - len(marker1) - if len_diff: - return len_diff + + # give preference to rightmost path return markers.index(marker2) - markers.index(marker1) return comparator diff --git a/ext/guessit/rules/common/date.py b/ext/guessit/rules/common/date.py index d6fb523a14..cef31fdcd0 100644 --- a/ext/guessit/rules/common/date.py +++ b/ext/guessit/rules/common/date.py @@ -42,7 +42,7 @@ def _is_int(string): return False -def _guess_day_first_parameter(groups): +def _guess_day_first_parameter(groups): # pylint:disable=inconsistent-return-statements """ If day_first is not defined, use some heuristic to fix it. It helps to solve issues with python dateutils 2.5.3 parser changes. @@ -67,7 +67,7 @@ def _guess_day_first_parameter(groups): return True -def search_date(string, year_first=None, day_first=None): +def search_date(string, year_first=None, day_first=None): # pylint:disable=inconsistent-return-statements """Looks for date patterns, and if found return the date and group span. Assumes there are sentinels at the beginning and end of the string that diff --git a/ext/guessit/rules/common/pattern.py b/ext/guessit/rules/common/pattern.py new file mode 100644 index 0000000000..5f560f2c96 --- /dev/null +++ b/ext/guessit/rules/common/pattern.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Pattern utility functions +""" + + +def is_disabled(context, name): + """Whether a specific pattern is disabled. + + The context object might define an inclusion list (includes) or an exclusion list (excludes) + A pattern is considered disabled if it's found in the exclusion list or + it's not found in the inclusion list and the inclusion list is not empty or not defined. + + :param context: + :param name: + :return: + """ + if not context: + return False + + excludes = context.get('excludes') + if excludes and name in excludes: + return True + + includes = context.get('includes') + return includes and name not in includes diff --git a/ext/guessit/rules/common/quantity.py b/ext/guessit/rules/common/quantity.py new file mode 100644 index 0000000000..bbd41fbb92 --- /dev/null +++ b/ext/guessit/rules/common/quantity.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Quantities: Size +""" +import re +from abc import abstractmethod + +import six + +from ..common import seps + + +class Quantity(object): + """ + Represent a quantity object with magnitude and units. + """ + + parser_re = re.compile(r'(?P\d+(?:[.]\d+)?)(?P[^\d]+)?') + + def __init__(self, magnitude, units): + self.magnitude = magnitude + self.units = units + + @classmethod + @abstractmethod + def parse_units(cls, value): + """ + Parse a string to a proper unit notation. + """ + raise NotImplementedError + + @classmethod + def fromstring(cls, string): + """ + Parse the string into a quantity object. + :param string: + :return: + """ + values = cls.parser_re.match(string).groupdict() + try: + magnitude = int(values['magnitude']) + except ValueError: + magnitude = float(values['magnitude']) + units = cls.parse_units(values['units']) + + return cls(magnitude, units) + + def __hash__(self): + return hash(str(self)) + + def __eq__(self, other): + if isinstance(other, six.string_types): + return str(self) == other + if not isinstance(other, self.__class__): + return NotImplemented + return self.magnitude == other.magnitude and self.units == other.units + + def __ne__(self, other): + return not self == other + + def __repr__(self): + return '<{0} [{1}]>'.format(self.__class__.__name__, self) + + def __str__(self): + return '{0}{1}'.format(self.magnitude, self.units) + + +class Size(Quantity): + """ + Represent size. + + e.g.: 1.1GB, 300MB + """ + + @classmethod + def parse_units(cls, value): + return value.strip(seps).upper() + + +class BitRate(Quantity): + """ + Represent bit rate. + + e.g.: 320Kbps, 1.5Mbps + """ + + @classmethod + def parse_units(cls, value): + value = value.strip(seps).capitalize() + for token in ('bits', 'bit'): + value = value.replace(token, 'bps') + + return value + + +class FrameRate(Quantity): + """ + Represent frame rate. + + e.g.: 24fps, 60fps + """ + + @classmethod + def parse_units(cls, value): + return 'fps' diff --git a/ext/guessit/rules/common/words.py b/ext/guessit/rules/common/words.py index 8882acb3dd..cccbc7d235 100644 --- a/ext/guessit/rules/common/words.py +++ b/ext/guessit/rules/common/words.py @@ -32,48 +32,3 @@ def iter_words(string): i += 1 if inside_word: yield _Word(span=(last_sep_index+1, i), value=string[last_sep_index+1:i]) - - -# list of common words which could be interpreted as properties, but which -# are far too common to be able to say they represent a property in the -# middle of a string (where they most likely carry their commmon meaning) -COMMON_WORDS = frozenset([ - # english words - 'is', 'it', 'am', 'mad', 'men', 'man', 'run', 'sin', 'st', 'to', - 'no', 'non', 'war', 'min', 'new', 'car', 'day', 'bad', 'bat', 'fan', - 'fry', 'cop', 'zen', 'gay', 'fat', 'one', 'cherokee', 'got', 'an', 'as', - 'cat', 'her', 'be', 'hat', 'sun', 'may', 'my', 'mr', 'rum', 'pi', 'bb', - 'bt', 'tv', 'aw', 'by', 'md', 'mp', 'cd', 'lt', 'gt', 'in', 'ad', 'ice', - 'ay', 'at', 'star', 'so', 'he', 'do', 'ax', 'mx', - # french words - 'bas', 'de', 'le', 'son', 'ne', 'ca', 'ce', 'et', 'que', - 'mal', 'est', 'vol', 'or', 'mon', 'se', 'je', 'tu', 'me', - 'ne', 'ma', 'va', 'au', 'lu', - # japanese words, - 'wa', 'ga', 'ao', - # spanish words - 'la', 'el', 'del', 'por', 'mar', 'al', - # italian words - 'un', - # other - 'ind', 'arw', 'ts', 'ii', 'bin', 'chan', 'ss', 'san', 'oss', 'iii', - 'vi', 'ben', 'da', 'lt', 'ch', 'sr', 'ps', 'cx', 'vo', - # new from babelfish - 'mkv', 'avi', 'dmd', 'the', 'dis', 'cut', 'stv', 'des', 'dia', 'and', - 'cab', 'sub', 'mia', 'rim', 'las', 'une', 'par', 'srt', 'ano', 'toy', - 'job', 'gag', 'reel', 'www', 'for', 'ayu', 'csi', 'ren', 'moi', 'sur', - 'fer', 'fun', 'two', 'big', 'psy', 'air', - # movie title - 'brazil', 'jordan', - # release groups - 'bs', # Bosnian - 'kz', - # countries - 'gt', 'lt', 'im', - # part/pt - 'pt', - # screener - 'scr', - # quality - 'sd', 'hr' -]) diff --git a/ext/guessit/rules/markers/groups.py b/ext/guessit/rules/markers/groups.py index bbe69d1c31..4716d15d7f 100644 --- a/ext/guessit/rules/markers/groups.py +++ b/ext/guessit/rules/markers/groups.py @@ -6,17 +6,20 @@ from rebulk import Rebulk -def groups(): +def groups(config): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ rebulk = Rebulk() rebulk.defaults(name="group", marker=True) - starting = '([{' - ending = ')]}' + starting = config['starting'] + ending = config['ending'] def mark_groups(input_string): """ diff --git a/ext/guessit/rules/markers/path.py b/ext/guessit/rules/markers/path.py index 5e487ea6bb..6d993b75a8 100644 --- a/ext/guessit/rules/markers/path.py +++ b/ext/guessit/rules/markers/path.py @@ -8,9 +8,12 @@ from rebulk.utils import find_all -def path(): +def path(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ @@ -22,6 +25,7 @@ def mark_path(input_string, context): Functional pattern to mark path elements. :param input_string: + :param context: :return: """ ret = [] diff --git a/ext/guessit/rules/processors.py b/ext/guessit/rules/processors.py index 0f21d0835a..6f5d731f6b 100644 --- a/ext/guessit/rules/processors.py +++ b/ext/guessit/rules/processors.py @@ -34,8 +34,7 @@ def when(self, matches, context): for match in matches.ending(group.end - 1): ending.append(match) - if starting or ending: - return starting, ending + return starting, ending def then(self, matches, when_response, context): starting, ending = when_response @@ -226,9 +225,12 @@ def then(self, matches, when_response, context): # pragma: no cover match.raw_end -= 1 -def processors(): +def processors(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ diff --git a/ext/guessit/rules/properties/audio_codec.py b/ext/guessit/rules/properties/audio_codec.py index 922df92893..a1cf585e0d 100644 --- a/ext/guessit/rules/properties/audio_codec.py +++ b/ext/guessit/rules/properties/audio_codec.py @@ -6,15 +6,20 @@ from rebulk.remodule import re from rebulk import Rebulk, Rule, RemoveMatch + from ..common import dash +from ..common.pattern import is_disabled from ..common.validators import seps_before, seps_after audio_properties = ['audio_codec', 'audio_profile', 'audio_channels'] -def audio_codec(): +def audio_codec(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ @@ -36,28 +41,38 @@ def audio_codec_priority(match1, match2): return match1 return '__default__' - rebulk.defaults(name="audio_codec", conflict_solver=audio_codec_priority) + rebulk.defaults(name='audio_codec', + conflict_solver=audio_codec_priority, + disabled=lambda context: is_disabled(context, 'audio_codec')) rebulk.regex("MP3", "LAME", r"LAME(?:\d)+-?(?:\d)+", value="MP3") - rebulk.regex('Dolby', 'DolbyDigital', 'Dolby-Digital', 'DD', 'AC3D?', value='AC3') - rebulk.regex("DolbyAtmos", "Dolby-Atmos", "Atmos", value="DolbyAtmos") + rebulk.regex('Dolby', 'DolbyDigital', 'Dolby-Digital', 'DD', 'AC3D?', value='Dolby Digital') + rebulk.regex('Dolby-?Atmos', 'Atmos', value='Dolby Atmos') rebulk.string("AAC", value="AAC") - rebulk.string('EAC3', 'DDP', 'DD+', value="EAC3") + rebulk.string('EAC3', 'DDP', 'DD+', value='Dolby Digital Plus') rebulk.string("Flac", value="FLAC") rebulk.string("DTS", value="DTS") - rebulk.regex("True-?HD", value="TrueHD") - - rebulk.defaults(name="audio_profile") - rebulk.string("HD", value="HD", tags="DTS") - rebulk.regex("HD-?MA", value="HDMA", tags="DTS") - rebulk.string("HE", value="HE", tags="AAC") - rebulk.string("LC", value="LC", tags="AAC") - rebulk.string("HQ", value="HQ", tags="AC3") - - rebulk.defaults(name="audio_channels") - rebulk.regex(r'(7[\W_][01](?:ch)?)(?:[^\d]|$)', value='7.1', children=True) - rebulk.regex(r'(5[\W_][01](?:ch)?)(?:[^\d]|$)', value='5.1', children=True) - rebulk.regex(r'(2[\W_]0(?:ch)?)(?:[^\d]|$)', value='2.0', children=True) + rebulk.regex('DTS-?HD', 'DTS(?=-?MA)', value='DTS-HD', + conflict_solver=lambda match, other: other if other.name == 'audio_codec' else '__default__') + rebulk.regex('True-?HD', value='Dolby TrueHD') + rebulk.string('Opus', value='Opus') + rebulk.string('Vorbis', value='Vorbis') + rebulk.string('PCM', value='PCM') + rebulk.string('LPCM', value='LPCM') + + rebulk.defaults(name='audio_profile', disabled=lambda context: is_disabled(context, 'audio_profile')) + rebulk.string('MA', value='Master Audio', tags='DTS-HD') + rebulk.string('HR', 'HRA', value='High Resolution Audio', tags='DTS-HD') + rebulk.string('ES', value='Extended Surround', tags='DTS') + rebulk.string('HE', value='High Efficiency', tags='AAC') + rebulk.string('LC', value='Low Complexity', tags='AAC') + rebulk.string('HQ', value='High Quality', tags='Dolby Digital') + rebulk.string('EX', value='EX', tags='Dolby Digital') + + rebulk.defaults(name="audio_channels", disabled=lambda context: is_disabled(context, 'audio_channels')) + rebulk.regex(r'(7[\W_][01](?:ch)?)(?=[^\d]|$)', value='7.1', children=True) + rebulk.regex(r'(5[\W_][01](?:ch)?)(?=[^\d]|$)', value='5.1', children=True) + rebulk.regex(r'(2[\W_]0(?:ch)?)(?=[^\d]|$)', value='2.0', children=True) rebulk.regex('7[01]', value='7.1', validator=seps_after, tags='weak-audio_channels') rebulk.regex('5[01]', value='5.1', validator=seps_after, tags='weak-audio_channels') rebulk.string('20', value='2.0', validator=seps_after, tags='weak-audio_channels') @@ -66,7 +81,7 @@ def audio_codec_priority(match1, match2): rebulk.string('2ch', 'stereo', value='2.0') rebulk.string('1ch', 'mono', value='1.0') - rebulk.rules(DtsRule, AacRule, Ac3Rule, AudioValidatorRule, HqConflictRule, AudioChannelsValidatorRule) + rebulk.rules(DtsHDRule, AacRule, DolbyDigitalRule, AudioValidatorRule, HqConflictRule, AudioChannelsValidatorRule) return rebulk @@ -111,6 +126,9 @@ def __init__(self, codec): super(AudioProfileRule, self).__init__() self.codec = codec + def enabled(self, context): + return not is_disabled(context, 'audio_profile') + def when(self, matches, context): profile_list = matches.named('audio_profile', lambda match: self.codec in match.tags) ret = [] @@ -120,16 +138,18 @@ def when(self, matches, context): codec = matches.next(profile, lambda match: match.name == 'audio_codec' and match.value == self.codec) if not codec: ret.append(profile) + if codec: + ret.extend(matches.conflicting(profile)) return ret -class DtsRule(AudioProfileRule): +class DtsHDRule(AudioProfileRule): """ - Rule to validate DTS profile + Rule to validate DTS-HD profile """ def __init__(self): - super(DtsRule, self).__init__("DTS") + super(DtsHDRule, self).__init__('DTS-HD') class AacRule(AudioProfileRule): @@ -141,13 +161,13 @@ def __init__(self): super(AacRule, self).__init__("AAC") -class Ac3Rule(AudioProfileRule): +class DolbyDigitalRule(AudioProfileRule): """ - Rule to validate AC3 profile + Rule to validate Dolby Digital profile """ def __init__(self): - super(Ac3Rule, self).__init__("AC3") + super(DolbyDigitalRule, self).__init__('Dolby Digital') class HqConflictRule(Rule): @@ -155,16 +175,16 @@ class HqConflictRule(Rule): Solve conflict between HQ from other property and from audio_profile. """ - dependency = [DtsRule, AacRule, Ac3Rule] + dependency = [DtsHDRule, AacRule, DolbyDigitalRule] consequence = RemoveMatch + def enabled(self, context): + return not is_disabled(context, 'audio_profile') + def when(self, matches, context): - hq_audio = matches.named('audio_profile', lambda match: match.value == 'HQ') + hq_audio = matches.named('audio_profile', lambda m: m.value == 'High Quality') hq_audio_spans = [match.span for match in hq_audio] - hq_other = matches.named('other', lambda match: match.span in hq_audio_spans) - - if hq_other: - return hq_other + return matches.named('other', lambda m: m.span in hq_audio_spans) class AudioChannelsValidatorRule(Rule): @@ -174,6 +194,9 @@ class AudioChannelsValidatorRule(Rule): priority = 128 consequence = RemoveMatch + def enabled(self, context): + return not is_disabled(context, 'audio_channels') + def when(self, matches, context): ret = [] diff --git a/ext/guessit/rules/properties/bit_rate.py b/ext/guessit/rules/properties/bit_rate.py new file mode 100644 index 0000000000..391f1d2fc8 --- /dev/null +++ b/ext/guessit/rules/properties/bit_rate.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +video_bit_rate and audio_bit_rate properties +""" +import re + +from rebulk import Rebulk +from rebulk.rules import Rule, RemoveMatch, RenameMatch + +from ..common import dash, seps +from ..common.pattern import is_disabled +from ..common.quantity import BitRate +from ..common.validators import seps_surround + + +def bit_rate(config): # pylint:disable=unused-argument + """ + Builder for rebulk object. + + :param config: rule configuration + :type config: dict + :return: Created Rebulk object + :rtype: Rebulk + """ + rebulk = Rebulk(disabled=lambda context: (is_disabled(context, 'audio_bit_rate') + and is_disabled(context, 'video_bit_rate'))) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) + rebulk.defaults(name='audio_bit_rate', validator=seps_surround) + rebulk.regex(r'\d+-?[kmg]b(ps|its?)', r'\d+\.\d+-?[kmg]b(ps|its?)', + conflict_solver=( + lambda match, other: match + if other.name == 'audio_channels' and 'weak-audio_channels' not in other.tags + else other + ), + formatter=BitRate.fromstring, tags=['release-group-prefix']) + + rebulk.rules(BitRateTypeRule) + + return rebulk + + +class BitRateTypeRule(Rule): + """ + Convert audio bit rate guess into video bit rate. + """ + consequence = [RenameMatch('video_bit_rate'), RemoveMatch] + + def when(self, matches, context): + to_rename = [] + to_remove = [] + + if is_disabled(context, 'audio_bit_rate'): + to_remove.extend(matches.named('audio_bit_rate')) + else: + video_bit_rate_disabled = is_disabled(context, 'video_bit_rate') + for match in matches.named('audio_bit_rate'): + previous = matches.previous(match, index=0, + predicate=lambda m: m.name in ('source', 'screen_size', 'video_codec')) + if previous and not matches.holes(previous.end, match.start, predicate=lambda m: m.value.strip(seps)): + after = matches.next(match, index=0, predicate=lambda m: m.name == 'audio_codec') + if after and not matches.holes(match.end, after.start, predicate=lambda m: m.value.strip(seps)): + bitrate = match.value + if bitrate.units == 'Kbps' or (bitrate.units == 'Mbps' and bitrate.magnitude < 10): + continue + + if video_bit_rate_disabled: + to_remove.append(match) + else: + to_rename.append(match) + + return to_rename, to_remove diff --git a/ext/guessit/rules/properties/bonus.py b/ext/guessit/rules/properties/bonus.py index e37613e9df..c4554cd065 100644 --- a/ext/guessit/rules/properties/bonus.py +++ b/ext/guessit/rules/properties/bonus.py @@ -9,21 +9,26 @@ from .title import TitleFromPosition from ..common.formatters import cleanup +from ..common.pattern import is_disabled from ..common.validators import seps_surround -def bonus(): +def bonus(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'bonus')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.regex(r'x(\d+)', name='bonus', private_parent=True, children=True, formatter=int, validator={'__parent__': lambda match: seps_surround}, conflict_solver=lambda match, conflicting: match - if conflicting.name in ['video_codec', 'episode'] and 'bonus-conflict' not in conflicting.tags + if conflicting.name in ('video_codec', 'episode') and 'weak-episode' not in conflicting.tags else '__default__') rebulk.rules(BonusTitleRule) @@ -40,7 +45,7 @@ class BonusTitleRule(Rule): properties = {'bonus_title': [None]} - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements bonus_number = matches.named('bonus', lambda match: not match.private, index=0) if bonus_number: filepath = matches.markers.at_match(bonus_number, lambda marker: marker.name == 'path', 0) diff --git a/ext/guessit/rules/properties/cds.py b/ext/guessit/rules/properties/cds.py index db1407d65b..873df6fef2 100644 --- a/ext/guessit/rules/properties/cds.py +++ b/ext/guessit/rules/properties/cds.py @@ -6,16 +6,22 @@ from rebulk.remodule import re from rebulk import Rebulk + from ..common import dash +from ..common.pattern import is_disabled -def cds(): +def cds(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'cd')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) rebulk.regex(r'cd-?(?P\d+)(?:-?of-?(?P\d+))?', validator={'cd': lambda match: 0 < match.value < 100, diff --git a/ext/guessit/rules/properties/container.py b/ext/guessit/rules/properties/container.py index 52889e1436..77599509a9 100644 --- a/ext/guessit/rules/properties/container.py +++ b/ext/guessit/rules/properties/container.py @@ -8,33 +8,35 @@ from rebulk import Rebulk from ..common import seps +from ..common.pattern import is_disabled from ..common.validators import seps_surround from ...reutils import build_or_pattern -def container(): +def container(config): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE).string_defaults(ignore_case=True) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'container')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE).string_defaults(ignore_case=True) rebulk.defaults(name='container', formatter=lambda value: value.strip(seps), tags=['extension'], conflict_solver=lambda match, other: other - if other.name in ['format', 'video_codec'] or + if other.name in ('source', 'video_codec') or other.name == 'container' and 'extension' not in other.tags else '__default__') - subtitles = ['srt', 'idx', 'sub', 'ssa', 'ass'] - info = ['nfo'] - videos = ['3g2', '3gp', '3gp2', 'asf', 'avi', 'divx', 'flv', 'm4v', 'mk2', - 'mka', 'mkv', 'mov', 'mp4', 'mp4a', 'mpeg', 'mpg', 'ogg', 'ogm', - 'ogv', 'qt', 'ra', 'ram', 'rm', 'ts', 'wav', 'webm', 'wma', 'wmv', - 'iso', 'vob'] - torrent = ['torrent'] - nzb = ['nzb'] + subtitles = config['subtitles'] + info = config['info'] + videos = config['videos'] + torrent = config['torrent'] + nzb = config['nzb'] rebulk.regex(r'\.'+build_or_pattern(subtitles)+'$', exts=subtitles, tags=['extension', 'subtitle']) rebulk.regex(r'\.'+build_or_pattern(info)+'$', exts=info, tags=['extension', 'info']) @@ -46,11 +48,11 @@ def container(): validator=seps_surround, formatter=lambda s: s.lower(), conflict_solver=lambda match, other: match - if other.name in ['format', - 'video_codec'] or other.name == 'container' and 'extension' in other.tags + if other.name in ('source', + 'video_codec') or other.name == 'container' and 'extension' in other.tags else '__default__') - rebulk.string(*[sub for sub in subtitles if sub not in ['sub']], tags=['subtitle']) + rebulk.string(*[sub for sub in subtitles if sub not in ('sub', 'ass')], tags=['subtitle']) rebulk.string(*videos, tags=['video']) rebulk.string(*torrent, tags=['torrent']) rebulk.string(*nzb, tags=['nzb']) diff --git a/ext/guessit/rules/properties/country.py b/ext/guessit/rules/properties/country.py index 5b390df062..138c80a263 100644 --- a/ext/guessit/rules/properties/country.py +++ b/ext/guessit/rules/properties/country.py @@ -7,41 +7,50 @@ import babelfish from rebulk import Rebulk -from ..common.words import COMMON_WORDS, iter_words +from ..common.pattern import is_disabled +from ..common.words import iter_words -def country(): +def country(config, common_words): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict + :param common_words: common words + :type common_words: set :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().defaults(name='country') + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'country')) + rebulk = rebulk.defaults(name='country') + + def find_countries(string, context=None): + """ + Find countries in given string. + """ + allowed_countries = context.get('allowed_countries') if context else None + return CountryFinder(allowed_countries, common_words).find(string) rebulk.functional(find_countries, #  Prefer language and any other property over country if not US or GB. conflict_solver=lambda match, other: match - if other.name != 'language' or match.value not in [babelfish.Country('US'), - babelfish.Country('GB')] + if other.name != 'language' or match.value not in (babelfish.Country('US'), + babelfish.Country('GB')) else other, - properties={'country': [None]}) - - return rebulk + properties={'country': [None]}, + disabled=lambda context: not context.get('allowed_countries')) + babelfish.country_converters['guessit'] = GuessitCountryConverter(config['synonyms']) -COUNTRIES_SYN = {'ES': ['españa'], - 'GB': ['UK'], - 'BR': ['brazilian', 'bra'], - 'CA': ['québec', 'quebec', 'qc'], - # FIXME: this one is a bit of a stretch, not sure how to do it properly, though... - 'MX': ['Latinoamérica', 'latin america']} + return rebulk class GuessitCountryConverter(babelfish.CountryReverseConverter): # pylint: disable=missing-docstring - def __init__(self): + def __init__(self, synonyms): self.guessit_exceptions = {} - for alpha2, synlist in COUNTRIES_SYN.items(): + for alpha2, synlist in synonyms.items(): for syn in synlist: self.guessit_exceptions[syn.lower()] = alpha2 @@ -78,32 +87,28 @@ def reverse(self, name): # pylint:disable=arguments-differ raise babelfish.CountryReverseError(name) -babelfish.country_converters['guessit'] = GuessitCountryConverter() - +class CountryFinder(object): + """Helper class to search and return country matches.""" -def is_allowed_country(country_object, context=None): - """ - Check if country is allowed. - """ - if context and context.get('allowed_countries'): - allowed_countries = context.get('allowed_countries') - return country_object.name.lower() in allowed_countries or country_object.alpha2.lower() in allowed_countries - return True + def __init__(self, allowed_countries, common_words): + self.allowed_countries = set([l.lower() for l in allowed_countries or []]) + self.common_words = common_words + def find(self, string): + """Return all matches for country.""" + for word_match in iter_words(string.strip().lower()): + word = word_match.value + if word.lower() in self.common_words: + continue -def find_countries(string, context=None): - """ - Find countries in given string. - """ - ret = [] - for word_match in iter_words(string.strip().lower()): - word = word_match.value - if word.lower() in COMMON_WORDS: - continue - try: - country_object = babelfish.Country.fromguessit(word) - if is_allowed_country(country_object, context): - ret.append((word_match.span[0], word_match.span[1], {'value': country_object})) - except babelfish.Error: - continue - return ret + try: + country_object = babelfish.Country.fromguessit(word) + if (country_object.name.lower() in self.allowed_countries or + country_object.alpha2.lower() in self.allowed_countries): + yield self._to_rebulk_match(word_match, country_object) + except babelfish.Error: + continue + + @classmethod + def _to_rebulk_match(cls, word, value): + return word.span[0], word.span[1], {'value': value} diff --git a/ext/guessit/rules/properties/crc.py b/ext/guessit/rules/properties/crc.py index f655bc1317..c65ab7b37f 100644 --- a/ext/guessit/rules/properties/crc.py +++ b/ext/guessit/rules/properties/crc.py @@ -6,16 +6,21 @@ from rebulk.remodule import re from rebulk import Rebulk +from ..common.pattern import is_disabled from ..common.validators import seps_surround -def crc(): +def crc(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'crc32')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(validator=seps_surround) rebulk.regex('(?:[a-fA-F]|[0-9]){8}', name='crc32', diff --git a/ext/guessit/rules/properties/date.py b/ext/guessit/rules/properties/date.py index 0b6083bd7f..4db121c279 100644 --- a/ext/guessit/rules/properties/date.py +++ b/ext/guessit/rules/properties/date.py @@ -6,21 +6,26 @@ from rebulk import Rebulk, RemoveMatch, Rule from ..common.date import search_date, valid_year +from ..common.pattern import is_disabled from ..common.validators import seps_surround -def date(): +def date(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ rebulk = Rebulk().defaults(validator=seps_surround) rebulk.regex(r"\d{4}", name="year", formatter=int, + disabled=lambda context: is_disabled(context, 'year'), validator=lambda match: seps_surround(match) and valid_year(match.value)) - def date_functional(string, context): + def date_functional(string, context): # pylint:disable=inconsistent-return-statements """ Search for date in the string and retrieves match @@ -33,8 +38,9 @@ def date_functional(string, context): return ret[0], ret[1], {'value': ret[2]} rebulk.functional(date_functional, name="date", properties={'date': [None]}, + disabled=lambda context: is_disabled(context, 'date'), conflict_solver=lambda match, other: other - if other.name in ['episode', 'season'] + if other.name in ('episode', 'season', 'crc32') else '__default__') rebulk.rules(KeepMarkedYearInFilepart) @@ -49,6 +55,9 @@ class KeepMarkedYearInFilepart(Rule): priority = 64 consequence = RemoveMatch + def enabled(self, context): + return not is_disabled(context, 'year') + def when(self, matches, context): ret = [] if len(matches.named('year')) > 1: diff --git a/ext/guessit/rules/properties/edition.py b/ext/guessit/rules/properties/edition.py index a6d05a7e41..822aa4ee39 100644 --- a/ext/guessit/rules/properties/edition.py +++ b/ext/guessit/rules/properties/edition.py @@ -7,28 +7,34 @@ from rebulk import Rebulk from ..common import dash +from ..common.pattern import is_disabled from ..common.validators import seps_surround -def edition(): +def edition(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).string_defaults(ignore_case=True) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'edition')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).string_defaults(ignore_case=True) rebulk.defaults(name='edition', validator=seps_surround) - rebulk.regex('collector', 'collector-edition', 'edition-collector', value='Collector Edition') - rebulk.regex('special-edition', 'edition-special', value='Special Edition', + rebulk.regex('collector', "collector'?s?-edition", 'edition-collector', value='Collector') + rebulk.regex('special-edition', 'edition-special', value='Special', conflict_solver=lambda match, other: other if other.name == 'episode_details' and other.value == 'Special' else '__default__') - rebulk.string('se', value='Special Edition', tags='has-neighbor') - rebulk.regex('criterion-edition', 'edition-criterion', value='Criterion Edition') - rebulk.regex('deluxe', 'deluxe-edition', 'edition-deluxe', value='Deluxe Edition') - rebulk.regex('limited', 'limited-edition', value='Limited Edition', tags=['has-neighbor', 'release-group-prefix']) - rebulk.regex(r'theatrical-cut', r'theatrical-edition', r'theatrical', value='Theatrical Edition') + rebulk.string('se', value='Special', tags='has-neighbor') + rebulk.string('ddc', value="Director's Definitive Cut") + rebulk.regex('criterion-edition', 'edition-criterion', 'CC', value='Criterion') + rebulk.regex('deluxe', 'deluxe-edition', 'edition-deluxe', value='Deluxe') + rebulk.regex('limited', 'limited-edition', value='Limited', tags=['has-neighbor', 'release-group-prefix']) + rebulk.regex(r'theatrical-cut', r'theatrical-edition', r'theatrical', value='Theatrical') rebulk.regex(r"director'?s?-cut", r"director'?s?-cut-edition", r"edition-director'?s?-cut", 'DC', value="Director's Cut") rebulk.regex('extended', 'extended-?cut', 'extended-?version', @@ -37,5 +43,10 @@ def edition(): for value in ('Remastered', 'Uncensored', 'Uncut', 'Unrated'): rebulk.string(value, value=value, tags=['has-neighbor', 'release-group-prefix']) rebulk.string('Festival', value='Festival', tags=['has-neighbor-before', 'has-neighbor-after']) + rebulk.regex('imax', 'imax-edition', value='IMAX') + rebulk.regex('fan-edit(?:ion)?', 'fan-collection', value='Fan') + rebulk.regex('ultimate-edition', value='Ultimate') + rebulk.regex("ultimate-collector'?s?-edition", value=['Ultimate', 'Collector']) + rebulk.regex('ultimate-fan-edit(?:ion)?', 'ultimate-fan-collection', value=['Ultimate', 'Fan']) return rebulk diff --git a/ext/guessit/rules/properties/episode_title.py b/ext/guessit/rules/properties/episode_title.py index 6d5016f13c..bcf605c0cc 100644 --- a/ext/guessit/rules/properties/episode_title.py +++ b/ext/guessit/rules/properties/episode_title.py @@ -9,26 +9,31 @@ from ..common import seps, title_seps from ..common.formatters import cleanup +from ..common.pattern import is_disabled from ..properties.title import TitleFromPosition, TitleBaseRule from ..properties.type import TypeProcessor -def episode_title(): +def episode_title(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ previous_names = ('episode', 'episode_details', 'episode_count', 'season', 'season_count', 'date', 'title', 'year') - rebulk = Rebulk().rules(RemoveConflictsWithEpisodeTitle(previous_names), - EpisodeTitleFromPosition(previous_names), - AlternativeTitleReplace(previous_names), - TitleToEpisodeTitle, - Filepart3EpisodeTitle, - Filepart2EpisodeTitle, - RenameEpisodeTitleWhenMovieType) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'episode_title')) + rebulk = rebulk.rules(RemoveConflictsWithEpisodeTitle(previous_names), + EpisodeTitleFromPosition(previous_names), + AlternativeTitleReplace(previous_names), + TitleToEpisodeTitle, + Filepart3EpisodeTitle, + Filepart2EpisodeTitle, + RenameEpisodeTitleWhenMovieType) return rebulk @@ -43,7 +48,7 @@ class RemoveConflictsWithEpisodeTitle(Rule): def __init__(self, previous_names): super(RemoveConflictsWithEpisodeTitle, self).__init__() self.previous_names = previous_names - self.next_names = ('streaming_service', 'screen_size', 'format', + self.next_names = ('streaming_service', 'screen_size', 'source', 'video_codec', 'audio_codec', 'other', 'container') self.affected_if_holes_after = ('part', ) self.affected_names = ('part', 'year') @@ -53,13 +58,11 @@ def when(self, matches, context): for filepart in matches.markers.named('path'): for match in matches.range(filepart.start, filepart.end, predicate=lambda m: m.name in self.affected_names): - before = matches.previous(match, index=0, - predicate=lambda m, fp=filepart: not m.private and m.start >= fp.start) + before = matches.range(filepart.start, match.start, predicate=lambda m: not m.private, index=-1) if not before or before.name not in self.previous_names: continue - after = matches.next(match, index=0, - predicate=lambda m, fp=filepart: not m.private and m.end <= fp.end) + after = matches.range(match.end, filepart.end, predicate=lambda m: not m.private, index=0) if not after or after.name not in self.next_names: continue @@ -100,16 +103,15 @@ def when(self, matches, context): for title in titles: title_groups[title.value].append(title) + episode_titles = [] if len(title_groups) < 2: - return + return episode_titles - episode_titles = [] for title in titles: if matches.previous(title, lambda match: match.name == 'episode'): episode_titles.append(title) - if episode_titles: - return episode_titles + return episode_titles def then(self, matches, when_response, context): for title in when_response: @@ -150,7 +152,7 @@ def should_remove(self, match, matches, filepart, hole, context): return False return super(EpisodeTitleFromPosition, self).should_remove(match, matches, filepart, hole, context) - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements if matches.named('episode_title'): return return super(EpisodeTitleFromPosition, self).when(matches, context) @@ -167,7 +169,7 @@ def __init__(self, previous_names): super(AlternativeTitleReplace, self).__init__() self.previous_names = previous_names - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements if matches.named('episode_title'): return @@ -202,7 +204,7 @@ class RenameEpisodeTitleWhenMovieType(Rule): dependency = TypeProcessor consequence = RenameMatch - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements if matches.named('episode_title', lambda m: 'alternative-replaced' not in m.tags) \ and not matches.named('type', lambda m: m.value == 'episode'): return matches.named('episode_title') @@ -226,7 +228,7 @@ class Filepart3EpisodeTitle(Rule): """ consequence = AppendMatch('title') - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements fileparts = matches.markers.named('path') if len(fileparts) < 3: return @@ -267,7 +269,7 @@ class Filepart2EpisodeTitle(Rule): """ consequence = AppendMatch('title') - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements fileparts = matches.markers.named('path') if len(fileparts) < 2: return diff --git a/ext/guessit/rules/properties/episodes.py b/ext/guessit/rules/properties/episodes.py index f74ae48e90..0f2e173cf5 100644 --- a/ext/guessit/rules/properties/episodes.py +++ b/ext/guessit/rules/properties/episodes.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ -episode, season, episode_count, season_count and episode_details properties +episode, season, disc, episode_count, season_count and episode_details properties """ import copy from collections import defaultdict @@ -12,24 +12,34 @@ from rebulk.utils import is_iterable from .title import TitleFromPosition -from ..common import dash, alt_dash, seps +from ..common import dash, alt_dash, seps, seps_no_fs from ..common.formatters import strip from ..common.numeral import numeral, parse_numeral +from ..common.pattern import is_disabled from ..common.validators import compose, seps_surround, seps_before, int_coercable from ...reutils import build_or_pattern -def episodes(): +def episodes(config): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ # pylint: disable=too-many-branches,too-many-statements,too-many-locals - rebulk = Rebulk() - rebulk.regex_defaults(flags=re.IGNORECASE).string_defaults(ignore_case=True) + def is_season_episode_disabled(context): + """Whether season and episode rules should be enabled.""" + return is_disabled(context, 'episode') or is_disabled(context, 'season') + + rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE).string_defaults(ignore_case=True) rebulk.defaults(private_names=['episodeSeparator', 'seasonSeparator', 'episodeMarker', 'seasonMarker']) + episode_max_range = config['episode_max_range'] + season_max_range = config['season_max_range'] + def episodes_season_chain_breaker(matches): """ Break chains if there's more than 100 offset between two neighbor values. @@ -39,11 +49,11 @@ def episodes_season_chain_breaker(matches): :rtype: """ eps = matches.named('episode') - if len(eps) > 1 and abs(eps[-1].value - eps[-2].value) > 100: + if len(eps) > 1 and abs(eps[-1].value - eps[-2].value) > episode_max_range: return True seasons = matches.named('season') - if len(seasons) > 1 and abs(seasons[-1].value - seasons[-2].value) > 100: + if len(seasons) > 1 and abs(seasons[-1].value - seasons[-2].value) > season_max_range: return True return False @@ -57,40 +67,41 @@ def season_episode_conflict_solver(match, other): :param other: :return: """ - if match.name == 'episode' and other.name in \ - ['screen_size', 'video_codec', 'audio_codec', 'audio_channels', 'container', 'date', 'year'] \ - and 'weak-audio_channels' not in other.tags: - return match - if match.name == 'season' and other.name in \ - ['screen_size', 'video_codec', 'audio_codec', 'audio_channels', 'container', 'date'] \ - and 'weak-audio_channels' not in other.tags: - return match - if match.name in ['season', 'episode'] and other.name in ['season', 'episode'] \ - and match.initiator != other.initiator: - if 'weak-episode' in match.tags or 'x' in match.initiator.raw.lower(): + if match.name != other.name: + if match.name == 'episode' and other.name == 'year': return match - if 'weak-episode' in other.tags or 'x' in other.initiator.raw.lower(): - return other + if match.name in ('season', 'episode'): + if other.name in ('video_codec', 'audio_codec', 'container', 'date'): + return match + if (other.name == 'audio_channels' and 'weak-audio_channels' not in other.tags + and not match.initiator.children.named(match.name + 'Marker')) or ( + other.name == 'screen_size' and not int_coercable(other.raw)): + + return match + if other.name in ('season', 'episode') and match.initiator != other.initiator: + if (match.initiator.name in ('weak_episode', 'weak_duplicate') + and other.initiator.name in ('weak_episode', 'weak_duplicate')): + return '__default__' + for current in (match, other): + if 'weak-episode' in current.tags or 'x' in current.initiator.raw.lower(): + return current return '__default__' - season_episode_seps = [] - season_episode_seps.extend(seps) - season_episode_seps.extend(['x', 'X', 'e', 'E']) - - season_words = ['season', 'saison', 'seizoen', 'serie', 'seasons', 'saisons', 'series', - 'tem', 'temp', 'temporada', 'temporadas', 'stagione'] - episode_words = ['episode', 'episodes', 'eps', 'ep', 'episodio', - 'episodios', 'capitulo', 'capitulos'] - of_words = ['of', 'sur'] - all_words = ['All'] - season_markers = ["S"] - season_ep_markers = ["x"] - episode_markers = ["xE", "Ex", "EP", "E", "x"] - range_separators = ['-', '~', 'to', 'a'] - weak_discrete_separators = list(sep for sep in seps if sep not in range_separators) - strong_discrete_separators = ['+', '&', 'and', 'et'] + season_words = config['season_words'] + episode_words = config['episode_words'] + of_words = config['of_words'] + all_words = config['all_words'] + season_markers = config['season_markers'] + season_ep_markers = config['season_ep_markers'] + disc_markers = config['disc_markers'] + episode_markers = config['episode_markers'] + range_separators = config['range_separators'] + weak_discrete_separators = list(sep for sep in seps_no_fs if sep not in range_separators) + strong_discrete_separators = config['discrete_separators'] discrete_separators = strong_discrete_separators + weak_discrete_separators + max_range_gap = config['max_range_gap'] + def ordering_validator(match): """ Validator for season list. They should be in natural order to be validated. @@ -125,7 +136,7 @@ def is_consecutive(property_name): separator = match.children.previous(current_match, lambda m: m.name == property_name + 'Separator', 0) if separator.raw not in range_separators and separator.raw in weak_discrete_separators: - if not current_match.value - previous_match.value == 1: + if not 0 < current_match.value - previous_match.value <= max_range_gap + 1: valid = False if separator.raw in strong_discrete_separators: valid = True @@ -143,12 +154,13 @@ def is_consecutive(property_name): private_parent=True, validate_all=True, validator={'__parent__': ordering_validator}, - conflict_solver=season_episode_conflict_solver) \ + conflict_solver=season_episode_conflict_solver, + disabled=is_season_episode_disabled) \ .regex(build_or_pattern(season_markers, name='seasonMarker') + r'(?P\d+)@?' + - build_or_pattern(episode_markers, name='episodeMarker') + r'@?(?P\d+)', + build_or_pattern(episode_markers + disc_markers, name='episodeMarker') + r'@?(?P\d+)', validate_all=True, validator={'__parent__': seps_before}).repeater('+') \ - .regex(build_or_pattern(episode_markers + discrete_separators + range_separators, + .regex(build_or_pattern(episode_markers + disc_markers + discrete_separators + range_separators, name='episodeSeparator', escape=True) + r'(?P\d+)').repeater('*') \ @@ -178,9 +190,11 @@ def is_consecutive(property_name): r'(?P\d+)').repeater('*') # episode_details property - for episode_detail in ('Special', 'Bonus', 'Omake', 'Ova', 'Oav', 'Pilot', 'Unaired'): - rebulk.string(episode_detail, value=episode_detail, name='episode_details') - rebulk.regex(r'Extras?', name='episode_details', value='Extras') + for episode_detail in ('Special', 'Bonus', 'Pilot', 'Unaired', 'Final'): + rebulk.string(episode_detail, value=episode_detail, name='episode_details', + disabled=lambda context: is_disabled(context, 'episode_details')) + rebulk.regex(r'Extras?', 'Omake', name='episode_details', value='Extras', + disabled=lambda context: is_disabled(context, 'episode_details')) def validate_roman(match): """ @@ -202,7 +216,8 @@ def validate_roman(match): formatter={'season': parse_numeral, 'count': parse_numeral}, validator={'__parent__': compose(seps_surround, ordering_validator), 'season': validate_roman, - 'count': validate_roman}) \ + 'count': validate_roman}, + disabled=lambda context: context.get('type') == 'movie' or is_disabled(context, 'season')) \ .defaults(validator=None) \ .regex(build_or_pattern(season_words, name='seasonMarker') + '@?(?P' + numeral + ')') \ .regex(r'' + build_or_pattern(of_words) + '@?(?P' + numeral + ')').repeater('?') \ @@ -214,7 +229,7 @@ def validate_roman(match): r'(?:v(?P\d+))?' + r'(?:-?' + build_or_pattern(of_words) + r'-?(?P\d+))?', # Episode 4 abbreviations=[dash], formatter={'episode': int, 'version': int, 'count': int}, - disabled=lambda context: context.get('type') == 'episode') + disabled=lambda context: context.get('type') == 'episode' or is_disabled(context, 'episode')) rebulk.regex(build_or_pattern(episode_words, name='episodeMarker') + r'-?(?P' + numeral + ')' + r'(?:v(?P\d+))?' + @@ -222,42 +237,44 @@ def validate_roman(match): abbreviations=[dash], validator={'episode': validate_roman}, formatter={'episode': parse_numeral, 'version': int, 'count': int}, - disabled=lambda context: context.get('type') != 'episode') + disabled=lambda context: context.get('type') != 'episode' or is_disabled(context, 'episode')) rebulk.regex(r'S?(?P\d+)-?(?:xE|Ex|E|x)-?(?P' + build_or_pattern(all_words) + ')', tags=['SxxExx'], abbreviations=[dash], validator=None, - formatter={'season': int, 'other': lambda match: 'Complete'}) + formatter={'season': int, 'other': lambda match: 'Complete'}, + disabled=lambda context: is_disabled(context, 'season')) # 12, 13 - rebulk.chain(tags=['bonus-conflict', 'weak-movie', 'weak-episode'], formatter={'episode': int, 'version': int}, - disabled=lambda context: context.get('type') == 'movie') \ + rebulk.chain(tags=['weak-episode'], formatter={'episode': int, 'version': int}, + disabled=lambda context: context.get('type') == 'movie' or is_disabled(context, 'episode')) \ .defaults(validator=None) \ .regex(r'(?P\d{2})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?P[x-])(?P\d{2})').repeater('*') # 012, 013 - rebulk.chain(tags=['bonus-conflict', 'weak-movie', 'weak-episode'], formatter={'episode': int, 'version': int}, - disabled=lambda context: context.get('type') == 'movie') \ + rebulk.chain(tags=['weak-episode'], formatter={'episode': int, 'version': int}, + disabled=lambda context: context.get('type') == 'movie' or is_disabled(context, 'episode')) \ .defaults(validator=None) \ .regex(r'0(?P\d{1,2})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?P[x-])0(?P\d{1,2})').repeater('*') # 112, 113 - rebulk.chain(tags=['bonus-conflict', 'weak-movie', 'weak-episode'], formatter={'episode': int, 'version': int}, - disabled=lambda context: (not context.get('episode_prefer_number', False) or - context.get('type') == 'movie')) \ + rebulk.chain(tags=['weak-episode'], + formatter={'episode': int, 'version': int}, + name='weak_episode', + disabled=lambda context: context.get('type') == 'movie' or is_disabled(context, 'episode')) \ .defaults(validator=None) \ .regex(r'(?P\d{3,4})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?P[x-])(?P\d{3,4})').repeater('*') # 1, 2, 3 - rebulk.chain(tags=['bonus-conflict', 'weak-movie', 'weak-episode'], formatter={'episode': int, 'version': int}, - disabled=lambda context: context.get('type') != 'episode') \ + rebulk.chain(tags=['weak-episode'], formatter={'episode': int, 'version': int}, + disabled=lambda context: context.get('type') != 'episode' or is_disabled(context, 'episode')) \ .defaults(validator=None) \ .regex(r'(?P\d)') \ .regex(r'v(?P\d+)').repeater('?') \ @@ -265,14 +282,16 @@ def validate_roman(match): # e112, e113 # TODO: Enhance rebulk for validator to be used globally (season_episode_validator) - rebulk.chain(formatter={'episode': int, 'version': int}) \ + rebulk.chain(formatter={'episode': int, 'version': int}, + disabled=lambda context: is_disabled(context, 'episode')) \ .defaults(validator=None) \ .regex(r'(?Pe)(?P\d{1,4})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?Pe|x|-)(?P\d{1,4})').repeater('*') # ep 112, ep113, ep112, ep113 - rebulk.chain(abbreviations=[dash], formatter={'episode': int, 'version': int}) \ + rebulk.chain(abbreviations=[dash], formatter={'episode': int, 'version': int}, + disabled=lambda context: is_disabled(context, 'episode')) \ .defaults(validator=None) \ .regex(r'ep-?(?P\d{1,4})') \ .regex(r'v(?P\d+)').repeater('?') \ @@ -281,23 +300,26 @@ def validate_roman(match): # cap 112, cap 112_114 rebulk.chain(abbreviations=[dash], tags=['see-pattern'], - formatter={'season': int, 'episode': int}) \ + formatter={'season': int, 'episode': int}, + disabled=is_season_episode_disabled) \ .defaults(validator=None) \ .regex(r'(?Pcap)-?(?P\d{1,2})(?P\d{2})') \ .regex(r'(?P-)(?P\d{1,2})(?P\d{2})').repeater('?') # 102, 0102 - rebulk.chain(tags=['bonus-conflict', 'weak-movie', 'weak-episode', 'weak-duplicate'], + rebulk.chain(tags=['weak-episode', 'weak-duplicate'], formatter={'season': int, 'episode': int, 'version': int}, - conflict_solver=lambda match, other: match if other.name == 'year' else '__default__', + name='weak_duplicate', + conflict_solver=season_episode_conflict_solver, disabled=lambda context: (context.get('episode_prefer_number', False) or - context.get('type') == 'movie')) \ + context.get('type') == 'movie') or is_season_episode_disabled(context)) \ .defaults(validator=None) \ .regex(r'(?P\d{1,2})(?P\d{2})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?Px|-)(?P\d{2})').repeater('*') - rebulk.regex(r'v(?P\d+)', children=True, private_parent=True, formatter=int) + rebulk.regex(r'v(?P\d+)', children=True, private_parent=True, formatter=int, + disabled=lambda context: is_disabled(context, 'version')) rebulk.defaults(private_names=['episodeSeparator', 'seasonSeparator']) @@ -305,19 +327,100 @@ def validate_roman(match): # detached of X count (season/episode) rebulk.regex(r'(?P\d+)-?' + build_or_pattern(of_words) + r'-?(?P\d+)-?' + build_or_pattern(episode_words) + '?', - abbreviations=[dash], children=True, private_parent=True, formatter=int) + abbreviations=[dash], children=True, private_parent=True, formatter=int, + disabled=lambda context: is_disabled(context, 'episode')) - rebulk.regex(r'Minisodes?', name='episode_format', value="Minisode") + rebulk.regex(r'Minisodes?', name='episode_format', value="Minisode", + disabled=lambda context: is_disabled(context, 'episode_format')) - rebulk.rules(RemoveInvalidSeason, RemoveInvalidEpisode, - SeePatternRange(range_separators + ['_']), EpisodeNumberSeparatorRange(range_separators), + rebulk.rules(WeakConflictSolver, RemoveInvalidSeason, RemoveInvalidEpisode, + SeePatternRange(range_separators + ['_']), + EpisodeNumberSeparatorRange(range_separators), SeasonSeparatorRange(range_separators), RemoveWeakIfMovie, RemoveWeakIfSxxExx, RemoveWeakDuplicate, EpisodeDetailValidator, RemoveDetachedEpisodeNumber, VersionValidator, - CountValidator, EpisodeSingleDigitValidator) + RemoveWeak, RenameToAbsoluteEpisode, CountValidator, EpisodeSingleDigitValidator, RenameToDiscMatch) return rebulk +class WeakConflictSolver(Rule): + """ + Rule to decide whether weak-episode or weak-duplicate matches should be kept. + + If an anime is detected: + - weak-duplicate matches should be removed + - weak-episode matches should be tagged as anime + Otherwise: + - weak-episode matches are removed unless they're part of an episode range match. + """ + priority = 128 + consequence = [RemoveMatch, AppendMatch] + + def enabled(self, context): + return context.get('type') != 'movie' + + @classmethod + def is_anime(cls, matches): + """Return True if it seems to be an anime. + + Anime characteristics: + - version, crc32 matches + - screen_size inside brackets + - release_group at start and inside brackets + """ + if matches.named('version') or matches.named('crc32'): + return True + + for group in matches.markers.named('group'): + if matches.range(group.start, group.end, predicate=lambda m: m.name == 'screen_size'): + return True + if matches.markers.starting(group.start, predicate=lambda m: m.name == 'path'): + hole = matches.holes(group.start, group.end, index=0) + if hole and hole.raw == group.raw: + return True + + return False + + def when(self, matches, context): + to_remove = [] + to_append = [] + anime_detected = self.is_anime(matches) + for filepart in matches.markers.named('path'): + weak_matches = matches.range(filepart.start, filepart.end, predicate=( + lambda m: m.initiator.name == 'weak_episode')) + weak_dup_matches = matches.range(filepart.start, filepart.end, predicate=( + lambda m: m.initiator.name == 'weak_duplicate')) + if anime_detected: + if weak_matches: + to_remove.extend(weak_dup_matches) + for match in matches.range(filepart.start, filepart.end, predicate=( + lambda m: m.name == 'episode' and m.initiator.name != 'weak_duplicate')): + episode = copy.copy(match) + episode.tags = episode.tags + ['anime'] + to_append.append(episode) + to_remove.append(match) + elif weak_dup_matches: + episodes_in_range = matches.range(filepart.start, filepart.end, predicate=( + lambda m: + m.name == 'episode' and m.initiator.name == 'weak_episode' + and m.initiator.children.named('episodeSeparator') + )) + if not episodes_in_range and not matches.range(filepart.start, filepart.end, + predicate=lambda m: 'SxxExx' in m.tags): + to_remove.extend(weak_matches) + else: + for match in episodes_in_range: + episode = copy.copy(match) + episode.tags = [] + to_append.append(episode) + to_remove.append(match) + + if to_append: + to_remove.extend(weak_dup_matches) + + return to_remove, to_append + + class CountValidator(Rule): """ Validate count property and rename it @@ -396,14 +499,16 @@ def when(self, matches, context): to_append = [] for separator in matches.named(self.property_name + 'Separator'): - previous_match = matches.previous(separator, lambda match: match.name == self.property_name, 0) - next_match = matches.next(separator, lambda match: match.name == self.property_name, 0) + previous_match = matches.previous(separator, lambda m: m.name == self.property_name, 0) + next_match = matches.next(separator, lambda m: m.name == self.property_name, 0) + initiator = separator.initiator if previous_match and next_match and separator.value in self.range_separators: to_remove.append(next_match) for episode_number in range(previous_match.value + 1, next_match.value): match = copy.copy(next_match) match.value = episode_number + initiator.children.append(match) to_append.append(match) to_append.append(next_match) to_remove.append(separator) @@ -415,9 +520,11 @@ def when(self, matches, context): if separator not in self.range_separators: separator = strip(separator) if separator in self.range_separators: + initiator = previous_match.initiator for episode_number in range(previous_match.value + 1, next_match.value): match = copy.copy(next_match) match.value = episode_number + initiator.children.append(match) to_append.append(match) to_append.append(Match(previous_match.end, next_match.start - 1, name=self.property_name + 'Separator', @@ -431,12 +538,46 @@ def when(self, matches, context): return to_remove, to_append +class RenameToAbsoluteEpisode(Rule): + """ + Rename episode to absolute_episodes. + + Absolute episodes are only used if two groups of episodes are detected: + S02E04-06 25-27 + 25-27 S02E04-06 + 2x04-06 25-27 + 28. Anime Name S02E05 + The matches in the group with higher episode values are renamed to absolute_episode. + """ + + consequence = RenameMatch('absolute_episode') + + def when(self, matches, context): # pylint:disable=inconsistent-return-statements + initiators = set([match.initiator for match in matches.named('episode') + if len(match.initiator.children.named('episode')) > 1]) + if len(initiators) != 2: + ret = [] + for filepart in matches.markers.named('path'): + if matches.range(filepart.start + 1, filepart.end, predicate=lambda m: m.name == 'episode'): + ret.extend( + matches.starting(filepart.start, predicate=lambda m: m.initiator.name == 'weak_episode')) + return ret + + initiators = sorted(initiators, key=lambda item: item.end) + if not matches.holes(initiators[0].end, initiators[1].start, predicate=lambda m: m.raw.strip(seps)): + first_range = matches.named('episode', predicate=lambda m: m.initiator == initiators[0]) + second_range = matches.named('episode', predicate=lambda m: m.initiator == initiators[1]) + if len(first_range) == len(second_range): + if second_range[0].value > first_range[0].value: + return second_range + if first_range[0].value > second_range[0].value: + return first_range + + class EpisodeNumberSeparatorRange(AbstractSeparatorRange): """ Remove separator matches and create matches for episoderNumber range. """ - priority = 128 - consequence = [RemoveMatch, AppendMatch] def __init__(self, range_separators): super(EpisodeNumberSeparatorRange, self).__init__(range_separators, "episode") @@ -446,8 +587,6 @@ class SeasonSeparatorRange(AbstractSeparatorRange): """ Remove separator matches and create matches for season range. """ - priority = 128 - consequence = [RemoveMatch, AppendMatch] def __init__(self, range_separators): super(SeasonSeparatorRange, self).__init__(range_separators, "season") @@ -455,7 +594,7 @@ def __init__(self, range_separators): class RemoveWeakIfMovie(Rule): """ - Remove weak-movie tagged matches if it seems to be a movie. + Remove weak-episode tagged matches if it seems to be a movie. """ priority = 64 consequence = RemoveMatch @@ -471,19 +610,48 @@ def when(self, matches, context): year = matches.range(filepart.start, filepart.end, predicate=lambda m: m.name == 'year', index=0) if year: remove = True - next_match = matches.next(year, predicate=lambda m, fp=filepart: m.private and m.end <= fp.end, index=0) - if next_match and not matches.at_match(next_match, predicate=lambda m: m.name == 'year'): + next_match = matches.range(year.end, filepart.end, predicate=lambda m: m.private, index=0) + if (next_match and not matches.holes(year.end, next_match.start, predicate=lambda m: m.raw.strip(seps)) + and not matches.at_match(next_match, predicate=lambda m: m.name == 'year')): to_ignore.add(next_match.initiator) + to_ignore.update(matches.range(filepart.start, filepart.end, + predicate=lambda m: len(m.children.named('episode')) > 1)) + + to_remove.extend(matches.conflicting(year)) if remove: - to_remove.extend(matches.tagged('weak-movie', predicate=lambda m: m.initiator not in to_ignore)) + to_remove.extend(matches.tagged('weak-episode', predicate=( + lambda m: m.initiator not in to_ignore and 'anime' not in m.tags))) return to_remove +class RemoveWeak(Rule): + """ + Remove weak-episode matches which appears after video, source, and audio matches. + """ + priority = 16 + consequence = RemoveMatch + + def when(self, matches, context): + to_remove = [] + for filepart in matches.markers.named('path'): + weaks = matches.range(filepart.start, filepart.end, predicate=lambda m: 'weak-episode' in m.tags) + if weaks: + previous = matches.previous(weaks[0], predicate=lambda m: m.name in ( + 'audio_codec', 'screen_size', 'streaming_service', 'source', 'video_profile', + 'audio_channels', 'audio_profile'), index=0) + if previous and not matches.holes( + previous.end, weaks[0].start, predicate=lambda m: m.raw.strip(seps)): + to_remove.extend(weaks) + return to_remove + + class RemoveWeakIfSxxExx(Rule): """ - Remove weak-movie tagged matches if SxxExx pattern is matched. + Remove weak-episode tagged matches if SxxExx pattern is matched. + + Weak episodes at beginning of filepart are kept. """ priority = 64 consequence = RemoveMatch @@ -492,9 +660,10 @@ def when(self, matches, context): to_remove = [] for filepart in matches.markers.named('path'): if matches.range(filepart.start, filepart.end, - predicate=lambda match: not match.private and 'SxxExx' in match.tags): - to_remove.extend(matches.range( - filepart.start, filepart.end, predicate=lambda match: 'weak-movie' in match.tags)) + predicate=lambda m: not m.private and 'SxxExx' in m.tags): + for match in matches.range(filepart.start, filepart.end, predicate=lambda m: 'weak-episode' in m.tags): + if match.start != filepart.start or match.initiator.name != 'weak_episode': + to_remove.append(match) return to_remove @@ -575,7 +744,7 @@ def when(self, matches, context): for filepart in matches.markers.named('path'): patterns = defaultdict(list) for match in reversed(matches.range(filepart.start, filepart.end, - predicate=lambda match: 'weak-duplicate' in match.tags)): + predicate=lambda m: 'weak-duplicate' in m.tags)): if match.pattern in patterns[match.name]: to_remove.append(match) else: @@ -615,12 +784,12 @@ def when(self, matches, context): episode_numbers = [] episode_values = set() - for match in matches.named('episode', lambda match: not match.private and 'weak-movie' in match.tags): + for match in matches.named('episode', lambda m: not m.private and 'weak-episode' in m.tags): if match.value not in episode_values: episode_numbers.append(match) episode_values.add(match.value) - episode_numbers = list(sorted(episode_numbers, key=lambda match: match.value)) + episode_numbers = list(sorted(episode_numbers, key=lambda m: m.value)) if len(episode_numbers) > 1 and \ episode_numbers[0].value < 10 and \ episode_numbers[1].value - episode_numbers[0].value != 1: @@ -664,3 +833,29 @@ def when(self, matches, context): if not matches.range(*group.span, predicate=lambda match: match.name == 'title'): ret.append(episode) return ret + + +class RenameToDiscMatch(Rule): + """ + Rename episodes detected with `d` episodeMarkers to `disc`. + """ + + consequence = [RenameMatch('disc'), RenameMatch('discMarker'), RemoveMatch] + + def when(self, matches, context): + discs = [] + markers = [] + to_remove = [] + + disc_disabled = is_disabled(context, 'disc') + + for marker in matches.named('episodeMarker', predicate=lambda m: m.value.lower() == 'd'): + if disc_disabled: + to_remove.append(marker) + to_remove.extend(marker.initiator.children) + continue + + markers.append(marker) + discs.extend(sorted(marker.initiator.children.named('episode'), key=lambda m: m.value)) + + return discs, markers, to_remove diff --git a/ext/guessit/rules/properties/film.py b/ext/guessit/rules/properties/film.py index 8cd0561e46..3c7e6c0ff5 100644 --- a/ext/guessit/rules/properties/film.py +++ b/ext/guessit/rules/properties/film.py @@ -7,10 +7,11 @@ from rebulk.remodule import re from ..common.formatters import cleanup +from ..common.pattern import is_disabled from ..common.validators import seps_surround -def film(): +def film(config): # pylint:disable=unused-argument """ Builder for rebulk object. :return: Created Rebulk object @@ -18,7 +19,8 @@ def film(): """ rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, validate_all=True, validator={'__parent__': seps_surround}) - rebulk.regex(r'f(\d{1,2})', name='film', private_parent=True, children=True, formatter=int) + rebulk.regex(r'f(\d{1,2})', name='film', private_parent=True, children=True, formatter=int, + disabled=lambda context: is_disabled(context, 'film')) rebulk.rules(FilmTitleRule) @@ -33,7 +35,10 @@ class FilmTitleRule(Rule): properties = {'film_title': [None]} - def when(self, matches, context): + def enabled(self, context): + return not is_disabled(context, 'film_title') + + def when(self, matches, context): # pylint:disable=inconsistent-return-statements bonus_number = matches.named('film', lambda match: not match.private, index=0) if bonus_number: filepath = matches.markers.at_match(bonus_number, lambda marker: marker.name == 'path', 0) diff --git a/ext/guessit/rules/properties/format.py b/ext/guessit/rules/properties/format.py deleted file mode 100644 index 83a9a2f65e..0000000000 --- a/ext/guessit/rules/properties/format.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -format property -""" -from rebulk.remodule import re - -from rebulk import Rebulk, RemoveMatch, Rule -from ..common import dash -from ..common.validators import seps_before, seps_after - - -def format_(): - """ - Builder for rebulk object. - :return: Created Rebulk object - :rtype: Rebulk - """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) - rebulk.defaults(name="format", tags=['video-codec-prefix', 'streaming_service.suffix']) - - rebulk.regex("VHS", "VHS-?Rip", value="VHS") - rebulk.regex("CAM", "CAM-?Rip", "HD-?CAM", value="Cam") - rebulk.regex("TELESYNC", "TS", "HD-?TS", value="Telesync") - rebulk.regex("WORKPRINT", "WP", value="Workprint") - rebulk.regex("TELECINE", "TC", value="Telecine") - rebulk.regex("PPV", "PPV-?Rip", value="PPV") # Pay Per View - rebulk.regex("SD-?TV", "SD-?TV-?Rip", "Rip-?SD-?TV", "TV-?Rip", - "Rip-?TV", "TV-?(?=Dub)", value="TV") # TV is too common to allow matching - rebulk.regex("DVB-?Rip", "DVB", "PD-?TV", value="DVB") - rebulk.regex("DVD", "DVD-?Rip", "VIDEO-?TS", "DVD-?R(?:$|(?!E))", # "DVD-?R(?:$|^E)" => DVD-Real ... - "DVD-?9", "DVD-?5", value="DVD") - - rebulk.regex("HD-?TV", "TV-?RIP-?HD", "HD-?TV-?RIP", "HD-?RIP", value="HDTV", - conflict_solver=lambda match, other: other if other.name == 'other' else '__default__') - rebulk.regex("VOD", "VOD-?Rip", value="VOD") - rebulk.regex("WEB-?Rip", "WEB-?DL-?Rip", "WEB-?Cap", value="WEBRip") - rebulk.regex("WEB-?DL", "WEB-?HD", "WEB", "DL-?WEB", "DL(?=-?Mux)", value="WEB-DL") - rebulk.regex("HD-?DVD-?Rip", "HD-?DVD", value="HD-DVD") - rebulk.regex("Blu-?ray(?:-?Rip)?", "B[DR]", "B[DR]-?Rip", "BD[59]", "BD25", "BD50", value="BluRay") - rebulk.regex("AHDTV", value="AHDTV") - rebulk.regex('UHD-?TV', 'UHD-?Rip', value='UHDTV', - conflict_solver=lambda match, other: other if other.name == 'other' else '__default__') - rebulk.regex("HDTC", value="HDTC") - rebulk.regex("DSR", "DSR?-?Rip", "SAT-?Rip", "DTH", "DTH-?Rip", value="SATRip") - - rebulk.rules(ValidateFormat) - - return rebulk - - -class ValidateFormat(Rule): - """ - Validate format with screener property, with video_codec property or separated - """ - priority = 64 - consequence = RemoveMatch - - def when(self, matches, context): - ret = [] - for format_match in matches.named('format'): - if not seps_before(format_match) and \ - not matches.range(format_match.start - 1, format_match.start - 2, - lambda match: 'format-prefix' in match.tags): - ret.append(format_match) - continue - if not seps_after(format_match) and \ - not matches.range(format_match.end, format_match.end + 1, - lambda match: 'format-suffix' in match.tags): - ret.append(format_match) - continue - return ret diff --git a/ext/guessit/rules/properties/language.py b/ext/guessit/rules/properties/language.py index af60c6d9da..0cc4b94a80 100644 --- a/ext/guessit/rules/properties/language.py +++ b/ext/guessit/rules/properties/language.py @@ -11,55 +11,80 @@ from rebulk import Rebulk, Rule, RemoveMatch, RenameMatch from rebulk.remodule import re -from ..common.words import iter_words, COMMON_WORDS +from ..common import seps +from ..common.pattern import is_disabled +from ..common.words import iter_words from ..common.validators import seps_surround -def language(): +def language(config, common_words): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict + :param common_words: common words + :type common_words: set :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk() + subtitle_both = config['subtitle_affixes'] + subtitle_prefixes = sorted(subtitle_both + config['subtitle_prefixes'], key=length_comparator) + subtitle_suffixes = sorted(subtitle_both + config['subtitle_suffixes'], key=length_comparator) + lang_both = config['language_affixes'] + lang_prefixes = sorted(lang_both + config['language_prefixes'], key=length_comparator) + lang_suffixes = sorted(lang_both + config['language_suffixes'], key=length_comparator) + weak_affixes = frozenset(config['weak_affixes']) + + rebulk = Rebulk(disabled=lambda context: (is_disabled(context, 'language') and + is_disabled(context, 'subtitle_language'))) rebulk.string(*subtitle_prefixes, name="subtitle_language.prefix", ignore_case=True, private=True, - validator=seps_surround, tags=['release-group-prefix']) + validator=seps_surround, tags=['release-group-prefix'], + disabled=lambda context: is_disabled(context, 'subtitle_language')) rebulk.string(*subtitle_suffixes, name="subtitle_language.suffix", ignore_case=True, private=True, - validator=seps_surround) + validator=seps_surround, + disabled=lambda context: is_disabled(context, 'subtitle_language')) rebulk.string(*lang_suffixes, name="language.suffix", ignore_case=True, private=True, - validator=seps_surround, tags=['format-suffix']) - rebulk.functional(find_languages, properties={'language': [None]}) - rebulk.rules(SubtitlePrefixLanguageRule, SubtitleSuffixLanguageRule, SubtitleExtensionRule) + validator=seps_surround, tags=['source-suffix'], + disabled=lambda context: is_disabled(context, 'language')) - return rebulk + def find_languages(string, context=None): + """Find languages in the string + :return: list of tuple (property, Language, lang_word, word) + """ + return LanguageFinder(context, subtitle_prefixes, subtitle_suffixes, + lang_prefixes, lang_suffixes, weak_affixes).find(string) -COMMON_WORDS_STRICT = frozenset(['brazil']) + rebulk.functional(find_languages, + properties={'language': [None]}, + disabled=lambda context: not context.get('allowed_languages')) + rebulk.rules(SubtitleExtensionRule, + SubtitlePrefixLanguageRule, + SubtitleSuffixLanguageRule, + RemoveLanguage, + RemoveInvalidLanguages(common_words)) -UNDETERMINED = babelfish.Language('und') + babelfish.language_converters['guessit'] = GuessitConverter(config['synonyms']) -SYN = {('ell', None): ['gr', 'greek'], - ('spa', None): ['esp', 'español', 'espanol'], - ('fra', None): ['français', 'vf', 'vff', 'vfi', 'vfq'], - ('swe', None): ['se'], - ('por', 'BR'): ['po', 'pb', 'pob', 'ptbr', 'br', 'brazilian'], - ('cat', None): ['català', 'castellano', 'espanol castellano', 'español castellano'], - ('ces', None): ['cz'], - ('ukr', None): ['ua'], - ('zho', None): ['cn'], - ('jpn', None): ['jp'], - ('hrv', None): ['scr'], - ('mul', None): ['multi', 'dl']} # http://scenelingo.wordpress.com/2009/03/24/what-does-dl-mean/ + return rebulk + + +UNDETERMINED = babelfish.Language('und') class GuessitConverter(babelfish.LanguageReverseConverter): # pylint: disable=missing-docstring _with_country_regexp = re.compile(r'(.*)\((.*)\)') _with_country_regexp2 = re.compile(r'(.*)-(.*)') - def __init__(self): + def __init__(self, synonyms): self.guessit_exceptions = {} - for (alpha3, country), synlist in SYN.items(): + for code, synlist in synonyms.items(): + if '_' in code: + (alpha3, country) = code.split('_') + else: + (alpha3, country) = (code, None) for syn in synlist: self.guessit_exceptions[syn.lower()] = (alpha3, country, None) @@ -76,15 +101,7 @@ def convert(self, alpha3, country=None, script=None): return str(babelfish.Language(alpha3, country, script)) def reverse(self, name): # pylint:disable=arguments-differ - with_country = (GuessitConverter._with_country_regexp.match(name) or - GuessitConverter._with_country_regexp2.match(name)) - name = name.lower() - if with_country: - lang = babelfish.Language.fromguessit(with_country.group(1).strip()) - lang.country = babelfish.Country.fromguessit(with_country.group(2).strip()) - return lang.alpha3, lang.country.alpha2 if lang.country else None, lang.script or None - # exceptions come first, as they need to override a potential match # with any of the other guessers try: @@ -96,7 +113,8 @@ def reverse(self, name): # pylint:disable=arguments-differ babelfish.Language.fromalpha3b, babelfish.Language.fromalpha2, babelfish.Language.fromname, - babelfish.Language.fromopensubtitles]: + babelfish.Language.fromopensubtitles, + babelfish.Language.fromietf]: try: reverse = conv(name) return reverse.alpha3, reverse.country, reverse.script @@ -113,24 +131,6 @@ def length_comparator(value): return len(value) -babelfish.language_converters['guessit'] = GuessitConverter() - - -subtitle_both = ['sub', 'subs', 'subbed', 'custom subbed', 'custom subs', - 'custom sub', 'customsubbed', 'customsubs', 'customsub', - 'soft subtitles', 'soft subs'] -subtitle_prefixes = sorted(subtitle_both + - ['st', 'vost', 'subforced', 'fansub', 'hardsub', - 'legenda', 'legendas', 'legendado', 'subtitulado', - 'soft', 'subtitles'], key=length_comparator) -subtitle_suffixes = sorted(subtitle_both + - ['subforced', 'fansub', 'hardsub'], key=length_comparator) -lang_both = ['dublado', 'dubbed', 'dub'] -lang_suffixes = sorted(lang_both + ['audio'], key=length_comparator) -lang_prefixes = sorted(lang_both + ['true'], key=length_comparator) - -weak_prefixes = ('audio', 'true') - _LanguageMatch = namedtuple('_LanguageMatch', ['property_name', 'word', 'lang']) @@ -149,7 +149,7 @@ def __init__(self, start, end, value, input_string, next_word=None): self.next_word = next_word @property - def extended_word(self): + def extended_word(self): # pylint:disable=inconsistent-return-statements """ Return the extended word for this instance, if any. """ @@ -175,10 +175,17 @@ def to_rebulk_match(language_match): end = word.end name = language_match.property_name if language_match.lang == UNDETERMINED: - return start, end, dict(name=name, value=word.value.lower(), - formatter=babelfish.Language, tags=['weak-language']) + return start, end, { + 'name': name, + 'value': word.value.lower(), + 'formatter': babelfish.Language, + 'tags': ['weak-language'] + } - return start, end, dict(name=name, value=language_match.lang) + return start, end, { + 'name': name, + 'value': language_match.lang + } class LanguageFinder(object): @@ -186,10 +193,21 @@ class LanguageFinder(object): Helper class to search and return language matches: 'language' and 'subtitle_language' properties """ - def __init__(self, allowed_languages): - self.parsed = dict() - self.allowed_languages = allowed_languages - self.common_words = COMMON_WORDS_STRICT if allowed_languages else COMMON_WORDS + def __init__(self, context, + subtitle_prefixes, subtitle_suffixes, + lang_prefixes, lang_suffixes, weak_affixes): + allowed_languages = context.get('allowed_languages') if context else None + self.allowed_languages = set([l.lower() for l in allowed_languages or []]) + self.weak_affixes = weak_affixes + self.prefixes_map = {} + self.suffixes_map = {} + + if not is_disabled(context, 'subtitle_language'): + self.prefixes_map['subtitle_language'] = subtitle_prefixes + self.suffixes_map['subtitle_language'] = subtitle_suffixes + + self.prefixes_map['language'] = lang_prefixes + self.suffixes_map['language'] = lang_suffixes def find(self, string): """ @@ -250,11 +268,11 @@ def iter_matches_for_candidate(self, language_word): """ tuples = [ (language_word, language_word.next_word, - dict(subtitle_language=subtitle_prefixes, language=lang_prefixes), + self.prefixes_map, lambda string, prefix: string.startswith(prefix), lambda string, prefix: string[len(prefix):]), (language_word.next_word, language_word, - dict(subtitle_language=subtitle_suffixes, language=lang_suffixes), + self.suffixes_map, lambda string, suffix: string.endswith(suffix), lambda string, suffix: string[:len(string) - len(suffix)]) ] @@ -271,7 +289,7 @@ def iter_matches_for_candidate(self, language_word): if match: yield match - def find_match_for_word(self, word, fallback_word, affixes, is_affix, strip_affix): + def find_match_for_word(self, word, fallback_word, affixes, is_affix, strip_affix): # pylint:disable=inconsistent-return-statements """ Return the language match for the given word and affixes. """ @@ -280,8 +298,6 @@ def find_match_for_word(self, word, fallback_word, affixes, is_affix, strip_affi continue word_lang = current_word.value.lower() - if word_lang in self.common_words: - continue for key, parts in affixes.items(): for part in parts: @@ -291,30 +307,31 @@ def find_match_for_word(self, word, fallback_word, affixes, is_affix, strip_affi match = None value = strip_affix(word_lang, part) if not value: - if fallback_word: - match = self.find_language_match_for_word(fallback_word, key=key, force=True) + if fallback_word and ( + abs(fallback_word.start - word.end) <= 1 or abs(word.start - fallback_word.end) <= 1): + match = self.find_language_match_for_word(fallback_word, key=key) - if not match and part not in weak_prefixes: + if not match and part not in self.weak_affixes: match = self.create_language_match(key, LanguageWord(current_word.start, current_word.end, 'und', current_word.input_string)) - elif value not in self.common_words: + else: match = self.create_language_match(key, LanguageWord(current_word.start, current_word.end, value, current_word.input_string)) if match: return match - def find_language_match_for_word(self, word, key='language', force=False): + def find_language_match_for_word(self, word, key='language'): # pylint:disable=inconsistent-return-statements """ Return the language match for the given word. """ for current_word in (word.extended_word, word): - if current_word and (force or current_word.value.lower() not in self.common_words): + if current_word: match = self.create_language_match(key, current_word) if match: return match - def create_language_match(self, key, word): + def create_language_match(self, key, word): # pylint:disable=inconsistent-return-statements """ Create a LanguageMatch for a given word """ @@ -323,40 +340,21 @@ def create_language_match(self, key, word): if lang is not None: return _LanguageMatch(property_name=key, word=word, lang=lang) - def parse_language(self, lang_word): + def parse_language(self, lang_word): # pylint:disable=inconsistent-return-statements """ Parse the lang_word into a valid Language. Multi and Undetermined languages are also valid languages. """ - if lang_word in self.parsed: - return self.parsed[lang_word] - try: lang = babelfish.Language.fromguessit(lang_word) - if self.allowed_languages: - if (hasattr(lang, 'name') and lang.name.lower() in self.allowed_languages) \ - or (hasattr(lang, 'alpha2') and lang.alpha2.lower() in self.allowed_languages) \ - or lang.alpha3.lower() in self.allowed_languages: - self.parsed[lang_word] = lang - return lang - # Keep language with alpha2 equivalent. Others are probably - # uncommon languages. - elif lang in ('mul', UNDETERMINED) or hasattr(lang, 'alpha2'): - self.parsed[lang_word] = lang + if ((hasattr(lang, 'name') and lang.name.lower() in self.allowed_languages) or + (hasattr(lang, 'alpha2') and lang.alpha2.lower() in self.allowed_languages) or + lang.alpha3.lower() in self.allowed_languages): return lang - self.parsed[lang_word] = None except babelfish.Error: - self.parsed[lang_word] = None - - -def find_languages(string, context=None): - """Find languages in the string - - :return: list of tuple (property, Language, lang_word, word) - """ - return LanguageFinder(context.get('allowed_languages')).find(string) + pass class SubtitlePrefixLanguageRule(Rule): @@ -367,6 +365,9 @@ class SubtitlePrefixLanguageRule(Rule): properties = {'subtitle_language': [None]} + def enabled(self, context): + return not is_disabled(context, 'subtitle_language') + def when(self, matches, context): to_rename = [] to_remove = matches.named('subtitle_language.prefix') @@ -412,6 +413,9 @@ class SubtitleSuffixLanguageRule(Rule): properties = {'subtitle_language': [None]} + def enabled(self, context): + return not is_disabled(context, 'subtitle_language') + def when(self, matches, context): to_append = [] to_remove = matches.named('subtitle_language.suffix') @@ -436,17 +440,64 @@ class SubtitleExtensionRule(Rule): """ Convert language guess as subtitle_language if next match is a subtitle extension. - Since it's a strong match, it also removes any conflicting format with it. + Since it's a strong match, it also removes any conflicting source with it. """ consequence = [RemoveMatch, RenameMatch('subtitle_language')] properties = {'subtitle_language': [None]} - def when(self, matches, context): + def enabled(self, context): + return not is_disabled(context, 'subtitle_language') + + def when(self, matches, context): # pylint:disable=inconsistent-return-statements subtitle_extension = matches.named('container', lambda match: 'extension' in match.tags and 'subtitle' in match.tags, 0) if subtitle_extension: subtitle_lang = matches.previous(subtitle_extension, lambda match: match.name == 'language', 0) if subtitle_lang: - return matches.conflicting(subtitle_lang, lambda m: m.name == 'format'), subtitle_lang + for weak in matches.named('subtitle_language', predicate=lambda m: 'weak-language' in m.tags): + weak.private = True + + return matches.conflicting(subtitle_lang, lambda m: m.name == 'source'), subtitle_lang + + +class RemoveLanguage(Rule): + """Remove language matches that were not converted to subtitle_language when language is disabled.""" + + consequence = RemoveMatch + + def enabled(self, context): + return is_disabled(context, 'language') + + def when(self, matches, context): + return matches.named('language') + + +class RemoveInvalidLanguages(Rule): + """Remove language matches that matches the blacklisted common words.""" + + consequence = RemoveMatch + + def __init__(self, common_words): + """Constructor.""" + super(RemoveInvalidLanguages, self).__init__() + self.common_words = common_words + + def when(self, matches, context): + to_remove = [] + for match in matches.range(0, len(matches.input_string), + predicate=lambda m: m.name in ('language', 'subtitle_language')): + if match.raw.lower() not in self.common_words: + continue + + group = matches.markers.at_match(match, index=0, predicate=lambda m: m.name == 'group') + if group and ( + not matches.range( + group.start, group.end, predicate=lambda m: m.name not in ('language', 'subtitle_language') + ) and (not matches.holes(group.start, group.end, predicate=lambda m: m.value.strip(seps)))): + continue + + to_remove.append(match) + + return to_remove diff --git a/ext/guessit/rules/properties/mimetype.py b/ext/guessit/rules/properties/mimetype.py index c57ada7781..f9e642ffae 100644 --- a/ext/guessit/rules/properties/mimetype.py +++ b/ext/guessit/rules/properties/mimetype.py @@ -8,16 +8,23 @@ from rebulk import Rebulk, CustomRule, POST_PROCESS from rebulk.match import Match +from ..common.pattern import is_disabled from ...rules.processors import Processors -def mimetype(): +def mimetype(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - return Rebulk().rules(Mimetype) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'mimetype')) + rebulk.rules(Mimetype) + + return rebulk class Mimetype(CustomRule): diff --git a/ext/guessit/rules/properties/other.py b/ext/guessit/rules/properties/other.py index 5fead16ef6..b3d49caa58 100644 --- a/ext/guessit/rules/properties/other.py +++ b/ext/guessit/rules/properties/other.py @@ -5,38 +5,43 @@ """ import copy -from rebulk import Rebulk, Rule, RemoveMatch, POST_PROCESS, AppendMatch +from rebulk import Rebulk, Rule, RemoveMatch, RenameMatch, POST_PROCESS, AppendMatch from rebulk.remodule import re from ..common import dash from ..common import seps +from ..common.pattern import is_disabled from ..common.validators import seps_after, seps_before, seps_surround, compose from ...reutils import build_or_pattern from ...rules.common.formatters import raw_cleanup -def other(): +def other(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).string_defaults(ignore_case=True) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'other')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).string_defaults(ignore_case=True) rebulk.defaults(name="other", validator=seps_surround) - rebulk.regex('Audio-?Fix', 'Audio-?Fixed', value='AudioFix') - rebulk.regex('Sync-?Fix', 'Sync-?Fixed', value='SyncFix') - rebulk.regex('Dual', 'Dual-?Audio', value='DualAudio') - rebulk.regex('ws', 'wide-?screen', value='WideScreen') - rebulk.regex('Re-?Enc(?:oded)?', value='ReEncoded') + rebulk.regex('Audio-?Fix', 'Audio-?Fixed', value='Audio Fixed') + rebulk.regex('Sync-?Fix', 'Sync-?Fixed', value='Sync Fixed') + rebulk.regex('Dual', 'Dual-?Audio', value='Dual Audio') + rebulk.regex('ws', 'wide-?screen', value='Widescreen') + rebulk.regex('Re-?Enc(?:oded)?', value='Reencoded') rebulk.string('Real', 'Fix', 'Fixed', value='Proper', tags=['has-neighbor-before', 'has-neighbor-after']) rebulk.string('Proper', 'Repack', 'Rerip', 'Dirfix', 'Nfofix', 'Prooffix', value='Proper', tags=['streaming_service.prefix', 'streaming_service.suffix']) rebulk.regex('(?:Proof-?)?Sample-?Fix', value='Proper', tags=['streaming_service.prefix', 'streaming_service.suffix']) - rebulk.string('Fansub', value='Fansub', tags='has-neighbor') - rebulk.string('Fastsub', value='Fastsub', tags='has-neighbor') + rebulk.string('Fansub', value='Fan Subtitled', tags='has-neighbor') + rebulk.string('Fastsub', value='Fast Subtitled', tags='has-neighbor') season_words = build_or_pattern(["seasons?", "series?"]) complete_articles = build_or_pattern(["The"]) @@ -61,29 +66,38 @@ def validate_complete(match): value={'other': 'Complete'}, tags=['release-group-prefix'], validator={'__parent__': compose(seps_surround, validate_complete)}) - rebulk.string('R5', 'RC', value='R5') + rebulk.string('R5', value='Region 5') + rebulk.string('RC', value='Region C') rebulk.regex('Pre-?Air', value='Preair') rebulk.regex('(?:PS-?)?Vita', value='PS Vita') + rebulk.regex('(HD)(?PRip)', value={'other': 'HD', 'another': 'Rip'}, + private_parent=True, children=True, validator={'__parent__': seps_surround}, validate_all=True) - for value in ( - 'Screener', 'Remux', '3D', 'mHD', 'HDLight', 'HQ', 'DDC', 'HR', 'PAL', 'SECAM', 'NTSC', - 'CC', 'LD', 'MD', 'XXX'): + for value in ('Screener', 'Remux', '3D', 'PAL', 'SECAM', 'NTSC', 'XXX'): rebulk.string(value, value=value) - rebulk.string('LDTV', value='LD') + rebulk.string('HQ', value='High Quality', tags='uhdbluray-neighbor') + rebulk.string('HR', value='High Resolution') + rebulk.string('LD', value='Line Dubbed') + rebulk.string('MD', value='Mic Dubbed') + rebulk.string('mHD', 'HDLight', value='Micro HD') + rebulk.string('LDTV', value='Low Definition') + rebulk.string('HFR', value='High Frame Rate') rebulk.string('HD', value='HD', validator=None, tags=['streaming_service.prefix', 'streaming_service.suffix']) - rebulk.regex('Full-?HD', 'FHD', value='FullHD', validator=None, + rebulk.regex('Full-?HD', 'FHD', value='Full HD', validator=None, tags=['streaming_service.prefix', 'streaming_service.suffix']) - rebulk.regex('Ultra-?(?:HD)?', 'UHD', value='UltraHD', validator=None, + rebulk.regex('Ultra-?(?:HD)?', 'UHD', value='Ultra HD', validator=None, tags=['streaming_service.prefix', 'streaming_service.suffix']) + rebulk.regex('Upscaled?', value='Upscaled') - for value in ('Complete', 'Classic', 'LiNE', 'Bonus', 'Trailer', 'FINAL', 'Retail', + for value in ('Complete', 'Classic', 'Bonus', 'Trailer', 'Retail', 'Colorized', 'Internal'): rebulk.string(value, value=value, tags=['has-neighbor', 'release-group-prefix']) + rebulk.regex('LiNE', value='Line Audio', tags=['has-neighbor-before', 'has-neighbor-after', 'release-group-prefix']) rebulk.regex('Read-?NFO', value='Read NFO') rebulk.string('CONVERT', value='Converted', tags='has-neighbor') - rebulk.string('DOCU', value='Documentary', tags='has-neighbor') + rebulk.string('DOCU', 'DOKU', value='Documentary', tags='has-neighbor') rebulk.string('OM', value='Open Matte', tags='has-neighbor') rebulk.string('STV', value='Straight to Video', tags='has-neighbor') rebulk.string('OAR', value='Original Aspect Ratio', tags='has-neighbor') @@ -92,16 +106,28 @@ def validate_complete(match): for coast in ('East', 'West'): rebulk.regex(r'(?:Live-)?(?:Episode-)?' + coast + '-?(?:Coast-)?Feed', value=coast + ' Coast Feed') - rebulk.string('VO', 'OV', value='OV', tags='has-neighbor') + rebulk.string('VO', 'OV', value='Original Video', tags='has-neighbor') + rebulk.string('Ova', 'Oav', value='Original Animated Video') rebulk.regex('Scr(?:eener)?', value='Screener', validator=None, - tags=['other.validate.screener', 'format-prefix', 'format-suffix']) + tags=['other.validate.screener', 'source-prefix', 'source-suffix']) rebulk.string('Mux', value='Mux', validator=seps_after, - tags=['other.validate.mux', 'video-codec-prefix', 'format-suffix']) - rebulk.string('HC', value='Hardcoded Subtitles') + tags=['other.validate.mux', 'video-codec-prefix', 'source-suffix']) + rebulk.string('HC', 'vost', value='Hardcoded Subtitles') + + rebulk.string('SDR', value='Standard Dynamic Range', tags='uhdbluray-neighbor') + rebulk.regex('HDR(?:10)?', value='HDR10', tags='uhdbluray-neighbor') + rebulk.regex('Dolby-?Vision', value='Dolby Vision', tags='uhdbluray-neighbor') + rebulk.regex('BT-?2020', value='BT.2020', tags='uhdbluray-neighbor') - rebulk.rules(ValidateHasNeighbor, ValidateHasNeighborAfter, ValidateHasNeighborBefore, ValidateScreenerRule, - ValidateMuxRule, ValidateHardcodedSubs, ValidateStreamingServiceNeighbor, ProperCountRule) + rebulk.string('Sample', value='Sample', tags=['at-end', 'not-a-release-group']) + rebulk.string('Proof', value='Proof', tags=['at-end', 'not-a-release-group']) + rebulk.string('Obfuscated', 'Scrambled', value='Obfuscated', tags=['at-end', 'not-a-release-group']) + rebulk.string('xpost', 'postbot', 'asrequested', value='Repost', tags='not-a-release-group') + + rebulk.rules(RenameAnotherToOther, ValidateHasNeighbor, ValidateHasNeighborAfter, ValidateHasNeighborBefore, + ValidateScreenerRule, ValidateMuxRule, ValidateHardcodedSubs, ValidateStreamingServiceNeighbor, + ValidateAtEnd, ProperCountRule) return rebulk @@ -116,7 +142,7 @@ class ProperCountRule(Rule): properties = {'proper_count': [None]} - def when(self, matches, context): + def when(self, matches, context): # pylint:disable=inconsistent-return-statements propers = matches.named('other', lambda match: match.value == 'Proper') if propers: raws = {} # Count distinct raw values @@ -128,11 +154,23 @@ def when(self, matches, context): return proper_count_match +class RenameAnotherToOther(Rule): + """ + Rename `another` properties to `other` + """ + priority = 32 + consequence = RenameMatch('other') + + def when(self, matches, context): + return matches.named('another') + + class ValidateHasNeighbor(Rule): """ Validate tag has-neighbor """ consequence = RemoveMatch + priority = 64 def when(self, matches, context): ret = [] @@ -158,6 +196,7 @@ class ValidateHasNeighborBefore(Rule): Validate tag has-neighbor-before that previous match exists. """ consequence = RemoveMatch + priority = 64 def when(self, matches, context): ret = [] @@ -177,6 +216,7 @@ class ValidateHasNeighborAfter(Rule): Validate tag has-neighbor-after that next match exists. """ consequence = RemoveMatch + priority = 64 def when(self, matches, context): ret = [] @@ -201,8 +241,8 @@ class ValidateScreenerRule(Rule): def when(self, matches, context): ret = [] for screener in matches.named('other', lambda match: 'other.validate.screener' in match.tags): - format_match = matches.previous(screener, lambda match: match.name == 'format', 0) - if not format_match or matches.input_string[format_match.end:screener.start].strip(seps): + source_match = matches.previous(screener, lambda match: match.initiator.name == 'source', 0) + if not source_match or matches.input_string[source_match.end:screener.start].strip(seps): ret.append(screener) return ret @@ -217,8 +257,8 @@ class ValidateMuxRule(Rule): def when(self, matches, context): ret = [] for mux in matches.named('other', lambda match: 'other.validate.mux' in match.tags): - format_match = matches.previous(mux, lambda match: match.name == 'format', 0) - if not format_match: + source_match = matches.previous(mux, lambda match: match.initiator.name == 'source', 0) + if not source_match: ret.append(mux) return ret @@ -257,16 +297,18 @@ class ValidateStreamingServiceNeighbor(Rule): def when(self, matches, context): to_remove = [] for match in matches.named('other', - predicate=lambda m: ('streaming_service.prefix' in m.tags or - 'streaming_service.suffix' in m.tags)): - + predicate=lambda m: (m.initiator.name != 'source' + and ('streaming_service.prefix' in m.tags + or 'streaming_service.suffix' in m.tags))): + match = match.initiator if not seps_after(match): if 'streaming_service.prefix' in match.tags: next_match = matches.next(match, lambda m: m.name == 'streaming_service', 0) if next_match and not matches.holes(match.end, next_match.start, predicate=lambda m: m.value.strip(seps)): continue - + if match.children: + to_remove.extend(match.children) to_remove.append(match) elif not seps_before(match): @@ -276,6 +318,27 @@ def when(self, matches, context): predicate=lambda m: m.value.strip(seps)): continue + if match.children: + to_remove.extend(match.children) to_remove.append(match) return to_remove + + +class ValidateAtEnd(Rule): + """Validate other which should occur at the end of a filepart.""" + + priority = 32 + consequence = RemoveMatch + + def when(self, matches, context): + to_remove = [] + for filepart in matches.markers.named('path'): + for match in matches.range(filepart.start, filepart.end, + predicate=lambda m: m.name == 'other' and 'at-end' in m.tags): + if (matches.holes(match.end, filepart.end, predicate=lambda m: m.value.strip(seps)) or + matches.range(match.end, filepart.end, predicate=lambda m: m.name not in ( + 'other', 'container'))): + to_remove.append(match) + + return to_remove diff --git a/ext/guessit/rules/properties/part.py b/ext/guessit/rules/properties/part.py index d274f7fbbb..ec038b187e 100644 --- a/ext/guessit/rules/properties/part.py +++ b/ext/guessit/rules/properties/part.py @@ -7,20 +7,25 @@ from rebulk import Rebulk from ..common import dash +from ..common.pattern import is_disabled from ..common.validators import seps_surround, int_coercable, compose from ..common.numeral import numeral, parse_numeral from ...reutils import build_or_pattern -def part(): +def part(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash], validator={'__parent__': seps_surround}) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'part')) + rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash], validator={'__parent__': seps_surround}) - prefixes = ['pt', 'part'] + prefixes = config['prefixes'] def validate_roman(match): """ diff --git a/ext/guessit/rules/properties/release_group.py b/ext/guessit/rules/properties/release_group.py index ace3f0eb32..5144a90244 100644 --- a/ext/guessit/rules/properties/release_group.py +++ b/ext/guessit/rules/properties/release_group.py @@ -6,22 +6,53 @@ import copy from rebulk import Rebulk, Rule, AppendMatch, RemoveMatch +from rebulk.match import Match from ..common import seps from ..common.expected import build_expected_function from ..common.comparators import marker_sorted from ..common.formatters import cleanup +from ..common.pattern import is_disabled from ..common.validators import int_coercable, seps_surround from ..properties.title import TitleFromPosition -def release_group(): +def release_group(config): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk() + forbidden_groupnames = config['forbidden_names'] + + groupname_ignore_seps = config['ignored_seps'] + groupname_seps = ''.join([c for c in seps if c not in groupname_ignore_seps]) + + def clean_groupname(string): + """ + Removes and strip separators from input_string + :param string: + :type string: + :return: + :rtype: + """ + string = string.strip(groupname_seps) + if not (string.endswith(tuple(groupname_ignore_seps)) and string.startswith(tuple(groupname_ignore_seps))) \ + and not any(i in string.strip(groupname_ignore_seps) for i in groupname_ignore_seps): + string = string.strip(groupname_ignore_seps) + for forbidden in forbidden_groupnames: + if string.lower().startswith(forbidden) and string[len(forbidden):len(forbidden) + 1] in seps: + string = string[len(forbidden):] + string = string.strip(groupname_seps) + if string.lower().endswith(forbidden) and string[-len(forbidden) - 1:-len(forbidden)] in seps: + string = string[:len(forbidden)] + string = string.strip(groupname_seps) + return string + + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'release_group')) expected_group = build_expected_function('expected_group') @@ -30,42 +61,135 @@ def release_group(): conflict_solver=lambda match, other: other, disabled=lambda context: not context.get('expected_group')) - return rebulk.rules(SceneReleaseGroup, AnimeReleaseGroup) + return rebulk.rules( + DashSeparatedReleaseGroup(clean_groupname), + SceneReleaseGroup(clean_groupname), + AnimeReleaseGroup + ) -forbidden_groupnames = ['rip', 'by', 'for', 'par', 'pour', 'bonus'] +_scene_previous_names = ('video_codec', 'source', 'video_api', 'audio_codec', 'audio_profile', 'video_profile', + 'audio_channels', 'screen_size', 'other', 'container', 'language', 'subtitle_language', + 'subtitle_language.suffix', 'subtitle_language.prefix', 'language.suffix') -groupname_ignore_seps = '[]{}()' -groupname_seps = ''.join([c for c in seps if c not in groupname_ignore_seps]) +_scene_previous_tags = ('release-group-prefix', ) -def clean_groupname(string): +class DashSeparatedReleaseGroup(Rule): """ - Removes and strip separators from input_string - :param string: - :type string: - :return: - :rtype: + Detect dash separated release groups that might appear at the end or at the beginning of a release name. + + Series.S01E02.Pilot.DVDRip.x264-CS.mkv + release_group: CS + abc-the.title.name.1983.1080p.bluray.x264.mkv + release_group: abc + + At the end: Release groups should be dash-separated and shouldn't contain spaces nor + appear in a group with other matches. The preceding matches should be separated by dot. + If a release group is found, the conflicting matches are removed. + + At the beginning: Release groups should be dash-separated and shouldn't contain spaces nor appear in a group. + It should be followed by a hole with dot-separated words. + Detection only happens if no matches exist at the beginning. """ - string = string.strip(groupname_seps) - if not (string.endswith(tuple(groupname_ignore_seps)) and string.startswith(tuple(groupname_ignore_seps))) \ - and not any(i in string.strip(groupname_ignore_seps) for i in groupname_ignore_seps): - string = string.strip(groupname_ignore_seps) - for forbidden in forbidden_groupnames: - if string.lower().startswith(forbidden) and string[len(forbidden):len(forbidden)+1] in seps: - string = string[len(forbidden):] - string = string.strip(groupname_seps) - if string.lower().endswith(forbidden) and string[-len(forbidden)-1:-len(forbidden)] in seps: - string = string[:len(forbidden)] - string = string.strip(groupname_seps) - return string - - -_scene_previous_names = ['video_codec', 'format', 'video_api', 'audio_codec', 'audio_profile', 'video_profile', - 'audio_channels', 'screen_size', 'other', 'container', 'language', 'subtitle_language', - 'subtitle_language.suffix', 'subtitle_language.prefix', 'language.suffix'] + consequence = [RemoveMatch, AppendMatch] + + def __init__(self, value_formatter): + """Default constructor.""" + super(DashSeparatedReleaseGroup, self).__init__() + self.value_formatter = value_formatter + + @classmethod + def is_valid(cls, matches, candidate, start, end, at_end): # pylint:disable=inconsistent-return-statements + """ + Whether a candidate is a valid release group. + """ + if not at_end: + if len(candidate.value) <= 1: + return False + + if matches.markers.at_match(candidate, predicate=lambda m: m.name == 'group'): + return False + + first_hole = matches.holes(candidate.end, end, predicate=lambda m: m.start == candidate.end, index=0) + if not first_hole: + return False + + raw_value = first_hole.raw + return raw_value[0] == '-' and '-' not in raw_value[1:] and '.' in raw_value and ' ' not in raw_value + + group = matches.markers.at_match(candidate, predicate=lambda m: m.name == 'group', index=0) + if group and matches.at_match(group, predicate=lambda m: not m.private and m.span != candidate.span): + return False + + count = 0 + match = candidate + while match: + current = matches.range(start, match.start, index=-1, predicate=lambda m: not m.private) + if not current: + break + + separator = match.input_string[current.end:match.start] + if not separator and match.raw[0] == '-': + separator = '-' + + match = current + + if count == 0: + if separator != '-': + break + + count += 1 + continue + + if separator == '.': + return True + + def detect(self, matches, start, end, at_end): # pylint:disable=inconsistent-return-statements + """ + Detect release group at the end or at the beginning of a filepart. + """ + candidate = None + if at_end: + container = matches.ending(end, lambda m: m.name == 'container', index=0) + if container: + end = container.start + + candidate = matches.ending(end, index=0, predicate=( + lambda m: not m.private and not ( + m.name == 'other' and 'not-a-release-group' in m.tags + ) and '-' not in m.raw and m.raw.strip() == m.raw)) + + if not candidate: + if at_end: + candidate = matches.holes(start, end, seps=seps, index=-1, + predicate=lambda m: m.end == end and m.raw.strip(seps) and m.raw[0] == '-') + else: + candidate = matches.holes(start, end, seps=seps, index=0, + predicate=lambda m: m.start == start and m.raw.strip(seps)) + + if candidate and self.is_valid(matches, candidate, start, end, at_end): + return candidate + + def when(self, matches, context): # pylint:disable=inconsistent-return-statements + if matches.named('release_group'): + return + + to_remove = [] + to_append = [] + for filepart in matches.markers.named('path'): + candidate = self.detect(matches, filepart.start, filepart.end, True) + if candidate: + to_remove.extend(matches.at_match(candidate)) + else: + candidate = self.detect(matches, filepart.start, filepart.end, False) + + if candidate: + releasegroup = Match(candidate.start, candidate.end, name='release_group', + formatter=self.value_formatter, input_string=candidate.input_string) -_scene_previous_tags = ['release-group-prefix'] + to_append.append(releasegroup) + return to_remove, to_append class SceneReleaseGroup(Rule): @@ -79,7 +203,12 @@ class SceneReleaseGroup(Rule): properties = {'release_group': [None]} - def when(self, matches, context): + def __init__(self, value_formatter): + """Default constructor.""" + super(SceneReleaseGroup, self).__init__() + self.value_formatter = value_formatter + + def when(self, matches, context): # pylint:disable=too-many-locals # If a release_group is found before, ignore this kind of release_group rule. ret = [] @@ -87,6 +216,8 @@ def when(self, matches, context): for filepart in marker_sorted(matches.markers.named('path'), matches): # pylint:disable=cell-var-from-loop start, end = filepart.span + if matches.named('release_group', predicate=lambda m: m.start >= start and m.end <= end): + continue titles = matches.named('title', predicate=lambda m: m.start >= start and m.end <= end) @@ -101,7 +232,7 @@ def keep_only_first_title(match): """ return match in titles[1:] - last_hole = matches.holes(start, end + 1, formatter=clean_groupname, + last_hole = matches.holes(start, end + 1, formatter=self.value_formatter, ignore=keep_only_first_title, predicate=lambda hole: cleanup(hole.value), index=-1) @@ -134,7 +265,7 @@ def previous_match_filter(match): # if hole is inside a group marker with same value, remove [](){} ... group = matches.markers.at_match(last_hole, lambda marker: marker.name == 'group', 0) if group: - group.formatter = clean_groupname + group.formatter = self.value_formatter if group.value == last_hole.value: last_hole.start = group.start + 1 last_hole.end = group.end - 1 @@ -165,11 +296,11 @@ def when(self, matches, context): # If a release_group is found before, ignore this kind of release_group rule. if matches.named('release_group'): - return + return to_remove, to_append if not matches.named('episode') and not matches.named('season') and matches.named('release_group'): # This doesn't seems to be an anime, and we already found another release_group. - return + return to_remove, to_append for filepart in marker_sorted(matches.markers.named('path'), matches): diff --git a/ext/guessit/rules/properties/screen_size.py b/ext/guessit/rules/properties/screen_size.py index b7732ab61c..83a797c1fa 100644 --- a/ext/guessit/rules/properties/screen_size.py +++ b/ext/guessit/rules/properties/screen_size.py @@ -3,67 +3,115 @@ """ screen_size property """ +from rebulk.match import Match from rebulk.remodule import re -from rebulk import Rebulk, Rule, RemoveMatch +from rebulk import Rebulk, Rule, RemoveMatch, AppendMatch + +from ..common.pattern import is_disabled +from ..common.quantity import FrameRate from ..common.validators import seps_surround from ..common import dash, seps +from ...reutils import build_or_pattern -def screen_size(): +def screen_size(config): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - def conflict_solver(match, other): - """ - Conflict solver for most screen_size. - """ - if other.name == 'screen_size': - if 'resolution' in other.tags: - # The chtouile to solve conflict in "720 x 432" string matching both 720p pattern - int_value = _digits_re.findall(match.raw)[-1] - if other.value.startswith(int_value): - return match - return other - return '__default__' - - rebulk = Rebulk().string_defaults(ignore_case=True).regex_defaults(flags=re.IGNORECASE) - rebulk.defaults(name="screen_size", validator=seps_surround, conflict_solver=conflict_solver) - - rebulk.regex(r"(?:\d{3,}(?:x|\*))?360(?:i|p?x?)", value="360p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?368(?:i|p?x?)", value="368p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?480(?:i|p?x?)", value="480p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?576(?:i|p?x?)", value="576p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?720(?:i|p?(?:50|60)?x?)", value="720p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?720(?:p(?:50|60)?x?)", value="720p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?720p?hd", value="720p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?900(?:i|p?x?)", value="900p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080i", value="1080i") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080p?x?", value="1080p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080(?:p(?:50|60)?x?)", value="1080p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080p?hd", value="1080p") - rebulk.regex(r"(?:\d{3,}(?:x|\*))?2160(?:i|p?x?)", value="4K") - rebulk.string('4k', value='4K') - - _digits_re = re.compile(r'\d+') - - rebulk.defaults(name="screen_size", validator=seps_surround) - rebulk.regex(r'\d{3,}-?(?:x|\*)-?\d{3,}', - formatter=lambda value: 'x'.join(_digits_re.findall(value)), - abbreviations=[dash], - tags=['resolution'], + interlaced = frozenset({res for res in config['interlaced']}) + progressive = frozenset({res for res in config['progressive']}) + frame_rates = [re.escape(rate) for rate in config['frame_rates']] + min_ar = config['min_ar'] + max_ar = config['max_ar'] + + rebulk = Rebulk() + rebulk = rebulk.string_defaults(ignore_case=True).regex_defaults(flags=re.IGNORECASE) + + rebulk.defaults(name='screen_size', validator=seps_surround, abbreviations=[dash], + disabled=lambda context: is_disabled(context, 'screen_size')) + + frame_rate_pattern = build_or_pattern(frame_rates, name='frame_rate') + interlaced_pattern = build_or_pattern(interlaced, name='height') + progressive_pattern = build_or_pattern(progressive, name='height') + + res_pattern = r'(?:(?P\d{3,4})(?:x|\*))?' + rebulk.regex(res_pattern + interlaced_pattern + r'(?Pi)' + frame_rate_pattern + '?') + rebulk.regex(res_pattern + progressive_pattern + r'(?Pp)' + frame_rate_pattern + '?') + rebulk.regex(res_pattern + progressive_pattern + r'(?Pp)?(?:hd)') + rebulk.regex(res_pattern + progressive_pattern + r'(?Pp)?x?') + rebulk.string('4k', value='2160p') + rebulk.regex(r'(?P\d{3,4})-?(?:x|\*)-?(?P\d{3,4})', conflict_solver=lambda match, other: '__default__' if other.name == 'screen_size' else other) - rebulk.rules(ScreenSizeOnlyOne, RemoveScreenSizeConflicts) + rebulk.regex(frame_rate_pattern + '(p|fps)', name='frame_rate', + formatter=FrameRate.fromstring, disabled=lambda context: is_disabled(context, 'frame_rate')) + + rebulk.rules(PostProcessScreenSize(progressive, min_ar, max_ar), ScreenSizeOnlyOne, ResolveScreenSizeConflicts) return rebulk +class PostProcessScreenSize(Rule): + """ + Process the screen size calculating the aspect ratio if available. + + Convert to a standard notation (720p, 1080p, etc) when it's a standard resolution and + aspect ratio is valid or not available. + + It also creates an aspect_ratio match when available. + """ + consequence = AppendMatch + + def __init__(self, standard_heights, min_ar, max_ar): + super(PostProcessScreenSize, self).__init__() + self.standard_heights = standard_heights + self.min_ar = min_ar + self.max_ar = max_ar + + def when(self, matches, context): + to_append = [] + for match in matches.named('screen_size'): + if not is_disabled(context, 'frame_rate'): + for frame_rate in match.children.named('frame_rate'): + frame_rate.formatter = FrameRate.fromstring + to_append.append(frame_rate) + + values = match.children.to_dict() + if 'height' not in values: + continue + + scan_type = (values.get('scan_type') or 'p').lower() + height = values['height'] + if 'width' not in values: + match.value = '{0}{1}'.format(height, scan_type) + continue + + width = values['width'] + calculated_ar = float(width) / float(height) + + aspect_ratio = Match(match.start, match.end, input_string=match.input_string, + name='aspect_ratio', value=round(calculated_ar, 3)) + + if not is_disabled(context, 'aspect_ratio'): + to_append.append(aspect_ratio) + + if height in self.standard_heights and self.min_ar < calculated_ar < self.max_ar: + match.value = '{0}{1}'.format(height, scan_type) + else: + match.value = '{0}x{1}'.format(width, height) + + return to_append + + class ScreenSizeOnlyOne(Rule): """ - Keep a single screen_size pet filepath part. + Keep a single screen_size per filepath part. """ consequence = RemoveMatch @@ -72,15 +120,15 @@ def when(self, matches, context): for filepart in matches.markers.named('path'): screensize = list(reversed(matches.range(filepart.start, filepart.end, lambda match: match.name == 'screen_size'))) - if len(screensize) > 1: + if len(screensize) > 1 and len(set((match.value for match in screensize))) > 1: to_remove.extend(screensize[1:]) return to_remove -class RemoveScreenSizeConflicts(Rule): +class ResolveScreenSizeConflicts(Rule): """ - Remove season and episode matches which conflicts with screen_size match. + Resolve screen_size conflicts with season and episode matches. """ consequence = RemoveMatch @@ -95,14 +143,21 @@ def when(self, matches, context): if not conflicts: continue + has_neighbor = False video_profile = matches.range(screensize.end, filepart.end, lambda match: match.name == 'video_profile', 0) if video_profile and not matches.holes(screensize.end, video_profile.start, predicate=lambda h: h.value and h.value.strip(seps)): to_remove.extend(conflicts) + has_neighbor = True - date = matches.previous(screensize, lambda match: match.name == 'date', 0) - if date and not matches.holes(date.end, screensize.start, - predicate=lambda h: h.value and h.value.strip(seps)): + previous = matches.previous(screensize, index=0, predicate=( + lambda m: m.name in ('date', 'source', 'other', 'streaming_service'))) + if previous and not matches.holes(previous.end, screensize.start, + predicate=lambda h: h.value and h.value.strip(seps)): to_remove.extend(conflicts) + has_neighbor = True + + if not has_neighbor: + to_remove.append(screensize) return to_remove diff --git a/ext/guessit/rules/properties/size.py b/ext/guessit/rules/properties/size.py index 84f0303ca4..c61580c044 100644 --- a/ext/guessit/rules/properties/size.py +++ b/ext/guessit/rules/properties/size.py @@ -7,23 +7,24 @@ from rebulk import Rebulk -from ..common.validators import seps_surround from ..common import dash +from ..common.quantity import Size +from ..common.pattern import is_disabled +from ..common.validators import seps_surround -def size(): +def size(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - - def format_size(value): - """Format size using uppercase and no space.""" - return re.sub(r'(?<=\d)[.](?=[^\d])', '', value.upper()) - - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'size')) + rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) rebulk.defaults(name='size', validator=seps_surround) - rebulk.regex(r'\d+\.?[mgt]b', r'\d+\.\d+[mgt]b', formatter=format_size, tags=['release-group-prefix']) + rebulk.regex(r'\d+-?[mgt]b', r'\d+\.\d+-?[mgt]b', formatter=Size.fromstring, tags=['release-group-prefix']) return rebulk diff --git a/ext/guessit/rules/properties/source.py b/ext/guessit/rules/properties/source.py new file mode 100644 index 0000000000..ae9a7b03ae --- /dev/null +++ b/ext/guessit/rules/properties/source.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +source property +""" +import copy + +from rebulk.remodule import re + +from rebulk import AppendMatch, Rebulk, RemoveMatch, Rule + +from .audio_codec import HqConflictRule +from ..common import dash, seps +from ..common.pattern import is_disabled +from ..common.validators import seps_before, seps_after + + +def source(config): # pylint:disable=unused-argument + """ + Builder for rebulk object. + + :param config: rule configuration + :type config: dict + :return: Created Rebulk object + :rtype: Rebulk + """ + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'source')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash], private_parent=True, children=True) + rebulk.defaults(name='source', tags=['video-codec-prefix', 'streaming_service.suffix']) + + rip_prefix = '(?PRip)-?' + rip_suffix = '-?(?PRip)' + rip_optional_suffix = '(?:' + rip_suffix + ')?' + + def build_source_pattern(*patterns, **kwargs): + """Helper pattern to build source pattern.""" + prefix_format = kwargs.get('prefix') or '' + suffix_format = kwargs.get('suffix') or '' + + string_format = prefix_format + '({0})' + suffix_format + return [string_format.format(pattern) for pattern in patterns] + + def demote_other(match, other): # pylint: disable=unused-argument + """Default conflict solver with 'other' property.""" + return other if other.name == 'other' else '__default__' + + rebulk.regex(*build_source_pattern('VHS', suffix=rip_optional_suffix), + value={'source': 'VHS', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('CAM', suffix=rip_optional_suffix), + value={'source': 'Camera', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('HD-?CAM', suffix=rip_optional_suffix), + value={'source': 'HD Camera', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('TELESYNC', 'TS', suffix=rip_optional_suffix), + value={'source': 'Telesync', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('HD-?TELESYNC', 'HD-?TS', suffix=rip_optional_suffix), + value={'source': 'HD Telesync', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('WORKPRINT', 'WP'), value='Workprint') + rebulk.regex(*build_source_pattern('TELECINE', 'TC', suffix=rip_optional_suffix), + value={'source': 'Telecine', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('HD-?TELECINE', 'HD-?TC', suffix=rip_optional_suffix), + value={'source': 'HD Telecine', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('PPV', suffix=rip_optional_suffix), + value={'source': 'Pay-per-view', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('SD-?TV', suffix=rip_optional_suffix), + value={'source': 'TV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('TV', suffix=rip_suffix), # TV is too common to allow matching + value={'source': 'TV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('TV', 'SD-?TV', prefix=rip_prefix), + value={'source': 'TV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('TV-?(?=Dub)'), value='TV') + rebulk.regex(*build_source_pattern('DVB', 'PD-?TV', suffix=rip_optional_suffix), + value={'source': 'Digital TV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('DVD', suffix=rip_optional_suffix), + value={'source': 'DVD', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('DM', suffix=rip_optional_suffix), + value={'source': 'Digital Master', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('VIDEO-?TS', 'DVD-?R(?:$|(?!E))', # 'DVD-?R(?:$|^E)' => DVD-Real ... + 'DVD-?9', 'DVD-?5'), value='DVD') + + rebulk.regex(*build_source_pattern('HD-?TV', suffix=rip_optional_suffix), conflict_solver=demote_other, + value={'source': 'HDTV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('TV-?HD', suffix=rip_suffix), conflict_solver=demote_other, + value={'source': 'HDTV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('TV', suffix='-?(?PRip-?HD)'), conflict_solver=demote_other, + value={'source': 'HDTV', 'other': 'Rip'}) + + rebulk.regex(*build_source_pattern('VOD', suffix=rip_optional_suffix), + value={'source': 'Video on Demand', 'other': 'Rip'}) + + rebulk.regex(*build_source_pattern('WEB', 'WEB-?DL', suffix=rip_suffix), + value={'source': 'Web', 'other': 'Rip'}) + # WEBCap is a synonym to WEBRip, mostly used by non english + rebulk.regex(*build_source_pattern('WEB-?(?PCap)', suffix=rip_optional_suffix), + value={'source': 'Web', 'other': 'Rip', 'another': 'Rip'}) + rebulk.regex(*build_source_pattern('WEB-?DL', 'WEB-?U?HD', 'WEB', 'DL-?WEB', 'DL(?=-?Mux)'), + value={'source': 'Web'}) + + rebulk.regex(*build_source_pattern('HD-?DVD', suffix=rip_optional_suffix), + value={'source': 'HD-DVD', 'other': 'Rip'}) + + rebulk.regex(*build_source_pattern('Blu-?ray', 'BD', 'BD[59]', 'BD25', 'BD50', suffix=rip_optional_suffix), + value={'source': 'Blu-ray', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('(?PBR)-?(?=Scr(?:eener)?)', '(?PBR)-?(?=Mux)'), # BRRip + value={'source': 'Blu-ray', 'another': 'Reencoded'}) + rebulk.regex(*build_source_pattern('(?PBR)', suffix=rip_suffix), # BRRip + value={'source': 'Blu-ray', 'other': 'Rip', 'another': 'Reencoded'}) + + rebulk.regex(*build_source_pattern('Ultra-?Blu-?ray', 'Blu-?ray-?Ultra'), value='Ultra HD Blu-ray') + + rebulk.regex(*build_source_pattern('AHDTV'), value='Analog HDTV') + rebulk.regex(*build_source_pattern('UHD-?TV', suffix=rip_optional_suffix), conflict_solver=demote_other, + value={'source': 'Ultra HDTV', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('UHD', suffix=rip_suffix), conflict_solver=demote_other, + value={'source': 'Ultra HDTV', 'other': 'Rip'}) + + rebulk.regex(*build_source_pattern('DSR', 'DTH', suffix=rip_optional_suffix), + value={'source': 'Satellite', 'other': 'Rip'}) + rebulk.regex(*build_source_pattern('DSR?', 'SAT', suffix=rip_suffix), + value={'source': 'Satellite', 'other': 'Rip'}) + + rebulk.rules(ValidateSource, UltraHdBlurayRule) + + return rebulk + + +class UltraHdBlurayRule(Rule): + """ + Replace other:Ultra HD and source:Blu-ray with source:Ultra HD Blu-ray + """ + dependency = HqConflictRule + consequence = [RemoveMatch, AppendMatch] + + @classmethod + def find_ultrahd(cls, matches, start, end, index): + """Find Ultra HD match.""" + return matches.range(start, end, index=index, predicate=( + lambda m: not m.private and m.name == 'other' and m.value == 'Ultra HD' + )) + + @classmethod + def validate_range(cls, matches, start, end): + """Validate no holes or invalid matches exist in the specified range.""" + return ( + not matches.holes(start, end, predicate=lambda m: m.value.strip(seps)) and + not matches.range(start, end, predicate=( + lambda m: not m.private and ( + m.name not in ('screen_size', 'color_depth') and ( + m.name != 'other' or 'uhdbluray-neighbor' not in m.tags)))) + ) + + def when(self, matches, context): + to_remove = [] + to_append = [] + for filepart in matches.markers.named('path'): + for match in matches.range(filepart.start, filepart.end, predicate=( + lambda m: not m.private and m.name == 'source' and m.value == 'Blu-ray')): + other = self.find_ultrahd(matches, filepart.start, match.start, -1) + if not other or not self.validate_range(matches, other.end, match.start): + other = self.find_ultrahd(matches, match.end, filepart.end, 0) + if not other or not self.validate_range(matches, match.end, other.start): + if not matches.range(filepart.start, filepart.end, predicate=( + lambda m: m.name == 'screen_size' and m.value == '2160p')): + continue + + if other: + other.private = True + + new_source = copy.copy(match) + new_source.value = 'Ultra HD Blu-ray' + to_remove.append(match) + to_append.append(new_source) + + return to_remove, to_append + + +class ValidateSource(Rule): + """ + Validate source with screener property, with video_codec property or separated + """ + priority = 64 + consequence = RemoveMatch + + def when(self, matches, context): + ret = [] + for match in matches.named('source'): + match = match.initiator + if not seps_before(match) and \ + not matches.range(match.start - 1, match.start - 2, + lambda m: 'source-prefix' in m.tags): + if match.children: + ret.extend(match.children) + ret.append(match) + continue + if not seps_after(match) and \ + not matches.range(match.end, match.end + 1, + lambda m: 'source-suffix' in m.tags): + if match.children: + ret.extend(match.children) + ret.append(match) + continue + return ret diff --git a/ext/guessit/rules/properties/streaming_service.py b/ext/guessit/rules/properties/streaming_service.py index b31690d339..1302befb0b 100644 --- a/ext/guessit/rules/properties/streaming_service.py +++ b/ext/guessit/rules/properties/streaming_service.py @@ -8,64 +8,150 @@ from rebulk import Rebulk from rebulk.rules import Rule, RemoveMatch +from ..common.pattern import is_disabled from ...rules.common import seps, dash +from ...rules.common.validators import seps_before, seps_after -def streaming_service(): +def streaming_service(config): # pylint: disable=too-many-statements,unused-argument """Streaming service property. + :param config: rule configuration + :type config: dict :return: :rtype: Rebulk """ - rebulk = Rebulk().string_defaults(ignore_case=True).regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) - rebulk.defaults(name='streaming_service', tags=['format-prefix']) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'streaming_service')) + rebulk = rebulk.string_defaults(ignore_case=True).regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) + rebulk.defaults(name='streaming_service', tags=['source-prefix']) rebulk.string('AE', 'A&E', value='A&E') rebulk.string('AMBC', value='ABC') + rebulk.string('AUBC', value='ABC Australia') + rebulk.string('AJAZ', value='Al Jazeera English') rebulk.string('AMC', value='AMC') - rebulk.string('AMZN', 'AmazonPrime', value='Amazon Prime') - rebulk.regex('Amazon-Prime', value='Amazon Prime') - rebulk.string('AS', 'AdultSwim', value='Adult Swim') - rebulk.regex('Adult-Swim', value='Adult Swim') - rebulk.string('iP', 'BBCiPlayer', value='BBC iPlayer') - rebulk.regex('BBC-iPlayer', value='BBC iPlayer') + rebulk.string('AMZN', 'Amazon', value='Amazon Prime') + rebulk.regex('Amazon-?Prime', value='Amazon Prime') + rebulk.string('AS', value='Adult Swim') + rebulk.regex('Adult-?Swim', value='Adult Swim') + rebulk.string('ATK', value="America's Test Kitchen") + rebulk.string('ANPL', value='Animal Planet') + rebulk.string('ANLB', value='AnimeLab') + rebulk.string('AOL', value='AOL') + rebulk.string('ARD', value='ARD') + rebulk.string('iP', value='BBC iPlayer') + rebulk.regex('BBC-?iPlayer', value='BBC iPlayer') + rebulk.string('BRAV', value='BravoTV') + rebulk.string('CNLP', value='Canal+') + rebulk.string('CN', value='Cartoon Network') + rebulk.string('CBC', value='CBC') rebulk.string('CBS', value='CBS') - rebulk.string('CC', 'ComedyCentral', value='Comedy Central') - rebulk.regex('Comedy-Central', value='Comedy Central') - rebulk.string('CR', 'CrunchyRoll', value='Crunchy Roll') - rebulk.regex('Crunchy-Roll', value='Crunchy Roll') - rebulk.string('CW', 'TheCW', value='The CW') - rebulk.regex('The-CW', value='The CW') + rebulk.string('CNBC', value='CNBC') + rebulk.string('CC', value='Comedy Central') + rebulk.string('4OD', value='Channel 4') + rebulk.string('CHGD', value='CHRGD') + rebulk.string('CMAX', value='Cinemax') + rebulk.string('CMT', value='Country Music Television') + rebulk.regex('Comedy-?Central', value='Comedy Central') + rebulk.string('CCGC', value='Comedians in Cars Getting Coffee') + rebulk.string('CR', value='Crunchy Roll') + rebulk.string('CRKL', value='Crackle') + rebulk.regex('Crunchy-?Roll', value='Crunchy Roll') + rebulk.string('CSPN', value='CSpan') + rebulk.string('CTV', value='CTV') + rebulk.string('CUR', value='CuriosityStream') + rebulk.string('CWS', value='CWSeed') + rebulk.string('DSKI', value='Daisuki') + rebulk.string('DHF', value='Deadhouse Films') + rebulk.string('DDY', value='Digiturk Diledigin Yerde') rebulk.string('DISC', 'Discovery', value='Discovery') - rebulk.string('DIY', value='DIY Network') rebulk.string('DSNY', 'Disney', value='Disney') - rebulk.string('EPIX', 'ePix', value='ePix') - rebulk.string('HBO', 'HBOGo', value='HBO Go') - rebulk.regex('HBO-Go', value='HBO Go') + rebulk.string('DIY', value='DIY Network') + rebulk.string('DOCC', value='Doc Club') + rebulk.string('DPLY', value='DPlay') + rebulk.string('ETV', value='E!') + rebulk.string('EPIX', value='ePix') + rebulk.string('ETTV', value='El Trece') + rebulk.string('ESPN', value='ESPN') + rebulk.string('ESQ', value='Esquire') + rebulk.string('FAM', value='Family') + rebulk.string('FJR', value='Family Jr') + rebulk.string('FOOD', value='Food Network') + rebulk.string('FOX', value='Fox') + rebulk.string('FREE', value='Freeform') + rebulk.string('FYI', value='FYI Network') + rebulk.string('GLBL', value='Global') + rebulk.string('GLOB', value='GloboSat Play') + rebulk.string('HLMK', value='Hallmark') + rebulk.string('HBO', value='HBO Go') + rebulk.regex('HBO-?Go', value='HBO Go') + rebulk.string('HGTV', value='HGTV') rebulk.string('HIST', 'History', value='History') + rebulk.string('HULU', value='Hulu') rebulk.string('ID', value='Investigation Discovery') - rebulk.string('IFC', 'IFC', value='IFC') - rebulk.string('PBS', 'PBS', value='PBS') - rebulk.string('NATG', 'NationalGeographic', value='National Geographic') - rebulk.regex('National-Geographic', value='National Geographic') - rebulk.string('NBA', 'NBATV', value='NBA TV') - rebulk.regex('NBA-TV', value='NBA TV') + rebulk.string('IFC', value='IFC') + rebulk.string('iTunes', 'iT', value='iTunes') + rebulk.string('ITV', value='ITV') + rebulk.string('KNOW', value='Knowledge Network') + rebulk.string('LIFE', value='Lifetime') + rebulk.string('MTOD', value='Motor Trend OnDemand') + rebulk.string('MNBC', value='MSNBC') + rebulk.string('MTV', value='MTV') + rebulk.string('NATG', value='National Geographic') + rebulk.regex('National-?Geographic', value='National Geographic') + rebulk.string('NBA', value='NBA TV') + rebulk.regex('NBA-?TV', value='NBA TV') rebulk.string('NBC', value='NBC') + rebulk.string('NF', 'Netflix', value='Netflix') rebulk.string('NFL', value='NFL') + rebulk.string('NFLN', value='NFL Now') + rebulk.string('GC', value='NHL GameCenter') rebulk.string('NICK', 'Nickelodeon', value='Nickelodeon') - rebulk.string('NF', 'Netflix', value='Netflix') - rebulk.string('iTunes', value='iTunes') - rebulk.string('RTE', value='RTÉ One') + rebulk.string('NRK', value='Norsk Rikskringkasting') + rebulk.string('PBS', value='PBS') + rebulk.string('PBSK', value='PBS Kids') + rebulk.string('PSN', value='Playstation Network') + rebulk.string('PLUZ', value='Pluzz') + rebulk.string('RTE', value='RTE One') + rebulk.string('SBS', value='SBS (AU)') rebulk.string('SESO', 'SeeSo', value='SeeSo') - rebulk.string('SPKE', 'SpikeTV', 'Spike TV', value='Spike TV') - rebulk.string('SYFY', 'Syfy', value='Syfy') - rebulk.string('TFOU', 'TFou', value='TFou') + rebulk.string('SHMI', value='Shomi') + rebulk.string('SPIK', value='Spike') + rebulk.string('SPKE', value='Spike TV') + rebulk.regex('Spike-?TV', value='Spike TV') + rebulk.string('SNET', value='Sportsnet') + rebulk.string('SPRT', value='Sprout') + rebulk.string('STAN', value='Stan') + rebulk.string('STZ', value='Starz') + rebulk.string('SVT', value='Sveriges Television') + rebulk.string('SWER', value='SwearNet') + rebulk.string('SYFY', value='Syfy') + rebulk.string('TBS', value='TBS') + rebulk.string('TFOU', value='TFou') + rebulk.string('CW', value='The CW') + rebulk.regex('The-?CW', value='The CW') rebulk.string('TLC', value='TLC') + rebulk.string('TUBI', value='TubiTV') rebulk.string('TV3', value='TV3 Ireland') rebulk.string('TV4', value='TV4 Sweeden') - rebulk.string('TVL', 'TVLand', 'TV Land', value='TV Land') + rebulk.string('TVL', value='TV Land') + rebulk.regex('TV-?Land', value='TV Land') rebulk.string('UFC', value='UFC') + rebulk.string('UKTV', value='UKTV') + rebulk.string('UNIV', value='Univision') rebulk.string('USAN', value='USA Network') + rebulk.string('VLCT', value='Velocity') + rebulk.string('VH1', value='VH1') + rebulk.string('VICE', value='Viceland') + rebulk.string('VMEO', value='Vimeo') + rebulk.string('VRV', value='VRV') + rebulk.string('WNET', value='W Network') + rebulk.string('WME', value='WatchMe') + rebulk.string('WWEN', value='WWE Network') + rebulk.string('XBOX', value='Xbox Video') + rebulk.string('YHOO', value='Yahoo') + rebulk.string('RED', value='YouTube Red') + rebulk.string('ZDF', value='ZDF') rebulk.rules(ValidateStreamingService) @@ -79,7 +165,7 @@ class ValidateStreamingService(Rule): consequence = RemoveMatch def when(self, matches, context): - """Streaming service is always before format. + """Streaming service is always before source. :param matches: :type matches: rebulk.match.Matches @@ -93,16 +179,20 @@ def when(self, matches, context): previous_match = matches.previous(service, lambda match: 'streaming_service.prefix' in match.tags, 0) has_other = service.initiator and service.initiator.children.named('other') - if not has_other and \ - (not next_match or matches.holes(service.end, next_match.start, - predicate=lambda match: match.value.strip(seps))) and \ - (not previous_match or matches.holes(previous_match.end, service.start, - predicate=lambda match: match.value.strip(seps))): - to_remove.append(service) - continue + if not has_other: + if (not next_match or + matches.holes(service.end, next_match.start, + predicate=lambda match: match.value.strip(seps)) or + not seps_before(service)): + if (not previous_match or + matches.holes(previous_match.end, service.start, + predicate=lambda match: match.value.strip(seps)) or + not seps_after(service)): + to_remove.append(service) + continue if service.value == 'Comedy Central': - # Current match is a valid streaming service, removing invalid closed caption (CC) matches - to_remove.extend(matches.named('other', predicate=lambda match: match.value == 'CC')) + # Current match is a valid streaming service, removing invalid Criterion Collection (CC) matches + to_remove.extend(matches.named('edition', predicate=lambda match: match.value == 'Criterion')) return to_remove diff --git a/ext/guessit/rules/properties/title.py b/ext/guessit/rules/properties/title.py index e87ceb6dea..798df1e2aa 100644 --- a/ext/guessit/rules/properties/title.py +++ b/ext/guessit/rules/properties/title.py @@ -13,16 +13,21 @@ from ..common.comparators import marker_sorted from ..common.expected import build_expected_function from ..common.formatters import cleanup, reorder_title +from ..common.pattern import is_disabled from ..common.validators import seps_surround -def title(): +def title(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().rules(TitleFromPosition, PreferTitleWithYear) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'title')) + rebulk.rules(TitleFromPosition, PreferTitleWithYear) expected_title = build_expected_function('expected_title') @@ -94,7 +99,7 @@ def is_ignored(self, match): Full word language and countries won't be ignored if they are uppercase. """ - return not (len(match) > 3 and match.raw.isupper()) and match.name in ['language', 'country', 'episode_details'] + return not (len(match) > 3 and match.raw.isupper()) and match.name in ('language', 'country', 'episode_details') def should_keep(self, match, to_keep, matches, filepart, hole, starting): """ @@ -114,7 +119,7 @@ def should_keep(self, match, to_keep, matches, filepart, hole, starting): :return: :rtype: """ - if match.name in ['language', 'country']: + if match.name in ('language', 'country'): # Keep language if exactly matching the hole. if len(hole.value) == len(match.raw): return True @@ -127,7 +132,7 @@ def should_keep(self, match, to_keep, matches, filepart, hole, starting): lambda c_match: c_match.name == match.name and c_match not in to_keep)) - if not other_languages: + if not other_languages and (not starting or len(match.raw) <= 3): return True return False @@ -145,7 +150,7 @@ def should_remove(self, match, matches, filepart, hole, context): return match.start >= hole.start and match.end <= hole.end return True - def check_titles_in_filepart(self, filepart, matches, context): + def check_titles_in_filepart(self, filepart, matches, context): # pylint:disable=inconsistent-return-statements """ Find title in filepart (ignoring language) """ @@ -154,12 +159,11 @@ def check_titles_in_filepart(self, filepart, matches, context): holes = matches.holes(start, end + 1, formatter=formatters(cleanup, reorder_title), ignore=self.is_ignored, - predicate=lambda hole: hole.value) + predicate=lambda m: m.value) holes = self.holes_process(holes, matches) for hole in holes: - # pylint:disable=cell-var-from-loop if not hole or (self.hole_filter and not self.hole_filter(hole, matches)): continue @@ -170,8 +174,8 @@ def check_titles_in_filepart(self, filepart, matches, context): if ignored_matches: for ignored_match in reversed(ignored_matches): - # pylint:disable=undefined-loop-variable - trailing = matches.chain_before(hole.end, seps, predicate=lambda match: match == ignored_match) + # pylint:disable=undefined-loop-variable, cell-var-from-loop + trailing = matches.chain_before(hole.end, seps, predicate=lambda m: m == ignored_match) if trailing: should_keep = self.should_keep(ignored_match, to_keep, matches, filepart, hole, False) if should_keep: @@ -188,7 +192,7 @@ def check_titles_in_filepart(self, filepart, matches, context): for ignored_match in ignored_matches: if ignored_match not in to_keep: starting = matches.chain_after(hole.start, seps, - predicate=lambda match: match == ignored_match) + predicate=lambda m: m == ignored_match) if starting: should_keep = self.should_keep(ignored_match, to_keep, matches, filepart, hole, True) if should_keep: @@ -214,7 +218,7 @@ def check_titles_in_filepart(self, filepart, matches, context): hole.tags = self.match_tags if self.alternative_match_name: # Split and keep values that can be a title - titles = hole.split(title_seps, lambda match: match.value) + titles = hole.split(title_seps, lambda m: m.value) for title_match in list(titles[1:]): previous_title = titles[titles.index(title_match) - 1] separator = matches.input_string[previous_title.end:title_match.start] @@ -231,14 +235,15 @@ def check_titles_in_filepart(self, filepart, matches, context): return titles, to_remove def when(self, matches, context): + ret = [] + to_remove = [] + if matches.named(self.match_name, lambda match: 'expected' in match.tags): - return + return ret, to_remove fileparts = [filepart for filepart in list(marker_sorted(matches.markers.named('path'), matches)) if not self.filepart_filter or self.filepart_filter(filepart, matches)] - to_remove = [] - # Priorize fileparts containing the year years_fileparts = [] for filepart in fileparts: @@ -246,7 +251,6 @@ def when(self, matches, context): if year_match: years_fileparts.append(filepart) - ret = [] for filepart in fileparts: try: years_fileparts.remove(filepart) @@ -282,6 +286,9 @@ class TitleFromPosition(TitleBaseRule): def __init__(self): super(TitleFromPosition, self).__init__('title', ['title'], 'alternative_title') + def enabled(self, context): + return not is_disabled(context, 'alternative_title') + class PreferTitleWithYear(Rule): """ @@ -302,7 +309,7 @@ def when(self, matches, context): if filepart: year_match = matches.range(filepart.start, filepart.end, lambda match: match.name == 'year', 0) if year_match: - group = matches.markers.at_match(year_match, lambda group: group.name == 'group') + group = matches.markers.at_match(year_match, lambda m: m.name == 'group') if group: with_year_in_group.append(title_match) else: diff --git a/ext/guessit/rules/properties/type.py b/ext/guessit/rules/properties/type.py index 6d798b643b..6a2877ef9e 100644 --- a/ext/guessit/rules/properties/type.py +++ b/ext/guessit/rules/properties/type.py @@ -6,6 +6,7 @@ from rebulk import CustomRule, Rebulk, POST_PROCESS from rebulk.match import Match +from ..common.pattern import is_disabled from ...rules.processors import Processors @@ -19,13 +20,19 @@ def _type(matches, value): matches.append(Match(len(matches.input_string), len(matches.input_string), name='type', value=value)) -def type_(): +def type_(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - return Rebulk().rules(TypeProcessor) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'type')) + rebulk = rebulk.rules(TypeProcessor) + + return rebulk class TypeProcessor(CustomRule): @@ -45,9 +52,10 @@ def when(self, matches, context): # pylint:disable=too-many-return-statements episode = matches.named('episode') season = matches.named('season') + absolute_episode = matches.named('absolute_episode') episode_details = matches.named('episode_details') - if episode or season or episode_details: + if episode or season or episode_details or absolute_episode: return 'episode' film = matches.named('film') diff --git a/ext/guessit/rules/properties/video_codec.py b/ext/guessit/rules/properties/video_codec.py index 86661469cc..1f8f75d371 100644 --- a/ext/guessit/rules/properties/video_codec.py +++ b/ext/guessit/rules/properties/video_codec.py @@ -8,42 +8,62 @@ from rebulk import Rebulk, Rule, RemoveMatch from ..common import dash +from ..common.pattern import is_disabled from ..common.validators import seps_after, seps_before, seps_surround -def video_codec(): +def video_codec(config): # pylint:disable=unused-argument """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).string_defaults(ignore_case=True) - rebulk.defaults(name="video_codec", tags=['format-suffix', 'streaming_service.suffix']) - - rebulk.regex(r"Rv\d{2}", value="Real") - rebulk.regex("Mpeg2", value="Mpeg2") - rebulk.regex("DVDivX", "DivX", value="DivX") - rebulk.regex("XviD", value="XviD") - rebulk.regex("[hx]-?264(?:-?AVC(HD)?)?", "MPEG-?4(?:-?AVC(HD)?)", "AVC(?:HD)?", value="h264") - rebulk.regex("[hx]-?265(?:-?HEVC)?", "HEVC", value="h265") - rebulk.regex('(?Phevc)(?P10)', value={'video_codec': 'h265', 'video_profile': '10bit'}, + rebulk = Rebulk() + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).string_defaults(ignore_case=True) + rebulk.defaults(name="video_codec", + tags=['source-suffix', 'streaming_service.suffix'], + disabled=lambda context: is_disabled(context, 'video_codec')) + + rebulk.regex(r'Rv\d{2}', value='RealVideo') + rebulk.regex('Mpe?g-?2', '[hx]-?262', value='MPEG-2') + rebulk.string("DVDivX", "DivX", value="DivX") + rebulk.string('XviD', value='Xvid') + rebulk.regex('VC-?1', value='VC-1') + rebulk.string('VP7', value='VP7') + rebulk.string('VP8', 'VP80', value='VP8') + rebulk.string('VP9', value='VP9') + rebulk.regex('[hx]-?263', value='H.263') + rebulk.regex('[hx]-?264(?:-?AVC(?:HD)?)?(?:-?SC)?', 'MPEG-?4(?:-?AVC(?:HD)?)', 'AVC(?:HD)?(?:-?SC)?', value='H.264') + rebulk.regex('[hx]-?265(?:-?HEVC)?', 'HEVC', value='H.265') + rebulk.regex('(?Phevc)(?P10)', value={'video_codec': 'H.265', 'color_depth': '10-bit'}, tags=['video-codec-suffix'], children=True) # http://blog.mediacoderhq.com/h264-profiles-and-levels/ # http://fr.wikipedia.org/wiki/H.264 - rebulk.defaults(name="video_profile", validator=seps_surround) - - rebulk.regex('10.?bits?', 'Hi10P?', 'YUV420P10', value='10bit') - rebulk.regex('8.?bits?', value='8bit') - - rebulk.string('BP', value='BP', tags='video_profile.rule') - rebulk.string('XP', 'EP', value='XP', tags='video_profile.rule') - rebulk.string('MP', value='MP', tags='video_profile.rule') - rebulk.string('HP', 'HiP', value='HP', tags='video_profile.rule') - rebulk.regex('Hi422P', value='Hi422P', tags='video_profile.rule') - rebulk.regex('Hi444PP', value='Hi444PP', tags='video_profile.rule') - - rebulk.string('DXVA', value='DXVA', name='video_api') + rebulk.defaults(name="video_profile", + validator=seps_surround, + disabled=lambda context: is_disabled(context, 'video_profile')) + + rebulk.string('BP', value='Baseline', tags='video_profile.rule') + rebulk.string('XP', 'EP', value='Extended', tags='video_profile.rule') + rebulk.string('MP', value='Main', tags='video_profile.rule') + rebulk.string('HP', 'HiP', value='High', tags='video_profile.rule') + rebulk.regex('Hi422P', value='High 4:2:2') + rebulk.regex('Hi444PP', value='High 4:4:4 Predictive') + rebulk.regex('Hi10P?', value='High 10') # no profile validation is required + + rebulk.string('DXVA', value='DXVA', name='video_api', + disabled=lambda context: is_disabled(context, 'video_api')) + + rebulk.defaults(name='color_depth', + validator=seps_surround, + disabled=lambda context: is_disabled(context, 'color_depth')) + rebulk.regex('12.?bits?', value='12-bit') + rebulk.regex('10.?bits?', 'YUV420P10', 'Hi10P?', value='10-bit') + rebulk.regex('8.?bits?', value='8-bit') rebulk.rules(ValidateVideoCodec, VideoProfileRule) @@ -52,11 +72,14 @@ def video_codec(): class ValidateVideoCodec(Rule): """ - Validate video_codec with format property or separated + Validate video_codec with source property or separated """ priority = 64 consequence = RemoveMatch + def enabled(self, context): + return not is_disabled(context, 'video_codec') + def when(self, matches, context): ret = [] for codec in matches.named('video_codec'): @@ -77,6 +100,9 @@ class VideoProfileRule(Rule): """ consequence = RemoveMatch + def enabled(self, context): + return not is_disabled(context, 'video_profile') + def when(self, matches, context): profile_list = matches.named('video_profile', lambda match: 'video_profile.rule' in match.tags) ret = [] diff --git a/ext/guessit/rules/properties/website.py b/ext/guessit/rules/properties/website.py index afca57abba..6df16be651 100644 --- a/ext/guessit/rules/properties/website.py +++ b/ext/guessit/rules/properties/website.py @@ -9,28 +9,32 @@ from rebulk import Rebulk, Rule, RemoveMatch from ..common import seps from ..common.formatters import cleanup +from ..common.pattern import is_disabled from ..common.validators import seps_surround from ...reutils import build_or_pattern -def website(): +def website(config): """ Builder for rebulk object. + + :param config: rule configuration + :type config: dict :return: Created Rebulk object :rtype: Rebulk """ - rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE).string_defaults(ignore_case=True) + rebulk = Rebulk(disabled=lambda context: is_disabled(context, 'website')) + rebulk = rebulk.regex_defaults(flags=re.IGNORECASE).string_defaults(ignore_case=True) rebulk.defaults(name="website") tlds = [l.strip().decode('utf-8') for l in resource_stream('guessit', 'tlds-alpha-by-domain.txt').readlines() if b'--' not in l][1:] # All registered domain extension - safe_tlds = ['com', 'org', 'net'] # For sure a website extension - safe_subdomains = ['www'] # For sure a website subdomain - safe_prefix = ['co', 'com', 'org', 'net'] # Those words before a tlds are sure - - website_prefixes = ['from'] + safe_tlds = config['safe_tlds'] # For sure a website extension + safe_subdomains = config['safe_subdomains'] # For sure a website subdomain + safe_prefix = config['safe_prefixes'] # Those words before a tlds are sure + website_prefixes = config['prefixes'] rebulk.regex(r'(?:[^a-z0-9]|^)((?:'+build_or_pattern(safe_subdomains) + r'\.)+(?:[a-z-]+\.)+(?:'+build_or_pattern(tlds) + diff --git a/ext/guessit/test/enable_disable_properties.yml b/ext/guessit/test/enable_disable_properties.yml new file mode 100644 index 0000000000..e330e37db0 --- /dev/null +++ b/ext/guessit/test/enable_disable_properties.yml @@ -0,0 +1,335 @@ +? vorbis +: options: --exclude audio_codec + -audio_codec: Vorbis + +? DTS-ES +: options: --exclude audio_profile + audio_codec: DTS + -audio_profile: Extended Surround + +? DTS.ES +: options: --include audio_codec + audio_codec: DTS + -audio_profile: Extended Surround + +? 5.1 +? 5ch +? 6ch +: options: --exclude audio_channels + -audio_channels: '5.1' + +? Movie Title-x01-Other Title.mkv +? Movie Title-x01-Other Title +? directory/Movie Title-x01-Other Title/file.mkv +: options: --exclude bonus + -bonus: 1 + -bonus_title: Other Title + +? Title-x02-Bonus Title.mkv +: options: --include bonus + bonus: 2 + -bonus_title: Other Title + +? cd 1of3 +: options: --exclude cd + -cd: 1 + -cd_count: 3 + +? This.Is.Us +: options: --exclude country + title: This Is Us + -country: US + +? 2015.01.31 +: options: --exclude date + year: 2015 + -date: 2015-01-31 + +? Something 2 mar 2013) +: options: --exclude date + -date: 2013-03-02 + +? 2012 2009 S01E02 2015 # If no year is marked, the second one is guessed. +: options: --exclude year + -year: 2009 + +? Director's cut +: options: --exclude edition + -edition: Director's Cut + +? 2x5 +? 2X5 +? 02x05 +? 2X05 +? 02x5 +? S02E05 +? s02e05 +? s02e5 +? s2e05 +? s02ep05 +? s2EP5 +: options: --exclude season + -season: 2 + -episode: 5 + +? 2x6 +? 2X6 +? 02x06 +? 2X06 +? 02x6 +? S02E06 +? s02e06 +? s02e6 +? s2e06 +? s02ep06 +? s2EP6 +: options: --exclude episode + -season: 2 + -episode: 6 + +? serie Season 2 other +: options: --exclude season + -season: 2 + +? Some Dummy Directory/S02 Some Series/E01-Episode title.mkv +: options: --exclude episode_title + -episode_title: Episode title + season: 2 + episode: 1 + +? Another Dummy Directory/S02 Some Series/E01-Episode title.mkv +: options: --include season --include episode + -episode_title: Episode title + season: 2 + episode: 1 + +# pattern contains season and episode: it wont work enabling only one +? Some Series S03E01E02 +: options: --include episode + -season: 3 + -episode: [1, 2] + +# pattern contains season and episode: it wont work enabling only one +? Another Series S04E01E02 +: options: --include season + -season: 4 + -episode: [1, 2] + +? Show.Name.Season.4.Episode.1 +: options: --include episode + -season: 4 + episode: 1 + +? Another.Show.Name.Season.4.Episode.1 +: options: --include season + season: 4 + -episode: 1 + +? Some Series S01 02 03 +: options: --exclude season + -season: [1, 2, 3] + +? Some Series E01 02 04 +: options: --exclude episode + -episode: [1, 2, 4] + +? A very special episode s06 special +: options: -t episode --exclude episode_details + season: 6 + -episode_details: Special + +? S01D02.3-5-GROUP +: options: --exclude disc + -season: 1 + -disc: [2, 3, 4, 5] + -episode: [2, 3, 4, 5] + +? S01D02&4-6&8 +: options: --exclude season + -season: 1 + -disc: [2, 4, 5, 6, 8] + -episode: [2, 4, 5, 6, 8] + +? Film Title-f01-Series Title.mkv +: options: --exclude film + -film: 1 + -film_title: Film Title + +? Another Film Title-f01-Series Title.mkv +: options: --exclude film_title + film: 1 + -film_title: Film Title + +? English +? .ENG. +: options: --exclude language + -language: English + +? SubFrench +? SubFr +? STFr +: options: --exclude subtitle_language + -language: French + -subtitle_language: French + +? ST.FR +: options: --exclude subtitle_language + language: French + -subtitle_language: French + +? ENG.-.sub.FR +? ENG.-.FR Sub +: options: --include language + language: [English, French] + -subtitle_language: French + +? ENG.-.SubFR +: options: --include language + language: English + -subtitle_language: French + +? ENG.-.FRSUB +? ENG.-.FRSUBS +? ENG.-.FR-SUBS +: options: --include subtitle_language + -language: English + subtitle_language: French + +? DVD.Real.XViD +? DVD.fix.XViD +: options: --exclude other + -other: Proper + -proper_count: 1 + +? Part 3 +? Part III +? Part Three +? Part Trois +? Part3 +: options: --exclude part + -part: 3 + +? Some.Title.XViD-by.Artik[SEDG].avi +: options: --exclude release_group + -release_group: Artik[SEDG] + +? "[ABC] Some.Title.avi" +? some/folder/[ABC]Some.Title.avi +: options: --exclude release_group + -release_group: ABC + +? 360p +? 360px +? "360" +? +500x360 +: options: --exclude screen_size + -screen_size: 360p + +? 640x360 +: options: --exclude aspect_ratio + screen_size: 360p + -aspect_ratio: 1.778 + +? 8196x4320 +: options: --exclude screen_size + -screen_size: 4320p + -aspect_ratio: 1.897 + +? 4.3gb +: options: --exclude size + -size: 4.3GB + +? VhS_rip +? VHS.RIP +: options: --exclude source + -source: VHS + -other: Rip + +? DVD.RIP +: options: --include other + -source: DVD + -other: Rip + +? Title Only.avi +: options: --exclude title + -title: Title Only + +? h265 +? x265 +? h.265 +? x.265 +? hevc +: options: --exclude video_codec + -video_codec: H.265 + +? hevc10 +: options: --include color_depth + -video_codec: H.265 + -color_depth: 10-bit + +? HEVC-YUV420P10 +: options: --include color_depth + -video_codec: H.265 + color_depth: 10-bit + +? h265-HP +: options: --exclude video_profile + video_codec: H.265 + -video_profile: High + +? House.of.Cards.2013.S02E03.1080p.NF.WEBRip.DD5.1.x264-NTb.mkv +? House.of.Cards.2013.S02E03.1080p.Netflix.WEBRip.DD5.1.x264-NTb.mkv +: options: --exclude streaming_service + -streaming_service: Netflix + +? wawa.co.uk +: options: --exclude website + -website: wawa.co.uk + +? movie.mkv +: options: --exclude mimetype + -mimetype: video/x-matroska + +? another movie.mkv +: options: --exclude container + -container: mkv + +? series s02e01 +: options: --exclude type + -type: episode + +? series s02e01 +: options: --exclude type + -type: episode + +? Hotel.Hell.S01E01.720p.DD5.1.448kbps-ALANiS +: options: --exclude audio_bit_rate + -audio_bit_rate: 448Kbps + +? Katy Perry - Pepsi & Billboard Summer Beats Concert Series 2012 1080i HDTV 20 Mbps DD2.0 MPEG2-TrollHD.ts +: options: --exclude video_bit_rate + -video_bit_rate: 20Mbps + +? "[Figmentos] Monster 34 - At the End of Darkness [781219F1].mkv" +: options: --exclude crc32 + -crc32: 781219F1 + +? 1080p25 +: options: --exclude frame_rate + screen_size: 1080p + -frame_rate: 25fps + +? 1080p25 +: options: --exclude screen_size + -screen_size: 1080p + -frame_rate: 25fps + +? 1080p25 +: options: --include frame_rate + -screen_size: 1080p + -frame_rate: 25fps + +? 1080p 30fps +: options: --exclude screen_size + -screen_size: 1080p + frame_rate: 30fps diff --git a/ext/guessit/test/episodes.yml b/ext/guessit/test/episodes.yml index 3b563709a1..97320c8092 100644 --- a/ext/guessit/test/episodes.yml +++ b/ext/guessit/test/episodes.yml @@ -6,8 +6,8 @@ season: 2 episode: 5 episode_title: Vaginatown - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: 0TV container: avi @@ -18,8 +18,8 @@ episode_title: Hello, Bandit language: English subtitle_language: French - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: AlFleNi-TeaM website: tvu.org.ru container: avi @@ -29,8 +29,8 @@ season: 1 episode: 3 episode_title: Right Place, Wrong Time - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: NoTV ? Series/Duckman/Duckman - S1E13 Joking The Chicken (unedited).avi @@ -89,7 +89,7 @@ episode: 2 episode_title: 65 Million Years Off language: english - format: DVD + source: DVD other: Complete ? series/Psych/Psych S02 Season 2 Complete English DVD/Psych.S02E03.Psy.Vs.Psy.Français.srt @@ -97,7 +97,7 @@ season: 2 episode: 3 episode_title: Psy Vs Psy - format: DVD + source: DVD language: English subtitle_language: French other: Complete @@ -107,7 +107,7 @@ season: 1 episode: 1 episode_title: Toutes Couleurs Unies - format: DVB + source: Digital TV release_group: Kceb language: french website: tvu.org.ru @@ -132,15 +132,16 @@ episode_title: 18-5-4 language: english subtitle_language: french - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: AlFleNi-TeaM website: tvu.org.ru ? series/__ Incomplete __/Dr Slump (Catalan)/Dr._Slump_-_003_DVB-Rip_Catalan_by_kelf.avi : title: Dr Slump episode: 3 - format: DVB + source: Digital TV + other: Rip language: catalan # Disabling this test because it just doesn't looks like a serie ... @@ -166,7 +167,8 @@ season: 4 episode: 7 episode_title: Cherokee Hair Tampons - format: DVD + source: DVD + other: Rip website: tvu.org.ru ? Series/Kaamelott/Kaamelott - Livre V - Ep 23 - Le Forfait.avi @@ -192,16 +194,18 @@ episode_format: Minisode episode: 1 episode_title: Good Cop Bad Cop - format: WEBRip - video_codec: XviD + source: Web + other: Rip + video_codec: Xvid ? Series/My Name Is Earl/My.Name.Is.Earl.S01Extras.-.Bad.Karma.DVDRip.XviD.avi : title: My Name Is Earl season: 1 episode_title: Extras - Bad Karma - format: DVD + source: DVD + other: Rip episode_details: Extras - video_codec: XviD + video_codec: Xvid ? series/Freaks And Geeks/Season 1/Episode 4 - Kim Kelly Is My Friend-eng(1).srt : title: Freaks And Geeks @@ -256,7 +260,7 @@ : title: new girl season: 1 episode: 17 - format: HDTV + source: HDTV release_group: lol ? Kaamelott - 5x44x45x46x47x48x49x50.avi @@ -296,8 +300,8 @@ season: 1 episode: 3 episode_title: Health Care - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: LOL ? /Volumes/data-1/Series/Futurama/Season 3/Futurama_-_S03_DVD_Bonus_-_Deleted_Scenes_Part_3.ogm @@ -306,15 +310,15 @@ part: 3 other: Bonus episode_title: Deleted Scenes - format: DVD + source: DVD ? Ben.and.Kate.S01E02.720p.HDTV.X264-DIMENSION.mkv : title: Ben and Kate season: 1 episode: 2 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: DIMENSION ? /volume1/TV Series/Drawn Together/Season 1/Drawn Together 1x04 Requiem for a Reality Show.avi @@ -328,10 +332,10 @@ season: 5 episode: 6 screen_size: 720p - format: WEB-DL + source: Web audio_channels: "5.1" - audio_codec: AC3 - video_codec: h264 + audio_codec: Dolby Digital + video_codec: H.264 release_group: CtrlHD ? /media/bdc64bfe-e36f-4af8-b550-e6fd2dfaa507/TV_Shows/Doctor Who (2005)/Saison 6/Doctor Who (2005) - S06E13 - The Wedding of River Song.mkv @@ -354,10 +358,10 @@ episode: 3 episode_title: Adventures in Baby-Getting screen_size: 720p - format: WEB-DL + source: Web audio_channels: "5.1" - audio_codec: AC3 - video_codec: h264 + audio_codec: Dolby Digital + video_codec: H.264 release_group: CtrlHD ? /home/disaster/Videos/TV/Merlin/merlin_2008.5x02.arthurs_bane_part_two.repack.720p_hdtv_x264-fov.mkv @@ -367,8 +371,8 @@ part: 2 episode_title: arthurs bane screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: fov year: 2008 other: Proper @@ -386,28 +390,28 @@ episode: 18 episode_title: Sheltered screen_size: 720p - format: WEB-DL + source: Web audio_channels: "5.1" - audio_codec: AC3 - video_codec: h264 + audio_codec: Dolby Digital + video_codec: H.264 ? Game of Thrones S03E06 1080i HDTV DD5.1 MPEG2-TrollHD.ts : title: Game of Thrones season: 3 episode: 6 screen_size: 1080i - format: HDTV + source: HDTV audio_channels: "5.1" - audio_codec: AC3 - video_codec: Mpeg2 + audio_codec: Dolby Digital + video_codec: MPEG-2 release_group: TrollHD ? gossip.girl.s01e18.hdtv.xvid-2hd.eng.srt : title: gossip girl season: 1 episode: 18 - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: 2hd subtitle_language: english @@ -416,8 +420,8 @@ season: 3 episode: [1, 2] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: IMMERSE ? Wheels.S03E01-02.720p.HDTV.x264-IMMERSE.mkv @@ -425,8 +429,8 @@ season: 3 episode: [1, 2] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: IMMERSE ? Wheels.S03E01-E02.720p.HDTV.x264-IMMERSE.mkv @@ -434,8 +438,8 @@ season: 3 episode: [1, 2] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: IMMERSE ? Wheels.S03E01-04.720p.HDTV.x264-IMMERSE.mkv @@ -443,8 +447,8 @@ season: 3 episode: [1, 2, 3, 4] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: IMMERSE ? Marvels.Agents.of.S.H.I.E.L.D-S01E06.720p.HDTV.X264-DIMENSION.mkv @@ -452,8 +456,8 @@ season: 1 episode: 6 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: DIMENSION ? Marvels.Agents.of.S.H.I.E.L.D.S01E06.720p.HDTV.X264-DIMENSION.mkv @@ -461,8 +465,8 @@ season: 1 episode: 6 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: DIMENSION ? Marvels.Agents.of.S.H.I.E.L.D..S01E06.720p.HDTV.X264-DIMENSION.mkv @@ -470,8 +474,8 @@ season: 1 episode: 6 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: DIMENSION ? Series/Friday Night Lights/Season 1/Friday Night Lights S01E19 - Ch-Ch-Ch-Ch-Changes.avi @@ -483,22 +487,24 @@ ? Dexter Saison VII FRENCH.BDRip.XviD-MiND.nfo : title: Dexter season: 7 - video_codec: XviD + video_codec: Xvid language: French - format: BluRay + source: Blu-ray + other: Rip release_group: MiND ? Dexter Saison sept FRENCH.BDRip.XviD-MiND.nfo : title: Dexter season: 7 - video_codec: XviD + video_codec: Xvid language: French - format: BluRay + source: Blu-ray + other: Rip release_group: MiND ? "Pokémon S16 - E29 - 1280*720 HDTV VF.mkv" : title: Pokémon - format: HDTV + source: HDTV language: French season: 16 episode: 29 @@ -506,20 +512,20 @@ ? One.Piece.E576.VOSTFR.720p.HDTV.x264-MARINE-FORD.mkv : episode: 576 - video_codec: h264 - format: HDTV + video_codec: H.264 + source: HDTV title: One Piece release_group: MARINE-FORD subtitle_language: French screen_size: 720p ? Dexter.S08E12.FINAL.MULTi.1080p.BluRay.x264-MiND.mkv -: video_codec: h264 +: video_codec: H.264 episode: 12 season: 8 - format: BluRay + source: Blu-ray title: Dexter - other: FINAL + episode_details: Final language: Multiple languages release_group: MiND screen_size: 1080p @@ -536,30 +542,30 @@ screen_size: 720p season: 1 title: Falling Skies - video_codec: h264 - other: HDLight + video_codec: H.264 + other: Micro HD ? Sleepy.Hollow.S01E09.720p.WEB-DL.DD5.1.H.264-BP.mkv : episode: 9 - video_codec: h264 - format: WEB-DL + video_codec: H.264 + source: Web title: Sleepy Hollow audio_channels: "5.1" screen_size: 720p season: 1 - video_profile: BP - audio_codec: AC3 +# video_profile: BP # TODO: related to https://github.com/guessit-io/guessit/issues/458#issuecomment-305719715 + audio_codec: Dolby Digital ? Sleepy.Hollow.S01E09.720p.WEB-DL.DD5.1.H.264-BS.mkv : episode: 9 - video_codec: h264 - format: WEB-DL + video_codec: H.264 + source: Web title: Sleepy Hollow audio_channels: "5.1" screen_size: 720p season: 1 release_group: BS - audio_codec: AC3 + audio_codec: Dolby Digital ? Battlestar.Galactica.S00.Pilot.FRENCH.DVDRip.XviD-NOTAG.avi : title: Battlestar Galactica @@ -567,8 +573,9 @@ episode_details: Pilot episode_title: Pilot language: French - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: NOTAG ? The Big Bang Theory S00E00 Unaired Pilot VOSTFR TVRip XviD-VioCs @@ -576,8 +583,9 @@ season: 0 episode: 0 subtitle_language: French - format: TV - video_codec: XviD + source: TV + other: Rip + video_codec: Xvid release_group: VioCs episode_details: [Unaired, Pilot] @@ -585,10 +593,10 @@ : title: The Big Bang Theory season: 1 episode: 0 - format: TV - video_codec: XviD + source: TV + video_codec: Xvid release_group: GIGGITY - other: Proper + other: [Proper, Rip] proper_count: 1 episode_details: [Unaired, Pilot] @@ -598,8 +606,8 @@ year: 2014 episode: 18 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: KILLERS ? 2.Broke.Girls.S03E10.480p.HDTV.x264-mSD.mkv @@ -607,29 +615,15 @@ season: 3 episode: 10 screen_size: 480p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: mSD -? House.of.Cards.2013.S02E03.1080p.NF.WEBRip.DD5.1.x264-NTb.mkv -? House.of.Cards.2013.S02E03.1080p.Netflix.WEBRip.DD5.1.x264-NTb.mkv -: title: House of Cards - year: 2013 - season: 2 - episode: 3 - screen_size: 1080p - streaming_service: Netflix - format: WEBRip - audio_channels: "5.1" - audio_codec: AC3 - video_codec: h264 - release_group: NTb - ? the.100.109.hdtv-lol.mp4 : title: the 100 season: 1 episode: 9 - format: HDTV + source: HDTV release_group: lol ? Criminal.Minds.5x03.Reckoner.ENG.-.sub.FR.HDTV.XviD-STi.[tvu.org.ru].avi @@ -638,8 +632,8 @@ subtitle_language: French season: 5 episode: 3 - video_codec: XviD - format: HDTV + video_codec: Xvid + source: HDTV website: tvu.org.ru release_group: STi episode_title: Reckoner @@ -651,7 +645,7 @@ ? '[Evil-Saizen]_Laughing_Salesman_14_[DVD][1C98686A].mkv' : crc32: 1C98686A episode: 14 - format: DVD + source: DVD release_group: Evil-Saizen title: Laughing Salesman @@ -680,22 +674,22 @@ : audio_codec: AAC crc32: 99E8E009 episode: 1 - format: BluRay + source: Blu-ray release_group: Daisei screen_size: 720p title: Free!:Iwatobi Swim Club - video_profile: 10bit + color_depth: 10-bit ? '[Tsundere] Boku wa Tomodachi ga Sukunai - 03 [BDRip h264 1920x1080 10bit FLAC][AF0C22CC].mkv' : audio_codec: FLAC crc32: AF0C22CC episode: 3 - format: BluRay + source: Blu-ray release_group: Tsundere screen_size: 1080p title: Boku wa Tomodachi ga Sukunai - video_codec: h264 - video_profile: 10bit + video_codec: H.264 + color_depth: 10-bit ? '[t.3.3.d]_Mikakunin_de_Shinkoukei_-_12_[720p][5DDC1352].mkv' : crc32: 5DDC1352 @@ -710,12 +704,12 @@ release_group: Anime-Koi screen_size: 720p title: Sabagebu! - video_codec: h264 + video_codec: H.264 ? '[aprm-Diogo4D] [BD][1080p] Nagi no Asukara 08 [4D102B7C].mkv' : crc32: 4D102B7C episode: 8 - format: BluRay + source: Blu-ray release_group: aprm-Diogo4D screen_size: 1080p title: Nagi no Asukara @@ -748,7 +742,7 @@ ? '[DeadFish] Tari Tari - 01 [BD][720p][AAC].mp4' : audio_codec: AAC episode: 1 - format: BluRay + source: Blu-ray release_group: DeadFish screen_size: 720p title: Tari Tari @@ -759,12 +753,12 @@ release_group: NoobSubs screen_size: 720p title: Sword Art Online II - video_profile: 8bit + color_depth: 8-bit ? '[DeadFish] 01 - Tari Tari [BD][720p][AAC].mp4' : audio_codec: AAC episode: 1 - format: BluRay + source: Blu-ray release_group: DeadFish screen_size: 720p title: Tari Tari @@ -775,12 +769,12 @@ release_group: NoobSubs screen_size: 720p title: Sword Art Online II - video_profile: 8bit + color_depth: 8-bit ? '[DeadFish] 12 - Tari Tari [BD][720p][AAC].mp4' : audio_codec: AAC episode: 12 - format: BluRay + source: Blu-ray release_group: DeadFish screen_size: 720p title: Tari Tari @@ -788,7 +782,7 @@ ? Something.Season.2.1of4.Ep.Title.HDTV.torrent : episode_count: 4 episode: 1 - format: HDTV + source: HDTV season: 2 title: Something episode_title: Title @@ -797,7 +791,7 @@ ? Something.Season.2of5.3of9.Ep.Title.HDTV.torrent : episode_count: 9 episode: 3 - format: HDTV + source: HDTV season: 2 season_count: 5 title: Something @@ -805,7 +799,7 @@ container: torrent ? Something.Other.Season.3of5.Complete.HDTV.torrent -: format: HDTV +: source: HDTV other: Complete season: 3 season_count: 5 @@ -827,22 +821,22 @@ ? W2Test.123.HDTV.XViD-FlexGet : episode: 23 season: 1 - format: HDTV + source: HDTV release_group: FlexGet title: W2Test - video_codec: XviD + video_codec: Xvid ? W2Test.123.HDTV.XViD-FlexGet : options: --episode-prefer-number episode: 123 - format: HDTV + source: HDTV release_group: FlexGet title: W2Test - video_codec: XviD + video_codec: Xvid ? FooBar.0307.PDTV-FlexGet : episode: 7 - format: DVB + source: Digital TV release_group: FlexGet season: 3 title: FooBar @@ -851,53 +845,51 @@ ? FooBar.307.PDTV-FlexGet : options: --episode-prefer-number episode: 307 - format: DVB + source: Digital TV release_group: FlexGet title: FooBar ? FooBar.07.PDTV-FlexGet -: options: --episode-prefer-number - episode: 7 - format: DVB +: episode: 7 + source: Digital TV release_group: FlexGet title: FooBar ? FooBar.7.PDTV-FlexGet -: options: --episode-prefer-number - episode: 7 - format: DVB +: episode: 7 + source: Digital TV release_group: FlexGet title: FooBar ? FooBar.0307.PDTV-FlexGet : episode: 7 - format: DVB + source: Digital TV release_group: FlexGet season: 3 title: FooBar ? FooBar.307.PDTV-FlexGet : episode: 7 - format: DVB + source: Digital TV release_group: FlexGet season: 3 title: FooBar ? FooBar.07.PDTV-FlexGet : episode: 7 - format: DVB + source: Digital TV release_group: FlexGet title: FooBar ? FooBar.07v4.PDTV-FlexGet : episode: 7 version: 4 - format: DVB + source: Digital TV release_group: FlexGet title: FooBar ? FooBar.7.PDTV-FlexGet -: format: DVB +: source: Digital TV release_group: FlexGet title: FooBar 7 type: movie @@ -905,7 +897,7 @@ ? FooBar.7.PDTV-FlexGet : options: -t episode episode: 7 - format: DVB + source: Digital TV release_group: FlexGet title: FooBar @@ -913,13 +905,13 @@ : options: -t episode episode: 7 version: 3 - format: DVB + source: Digital TV release_group: FlexGet title: FooBar ? Test.S02E01.hdtv.real.proper : episode: 1 - format: HDTV + source: HDTV other: Proper proper_count: 2 season: 2 @@ -927,7 +919,7 @@ ? Real.Test.S02E01.hdtv.proper : episode: 1 - format: HDTV + source: HDTV other: Proper proper_count: 1 season: 2 @@ -935,7 +927,7 @@ ? Test.Real.S02E01.hdtv.proper : episode: 1 - format: HDTV + source: HDTV other: Proper proper_count: 1 season: 2 @@ -943,7 +935,7 @@ ? Test.S02E01.hdtv.proper : episode: 1 - format: HDTV + source: HDTV other: Proper proper_count: 1 season: 2 @@ -951,7 +943,7 @@ ? Test.S02E01.hdtv.real.repack.proper : episode: 1 - format: HDTV + source: HDTV other: Proper proper_count: 3 season: 2 @@ -959,10 +951,10 @@ ? Date.Show.03-29-2012.HDTV.XViD-FlexGet : date: 2012-03-29 - format: HDTV + source: HDTV release_group: FlexGet title: Date Show - video_codec: XviD + video_codec: Xvid ? Something.1x5.Season.Complete-FlexGet : episode: 5 @@ -1000,13 +992,13 @@ audio_codec: AAC country: US episode: 14 - format: HDTV + source: HDTV release_group: NOGRP screen_size: 720p season: 2013 title: FlexGet episode_title: Title Here - video_codec: h264 + video_codec: H.264 year: 2013 ? FlexGet.14.of.21.Title.Here.720p.HDTV.AAC5.1.x264-NOGRP @@ -1014,25 +1006,25 @@ audio_codec: AAC episode_count: 21 episode: 14 - format: HDTV + source: HDTV release_group: NOGRP screen_size: 720p title: FlexGet episode_title: Title Here - video_codec: h264 + video_codec: H.264 ? FlexGet.Series.2013.14.of.21.Title.Here.720p.HDTV.AAC5.1.x264-NOGRP : audio_channels: '5.1' audio_codec: AAC episode_count: 21 episode: 14 - format: HDTV + source: HDTV release_group: NOGRP screen_size: 720p season: 2013 title: FlexGet episode_title: Title Here - video_codec: h264 + video_codec: H.264 year: 2013 ? Something.S04E05E09 @@ -1055,12 +1047,14 @@ title: FooBar ? FooBar 360 -: screen_size: 360p +: season: 3 + episode: 60 title: FooBar + -screen_size: 360p ? BarFood christmas special HDTV : options: --expected-title BarFood - format: HDTV + source: HDTV title: BarFood episode_title: christmas special episode_details: Special @@ -1082,47 +1076,47 @@ ? Test.13.HDTV-Ignored : episode: 13 - format: HDTV + source: HDTV release_group: Ignored title: Test ? Test.13.HDTV-Ignored : options: --expected-series test episode: 13 - format: HDTV + source: HDTV release_group: Ignored title: Test ? Test.13.HDTV-Ignored : title: Test episode: 13 - format: HDTV + source: HDTV release_group: Ignored ? Test.13.HDTV-Ignored : episode: 13 - format: HDTV + source: HDTV release_group: Ignored title: Test ? Test.13.HDTV-FlexGet : episode: 13 - format: HDTV + source: HDTV release_group: FlexGet title: Test ? Test.14.HDTV-Name : episode: 14 - format: HDTV + source: HDTV release_group: Name title: Test ? Real.Time.With.Bill.Maher.2014.10.31.HDTV.XviD-AFG.avi : date: 2014-10-31 - format: HDTV + source: HDTV release_group: AFG title: Real Time With Bill Maher - video_codec: XviD + video_codec: Xvid ? Arrow.S03E21.Al.Sah-Him.1080p.WEB-DL.DD5.1.H.264-BS.mkv : title: Arrow @@ -1130,11 +1124,11 @@ episode: 21 episode_title: Al Sah-Him screen_size: 1080p - audio_codec: AC3 + audio_codec: Dolby Digital audio_channels: "5.1" - video_codec: h264 + video_codec: H.264 release_group: BS - format: WEB-DL + source: Web ? How to Make It in America - S02E06 - I'm Sorry, Who's Yosi?.mkv : title: How to Make It in America @@ -1144,63 +1138,27 @@ ? 24.S05E07.FRENCH.DVDRip.XviD-FiXi0N.avi : episode: 7 - format: DVD + source: DVD + other: Rip language: fr season: 5 title: '24' - video_codec: XviD + video_codec: Xvid release_group: FiXi0N ? 12.Monkeys.S01E12.FRENCH.BDRip.x264-VENUE.mkv : episode: 12 - format: BluRay + source: Blu-ray + other: Rip language: fr release_group: VENUE season: 1 title: 12 Monkeys - video_codec: h264 - -? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.720p.CC.WEBRip.AAC2.0.x264-BTW.mkv -? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.720p.ComedyCentral.WEBRip.AAC2.0.x264-BTW.mkv -? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.720p.Comedy.Central.WEBRip.AAC2.0.x264-BTW.mkv -: audio_channels: '2.0' - audio_codec: AAC - date: 2015-07-01 - format: WEBRip - edition: Extended - release_group: BTW - screen_size: 720p - streaming_service: Comedy Central - title: The Daily Show - episode_title: Kirsten Gillibrand - video_codec: h264 - -? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.Interview.720p.CC.WEBRip.AAC2.0.x264-BTW.mkv -: audio_channels: '2.0' - audio_codec: AAC - date: 2015-07-01 - format: WEBRip - release_group: BTW - screen_size: 720p - streaming_service: Comedy Central - title: The Daily Show - episode_title: Kirsten Gillibrand Extended Interview - video_codec: h264 - -? The.Daily.Show.2015.07.02.Sarah.Vowell.CC.WEBRip.AAC2.0.x264-BTW.mkv -: audio_channels: '2.0' - audio_codec: AAC - date: 2015-07-02 - format: WEBRip - release_group: BTW - streaming_service: Comedy Central - title: The Daily Show - episode_title: Sarah Vowell - video_codec: h264 + video_codec: H.264 ? 90.Day.Fiance.S02E07.I.Have.To.Tell.You.Something.720p.HDTV.x264-W4F : episode: 7 - format: HDTV + source: HDTV screen_size: 720p season: 2 title: 90 Day Fiance @@ -1209,42 +1167,44 @@ ? Doctor.Who.2005.S04E06.FRENCH.LD.DVDRip.XviD-TRACKS.avi : episode: 6 - format: DVD + source: DVD language: fr release_group: TRACKS season: 4 title: Doctor Who - other: LD - video_codec: XviD + other: [Line Dubbed, Rip] + video_codec: Xvid year: 2005 ? Astro.Le.Petit.Robot.S01E01+02.FRENCH.DVDRiP.X264.INT-BOOLZ.mkv : episode: [1, 2] - format: DVD + source: DVD + other: Rip language: fr release_group: INT-BOOLZ season: 1 title: Astro Le Petit Robot - video_codec: h264 + video_codec: H.264 ? Annika.Bengtzon.2012.E01.Le.Testament.De.Nobel.FRENCH.DVDRiP.XViD-STVFRV.avi : episode: 1 - format: DVD + source: DVD + other: Rip language: fr release_group: STVFRV title: Annika Bengtzon episode_title: Le Testament De Nobel - video_codec: XviD + video_codec: Xvid year: 2012 ? Dead.Set.02.FRENCH.LD.DVDRip.XviD-EPZ.avi : episode: 2 - format: DVD + source: DVD language: fr - other: LD + other: [Line Dubbed, Rip] release_group: EPZ title: Dead Set - video_codec: XviD + video_codec: Xvid ? Phineas and Ferb S01E00 & S01E01 & S01E02 : episode: [0, 1, 2] @@ -1253,11 +1213,11 @@ ? Show.Name.S01E02.S01E03.HDTV.XViD.Etc-Group : episode: [2, 3] - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show Name - S01E02 - S01E03 - S01E04 - Ep Name : episode: [2, 3, 4] @@ -1267,11 +1227,11 @@ ? Show.Name.1x02.1x03.HDTV.XViD.Etc-Group : episode: [2, 3] - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show Name - 1x02 - 1x03 - 1x04 - Ep Name : episode: [2, 3, 4] @@ -1281,11 +1241,11 @@ ? Show.Name.S01E02.HDTV.XViD.Etc-Group : episode: 2 - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show Name - S01E02 - My Ep Name : episode: 2 @@ -1301,11 +1261,11 @@ ? Show.Name.S01E02E03.HDTV.XViD.Etc-Group : episode: [2, 3] - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show Name - S01E02-03 - My Ep Name : episode: [2, 3] @@ -1320,11 +1280,11 @@ ? Show_Name.1x02.HDTV_XViD_Etc-Group : episode: 2 - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show Name - 1x02 - My Ep Name : episode: 2 @@ -1334,11 +1294,11 @@ ? Show_Name.1x02x03x04.HDTV_XViD_Etc-Group : episode: [2, 3, 4] - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show Name - 1x02-03-04 - My Ep Name : episode: [2, 3, 4] @@ -1351,25 +1311,25 @@ : date: 2010-11-23 season: 1 episode: 0 - format: HDTV + source: HDTV release_group: Etc-Group title: Show Name episode_title: Event - video_codec: XviD + video_codec: Xvid ? Show.Name.101.Event.2010.11.23.HDTV.XViD.Etc-Group : date: 2010-11-23 season: 1 episode: 1 - format: HDTV + source: HDTV release_group: Etc-Group title: Show Name episode_title: Event - video_codec: XviD + video_codec: Xvid ? Show.Name.2010.11.23.HDTV.XViD.Etc-Group : date: 2010-11-23 - format: HDTV + source: HDTV release_group: Etc-Group title: Show Name @@ -1385,11 +1345,11 @@ episode_title: Ep Name ? Show.Name.S01.HDTV.XViD.Etc-Group -: format: HDTV +: source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? Show.Name.E02-03 : episode: [2, 3] @@ -1408,8 +1368,8 @@ ? Show.Name.Part.3.HDTV.XViD.Etc-Group : part: 3 title: Show Name - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: Etc-Group type: movie # Fallback to movie type because we can't tell it's a series ... @@ -1431,11 +1391,11 @@ ? Show.Name.102.HDTV.XViD.Etc-Group : episode: 2 - format: HDTV + source: HDTV release_group: Etc-Group season: 1 title: Show Name - video_codec: XviD + video_codec: Xvid ? '[HorribleSubs] Maria the Virgin Witch - 01 [720p].mkv' : episode: 1 @@ -1444,29 +1404,26 @@ title: Maria the Virgin Witch ? '[ISLAND]One_Piece_679_[VOSTFR]_[V1]_[8bit]_[720p]_[EB7838FC].mp4' -: options: -E - crc32: EB7838FC +: crc32: EB7838FC episode: 679 release_group: ISLAND screen_size: 720p title: One Piece subtitle_language: fr - video_profile: 8bit + color_depth: 8-bit version: 1 ? '[ISLAND]One_Piece_679_[VOSTFR]_[8bit]_[720p]_[EB7838FC].mp4' -: options: -E - crc32: EB7838FC +: crc32: EB7838FC episode: 679 release_group: ISLAND screen_size: 720p title: One Piece subtitle_language: fr - video_profile: 8bit + color_depth: 8-bit ? '[Kaerizaki-Fansub]_One_Piece_679_[VOSTFR][HD_1280x720].mp4' -: options: -E - episode: 679 +: episode: 679 other: HD release_group: Kaerizaki-Fansub screen_size: 720p @@ -1474,19 +1431,15 @@ subtitle_language: fr ? '[Kaerizaki-Fansub]_One_Piece_679_[VOSTFR][FANSUB][HD_1280x720].mp4' -: options: -E - episode: 679 - other: - - Fansub - - HD +: episode: 679 + other: [Fan Subtitled, HD] release_group: Kaerizaki-Fansub screen_size: 720p title: One Piece subtitle_language: fr ? '[Kaerizaki-Fansub]_One_Piece_681_[VOSTFR][HD_1280x720]_V2.mp4' -: options: -E - episode: 681 +: episode: 681 other: HD release_group: Kaerizaki-Fansub screen_size: 720p @@ -1495,8 +1448,7 @@ version: 2 ? '[Kaerizaki-Fansub] High School DxD New 04 VOSTFR HD (1280x720) V2.mp4' -: options: -E - episode: 4 +: episode: 4 other: HD release_group: Kaerizaki-Fansub screen_size: 720p @@ -1505,8 +1457,7 @@ version: 2 ? '[Kaerizaki-Fansub] One Piece 603 VOSTFR PS VITA (960x544) V2.mp4' -: options: -E - episode: 603 +: episode: 603 release_group: Kaerizaki-Fansub other: PS Vita screen_size: 960x544 @@ -1540,13 +1491,12 @@ release_group: Stratos-Subs screen_size: 720p title: Infinite Stratos - video_codec: h264 + video_codec: H.264 # [ShinBunBu-Subs] Bleach - 02-03 (CX 1280x720 x264 AAC) ? '[SGKK] Bleach 312v1 [720p/MKV]' -: options: -E # guessit 1.x for episode only when version is guessed, but it's doesn't make it consistent. - episode: 312 +: episode: 312 release_group: SGKK screen_size: 720p title: Bleach @@ -1558,7 +1508,7 @@ release_group: Ayako screen_size: 720p title: Infinite Stratos - video_codec: h264 + video_codec: H.264 ? '[Ayako] Infinite Stratos - IS - 07v2 [H264][720p][44419534]' : crc32: '44419534' @@ -1566,7 +1516,7 @@ release_group: Ayako screen_size: 720p title: Infinite Stratos - video_codec: h264 + video_codec: H.264 version: 2 ? '[Ayako-Shikkaku] Oniichan no Koto Nanka Zenzen Suki Janain Dakara ne - 10 [LQ][h264][720p] [8853B21C]' @@ -1575,18 +1525,15 @@ release_group: Ayako-Shikkaku screen_size: 720p title: Oniichan no Koto Nanka Zenzen Suki Janain Dakara ne - video_codec: h264 + video_codec: H.264 -# TODO: Add support for absolute episodes -? Bleach - s16e03-04 - 313-314 -? Bleach.s16e03-04.313-314 -? Bleach.s16e03-04.313-314 ? Bleach - s16e03-04 - 313-314 -? Bleach.s16e03-04.313-314 +? Bleach.s16e03-04.313-314-GROUP ? Bleach s16e03e04 313-314 -: episode: [3, 4] +: title: Bleach season: 16 - title: Bleach + episode: [3, 4] + absolute_episode: [313, 314] ? Bleach - 313-314 : options: -E @@ -1599,7 +1546,7 @@ release_group: ShinBunBu-Subs screen_size: 720p title: Bleach - video_codec: h264 + video_codec: H.264 ? 003. Show Name - Ep Name.avi : episode: 3 @@ -1623,23 +1570,23 @@ ? Project.Runway.S14E00.and.S14E01.(Eng.Subs).SDTV.x264-[2Maverick].mp4 : episode: [0, 1] - format: TV + source: TV release_group: 2Maverick season: 14 title: Project Runway subtitle_language: en - video_codec: h264 + video_codec: H.264 ? '[Hatsuyuki-Kaitou]_Fairy_Tail_2_-_16-20_[720p][10bit].torrent' : episode: [16, 17, 18, 19, 20] release_group: Hatsuyuki-Kaitou screen_size: 720p title: Fairy Tail 2 - video_profile: 10bit + color_depth: 10-bit ? '[Hatsuyuki-Kaitou]_Fairy_Tail_2_-_16-20_(191-195)_[720p][10bit].torrent' -: options: -E - episode: [16, 17, 18, 19, 20, 191, 192, 193, 194, 195] +: episode: [16, 17, 18, 19, 20] + absolute_episode: [191, 192, 193, 194, 195] release_group: Hatsuyuki-Kaitou screen_size: 720p title: Fairy Tail 2 @@ -1653,15 +1600,15 @@ ? The.Good.Wife.S06E01.E10.720p.WEB-DL.DD5.1.H.264-CtrlHD/The.Good.Wife.S06E09.Trust.Issues.720p.WEB-DL.DD5.1.H.264-CtrlHD.mkv : audio_channels: '5.1' - audio_codec: AC3 + audio_codec: Dolby Digital episode: 9 - format: WEB-DL + source: Web release_group: CtrlHD screen_size: 720p season: 6 title: The Good Wife episode_title: Trust Issues - video_codec: h264 + video_codec: H.264 ? Fear the Walking Dead - 01x02 - So Close, Yet So Far.REPACK-KILLERS.French.C.updated.Addic7ed.com.mkv : episode: 2 @@ -1683,16 +1630,15 @@ ? /av/unsorted/The.Daily.Show.2015.07.22.Jake.Gyllenhaal.720p.HDTV.x264-BATV.mkv : date: 2015-07-22 - format: HDTV + source: HDTV release_group: BATV screen_size: 720p title: The Daily Show episode_title: Jake Gyllenhaal - video_codec: h264 + video_codec: H.264 ? "[7.1.7.8.5] Foo Bar - 11 (H.264) [5235532D].mkv" -: options: -E - episode: 11 +: episode: 11 ? my 720p show S01E02 : options: -T "my 720p show" @@ -1723,58 +1669,56 @@ screen_size: 720p season: 1 title: Foo's & Bars - video_codec: XviD + video_codec: Xvid year: 2009 ? Date.Series.10-11-2008.XViD : date: 2008-11-10 title: Date - video_codec: XviD + video_codec: Xvid ? Scrubs/SEASON-06/Scrubs.S06E09.My.Perspective.DVDRip.XviD-WAT/scrubs.s06e09.dvdrip.xvid-wat.avi : container: avi episode: 9 episode_title: My Perspective - format: DVD - mimetype: video/x-msvideo + source: DVD + other: Rip release_group: WAT season: 6 title: Scrubs - video_codec: XviD + video_codec: Xvid ? '[PuyaSubs!] Digimon Adventure tri - 01 [720p][F9967949].mkv' : container: mkv crc32: F9967949 episode: 1 - mimetype: video/x-matroska release_group: PuyaSubs! screen_size: 720p title: Digimon Adventure tri ? Sherlock.S01.720p.BluRay.x264-AVCHD -: format: BluRay +: source: Blu-ray screen_size: 720p season: 1 title: Sherlock - video_codec: h264 + video_codec: H.264 ? Running.Wild.With.Bear.Grylls.S02E07.Michael.B.Jordan.PROPER.HDTV.x264-W4F.avi : container: avi episode: 7 episode_title: Michael B Jordan - format: HDTV - mimetype: video/x-msvideo + source: HDTV other: Proper proper_count: 1 release_group: W4F season: 2 title: Running Wild With Bear Grylls - video_codec: h264 + video_codec: H.264 ? Homeland.S05E11.Our.Man.in.Damascus.German.Sub.720p.HDTV.x264.iNTERNAL-BaCKToRG : episode: 11 episode_title: Our Man in Damascus - format: HDTV + source: HDTV other: Internal release_group: BaCKToRG screen_size: 720p @@ -1782,14 +1726,14 @@ subtitle_language: de title: Homeland type: episode - video_codec: h264 + video_codec: H.264 ? Breaking.Bad.S01E01.2008.BluRay.VC1.1080P.5.1.WMV-NOVO : title: Breaking Bad season: 1 episode: 1 year: 2008 - format: BluRay + source: Blu-ray screen_size: 1080p audio_channels: '5.1' container: WMV @@ -1800,8 +1744,8 @@ : title: Cosmos A Space Time Odyssey season: 1 episode: 2 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 other: Proper proper_count: 1 release_group: LOL @@ -1811,8 +1755,8 @@ : title: Fear The Walking Dead season: 2 episode: 1 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 audio_codec: AAC container: mp4 release_group: k3n @@ -1824,8 +1768,8 @@ episode: 1 episode_details: Pilot episode_title: Pilot - format: DVD - video_codec: h264 + source: DVD + video_codec: H.264 other: [Screener, Preair] release_group: NoGRP type: episode @@ -1834,8 +1778,8 @@ : title: Once Upon a Time season: 5 episode: 19 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 other: Proper proper_count: 1 release_group: LOL[ettv] @@ -1845,49 +1789,49 @@ : title: Show Name season: 1 episode: 3 - format: WEB-DL - video_codec: h264 + source: Web + video_codec: H.264 language: hu release_group: nIk type: episode ? Game.of.Thrones.S6.Ep5.X265.Dolby.2.0.KTM3.mp4 : audio_channels: '2.0' - audio_codec: AC3 + audio_codec: Dolby Digital container: mp4 episode: 5 release_group: KTM3 season: 6 title: Game of Thrones type: episode - video_codec: h265 + video_codec: H.265 ? Fargo.-.Season.1.-.720p.BluRay.-.x264.-.ShAaNiG -: format: BluRay +: source: Blu-ray release_group: ShAaNiG screen_size: 720p season: 1 title: Fargo type: episode - video_codec: h264 + video_codec: H.264 ? Show.Name.S02E02.Episode.Title.1080p.WEB-DL.x264.5.1Ch.-.Group : audio_channels: '5.1' episode: 2 episode_title: Episode Title - format: WEB-DL + source: Web release_group: Group screen_size: 1080p season: 2 title: Show Name type: episode - video_codec: h264 + video_codec: H.264 ? Breaking.Bad.S01E01.2008.BluRay.VC1.1080P.5.1.WMV-NOVO : audio_channels: '5.1' container: wmv episode: 1 - format: BluRay + source: Blu-ray release_group: NOVO screen_size: 1080p season: 1 @@ -1897,20 +1841,20 @@ ? Cosmos.A.Space.Time.Odyssey.S01E02.HDTV.x264.PROPER-LOL : episode: 2 - format: HDTV + source: HDTV other: Proper proper_count: 1 release_group: LOL season: 1 title: Cosmos A Space Time Odyssey type: episode - video_codec: h264 + video_codec: H.264 ? Elementary.S01E01.Pilot.DVDSCR.x264.PREAiR-NoGRP : episode: 1 episode_details: Pilot episode_title: Pilot - format: DVD + source: DVD other: - Screener - Preair @@ -1918,25 +1862,24 @@ season: 1 title: Elementary type: episode - video_codec: h264 + video_codec: H.264 ? Fear.The.Walking.Dead.S02E01.HDTV.x264.AAC.MP4-k3n.mp4 : audio_codec: AAC container: mp4 episode: 1 - format: HDTV - mimetype: video/mp4 + source: HDTV release_group: k3n season: 2 title: Fear The Walking Dead type: episode - video_codec: h264 + video_codec: H.264 ? Game.of.Thrones.S03.1080p.BluRay.DTS-HD.MA.5.1.AVC.REMUX-FraMeSToR : audio_channels: '5.1' - audio_codec: DTS - audio_profile: HDMA - format: BluRay + audio_codec: DTS-HD + audio_profile: Master Audio + source: Blu-ray other: Remux release_group: FraMeSToR screen_size: 1080p @@ -1946,16 +1889,16 @@ ? Show.Name.S01E02.HDTV.x264.NL-subs-ABC : episode: 2 - format: HDTV + source: HDTV release_group: ABC season: 1 subtitle_language: nl title: Show Name type: episode - video_codec: h264 + video_codec: H.264 ? Friends.S01-S10.COMPLETE.720p.BluRay.x264-PtM -: format: BluRay +: source: Blu-ray other: Complete release_group: PtM screen_size: 720p @@ -1972,44 +1915,44 @@ - 10 title: Friends type: episode - video_codec: h264 + video_codec: H.264 ? Duck.Dynasty.S02E07.Streik.German.DOKU.DL.WS.DVDRiP.x264-CDP : episode: 7 - episode_title: Streik German DOKU - format: DVD + episode_title: Streik German + source: DVD language: mul - other: WideScreen + other: [Documentary, Widescreen, Rip] release_group: CDP season: 2 title: Duck Dynasty type: episode - video_codec: h264 + video_codec: H.264 ? Family.Guy.S13E14.JOLO.German.AC3D.DL.720p.WebHD.x264-CDD -: audio_codec: AC3 +: audio_codec: Dolby Digital episode: 14 episode_title: JOLO German - format: WEB-DL + source: Web language: mul release_group: CDD screen_size: 720p season: 13 title: Family Guy type: episode - video_codec: h264 + video_codec: H.264 ? How.I.Met.Your.Mother.COMPLETE.SERIES.DVDRip.XviD-AR : options: -L en -C us - format: DVD - other: Complete + source: DVD + other: [Complete, Rip] release_group: AR title: How I Met Your Mother type: movie # Should be episode - video_codec: XviD + video_codec: Xvid ? Show Name The Complete Seasons 1 to 5 720p BluRay x265 HEVC-SUJAIDR[UTR] -: format: BluRay +: source: Blu-ray other: Complete release_group: SUJAIDR[UTR] screen_size: 720p @@ -2021,12 +1964,12 @@ - 5 title: Show Name type: episode - video_codec: h265 + video_codec: H.265 ? Fear.the.Walking.Dead.-.Season.2.epi.02.XviD.Eng.Ac3-5.1.sub.ita.eng.iCV-MIRCrew : options: -t episode audio_channels: '5.1' - audio_codec: AC3 + audio_codec: Dolby Digital episode: 2 episode_title: epi language: en @@ -2035,11 +1978,11 @@ subtitle_language: it title: Fear the Walking Dead type: episode - video_codec: XviD + video_codec: Xvid ? Game.Of.Thrones.S06E04.720p.PROPER.HDTV.x264-HDD : episode: 4 - format: HDTV + source: HDTV other: Proper proper_count: 1 release_group: HDD @@ -2047,53 +1990,54 @@ season: 6 title: Game Of Thrones type: episode - video_codec: h264 + video_codec: H.264 ? Marvels.Daredevil.S02E04.WEBRip.x264-NF69.mkv : container: mkv episode: 4 - format: WEBRip + source: Web + other: Rip release_group: NF69 season: 2 title: Marvels Daredevil type: episode - video_codec: h264 + video_codec: H.264 ? The.Walking.Dead.S06E01.FRENCH.1080p.WEB-DL.DD5.1.HEVC.x265-GOLF68 : audio_channels: '5.1' - audio_codec: AC3 + audio_codec: Dolby Digital episode: 1 - format: WEB-DL + source: Web language: fr release_group: GOLF68 screen_size: 1080p season: 6 title: The Walking Dead type: episode - video_codec: h265 + video_codec: H.265 ? American.Crime.S01E03.FASTSUB.VOSTFR.720p.HDTV.x264-F4ST : episode: 3 - format: HDTV - other: Fastsub + source: HDTV + other: Fast Subtitled release_group: F4ST screen_size: 720p season: 1 subtitle_language: fr title: American Crime type: episode - video_codec: h264 + video_codec: H.264 ? Gotham.S02E12.FASTSUB.VOSTFR.HDTV.X264-F4ST3R : episode: 12 - format: HDTV - other: Fastsub + source: HDTV + other: Fast Subtitled release_group: F4ST3R season: 2 subtitle_language: fr title: Gotham type: episode - video_codec: h264 + video_codec: H.264 # WEBRip + LD ? Australian.Story.2016.05.23.Into.The.Fog.of.War.Part.1.360p.LDTV.WEBRIP.[MPup] @@ -2102,8 +2046,8 @@ episode_title: Into The Fog of War part: 1 screen_size: 360p - other: LD - format: WEBRip + other: [Low Definition, Rip] + source: Web release_group: MPup type: episode @@ -2113,8 +2057,8 @@ season: 4 episode: 6 language: fr - format: AHDTV - video_codec: XviD + source: Analog HDTV + video_codec: Xvid type: episode # WEBDLRip @@ -2122,10 +2066,10 @@ : title: Show Name season: 6 episode: 14 - format: WEBRip + source: Web + other: Rip release_group: qqss44 container: avi - mimetype: video/x-msvideo type: episode # WEBCap @@ -2135,8 +2079,9 @@ episode: 6 episode_title: Steven Floats screen_size: 720p - format: WEBRip - video_codec: h264 + source: Web + other: Rip + video_codec: H.264 release_group: SRS type: episode @@ -2146,9 +2091,9 @@ season: 5 episode: 9 episode_title: Some Episode Title - other: WideScreen - format: SATRip - video_codec: h264 + other: Widescreen + source: Satellite + video_codec: H.264 release_group: NY2 type: episode @@ -2157,9 +2102,9 @@ : title: Squidbillies season: 4 episode: 5 - other: WideScreen - format: SATRip - video_codec: XviD + other: [Widescreen, Rip] + source: Satellite + video_codec: Xvid release_group: aAF type: episode @@ -2167,14 +2112,13 @@ ? /series/The.B*.B*.T*.S10E01.1080p.HDTV.X264-DIMENSION[rarbg]/The.B*.B*.T*.S10E01.1080p.HDTV.X264-DIMENSION.mkv : container: mkv episode: 1 - format: HDTV - mimetype: video/x-matroska - release_group: DIMENSION[rarbg] + source: HDTV + release_group: DIMENSION screen_size: 1080p season: 10 title: The B B T type: episode - video_codec: h264 + video_codec: H.264 ? '[Y-F] Very long Show Name Here - 03 Vostfr HD 8bits' : release_group: Y-F @@ -2182,7 +2126,7 @@ episode: 3 subtitle_language: fr other: HD - video_profile: 8bit + color_depth: 8-bit type: episode ? '[.www.site.com.].-.Snooze.and.Go.Sleep.S03E02.1080p.HEVC.x265-MeGusta' @@ -2192,17 +2136,17 @@ season: 3 title: Snooze and Go Sleep type: episode - video_codec: h265 + video_codec: H.265 website: www.site.com ? Show.Name.S01.720p.HDTV.DD5.1.x264-Group/show.name.0106.720p-group.mkv : title: Show Name season: 1 screen_size: 720p - format: HDTV - audio_codec: AC3 + source: HDTV + audio_codec: Dolby Digital audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: Group episode: 6 container: mkv @@ -2211,8 +2155,8 @@ ? Coupling Season 1 - 4 Complete DVDRip/Coupling Season 4/Coupling - (4x03) - Bed Time.mkv : title: Coupling - other: Complete - format: DVD + other: [Complete, Rip] + source: DVD season: 4 episode: 3 episode_title: Bed Time @@ -2224,1742 +2168,2329 @@ : title: Vice News Tonight date: 2016-10-10 screen_size: 1080p - format: WEBRip + source: Web + other: Rip audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 release_group: monkee type: episode -# Streaming service: Amazon -? Show.Name.S07E04.Service.1080p.AMZN.WEBRip.DD+5.1.x264 -: title: Show Name - season: 7 - episode: 4 - episode_title: Service - screen_size: 1080p - streaming_service: Amazon Prime - format: WEBRip - audio_codec: EAC3 - audio_channels: '5.1' - video_codec: h264 +? frasier.s8e6-768660.srt +: container: srt + episode: 6 + episode_title: '768660' + season: 8 + title: frasier type: episode -# Streaming service: Comedy Central -? Show.Name.2016.09.28.Nice.Title.Extended.1080p.CC.WEBRip.AAC2.0.x264-monkee +? Show.Name.S03E15.480p.177mb.Proper.HDTV.x264 : title: Show Name - date: 2016-09-28 - episode_title: Nice Title - edition: Extended - screen_size: 1080p - streaming_service: Comedy Central - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + season: 3 + episode: 15 + screen_size: 480p + size: 177MB + other: Proper + proper_count: 1 + source: HDTV + video_codec: H.264 type: episode -# Streaming service: The CW -? Show.Name.US.S12E20.Nice.Title.720p.CW.WEBRip.AAC2.0.x264-monkee +? Show.Name.S03E15.480p.4.8GB.Proper.HDTV.x264 : title: Show Name - country: US - season: 12 - episode: 20 - episode_title: Nice Title - screen_size: 720p - streaming_service: The CW - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + season: 3 + episode: 15 + screen_size: 480p + size: 4.8GB + other: Proper + proper_count: 1 + source: HDTV + video_codec: H.264 type: episode -# Streaming service: AMBC -? Show.Name.2016.09.27.Nice.Title.720p.AMBC.WEBRip.AAC2.0.x264-monkee +? Show.Name.S03.1.1TB.Proper.HDTV.x264 : title: Show Name - date: 2016-09-27 - episode_title: Nice Title - screen_size: 720p - streaming_service: ABC - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee - type: episode - -# Streaming service: HIST -? Show.Name.720p.HIST.WEBRip.AAC2.0.H.264-monkee -: options: -t episode - title: Show Name - screen_size: 720p - streaming_service: History - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + season: 3 + size: 1.1TB + other: Proper + proper_count: 1 + source: HDTV + video_codec: H.264 type: episode -# Streaming service: PBS -? Show.Name.2015.Nice.Title.1080p.PBS.WEBRip.AAC2.0.H264-monkee -: options: -t episode - title: Show Name - year: 2015 - episode_title: Nice Title +? Some.Show.S02E14.1080p.HDTV.X264-reenc.GROUP +? Some.Show.S02E14.1080p.HDTV.X264-re-enc.GROUP +? Some.Show.S02E14.1080p.HDTV.X264-re-encoded.GROUP +? Some.Show.S02E14.1080p.HDTV.X264-reencoded.GROUP +: title: Some Show + season: 2 + episode: 14 screen_size: 1080p - streaming_service: PBS - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + source: HDTV + video_codec: H.264 + other: Reencoded + release_group: GROUP type: episode -# Streaming service: SeeSo -? Show.Name.2016.Nice.Title.1080p.SESO.WEBRip.AAC2.0.x264-monkee -: options: -t episode - title: Show Name +# DDP is DD+ +? Show.Name.2016.S01E01.2160p.AMZN.WEBRip.DDP5.1.x264-Group +: title: Show Name year: 2016 - episode_title: Nice Title - screen_size: 1080p - streaming_service: SeeSo - format: WEBRip + season: 1 + episode: 1 + screen_size: 2160p + streaming_service: Amazon Prime + source: Web + other: Rip + audio_codec: Dolby Digital Plus + audio_channels: '5.1' + video_codec: H.264 + release_group: Group + type: episode + +? Show Name S02e19 [Mux - H264 - Ita Aac] DLMux by UBi +: title: Show Name + season: 2 + episode: 19 + video_codec: H.264 + language: it audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + source: Web + other: Mux + release_group: UBi type: episode -# Streaming service: Discovery -? Show.Name.S01E03.Nice.Title.720p.DISC.WEBRip.AAC2.0.x264-NTb +? Show Name S01e10[Mux - 1080p - H264 - Ita Eng Ac3 - Sub Ita Eng]DLMux By GiuseppeTnT Littlelinx : title: Show Name season: 1 - episode: 3 - episode_title: Nice Title - screen_size: 720p - streaming_service: Discovery - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: NTb + episode: 10 + screen_size: 1080p + video_codec: H.264 + language: [it, en] + source: Web + other: Mux + audio_codec: Dolby Digital + subtitle_language: [it, en] + release_group: GiuseppeTnT Littlelinx type: episode -# Streaming service: BBC iPlayer -? Show.Name.2016.08.18.Nice.Title.720p.iP.WEBRip.AAC2.0.H.264-monkee +? Show Name S04e07-08 [H264 - Ita Aac] HDTVMux by Group : title: Show Name - date: 2016-08-18 - episode_title: Nice Title - streaming_service: BBC iPlayer - screen_size: 720p - format: WEBRip + season: 4 + episode: [7, 8] + video_codec: H.264 + language: it audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + source: HDTV + other: Mux + release_group: Group type: episode -# Streaming service: A&E -? Show.Name.S15E18.Nice.Title.720p.AE.WEBRip.AAC2.0.H.264-monkee +? Show Name 3x18 Un Tuffo Nel Passato ITA HDTVMux x264 Group : title: Show Name - season: 15 + season: 3 episode: 18 - episode_title: Nice Title - screen_size: 720p - streaming_service: A&E - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + episode_title: Un Tuffo Nel Passato + language: it + source: HDTV + other: Mux + video_codec: H.264 + release_group: Group type: episode -# Streaming service: Adult Swim -? Show.Name.S04E01.Nice.Title.1080p.AS.WEBRip.AAC2.0.H.264-monkee +? Show.Name.S03.1080p.BlurayMUX.AVC.DTS-HD.MA : title: Show Name - season: 4 - episode: 1 - episode_title: Nice Title + season: 3 screen_size: 1080p - streaming_service: Adult Swim - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + source: Blu-ray + other: Mux + video_codec: H.264 + audio_codec: DTS-HD + audio_profile: Master Audio type: episode -# Streaming service: Netflix -? Show.Name.2013.S02E03.1080p.NF.WEBRip.DD5.1.x264-NTb.mkv -: title: Show Name - year: 2013 - season: 2 - episode: 3 +? Show.Name.-.07.(2016).[RH].[English.Dubbed][WEBRip]..[HD.1080p] +: options: -t episode + episode: 7 + source: Web + other: Rip + language: en + other: [HD, Rip] screen_size: 1080p - streaming_service: Netflix - format: WEBRip - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: NTb - container: mkv - mimetype: video/x-matroska + title: Show Name type: episode + year: 2016 -# Streaming service: CBS -? Show.Name.2016.05.10.Nice.Title.720p.CBS.WEBRip.AAC2.0.x264-monkee -: title: Show Name - date: 2016-05-10 - episode_title: Nice Title +? Show.Name.-.476-479.(2007).[HorribleSubs][WEBRip]..[HD.720p] +: options: -t episode + episode: + - 476 + - 477 + - 478 + - 479 + source: Web + other: [Rip, HD] + release_group: HorribleSubs screen_size: 720p - streaming_service: CBS - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + title: Show Name type: episode + year: 2007 -# Streaming service: NBA TV -? NBA.2016.02.27.Team.A.vs.Team.B.720p.NBA.WEBRip.AAC2.0.H.264-monkee -: title: NBA - date: 2016-02-27 - episode_title: Team A vs Team B - screen_size: 720p - streaming_service: NBA TV - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee +? /11.22.63/Season 1/11.22.63.106.hdtv-abc +: options: -T 11.22.63 + title: 11.22.63 + season: 1 + episode: 6 + source: HDTV + release_group: abc type: episode -# Streaming service: ePix -? Show.Name.S05E04.Nice.Title.Part4.720p.EPIX.WEBRip.AAC2.0.H.264-monkee -: title: Show Name - season: 5 - episode: 4 - episode_title: Nice Title - part: 4 - screen_size: 720p - streaming_service: ePix - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee +? Proof.2015.S01E10.1080p.WEB-DL.DD5.1.H.264-KINGS.mkv +: title: Proof + season: 1 + episode: 10 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: KINGS + container: mkv type: episode -# Streaming service: NBC -? Show.Name.S41E03.Nice.Title.720p.NBC.WEBRip.AAC2.0.x264-monkee +# Hardcoded subtitles +? Show.Name.S06E16.HC.SWESUB.HDTV.x264 : title: Show Name - season: 41 - episode: 3 - episode_title: Nice Title - screen_size: 720p - streaming_service: NBC - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + season: 6 + episode: 16 + other: Hardcoded Subtitles + source: HDTV + video_codec: H.264 + subtitle_language: sv type: episode -# Streaming service: Syfy -? Show.Name.S01E02.Nice.Title.720p.SYFY.WEBRip.AAC2.0.x264-group -: title: Show Name - season: 1 - episode: 2 - episode_title: Nice Title - screen_size: 720p - streaming_service: Syfy - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: group +? From [ WWW.TORRENTING.COM ] - White.Rabbit.Project.S01E08.1080p.NF.WEBRip.DD5.1.x264-ViSUM/White.Rabbit.Project.S01E08.1080p.NF.WEBRip.DD5.1.x264-ViSUM.mkv +: title: White Rabbit Project + website: WWW.TORRENTING.COM + season: 1 + episode: 8 + screen_size: 1080p + streaming_service: Netflix + source: Web + other: Rip + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: ViSUM + container: mkv type: episode -# Streaming service: Spike TV -? Show.Name.S01E02.Nice.Title.720p.SPKE.WEBRip.AAC2.0.x264-group -: title: Show Name +? /tv/Daniel Tiger's Neighborhood/S02E06 - Playtime Is Different.mp4 +: season: 2 + episode: 6 + title: Daniel Tiger's Neighborhood + episode_title: Playtime Is Different + container: mp4 + type: episode + +? Zoo.S02E05.1080p.WEB-DL.DD5.1.H.264.HKD/160725_02.mkv +: title: Zoo + season: 2 + episode: 5 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: HKD + container: mkv + type: episode + +? We.Bare.Bears.S01E14.Brother.Up.1080p.WEB-DL.AAC2.0.H.264-TVSmash/mxNMuJWeO7PUWCMEwqKSsS6D8Vs9S6V3PHD.mkv +: title: We Bare Bears season: 1 - episode: 2 - episode_title: Nice Title - screen_size: 720p - streaming_service: Spike TV - format: WEBRip + episode: 14 + episode_title: Brother Up + screen_size: 1080p + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 - release_group: group + video_codec: H.264 + release_group: TVSmash + container: mkv type: episode -# Streaming service: IFC -? Show.Name.S01E02.Nice.Title.720p.IFC.WEBRip.AAC2.0.x264-group -: title: Show Name +? Beyond.S01E02.Tempus.Fugit.720p.FREE.WEBRip.AAC2.0.x264-BTW/gNWDXow11s7E0X7GTDrZ.mkv +: title: Beyond season: 1 episode: 2 - episode_title: Nice Title + episode_title: Tempus Fugit screen_size: 720p - streaming_service: IFC - format: WEBRip + source: Web + other: Rip audio_codec: AAC audio_channels: '2.0' - video_codec: h264 - release_group: group + video_codec: H.264 + release_group: BTW + container: mkv type: episode -# Streaming service: NATG -? Show.Name.S01E02.Nice.Title.720p.NATG.WEBRip.AAC2.0.x264-group -: title: Show Name - season: 1 +? Bones.S12E02.The.Brain.In.The.Bot.1080p.WEB-DL.DD5.1.H.264-R2D2/161219_06.mkv +: title: Bones + season: 12 episode: 2 - episode_title: Nice Title - screen_size: 720p - streaming_service: National Geographic - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: group + episode_title: The Brain In The Bot + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: R2D2 + container: mkv type: episode -# Streaming service: NFL -? Show.Name.S01E02.Nice.Title.720p.NFL.WEBRip.AAC2.0.x264-group -: title: Show Name +? The.Messengers.2015.S01E07.1080p.WEB-DL.DD5.1.H264.Nlsubs-Q/QoQ-sbuSLN.462.H.1.5DD.LD-BEW.p0801.70E10S.5102.sregnesseM.ehT.mkv +: title: The Messengers + year: 2015 season: 1 - episode: 2 - episode_title: Nice Title - screen_size: 720p - streaming_service: NFL - format: WEBRip + episode: 7 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + subtitle_language: nl + release_group: Q + container: mkv + type: episode + +? /Finding.Carter.S02E01.Love.the.Way.You.Lie.1080p.WEB-DL.AAC2.0.H.264-NL/LN-462.H.0.2CAA.LD-BEW.p0801.eiL.uoY.yaW.eht.evoL.10E20S.retraC.gnidniF.mkv +: title: Finding Carter + season: 2 + episode: 1 + episode_title: Love the Way You Lie + screen_size: 1080p + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 - release_group: group + video_codec: H.264 + release_group: NL + container: mkv + type: episode + +? Mr.Robot.S02E12.1080p.WEB-DL.DD5.1-NL.Subs-Het.Robot.Team.OYM/sbuS LN-1.5DD LD-BEW p0801 21E20S toboR .rM.mkv +: title: Mr Robot + season: 2 + episode: 12 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + release_group: Het.Robot.Team.OYM type: episode -# Streaming service: UFC -? Show.Name.S01E02.Nice.Title.720p.UFC.WEBRip.AAC2.0.x264-group +? Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT +? /Show Name/Season 01/Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT +? /Show Name/Temporada 01/Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT : title: Show Name season: 1 episode: 2 - episode_title: Nice Title screen_size: 720p - streaming_service: UFC - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: group + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT type: episode -# Streaming service: TV Land -? Show.Name.S01E02.Nice.Title.720p.TVL.WEBRip.AAC2.0.x264-group +# newpct +? Show Name - Temporada 4 [HDTV][Cap.408][Espanol Castellano] +? Show Name - Temporada 4 [HDTV][Cap.408][Español Castellano] : title: Show Name - season: 1 - episode: 2 - episode_title: Nice Title - screen_size: 720p - streaming_service: TV Land - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: group + season: 4 + episode: 8 + source: HDTV + language: ca type: episode -# Streaming service: Crunchy Roll -? Show.Name.S01.1080p.CR.WEBRip.AAC.2.0.x264-monkee +# newpct +? -Show Name - Temporada 4 [HDTV][Cap.408][Espanol Castellano] +? -Show Name - Temporada 4 [HDTV][Cap.408][Español Castellano] +: release_group: Castellano + +# newpct +? Show.Name.-.Temporada1.[HDTV][Cap.105][Español.Castellano] : title: Show Name + source: HDTV season: 1 - screen_size: 1080p - streaming_service: Crunchy Roll - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + episode: 5 + language: ca type: episode -# Streaming service: Disney -? Show.Name.S01.1080p.DSNY.WEBRip.AAC.2.0.x264-monkee +# newpct +? Show.Name.-.Temporada1.[HDTV][Cap.105][Español] : title: Show Name + source: HDTV season: 1 - screen_size: 1080p - streaming_service: Disney - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + episode: 5 + language: es type: episode -# Streaming service: Nickelodeon -? Show.Name.S01.1080p.NICK.WEBRip.AAC.2.0.x264-monkee +# newpct - season and episode with range: +? Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102_104]SPANISH.AUDIO-NEWPCT : title: Show Name season: 1 - screen_size: 1080p - streaming_service: Nickelodeon - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + episode: [2, 3, 4] + screen_size: 720p + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT type: episode -# Streaming service: TFou -? Show.Name.S01.1080p.TFOU.WEBRip.AAC.2.0.x264-monkee +# newpct - season and episode (2 digit season) +? Show.Name.-.Temporada.15.720p.HDTV.x264[Cap.1503]SPANISH.AUDIO-NEWPCT : title: Show Name - season: 1 - screen_size: 1080p - streaming_service: TFou - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: monkee + season: 15 + episode: 3 + screen_size: 720p + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT type: episode -? frasier.s8e6-768660.srt -: container: srt - episode: 6 - episode_title: '768660' - season: 8 - title: frasier +# newpct - season and episode (2 digit season with range) +? Show.Name.-.Temporada.15.720p.HDTV.x264[Cap.1503_1506]SPANISH.AUDIO-NEWPCT +: title: Show Name + season: 15 + episode: [3, 4, 5, 6] + screen_size: 720p + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT type: episode -? Show.Name.S03E15.480p.177mb.Proper.HDTV.x264 +# newpct - season and episode: +? Show.Name.-.Temp.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT : title: Show Name - season: 3 - episode: 15 - screen_size: 480p - size: 177MB - other: Proper - proper_count: 1 - format: HDTV - video_codec: h264 + season: 1 + episode: 2 + screen_size: 720p + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT type: episode -? Show.Name.S03E15.480p.4.8GB.Proper.HDTV.x264 +# newpct - season and episode: +? Show.Name.-.Tem.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT : title: Show Name - season: 3 - episode: 15 - screen_size: 480p - size: 4.8GB - other: Proper - proper_count: 1 - format: HDTV - video_codec: h264 + season: 1 + episode: 2 + screen_size: 720p + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT type: episode -? Show.Name.S03.1.1TB.Proper.HDTV.x264 +# newpct - season and episode: +? Show.Name.-.Tem.1.720p.HDTV.x264[Cap.112_114.Final]SPANISH.AUDIO-NEWPCT : title: Show Name - season: 3 - size: 1.1TB - other: Proper - proper_count: 1 - format: HDTV - video_codec: h264 + season: 1 + episode: [12, 13, 14] + screen_size: 720p + source: HDTV + video_codec: H.264 + language: es + release_group: NEWPCT + episode_details: Final type: episode -? Some.Show.S02E14.1080p.HDTV.X264-reenc.GROUP -? Some.Show.S02E14.1080p.HDTV.X264-re-enc.GROUP -? Some.Show.S02E14.1080p.HDTV.X264-re-encoded.GROUP -? Some.Show.S02E14.1080p.HDTV.X264-reencoded.GROUP -: title: Some Show - season: 2 - episode: 14 - screen_size: 1080p - format: HDTV - video_codec: h264 - other: ReEncoded - release_group: GROUP +? Mastercook Italia - Stagione 6 (2016) 720p ep13 spyro.mkv +: title: Mastercook Italia + season: 6 + episode: 13 + year: 2016 + screen_size: 720p + episode_title: spyro + container: mkv type: episode -# DDP is DD+ -? Show.Name.2016.S01E01.2160p.AMZN.WEBRip.DDP5.1.x264-Group -: title: Show Name +? Mastercook Italia - Stagione 6 (2016) 720p Episodio 13 spyro.mkv +: title: Mastercook Italia + season: 6 year: 2016 - season: 1 - episode: 1 - screen_size: 4K - streaming_service: Amazon Prime - format: WEBRip - audio_codec: EAC3 - audio_channels: '5.1' - video_codec: h264 - release_group: Group + screen_size: 720p + episode: 13 + episode_title: spyro + container: mkv type: episode -? Show Name S02e19 [Mux - H264 - Ita Aac] DLMux by UBi +# Italian releases +? Show Name 3x18 Un Tuffo Nel Passato ITA HDTVMux x264 NovaRip : title: Show Name - season: 2 - episode: 19 - video_codec: h264 + season: 3 + episode: 18 + episode_title: Un Tuffo Nel Passato language: it - audio_codec: AAC - format: WEB-DL + source: HDTV other: Mux - release_group: UBi + video_codec: H.264 + release_group: NovaRip type: episode -? Show Name S01e10[Mux - 1080p - H264 - Ita Eng Ac3 - Sub Ita Eng]DLMux By GiuseppeTnT Littlelinx -: title: Show Name - season: 1 - episode: 10 - screen_size: 1080p - video_codec: h264 - language: [it, en] - format: WEB-DL - other: Mux - audio_codec: AC3 - subtitle_language: [it, en] - release_group: GiuseppeTnT Littlelinx - type: episode - -? Show Name S04e07-08 [H264 - Ita Aac] HDTVMux by Group -: title: Show Name - season: 4 - episode: [7, 8] - video_codec: h264 - language: it - audio_codec: AAC - format: HDTV - other: Mux - release_group: Group - type: episode - -? Show Name 3x18 Un Tuffo Nel Passato ITA HDTVMux x264 Group +# Italian releases +? Show Name 3x18 Un Tuffo Nel Passato ITA HDTVMux x264 NovaRip : title: Show Name season: 3 episode: 18 episode_title: Un Tuffo Nel Passato language: it - format: HDTV + source: HDTV other: Mux - video_codec: h264 - release_group: Group + video_codec: H.264 + release_group: NovaRip type: episode -? Show.Name.S03.1080p.BlurayMUX.AVC.DTS-HD.MA +# Subbed: No language hint +? Show.Name.S06E03.1080p.HDTV.Legendado +: subtitle_language: und + +# Subbed: No language hint +? Show.Name.S01E09.Subbed.1080p.BluRay.x264-RRH : title: Show Name - season: 3 + season: 1 + episode: 9 + subtitle_language: und screen_size: 1080p - format: BluRay - other: Mux - video_codec: h264 - audio_codec: DTS - audio_profile: HDMA + source: Blu-ray + video_codec: H.264 + release_group: RRH type: episode -? Show.Name.-.07.(2016).[RH].[English.Dubbed][WEBRip]..[HD.1080p] -: options: -t episode - episode: 7 - format: WEBRip - language: en - other: HD +# Legendado PT-BR +? Show.Name.S06E05.1080p.WEBRip.Legendado.PT-BR +? Show.Name.S06E05.1080p.WEBRip.Legendas.PT-BR +? Show.Name.S06E05.1080p.WEBRip.Legenda.PT-BR +: title: Show Name + season: 6 + episode: 5 screen_size: 1080p - title: Show Name - type: episode - year: 2016 - -? Show.Name.-.476-479.(2007).[HorribleSubs][WEBRip]..[HD.720p] -: options: -t episode -E - episode: - - 476 - - 477 - - 478 - - 479 - format: WEBRip - other: HD - release_group: HorribleSubs - screen_size: 720p - title: Show Name - type: episode - year: 2007 - -? /11.22.63/Season 1/11.22.63.106.hdtv-abc -: options: -T 11.22.63 - title: 11.22.63 - season: 1 - episode: 6 - format: HDTV - release_group: abc + source: Web + other: Rip + subtitle_language: pt-BR type: episode -# Streaming service: DIY Network -? Show.Name.S01.720p.DIY.WEBRip.AAC2.0.H.264-BTN +? Show.Name.S01E07.Super, Title.WEB-DL 720p.br.srt : title: Show Name season: 1 + episode: 7 + episode_title: Super, Title + source: Web screen_size: 720p - streaming_service: DIY Network - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: BTN + subtitle_language: pt-BR + container: srt type: episode -# Streaming service: USA Network -? Show.Name.S01E02.Exfil.1080p.USAN.WEBRip.AAC2.0.x264-AJP69 +? -Show.Name.S01E07.Super, Title.WEB-DL 720p.br.srt +: language: pt-BR + +# Legendado PT +? Show.Name.S06E05.1080p.WEBRip.Legendado.PT : title: Show Name - season: 1 - episode: 2 + season: 6 + episode: 5 screen_size: 1080p - streaming_service: USA Network - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: AJP69 + source: Web + other: Rip + subtitle_language: pt type: episode -# Streaming service: TV3 Ireland -? Show.Name.S01E08.576p.TV3.WEBRip.AAC2.0.x264-HARiKEN +? Show.Name.S05E01.SPANISH.SUBBED.720p.HDTV.x264-sPHD : title: Show Name - season: 1 - episode: 8 - screen_size: 576p - streaming_service: TV3 Ireland - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: HARiKEN + season: 5 + episode: 1 + subtitle_language: spa + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: sPHD type: episode -# Streaming service: TV4 Sweeden -? Show.Name.S05.720p.TV4.WEBRip.AAC2.0.H.264-BTW +? Show.Name.S01E01.German.Subbed.HDTV.XviD-ASAP : title: Show Name - season: 5 - screen_size: 720p - streaming_service: TV4 Sweeden - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: BTW + season: 1 + episode: 1 + subtitle_language: deu + source: HDTV + video_codec: Xvid + release_group: ASAP type: episode -# Streaming service: TLC -? Show.Name.S02.720p.TLC.WEBRip.AAC2.0.x264-BTW +? Show.Name.S04E21.Aint.Nothing.Like.the.Real.Thing.German.Custom.Subbed.720p.HDTV.x264.iNTERNAL-BaCKToRG : title: Show Name - season: 2 + season: 4 + episode: 21 + episode_title: Aint Nothing Like the Real Thing + subtitle_language: deu screen_size: 720p - streaming_service: TLC - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: BTW + source: HDTV + video_codec: H.264 type: episode -# Streaming service: Investigation Discovery -? Show.Name.S01E01.720p.ID.WEBRip.AAC2.0.x264-BTW +? Show.Name.S01.Season.Complet.WEBRiP.Ro.Subbed.TM : title: Show Name season: 1 - episode: 1 - screen_size: 720p - streaming_service: Investigation Discovery - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: BTW + other: [Complete, Rip] + source: Web + subtitle_language: ro type: episode -# Streaming service: RTÉ One -? Show.Name.S10E01.576p.RTE.WEBRip.AAC2.0.H.264-RTN +? Show.Name.(2013).Season.3.-.Eng.Soft.Subtitles.720p.WEBRip.x264.[MKV,AC3,5.1].Ehhhh : title: Show Name - season: 10 - episode: 1 - screen_size: 576p - streaming_service: RTÉ One - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: RTN + year: 2013 + season: 3 + subtitle_language: en + screen_size: 720p + source: Web + other: Rip + video_codec: H.264 + container: mkv + audio_codec: Dolby Digital + audio_channels: '5.1' + release_group: Ehhhh type: episode -# Streaming service: AMC -? Show.Name.S01E01.1080p.AMC.WEBRip.H.264.AAC2.0-CasStudio +# Dublado +? Show.Name.S02E03.720p.HDTV.x264-Belex.-.Dual.Audio.-.Dublado : title: Show Name - season: 1 - episode: 1 - screen_size: 1080p - streaming_service: AMC - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: CasStudio + season: 2 + episode: 3 + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: Belex + other: Dual Audio + language: und type: episode -? Proof.2015.S01E10.1080p.WEB-DL.DD5.1.H.264-KINGS.mkv -: title: Proof - season: 1 +? Show.Name.S06E10.1080p.WEB-DL.DUAL.[Dublado].RK +: title: Show Name + season: 6 episode: 10 screen_size: 1080p - format: WEB-DL - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: KINGS - container: mkv + source: Web + other: Dual Audio + language: und + release_group: RK type: episode -# Hardcoded subtitles -? Show.Name.S06E16.HC.SWESUB.HDTV.x264 +? Show.Name.S06E12.720p.WEB-DL.Dual.Audio.Dublado : title: Show Name season: 6 - episode: 16 - other: Hardcoded Subtitles - format: HDTV - video_codec: h264 - subtitle_language: sv + episode: 12 + screen_size: 720p + source: Web + other: Dual Audio + language: und type: episode -? From [ WWW.TORRENTING.COM ] - White.Rabbit.Project.S01E08.1080p.NF.WEBRip.DD5.1.x264-ViSUM/White.Rabbit.Project.S01E08.1080p.NF.WEBRip.DD5.1.x264-ViSUM.mkv -: title: White Rabbit Project - website: WWW.TORRENTING.COM - season: 1 - episode: 8 - screen_size: 1080p - streaming_service: Netflix - format: WEBRip - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: ViSUM +? Show.Name.S05E07.720p.DUBLADO.HDTV.x264-0SEC-pia.mkv +: title: Show Name + season: 5 + episode: 7 + screen_size: 720p + language: und + source: HDTV + video_codec: H.264 + release_group: 0SEC-pia container: mkv type: episode -? /tv/Daniel Tiger's Neighborhood/S02E06 - Playtime Is Different.mp4 -: season: 2 - episode: 6 - title: Daniel Tiger's Neighborhood - episode_title: Playtime Is Different - container: mp4 +? Show.Name.S02E07.Shiva.AC3.Dubbed.WEBRip.x264 +: title: Show Name + season: 2 + episode: 7 + episode_title: Shiva + audio_codec: Dolby Digital + language: und + source: Web + other: Rip + video_codec: H.264 type: episode -? Zoo.S02E05.1080p.WEB-DL.DD5.1.H.264.HKD/160725_02.mkv -: title: Zoo - season: 2 - episode: 5 +# Legendas +? Show.Name.S05.1080p.BluRay.x264-Belex.-.Dual.Audio.+.Legendas +: title: Show Name + season: 5 screen_size: 1080p - format: WEB-DL - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: HKD - container: mkv + source: Blu-ray + video_codec: H.264 + release_group: Belex + other: Dual Audio + subtitle_language: und type: episode -? We.Bare.Bears.S01E14.Brother.Up.1080p.WEB-DL.AAC2.0.H.264-TVSmash/mxNMuJWeO7PUWCMEwqKSsS6D8Vs9S6V3PHD.mkv -: title: We Bare Bears - season: 1 - episode: 14 - episode_title: Brother Up +# Legendas +? Show.Name.S05.1080p.BluRay.x264-Belex.-.Dual.Audio.+.Legendas +: title: Show Name + season: 5 screen_size: 1080p - format: WEB-DL - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: TVSmash - container: mkv + source: Blu-ray + video_codec: H.264 + release_group: Belex + other: Dual Audio + subtitle_language: und type: episode -? Beyond.S01E02.Tempus.Fugit.720p.FREE.WEBRip.AAC2.0.x264-BTW/gNWDXow11s7E0X7GTDrZ.mkv -: title: Beyond +# Subtitulado +? Show.Name.S01E03.HDTV.Subtitulado.Esp.SC +? Show.Name.S01E03.HDTV.Subtitulado.Espanol.SC +? Show.Name.S01E03.HDTV.Subtitulado.Español.SC +: title: Show Name season: 1 - episode: 2 - episode_title: Tempus Fugit + episode: 3 + source: HDTV + subtitle_language: es + release_group: SC + type: episode + +# Subtitles/Subbed +? Show.Name.S02E08.720p.WEB-DL.Subtitles +? Show.Name.S02E08.Subbed.720p.WEB-DL +: title: Show Name + season: 2 + episode: 8 screen_size: 720p - format: WEBRip - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - release_group: BTW - container: mkv + source: Web + subtitle_language: und type: episode -? Bones.S12E02.The.Brain.In.The.Bot.1080p.WEB-DL.DD5.1.H.264-R2D2/161219_06.mkv -: title: Bones - season: 12 - episode: 2 - episode_title: The Brain In The Bot - screen_size: 1080p - format: WEB-DL - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: R2D2 - container: mkv +# Dubbed +? Show.Name.s01e01.german.Dubbed +: title: Show Name + season: 1 + episode: 1 + language: de type: episode -? The.Messengers.2015.S01E07.1080p.WEB-DL.DD5.1.H264.Nlsubs-Q/QoQ-sbuSLN.462.H.1.5DD.LD-BEW.p0801.70E10S.5102.sregnesseM.ehT.mkv -: title: The Messengers - year: 2015 +? Show.Name.S06E05.Das.Toor.German.AC3.Dubbed.HDTV.German +: title: Show Name + season: 6 + episode: 5 + language: de + audio_codec: Dolby Digital + source: HDTV + type: episode + +? Show.Name.S01E01.Savage.Season.GERMAN.DUBBED.WS.HDTVRip.x264-TVP +: title: Show Name season: 1 - episode: 7 + episode: 1 + episode_title: Savage Season + language: de + other: [Widescreen, Rip] + source: HDTV + video_codec: H.264 + release_group: TVP + type: episode + +# Dubbed +? "[AnimeRG].Show.Name.-.03.[Eng.Dubbed].[720p].[WEB-DL].[JRR]" +: title: Show Name + episode: 3 + language: en + screen_size: 720p + source: Web + release_group: JRR + type: episode + +# Dubbed +? "[RH].Show.Name.-.03.[English.Dubbed].[1080p]" +: title: Show Name + episode: 3 + language: en screen_size: 1080p - format: WEB-DL - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - subtitle_language: nl - release_group: Q - container: mkv + release_group: RH type: episode -? /Finding.Carter.S02E01.Love.the.Way.You.Lie.1080p.WEB-DL.AAC2.0.H.264-NL/LN-462.H.0.2CAA.LD-BEW.p0801.eiL.uoY.yaW.eht.evoL.10E20S.retraC.gnidniF.mkv -: title: Finding Carter +# Hebsubs +? Show.Name.S05E05.HDTV.XviD-AFG.HebSubs +: title: Show Name + season: 5 + episode: 5 + source: HDTV + video_codec: Xvid + release_group: AFG + subtitle_language: he + type: episode + +? Show Name - S02E31 - Episode 55 (720p.HDTV) +: title: Show Name season: 2 - episode: 1 - episode_title: Love the Way You Lie - screen_size: 1080p - format: WEB-DL - audio_codec: AAC - audio_channels: '2.0' - video_codec: h264 - language: nl - container: mkv + episode: 31 + episode_title: Episode 55 + screen_size: 720p + source: HDTV type: episode -? Mr.Robot.S02E12.1080p.WEB-DL.DD5.1-NL.Subs-Het.Robot.Team.OYM/sbuS LN-1.5DD LD-BEW p0801 21E20S toboR .rM.mkv -: title: Mr Robot +# Scenario: Removing invalid season and episode matches. Correct episode_title match +? Show.Name.S02E06.eps2.4.m4ster-s1ave.aes.1080p.AMZN.WEBRip.DD5.1.x264-GROUP +: title: Show Name season: 2 - episode: 12 + episode: 6 + episode_title: eps2 4 m4ster-s1ave aes screen_size: 1080p - format: WEB-DL - audio_codec: AC3 + streaming_service: Amazon Prime + source: Web + other: Rip + audio_codec: Dolby Digital audio_channels: '5.1' - release_group: Het.Robot.Team.OYM + video_codec: H.264 + release_group: GROUP type: episode -? Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT -? /Show Name/Season 01/Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT -? /Show Name/Temporada 01/Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT +? Show.Name.S01E05.3xpl0its.wmv.720p.WEBdl.EN-SUB.x264-[MULVAcoded].mkv : title: Show Name season: 1 - episode: 2 + episode: 5 + episode_title: 3xpl0its screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT + source: Web + subtitle_language: en + video_codec: H.264 type: episode -# newpct -? Show Name - Temporada 4 [HDTV][Cap.408][Espanol Castellano] -? Show Name - Temporada 4 [HDTV][Cap.408][Español Castellano] +# Regression: S4L release group detected as season 4 +# https://github.com/guessit-io/guessit/issues/352 +? Show Name S01E06 DVD-RIP x264-S4L : title: Show Name - season: 4 - episode: 8 - format: HDTV - language: ca + season: 1 + episode: 6 + source: DVD + video_codec: H.264 + release_group: S4L type: episode -# newpct -? -Show Name - Temporada 4 [HDTV][Cap.408][Espanol Castellano] -? -Show Name - Temporada 4 [HDTV][Cap.408][Español Castellano] -: release_group: Castellano +# Corner case with only date and 720p +? The.Show.Name.2016.05.18.720.HDTV.x264-GROUP.VTV +: title: The Show Name + date: 2016-05-18 + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: GROUP.VTV + type: episode -# newpct -? Show.Name.-.Temporada1.[HDTV][Cap.105][Español.Castellano] +# Corner case with only date and 720p +? -The.Show.Name.2016.05.18.720.HDTV.x264-GROUP.VTV +: season: 7 + episode: 20 + +# https://github.com/guessit-io/guessit/issues/308 (conflict with screen size) +? "[SuperGroup].Show.Name.-.06.[720.Hi10p][1F5578AC]" : title: Show Name - format: HDTV - season: 1 - episode: 5 - language: ca + episode: 6 + screen_size: 720p + color_depth: 10-bit + crc32: 1F5578AC + release_group: SuperGroup type: episode -# newpct -? Show.Name.-.Temporada1.[HDTV][Cap.105][Español] +# https://github.com/guessit-io/guessit/issues/308 (conflict with screen size) +? "[SuperGroup].Show.Name.-.06.[1080.Hi10p][1F5578AC]" : title: Show Name - format: HDTV - season: 1 + episode: 6 + screen_size: 1080p + color_depth: 10-bit + crc32: 1F5578AC + release_group: SuperGroup + type: episode + +? "[MK-Pn8].Dimension.W.-.05.[720p][Hi10][Dual][TV-Dub][EDA6E7F1]" +: options: -C us -L und + release_group: MK-Pn8 + title: Dimension W episode: 5 - language: es + screen_size: 720p + color_depth: 10-bit + other: Dual Audio + source: TV + language: und + crc32: EDA6E7F1 type: episode -# newpct - season and episode with range: -? Show.Name.-.Temporada.1.720p.HDTV.x264[Cap.102_104]SPANISH.AUDIO-NEWPCT +? "[Zero-Raws].Show.Name.493-498.&.500-507.(CX.1280x720.VFR.x264.AAC)" +: release_group: Zero-Raws + title: Show Name + episode: [493, 494, 495, 496, 497, 498, 500, 501, 502, 503, 504, 505, 506, 507] + screen_size: 720p + subtitle_language: fr + video_codec: H.264 + audio_codec: AAC + type: episode + +# NetflixUHD +? Show.Name.S01E06.NetflixUHD : title: Show Name season: 1 - episode: [2, 3, 4] - screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT + episode: 6 + streaming_service: Netflix + other: Ultra HD type: episode -# newpct - season and episode (2 digit season) -? Show.Name.-.Temporada.15.720p.HDTV.x264[Cap.1503]SPANISH.AUDIO-NEWPCT +? Show.Name.S04E13.FINAL.MULTI.DD51.2160p.NetflixUHDRip.x265-TVS : title: Show Name - season: 15 - episode: 3 - screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT + season: 4 + episode: 13 + episode_details: Final + language: mul + audio_codec: Dolby Digital + audio_channels: '5.1' + screen_size: 2160p + streaming_service: Netflix + source: Ultra HDTV + other: Rip + video_codec: H.265 + release_group: TVS type: episode -# newpct - season and episode (2 digit season with range) -? Show.Name.-.Temporada.15.720p.HDTV.x264[Cap.1503_1506]SPANISH.AUDIO-NEWPCT +? Show.Name.S06E11.Of.Late.I.Think.of.Rosewood.iTunesHD.x264 : title: Show Name - season: 15 - episode: [3, 4, 5, 6] + season: 6 + episode: 11 + episode_title: Of Late I Think of Rosewood + streaming_service: iTunes + other: HD + video_codec: H.264 + type: episode + +? Show.Name.S01.720p.iTunes.h264-Group +: title: Show Name + season: 1 screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT + streaming_service: iTunes + video_codec: H.264 + release_group: Group type: episode -# newpct - season and episode: -? Show.Name.-.Temp.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT +? Show.Name.1x01.eps1.0.hellofriend.(HDiTunes.Ac3.Esp).(2015).By.Malaguita.avi +: title: Show Name + season: 1 + episode: 1 + episode_title: eps1 0 hellofriend + other: HD + streaming_service: iTunes + audio_codec: Dolby Digital + language: spa + year: 2015 + container: avi + type: episode + +? "[Hanamaru&LoliHouse] The Dragon Dentist - 01 [WebRip 1920x1080 HEVC-yuv420p10 AAC].mkv" +: release_group: Hanamaru&LoliHouse + title: The Dragon Dentist + episode: 1 + source: Web + other: Rip + screen_size: 1080p + video_codec: H.265 + color_depth: 10-bit + audio_codec: AAC + container: mkv + type: episode + +? Show Name - Season 1 Episode 50 : title: Show Name season: 1 + episode: 50 + type: episode + +? Vikings.Seizoen.4.1080p.Web.NLsubs +: title: Vikings + season: 4 + screen_size: 1080p + source: Web + subtitle_language: nl + type: episode + +? Star.Wars.Rebels.S01E01.Spark.of.Rebellion.ALTERNATE.CUT.HDTV.x264-W4F.mp4 +: title: Star Wars Rebels + season: 1 + episode: 1 + episode_title: Spark of Rebellion + edition: Alternative Cut + source: HDTV + video_codec: H.264 + release_group: W4F + container: mp4 + type: episode + +? DCs.Legends.of.Tomorrow.S02E12.HDTV.XviD-FUM +: title: DCs Legends of Tomorrow + season: 2 + episode: 12 + source: HDTV + video_codec: Xvid + release_group: FUM + type: episode + +? DC's Legends of Tomorrow 2016 - S02E02 +: title: DC's Legends of Tomorrow + year: 2016 + season: 2 episode: 2 - screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT type: episode -# newpct - season and episode: -? Show.Name.-.Tem.1.720p.HDTV.x264[Cap.102]SPANISH.AUDIO-NEWPCT -: title: Show Name +? Broadchurch.S01.DIRFIX.720p.BluRay.x264-SHORTBREHD +: title: Broadchurch + season: 1 + other: Proper + screen_size: 720p + source: Blu-ray + video_codec: H.264 + release_group: SHORTBREHD + proper_count: 1 + type: episode + +? Simply Red - 2016-07-08 Montreux Jazz Festival 720p +: title: Simply Red + date: 2016-07-08 + episode_title: Montreux Jazz Festival + screen_size: 720p + type: episode + +? Ridiculousness.S07E14.iNTERNAL.HDTV.x264-YesTV +: title: Ridiculousness + season: 7 + episode: 14 + other: Internal + source: HDTV + video_codec: H.264 + release_group: YesTV + type: episode + +? Stephen.Colbert.2016.05.25.James.McAvoy.iNTERNAL.XviD-AFG +: title: Stephen Colbert + date: 2016-05-25 + episode_title: James McAvoy + other: Internal + video_codec: Xvid + release_group: AFG + type: episode + +? The.100.S01E13.iNTERNAL.READNFO.720p.HDTV.x264-2HD +: title: The 100 + season: 1 + episode: 13 + other: [Internal, Read NFO] + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: 2HD + type: episode + +? The.100.S01E13.READ.NFO.720p.HDTV.x264-2HD +: title: The 100 + season: 1 + episode: 13 + other: Read NFO + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: 2HD + type: episode + +? Dr.Ken.S01E21.SAMPLEFIX.720p.HDTV.x264-SVA +: title: Dr Ken + season: 1 + episode: 21 + other: Proper + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: SVA + type: episode + +? Rick and Morty Season 1 [UNCENSORED] [BDRip] [1080p] [HEVC] +: title: Rick and Morty + season: 1 + edition: Uncensored + other: Rip + source: Blu-ray + screen_size: 1080p + video_codec: H.265 + type: episode + +? 12.Monkeys.S01E01.LiMiTED.FRENCH.1080p.WEB-DL.H264-AUTHORiTY +: title: 12 Monkeys + season: 1 + episode: 1 + edition: Limited + language: french + screen_size: 1080p + source: Web + video_codec: H.264 + release_group: AUTHORiTY + type: episode + +? Undateable.2014.S03E05.West.Feed.HDTV.x264-2HD +: title: Undateable + year: 2014 + season: 3 + episode: 5 + other: West Coast Feed + source: HDTV + video_codec: H.264 + release_group: 2HD + type: episode + +? Undateable.2014.S02E07-E08.Live.Episode.West.Coast.Feed.HDTV.x264-2HD +: title: Undateable + year: 2014 + season: 2 + episode: [7, 8] + other: West Coast Feed + source: HDTV + video_codec: H.264 + release_group: 2HD + type: episode + +? Undateable.S03E01-E02.LIVE.EAST.FEED.720p.HDTV.x264-KILLERS +: title: Undateable + season: 3 + episode: [1, 2] + other: East Coast Feed + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: KILLERS + type: episode + +? Undateable.2014.S02E07.Live.Episode.East.Coast.Feed.HDTV.x264-2HD +: title: Undateable + year: 2014 + season: 2 + episode: 7 + other: East Coast Feed + source: HDTV + video_codec: H.264 + release_group: 2HD + type: episode + +? Undateable.2014.S02E07.East.Coast.Feed.720p.WEB-DL.DD5.1.H.264-NTb +: title: Undateable + year: 2014 + season: 2 + episode: 7 + other: East Coast Feed + screen_size: 720p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: NTb + type: episode + +? True Detective S02E04 720p HDTV x264-0SEC [GloDLS].mkv +: title: True Detective + season: 2 + episode: 4 + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: 0SEC [GloDLS] + container: mkv + type: episode + +? Anthony.Bourdain.Parts.Unknown.S09E01.Los.Angeles.720p.HDTV.x264-MiNDTHEGAP +: title: Anthony Bourdain Parts Unknown + season: 9 + episode: 1 + episode_title: Los Angeles + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: MiNDTHEGAP + type: episode + +? -feud.s01e05.and.the.winner.is.(the.oscars.of.1963).720p.amzn.webrip.dd5.1.x264-casstudio.mkv +: year: 1963 + +? feud.s01e05.and.the.winner.is.(the.oscars.of.1963).720p.amzn.webrip.dd5.1.x264-casstudio.mkv +: title: feud + season: 1 + episode: 5 + episode_title: and the winner is + screen_size: 720p + streaming_service: Amazon Prime + source: Web + other: Rip + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: casstudio + container: mkv + type: episode + +? Adventure.Time.S08E16.Elements.Part.1.Skyhooks.720p.WEB-DL.AAC2.0.H.264-RTN.mkv +: title: Adventure Time + season: 8 + episode: 16 + episode_title: Elements Part 1 Skyhooks + screen_size: 720p + source: Web + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: RTN + container: mkv + type: episode + +? D:\TV\SITCOMS (CLASSIC)\That '70s Show\Season 07\That '70s Show - S07E22 - 2000 Light Years from Home.mkv +: title: That '70s Show + season: 7 + episode: 22 + episode_title: 2000 Light Years from Home + container: mkv + type: episode + +? Show.Name.S02E01.Super.Title.720p.WEB-DL.DD5.1.H.264-ABC.nzb +: title: Show Name + season: 2 + episode: 1 + episode_title: Super Title + screen_size: 720p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: ABC + container: nzb + type: episode + +? "[SGKK] Bleach 312v1 [720p/mkv]-Group.mkv" +: title: Bleach + episode: 312 + version: 1 + screen_size: 720p + release_group: Group + container: mkv + type: episode + +? The.Expanse.S02E08.720p.WEBRip.x264.EAC3-KiNGS.mkv +: title: The Expanse + season: 2 + episode: 8 + screen_size: 720p + source: Web + other: Rip + video_codec: H.264 + audio_codec: Dolby Digital Plus + release_group: KiNGS + container: mkv + type: episode + +? Series_name.2005.211.episode.title.avi +: title: Series name + year: 2005 + season: 2 + episode: 11 + episode_title: episode title + container: avi + type: episode + +? the.flash.2014.208.hdtv-lol[ettv].mkv +: title: the flash + year: 2014 + season: 2 + episode: 8 + source: HDTV + release_group: lol[ettv] + container: mkv + type: episode + +? "[Despair-Paradise].Kono.Subarashii.Sekai.ni.Shukufuku.wo!.2.-..09.vostfr.FHD" +: release_group: Despair-Paradise + title: Kono Subarashii Sekai ni Shukufuku wo! 2 + episode: 9 + subtitle_language: fr + other: Full HD + type: episode + +? Whose Line is it anyway/Season 01/Whose.Line.is.it.Anyway.US.S13E01.720p.WEB.x264-TBS.mkv +: title: Whose Line is it Anyway + season: 13 + episode: 1 + country: US + screen_size: 720p + source: Web + video_codec: H.264 + release_group: TBS + container: mkv + type: episode + +? Planet.Earth.II.S01.2160p.UHD.BluRay.HDR.DTS-HD.MA5.1.x265-ULTRAHDCLUB +: title: Planet Earth II + season: 1 + screen_size: 2160p + source: Ultra HD Blu-ray + other: HDR10 + audio_codec: DTS-HD + audio_profile: Master Audio + audio_channels: '5.1' + video_codec: H.265 + release_group: ULTRAHDCLUB + type: episode + +? Reizen.Waes.S03.FLEMISH.1080p.HDTV.MP2.H.264-NOGRP/Reizen.Waes.S03E05.China.PART1.FLEMISH.1080p.HDTV.MP2.H.264-NOGRP.mkv +: title: Reizen Waes + season: 3 + episode: 5 + part: 1 + language: nl-BE + screen_size: 1080p + source: HDTV + video_codec: H.264 + release_group: NOGRP + container: mkv + type: episode + +? "/folder/Marvels.Agent.Carter.S02E05.The.Atomic.Job.1080p.WEB-DL.DD5.1.H264-Coo7[rartv]/Marvel's.Agent.Carter.S02E05.The.Atomic.Job.1080p.WEB-DL.DD5.1.H.264-Coo7.mkv" +: title: Marvel's Agent Carter + season: 2 + episode: 5 + episode_title: The Atomic Job + release_group: Coo7 + type: episode + +? My.Name.Is.Earl.S01-S04.DVDRip.XviD-AR +: title: My Name Is Earl + season: [1, 2, 3, 4] + source: DVD + other: Rip + video_codec: Xvid + release_group: AR + type: episode + +? American.Dad.S01E01.Pilot.DVDRip.x264-CS +: title: American Dad + season: 1 + episode: 1 + episode_details: Pilot + source: DVD + other: Rip + video_codec: H.264 + release_group: CS + type: episode + +? Black.Sails.S01E01.HDTV.XviD.HebSubs-DR +: title: Black Sails + season: 1 + episode: 1 + source: HDTV + video_codec: Xvid + subtitle_language: he + release_group: DR + type: episode + +? The.West.Wing.S04E06.Game.On.720p.WEB-DL.AAC2.0.H.264-MC +: title: The West Wing + season: 4 + episode: 6 + episode_title: Game On + screen_size: 720p + source: Web + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: MC + type: episode + +? 12.Monkeys.S02E05.1080p.WEB-DL.DD5.1.H.264-NA +: title: 12 Monkeys + season: 2 + episode: 5 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: NA + type: episode + +? Fear.the.Walking.Dead.S03E07.1080p.AMZN.WEBRip.DD5.1.x264-VLAD[rarbg]/Fear.the.Walking.Dead.S03E07.1080p.AMZN.WEB-DL.DD+5.1.H.264-VLAD.mkv +: title: Fear the Walking Dead + season: 3 + episode: 7 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital Plus + audio_channels: '5.1' + video_codec: H.264 + release_group: VLAD + container: mkv + type: episode + +? American.Crime.S01E02.1080p.WEB-DL.DD5.1.H.264-NL +: title: American Crime + season: 1 + episode: 2 + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: NL + type: episode + +? Better.Call.Saul.S02.720p.HDTV.x264-TL +: title: Better Call Saul + season: 2 + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: TL + type: episode + +? 60.Minutes.2008.12.14.HDTV.XviD-YT +: options: -T '60 Minutes' + title: 60 Minutes + date: 2008-12-14 + source: HDTV + video_codec: Xvid + release_group: YT + type: episode + +? Storm.Chasers.Season.1 +: title: Storm Chasers season: 1 - episode: 2 - screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT type: episode -# newpct - season and episode: -? Show.Name.-.Tem.1.720p.HDTV.x264[Cap.112_114.Final]SPANISH.AUDIO-NEWPCT -: title: Show Name - season: 1 - episode: [12, 13, 14] +? Faking.It.2014.S03E08.720p.HDTV.x264-AVS +: title: Faking It + year: 2014 + season: 3 + episode: 8 screen_size: 720p - format: HDTV - video_codec: h264 - language: es - release_group: NEWPCT - other: FINAL + source: HDTV + video_codec: H.264 + release_group: AVS type: episode -? Mastercook Italia - Stagione 6 (2016) 720p ep13 spyro.mkv -: title: Mastercook Italia - season: 6 - episode: 13 - year: 2016 - screen_size: 720p - episode_title: spyro +? /series/Marvel's Agents of S.H.I.E.L.D/Season 4/Marvels.Agents.of.S.H.I.E.L.D.S04E01.The.Ghost.1080p.WEB-DL.DD5.1.H.264-AG.mkv +: title: Marvels Agents of S.H.I.E.L.D. + season: 4 + episode: 1 + episode_title: The Ghost + screen_size: 1080p + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: AG container: mkv type: episode -? Mastercook Italia - Stagione 6 (2016) 720p Episodio 13 spyro.mkv -: title: Mastercook Italia - season: 6 - year: 2016 - screen_size: 720p - episode: 13 - episode_title: spyro +? "[FASubs & TTF] Inuyasha - 099 [DVD] [B15AA1AC].mkv" +: release_group: FASubs & TTF + title: Inuyasha + episode: 99 + source: DVD + crc32: B15AA1AC container: mkv type: episode -# Italian releases -? Show Name 3x18 Un Tuffo Nel Passato ITA HDTVMux x264 NovaRip +? Show.Name.S01E03.PL.SUBBED.480p.WEBRiP.x264 : title: Show Name - season: 3 - episode: 18 - episode_title: Un Tuffo Nel Passato - language: it - format: HDTV - other: Mux - video_codec: h264 - release_group: NovaRip + season: 1 + episode: 3 + subtitle_language: pl + screen_size: 480p + source: Web + other: Rip + video_codec: H.264 type: episode -# Italian releases -? Show Name 3x18 Un Tuffo Nel Passato ITA HDTVMux x264 NovaRip -: options: --allowed-languages it - title: Show Name - season: 3 - episode: 18 - episode_title: Un Tuffo Nel Passato - language: it - format: HDTV - other: Mux - video_codec: h264 - release_group: NovaRip +? Show.Name.s10e15(233).480p.BDRip-AVC.Ukr.hurtom +: title: Show Name + season: 10 + episode: 15 + screen_size: 480p + source: Blu-ray + other: Rip + video_codec: H.264 + language: uk + release_group: hurtom type: episode -# Subbed: No language hint -? Show.Name.S06E03.1080p.HDTV.Legendado -: subtitle_language: und - -# Subbed: No language hint -? Show.Name.S01E09.Subbed.1080p.BluRay.x264-RRH -: title: Show Name +? Goof.Troop.1x24.Waste.Makes.Haste.720p.HDTV.x264.CZ-SDTV +: title: Goof Troop season: 1 - episode: 9 - subtitle_language: und - screen_size: 1080p - format: BluRay - video_codec: h264 - release_group: RRH + episode: 24 + episode_title: Waste Makes Haste + screen_size: 720p + source: HDTV + video_codec: H.264 + language: cs + release_group: SDTV type: episode -# Legendado PT-BR -? Show.Name.S06E05.1080p.WEBRip.Legendado.PT-BR -? Show.Name.S06E05.1080p.WEBRip.Legendas.PT-BR -? Show.Name.S06E05.1080p.WEBRip.Legenda.PT-BR -: title: Show Name - season: 6 - episode: 5 - screen_size: 1080p - format: WEBRip - subtitle_language: pt-BR +? Marvels.Daredevil.S02E11.German.DL.DUBBED.2160p.WebUHD.x264-UHDTV +: title: Marvels Daredevil + season: 2 + episode: 11 + language: [de, mul] + screen_size: 2160p + source: Web + video_codec: H.264 + release_group: UHDTV type: episode -? Show.Name.S01E07.Super, Title.WEB-DL 720p.br.srt -: title: Show Name - season: 1 - episode: 7 - episode_title: Super, Title - format: WEB-DL +? BBC The Story of China 1 of 6 - Ancestors CC HDTV x264 AC3 2.0 720p mkv +: title: BBC The Story of China + episode: 1 + episode_count: 6 + episode_title: Ancestors + source: HDTV + video_codec: H.264 + audio_codec: Dolby Digital + audio_channels: '2.0' screen_size: 720p - subtitle_language: pt-BR - container: srt + container: mkv type: episode -? -Show.Name.S01E07.Super, Title.WEB-DL 720p.br.srt -: language: pt-BR +? Duck.Dynasty.S09E04.Drone.Survivor.720p.AE.WEBRip.AAC2.0.H264-BTW[rartv] +: title: Duck Dynasty + season: 9 + episode: 4 + episode_title: Drone Survivor + screen_size: 720p + streaming_service: A&E + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTW[rartv] + type: episode -# Legendado PT -? Show.Name.S06E05.1080p.WEBRip.Legendado.PT -: title: Show Name - season: 6 - episode: 5 +? Mr.Selfridge.S04E03.720p.WEB-DL.AAC2.0.H264-MS[rartv] +: title: Mr Selfridge + season: 4 + episode: 3 + screen_size: 720p + source: Web + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: MS[rartv] + type: episode + +? Second.Chance.S01E02.One.More.Notch.1080p.WEB-DL.DD5.1.H264-SC[rartv] +: title: Second Chance + season: 1 + episode: 2 + episode_title: One More Notch screen_size: 1080p - format: WEBRip - subtitle_language: pt + source: Web + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: rartv type: episode -? Show.Name.S05E01.SPANISH.SUBBED.720p.HDTV.x264-sPHD -: title: Show Name +? Total.Divas.S05E01.720p.HDTV.AAC2.0.H.264-SC-SDH +: title: Total Divas season: 5 episode: 1 - subtitle_language: spa screen_size: 720p - format: HDTV - video_codec: h264 - release_group: sPHD + source: HDTV + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: SDH type: episode -? Show.Name.S01E01.German.Subbed.HDTV.XviD-ASAP -: title: Show Name +? Marvel's Jessica Jones (2015) s01e09 - AKA Sin Bin.mkv +: title: Marvel's Jessica Jones season: 1 - episode: 1 - subtitle_language: deu - format: HDTV - video_codec: XviD - release_group: ASAP + episode: 9 + episode_title: AKA Sin Bin + container: mkv type: episode -? Show.Name.S04E21.Aint.Nothing.Like.the.Real.Thing.German.Custom.Subbed.720p.HDTV.x264.iNTERNAL-BaCKToRG -: title: Show Name - season: 4 - episode: 21 - episode_title: Aint Nothing Like the Real Thing - subtitle_language: deu +? Hotel.Hell.S01E01.720p.DD5.1.448kbps-ALANiS +: title: Hotel Hell + season: 1 + episode: 1 screen_size: 720p - format: HDTV - video_codec: h264 + audio_codec: Dolby Digital + audio_channels: '5.1' + audio_bit_rate: 448Kbps + release_group: ALANiS type: episode -? Show.Name.S01.Season.Complet.WEBRiP.Ro.Subbed.TM -: title: Show Name +? Greys.Anatomy.S07D1.NTSC.DVDR-ToF +: title: Greys Anatomy + season: 7 + disc: 1 + other: NTSC + source: DVD + release_group: ToF + type: episode + +? Greys.Anatomy.S07D1.NTSC.DVDR-ToF +: title: Greys Anatomy + season: 7 + disc: 1 + other: NTSC + source: DVD + release_group: ToF + type: episode + +? Greys.Anatomy.S07D1-3&5.NTSC.DVDR-ToF +: title: Greys Anatomy + season: 7 + disc: [1, 2, 3, 5] + other: NTSC + source: DVD + release_group: ToF + type: episode + +? El.Principe.2014.S01D01.SPANiSH.COMPLETE.BLURAY-COJONUDO +: title: El Principe + year: 2014 season: 1 + disc: 1 + language: spa other: Complete - format: WEBRip - subtitle_language: ro + source: Blu-ray + release_group: COJONUDO type: episode -? Show.Name.(2013).Season.3.-.Eng.Soft.Subtitles.720p.WEBRip.x264.[MKV,AC3,5.1].Ehhhh -: title: Show Name - year: 2013 - season: 3 - subtitle_language: en - screen_size: 720p - format: WEBRip - video_codec: h264 - container: mkv - audio_codec: AC3 - audio_channels: '5.1' - release_group: Ehhhh +? The Simpsons - Season 2 Complete [DVDRIP VP7 KEGGERMAN +: title: The Simpsons + season: 2 + other: [Complete, Rip] + source: DVD + video_codec: VP7 + release_group: KEGGERMAN type: episode -# Dublado -? Show.Name.S02E03.720p.HDTV.x264-Belex.-.Dual.Audio.-.Dublado -: title: Show Name - season: 2 - episode: 3 - screen_size: 720p - format: HDTV - video_codec: h264 - release_group: Belex - other: DualAudio - language: und +? Barney & Friends_ Easy as ABC (Season 9_ Episode 15)_VP8_Vorbis_360p.webm +: title: Barney & Friends Easy as ABC + season: 9 + episode: 15 + video_codec: VP8 + audio_codec: Vorbis + screen_size: 360p + container: webm type: episode -? Show.Name.S06E10.1080p.WEB-DL.DUAL.[Dublado].RK -: title: Show Name - season: 6 - episode: 10 +? Victoria.S01.1080p.BluRay.HEVC.DTSMA.LPCM.PGS-OZM +: title: Victoria + season: 1 screen_size: 1080p - format: WEB-DL - other: DualAudio - language: und - release_group: RK + source: Blu-ray + video_codec: H.265 + audio_codec: [DTS-HD, LPCM] + audio_profile: Master Audio + # Does it worth to add subtitle_format? Such rare case + # subtitle_format: PGS + # release_group: OZM type: episode -? Show.Name.S06E12.720p.WEB-DL.Dual.Audio.Dublado -: title: Show Name - season: 6 - episode: 12 - screen_size: 720p - format: WEB-DL - other: DualAudio - language: und +? The.Prisoners.S01E03.1080p.DM.AAC2.0.x264-BTN +: title: The Prisoners + season: 1 + episode: 3 + screen_size: 1080p + source: Digital Master + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTN type: episode -? Show.Name.S05E07.720p.DUBLADO.HDTV.x264-0SEC-pia.mkv -: title: Show Name - season: 5 - episode: 7 - screen_size: 720p - language: und - format: HDTV - video_codec: h264 - release_group: 0SEC-pia - container: mkv +? Panorama.S2013E25.Broken.by.Battle.1080p.DM.AAC2.0.x264-BTN +: title: Panorama + season: 2013 + episode: 25 + episode_title: Broken by Battle + screen_size: 1080p + source: Digital Master + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTN type: episode -? Show.Name.S02E07.Shiva.AC3.Dubbed.WEBRip.x264 -: title: Show Name - season: 2 - episode: 7 - episode_title: Shiva - audio_codec: AC3 - language: und - format: WEBRip - video_codec: h264 +? Our.World.S2014E11.Chinas.Model.Army.720p.DM.AAC2.0.x264-BTN +: title: Our World + season: 2014 + episode: 11 + episode_title: Chinas Model Army + screen_size: 720p + source: Digital Master + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTN type: episode -# Legendas -? Show.Name.S05.1080p.BluRay.x264-Belex.-.Dual.Audio.+.Legendas -: title: Show Name - season: 5 +? Storyville.S2016E08.My.Nazi.Legacy.1080p.DM.x264-BTN +: title: Storyville + season: 2016 + episode: 8 + episode_title: My Nazi Legacy screen_size: 1080p - format: BluRay - video_codec: h264 - release_group: Belex - other: DualAudio - subtitle_language: und + source: Digital Master + video_codec: H.264 + release_group: BTN type: episode -# Legendas -? Show.Name.S05.1080p.BluRay.x264-Belex.-.Dual.Audio.+.Legendas -: options: --allowed-languages und - title: Show Name - season: 5 +? Comedians.in.Cars.Getting.Coffee.S07E01.1080p.DM.FLAC2.0.x264-NTb +: title: Comedians in Cars Getting Coffee + season: 7 + episode: 1 screen_size: 1080p - format: BluRay - video_codec: h264 - release_group: Belex - other: DualAudio - subtitle_language: und + source: Digital Master + audio_codec: FLAC + audio_channels: '2.0' + video_codec: H.264 + release_group: NTb type: episode -# Subtitulado -? Show.Name.S01E03.HDTV.Subtitulado.Esp.SC -? Show.Name.S01E03.HDTV.Subtitulado.Espanol.SC -? Show.Name.S01E03.HDTV.Subtitulado.Español.SC -# SC is a release group, not a language. To be addressed in #296 -: options: --allowed-languages spa --allowed-countries ESP +? "[SomeGroup-Fansub]_Show_Name_727_[VOSTFR][HD_1280x720]" +: release_group: SomeGroup-Fansub title: Show Name - season: 1 - episode: 3 - format: HDTV - subtitle_language: es - release_group: SC + episode: 727 + subtitle_language: fr + other: HD + screen_size: 720p type: episode -# Subtitles/Subbed -? Show.Name.S02E08.720p.WEB-DL.Subtitles -? Show.Name.S02E08.Subbed.720p.WEB-DL -: title: Show Name - season: 2 - episode: 8 +? "[GROUP]Show_Name_726_[VOSTFR]_[V1]_[8bit]_[720p]_[2F7B3FA2]" +: release_group: GROUP + title: Show Name + episode: 726 + subtitle_language: fr + version: 1 + color_depth: 8-bit screen_size: 720p - format: WEB-DL - subtitle_language: und + crc32: 2F7B3FA2 type: episode -# Dubbed -? Show.Name.s01e01.german.Dubbed +? Show Name 445 VOSTFR par Fansub-Resistance (1280*720) - version MQ : title: Show Name - season: 1 - episode: 1 - language: de + episode: 445 + subtitle_language: fr + screen_size: 720p type: episode -? Show.Name.S06E05.Das.Toor.German.AC3.Dubbed.HDTV.German -: title: Show Name - season: 6 - episode: 5 - language: de - audio_codec: AC3 - format: HDTV +? Anime Show Episode 159 v2 [VOSTFR][720p][AAC].mp4 +: title: Anime Show + episode: 159 + version: 2 + subtitle_language: fr + screen_size: 720p + audio_codec: AAC + container: mp4 type: episode -? Show.Name.S01E01.Savage.Season.GERMAN.DUBBED.WS.HDTVRip.x264-TVP -: title: Show Name - season: 1 - episode: 1 - episode_title: Savage Season - language: de - other: WideScreen - format: HDTV - video_codec: h264 - release_group: TVP +? "[Group] Anime Super Episode 161 [VOSTFR][720p].mp4" +: release_group: Group + title: Anime Super + episode: 161 + subtitle_language: fr + screen_size: 720p + container: mp4 type: episode -# Dubbed -? "[AnimeRG].Show.Name.-.03.[Eng.Dubbed].[720p].[WEB-DL].[JRR]" -: title: Show Name - episode: 3 - language: en +? Anime Show Episode 59 v2 [VOSTFR][720p][AAC].mp4 +: title: Anime Show + episode: 59 + version: 2 + subtitle_language: fr screen_size: 720p - format: WEB-DL - release_group: JRR + audio_codec: AAC + container: mp4 type: episode -# Dubbed -? "[RH].Show.Name.-.03.[English.Dubbed].[1080p]" +? Show.Name.-.476-479.(2007).[HorribleSubs][WEBRip]..[HD.720p] : title: Show Name - episode: 3 - language: en - screen_size: 1080p - release_group: RH + episode: [476, 477, 478, 479] + year: 2007 + release_group: HorribleSubs + source: Web + other: [Rip, HD] + screen_size: 720p type: episode -# Hebsubs -? Show.Name.S05E05.HDTV.XviD-AFG.HebSubs +? Show Name - 722 [HD_1280x720].mp4 : title: Show Name - season: 5 - episode: 5 - format: HDTV - video_codec: XviD - release_group: AFG - subtitle_language: he + episode: 722 + other: HD + screen_size: 720p + container: mp4 type: episode -? Show Name - S02E31 - Episode 55 (720p.HDTV) -: title: Show Name - season: 2 - episode: 31 - episode_title: Episode 55 +? Show!.Name.2.-.10.(2016).[HorribleSubs][WEBRip]..[HD.720p] +: title: Show! Name 2 + episode: 10 + year: 2016 + release_group: HorribleSubs + source: Web + other: [Rip, HD] screen_size: 720p - format: HDTV type: episode -# Scenario: Removing invalid season and episode matches. Correct episode_title match -? Show.Name.S02E06.eps2.4.m4ster-s1ave.aes.1080p.AMZN.WEBRip.DD5.1.x264-GROUP -: title: Show Name - season: 2 - episode: 6 - episode_title: eps2 4 m4ster-s1ave aes - screen_size: 1080p - streaming_service: Amazon Prime - format: WEBRip - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 +? 'C:\folder\[GROUP]_An_Anime_Show_100_-_10_[1080p]_mkv' +: options: -T 'An Anime Show 100' release_group: GROUP + title: An Anime Show 100 + episode: 10 + screen_size: 1080p + container: mkv type: episode -? Show.Name.S01E05.3xpl0its.wmv.720p.WEBdl.EN-SUB.x264-[MULVAcoded].mkv -: title: Show Name - season: 1 +? "[Group].Show.Name!.Super!!.-.05.[720p][AAC].mp4" +: release_group: Group + title: Show Name! Super!! episode: 5 - episode_title: 3xpl0its screen_size: 720p - format: WEB-DL - subtitle_language: en - video_codec: h264 + audio_codec: AAC + container: mp4 type: episode -# Regression: S4L release group detected as season 4 -# https://github.com/guessit-io/guessit/issues/352 -? Show Name S01E06 DVD-RIP x264-S4L -: title: Show Name - season: 1 - episode: 6 - format: DVD - video_codec: h264 - release_group: S4L +? "[GROUP].Mobile.Suit.Gundam.Unicorn.RE.0096.-.14.[720p].mkv" +: options: -T 'Mobile Suit Gundam Unicorn RE 0096' + release_group: GROUP + title: Mobile Suit Gundam Unicorn RE 0096 + episode: 14 + screen_size: 720p + container: mkv type: episode -# Corner case with only date and 720p -? The.Show.Name.2016.05.18.720.HDTV.x264-GROUP.VTV -: title: The Show Name - date: 2016-05-18 +? Show.Name.-.Other Name.-.02.(1280x720.HEVC.AAC) +: title: Show Name + alternative_title: Other Name + episode: 2 screen_size: 720p - format: HDTV - video_codec: h264 - release_group: GROUP.VTV + video_codec: H.265 + audio_codec: AAC type: episode -# Corner case with only date and 720p -? -The.Show.Name.2016.05.18.720.HDTV.x264-GROUP.VTV -: season: 7 - episode: 20 +? "[GroupName].Show.Name.-.02.5.(Special).[BD.1080p]" +: release_group: GroupName + title: Show Name + episode: 2 + episode_details: Special + screen_size: 1080p + source: Blu-ray + type: episode -# https://github.com/guessit-io/guessit/issues/308 (conflict with screen size) -? "[SuperGroup].Show.Name.-.06.[720.Hi10p][1F5578AC]" +? "[Group].Show.Name.2.The.Big.Show.-.11.[1080p]" +: title: Show Name 2 The Big Show + episode: 11 + screen_size: 1080p + type: episode + +? "[SuperGroup].Show.Name.-.Still.Name.-.11.[1080p]" +: release_group: SuperGroup + title: Show Name + alternative_title: Still Name + episode: 11 + screen_size: 1080p + type: episode + +? "[SuperGroup].Show.Name.-.462" +: release_group: SuperGroup + title: Show Name + episode: 462 + type: episode + +? Show.Name.10.720p : title: Show Name - episode: 6 + episode: 10 screen_size: 720p - video_profile: 10bit - crc32: 1F5578AC - release_group: SuperGroup type: episode -# https://github.com/guessit-io/guessit/issues/308 (conflict with screen size) -? "[SuperGroup].Show.Name.-.06.[1080.Hi10p][1F5578AC]" -: title: Show Name - episode: 6 +? "[Group].Show.Name.G2.-.19.[1080p]" +: release_group: Group + title: Show Name G2 + episode: 19 screen_size: 1080p - video_profile: 10bit - crc32: 1F5578AC - release_group: SuperGroup type: episode -? "[MK-Pn8].Dimension.W.-.05.[720p][Hi10][Dual][TV-Dub][EDA6E7F1]" -: options: -C us -L und - release_group: MK-Pn8 - title: Dimension W - episode: 5 - screen_size: 720p - video_profile: 10bit - other: DualAudio - format: TV - language: und - crc32: EDA6E7F1 +? "[Group].Show.Name.S2.-.19.[1080p]" +? /Show.Name.S2/[Group].Show.Name.S2.-.19.[1080p] +? /Show Name S2/[Group].Show.Name.S2.-.19.[1080p] +: options: -T 'Show Name S2' + release_group: Group + title: Show Name S2 + episode: 19 + screen_size: 1080p type: episode -# NetflixUHD -? Show.Name.S01E06.NetflixUHD -: title: Show Name - season: 1 - episode: 6 - streaming_service: Netflix - other: UltraHD +? "[ABC]_Show_Name_001.mkv" +: release_group: ABC + title: Show Name + episode: 1 + container: mkv type: episode -? Show.Name.S04E13.FINAL.MULTI.DD51.2160p.NetflixUHDRip.x265-TVS -: title: Show Name - season: 4 - episode: 13 - other: FINAL - language: mul - audio_codec: AC3 - audio_channels: '5.1' - screen_size: 4K - streaming_service: Netflix - format: UHDTV - video_codec: h265 - release_group: TVS +? 003-005. Show Name - Ep Name.mkv +: episode: [3, 4, 5] + title: Show Name + episode_title: Ep Name + container: mkv type: episode -? Show.Name.S06E11.Of.Late.I.Think.of.Rosewood.iTunesHD.x264 -: title: Show Name - season: 6 - episode: 11 - episode_title: Of Late I Think of Rosewood - streaming_service: iTunes - other: HD - video_codec: h264 +? 003. Show Name - Ep Name.mkv +: episode: 3 + title: Show Name + episode_title: Ep Name + container: mkv type: episode -? Show.Name.S01.720p.iTunes.h264-Group +? 165.Show Name.s08e014 +: absolute_episode: 165 + title: Show Name + season: 8 + episode: 14 + type: episode + +? Show Name - 16x03-05 - 313-315 +? Show.Name.16x03-05.313-315-GROUP +? Show Name 16x03-05 313-315 +? Show Name - 313-315 - s16e03-05 +? Show.Name.313-315.s16e03-05 +? Show Name 313-315 s16e03-05 : title: Show Name - season: 1 - screen_size: 720p - streaming_service: iTunes - video_codec: h264 - release_group: Group + absolute_episode: [313, 314, 315] + season: 16 + episode: [3, 4, 5] type: episode -? Show.Name.1x01.eps1.0.hellofriend.(HDiTunes.Ac3.Esp).(2015).By.Malaguita.avi +? Show Name 13-16 : title: Show Name - season: 1 - episode: 1 - episode_title: eps1 0 hellofriend + episode: [13, 14, 15, 16] + type: episode + +? Show Name 804 vostfr HD +: options: --episode-prefer-number + title: Show Name + episode: 804 + subtitle_language: fr other: HD - streaming_service: iTunes - audio_codec: AC3 - language: spa - year: 2015 - container: avi type: episode -? "[Hanamaru&LoliHouse] The Dragon Dentist - 01 [WebRip 1920x1080 HEVC-yuv420p10 AAC].mkv" -: release_group: Hanamaru&LoliHouse - title: The Dragon Dentist +? "[Doki] Re Zero kara Hajimeru Isekai Seikatsu - 01 1920x1080 Hi10P BD FLAC [7F64383D].mkv" +: release_group: Doki + title: Re Zero kara Hajimeru Isekai Seikatsu episode: 1 - format: WEBRip screen_size: 1080p - video_codec: h265 - video_profile: 10bit - audio_codec: AAC + aspect_ratio: 1.778 + video_profile: High 10 + color_depth: 10-bit + source: Blu-ray + audio_codec: FLAC + crc32: 7F64383D container: mkv type: episode -? Show Name - Season 1 Episode 50 -: title: Show Name - season: 1 - episode: 50 +? Shark Tank (AU) - S02E01 - HDTV-720p.mkv +: title: Shark Tank + country: AU + season: 2 + episode: 1 + source: HDTV + screen_size: 720p + container: mkv type: episode -? Vikings.Seizoen.4.1080p.Web.NLsubs -: title: Vikings - season: 4 +? "[HorribleSubs] Garo - Vanishing Line - 01 [1080p].mkv" +: release_group: HorribleSubs + title: Garo + alternative_title: Vanishing Line + episode: 1 screen_size: 1080p - format: WEB-DL - subtitle_language: nl + container: mkv type: episode -? Star.Wars.Rebels.S01E01.Spark.of.Rebellion.ALTERNATE.CUT.HDTV.x264-W4F.mp4 -: title: Star Wars Rebels +? "[HorribleSubs] Yowamushi Pedal - Glory Line - 01 [1080p].mkv" +: release_group: HorribleSubs + title: Yowamushi Pedal + alternative_title: Glory Line + episode: 1 + screen_size: 1080p + container: mkv + type: episode + +? c:\Temp\autosubliminal\completed\2 Broke Girls\Season 01\2 Broke Girls - S01E01 - HDTV-720p Proper - x264 AC3 - IMMERSE - [2011-09-19].mkv +: title: 2 Broke Girls season: 1 episode: 1 - episode_title: Spark of Rebellion - edition: Alternative Cut - format: HDTV - video_codec: h264 - release_group: W4F + source: HDTV + screen_size: 720p + other: Proper + video_codec: H.264 + audio_codec: Dolby Digital + release_group: IMMERSE + date: 2011-09-19 + container: mkv + type: episode + +? c:\Temp\postprocessing\Marvels.Agents.of.S.H.I.E.L.D.s01e02.0.8.4.720p.WEB.DL.mkv +: title: Marvels Agents of S.H.I.E.L.D. + season: 1 + episode: 2 + episode_title: 0.8.4. + screen_size: 720p + source: Web + container: mkv + type: episode + +? Mind.Field.S02E06.The.Power.of.Suggestion.1440p.H264.WEBDL.Subtitles +: title: Mind Field + season: 2 + episode: 6 + episode_title: The Power of Suggestion + screen_size: 1440p + video_codec: H.264 + source: Web + subtitle_language: und + type: episode + +? The Power of Suggestion - Mind Field S2 (Ep 6) (1440p_24fps_H264-384kbit_AAC 6Ch).mp4 +: title: The Power of Suggestion + alternative_title: Mind Field + season: 2 + episode: 6 + screen_size: 1440p + frame_rate: 24fps + video_codec: H.264 + audio_bit_rate: 384Kbps + audio_codec: AAC + audio_channels: '5.1' container: mp4 type: episode -? DCs.Legends.of.Tomorrow.S02E12.HDTV.XviD-FUM -: title: DCs Legends of Tomorrow - season: 2 - episode: 12 - format: HDTV - video_codec: XviD - release_group: FUM +? Mind.Field.S02E06.The.Power.of.Suggestion.1440p.H264.WEBDL.Subtitles/The Power of Suggestion - Mind Field S2 (Ep 6) (1440p_24fps_H264-384kbit_AAC 6Ch).mp4 +: season: 2 + episode: 6 + title: The Power of Suggestion + alternative_title: Mind Field + screen_size: 1440p + frame_rate: 24fps + video_codec: H.264 + source: Web + subtitle_language: und + audio_bit_rate: 384Kbps + audio_codec: AAC + audio_channels: '5.1' + container: mp4 type: episode -? DC's Legends of Tomorrow 2016 - S02E02 -: title: DC's Legends of Tomorrow - year: 2016 +? Mind.Field.S02E06.The.Power.of.Suggestion.1440p.H264.WEBDL.Subtitles/The Power of Suggestion - Mind Field S2 (Ep 6) (English).srt +: title: Mind Field season: 2 - episode: 2 + episode: 6 + episode_title: The Power of Suggestion + screen_size: 1440p + video_codec: H.264 + source: Web + subtitle_language: en + container: srt type: episode -? Broadchurch.S01.DIRFIX.720p.BluRay.x264-SHORTBREHD -: title: Broadchurch - season: 1 - other: Proper - screen_size: 720p - format: BluRay - video_codec: h264 - release_group: SHORTBREHD - proper_count: 1 +? Mind.Field.S02E06.The.Power.of.Suggestion.1440p.H264.WEBDL.Subtitles/The Power of Suggestion - Mind Field S2 (Ep 6) (Korean).srt +: title: Mind Field + season: 2 + episode: 6 + episode_title: The Power of Suggestion + screen_size: 1440p + video_codec: H.264 + source: Web + subtitle_language: ko + container: srt type: episode -? Simply Red - 2016-07-08 Montreux Jazz Festival 720p -: title: Simply Red - date: 2016-07-08 - episode_title: Montreux Jazz Festival - screen_size: 720p +? '[HorribleSubs] Overlord II - 01 [1080p] 19.1mbits - 120fps.mkv' +: release_group: HorribleSubs + title: Overlord II + episode: 1 + screen_size: 1080p + video_bit_rate: 19.1Mbps + frame_rate: 120fps + container: mkv type: episode -? Ridiculousness.S07E14.iNTERNAL.HDTV.x264-YesTV -: title: Ridiculousness +? One Piece - 720 +: title: One Piece season: 7 - episode: 14 - other: Internal - format: HDTV - video_codec: h264 - release_group: YesTV - type: episode - -? Stephen.Colbert.2016.05.25.James.McAvoy.iNTERNAL.XviD-AFG -: title: Stephen Colbert - date: 2016-05-25 - episode_title: James McAvoy - other: Internal - video_codec: XviD - release_group: AFG + episode: 20 type: episode -? The.100.S01E13.iNTERNAL.READNFO.720p.HDTV.x264-2HD -: title: The 100 - season: 1 - episode: 13 - other: [Internal, Read NFO] - screen_size: 720p - format: HDTV - video_codec: h264 - release_group: 2HD +? foobar.213.avi +: options: -E + title: foobar + episode: 213 + container: avi type: episode -? The.100.S01E13.READ.NFO.720p.HDTV.x264-2HD -: title: The 100 - season: 1 - episode: 13 - other: Read NFO - screen_size: 720p - format: HDTV - video_codec: h264 - release_group: 2HD +? FooBar - 360 368p-Grp +: options: -E + title: FooBar + episode: 360 + screen_size: 368p + release_group: Grp type: episode -? Dr.Ken.S01E21.SAMPLEFIX.720p.HDTV.x264-SVA -: title: Dr Ken +? wwiis.most.daring.raids.s01e04.storming.mussolinis.island.1080p.web.h.264-edhd-sample.mkv +: title: wwiis most daring raids season: 1 - episode: 21 - other: Proper - screen_size: 720p - format: HDTV - video_codec: h264 - release_group: SVA + episode: 4 + episode_title: storming mussolinis island + screen_size: 1080p + source: Web + video_codec: H.264 + release_group: edhd + other: Sample + container: mkv type: episode -? Rick and Morty Season 1 [UNCENSORED] [BDRip] [1080p] [HEVC] -: title: Rick and Morty +? WWIIs.Most.Daring.Raids.S01E04.Storming.Mussolinis.Island.1080p.WEB.h264-EDHD/wwiis.most.daring.raids.s01e04.storming.mussolinis.island.1080p.web.h.264-edhd-sample.mkv +: title: wwiis most daring raids season: 1 - edition: Uncensored - format: BluRay + episode: 4 + episode_title: Storming Mussolinis Island screen_size: 1080p - video_codec: h265 + source: Web + video_codec: H.264 + release_group: edhd + other: Sample + container: mkv type: episode -? 12.Monkeys.S01E01.LiMiTED.FRENCH.1080p.WEB-DL.H264-AUTHORiTY -: title: 12 Monkeys - season: 1 +? dcs.legends.of.tomorrow.s02e01.1080p.bluray.x264-rovers.proof +: title: dcs legends of tomorrow + season: 2 episode: 1 - edition: Limited Edition - language: french screen_size: 1080p - format: WEB-DL - video_codec: h264 - release_group: AUTHORiTY + source: Blu-ray + video_codec: H.264 + release_group: rovers + other: Proof type: episode -? Undateable.2014.S03E05.West.Feed.HDTV.x264-2HD -: title: Undateable - year: 2014 - season: 3 - episode: 5 - other: West Coast Feed - format: HDTV - video_codec: h264 - release_group: 2HD +? dcs.legends.of.tomorrow.s02e01.720p.bluray.x264-demand.sample.mkv +: title: dcs legends of tomorrow + season: 2 + episode: 1 + screen_size: 720p + source: Blu-ray + video_codec: H.264 + release_group: demand + other: Sample + container: mkv type: episode -? Undateable.2014.S02E07-E08.Live.Episode.West.Coast.Feed.HDTV.x264-2HD -: title: Undateable - year: 2014 - season: 2 - episode: [7, 8] - other: West Coast Feed - format: HDTV - video_codec: h264 - release_group: 2HD +? Season 06/e01.1080p.bluray.x264-wavey-obfuscated.mkv +: season: 6 + episode: 1 + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + title: wavey + other: Obfuscated + container: mkv type: episode -? Undateable.S03E01-E02.LIVE.EAST.FEED.720p.HDTV.x264-KILLERS -: title: Undateable - season: 3 - episode: [1, 2] - other: East Coast Feed - screen_size: 720p - format: HDTV - video_codec: h264 - release_group: KILLERS +? Hells.Kitchen.US.S17E08.1080p.HEVC.x265-MeGusta-Obfuscated/c48db7d2aeb040e8a920a9fd6effcbf4.mkv +: title: Hells Kitchen + country: US + season: 17 + episode: 8 + screen_size: 1080p + video_codec: H.265 + release_group: MeGusta + other: Obfuscated + uuid: c48db7d2aeb040e8a920a9fd6effcbf4 + container: mkv type: episode -? Undateable.2014.S02E07.Live.Episode.East.Coast.Feed.HDTV.x264-2HD -: title: Undateable - year: 2014 - season: 2 - episode: 7 - other: East Coast Feed - format: HDTV - video_codec: h264 - release_group: 2HD +? Blue.Bloods.S08E09.1080p.HEVC.x265-MeGusta-Obfuscated/afaae96ae7a140e0981ced2a79221751.mkv +: title: Blue Bloods + season: 8 + episode: 9 + screen_size: 1080p + video_codec: H.265 + release_group: MeGusta + other: Obfuscated + container: mkv type: episode -? Undateable.2014.S02E07.East.Coast.Feed.720p.WEB-DL.DD5.1.H.264-NTb -: title: Undateable - year: 2014 +? MacGyver.2016.S02E09.CD-ROM.and.Hoagie.Foil.1080p.AMZN.WEBRip.DDP5.1.x264-NTb-Scrambled/c329b27187d44a94b4a25b21502db552.mkv +: title: MacGyver + year: 2016 season: 2 - episode: 7 - other: East Coast Feed - screen_size: 720p - format: WEB-DL - audio_codec: AC3 + episode: 9 + screen_size: 1080p + streaming_service: Amazon Prime + source: Web + other: [Rip, Obfuscated] + audio_codec: Dolby Digital Plus audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: NTb + uuid: c329b27187d44a94b4a25b21502db552 + container: mkv type: episode -? True Detective S02E04 720p HDTV x264-0SEC [GloDLS].mkv -: title: True Detective - season: 2 - episode: 4 - screen_size: 720p - format: HDTV - video_codec: h264 - release_group: 0SEC [GloDLS] +? The.Late.Late.Show.with.James.Corden.2017.11.27.Armie.Hammer.Juno.Temple.Charlie.Puth.1080p.AMZN.WEB-DL.DDP2.0.H.264-monkee-Scrambled/42e7e8a48eb7454aaebebcf49705ce41.mkv +: title: The Late Late Show with James Corden + date: 2017-11-27 + episode_title: Armie Hammer Juno Temple Charlie Puth + screen_size: 1080p + streaming_service: Amazon Prime + source: Web + audio_codec: Dolby Digital Plus + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + other: Obfuscated + uuid: 42e7e8a48eb7454aaebebcf49705ce41 container: mkv type: episode -? Anthony.Bourdain.Parts.Unknown.S09E01.Los.Angeles.720p.HDTV.x264-MiNDTHEGAP -: title: Anthony Bourdain Parts Unknown - season: 9 - episode: 1 - episode_title: Los Angeles +? Educating Greater Manchester S01E07 720p HDTV x264-PLUTONiUM-AsRequested +: title: Educating Greater Manchester + season: 1 + episode: 7 screen_size: 720p - format: HDTV - video_codec: h264 - release_group: MiNDTHEGAP + source: HDTV + video_codec: H.264 + release_group: PLUTONiUM + other: Repost type: episode -? -feud.s01e05.and.the.winner.is.(the.oscars.of.1963).720p.amzn.webrip.dd5.1.x264-casstudio.mkv -: year: 1963 - -? feud.s01e05.and.the.winner.is.(the.oscars.of.1963).720p.amzn.webrip.dd5.1.x264-casstudio.mkv -: title: feud - season: 1 - episode: 5 - episode_title: and the winner is - screen_size: 720p - streaming_service: Amazon Prime - format: WEBRip - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: casstudio - container: mkv +? Im A Celebrity Get Me Out Of Here S17E14 HDTV x264-PLUTONiUM-xpost +: title: Im A Celebrity Get Me Out Of Here + season: 17 + episode: 14 + source: HDTV + video_codec: H.264 + release_group: PLUTONiUM + other: Repost type: episode -? Adventure.Time.S08E16.Elements.Part.1.Skyhooks.720p.WEB-DL.AAC2.0.H.264-RTN.mkv -: title: Adventure Time - season: 8 - episode: 16 - season: 8 - episode: 16 - episode_title: Elements Part 1 Skyhooks +? Tales S01E08 All I Need Method Man Featuring Mary J Blige 720p BET WEBRip AAC2 0 x264-RTN-xpost +: title: Tales + season: 1 + episode: 8 + episode_title: All I Need Method Man Featuring Mary J Blige screen_size: 720p - format: WEB-DL + source: Web + other: [Rip, Repost] audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 release_group: RTN - container: mkv type: episode -? D:\TV\SITCOMS (CLASSIC)\That '70s Show\Season 07\That '70s Show - S07E22 - 2000 Light Years from Home.mkv -: title: That '70s Show - season: 7 - episode: 22 - episode_title: 2000 Light Years from Home - other: Classic - container: mkv - mimetype: video/x-matroska +? This is Us S01E11 Herzensangelegenheiten German DL WS DVDRip x264-CDP-xpost +: options: --exclude country + title: This is Us + season: 1 + episode: 11 + episode_title: Herzensangelegenheiten + language: + - de + - mul + other: + - Widescreen + - Rip + - Repost + source: DVD + video_codec: H.264 + release_group: CDP type: episode -? Show.Name.S02E01.Super.Title.720p.WEB-DL.DD5.1.H.264-ABC.nzb -: title: Show Name +? The Girlfriend Experience S02E10 1080p WEB H264-STRiFE-postbot +: title: The Girlfriend Experience season: 2 - episode: 1 - episode_title: Super Title - screen_size: 720p - format: WEB-DL - audio_codec: AC3 - audio_channels: '5.1' - video_codec: h264 - release_group: ABC - container: nzb + episode: 10 + screen_size: 1080p + source: Web + video_codec: H.264 + release_group: STRiFE + other: Repost type: episode -? "[SGKK] Bleach 312v1 [720p/mkv]-Group.mkv" -: title: Bleach - season: 3 - episode: 12 - version: 1 - screen_size: 720p - release_group: Group +? The.Girlfriend.Experience.S02E10.1080p.WEB.H264-STRiFE-postbot/90550c1adaf44c47b60d24f59603bb98.mkv +: title: The Girlfriend Experience + season: 2 + episode: 10 + screen_size: 1080p + source: Web + video_codec: H.264 + release_group: STRiFE + other: Repost + uuid: 90550c1adaf44c47b60d24f59603bb98 container: mkv type: episode -? The.Expanse.S02E08.720p.WEBRip.x264.EAC3-KiNGS.mkv -: title: The Expanse - season: 2 - episode: 8 - screen_size: 720p - format: WEBRip - video_codec: h264 - audio_codec: EAC3 - release_group: KiNGS +? 24.S01E02.1080p.BluRay.REMUX.AVC.DD.2.0-EPSiLON-xpost/eb518eaf33f641a1a8c6e0973a67aec2.mkv +: title: '24' + season: 1 + episode: 2 + screen_size: 1080p + source: Blu-ray + other: [Remux, Repost] + video_codec: H.264 + audio_codec: Dolby Digital + audio_channels: '2.0' + release_group: EPSiLON + uuid: eb518eaf33f641a1a8c6e0973a67aec2 container: mkv type: episode -? Series_name.2005.211.episode.title.avi -: title: Series name - year: 2005 - season: 2 - episode: 11 - episode_title: episode title - container: avi +? Educating.Greater.Manchester.S01E02.720p.HDTV.x264-PLUTONiUM-AsRequested/47fbcb2393aa4b5cbbb340d3173ca1a9.mkv +: title: Educating Greater Manchester + season: 1 + episode: 2 + screen_size: 720p + source: HDTV + video_codec: H.264 + release_group: PLUTONiUM + other: Repost + uuid: 47fbcb2393aa4b5cbbb340d3173ca1a9 + container: mkv type: episode -? the.flash.2014.208.hdtv-lol[ettv].mkv -: title: the flash - year: 2014 +? Stranger.Things.S02E05.Chapter.Five.Dig.Dug.720p.NF.WEBRip.DD5.1.x264-PSYPHER-AsRequested-Obfuscated +: title: Stranger Things season: 2 - episode: 8 - format: HDTV - release_group: lol[ettv] - container: mkv + episode: 5 + episode_title: Chapter Five Dig Dug + screen_size: 720p + streaming_service: Netflix + source: Web + other: [Rip, Repost, Obfuscated] + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: PSYPHER type: episode -? "[Despair-Paradise].Kono.Subarashii.Sekai.ni.Shukufuku.wo!.2.-..09.vostfr.FHD" -: options: -E -t episode - release_group: Despair-Paradise - title: Kono Subarashii Sekai ni Shukufuku wo! 2 - episode: 9 - subtitle_language: fr - other: FullHD +? Show.Name.-.Season.1.3.4-.Mp4.1080p +: title: Show Name + season: [1, 3, 4] + container: mp4 + screen_size: 1080p type: episode diff --git a/ext/guessit/test/movies.yml b/ext/guessit/test/movies.yml index 610c3836c8..33d5d189b9 100644 --- a/ext/guessit/test/movies.yml +++ b/ext/guessit/test/movies.yml @@ -5,16 +5,17 @@ : title: Fear and Loathing in Las Vegas year: 1998 screen_size: 720p - format: HD-DVD + source: HD-DVD audio_codec: DTS - video_codec: h264 + video_codec: H.264 container: mkv release_group: ESiR ? Movies/El Dia de la Bestia (1995)/El.dia.de.la.bestia.DVDrip.Spanish.DivX.by.Artik[SEDG].avi : title: El Dia de la Bestia year: 1995 - format: DVD + source: DVD + other: Rip language: spanish video_codec: DivX release_group: Artik[SEDG] @@ -23,37 +24,40 @@ ? Movies/Dark City (1998)/Dark.City.(1998).DC.BDRip.720p.DTS.X264-CHD.mkv : title: Dark City year: 1998 - format: BluRay + source: Blu-ray + other: Rip screen_size: 720p audio_codec: DTS - video_codec: h264 + video_codec: H.264 release_group: CHD ? Movies/Sin City (BluRay) (2005)/Sin.City.2005.BDRip.720p.x264.AC3-SEPTiC.mkv : title: Sin City year: 2005 - format: BluRay + source: Blu-ray + other: Rip screen_size: 720p - video_codec: h264 - audio_codec: AC3 + video_codec: H.264 + audio_codec: Dolby Digital release_group: SEPTiC ? Movies/Borat (2006)/Borat.(2006).R5.PROPER.REPACK.DVDRip.XviD-PUKKA.avi : title: Borat year: 2006 proper_count: 2 - format: DVD - other: [ R5, Proper ] - video_codec: XviD + source: DVD + other: [ Region 5, Proper, Rip ] + video_codec: Xvid release_group: PUKKA ? "[XCT].Le.Prestige.(The.Prestige).DVDRip.[x264.HP.He-Aac.{Fr-Eng}.St{Fr-Eng}.Chaps].mkv" : title: Le Prestige - format: DVD - video_codec: h264 - video_profile: HP + source: DVD + other: Rip + video_codec: H.264 + video_profile: High audio_codec: AAC - audio_profile: HE + audio_profile: High Efficiency language: [ french, english ] subtitle_language: [ french, english ] release_group: Chaps @@ -61,23 +65,24 @@ ? Battle Royale (2000)/Battle.Royale.(Batoru.Rowaiaru).(2000).(Special.Edition).CD1of2.DVDRiP.XviD-[ZeaL].avi : title: Battle Royale year: 2000 - edition: Special Edition + edition: Special cd: 1 cd_count: 2 - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: ZeaL ? Movies/Brazil (1985)/Brazil_Criterion_Edition_(1985).CD2.avi : title: Brazil - edition: Criterion Edition + edition: Criterion year: 1985 cd: 2 ? Movies/Persepolis (2007)/[XCT] Persepolis [H264+Aac-128(Fr-Eng)+ST(Fr-Eng)+Ind].mkv : title: Persepolis year: 2007 - video_codec: h264 + video_codec: H.264 audio_codec: AAC language: [ French, English ] subtitle_language: [ French, English ] @@ -86,17 +91,18 @@ ? Movies/Toy Story (1995)/Toy Story [HDTV 720p English-Spanish].mkv : title: Toy Story year: 1995 - format: HDTV + source: HDTV screen_size: 720p language: [ english, spanish ] ? Movies/Office Space (1999)/Office.Space.[Dual-DVDRip].[Spanish-English].[XviD-AC3-AC3].[by.Oswald].avi : title: Office Space year: 1999 - format: DVD + other: [Dual Audio, Rip] + source: DVD language: [ english, spanish ] - video_codec: XviD - audio_codec: AC3 + video_codec: Xvid + audio_codec: Dolby Digital ? Movies/Wild Zero (2000)/Wild.Zero.DVDivX-EPiC.avi : title: Wild Zero @@ -106,30 +112,33 @@ ? movies/Baraka_Edition_Collector.avi : title: Baraka - edition: Collector Edition + edition: Collector ? Movies/Blade Runner (1982)/Blade.Runner.(1982).(Director's.Cut).CD1.DVDRip.XviD.AC3-WAF.avi : title: Blade Runner year: 1982 edition: Director's Cut cd: 1 - format: DVD - video_codec: XviD - audio_codec: AC3 + source: DVD + other: Rip + video_codec: Xvid + audio_codec: Dolby Digital release_group: WAF ? movies/American.The.Bill.Hicks.Story.2009.DVDRip.XviD-EPiSODE.[UsaBit.com]/UsaBit.com_esd-americanbh.avi : title: American The Bill Hicks Story year: 2009 - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: EPiSODE website: UsaBit.com ? movies/Charlie.And.Boots.DVDRip.XviD-TheWretched/wthd-cab.avi : title: Charlie And Boots - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: TheWretched ? movies/Steig Larsson Millenium Trilogy (2009) BRrip 720 AAC x264/(1)The Girl With The Dragon Tattoo (2009) BRrip 720 AAC x264.mkv @@ -137,18 +146,19 @@ #film_title: Steig Larsson Millenium Trilogy #film: 1 year: 2009 - format: BluRay + source: Blu-ray + other: [Reencoded, Rip] audio_codec: AAC - video_codec: h264 + video_codec: H.264 screen_size: 720p ? movies/Greenberg.REPACK.LiMiTED.DVDRip.XviD-ARROW/arw-repack-greenberg.dvdrip.xvid.avi : title: Greenberg - format: DVD - video_codec: XviD + source: DVD + video_codec: Xvid release_group: ARROW - other: Proper - edition: Limited Edition + other: [Proper, Rip] + edition: Limited proper_count: 1 ? Movies/Fr - Paris 2054, Renaissance (2005) - De Christian Volckman - (Film Divx Science Fiction Fantastique Thriller Policier N&B).avi @@ -161,14 +171,16 @@ : title: Avida year: 2006 language: french - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: PROD ? Movies/Alice in Wonderland DVDRip.XviD-DiAMOND/dmd-aw.avi : title: Alice in Wonderland - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: DiAMOND ? Movies/Ne.Le.Dis.A.Personne.Fr 2 cd/personnea_mp.avi @@ -180,49 +192,54 @@ : title: Bunker Palace Hôtel year: 1989 language: french - format: VHS + source: VHS + other: Rip ? Movies/21 (2008)/21.(2008).DVDRip.x264.AC3-FtS.[sharethefiles.com].mkv : title: "21" year: 2008 - format: DVD - video_codec: h264 - audio_codec: AC3 + source: DVD + other: Rip + video_codec: H.264 + audio_codec: Dolby Digital release_group: FtS website: sharethefiles.com ? Movies/9 (2009)/9.2009.Blu-ray.DTS.720p.x264.HDBRiSe.[sharethefiles.com].mkv : title: "9" year: 2009 - format: BluRay + source: Blu-ray audio_codec: DTS screen_size: 720p - video_codec: h264 + video_codec: H.264 release_group: HDBRiSe website: sharethefiles.com ? Movies/Mamma.Mia.2008.DVDRip.AC3.XviD-CrazyTeam/Mamma.Mia.2008.DVDRip.AC3.XviD-CrazyTeam.avi : title: Mamma Mia year: 2008 - format: DVD - audio_codec: AC3 - video_codec: XviD + source: DVD + other: Rip + audio_codec: Dolby Digital + video_codec: Xvid release_group: CrazyTeam ? Movies/M.A.S.H. (1970)/MASH.(1970).[Divx.5.02][Dual-Subtitulos][DVDRip].ogm : title: MASH year: 1970 video_codec: DivX - format: DVD + source: DVD + other: [Dual Audio, Rip] ? Movies/The Doors (1991)/09.03.08.The.Doors.(1991).BDRip.720p.AC3.X264-HiS@SiLUHD-English.[sharethefiles.com].mkv : title: The Doors year: 1991 date: 2008-03-09 - format: BluRay + source: Blu-ray + other: Rip screen_size: 720p - audio_codec: AC3 - video_codec: h264 + audio_codec: Dolby Digital + video_codec: H.264 release_group: HiS@SiLUHD language: english website: sharethefiles.com @@ -232,17 +249,18 @@ title: The Doors year: 1991 date: 2008-03-09 - format: BluRay + source: Blu-ray + other: Rip screen_size: 720p - audio_codec: AC3 - video_codec: h264 + audio_codec: Dolby Digital + video_codec: H.264 release_group: HiS@SiLUHD language: english website: sharethefiles.com ? Movies/Ratatouille/video_ts-ratatouille.srt : title: Ratatouille - format: DVD + source: DVD # Removing this one because 001 is guessed as an episode number. # ? Movies/001 __ A classer/Fantomas se déchaine - Louis de Funès.avi @@ -252,18 +270,20 @@ : title: Comme une Image year: 2004 language: french - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: NTK website: www.divx-overnet.com ? Movies/Fantastic Mr Fox/Fantastic.Mr.Fox.2009.DVDRip.{x264+LC-AAC.5.1}{Fr-Eng}{Sub.Fr-Eng}-™.[sharethefiles.com].mkv : title: Fantastic Mr Fox year: 2009 - format: DVD - video_codec: h264 + source: DVD + other: Rip + video_codec: H.264 audio_codec: AAC - audio_profile: LC + audio_profile: Low Complexity audio_channels: "5.1" language: [ french, english ] subtitle_language: [ french, english ] @@ -272,8 +292,9 @@ ? Movies/Somewhere.2010.DVDRip.XviD-iLG/i-smwhr.avi : title: Somewhere year: 2010 - format: DVD - video_codec: XviD + source: DVD + other: Rip + video_codec: Xvid release_group: iLG ? Movies/Moon_(2009).mkv @@ -339,21 +360,21 @@ ? /public/uTorrent/Downloads Finished/Movies/Indiana.Jones.and.the.Temple.of.Doom.1984.HDTV.720p.x264.AC3.5.1-REDµX/Indiana.Jones.and.the.Temple.of.Doom.1984.HDTV.720p.x264.AC3.5.1-REDµX.mkv : title: Indiana Jones and the Temple of Doom year: 1984 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 - audio_codec: AC3 + video_codec: H.264 + audio_codec: Dolby Digital audio_channels: "5.1" release_group: REDµX ? The.Director’s.Notebook.2006.Blu-Ray.x264.DXVA.720p.AC3-de[42].mkv : title: The Director’s Notebook year: 2006 - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_api: DXVA screen_size: 720p - audio_codec: AC3 + audio_codec: Dolby Digital release_group: de[42] @@ -361,17 +382,18 @@ : title: Cosmopolis year: 2012 screen_size: 720p - video_codec: h264 + video_codec: H.264 release_group: AN0NYM0US[bb] - format: BluRay - edition: Limited Edition + source: Blu-ray + edition: Limited ? movies/La Science des Rêves (2006)/La.Science.Des.Reves.FRENCH.DVDRip.XviD-MP-AceBot.avi : title: La Science des Rêves year: 2006 - format: DVD - video_codec: XviD - video_profile: MP + source: DVD + other: Rip + video_codec: Xvid + video_profile: Main release_group: AceBot language: French @@ -382,8 +404,8 @@ : title: The Rum Diary year: 2011 screen_size: 1080p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 audio_codec: DTS release_group: D-Z0N3 @@ -391,8 +413,8 @@ : title: Life Of Pi year: 2012 screen_size: 1080p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 audio_codec: DTS release_group: D-Z0N3 @@ -400,28 +422,28 @@ : title: The Kings Speech year: 2010 screen_size: 1080p - format: BluRay + source: Blu-ray audio_codec: DTS - video_codec: h264 + video_codec: H.264 release_group: D Z0N3 ? Street.Kings.2008.BluRay.1080p.DTS.x264.dxva EuReKA.mkv : title: Street Kings year: 2008 - format: BluRay + source: Blu-ray screen_size: 1080p audio_codec: DTS - video_codec: h264 + video_codec: H.264 video_api: DXVA release_group: EuReKA ? 2001.A.Space.Odyssey.1968.HDDVD.1080p.DTS.x264.dxva EuReKA.mkv : title: 2001 A Space Odyssey year: 1968 - format: HD-DVD + source: HD-DVD screen_size: 1080p audio_codec: DTS - video_codec: h264 + video_codec: H.264 video_api: DXVA release_group: EuReKA @@ -429,24 +451,25 @@ : title: "2012" year: 2009 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 audio_codec: DTS release_group: WiKi ? /share/Download/movie/Dead Man Down (2013) BRRiP XViD DD5_1 Custom NLSubs =-_lt Q_o_Q gt-=_/XD607ebb-BRc59935-5155473f-1c5f49/XD607ebb-BRc59935-5155473f-1c5f49.avi : title: Dead Man Down year: 2013 - format: BluRay - video_codec: XviD + source: Blu-ray + other: [Reencoded, Rip] + video_codec: Xvid audio_channels: "5.1" - audio_codec: AC3 + audio_codec: Dolby Digital uuid: XD607ebb-BRc59935-5155473f-1c5f49 ? Pacific.Rim.3D.2013.COMPLETE.BLURAY-PCH.avi : title: Pacific Rim year: 2013 - format: BluRay + source: Blu-ray other: - Complete - 3D @@ -458,33 +481,33 @@ language: - French - English - format: DVD + source: DVD other: [Straight to Video, Read NFO, NTSC] ? Immersion.French.2011.STV.READNFO.QC.FRENCH.NTSC.DVDR.nfo : title: Immersion French year: 2011 language: French - format: DVD + source: DVD other: [Straight to Video, Read NFO, NTSC] ? Immersion.French.2011.STV.READNFO.QC.NTSC.DVDR.nfo : title: Immersion language: French year: 2011 - format: DVD + source: DVD other: [Straight to Video, Read NFO, NTSC] ? French.Immersion.2011.STV.READNFO.QC.ENGLISH.NTSC.DVDR.nfo : title: French Immersion year: 2011 language: ENGLISH - format: DVD + source: DVD other: [Straight to Video, Read NFO, NTSC] ? Howl's_Moving_Castle_(2004)_[720p,HDTV,x264,DTS]-FlexGet.avi -: video_codec: h264 - format: HDTV +: video_codec: H.264 + source: HDTV title: Howl's Moving Castle screen_size: 720p year: 2004 @@ -495,43 +518,42 @@ : screen_size: 1080p year: 2008 language: French - video_codec: h264 + video_codec: H.264 title: Pirates de langkasuka release_group: AsiaRa ? Masala (2013) Telugu Movie HD DVDScr XviD - Exclusive.avi : year: 2013 - video_codec: XviD + video_codec: Xvid title: Masala - format: HD-DVD + source: HD-DVD other: Screener - language: Telugu release_group: Exclusive ? Django Unchained 2012 DVDSCR X264 AAC-P2P.nfo : year: 2012 other: Screener - video_codec: h264 + video_codec: H.264 title: Django Unchained audio_codec: AAC - format: DVD + source: DVD release_group: P2P ? Ejecutiva.En.Apuros(2009).BLURAY.SCR.Xvid.Spanish.LanzamientosD.nfo : year: 2009 other: Screener - format: BluRay - video_codec: XviD + source: Blu-ray + video_codec: Xvid language: Spanish title: Ejecutiva En Apuros ? Die.Schluempfe.2.German.DL.1080p.BluRay.x264-EXQUiSiTE.mkv : title: Die Schluempfe 2 - format: BluRay + source: Blu-ray language: - Multiple languages - German - video_codec: h264 + video_codec: H.264 release_group: EXQUiSiTE screen_size: 1080p @@ -539,96 +561,99 @@ : title: Rocky year: 1976 subtitle_language: French - format: BluRay - video_codec: h264 - audio_codec: AC3 + source: Blu-ray + other: [Reencoded, Rip] + video_codec: H.264 + audio_codec: Dolby Digital release_group: FUNKY ? REDLINE (BD 1080p H264 10bit FLAC) [3xR].mkv : title: REDLINE - format: BluRay - video_codec: h264 - video_profile: 10bit + source: Blu-ray + video_codec: H.264 + color_depth: 10-bit audio_codec: FLAC screen_size: 1080p ? The.Lizzie.McGuire.Movie.(2003).HR.DVDRiP.avi : title: The Lizzie McGuire Movie year: 2003 - format: DVD - other: HR + source: DVD + other: [High Resolution, Rip] ? Hua.Mulan.BRRIP.MP4.x264.720p-HR.avi : title: Hua Mulan - video_codec: h264 - format: BluRay + video_codec: H.264 + source: Blu-ray screen_size: 720p - other: HR + other: [Reencoded, Rip] + release_group: HR ? Dr.Seuss.The.Lorax.2012.DVDRip.LiNE.XviD.AC3.HQ.Hive-CM8.mp4 -: video_codec: XviD +: video_codec: Xvid title: Dr Seuss The Lorax - format: DVD - other: LiNE + source: DVD + other: [Rip, Line Audio] year: 2012 - audio_codec: AC3 - audio_profile: HQ + audio_codec: Dolby Digital + audio_profile: High Quality release_group: Hive-CM8 ? "Star Wars: Episode IV - A New Hope (2004) Special Edition.MKV" : title: "Star Wars: Episode IV" alternative_title: A New Hope year: 2004 - edition: Special Edition + edition: Special ? Dr.LiNE.The.Lorax.2012.DVDRip.LiNE.XviD.AC3.HQ.Hive-CM8.mp4 -: video_codec: XviD +: video_codec: Xvid title: Dr LiNE The Lorax - format: DVD - other: LiNE + source: DVD + other: [Rip, Line Audio] year: 2012 - audio_codec: AC3 - audio_profile: HQ + audio_codec: Dolby Digital + audio_profile: High Quality release_group: Hive-CM8 ? Dr.LiNE.The.Lorax.2012.DVDRip.XviD.AC3.HQ.Hive-CM8.mp4 -: video_codec: XviD +: video_codec: Xvid title: Dr LiNE The Lorax - format: DVD + source: DVD + other: Rip year: 2012 - audio_codec: AC3 - audio_profile: HQ + audio_codec: Dolby Digital + audio_profile: High Quality release_group: Hive-CM8 ? Perfect Child-2007-TRUEFRENCH-TVRip.Xvid-h@mster.avi : release_group: h@mster title: Perfect Child - video_codec: XviD + video_codec: Xvid language: French - format: TV + source: TV + other: Rip year: 2007 ? entre.ciel.et.terre.(1994).dvdrip.h264.aac-psypeon.avi : audio_codec: AAC - format: DVD + source: DVD + other: Rip release_group: psypeon title: entre ciel et terre - video_codec: h264 + video_codec: H.264 year: 1994 ? Yves.Saint.Laurent.2013.FRENCH.DVDSCR.MD.XviD-ViVARiUM.avi -: format: DVD +: source: DVD language: French - other: - - MD - - Screener + other: [Screener, Mic Dubbed] release_group: ViVARiUM title: Yves Saint Laurent - video_codec: XviD + video_codec: Xvid year: 2013 ? Echec et Mort - Hard to Kill - Steven Seagal Multi 1080p BluRay x264 CCATS.avi -: format: BluRay +: source: Blu-ray language: Multiple languages release_group: CCATS screen_size: 1080p @@ -636,7 +661,7 @@ alternative_title: - Hard to Kill - Steven Seagal - video_codec: h264 + video_codec: H.264 ? Paparazzi - Timsit/Lindon (MKV 1080p tvripHD) : options: -n @@ -646,35 +671,36 @@ - Lindon screen_size: 1080p container: mkv - format: HDTV + source: HDTV + other: Rip ? some.movie.720p.bluray.x264-mind : title: some movie screen_size: 720p - video_codec: h264 + video_codec: H.264 release_group: mind - format: BluRay + source: Blu-ray ? Dr LiNE The Lorax 720p h264 BluRay : title: Dr LiNE The Lorax screen_size: 720p - video_codec: h264 - format: BluRay + video_codec: H.264 + source: Blu-ray #TODO: Camelcase implementation #? BeatdownFrenchDVDRip.mkv #: options: -c # title: Beatdown # language: French -# format: DVD +# source: DVD #? YvesSaintLaurent2013FrenchDVDScrXvid.avi #: options: -c -# format: DVD +# source: DVD # language: French # other: Screener # title: Yves saint laurent -# video_codec: XviD +# video_codec: Xvid # year: 2013 @@ -683,7 +709,7 @@ title: Elle s en va ? FooBar.7.PDTV-FlexGet -: format: DVB +: source: Digital TV release_group: FlexGet title: FooBar 7 @@ -693,7 +719,7 @@ language: fr screen_size: 1080p title: Riddick - video_codec: h265 + video_codec: H.265 ? "[h265 - HEVC] Riddick Unrated Director Cut French [1080p DTS].mkv" : audio_codec: DTS @@ -701,38 +727,36 @@ language: fr screen_size: 1080p title: Riddick - video_codec: h265 + video_codec: H.265 ? Barbecue-2014-French-mHD-1080p : language: fr - other: mHD + other: Micro HD screen_size: 1080p title: Barbecue year: 2014 ? Underworld Quadrilogie VO+VFF+VFQ 1080p HDlight.x264~Tonyk~Monde Infernal : language: fr - other: - - HDLight - - OV + other: [Original Video, Micro HD] screen_size: 1080p title: Underworld Quadrilogie - video_codec: h264 + video_codec: H.264 ? A Bout Portant (The Killers).PAL.Multi.DVD-R-KZ -: format: DVD +: source: DVD language: mul release_group: KZ title: A Bout Portant ? "Mise à Sac (Alain Cavalier, 1967) [Vhs.Rip.Vff]" -: format: VHS +: source: VHS language: fr title: "Mise à Sac" year: 1967 ? A Bout Portant (The Killers).PAL.Multi.DVD-R-KZ -: format: DVD +: source: DVD other: PAL language: mul release_group: KZ @@ -747,7 +771,8 @@ year: 2009 ? La Defense Lincoln (The Lincoln Lawyer) 2011 [DVDRIP][Vostfr] -: format: DVD +: source: DVD + other: Rip subtitle_language: fr title: La Defense Lincoln year: 2011 @@ -757,7 +782,7 @@ language: fr screen_size: 1080p title: Fight Club - video_codec: h265 + video_codec: H.265 ? Love Gourou (Mike Myers) - FR : language: fr @@ -765,11 +790,11 @@ ? '[h265 - hevc] transformers 2 1080p french ac3 6ch.' : audio_channels: '5.1' - audio_codec: AC3 + audio_codec: Dolby Digital language: fr screen_size: 1080p title: transformers 2 - video_codec: h265 + video_codec: H.265 ? 1.Angry.Man.1957.mkv : title: 1 Angry Man @@ -788,30 +813,29 @@ title: Looney Tunes ? Das.Appartement.German.AC3D.DL.720p.BluRay.x264-TVP -: audio_codec: AC3 - format: BluRay +: audio_codec: Dolby Digital + source: Blu-ray language: mul release_group: TVP screen_size: 720p title: Das Appartement German type: movie - video_codec: h264 + video_codec: H.264 ? Das.Appartement.GERMAN.AC3D.DL.720p.BluRay.x264-TVP -: audio_codec: AC3 - format: BluRay +: audio_codec: Dolby Digital + source: Blu-ray language: - de - mul release_group: TVP screen_size: 720p title: Das Appartement - video_codec: h264 + video_codec: H.264 ? Hyena.Road.2015.German.1080p.DL.DTSHD.Bluray.x264-pmHD -: audio_codec: DTS - audio_profile: HD - format: BluRay +: audio_codec: DTS-HD + source: Blu-ray language: - de - mul @@ -819,13 +843,12 @@ screen_size: 1080p title: Hyena Road type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? Hyena.Road.2015.German.1080p.DL.DTSHD.Bluray.x264-pmHD -: audio_codec: DTS - audio_profile: HD - format: BluRay +: audio_codec: DTS-HD + source: Blu-ray language: - de - mul @@ -833,16 +856,34 @@ screen_size: 1080p title: Hyena Road type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? Name.BDMux.720p -? Name.BDRipMux.720p +: title: Name + source: Blu-ray + other: Mux + screen_size: 720p + type: movie + ? Name.BRMux.720p +: title: Name + source: Blu-ray + other: [Reencoded, Mux] + screen_size: 720p + type: movie + +? Name.BDRipMux.720p +: title: Name + source: Blu-ray + other: [Rip, Mux] + screen_size: 720p + type: movie + ? Name.BRRipMux.720p : title: Name - format: BluRay - other: Mux + source: Blu-ray + other: [Reencoded, Rip, Mux] screen_size: 720p type: movie @@ -860,13 +901,11 @@ : title: Hacksaw Ridge year: 2016 language: mul - screen_size: 4K - other: UltraHD - format: BluRay - video_codec: h265 - video_profile: 10bit - audio_codec: [DTS, DolbyAtmos] - audio_profile: HD + screen_size: 2160p + source: Ultra HD Blu-ray + video_codec: H.265 + color_depth: 10-bit + audio_codec: [DTS-HD, Dolby Atmos] audio_channels: '7.1' release_group: DDR container: mkv @@ -876,9 +915,9 @@ : title: Special Correspondents year: 2016 language: [it, en] - screen_size: 4K + screen_size: 2160p streaming_service: Netflix - other: UltraHD + other: Ultra HD release_group: TeamPremium container: mp4 type: movie @@ -892,13 +931,12 @@ ? Suicide Squad EXTENDED (2016) 2160p 4K UltraHD Blu-Ray x265 (HEVC 10bit BT709) Dolby Atmos 7.1 -DDR : title: Suicide Squad edition: Extended - other: UltraHD year: 2016 - screen_size: 4K - format: BluRay - video_codec: h265 - video_profile: 10bit - audio_codec: DolbyAtmos + screen_size: 2160p + source: Ultra HD Blu-ray + video_codec: H.265 + color_depth: 10-bit + audio_codec: Dolby Atmos audio_channels: '7.1' release_group: DDR type: movie @@ -916,25 +954,25 @@ year: 1949 edition: Alternative Cut screen_size: 1080p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 release_group: SADPANDA[rarbg] ? The.Movie.CONVERT.720p.HDTV.x264-C4TV : title: The Movie other: Converted screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: C4TV type: movie ? Its.A.Wonderful.Life.1946.Colorized.720p.BRRip.999MB.MkvCage.com : title: Its A Wonderful Life year: 1946 - other: Colorized + other: [Colorized, Reencoded, Rip] screen_size: 720p - format: BluRay + source: Blu-ray size: 999MB website: MkvCage.com type: movie @@ -951,19 +989,19 @@ year: 2000 edition: Director's Cut screen_size: 1080p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 release_group: anoXmous type: movie ? Before.the.Flood.2016.DOCU.1080p.WEBRip.x264.DD5.1-FGT : title: Before the Flood year: 2016 - other: Documentary + other: [Documentary, Rip] screen_size: 1080p - format: WEBRip - video_codec: h264 - audio_codec: AC3 + source: Web + video_codec: H.264 + audio_codec: Dolby Digital audio_channels: '5.1' release_group: FGT type: movie @@ -971,7 +1009,7 @@ ? Zootopia.2016.HDRip.1.46Gb.Dub.MegaPeer : title: Zootopia year: 2016 - format: HDTV + other: [HD, Rip] size: 1.46GB language: und release_group: MegaPeer @@ -981,26 +1019,27 @@ : title: Suntan year: 2016 edition: Festival - format: DVD - video_codec: h264 + source: DVD + other: Rip + video_codec: H.264 release_group: IcHoR type: movie ? Hardwired.STV.NFOFiX.FRENCH.DVDRiP.XviD-SURViVAL : title: Hardwired - other: [Straight to Video, Proper] + other: [Straight to Video, Proper, Rip] language: french - format: DVD - video_codec: XviD + source: DVD + video_codec: Xvid release_group: SURViVAL proper_count: 1 type: movie ? Maze.Runner.The.Scorch.Trials.OM.2015.WEB-DLRip.by.Seven : title: Maze Runner The Scorch Trials - other: Open Matte + other: [Open Matte, Rip] year: 2015 - format: WEBRip + source: Web release_group: Seven type: movie @@ -1008,13 +1047,13 @@ : title: Kampen Om Tungtvannet aka The Heavy Water War other: Complete screen_size: 720p - video_codec: h265 + video_codec: H.265 release_group: Lund type: movie ? All.Fall.Down.x264.PROOFFIX-OUTLAWS : title: All Fall Down - video_codec: h264 + video_codec: H.264 other: Proper release_group: OUTLAWS proper_count: 1 @@ -1023,25 +1062,26 @@ ? The.Last.Survivors.2014.PROOF.SAMPLE.FiX.BDRip.x264-TOPCAT : title: The Last Survivors year: 2014 - other: Proper - format: BluRay - video_codec: h264 + other: [Proper, Rip] + source: Blu-ray + video_codec: H.264 release_group: TOPCAT type: movie ? Bad Santa 2 2016 THEATRiCAL FRENCH BDRip XviD-EXTREME : title: Bad Santa 2 year: 2016 - edition: Theatrical Edition + edition: Theatrical language: french - format: BluRay - video_codec: XviD + source: Blu-ray + other: Rip + video_codec: Xvid release_group: EXTREME type: movie ? The Lord of the Rings The Fellowship of the Ring THEATRICAL EDITION (2001) [1080p] : title: The Lord of the Rings The Fellowship of the Ring - edition: Theatrical Edition + edition: Theatrical year: 2001 screen_size: 1080p type: movie @@ -1049,19 +1089,20 @@ ? World War Z (2013) Theatrical Cut 720p BluRay x264 : title: World War Z year: 2013 - edition: Theatrical Edition + edition: Theatrical screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 type: movie ? The Heartbreak Kid (1993) UNCUT 720p WEBRip x264 : title: The Heartbreak Kid year: 1993 edition: Uncut + other: Rip screen_size: 720p - format: WEBRip - video_codec: h264 + source: Web + video_codec: H.264 type: movie ? Mrs.Doubtfire.1993.720p.OAR.Bluray.DTS.x264-CtrlHD @@ -1069,24 +1110,25 @@ year: 1993 screen_size: 720p other: Original Aspect Ratio - format: BluRay + source: Blu-ray audio_codec: DTS - video_codec: h264 + video_codec: H.264 release_group: CtrlHD type: movie ? Aliens.SE.1986.BDRip.1080p : title: Aliens - edition: Special Edition + edition: Special year: 1986 - format: BluRay + source: Blu-ray + other: Rip screen_size: 1080p type: movie ? 10 Cloverfield Lane.[Blu-Ray 1080p].[MULTI] : options: --type movie title: 10 Cloverfield Lane - format: BluRay + source: Blu-ray screen_size: 1080p language: Multiple languages type: movie @@ -1094,15 +1136,586 @@ ? 007.Spectre.[HDTC.MD].[TRUEFRENCH] : options: --type movie title: 007 Spectre - format: HDTC + source: HD Telecine language: French type: movie ? We.Are.X.2016.LIMITED.BDRip.x264-BiPOLAR : title: We Are X year: 2016 - edition: Limited Edition - format: BluRay - video_codec: h264 + edition: Limited + source: Blu-ray + other: Rip + video_codec: H.264 release_group: BiPOLAR type: movie + +? The Rack (VHS) [1956] Paul Newman +: title: The Rack + source: VHS + year: 1956 + type: movie + +? Les.Magiciens.1976.VHSRip.XViD.MKO +: title: Les Magiciens + year: 1976 + source: VHS + other: Rip + video_codec: Xvid + release_group: MKO + type: movie + +? The Boss Baby 2017 720p CAM x264 AC3 TiTAN +: title: The Boss Baby + year: 2017 + screen_size: 720p + source: Camera + video_codec: H.264 + audio_codec: Dolby Digital + release_group: TiTAN + type: movie + +? The.Boss.Baby.2017.HDCAM.XviD-MrGrey +: title: The Boss Baby + year: 2017 + source: HD Camera + video_codec: Xvid + release_group: MrGrey + type: movie + +? The Martian 2015 Multi 2160p 4K UHD Bluray HEVC10 SDR DTSHD 7.1 -Zeus +: title: The Martian + year: 2015 + language: mul + screen_size: 2160p + source: Ultra HD Blu-ray + video_codec: H.265 + color_depth: 10-bit + other: Standard Dynamic Range + audio_codec: DTS-HD + audio_channels: '7.1' + release_group: Zeus + type: movie + +? Fantastic Beasts and Where to Find Them 2016 Multi 2160p UHD BluRay HEVC HDR Atmos7.1-DDR +: title: Fantastic Beasts and Where to Find Them + year: 2016 + language: mul + screen_size: 2160p + source: Ultra HD Blu-ray + video_codec: H.265 + other: HDR10 + audio_codec: Dolby Atmos + audio_channels: '7.1' + release_group: DDR + type: movie + +? Life of Pi 2012 2160p 4K BluRay HDR10 HEVC BT2020 DTSHD 7.1 subs -DDR +: title: Life of Pi + year: 2012 + screen_size: 2160p + source: Ultra HD Blu-ray + other: [HDR10, BT.2020] + subtitle_language: und + release_group: DDR + +? Captain.America.Civil.War.HDR.1080p.HEVC.10bit.BT.2020.DTS-HD.MA.7.1-VISIONPLUSHDR +: title: Captain America Civil War + other: [HDR10, BT.2020] + screen_size: 1080p + video_codec: H.265 + color_depth: 10-bit + audio_codec: DTS-HD + audio_profile: Master Audio + audio_channels: '7.1' + release_group: VISIONPLUSHDR + type: movie + +? Deadpool.2016.4K.2160p.UHD.HQ.8bit.BluRay.8CH.x265.HEVC-MZABI.mkv +: title: Deadpool + year: 2016 + screen_size: 2160p + source: Ultra HD Blu-ray + other: High Quality + color_depth: 8-bit + audio_channels: '7.1' + video_codec: H.265 + release_group: MZABI + type: movie + +? Fantastic.Beasts.and.Where.to.Find.Them.2016.2160p.4K.UHD.10bit.HDR.BluRay.7.1.x265.HEVC-MZABI.mkv +: title: Fantastic Beasts and Where to Find Them + year: 2016 + screen_size: 2160p + source: Ultra HD Blu-ray + color_depth: 10-bit + other: HDR10 + audio_channels: '7.1' + video_codec: H.265 + release_group: MZABI + container: mkv + type: movie + +? The.Arrival.4K.HDR.HEVC.10bit.BT2020.DTS.HD-MA-MadVR.HDR10.Dolby.Vision-VISIONPLUSHDR1000 +: title: The Arrival + screen_size: 2160p + other: [HDR10, BT.2020, Dolby Vision] + video_codec: H.265 + color_depth: 10-bit + audio_codec: DTS-HD + audio_profile: Master Audio + release_group: VISIONPLUSHDR1000 + type: movie + +? How To Steal A Dog.2014.BluRay.1080p.12bit.HEVC.OPUS 5.1-Hn1Dr2.mkv +: title: How To Steal A Dog + year: 2014 + source: Blu-ray + screen_size: 1080p + color_depth: 12-bit + video_codec: H.265 + audio_codec: Opus + audio_channels: '5.1' + release_group: Hn1Dr2 + container: mkv + type: movie + +? Interstelar.2014.IMAX.RUS.BDRip.x264.-HELLYWOOD.mkv +: title: Interstelar + year: 2014 + edition: IMAX + language: ru + source: Blu-ray + other: Rip + video_codec: H.264 + release_group: HELLYWOOD + container: mkv + type: movie + +? The.Dark.Knight.IMAX.EDITION.HQ.BluRay.1080p.x264.AC3.Hindi.Eng.ETRG +: title: The Dark Knight + edition: IMAX + other: High Quality + source: Blu-ray + screen_size: 1080p + video_codec: H.264 + audio_codec: Dolby Digital + language: [hindi, english] + release_group: ETRG + type: movie + +? The.Martian.2015.4K.UHD.UPSCALED-ETRG +: title: The Martian + year: 2015 + screen_size: 2160p + other: [Ultra HD, Upscaled] + release_group: ETRG + type: movie + +? Delibal 2015 720p Upscale DVDRip x264 DD5.1 AC3 +: title: Delibal + year: 2015 + screen_size: 720p + other: [Upscaled, Rip] + source: DVD + video_codec: H.264 + audio_codec: Dolby Digital + audio_channels: '5.1' + type: movie + +? Casablanca [Ultimate Collector's Edition].1942.BRRip.XviD-VLiS +: title: Casablanca + edition: [Ultimate, Collector] + year: 1942 + source: Blu-ray + other: [Reencoded, Rip] + video_codec: Xvid + release_group: VLiS + type: movie + +? Batman V Superman Dawn of Justice 2016 Extended Cut Ultimate Edition HDRip x264 AC3-DaDDy +: title: Batman V Superman Dawn of Justice + year: 2016 + edition: [Extended, Ultimate] + other: [HD, Rip] + video_codec: H.264 + audio_codec: Dolby Digital + release_group: DaDDy + type: movie + +? Stargate SG1 Ultimate Fan Collection +: title: Stargate SG1 + edition: [Ultimate, Fan] + +? The.Jungle.Book.2016.MULTi.1080p.BluRay.x264.DTS-HD.MA.7.1.DTS-HD.HRA.5.1-LeRalou +: title: The Jungle Book + year: 2016 + language: mul + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + audio_codec: DTS-HD + audio_profile: [Master Audio, High Resolution Audio] + audio_channels: ['7.1', '5.1'] + release_group: LeRalou + type: movie + +? Terminus.2015.BluRay.1080p.x264.DTS-HD.HRA.5.1-LTT +: title: Terminus + year: 2015 + source: Blu-ray + screen_size: 1080p + video_codec: H.264 + audio_codec: DTS-HD + audio_profile: High Resolution Audio + audio_channels: '5.1' + release_group: LTT + type: movie + +? Ghost.in.the.Shell.1995.1080p.Bluray.DTSES.x264-SHiTSoNy +: title: Ghost in the Shell + year: 1995 + screen_size: 1080p + source: Blu-ray + audio_codec: DTS + audio_profile: Extended Surround + +? The.Boss.Baby.2017.BluRay.1080p.DTS-ES.x264-PRoDJi +: title: The Boss Baby + year: 2017 + source: Blu-ray + screen_size: 1080p + audio_codec: DTS + audio_profile: Extended Surround + video_codec: H.264 + release_group: PRoDJi + type: movie + +? Title.2000.720p.BluRay.DDEX.x264-HDClub.mkv +: title: Title + year: 2000 + screen_size: 720p + source: Blu-ray + audio_codec: Dolby Digital + audio_profile: EX + video_codec: H.264 + release_group: HDClub + container: mkv + type: movie + +? Jack Reacher Never Go Back 2016 720p Bluray DD-EX x264-BluPanther +: title: Jack Reacher Never Go Back + year: 2016 + screen_size: 720p + source: Blu-ray + audio_codec: Dolby Digital + audio_profile: EX + video_codec: H.264 + release_group: BluPanther + type: movie + +? How To Steal A Dog.2014.BluRay.1080p.12bit.HEVC.OPUS 5.1-Hn1Dr2.mkv +: title: How To Steal A Dog + year: 2014 + source: Blu-ray + screen_size: 1080p + color_depth: 12-bit + video_codec: H.265 + audio_codec: Opus + audio_channels: '5.1' + release_group: Hn1Dr2 + container: mkv + type: movie + +? How.To.Be.Single.2016.1080p.BluRay.x264-BLOW/blow-how.to.be.single.2016.1080p.bluray.x264.mkv +: title: How To Be Single + year: 2016 + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + release_group: BLOW + container: mkv + type: movie + +? After.the.Storm.2016.720p.YIFY +: title: After the Storm + year: 2016 + screen_size: 720p + release_group: YIFY + type: movie + +? Battle Royale 2000 DC (1080p Bluray x265 HEVC 10bit AAC 7.1 Japanese Tigole) +: title: Battle Royale + year: 2000 + edition: Director's Cut + screen_size: 1080p + source: Blu-ray + video_codec: H.265 + color_depth: 10-bit + audio_codec: AAC + audio_channels: '7.1' + language: jp + release_group: Tigole + +? Congo.The.Grand.Inga.Project.2013.1080p.BluRay.x264-OBiTS +: title: Congo The Grand Inga Project + year: 2013 + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + release_group: OBiTS + type: movie + +? Congo.The.Grand.Inga.Project.2013.BRRip.XviD.MP3-RARBG +: title: Congo The Grand Inga Project + year: 2013 + source: Blu-ray + other: [Reencoded, Rip] + video_codec: Xvid + audio_codec: MP3 + release_group: RARBG + type: movie + +? Congo.The.Grand.Inga.Project.2013.720p.BluRay.H264.AAC-RARBG +: title: Congo The Grand Inga Project + year: 2013 + screen_size: 720p + source: Blu-ray + video_codec: H.264 + audio_codec: AAC + release_group: RARBG + type: movie + +? Mit.dem.Bauch.durch.die.Wand.SWiSSGERMAN.DOKU.DVDRiP.x264-DEFLOW +: title: Mit dem Bauch durch die Wand + language: de-CH + other: [Documentary, Rip] + source: DVD + video_codec: H.264 + release_group: DEFLOW + type: movie + +? InDefinitely.Maybe.2008.1080p.EUR.BluRay.VC-1.DTS-HD.MA.5.1-FGT +: title: InDefinitely Maybe + year: 2008 + screen_size: 1080p + source: Blu-ray + video_codec: VC-1 + audio_codec: DTS-HD + audio_profile: Master Audio + audio_channels: '5.1' + release_group: FGT + type: movie + +? Bjyukujyo Kyoushi Kan XXX 720P WEBRIP MP4-GUSH +: title: Bjyukujyo Kyoushi Kan + other: [XXX, Rip] + screen_size: 720p + source: Web + container: mp4 + release_group: GUSH + type: movie + +? The.Man.With.The.Golden.Arm.1955.1080p.BluRay.x264.DTS-FGT +: title: The Man With The Golden Arm + year: 1955 + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + audio_codec: DTS + release_group: FGT + type: movie + +? blow-how.to.be.single.2016.1080p.bluray.x264.mkv +: release_group: blow + title: how to be single + year: 2016 + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + container: mkv + type: movie + +? ulshd-the.right.stuff.1983.multi.1080p.bluray.x264.mkv +: release_group: ulshd + title: the right stuff + year: 1983 + language: mul + screen_size: 1080p + source: Blu-ray + video_codec: H.264 + container: mkv + type: movie + +? FROZEN [2010] LiMiTED DVDRip H262 AAC[ ENG SUBS]-MANTESH +: title: FROZEN + year: 2010 + edition: Limited + source: DVD + other: Rip + video_codec: MPEG-2 + audio_codec: AAC + subtitle_language: english + release_group: MANTESH + type: movie + +? Family.Katta.2016.1080p.WEB-DL.H263.DD5.1.ESub-DDR +: title: Family Katta + year: 2016 + screen_size: 1080p + source: Web + video_codec: H.263 + audio_codec: Dolby Digital + audio_channels: '5.1' + subtitle_language: und + release_group: DDR + type: movie + +? Bad Boys 2 1080i.mpg2.rus.eng.ts +: title: Bad Boys 2 + screen_size: 1080i + video_codec: MPEG-2 + language: [russian, english] + container: ts + type: movie + +? Alien.Director.Cut.Ita.Eng.VP9.Opus.AlphaBot.webm +: title: Alien + edition: Director's Cut + language: [english, italian] + video_codec: VP9 + audio_codec: Opus + release_group: AlphaBot + container: webm + type: movie + +? The.Stranger.1946.US.(Kino.Classics).Bluray.1080p.LPCM.DD-2.0.x264-Grym@BTNET +: title: The Stranger + year: 1946 + country: US + source: Blu-ray + screen_size: 1080p + audio_codec: [LPCM, Dolby Digital] + audio_channels: '2.0' + video_codec: H.264 + release_group: Grym@BTNET + type: movie + +? X-Men.Apocalypse.2016.complete.hdts.pcm.TrueFrench-Scarface45.avi +: title: X-Men Apocalypse + year: 2016 + other: Complete + source: HD Telesync + audio_codec: PCM + language: french + release_group: Scarface45 + container: avi + type: movie + +? Tears.of.Steel.2012.2160p.DMRip.Eng.HDCLUB.mkv +: title: Tears of Steel + year: 2012 + screen_size: 2160p + source: Digital Master + other: Rip + language: english + release_group: HDCLUB + container: mkv + type: movie + +? "/Movies/Open Season 2 (2008)/Open Season 2 (2008) - Bluray-1080p.x264.DTS.mkv" +: options: --type movie + title: Open Season 2 + year: 2008 + source: Blu-ray + screen_size: 1080p + video_codec: H.264 + audio_codec: DTS + container: mkv + type: movie + +? Re-Animator.1985.INTEGRAL VERSION LIMITED EDITION.1080p.BluRay.REMUX.AVC.DTS-HD MA 5.1-LAZY +: title: Re-Animator + year: 1985 + edition: Limited + screen_size: 1080p + source: Blu-ray + other: Remux + video_codec: H.264 + audio_codec: DTS-HD + audio_profile: Master Audio + audio_channels: '5.1' + release_group: LAZY + type: movie + +? Test (2013) [WEBDL-1080p] [x264 AC3] [ENG+RU+PT] [NTb].mkv +: title: Test + year: 2013 + source: Web + screen_size: 1080p + video_codec: H.264 + audio_codec: Dolby Digital + language: [en, ru, pt] + release_group: NTb + container: mkv + type: movie + +? "[nextorrent.org] Bienvenue.Au.Gondwana.2016.FRENCH.DVDRiP.XViD-AViTECH.avi" +: website: nextorrent.org + title: Bienvenue Au Gondwana + year: 2016 + language: french + source: DVD + other: Rip + video_codec: Xvid + release_group: AViTECH + container: avi + type: movie + +? Star Trek First Contact (1996) Blu-Ray 1080p24 H.264 TrueHD 5.1 CtrlHD +: title: Star Trek First Contact + year: 1996 + source: Blu-ray + screen_size: 1080p + frame_rate: 24fps + video_codec: H.264 + audio_codec: Dolby TrueHD + audio_channels: '5.1' + release_group: CtrlHD + type: movie + +? The.Hobbit.The.Desolation.of.Smaug.Extended.HFR.48fps.ITA.ENG.AC3.BDRip.1080p.x264_ZMachine.mkv +: title: The Hobbit The Desolation of Smaug + edition: Extended + other: [High Frame Rate, Rip] + frame_rate: 48fps + language: [it, en] + audio_codec: Dolby Digital + source: Blu-ray + screen_size: 1080p + video_codec: H.264 + release_group: ZMachine + container: mkv + type: movie + +? Test (2013) [WEBDL-1080p] [x264 AC3] [ENG+PT+DE] [STANDARD] +: title: Test + year: 2013 + source: Web + screen_size: 1080p + video_codec: H.264 + audio_codec: Dolby Digital + language: [en, pt, de] + release_group: STANDARD + type: movie + +? Test (2013) [WEBDL-1080p] [x264 AC3] [ENG+DE+IT] [STANDARD] +: title: Test + year: 2013 + source: Web + screen_size: 1080p + video_codec: H.264 + audio_codec: Dolby Digital + language: [en, de, it] + release_group: STANDARD + type: movie diff --git a/ext/guessit/test/rules/audio_codec.yml b/ext/guessit/test/rules/audio_codec.yml index df5ac4dc9b..cbb6fc8bc1 100644 --- a/ext/guessit/test/rules/audio_codec.yml +++ b/ext/guessit/test/rules/audio_codec.yml @@ -12,18 +12,18 @@ ? +DD ? +Dolby Digital ? +AC3 -: audio_codec: AC3 +: audio_codec: Dolby Digital ? +DDP ? +DD+ ? +EAC3 -: audio_codec: EAC3 +: audio_codec: Dolby Digital Plus ? +DolbyAtmos ? +Dolby Atmos ? +Atmos ? -Atmosphere -: audio_codec: DolbyAtmos +: audio_codec: Dolby Atmos ? +AAC : audio_codec: AAC @@ -36,33 +36,34 @@ ? +True-HD ? +trueHD -: audio_codec: TrueHD +: audio_codec: Dolby TrueHD ? +True-HD51 ? +trueHD51 -: audio_codec: TrueHD +: audio_codec: Dolby TrueHD audio_channels: '5.1' - +? +DTSHD +? +DTS HD ? +DTS-HD -: audio_codec: DTS - audio_profile: HD +: audio_codec: DTS-HD ? +DTS-HDma -: audio_codec: DTS - audio_profile: HDMA +? +DTSMA +: audio_codec: DTS-HD + audio_profile: Master Audio ? +AC3-hq -: audio_codec: AC3 - audio_profile: HQ +: audio_codec: Dolby Digital + audio_profile: High Quality ? +AAC-HE : audio_codec: AAC - audio_profile: HE + audio_profile: High Efficiency ? +AAC-LC : audio_codec: AAC - audio_profile: LC + audio_profile: Low Complexity ? +AAC2.0 ? +AAC20 @@ -90,8 +91,41 @@ ? DD5.1 ? DD51 -: audio_codec: AC3 +: audio_codec: Dolby Digital audio_channels: '5.1' ? -51 : audio_channels: '5.1' + +? DTS-HD.HRA +? DTSHD.HRA +? DTS-HD.HR +? DTSHD.HR +? -HRA +? -HR +: audio_codec: DTS-HD + audio_profile: High Resolution Audio + +? DTSES +? DTS-ES +? -ES +: audio_codec: DTS + audio_profile: Extended Surround + +? DD-EX +? DDEX +? -EX +: audio_codec: Dolby Digital + audio_profile: EX + +? OPUS +: audio_codec: Opus + +? Vorbis +: audio_codec: Vorbis + +? PCM +: audio_codec: PCM + +? LPCM +: audio_codec: LPCM diff --git a/ext/guessit/test/rules/cds.yml b/ext/guessit/test/rules/cds.yml index cc63765e51..d76186c6b4 100644 --- a/ext/guessit/test/rules/cds.yml +++ b/ext/guessit/test/rules/cds.yml @@ -7,4 +7,4 @@ ? Some.Title-DVDRIP-x264-CDP : cd: !!null release_group: CDP - video_codec: h264 + video_codec: H.264 diff --git a/ext/guessit/test/rules/country.yml b/ext/guessit/test/rules/country.yml index f2da1b2057..7e96939801 100644 --- a/ext/guessit/test/rules/country.yml +++ b/ext/guessit/test/rules/country.yml @@ -8,3 +8,6 @@ ? This.is.us.title : title: This is us title +? This.Is.Us +: options: --no-embedded-config + title: This Is Us diff --git a/ext/guessit/test/rules/edition.yml b/ext/guessit/test/rules/edition.yml index 4d96017b3c..4b7fd98668 100644 --- a/ext/guessit/test/rules/edition.yml +++ b/ext/guessit/test/rules/edition.yml @@ -7,25 +7,57 @@ ? Collector ? Collector Edition ? Edition Collector -: edition: Collector Edition +: edition: Collector ? Special Edition ? Edition Special ? -Special -: edition: Special Edition +: edition: Special ? Criterion Edition ? Edition Criterion +? CC ? -Criterion -: edition: Criterion Edition +: edition: Criterion ? Deluxe ? Deluxe Edition ? Edition Deluxe -: edition: Deluxe Edition +: edition: Deluxe ? Super Movie Alternate XViD ? Super Movie Alternative XViD ? Super Movie Alternate Cut XViD ? Super Movie Alternative Cut XViD : edition: Alternative Cut + +? ddc +: edition: Director's Definitive Cut + +? IMAX +? IMAX Edition +: edition: IMAX + +? ultimate edition +? -ultimate +: edition: Ultimate + +? ultimate collector edition +? ultimate collector's edition +? ultimate collectors edition +? -collectors edition +? -ultimate edition +: edition: [Ultimate, Collector] + +? ultimate collectors edition dc +: edition: [Ultimate, Collector, Director's Cut] + +? fan edit +? fan edition +? fan collection +: edition: Fan + +? ultimate fan edit +? ultimate fan edition +? ultimate fan collection +: edition: [Ultimate, Fan] diff --git a/ext/guessit/test/rules/episodes.yml b/ext/guessit/test/rules/episodes.yml index 9c67c294a9..98325fa1d9 100644 --- a/ext/guessit/test/rules/episodes.yml +++ b/ext/guessit/test/rules/episodes.yml @@ -156,7 +156,7 @@ ? Show.Name.Season.1.3&5.HDTV.XviD-GoodGroup[SomeTrash] ? Show.Name.Season.1.3 and 5.HDTV.XviD-GoodGroup[SomeTrash] -: format: HDTV +: source: HDTV release_group: GoodGroup[SomeTrash] season: - 1 @@ -164,12 +164,12 @@ - 5 title: Show Name type: episode - video_codec: XviD + video_codec: Xvid ? Show.Name.Season.1.2.3-5.HDTV.XviD-GoodGroup[SomeTrash] ? Show.Name.Season.1.2.3~5.HDTV.XviD-GoodGroup[SomeTrash] ? Show.Name.Season.1.2.3 to 5.HDTV.XviD-GoodGroup[SomeTrash] -: format: HDTV +: source: HDTV release_group: GoodGroup[SomeTrash] season: - 1 @@ -179,18 +179,19 @@ - 5 title: Show Name type: episode - video_codec: XviD + video_codec: Xvid ? The.Get.Down.S01EP01.FRENCH.720p.WEBRIP.XVID-STR : episode: 1 - format: WEBRip + source: Web + other: Rip language: fr release_group: STR screen_size: 720p season: 1 title: The Get Down type: episode - video_codec: XviD + video_codec: Xvid ? My.Name.Is.Earl.S01E01-S01E21.SWE-SUB : episode: @@ -269,4 +270,10 @@ ? Episode71 ? Episode 71 -: episode: 71 \ No newline at end of file +: episode: 71 + +? S01D02.3-5-GROUP +: disc: [2, 3, 4, 5] + +? S01D02&4-6&8 +: disc: [2, 4, 5, 6, 8] diff --git a/ext/guessit/test/rules/format.yml b/ext/guessit/test/rules/format.yml deleted file mode 100644 index e983cfb1b9..0000000000 --- a/ext/guessit/test/rules/format.yml +++ /dev/null @@ -1,138 +0,0 @@ -# Multiple input strings having same expected results can be chained. -# Use - marker to check inputs that should not match results. -? +VHS -? +VHSRip -? +VHS-Rip -? +VhS_rip -? +VHS.RIP -? -VHSAnythingElse -? -SomeVHS stuff -? -VH -? -VHx -? -VHxRip -: format: VHS - -? +Cam -? +CamRip -? +CaM Rip -? +Cam_Rip -? +cam.rip -: format: Cam - -? +Telesync -? +TS -? +HD TS -? -Hd.Ts # ts file extension -? -HD.TS # ts file extension -? +Hd-Ts -: format: Telesync - -? +Workprint -? +workPrint -? +WorkPrint -? +WP -? -Work Print -: format: Workprint - -? +Telecine -? +teleCine -? +TC -? -Tele Cine -: format: Telecine - -? +PPV -? +ppv-rip -: format: PPV - -? -TV -? +SDTV -? +SDTVRIP -? +Rip sd tv -? +TvRip -? +Rip TV -: format: TV - -? +DVB -? +DVB-Rip -? +DvBRiP -? +pdTV -? +Pd Tv -: format: DVB - -? +DVD -? +DVD-RIP -? +video ts -? +DVDR -? +DVD 9 -? +dvd 5 -? -dvd ts -: format: DVD - -format: ts - -? +HDTV -? +tv rip hd -? +HDtv Rip -? +HdRip -: format: HDTV - -? +VOD -? +VodRip -? +vod rip -: format: VOD - -? +webrip -? +Web Rip -? +webdlrip -? +web dl rip -? +webcap -? +web cap -: format: WEBRip - -? +webdl -? +Web DL -? +webHD -? +WEB hd -? +web -: format: WEB-DL - -? +HDDVD -? +hd dvd -? +hdDvdRip -: format: HD-DVD - -? +BluRay -? +BluRay rip -? +BD -? +BR -? +BDRip -? +BR rip -? +BD5 -? +BD9 -? +BD25 -? +bd50 -: format: BluRay - -? XVID.NTSC.DVDR.nfo -: format: DVD - -? AHDTV -: format: AHDTV - -? dsr -? dsrip -? ds rip -? dsrrip -? dsr rip -? satrip -? sat rip -? dth -? dthrip -? dth rip -: format: SATRip - -? HDTC -: format: HDTC - -? UHDTV -? UHDRip -: format: UHDTV diff --git a/ext/guessit/test/rules/language.yml b/ext/guessit/test/rules/language.yml index 51bbd8da87..10e5b9c05f 100644 --- a/ext/guessit/test/rules/language.yml +++ b/ext/guessit/test/rules/language.yml @@ -36,4 +36,12 @@ ? +ENG.-.SubSV ? +ENG.-.SVSUB : language: English - subtitle_language: Swedish \ No newline at end of file + subtitle_language: Swedish + +? The English Patient (1996) +: title: The English Patient + -language: english + +? French.Kiss.1995.1080p +: title: French Kiss + -language: french diff --git a/ext/guessit/test/rules/other.yml b/ext/guessit/test/rules/other.yml index 3d3df706ec..113b6d8132 100644 --- a/ext/guessit/test/rules/other.yml +++ b/ext/guessit/test/rules/other.yml @@ -12,22 +12,22 @@ ? +AudioFixed ? +Audio Fix ? +Audio Fixed -: other: AudioFix +: other: Audio Fixed ? +SyncFix ? +SyncFixed ? +Sync Fix ? +Sync Fixed -: other: SyncFix +: other: Sync Fixed ? +DualAudio ? +Dual Audio -: other: DualAudio +: other: Dual Audio ? +ws ? +WideScreen ? +Wide Screen -: other: WideScreen +: other: Widescreen # Fix and Real must be surround by others properties to be matched. ? DVD.Real.XViD @@ -58,18 +58,20 @@ proper_count: 1 ? XViD.Fansub -: other: Fansub +: other: Fan Subtitled ? XViD.Fastsub -: other: Fastsub +: other: Fast Subtitled ? +Season Complete ? -Complete : other: Complete ? R5 +: other: Region 5 + ? RC -: other: R5 +: other: Region C ? PreAir ? Pre Air @@ -90,28 +92,23 @@ ? FHD ? FullHD ? Full HD -: other: FullHD +: other: Full HD ? UHD ? Ultra ? UltraHD ? Ultra HD -: other: UltraHD +: other: Ultra HD ? mHD # ?? -: other: mHD - ? HDLight -: other: HDLight +: other: Micro HD ? HQ -: other: HQ - -? ddc -: other: DDC +: other: High Quality ? hr -: other: HR +: other: High Resolution ? PAL : other: PAL @@ -122,15 +119,14 @@ ? NTSC : other: NTSC -? CC -: other: CC +? LDTV +: other: Low Definition ? LD -? LDTV -: other: LD +: other: Line Dubbed ? MD -: other: MD +: other: Mic Dubbed ? -The complete movie : other: Complete @@ -139,16 +135,38 @@ : title: The complete movie ? +AC3-HQ -: audio_profile: HQ +: audio_profile: High Quality ? Other-HQ -: other: HQ +: other: High Quality ? reenc ? re-enc ? re-encoded ? reencoded -: other: ReEncoded +: other: Reencoded ? CONVERT XViD -: other: Converted \ No newline at end of file +: other: Converted + +? +HDRIP # it's a Rip from non specified HD source +: other: [HD, Rip] + +? SDR +: other: Standard Dynamic Range + +? HDR +? HDR10 +? -HDR100 +: other: HDR10 + +? BT2020 +? BT.2020 +? -BT.20200 +? -BT.2021 +: other: BT.2020 + +? Upscaled +? Upscale +: other: Upscaled + diff --git a/ext/guessit/test/rules/release_group.yml b/ext/guessit/test/rules/release_group.yml index f9d01e723f..c96383e941 100644 --- a/ext/guessit/test/rules/release_group.yml +++ b/ext/guessit/test/rules/release_group.yml @@ -42,30 +42,30 @@ ? Show.Name.x264-byEMP : title: Show Name - video_codec: h264 + video_codec: H.264 release_group: byEMP ? Show.Name.x264-NovaRip : title: Show Name - video_codec: h264 + video_codec: H.264 release_group: NovaRip ? Show.Name.x264-PARTiCLE : title: Show Name - video_codec: h264 + video_codec: H.264 release_group: PARTiCLE ? Show.Name.x264-POURMOi : title: Show Name - video_codec: h264 + video_codec: H.264 release_group: POURMOi ? Show.Name.x264-RipPourBox : title: Show Name - video_codec: h264 + video_codec: H.264 release_group: RipPourBox ? Show.Name.x264-RiPRG : title: Show Name - video_codec: h264 + video_codec: H.264 release_group: RiPRG diff --git a/ext/guessit/test/rules/screen_size.yml b/ext/guessit/test/rules/screen_size.yml index 1145dd7eb3..450d77e4ef 100644 --- a/ext/guessit/test/rules/screen_size.yml +++ b/ext/guessit/test/rules/screen_size.yml @@ -2,68 +2,258 @@ # Use - marker to check inputs that should not match results. ? +360p ? +360px -? +360i -? "+360" +? -360 ? +500x360 +? -250x360 +: screen_size: 360p + +? +640x360 +? -640x360i +? -684x360i : screen_size: 360p + aspect_ratio: 1.778 + +? +360i +: screen_size: 360i + +? +480x360i +? -480x360p +? -450x360 +: screen_size: 360i + aspect_ratio: 1.333 ? +368p ? +368px -? +368i -? "+368" +? -368i +? -368 ? +500x368 : screen_size: 368p +? -490x368 +? -700x368 +: screen_size: 368p + +? +492x368p +: screen_size: + aspect_ratio: 1.337 + +? +654x368 +: screen_size: 368p + aspect_ratio: 1.777 + +? +698x368 +: screen_size: 368p + aspect_ratio: 1.897 + +? +368i +: -screen_size: 368i + ? +480p ? +480px -? +480i -? "+480" -? +500x480 +? -480i +? -480 +? -500x480 +? -638x480 +? -920x480 +: screen_size: 480p + +? +640x480 : screen_size: 480p + aspect_ratio: 1.333 + +? +852x480 +: screen_size: 480p + aspect_ratio: 1.775 + +? +910x480 +: screen_size: 480p + aspect_ratio: 1.896 + +? +500x480 +? +500 x 480 +? +500 * 480 +? +500x480p +? +500X480i +: screen_size: 500x480 + aspect_ratio: 1.042 + +? +480i +? +852x480i +: screen_size: 480i ? +576p ? +576px -? +576i -? "+576" -? +500x576 +? -576i +? -576 +? -500x576 +? -766x576 +? -1094x576 : screen_size: 576p +? +768x576 +: screen_size: 576p + aspect_ratio: 1.333 + +? +1024x576 +: screen_size: 576p + aspect_ratio: 1.778 + +? +1092x576 +: screen_size: 576p + aspect_ratio: 1.896 + +? +500x576 +: screen_size: 500x576 + aspect_ratio: 0.868 + +? +576i +: screen_size: 576i + ? +720p ? +720px +? -720i ? 720hd ? 720pHD -? +720i -? "+720" -? +500x720 +? -720 +? -500x720 +? -950x720 +? -1368x720 +: screen_size: 720p + +? +960x720 +: screen_size: 720p + aspect_ratio: 1.333 + +? +1280x720 : screen_size: 720p + aspect_ratio: 1.778 + +? +1366x720 +: screen_size: 720p + aspect_ratio: 1.897 + +? +500x720 +: screen_size: 500x720 + aspect_ratio: 0.694 ? +900p ? +900px -? +900i -? "+900" -? +500x900 +? -900i +? -900 +? -500x900 +? -1198x900 +? -1710x900 +: screen_size: 900p + +? +1200x900 +: screen_size: 900p + aspect_ratio: 1.333 + +? +1600x900 : screen_size: 900p + aspect_ratio: 1.778 + +? +1708x900 +: screen_size: 900p + aspect_ratio: 1.898 + +? +500x900 +? +500x900p +? +500x900i +: screen_size: 500x900 + aspect_ratio: 0.556 + +? +900i +: screen_size: 900i ? +1080p ? +1080px ? +1080hd ? +1080pHD ? -1080i -? "+1080" -? +500x1080 +? -1080 +? -500x1080 +? -1438x1080 +? -2050x1080 +: screen_size: 1080p + +? +1440x1080 +: screen_size: 1080p + aspect_ratio: 1.333 + +? +1920x1080 +: screen_size: 1080p + aspect_ratio: 1.778 + +? +2048x1080 : screen_size: 1080p + aspect_ratio: 1.896 ? +1080i ? -1080p : screen_size: 1080i +? 1440p +: screen_size: 1440p + +? +500x1080 +: screen_size: 500x1080 + aspect_ratio: 0.463 + ? +2160p ? +2160px -? +2160i -? "+2160" +? -2160i +? -2160 ? +4096x2160 -: screen_size: 4K +? +4k +? -2878x2160 +? -4100x2160 +: screen_size: 2160p + +? +2880x2160 +: screen_size: 2160p + aspect_ratio: 1.333 + +? +3840x2160 +: screen_size: 2160p + aspect_ratio: 1.778 + +? +4098x2160 +: screen_size: 2160p + aspect_ratio: 1.897 + +? +500x2160 +: screen_size: 500x2160 + aspect_ratio: 0.231 + +? +4320p +? +4320px +? -4320i +? -4320 +? -5758x2160 +? -8198x2160 +: screen_size: 4320p + +? +5760x4320 +: screen_size: 4320p + aspect_ratio: 1.333 + +? +7680x4320 +: screen_size: 4320p + aspect_ratio: 1.778 + +? +8196x4320 +: screen_size: 4320p + aspect_ratio: 1.897 + +? +500x4320 +: screen_size: 500x4320 + aspect_ratio: 0.116 ? Test.File.720hd.bluray +? Test.File.720p24 +? Test.File.720p30 ? Test.File.720p50 +? Test.File.720p60 +? Test.File.720p120 : screen_size: 720p diff --git a/ext/guessit/test/rules/source.yml b/ext/guessit/test/rules/source.yml new file mode 100644 index 0000000000..cda8f1ac43 --- /dev/null +++ b/ext/guessit/test/rules/source.yml @@ -0,0 +1,323 @@ +# Multiple input strings having same expected results can be chained. +# Use - marker to check inputs that should not match results. +? +VHS +? -VHSAnythingElse +? -SomeVHS stuff +? -VH +? -VHx +: source: VHS + -other: Rip + +? +VHSRip +? +VHS-Rip +? +VhS_rip +? +VHS.RIP +? -VHS +? -VHxRip +: source: VHS + other: Rip + +? +Cam +: source: Camera + -other: Rip + +? +CamRip +? +CaM Rip +? +Cam_Rip +? +cam.rip +? -Cam +: source: Camera + other: Rip + +? +HDCam +? +HD-Cam +: source: HD Camera + -other: Rip + +? +HDCamRip +? +HD-Cam.rip +? -HDCam +? -HD-Cam +: source: HD Camera + other: Rip + +? +Telesync +? +TS +: source: Telesync + -other: Rip + +? +TelesyncRip +? +TSRip +? -Telesync +? -TS +: source: Telesync + other: Rip + +? +HD TS +? -Hd.Ts # ts file extension +? -HD.TS # ts file extension +? +Hd-Ts +: source: HD Telesync + -other: Rip + +? +HD TS Rip +? +Hd-Ts-Rip +? -HD TS +? -Hd-Ts +: source: HD Telesync + other: Rip + +? +Workprint +? +workPrint +? +WorkPrint +? +WP +? -Work Print +: source: Workprint + -other: Rip + +? +Telecine +? +teleCine +? +TC +? -Tele Cine +: source: Telecine + -other: Rip + +? +Telecine Rip +? +teleCine-Rip +? +TC-Rip +? -Telecine +? -TC +: source: Telecine + other: Rip + +? +HD-TELECINE +? +HDTC +: source: HD Telecine + -other: Rip + +? +HD-TCRip +? +HD TELECINE RIP +? -HD-TELECINE +? -HDTC +: source: HD Telecine + other: Rip + +? +PPV +: source: Pay-per-view + -other: Rip + +? +ppv-rip +? -PPV +: source: Pay-per-view + other: Rip + +? -TV +? +SDTV +? +TV-Dub +: source: TV + -other: Rip + +? +SDTVRIP +? +Rip sd tv +? +TvRip +? +Rip TV +? -TV +? -SDTV +: source: TV + other: Rip + +? +DVB +? +pdTV +? +Pd Tv +: source: Digital TV + -other: Rip + +? +DVB-Rip +? +DvBRiP +? +pdtvRiP +? +pd tv RiP +? -DVB +? -pdTV +? -Pd Tv +: source: Digital TV + other: Rip + +? +DVD +? +video ts +? +DVDR +? +DVD 9 +? +dvd 5 +? -dvd ts +: source: DVD + -source: Telesync + -other: Rip + +? +DVD-RIP +? -video ts +? -DVD +? -DVDR +? -DVD 9 +? -dvd 5 +: source: DVD + other: Rip + +? +HDTV +: source: HDTV + -other: Rip + +? +tv rip hd +? +HDtv Rip +? -HdRip # it's a Rip from non specified HD source +? -HDTV +: source: HDTV + other: Rip + +? +VOD +: source: Video on Demand + -other: Rip + +? +VodRip +? +vod rip +? -VOD +: source: Video on Demand + other: Rip + +? +webrip +? +Web Rip +? +webdlrip +? +web dl rip +? +webcap +? +web cap +? +webcaprip +? +web cap rip +: source: Web + other: Rip + +? +webdl +? +Web DL +? +webHD +? +WEB hd +? +web +: source: Web + -other: Rip + +? +HDDVD +? +hd dvd +: source: HD-DVD + -other: Rip + +? +hdDvdRip +? -HDDVD +? -hd dvd +: source: HD-DVD + other: Rip + +? +BluRay +? +BD +? +BD5 +? +BD9 +? +BD25 +? +bd50 +: source: Blu-ray + -other: Rip + +? +BR-Scr +? +BR.Screener +: source: Blu-ray + other: [Reencoded, Screener] + -language: pt-BR + +? +BR-Rip +? +BRRip +: source: Blu-ray + other: [Reencoded, Rip] + -language: pt-BR + +? +BluRay rip +? +BDRip +? -BluRay +? -BD +? -BR +? -BR rip +? -BD5 +? -BD9 +? -BD25 +? -bd50 +: source: Blu-ray + other: Rip + +? XVID.NTSC.DVDR.nfo +: source: DVD + -other: Rip + +? +AHDTV +: source: Analog HDTV + -other: Rip + +? +dsr +? +dth +: source: Satellite + -other: Rip + +? +dsrip +? +ds rip +? +dsrrip +? +dsr rip +? +satrip +? +sat rip +? +dthrip +? +dth rip +? -dsr +? -dth +: source: Satellite + other: Rip + +? +UHDTV +: source: Ultra HDTV + -other: Rip + +? +UHDRip +? +UHDTV Rip +? -UHDTV +: source: Ultra HDTV + other: Rip + +? UHD Bluray +? UHD 2160p Bluray +? UHD 8bit Bluray +? UHD HQ 8bit Bluray +? Ultra Bluray +? Ultra HD Bluray +? Bluray ULTRA +? Bluray Ultra HD +? Bluray UHD +? 4K Bluray +? 2160p Bluray +? UHD 10bit HDR Bluray +? UHD HDR10 Bluray +? -HD Bluray +? -AMERICAN ULTRA (2015) 1080p Bluray +? -American.Ultra.2015.BRRip +? -BRRip XviD AC3-ULTRAS +? -UHD Proper Bluray +: source: Ultra HD Blu-ray + +? UHD.BRRip +? UHD.2160p.BRRip +? BRRip.2160p.UHD +? BRRip.[4K-2160p-UHD] +: source: Ultra HD Blu-ray + other: [Reencoded, Rip] + +? UHD.2160p.BDRip +? BDRip.[4K-2160p-UHD] +: source: Ultra HD Blu-ray + other: Rip + +? DM +: source: Digital Master + +? DMRIP +? DM-RIP +: source: Digital Master + other: Rip diff --git a/ext/guessit/test/rules/video_codec.yml b/ext/guessit/test/rules/video_codec.yml index a11991ecc7..c37c1a6033 100644 --- a/ext/guessit/test/rules/video_codec.yml +++ b/ext/guessit/test/rules/video_codec.yml @@ -6,15 +6,19 @@ ? Rv30 ? rv40 ? -xrv40 -: video_codec: Real +: video_codec: RealVideo ? mpeg2 ? MPEG2 +? MPEG-2 +? mpg2 +? H262 +? H.262 +? x262 ? -mpeg -? -mpeg 2 # Not sure if we should ignore this one ... ? -xmpeg2 ? -mpeg2x -: video_codec: Mpeg2 +: video_codec: MPEG-2 ? DivX ? -div X @@ -26,19 +30,29 @@ ? XviD ? xvid ? -x vid -: video_codec: XviD +: video_codec: Xvid + +? h263 +? x263 +? h.263 +: video_codec: H.263 ? h264 ? x264 ? h.264 ? x.264 ? mpeg4-AVC +? AVC +? AVCHD +? AVCHD-SC +? H.264-SC +? H.264-AVCHD-SC ? -MPEG-4 ? -mpeg4 ? -mpeg ? -h 265 ? -x265 -: video_codec: h264 +: video_codec: H.264 ? h265 ? x265 @@ -47,13 +61,27 @@ ? hevc ? -h 264 ? -x264 -: video_codec: h265 +: video_codec: H.265 ? hevc10 ? HEVC-YUV420P10 -: video_codec: h265 - video_profile: 10bit +: video_codec: H.265 + color_depth: 10-bit ? h265-HP -: video_codec: h265 - video_profile: HP \ No newline at end of file +: video_codec: H.265 + video_profile: High + +? VC1 +? VC-1 +: video_codec: VC-1 + +? VP7 +: video_codec: VP7 + +? VP8 +? VP80 +: video_codec: VP8 + +? VP9 +: video_codec: VP9 diff --git a/ext/guessit/test/streaming_services.yaml b/ext/guessit/test/streaming_services.yaml new file mode 100644 index 0000000000..adf52e715e --- /dev/null +++ b/ext/guessit/test/streaming_services.yaml @@ -0,0 +1,1934 @@ +? House.of.Cards.2013.S02E03.1080p.NF.WEBRip.DD5.1.x264-NTb.mkv +? House.of.Cards.2013.S02E03.1080p.Netflix.WEBRip.DD5.1.x264-NTb.mkv +: title: House of Cards + year: 2013 + season: 2 + episode: 3 + screen_size: 1080p + streaming_service: Netflix + source: Web + other: Rip + audio_channels: "5.1" + audio_codec: Dolby Digital + video_codec: H.264 + release_group: NTb + +? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.720p.CC.WEBRip.AAC2.0.x264-BTW.mkv +? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.720p.ComedyCentral.WEBRip.AAC2.0.x264-BTW.mkv +? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.720p.Comedy.Central.WEBRip.AAC2.0.x264-BTW.mkv +: audio_channels: '2.0' + audio_codec: AAC + date: 2015-07-01 + edition: Extended + source: Web + other: Rip + release_group: BTW + screen_size: 720p + streaming_service: Comedy Central + title: The Daily Show + episode_title: Kirsten Gillibrand + video_codec: H.264 + +? The.Daily.Show.2015.07.01.Kirsten.Gillibrand.Extended.Interview.720p.CC.WEBRip.AAC2.0.x264-BTW.mkv +: audio_channels: '2.0' + audio_codec: AAC + date: 2015-07-01 + source: Web + release_group: BTW + screen_size: 720p + streaming_service: Comedy Central + title: The Daily Show + episode_title: Kirsten Gillibrand Extended Interview + video_codec: H.264 + +? The.Daily.Show.2015.07.02.Sarah.Vowell.CC.WEBRip.AAC2.0.x264-BTW.mkv +: audio_channels: '2.0' + audio_codec: AAC + date: 2015-07-02 + source: Web + release_group: BTW + streaming_service: Comedy Central + title: The Daily Show + episode_title: Sarah Vowell + video_codec: H.264 + +# Streaming service: Amazon +? Show.Name.S07E04.Service.1080p.AMZN.WEBRip.DD+5.1.x264 +? Show.Name.S07E04.Service.1080p.AmazonPrime.WEBRip.DD+5.1.x264 +: title: Show Name + season: 7 + episode: 4 + episode_title: Service + screen_size: 1080p + streaming_service: Amazon Prime + source: Web + other: Rip + audio_codec: Dolby Digital Plus + audio_channels: '5.1' + video_codec: H.264 + type: episode + +# Streaming service: Comedy Central +? Show.Name.2016.09.28.Nice.Title.Extended.1080p.CC.WEBRip.AAC2.0.x264-monkee +: title: Show Name + date: 2016-09-28 + episode_title: Nice Title + edition: Extended + other: Rip + screen_size: 1080p + streaming_service: Comedy Central + source: Web + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: The CW +? Show.Name.US.S12E20.Nice.Title.720p.CW.WEBRip.AAC2.0.x264-monkee +? Show.Name.US.S12E20.Nice.Title.720p.TheCW.WEBRip.AAC2.0.x264-monkee +: title: Show Name + country: US + season: 12 + episode: 20 + episode_title: Nice Title + screen_size: 720p + streaming_service: The CW + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: AMBC +? Show.Name.2016.09.27.Nice.Title.720p.AMBC.WEBRip.AAC2.0.x264-monkee +: title: Show Name + date: 2016-09-27 + episode_title: Nice Title + screen_size: 720p + streaming_service: ABC + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: HIST +? Show.Name.720p.HIST.WEBRip.AAC2.0.H.264-monkee +? Show.Name.720p.History.WEBRip.AAC2.0.H.264-monkee +: options: -t episode + title: Show Name + screen_size: 720p + streaming_service: History + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: PBS +? Show.Name.2015.Nice.Title.1080p.PBS.WEBRip.AAC2.0.H264-monkee +: options: -t episode + title: Show Name + year: 2015 + episode_title: Nice Title + screen_size: 1080p + streaming_service: PBS + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: SeeSo +? Show.Name.2016.Nice.Title.1080p.SESO.WEBRip.AAC2.0.x264-monkee +: options: -t episode + title: Show Name + year: 2016 + episode_title: Nice Title + screen_size: 1080p + streaming_service: SeeSo + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: Discovery +? Show.Name.S01E03.Nice.Title.720p.DISC.WEBRip.AAC2.0.x264-NTb +? Show.Name.S01E03.Nice.Title.720p.Discovery.WEBRip.AAC2.0.x264-NTb +: title: Show Name + season: 1 + episode: 3 + episode_title: Nice Title + screen_size: 720p + streaming_service: Discovery + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: NTb + type: episode + +# Streaming service: BBC iPlayer +? Show.Name.2016.08.18.Nice.Title.720p.iP.WEBRip.AAC2.0.H.264-monkee +? Show.Name.2016.08.18.Nice.Title.720p.BBCiPlayer.WEBRip.AAC2.0.H.264-monkee +: title: Show Name + date: 2016-08-18 + episode_title: Nice Title + streaming_service: BBC iPlayer + screen_size: 720p + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: A&E +? Show.Name.S15E18.Nice.Title.720p.AE.WEBRip.AAC2.0.H.264-monkee +? Show.Name.S15E18.Nice.Title.720p.A&E.WEBRip.AAC2.0.H.264-monkee +: title: Show Name + season: 15 + episode: 18 + episode_title: Nice Title + screen_size: 720p + streaming_service: A&E + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: Adult Swim +? Show.Name.S04E01.Nice.Title.1080p.AS.WEBRip.AAC2.0.H.264-monkee +? Show.Name.S04E01.Nice.Title.1080p.AdultSwim.WEBRip.AAC2.0.H.264-monkee +: title: Show Name + season: 4 + episode: 1 + episode_title: Nice Title + screen_size: 1080p + streaming_service: Adult Swim + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: Netflix +? Show.Name.2013.S02E03.1080p.NF.WEBRip.DD5.1.x264-NTb.mkv +: title: Show Name + year: 2013 + season: 2 + episode: 3 + screen_size: 1080p + streaming_service: Netflix + source: Web + other: Rip + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: NTb + container: mkv + type: episode + +# Streaming service: CBS +? Show.Name.2016.05.10.Nice.Title.720p.CBS.WEBRip.AAC2.0.x264-monkee +: title: Show Name + date: 2016-05-10 + episode_title: Nice Title + screen_size: 720p + streaming_service: CBS + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: NBA TV +? NBA.2016.02.27.Team.A.vs.Team.B.720p.NBA.WEBRip.AAC2.0.H.264-monkee +? NBA.2016.02.27.Team.A.vs.Team.B.720p.NBATV.WEBRip.AAC2.0.H.264-monkee +: title: NBA + date: 2016-02-27 + episode_title: Team A vs Team B + screen_size: 720p + streaming_service: NBA TV + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: ePix +? Show.Name.S05E04.Nice.Title.Part4.720p.EPIX.WEBRip.AAC2.0.H.264-monkee +? Show.Name.S05E04.Nice.Title.Part4.720p.ePix.WEBRip.AAC2.0.H.264-monkee +: title: Show Name + season: 5 + episode: 4 + episode_title: Nice Title + part: 4 + screen_size: 720p + streaming_service: ePix + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: NBC +? Show.Name.S41E03.Nice.Title.720p.NBC.WEBRip.AAC2.0.x264-monkee +: title: Show Name + season: 41 + episode: 3 + episode_title: Nice Title + screen_size: 720p + streaming_service: NBC + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: Syfy +? Show.Name.S01E02.Nice.Title.720p.SYFY.WEBRip.AAC2.0.x264-group +? Show.Name.S01E02.Nice.Title.720p.Syfy.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: Syfy + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: Spike TV +? Show.Name.S01E02.Nice.Title.720p.SPKE.WEBRip.AAC2.0.x264-group +? Show.Name.S01E02.Nice.Title.720p.Spike TV.WEBRip.AAC2.0.x264-group +? Show.Name.S01E02.Nice.Title.720p.SpikeTV.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: Spike TV + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: IFC +? Show.Name.S01E02.Nice.Title.720p.IFC.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: IFC + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: NATG +? Show.Name.S01E02.Nice.Title.720p.NATG.WEBRip.AAC2.0.x264-group +? Show.Name.S01E02.Nice.Title.720p.NationalGeographic.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: National Geographic + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: NFL +? Show.Name.S01E02.Nice.Title.720p.NFL.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: NFL + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: UFC +? Show.Name.S01E02.Nice.Title.720p.UFC.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: UFC + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: TV Land +? Show.Name.S01E02.Nice.Title.720p.TVL.WEBRip.AAC2.0.x264-group +? Show.Name.S01E02.Nice.Title.720p.TVLand.WEBRip.AAC2.0.x264-group +? Show.Name.S01E02.Nice.Title.720p.TV Land.WEBRip.AAC2.0.x264-group +: title: Show Name + season: 1 + episode: 2 + episode_title: Nice Title + screen_size: 720p + streaming_service: TV Land + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: group + type: episode + +# Streaming service: Crunchy Roll +? Show.Name.S01.1080p.CR.WEBRip.AAC.2.0.x264-monkee +: title: Show Name + season: 1 + screen_size: 1080p + streaming_service: Crunchy Roll + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: Disney +? Show.Name.S01.1080p.DSNY.WEBRip.AAC.2.0.x264-monkee +? Show.Name.S01.1080p.Disney.WEBRip.AAC.2.0.x264-monkee +: title: Show Name + season: 1 + screen_size: 1080p + streaming_service: Disney + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: Nickelodeon +? Show.Name.S01.1080p.NICK.WEBRip.AAC.2.0.x264-monkee +? Show.Name.S01.1080p.Nickelodeon.WEBRip.AAC.2.0.x264-monkee +: title: Show Name + season: 1 + screen_size: 1080p + streaming_service: Nickelodeon + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: TFou +? Show.Name.S01.1080p.TFOU.WEBRip.AAC.2.0.x264-monkee +? Show.Name.S01.1080p.TFou.WEBRip.AAC.2.0.x264-monkee +: title: Show Name + season: 1 + screen_size: 1080p + streaming_service: TFou + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: monkee + type: episode + +# Streaming service: DIY Network +? Show.Name.S01.720p.DIY.WEBRip.AAC2.0.H.264-BTN +: title: Show Name + season: 1 + screen_size: 720p + streaming_service: DIY Network + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTN + type: episode + +# Streaming service: USA Network +? Show.Name.S01E02.Exfil.1080p.USAN.WEBRip.AAC2.0.x264-AJP69 +: title: Show Name + season: 1 + episode: 2 + screen_size: 1080p + streaming_service: USA Network + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: AJP69 + type: episode + +# Streaming service: TV3 Ireland +? Show.Name.S01E08.576p.TV3.WEBRip.AAC2.0.x264-HARiKEN +: title: Show Name + season: 1 + episode: 8 + screen_size: 576p + streaming_service: TV3 Ireland + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: HARiKEN + type: episode + +# Streaming service: TV4 Sweeden +? Show.Name.S05.720p.TV4.WEBRip.AAC2.0.H.264-BTW +: title: Show Name + season: 5 + screen_size: 720p + streaming_service: TV4 Sweeden + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTW + type: episode + +# Streaming service: TLC +? Show.Name.S02.720p.TLC.WEBRip.AAC2.0.x264-BTW +: title: Show Name + season: 2 + screen_size: 720p + streaming_service: TLC + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTW + type: episode + +# Streaming service: Investigation Discovery +? Show.Name.S01E01.720p.ID.WEBRip.AAC2.0.x264-BTW +: title: Show Name + season: 1 + episode: 1 + screen_size: 720p + streaming_service: Investigation Discovery + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: BTW + type: episode + +# Streaming service: RTÉ One +? Show.Name.S10E01.576p.RTE.WEBRip.AAC2.0.H.264-RTN +: title: Show Name + season: 10 + episode: 1 + screen_size: 576p + streaming_service: RTÉ One + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: RTN + type: episode + +# Streaming service: AMC +? Show.Name.S01E01.1080p.AMC.WEBRip.H.264.AAC2.0-CasStudio +: title: Show Name + season: 1 + episode: 1 + screen_size: 1080p + streaming_service: AMC + source: Web + other: Rip + audio_codec: AAC + audio_channels: '2.0' + video_codec: H.264 + release_group: CasStudio + type: episode + +? Suits.S07E01.1080p.iT.WEB-DL.DD5.1.H.264-VLAD.mkv +? Suits.S07E01.1080p.iTunes.WEB-DL.DD5.1.H.264-VLAD.mkv +: title: Suits + season: 7 + episode: 1 + screen_size: 1080p + source: Web + streaming_service: iTunes + audio_codec: Dolby Digital + audio_channels: '5.1' + video_codec: H.264 + release_group: VLAD + container: mkv + type: episode + +? UpFront.S01.720p.AJAZ.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 720p + season: 1 + source: Web + streaming_service: Al Jazeera English + title: UpFront + type: episode + video_codec: H.264 + +? Smack.The.Pony.S01.4OD.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + season: 1 + source: Web + streaming_service: Channel 4 + title: Smack The Pony + type: episode + video_codec: H.264 + +? The.Toy.Box.S01E01.720p.AMBC.WEBRip.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: BTN + screen_size: 720p + season: 1 + source: Web + streaming_service: ABC + title: The Toy Box + type: episode + video_codec: H.264 + +? Gundam.Reconguista.in.G.S01.720p.ANLB.WEBRip.AAC2.0.x264-HorribleSubs +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: HorribleSubs + screen_size: 720p + season: 1 + source: Web + streaming_service: AnimeLab + title: Gundam Reconguista in G + type: episode + video_codec: H.264 + +? Animal.Nation.with.Anthony.Anderson.S01E01.1080p.ANPL.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: RTN + screen_size: 1080p + season: 1 + source: Web + streaming_service: Animal Planet + title: Animal Nation with Anthony Anderson + type: episode + video_codec: H.264 + +? Park.Bench.S01.1080p.AOL.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 1080p + season: 1 + source: Web + streaming_service: AOL + title: Park Bench + type: episode + video_codec: H.264 + +? Crime.Scene.Cleaner.S05.720p.ARD.WEBRip.AAC2.0.H.264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + screen_size: 720p + season: 5 + source: Web + streaming_service: ARD + title: Crime Scene Cleaner + type: episode + video_codec: H.264 + +? Decker.S03.720p.AS.WEB-DL.AAC2.0.H.264-RTN +: audio_channels: '2.0' + audio_codec: AAC + release_group: RTN + screen_size: 720p + season: 3 + source: Web + streaming_service: Adult Swim + title: Decker + type: episode + video_codec: H.264 + +? Southern.Charm.Savannah.S01E04.Hurricane.On.The.Horizon.1080p.BRAV.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + episode: 4 + episode_title: Hurricane On The Horizon + other: Rip + release_group: BTW + screen_size: 1080p + season: 1 + source: Web + streaming_service: BravoTV + title: Southern Charm Savannah + type: episode + video_codec: H.264 + +? Four.in.the.Morning.S01E01.Pig.RERip.720p.CBC.WEBRip.AAC2.0.H.264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + episode_title: Pig + other: + - Proper + - Rip + proper_count: 1 + release_group: RTN + screen_size: 720p + season: 1 + source: Web + streaming_service: CBC + title: Four in the Morning + type: episode + video_codec: H.264 + +? Rio.Olympics.2016.08.07.Mens.Football.Group.C.Germany.vs.South.Korea.720p.CBC.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + date: 2016-08-07 + episode_title: Mens Football Group C Germany vs South Korea + other: Rip + release_group: BTW + screen_size: 720p + source: Web + streaming_service: CBC + title: Rio Olympics + type: episode + video_codec: H.264 + +? Comedians.In.Cars.Getting.Coffee.S01.720p.CCGC.WEBRip.AAC2.0.x264-monkee +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: monkee + screen_size: 720p + season: 1 + source: Web + streaming_service: Comedians in Cars Getting Coffee + title: Comedians In Cars Getting Coffee + type: episode + video_codec: H.264 + +? Life.on.Top.S02.720p.CMAX.WEBRip.AAC2.0.x264-CMAX +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: CMAX + screen_size: 720p + season: 2 + source: Web + streaming_service: Cinemax + title: Life on Top + type: episode + video_codec: H.264 + +? Sun.Records.S01.720p.CMT.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 720p + season: 1 + source: Web + streaming_service: Country Music Television + title: Sun Records + type: episode + video_codec: H.264 + +? Infinity.Train.S01E00.Pilot.REPACK.720p.CN.WEBRip.AAC2.0.H.264-monkee +: audio_channels: '2.0' + audio_codec: AAC + episode: 0 + episode_details: Pilot + episode_title: Pilot + language: zh + other: + - Proper + - Rip + proper_count: 1 + release_group: monkee + screen_size: 720p + season: 1 + source: Web + streaming_service: Cartoon Network + title: Infinity Train + type: episode + video_codec: H.264 + +? Jay.Lenos.Garage.2015.S03E02.1080p.CNBC.WEB-DL.x264-TOPKEK +: episode: 2 + release_group: TOPKEK + screen_size: 1080p + season: 3 + source: Web + streaming_service: CNBC + title: Jay Lenos Garage + type: episode + video_codec: H.264 + year: 2015 + +? US.Presidential.Debates.2015.10.28.Third.Republican.Debate.720p.CNBC.WEBRip.AAC2.0.H.264-monkee +: audio_channels: '2.0' + audio_codec: AAC + country: US + date: 2015-10-28 + episode_title: Third Republican Debate + other: Rip + release_group: monkee + screen_size: 720p + source: Web + streaming_service: CNBC + title: Presidential Debates + type: episode + video_codec: H.264 + +? What.The.Fuck.France.S01E01.Le.doublage.CNLP.WEBRip.AAC2.0.x264-TURTLE +: audio_channels: '2.0' + audio_codec: AAC + country: FR + episode: 1 + episode_title: Le doublage + other: Rip + release_group: TURTLE + season: 1 + source: Web + streaming_service: Canal+ + title: What The Fuck + type: episode + video_codec: H.264 + +? SuperMansion.S02.720p.CRKL.WEBRip.AAC2.0.x264-VLAD +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: VLAD + screen_size: 720p + season: 2 + source: Web + streaming_service: Crackle + title: SuperMansion + type: episode + video_codec: H.264 + +? Chosen.S02.1080p.CRKL.WEBRip.AAC2.0.x264-AJP69 +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: AJP69 + screen_size: 1080p + season: 2 + source: Web + streaming_service: Crackle + title: Chosen + type: episode + video_codec: H.264 + +? Chosen.S03.1080p.CRKL.WEBRip.AAC2.0.x264-AJP69 +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: AJP69 + screen_size: 1080p + season: 3 + source: Web + streaming_service: Crackle + title: Chosen + type: episode + video_codec: H.264 + +? Snatch.S01.1080p.CRKL.WEBRip.AAC2.0.x264-DEFLATE +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: DEFLATE + screen_size: 1080p + season: 1 + source: Web + streaming_service: Crackle + title: Snatch + type: episode + video_codec: H.264 + +? White.House.Correspondents.Dinner.2015.Complete.CSPN.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: + - Complete + - Rip + release_group: BTW + source: Web + streaming_service: CSpan + title: White House Correspondents Dinner + type: movie + video_codec: H.264 + year: 2015 + +? The.Amazing.Race.Canada.S03.720p.CTV.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + country: CA + other: Rip + release_group: BTW + screen_size: 720p + season: 3 + source: Web + streaming_service: CTV + title: The Amazing Race + type: episode + video_codec: H.264 + +? Miniverse.S01E01.Explore.the.Solar.System.2160p.CUR.WEB-DL.DDP2.0.x264-monkee +: audio_channels: '2.0' + audio_codec: Dolby Digital Plus + episode: 1 + episode_title: Explore the Solar System + release_group: monkee + screen_size: 2160p + season: 1 + source: Web + streaming_service: CuriosityStream + title: Miniverse + type: episode + video_codec: H.264 + +? Vixen.S02.720p.CWS.WEBRip.AAC2.0.x264-BMF +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BMF + screen_size: 720p + season: 2 + source: Web + streaming_service: CWSeed + title: Vixen + type: episode + video_codec: H.264 + +? Abidin.Dino.DDY.WEBRip.AAC2.0.H.264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + source: Web + streaming_service: Digiturk Diledigin Yerde + title: Abidin Dino + type: movie + video_codec: H.264 + +? Fast.N.Loud.S08.1080p.DISC.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: RTN + screen_size: 1080p + season: 8 + source: Web + streaming_service: Discovery + title: Fast N Loud + type: episode + video_codec: H.264 + +? Bake.Off.Italia.S04.1080p.DPLY.WEBRip.AAC2.0.x264-Threshold +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: Threshold + screen_size: 1080p + season: 4 + source: Web + streaming_service: DPlay + title: Bake Off Italia + type: episode + video_codec: H.264 + +? Long.Riders.S01.DSKI.WEBRip.AAC2.0.x264-HorribleSubs +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: HorribleSubs + season: 1 + source: Web + streaming_service: Daisuki + title: Long Riders + type: episode + video_codec: H.264 + +? Milo.Murphys.Law.S01.720p.DSNY.WEB-DL.AAC2.0.x264-TVSmash +: audio_channels: '2.0' + audio_codec: AAC + release_group: TVSmash + screen_size: 720p + season: 1 + source: Web + streaming_service: Disney + title: Milo Murphys Law + type: episode + video_codec: H.264 + +? 30.for.30.S03E15.Doc.and.Darryl.720p.ESPN.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + episode: 15 + episode_title: Doc and Darryl + other: Rip + release_group: BTW + screen_size: 720p + season: 3 + source: Web + streaming_service: ESPN + title: 30 for 30 + type: episode + video_codec: H.264 + +? Boundless.S03.720p.ESQ.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: RTN + screen_size: 720p + season: 3 + source: Web + streaming_service: Esquire + title: Boundless + type: episode + video_codec: H.264 + +? Periodismo.Para.Todos.S2016E01.720p.ETTV.WEBRip.AAC2.0.H.264-braggart74 +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: braggart74 + screen_size: 720p + season: 2016 + source: Web + streaming_service: El Trece + title: Periodismo Para Todos + type: episode + video_codec: H.264 + year: 2016 + +? Just.Jillian.S01E01.1080p.ETV.WEBRip.AAC2.0.x264-GoApe +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: GoApe + screen_size: 1080p + season: 1 + source: Web + streaming_service: E! + title: Just Jillian + type: episode + video_codec: H.264 + +? New.Money.S01.1080p.ETV.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 1080p + season: 1 + source: Web + streaming_service: E! + title: New Money + type: episode + video_codec: H.264 + +? Gaming.Show.In.My.Parents.Garage.S02E01.The.Power.Up1000.FAM.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + episode_title: The Power Up1000 + other: Rip + release_group: RTN + season: 2 + source: Web + streaming_service: Family + title: Gaming Show In My Parents Garage + type: episode + video_codec: H.264 + +? Little.People.2016.S01E03.Proud.to.Be.You.and.Me.720p.FJR.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 3 + episode_title: Proud to Be You and Me + other: Rip + release_group: RTN + screen_size: 720p + season: 1 + source: Web + streaming_service: Family Jr + title: Little People + type: episode + video_codec: H.264 + year: 2016 + +? The.Pioneer.Woman.S00E08.Summer.Summer.Summer.720p.FOOD.WEB-DL.AAC2.0.x264-AJP69 +: audio_channels: '2.0' + audio_codec: AAC + episode: 8 + episode_title: Summer Summer Summer + release_group: AJP69 + screen_size: 720p + season: 0 + source: Web + streaming_service: Food Network + title: The Pioneer Woman + type: episode + video_codec: H.264 + +? Prata.da.Casa.S01E01.720p.FOX.WEBRip.AAC2.0.H.264-BARRY +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: BARRY + screen_size: 720p + season: 1 + source: Web + streaming_service: Fox + title: Prata da Casa + type: episode + video_codec: H.264 + +? Grandfathered.S01.720p.FOX.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 720p + season: 1 + source: Web + streaming_service: Fox + title: Grandfathered + type: episode + video_codec: H.264 + +? Truth.and.Iliza.S01E01.FREE.WEBRip.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: BTN + season: 1 + source: Web + streaming_service: Freeform + title: Truth and Iliza + type: episode + video_codec: H.264 + +? Seven.Year.Switch.S01.720p.FYI.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 720p + season: 1 + source: Web + streaming_service: FYI Network + title: Seven Year Switch + type: episode + video_codec: H.264 + +? NHL.2015.10.09.Leafs.vs.Red.Wings.Condensed.Game.720p.Away.Feed.GC.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + date: 2015-10-09 + episode_title: Leafs vs Red Wings Condensed Game + other: Rip + release_group: BTW + screen_size: 720p + source: Web + streaming_service: NHL GameCenter + title: NHL + type: episode + video_codec: H.264 + +? NHL.2016.01.26.Maple.Leafs.vs.Panthers.720p.Home.Feed.GC.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + date: 2016-01-26 + episode_title: Maple Leafs vs Panthers + other: Rip + release_group: BTW + screen_size: 720p + source: Web + streaming_service: NHL GameCenter + title: NHL + type: episode + video_codec: H.264 + +? Big.Brother.Canada.S05.GLBL.WEBRip.AAC2.0.H.264-RTN +: audio_channels: '2.0' + audio_codec: AAC + country: CA + other: Rip + release_group: RTN + season: 5 + source: Web + streaming_service: Global + title: Big Brother + type: episode + video_codec: H.264 + +? Pornolandia.S01.720p.GLOB.WEBRip.AAC2.0.x264-GeneX +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: GeneX + screen_size: 720p + season: 1 + source: Web + streaming_service: GloboSat Play + title: Pornolandia + type: episode + video_codec: H.264 + +? Transando.com.Laerte.S01.720p.GLOB.WEBRip.AAC2.0.x264-GeneX +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: GeneX + screen_size: 720p + season: 1 + source: Web + streaming_service: GloboSat Play + title: Transando com Laerte + type: episode + video_codec: H.264 + +? Flip.or.Flop.S01.720p.HGTV.WEBRip.AAC2.0.H.264-AJP69 +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: AJP69 + screen_size: 720p + season: 1 + source: Web + streaming_service: HGTV + title: Flip or Flop + type: episode + video_codec: H.264 + +? Kitten.Bowl.2014.720p.HLMK.WEBRip.AAC2.0.x264-monkee +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: monkee + screen_size: 720p + source: Web + streaming_service: Hallmark + title: Kitten Bowl + type: movie + video_codec: H.264 + year: 2014 + +? Still.Star-Crossed.S01E05.720p.HULU.WEB-DL.AAC2.0.H.264-VLAD +: audio_channels: '2.0' + audio_codec: AAC + episode: 5 + release_group: VLAD + screen_size: 720p + season: 1 + source: Web + streaming_service: Hulu + title: Still Star-Crossed + type: episode + video_codec: H.264 + +? EastEnders.2017.07.17.720p.iP.WEB-DL.AAC2.0.H.264-BTN +: audio_channels: '2.0' + audio_codec: AAC + date: 2017-07-17 + release_group: BTN + screen_size: 720p + source: Web + streaming_service: BBC iPlayer + title: EastEnders + type: episode + video_codec: H.264 + +? Handmade.in.Japan.S01E01.720p.iP.WEBRip.AAC2.0.H.264-SUP +: audio_channels: '2.0' + audio_codec: AAC + country: JP + episode: 1 + other: Rip + release_group: SUP + screen_size: 720p + season: 1 + source: Web + streaming_service: BBC iPlayer + title: Handmade in + type: episode + video_codec: H.264 + +? The.Chillenden.Murders.S01.720p.iP.WEBRip.AAC2.0.H.264-HAX +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: HAX + screen_size: 720p + season: 1 + source: Web + streaming_service: BBC iPlayer + title: The Chillenden Murders + type: episode + video_codec: H.264 + +? The.Street.S01.ITV.WEB-DL.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + release_group: RTN + season: 1 + source: Web + streaming_service: ITV + title: The Street + type: episode + video_codec: H.264 + +? Hope.for.Wildlife.S04.1080p.KNOW.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 1080p + season: 4 + source: Web + streaming_service: Knowledge Network + title: Hope for Wildlife + type: episode + video_codec: H.264 + +? Kim.of.Queens.S02.720p.LIFE.WEBRip.AAC2.0.H.264-RTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: RTN + screen_size: 720p + season: 2 + source: Web + streaming_service: Lifetime + title: Kim of Queens + type: episode + video_codec: H.264 + +? The.Rachel.Maddow.Show.2017.02.22.720p.MNBC.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + date: 2017-02-22 + other: Rip + release_group: BTW + screen_size: 720p + source: Web + streaming_service: MSNBC + title: The Rachel Maddow Show + type: episode + video_codec: H.264 + +? Ignition.S06E12.720p.MTOD.WEB-DL.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 12 + release_group: RTN + screen_size: 720p + season: 6 + source: Web + streaming_service: Motor Trend OnDemand + title: Ignition + type: episode + video_codec: H.264 + +? Teen.Mom.UK.S01E01.Life.as.a.Teen.Mum.1080p.MTV.WEB-DL.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + country: GB + episode: 1 + episode_title: Life as a Teen Mum + release_group: BTW + screen_size: 1080p + season: 1 + source: Web + streaming_service: MTV + title: Teen Mom + type: episode + video_codec: H.264 + +? Undrafted.S01.720p.NFLN.WEBRip.AAC2.0.H.264-TTYL +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: TTYL + screen_size: 720p + season: 1 + source: Web + streaming_service: NFL Now + title: Undrafted + type: episode + video_codec: H.264 + +? NFL.2016.08.25.PreSeason.Cowboys.vs.Seahawks.720p.NFL.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + date: 2016-08-25 + episode_title: PreSeason Cowboys vs Seahawks + other: Rip + release_group: BTW + screen_size: 720p + source: Web + streaming_service: NFL + title: NFL + type: episode + video_codec: H.264 + +? Bunsen.is.a.Beast.S01E23.Guinea.Some.Lovin.1080p.NICK.WEBRip.AAC2.0.x264-TVSmash +: audio_channels: '2.0' + audio_codec: AAC + country: GN + episode: 23 + episode_title: Some Lovin + other: Rip + release_group: TVSmash + screen_size: 1080p + season: 1 + source: Web + streaming_service: Nickelodeon + title: Bunsen is a Beast + type: episode + video_codec: H.264 + +? Valkyrie.S01.720p.NRK.WEBRip.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + screen_size: 720p + season: 1 + source: Web + streaming_service: Norsk Rikskringkasting + title: Valkyrie + type: episode + video_codec: H.264 + +? Food.Forward.S01.720p.PBS.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: RTN + screen_size: 720p + season: 1 + source: Web + streaming_service: PBS + title: Food Forward + type: episode + video_codec: H.264 + +? SciGirls.S01E01.Turtle.Mania.720p.PBSK.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + episode_title: Turtle Mania + other: Rip + release_group: RTN + screen_size: 720p + season: 1 + source: Web + streaming_service: PBS Kids + title: SciGirls + type: episode + video_codec: H.264 + +? Powers.2015.S01.1080p.PSN.WEBRip.DD5.1.x264-NTb +: audio_channels: '5.1' + audio_codec: Dolby Digital + other: Rip + release_group: NTb + screen_size: 1080p + season: 1 + source: Web + streaming_service: Playstation Network + title: Powers + type: episode + video_codec: H.264 + year: 2015 + +? Escape.The.Night.S02E02.The.Masquerade.Part.II.1080p.RED.WEBRip.AAC5.1.VP9-BTW +: audio_channels: '5.1' + audio_codec: AAC + episode: 2 + episode_title: The Masquerade + other: Rip + part: 2 + release_group: VP9-BTW + screen_size: 1080p + season: 2 + source: Web + streaming_service: YouTube Red + title: Escape The Night + type: episode + +? Escape.The.Night.S02E02.The.Masquerade.Part.II.2160p.RED.WEBRip.AAC5.1.VP9-BTW +: audio_channels: '5.1' + audio_codec: AAC + episode: 2 + episode_title: The Masquerade + other: Rip + part: 2 + release_group: VP9-BTW + screen_size: 2160p + season: 2 + source: Web + streaming_service: YouTube Red + title: Escape The Night + type: episode + +? Escape.The.Night.S02E02.The.Masquerade.Part.II.720p.RED.WEBRip.AAC5.1.VP9-BTW +: audio_channels: '5.1' + audio_codec: AAC + episode: 2 + episode_title: The Masquerade + other: Rip + part: 2 + release_group: VP9-BTW + screen_size: 720p + season: 2 + source: Web + streaming_service: YouTube Red + title: Escape The Night + type: episode + +? The.Family.Law.S02E01.720p.SBS.WEB-DL.AAC2.0.H.264-BTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + release_group: BTN + screen_size: 720p + season: 2 + source: Web + streaming_service: SBS (AU) + title: The Family Law + type: episode + video_codec: H.264 + +? Theres.No.Joy.In.Beachville.The.True.Story.of.Baseballs.Origin.720p.SNET.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 720p + source: Web + streaming_service: Sportsnet + title: Theres No Joy In Beachville The True Story of Baseballs Origin + type: movie + video_codec: H.264 + +? One.Night.Only.Alec.Baldwin.720p.SPIK.WEB-DL.AAC2.0.x264-NOGRP +: audio_channels: '2.0' + audio_codec: AAC + release_group: NOGRP + screen_size: 720p + source: Web + streaming_service: Spike + title: One Night Only Alec Baldwin + type: movie + video_codec: H.264 + +? Ink.Master.S08.720p.SPIK.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 720p + season: 8 + source: Web + streaming_service: Spike + title: Ink Master + type: episode + video_codec: H.264 + +? Jungle.Bunch.S01E01.Deep.Chasm.1080p.SPRT.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + episode_title: Deep Chasm + other: Rip + release_group: RTN + screen_size: 1080p + season: 1 + source: Web + streaming_service: Sprout + title: Jungle Bunch + type: episode + video_codec: H.264 + +? Ash.vs.Evil.Dead.S01.720p.STZ.WEBRip.AAC2.0.x264-NTb +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: NTb + screen_size: 720p + season: 1 + source: Web + streaming_service: Starz + title: Ash vs Evil Dead + type: episode + video_codec: H.264 + +? WWE.Swerved.S01.720p.WWEN.WEBRip.AAC2.0.H.264-PPKORE +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: PPKORE + screen_size: 720p + season: 1 + source: Web + streaming_service: WWE Network + title: WWE Swerved + type: episode + video_codec: H.264 + +? Face.Off.S11.1080p.SYFY.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + screen_size: 1080p + season: 11 + source: Web + streaming_service: Syfy + title: Face Off + type: episode + video_codec: H.264 + +? Conan.2016.09.22.Jeff.Garlin.720p.TBS.WEBRip.AAC2.0.H.264-NOGRP +: audio_channels: '2.0' + audio_codec: AAC + date: 2016-09-22 + episode_title: Jeff Garlin + other: Rip + release_group: NOGRP + screen_size: 720p + source: Web + streaming_service: TBS + title: Conan + type: episode + video_codec: H.264 + +? Swans.Crossing.S01.TUBI.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: RTN + season: 1 + source: Web + streaming_service: TubiTV + title: Swans Crossing + type: episode + video_codec: H.264 + +? The.Joy.of.Techs.S01.UKTV.WEB-DL.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + release_group: RTN + season: 1 + source: Web + streaming_service: UKTV + title: The Joy of Techs + type: episode + video_codec: H.264 + +? Rock.Icons.S01.720p.VH1.WEB-DL.AAC2.0.H.264-RTN +: audio_channels: '2.0' + audio_codec: AAC + release_group: RTN + screen_size: 720p + season: 1 + source: Web + streaming_service: VH1 + title: Rock Icons + type: episode + video_codec: H.264 + +? Desus.and.Mero.S01E130.2017.07.18.1080p.VICE.WEB-DL.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + date: 2017-07-18 + episode: 130 + release_group: RTN + screen_size: 1080p + season: 1 + source: Web + streaming_service: Viceland + title: Desus and Mero + type: episode + video_codec: H.264 + +? Graveyard.Carz.S07.1080p.VLCT.WEBRip.AAC2.0.x264-RTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: RTN + screen_size: 1080p + season: 7 + source: Web + streaming_service: Velocity + title: Graveyard Carz + type: episode + video_codec: H.264 + +? Other.Space.S01E01.1080p.YHOO.WEBRip.AAC2.0.x264-BTW +: audio_channels: '2.0' + audio_codec: AAC + episode: 1 + other: Rip + release_group: BTW + screen_size: 1080p + season: 1 + source: Web + streaming_service: Yahoo + title: Other Space + type: episode + video_codec: H.264 + +? Americas.Test.Kitchen.S17.720p.ATK.WEB-DL.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + release_group: BTN + screen_size: 720p + season: 17 + source: Web + streaming_service: America's Test Kitchen + title: Americas Test Kitchen + type: episode + video_codec: H.264 + +? Bushwhacked.Bugs.S01.AUBC.WEBRip.AAC2.0.H.264-DAWN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: DAWN + season: 1 + source: Web + streaming_service: ABC Australia + title: Bushwhacked Bugs + type: episode + video_codec: H.264 + +? VICE.S05E12.1080p.HBO.WEB-DL.AAC2.0.H.264-monkee +? VICE.S05E12.1080p.HBO-Go.WEB-DL.AAC2.0.H.264-monkee +? VICE.S05E12.1080p.HBOGo.WEB-DL.AAC2.0.H.264-monkee +: audio_channels: '2.0' + audio_codec: AAC + episode: 12 + release_group: monkee + screen_size: 1080p + season: 5 + source: Web + streaming_service: HBO Go + title: VICE + type: episode + video_codec: H.264 + +? Dix.Pour.Cent.S02.PLUZ.WEBRip.AAC2.0.H.264-TURTLE +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: TURTLE + season: 2 + source: Web + streaming_service: Pluzz + title: Dix Pour Cent + type: episode + video_codec: H.264 + +? Ulveson.och.Herngren.S01.720p.SVT.WEBRip.AAC2.0.H.264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + screen_size: 720p + season: 1 + source: Web + streaming_service: Sveriges Television + title: Ulveson och Herngren + type: episode + video_codec: H.264 + +? Bravest.Warriors.S03.1080p.VRV.WEBRip.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + screen_size: 1080p + season: 3 + source: Web + streaming_service: VRV + title: Bravest Warriors + type: episode + video_codec: H.264 + +? The.Late.Night.Big.Breakfast.S02.WME.WEBRip.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + season: 2 + source: Web + streaming_service: WatchMe + title: The Late Night Big Breakfast + type: episode + video_codec: H.264 + +? Hockey.Wives.S02.WNET.WEBRip.AAC2.0.H.264-BTW +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTW + season: 2 + source: Web + streaming_service: W Network + title: Hockey Wives + type: episode + video_codec: H.264 + +? Sin.City.Saints.S01.1080p.YHOO.WEBRip.AAC2.0.x264-NTb +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: NTb + screen_size: 1080p + season: 1 + source: Web + streaming_service: Yahoo + title: Sin City Saints + type: episode + video_codec: H.264 + +? 555.S01.1080p.VMEO.WEBRip.AAC2.0.x264-BTN +: audio_channels: '2.0' + audio_codec: AAC + other: Rip + release_group: BTN + screen_size: 1080p + season: 1 + source: Web + streaming_service: Vimeo + title: '555' + type: episode + video_codec: H.264 + +# All this below shouldn't match any streaming services +? London.2012.Olympics.CTV.Preview.Show.HDTV.x264-2HD +: alternative_title: Olympics CTV Preview Show + release_group: 2HD + source: HDTV + title: London + type: movie + video_codec: H.264 + year: 2012 + +? UFC.on.FOX.24.1080p.HDTV.x264-VERUM +: episode: 24 + release_group: VERUM + screen_size: 1080p + source: HDTV + title: UFC on FOX + type: episode + video_codec: H.264 + +? ESPN.E.60.2016.10.04.HDTV.x264-LoTV +: date: 2016-10-04 + episode: 60 + release_group: LoTV + source: HDTV + title: ESPN E + type: episode + video_codec: H.264 + +? GTTV.E3.All.Access.Live.Day.1.Xbox.Showcase.Preshow.HDTV.x264-SYS +: episode: 3 + episode_title: All Access Live Day 1 Xbox Showcase Preshow + release_group: SYS + source: HDTV + title: GTTV + type: episode + video_codec: H.264 diff --git a/ext/guessit/test/test_api.py b/ext/guessit/test/test_api.py index ca33df044a..9abb84d9fd 100644 --- a/ext/guessit/test/test_api.py +++ b/ext/guessit/test/test_api.py @@ -27,6 +27,14 @@ def test_forced_binary(): assert ret and 'title' in ret and isinstance(ret['title'], six.binary_type) +@pytest.mark.skipif('sys.version_info < (3, 4)', reason="Path is not available") +def test_pathlike_object(): + from pathlib import Path + path = Path('Fear.and.Loathing.in.Las.Vegas.FRENCH.ENGLISH.720p.HDDVD.DTS.x264-ESiR.mkv') + ret = guessit(path) + assert ret and 'title' in ret + + def test_unicode_japanese(): ret = guessit('[阿维达].Avida.2006.FRENCH.DVDRiP.XViD-PROD.avi') assert ret and 'title' in ret diff --git a/ext/guessit/test/test_api_unicode_literals.py b/ext/guessit/test/test_api_unicode_literals.py index 3347a7d892..826f7cd163 100644 --- a/ext/guessit/test/test_api_unicode_literals.py +++ b/ext/guessit/test/test_api_unicode_literals.py @@ -53,6 +53,14 @@ def test_forced_binary_japanese_options(): """ +def test_ensure_standard_string_class(): + class CustomStr(str): + pass + + ret = guessit(CustomStr('1080p'), options={'advanced': True}) + assert ret and 'screen_size' in ret and not isinstance(ret['screen_size'].input_string, CustomStr) + + def test_properties(): props = properties() assert 'video_codec' in props.keys() diff --git a/ext/guessit/test/test_yml.py b/ext/guessit/test/test_yml.py index 31aed67361..c866093921 100644 --- a/ext/guessit/test/test_yml.py +++ b/ext/guessit/test/test_yml.py @@ -136,7 +136,7 @@ class TestYml(object): Use $ marker to check inputs that should not match results. """ - options_re = re.compile(r'^([ \+-]+)(.*)') + options_re = re.compile(r'^([ +-]+)(.*)') files, ids = files_and_ids(filename_predicate) @@ -149,7 +149,7 @@ def set_default(expected, default): @pytest.mark.parametrize('filename', files, ids=ids) def test(self, filename, caplog): - caplog.setLevel(logging.INFO) + caplog.set_level(logging.INFO) with open(os.path.join(__location__, filename), 'r', encoding='utf-8') as infile: data = yaml.load(infile, OrderedDictYAMLLoader) entries = Results() @@ -274,10 +274,10 @@ def check_expected(self, result, expected, entry): if negates_key: entry.valid.append((expected_key, expected_value)) else: - entry.different.append((expected_key, expected_value, result[expected_key])) + entry.different.append((expected_key, expected_value, result[result_key])) else: if negates_key: - entry.different.append((expected_key, expected_value, result[expected_key])) + entry.different.append((expected_key, expected_value, result[result_key])) else: entry.valid.append((expected_key, expected_value)) elif not negates_key: diff --git a/ext/guessit/test/various.yml b/ext/guessit/test/various.yml index 15964457e1..c95b8e6b36 100644 --- a/ext/guessit/test/various.yml +++ b/ext/guessit/test/various.yml @@ -3,9 +3,9 @@ title: Fear and Loathing in Las Vegas year: 1998 screen_size: 720p - format: HD-DVD + source: HD-DVD audio_codec: DTS - video_codec: h264 + video_codec: H.264 release_group: ESiR ? Series/Duckman/Duckman - 101 (01) - 20021107 - I, Duckman.avi @@ -36,8 +36,9 @@ episode_format: Minisode episode: 1 episode_title: Good Cop Bad Cop - format: WEBRip - video_codec: XviD + source: Web + other: Rip + video_codec: Xvid ? Series/Kaamelott/Kaamelott - Livre V - Ep 23 - Le Forfait.avi : type: episode @@ -50,10 +51,10 @@ title: The Doors year: 1991 date: 2008-03-09 - format: BluRay + source: Blu-ray screen_size: 720p - audio_codec: AC3 - video_codec: h264 + audio_codec: Dolby Digital + video_codec: H.264 release_group: HiS@SiLUHD language: english website: sharethefiles.com @@ -63,14 +64,15 @@ title: MASH year: 1970 video_codec: DivX - format: DVD + source: DVD + other: [Dual Audio, Rip] ? the.mentalist.501.hdtv-lol.mp4 : type: episode title: the mentalist season: 5 episode: 1 - format: HDTV + source: HDTV release_group: lol ? the.simpsons.2401.hdtv-lol.mp4 @@ -78,7 +80,7 @@ title: the simpsons season: 24 episode: 1 - format: HDTV + source: HDTV release_group: lol ? Homeland.S02E01.HDTV.x264-EVOLVE.mp4 @@ -86,8 +88,8 @@ title: Homeland season: 2 episode: 1 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: EVOLVE ? /media/Band_of_Brothers-e01-Currahee.mkv @@ -115,7 +117,7 @@ title: new girl season: 1 episode: 17 - format: HDTV + source: HDTV release_group: lol ? The.Office.(US).1x03.Health.Care.HDTV.XviD-LOL.avi @@ -125,8 +127,8 @@ season: 1 episode: 3 episode_title: Health Care - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: LOL ? The_Insider-(1999)-x02-60_Minutes_Interview-1996.mp4 @@ -154,18 +156,18 @@ season: 56 episode: 6 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 ? White.House.Down.2013.1080p.BluRay.DTS-HD.MA.5.1.x264-PublicHD.mkv : type: movie title: White House Down year: 2013 screen_size: 1080p - format: BluRay - audio_codec: DTS - audio_profile: HDMA - video_codec: h264 + source: Blu-ray + audio_codec: DTS-HD + audio_profile: Master Audio + video_codec: H.264 release_group: PublicHD audio_channels: "5.1" @@ -174,10 +176,10 @@ title: White House Down year: 2013 screen_size: 1080p - format: BluRay - audio_codec: DTS - audio_profile: HDMA - video_codec: h264 + source: Blu-ray + audio_codec: DTS-HD + audio_profile: Master Audio + video_codec: H.264 release_group: PublicHD audio_channels: "5.1" @@ -188,10 +190,10 @@ season: 1 episode: 1 screen_size: 720p - format: WEB-DL + source: Web audio_channels: "5.1" - video_codec: h264 - audio_codec: AC3 + video_codec: H.264 + audio_codec: Dolby Digital release_group: NTb ? Despicable.Me.2.2013.1080p.BluRay.x264-VeDeTT.nfo @@ -199,37 +201,39 @@ title: Despicable Me 2 year: 2013 screen_size: 1080p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 release_group: VeDeTT ? Le Cinquieme Commando 1971 SUBFORCED FRENCH DVDRiP XViD AC3 Bandix.mkv : type: movie - audio_codec: AC3 - format: DVD + audio_codec: Dolby Digital + source: DVD + other: Rip release_group: Bandix subtitle_language: French title: Le Cinquieme Commando - video_codec: XviD + video_codec: Xvid year: 1971 ? Le Seigneur des Anneaux - La Communauté de l'Anneau - Version Longue - BDRip.mkv : type: movie - format: BluRay title: Le Seigneur des Anneaux + source: Blu-ray + other: Rip ? La petite bande (Michel Deville - 1983) VF PAL MP4 x264 AAC.mkv : type: movie audio_codec: AAC language: French title: La petite bande - video_codec: h264 + video_codec: H.264 year: 1983 other: PAL ? Retour de Flammes (Gregor Schnitzler 2003) FULL DVD.iso : type: movie - format: DVD + source: DVD title: Retour de Flammes type: movie year: 2003 @@ -250,16 +254,16 @@ : type: movie year: 2014 title: A Common Title - edition: Special Edition + edition: Special ? Downton.Abbey.2013.Christmas.Special.HDTV.x264-FoV.mp4 : type: episode year: 2013 title: Downton Abbey episode_title: Christmas Special - video_codec: h264 + video_codec: H.264 release_group: FoV - format: HDTV + source: HDTV episode_details: Special ? Doctor_Who_2013_Christmas_Special.The_Time_of_The_Doctor.HD @@ -280,10 +284,10 @@ ? Robot Chicken S06-Born Again Virgin Christmas Special HDTV x264.avi : type: episode title: Robot Chicken - format: HDTV + source: HDTV season: 6 episode_title: Born Again Virgin Christmas Special - video_codec: h264 + video_codec: H.264 episode_details: Special ? Wicked.Tuna.S03E00.Head.To.Tail.Special.HDTV.x264-YesTV @@ -293,14 +297,14 @@ release_group: YesTV season: 3 episode: 0 - video_codec: h264 - format: HDTV + video_codec: H.264 + source: HDTV episode_details: Special ? The.Voice.UK.S03E12.HDTV.x264-C4TV : episode: 12 - video_codec: h264 - format: HDTV + video_codec: H.264 + source: HDTV title: The Voice release_group: C4TV season: 3 @@ -317,21 +321,21 @@ ? FlexGet.S01E02.TheName.HDTV.xvid : episode: 2 - format: HDTV + source: HDTV season: 1 title: FlexGet episode_title: TheName type: episode - video_codec: XviD + video_codec: Xvid ? FlexGet.S01E02.TheName.HDTV.xvid : episode: 2 - format: HDTV + source: HDTV season: 1 title: FlexGet episode_title: TheName type: episode - video_codec: XviD + video_codec: Xvid ? some.series.S03E14.Title.Here.720p : episode: 14 @@ -362,7 +366,7 @@ ? Something.Season.2.1of4.Ep.Title.HDTV.torrent : episode_count: 4 episode: 1 - format: HDTV + source: HDTV season: 2 title: Something episode_title: Title @@ -372,7 +376,7 @@ ? Show-A (US) - Episode Title S02E09 hdtv : country: US episode: 9 - format: HDTV + source: HDTV season: 2 title: Show-A type: episode @@ -402,23 +406,25 @@ type: movie ? Movies/El Bosque Animado (1987)/El.Bosque.Animado.[Jose.Luis.Cuerda.1987].[Xvid-Dvdrip-720 * 432].avi -: format: DVD +: source: DVD + other: Rip screen_size: 720x432 title: El Bosque Animado - video_codec: XviD + video_codec: Xvid year: 1987 type: movie ? Movies/El Bosque Animado (1987)/El.Bosque.Animado.[Jose.Luis.Cuerda.1987].[Xvid-Dvdrip-720x432].avi -: format: DVD +: source: DVD + other: Rip screen_size: 720x432 title: El Bosque Animado - video_codec: XviD + video_codec: Xvid year: 1987 type: movie ? 2009.shoot.fruit.chan.multi.dvd9.pal -: format: DVD +: source: DVD language: mul other: PAL title: shoot fruit chan @@ -426,7 +432,7 @@ year: 2009 ? 2009.shoot.fruit.chan.multi.dvd5.pal -: format: DVD +: source: DVD language: mul other: PAL title: shoot fruit chan @@ -435,25 +441,25 @@ ? The.Flash.2014.S01E01.PREAIR.WEBRip.XviD-EVO.avi : episode: 1 - format: WEBRip - other: Preair + source: Web + other: [Preair, Rip] release_group: EVO season: 1 title: The Flash type: episode - video_codec: XviD + video_codec: Xvid year: 2014 ? Ice.Lake.Rebels.S01E06.Ice.Lake.Games.720p.HDTV.x264-DHD : episode: 6 - format: HDTV + source: HDTV release_group: DHD screen_size: 720p season: 1 title: Ice Lake Rebels episode_title: Ice Lake Games type: episode - video_codec: h264 + video_codec: H.264 ? The League - S06E10 - Epi Sexy.mkv : episode: 10 @@ -463,23 +469,23 @@ type: episode ? Stay (2005) [1080p]/Stay.2005.1080p.BluRay.x264.YIFY.mp4 -: format: BluRay +: source: Blu-ray release_group: YIFY screen_size: 1080p title: Stay type: movie - video_codec: h264 + video_codec: H.264 year: 2005 ? /media/live/A/Anger.Management.S02E82.720p.HDTV.X264-DIMENSION.mkv -: format: HDTV +: source: HDTV release_group: DIMENSION screen_size: 720p title: Anger Management type: episode season: 2 episode: 82 - video_codec: h264 + video_codec: H.264 ? "[Figmentos] Monster 34 - At the End of Darkness [781219F1].mkv" : type: episode @@ -492,7 +498,7 @@ ? Game.of.Thrones.S05E07.720p.HDTV-KILLERS.mkv : type: episode episode: 7 - format: HDTV + source: HDTV release_group: KILLERS screen_size: 720p season: 5 @@ -501,7 +507,7 @@ ? Game.of.Thrones.S05E07.HDTV.720p-KILLERS.mkv : type: episode episode: 7 - format: HDTV + source: HDTV release_group: KILLERS screen_size: 720p season: 5 @@ -519,8 +525,8 @@ title: Star Trek Into Darkness year: 2013 screen_size: 720p - format: WEB-DL - video_codec: h264 + source: Web + video_codec: H.264 release_group: publichd ? /var/medias/series/The Originals/Season 02/The.Originals.S02E15.720p.HDTV.X264-DIMENSION.mkv @@ -529,8 +535,8 @@ season: 2 episode: 15 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: DIMENSION ? Test.S01E01E07-FooBar-Group.avi @@ -539,202 +545,211 @@ - 1 - 7 episode_title: FooBar-Group # Make sure it doesn't conflict with uuid - mimetype: video/x-msvideo season: 1 title: Test type: episode ? TEST.S01E02.2160p.NF.WEBRip.x264.DD5.1-ABC : audio_channels: '5.1' - audio_codec: AC3 + audio_codec: Dolby Digital episode: 2 - format: WEBRip + source: Web + other: Rip release_group: ABC - screen_size: 4K + screen_size: 2160p season: 1 streaming_service: Netflix title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.2015.12.30.720p.WEBRip.h264-ABC : date: 2015-12-30 - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 720p title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S01E10.24.1080p.NF.WEBRip.AAC2.0.x264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 10 episode_title: '24' - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 1080p season: 1 streaming_service: Netflix title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S01E10.24.1080p.NF.WEBRip.AAC2.0.x264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 10 episode_title: '24' - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 1080p season: 1 streaming_service: Netflix title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S01E10.24.1080p.NF.WEBRip.AAC.2.0.x264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 10 episode_title: '24' - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 1080p season: 1 streaming_service: Netflix title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S05E02.720p.iP.WEBRip.AAC2.0.H264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 2 - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 720p season: 5 title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S03E07.720p.WEBRip.AAC2.0.x264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 7 - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 720p season: 3 title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S15E15.24.1080p.FREE.WEBRip.AAC2.0.x264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 15 episode_title: '24' - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 1080p season: 15 title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.S11E11.24.720p.ETV.WEBRip.AAC2.0.x264-ABC : audio_channels: '2.0' audio_codec: AAC episode: 11 episode_title: '24' - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 720p season: 11 title: TEST type: episode - video_codec: h264 + video_codec: H.264 ? TEST.2015.1080p.HC.WEBRip.x264.AAC2.0-ABC : audio_channels: '2.0' audio_codec: AAC - format: WEBRip + source: Web + other: Rip release_group: ABC screen_size: 1080p title: TEST type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? TEST.2015.1080p.3D.BluRay.Half-SBS.x264.DTS-HD.MA.7.1-ABC : audio_channels: '7.1' - audio_codec: DTS - audio_profile: HDMA - format: BluRay + audio_codec: DTS-HD + audio_profile: Master Audio + source: Blu-ray other: 3D release_group: ABC screen_size: 1080p title: TEST type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? TEST.2015.1080p.3D.BluRay.Half-OU.x264.DTS-HD.MA.7.1-ABC : audio_channels: '7.1' - audio_codec: DTS - audio_profile: HDMA - format: BluRay + audio_codec: DTS-HD + audio_profile: Master Audio + source: Blu-ray other: 3D release_group: ABC screen_size: 1080p title: TEST type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? TEST.2015.1080p.3D.BluRay.Half-OU.x264.DTS-HD.MA.TrueHD.7.1.Atmos-ABC : audio_channels: '7.1' audio_codec: - - DTS - - TrueHD - - DolbyAtmos - audio_profile: HDMA - format: BluRay + - DTS-HD + - Dolby TrueHD + - Dolby Atmos + audio_profile: Master Audio + source: Blu-ray other: 3D release_group: ABC screen_size: 1080p title: TEST type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? TEST.2015.1080p.3D.BluRay.Half-SBS.x264.DTS-HD.MA.TrueHD.7.1.Atmos-ABC : audio_channels: '7.1' audio_codec: - - DTS - - TrueHD - - DolbyAtmos - audio_profile: HDMA - format: BluRay + - DTS-HD + - Dolby TrueHD + - Dolby Atmos + audio_profile: Master Audio + source: Blu-ray other: 3D release_group: ABC screen_size: 1080p title: TEST type: movie - video_codec: h264 + video_codec: H.264 year: 2015 ? TEST.2015.1080p.BluRay.REMUX.AVC.DTS-HD.MA.TrueHD.7.1.Atmos-ABC : audio_channels: '7.1' audio_codec: - - DTS - - TrueHD - - DolbyAtmos - audio_profile: HDMA - format: BluRay + - DTS-HD + - Dolby TrueHD + - Dolby Atmos + audio_profile: Master Audio + source: Blu-ray other: Remux release_group: ABC screen_size: 1080p @@ -743,23 +758,24 @@ year: 2015 ? Gangs of New York 2002 REMASTERED 1080p BluRay x264-AVCHD -: format: BluRay +: source: Blu-ray edition: Remastered screen_size: 1080p title: Gangs of New York type: movie - video_codec: h264 + video_codec: H.264 year: 2002 ? Peep.Show.S06E02.DVDrip.x264-faks86.mkv : container: mkv episode: 2 - format: DVD + source: DVD + other: Rip release_group: faks86 season: 6 title: Peep Show type: episode - video_codec: h264 + video_codec: H.264 # Episode title is indeed 'October 8, 2014' # https://thetvdb.com/?tab=episode&seriesid=82483&seasonid=569935&id=4997362&lid=7 @@ -774,28 +790,155 @@ ? Red.Rock.S02E59.WEB-DLx264-JIVE : episode: 59 season: 2 - format: WEB-DL + source: Web release_group: JIVE title: Red Rock type: episode - video_codec: h264 + video_codec: H.264 ? Pawn.Stars.S12E31.Deals.On.Wheels.PDTVx264-JIVE : episode: 31 episode_title: Deals On Wheels season: 12 - format: DVB + source: Digital TV release_group: JIVE title: Pawn Stars type: episode - video_codec: h264 + video_codec: H.264 ? Duck.Dynasty.S09E09.Van.He-llsing.HDTVx264-JIVE : episode: 9 episode_title: Van He-llsing season: 9 - format: HDTV + source: HDTV release_group: JIVE title: Duck Dynasty type: episode - video_codec: h264 \ No newline at end of file + video_codec: H.264 + +? ATKExotics.16.01.24.Ava.Alba.Watersports.XXX.1080p.MP4-KTR +: title: ATKExotics + episode_title: Ava Alba Watersports + other: XXX + screen_size: 1080p + container: mp4 + release_group: KTR + type: episode + +? PutaLocura.15.12.22.Spanish.Luzzy.XXX.720p.MP4-oRo +: title: PutaLocura + episode_title: Spanish Luzzy + other: XXX + screen_size: 720p + container: mp4 + release_group: oRo + type: episode + +? French Maid Services - Lola At Your Service WEB-DL SPLIT SCENES MP4-RARBG +: title: French Maid Services + alternative_title: Lola At Your Service + source: Web + container: mp4 + release_group: RARBG + type: movie + +? French Maid Services - Lola At Your Service - Marc Dorcel WEB-DL SPLIT SCENES MP4-RARBG +: title: French Maid Services + alternative_title: [Lola At Your Service, Marc Dorcel] + source: Web + container: mp4 + release_group: RARBG + type: movie + +? PlayboyPlus.com_16.01.23.Eleni.Corfiate.Playboy.Romania.XXX.iMAGESET-OHRLY +: episode_title: Eleni Corfiate Playboy Romania + other: XXX + type: episode + +? TeenPornoPass - Anna - Beautiful Ass Deep Penetrated 720p mp4 +: title: TeenPornoPass + alternative_title: + - Anna + - Beautiful Ass Deep Penetrated + screen_size: 720p + container: mp4 + type: movie + +? SexInJeans.Gina.Gerson.Super.Nasty.Asshole.Pounding.With.Gina.In.Jeans.A.Devil.In.Denim.The.Finest.Ass.Fuck.Frolicking.mp4 +: title: SexInJeans Gina Gerson Super Nasty Asshole Pounding With Gina In Jeans A Devil In Denim The Finest Ass Fuck Frolicking + container: mp4 + type: movie + +? TNA Impact Wrestling HDTV 2017-06-22 720p H264 AVCHD-SC-SDH +: title: TNA Impact Wrestling + source: HDTV + date: 2017-06-22 + screen_size: 720p + video_codec: H.264 + release_group: SDH + type: episode + +? Katy Perry - Pepsi & Billboard Summer Beats Concert Series 2012 1080i HDTV 20 Mbps DD2.0 MPEG2-TrollHD.ts +: title: Katy Perry + alternative_title: Pepsi & Billboard Summer Beats Concert + year: 2012 + screen_size: 1080i + source: HDTV + video_bit_rate: 20Mbps + audio_codec: Dolby Digital + audio_channels: '2.0' + video_codec: MPEG-2 + release_group: TrollHD + container: ts + +? Justin Timberlake - MTV Video Music Awards 2013 1080i 32 Mbps DTS-HD 5.1.ts +: title: Justin Timberlake + alternative_title: MTV Video Music Awards + year: 2013 + screen_size: 1080i + video_bit_rate: 32Mbps + audio_codec: DTS-HD + audio_channels: '5.1' + container: ts + type: movie + +? Chuck Berry The Very Best Of Chuck Berry(2010)[320 Kbps] +: title: Chuck Berry The Very Best Of Chuck Berry + year: 2010 + audio_bit_rate: 320Kbps + type: movie + +? Title Name [480p][1.5Mbps][.mp4] +: title: Title Name + screen_size: 480p + video_bit_rate: 1.5Mbps + container: mp4 + type: movie + +? This.is.Us +: options: --no-embedded-config + title: This is Us + type: movie + +? This.is.Us +: options: --excludes country + title: This is Us + type: movie + +? MotoGP.2016x03.USA.Race.BTSportHD.1080p25 +: title: MotoGP + season: 2016 + year: 2016 + episode: 3 + screen_size: 1080p + frame_rate: 25fps + type: episode + +? BBC.Earth.South.Pacific.2010.D2.1080p.24p.BD25.DTS-HD +: title: BBC Earth South Pacific + year: 2010 + screen_size: 1080p + frame_rate: 24fps + source: Blu-ray + audio_codec: DTS-HD + type: movie diff --git a/ext/guessit/yamlutils.py b/ext/guessit/yamlutils.py index 2824575daf..01ac77781a 100644 --- a/ext/guessit/yamlutils.py +++ b/ext/guessit/yamlutils.py @@ -3,6 +3,7 @@ """ Options """ + try: from collections import OrderedDict except ImportError: # pragma: no-cover @@ -11,6 +12,8 @@ import yaml +from .rules.common.quantity import BitRate, FrameRate, Size + class OrderedDictYAMLLoader(yaml.Loader): """ @@ -61,11 +64,18 @@ class CustomDumper(yaml.SafeDumper): def default_representer(dumper, data): """Default representer""" return dumper.represent_str(str(data)) + + CustomDumper.add_representer(babelfish.Language, default_representer) CustomDumper.add_representer(babelfish.Country, default_representer) +CustomDumper.add_representer(BitRate, default_representer) +CustomDumper.add_representer(FrameRate, default_representer) +CustomDumper.add_representer(Size, default_representer) def ordered_dict_representer(dumper, data): """OrderedDict representer""" - return dumper.represent_dict(data) + return dumper.represent_mapping('tag:yaml.org,2002:map', data.items()) + + CustomDumper.add_representer(OrderedDict, ordered_dict_representer) diff --git a/ext/readme.md b/ext/readme.md index ee1ebf3a05..30cd779b3f 100644 --- a/ext/readme.md +++ b/ext/readme.md @@ -26,7 +26,7 @@ :: | `futures` | [3.2.0](https://pypi.org/project/futures/3.2.0/) | **`medusa`**, `subliminal`, `tornado` | Module: `concurrent.futures`
Markers: `python_version >= '2.6' and python_version < '3'` :: | `PyGithub` | [1.40](https://pypi.org/project/PyGithub/1.40/) | **`medusa`** | Module: `github`
**Removed tests** :: | `gntp` | [1.0.3](https://pypi.org/project/gntp/1.0.3/) | **`medusa`** | - -:: | `guessit` | [2.1.4](https://pypi.org/project/guessit/2.1.4/) | **`medusa`**, `subliminal` | - +:: | `guessit` | [3.0.0](https://pypi.org/project/guessit/3.0.0/) | **`medusa`**, `subliminal` | - :: | `html5lib` | [1.0.1](https://pypi.org/project/html5lib/1.0.1/) | **`medusa`** (via `beautifulsoup4`) | - :: | `httplib2` | [0.11.3](https://pypi.org/project/httplib2/0.11.3/) | `oauth2` | - :: | `idna` | [2.7](https://pypi.org/project/idna/2.7/) | `requests` | - @@ -55,7 +55,7 @@ :: | singledispatch.py
`singledispatch_helpers.py` | [3.4.0.3](https://pypi.org/project/singledispatch/3.4.0.3/) | `tornado` | Markers: `python_version < '3.4'` :: | six.py | [1.11.0](https://pypi.org/project/six/1.11.0/) | **`medusa`**, `tvdbapiv2`, `configobj`, `python-dateutil`, `guessit`, `html5lib`, `imdbpie`, `Js2Py`, `knowit`, `rebulk`, `subliminal`, `validators` | - :: | `stevedore` | [1.29.0](https://pypi.org/project/stevedore/1.29.0/) | `subliminal` | - -:: | `subliminal` | [879c0c8](https://github.com/Diaoul/subliminal/tree/879c0c8d18618e32ad466bb63bd939edb268bc60) | **`medusa`** | - +:: | `subliminal` | pymedusa/[78687f4](https://github.com/pymedusa/subliminal/tree/78687f45d23b1bc47fae0a5493be0198dc1fd5b5) | **`medusa`** | - :: | `tornado` | [5.1](https://pypi.org/project/tornado/5.1/) | **`medusa`**, `tornroutes` | - :: | `tornroutes` | [0.5.1](https://pypi.org/project/tornroutes/0.5.1/) | **`medusa`** | - :: | `tzlocal` | [1.5.1](https://pypi.org/project/tzlocal/1.5.1/) | `Js2Py` | - diff --git a/ext/subliminal/providers/addic7ed.py b/ext/subliminal/providers/addic7ed.py index 1832cf92c8..63ed3b25c6 100644 --- a/ext/subliminal/providers/addic7ed.py +++ b/ext/subliminal/providers/addic7ed.py @@ -72,9 +72,9 @@ def get_matches(self, video): # resolution if video.resolution and self.version and video.resolution in self.version.lower(): matches.add('resolution') - # format - if video.format and self.version and video.format.lower() in self.version.lower(): - matches.add('format') + # source + if video.source and self.version and video.source.lower() in self.version.lower(): + matches.add('source') # other properties matches |= guess_matches(video, guessit(self.version), partial=True) diff --git a/ext/subliminal/providers/legendastv.py b/ext/subliminal/providers/legendastv.py index 925bb9ead7..3468c65c1c 100644 --- a/ext/subliminal/providers/legendastv.py +++ b/ext/subliminal/providers/legendastv.py @@ -170,7 +170,7 @@ def __init__(self, username=None, password=None): # Provider needs UNRAR installed. If not available raise ConfigurationError try: - rarfile.custom_check(rarfile.UNRAR_TOOL) + rarfile.custom_check([rarfile.UNRAR_TOOL], True) except rarfile.RarExecError: raise ConfigurationError('UNRAR tool not available') diff --git a/ext/subliminal/refiners/metadata.py b/ext/subliminal/refiners/metadata.py index a840874232..9e7a0a80a2 100644 --- a/ext/subliminal/refiners/metadata.py +++ b/ext/subliminal/refiners/metadata.py @@ -45,13 +45,13 @@ def refine(video, embedded_subtitles=True, **kwargs): # video codec if video_track.codec_id == 'V_MPEG4/ISO/AVC': - video.video_codec = 'h264' + video.video_codec = 'H.264' logger.debug('Found video_codec %s', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/SP': video.video_codec = 'DivX' logger.debug('Found video_codec %s', video.video_codec) elif video_track.codec_id == 'V_MPEG4/ISO/ASP': - video.video_codec = 'XviD' + video.video_codec = 'Xvid' logger.debug('Found video_codec %s', video.video_codec) else: logger.warning('MKV has no video track') @@ -61,7 +61,7 @@ def refine(video, embedded_subtitles=True, **kwargs): audio_track = mkv.audio_tracks[0] # audio codec if audio_track.codec_id == 'A_AC3': - video.audio_codec = 'AC3' + video.audio_codec = 'Dolby Digital' logger.debug('Found audio_codec %s', video.audio_codec) elif audio_track.codec_id == 'A_DTS': video.audio_codec = 'DTS' diff --git a/ext/subliminal/score.py b/ext/subliminal/score.py index 61dd22c250..e084a1ed1e 100644 --- a/ext/subliminal/score.py +++ b/ext/subliminal/score.py @@ -17,7 +17,7 @@ * season * episode * release_group - * format + * source * audio_codec * resolution * hearing_impaired @@ -37,11 +37,11 @@ #: Scores for episodes episode_scores = {'hash': 359, 'series': 180, 'year': 90, 'season': 30, 'episode': 30, 'release_group': 15, - 'format': 7, 'audio_codec': 3, 'resolution': 2, 'video_codec': 2, 'hearing_impaired': 1} + 'source': 7, 'audio_codec': 3, 'resolution': 2, 'video_codec': 2, 'hearing_impaired': 1} #: Scores for movies movie_scores = {'hash': 119, 'title': 60, 'year': 30, 'release_group': 15, - 'format': 7, 'audio_codec': 3, 'resolution': 2, 'video_codec': 2, 'hearing_impaired': 1} + 'source': 7, 'audio_codec': 3, 'resolution': 2, 'video_codec': 2, 'hearing_impaired': 1} #: Equivalent release groups equivalent_release_groups = ({'LOL', 'DIMENSION'}, {'ASAP', 'IMMERSE', 'FLEET'}, {'AVS', 'SVA'}) @@ -152,30 +152,30 @@ def solve_episode_equations(): from sympy import Eq, solve, symbols hash, series, year, season, episode, release_group = symbols('hash series year season episode release_group') - format, audio_codec, resolution, video_codec = symbols('format audio_codec resolution video_codec') + source, audio_codec, resolution, video_codec = symbols('source audio_codec resolution video_codec') hearing_impaired = symbols('hearing_impaired') equations = [ # hash is best - Eq(hash, series + year + season + episode + release_group + format + audio_codec + resolution + video_codec), + Eq(hash, series + year + season + episode + release_group + source + audio_codec + resolution + video_codec), # series counts for the most part in the total score - Eq(series, year + season + episode + release_group + format + audio_codec + resolution + video_codec + 1), + Eq(series, year + season + episode + release_group + source + audio_codec + resolution + video_codec + 1), # year is the second most important part - Eq(year, season + episode + release_group + format + audio_codec + resolution + video_codec + 1), + Eq(year, season + episode + release_group + source + audio_codec + resolution + video_codec + 1), # season is important too - Eq(season, release_group + format + audio_codec + resolution + video_codec + 1), + Eq(season, release_group + source + audio_codec + resolution + video_codec + 1), # episode is equally important to season Eq(episode, season), # release group is the next most wanted match - Eq(release_group, format + audio_codec + resolution + video_codec + 1), + Eq(release_group, source + audio_codec + resolution + video_codec + 1), - # format counts as much as audio_codec, resolution and video_codec - Eq(format, audio_codec + resolution + video_codec), + # source counts as much as audio_codec, resolution and video_codec + Eq(source, audio_codec + resolution + video_codec), # audio_codec is more valuable than video_codec Eq(audio_codec, video_codec + 1), @@ -190,7 +190,7 @@ def solve_episode_equations(): Eq(hearing_impaired, 1), ] - return solve(equations, [hash, series, year, season, episode, release_group, format, audio_codec, resolution, + return solve(equations, [hash, series, year, season, episode, release_group, source, audio_codec, resolution, hearing_impaired, video_codec]) @@ -198,24 +198,24 @@ def solve_movie_equations(): from sympy import Eq, solve, symbols hash, title, year, release_group = symbols('hash title year release_group') - format, audio_codec, resolution, video_codec = symbols('format audio_codec resolution video_codec') + source, audio_codec, resolution, video_codec = symbols('source audio_codec resolution video_codec') hearing_impaired = symbols('hearing_impaired') equations = [ # hash is best - Eq(hash, title + year + release_group + format + audio_codec + resolution + video_codec), + Eq(hash, title + year + release_group + source + audio_codec + resolution + video_codec), # title counts for the most part in the total score - Eq(title, year + release_group + format + audio_codec + resolution + video_codec + 1), + Eq(title, year + release_group + source + audio_codec + resolution + video_codec + 1), # year is the second most important part - Eq(year, release_group + format + audio_codec + resolution + video_codec + 1), + Eq(year, release_group + source + audio_codec + resolution + video_codec + 1), # release group is the next most wanted match - Eq(release_group, format + audio_codec + resolution + video_codec + 1), + Eq(release_group, source + audio_codec + resolution + video_codec + 1), - # format counts as much as audio_codec, resolution and video_codec - Eq(format, audio_codec + resolution + video_codec), + # source counts as much as audio_codec, resolution and video_codec + Eq(source, audio_codec + resolution + video_codec), # audio_codec is more valuable than video_codec Eq(audio_codec, video_codec + 1), @@ -230,5 +230,5 @@ def solve_movie_equations(): Eq(hearing_impaired, 1), ] - return solve(equations, [hash, title, year, release_group, format, audio_codec, resolution, hearing_impaired, + return solve(equations, [hash, title, year, release_group, source, audio_codec, resolution, hearing_impaired, video_codec]) diff --git a/ext/subliminal/subtitle.py b/ext/subliminal/subtitle.py index 726b28e373..6578f4ca6f 100644 --- a/ext/subliminal/subtitle.py +++ b/ext/subliminal/subtitle.py @@ -237,9 +237,9 @@ def guess_matches(video, guess, partial=False): # resolution if video.resolution and 'screen_size' in guess and guess['screen_size'] == video.resolution: matches.add('resolution') - # format - if video.format and 'format' in guess and guess['format'].lower() == video.format.lower(): - matches.add('format') + # source + if video.source and 'source' in guess and guess['source'].lower() == video.source.lower(): + matches.add('source') # video_codec if video.video_codec and 'video_codec' in guess and guess['video_codec'] == video.video_codec: matches.add('video_codec') diff --git a/ext/subliminal/video.py b/ext/subliminal/video.py index a6efb80163..bedb99a20f 100644 --- a/ext/subliminal/video.py +++ b/ext/subliminal/video.py @@ -24,7 +24,7 @@ class Video(object): Represent a video, existing or not. :param str name: name or path of the video. - :param str format: format of the video (HDTV, WEB-DL, BluRay, ...). + :param str source: source of the video (HDTV, Web, Blu-ray, ...). :param str release_group: release group of the video. :param str resolution: resolution of the video stream (480p, 720p, 1080p or 1080i). :param str video_codec: codec of the video stream. @@ -35,13 +35,13 @@ class Video(object): :param set subtitle_languages: existing subtitle languages. """ - def __init__(self, name, format=None, release_group=None, resolution=None, video_codec=None, audio_codec=None, + def __init__(self, name, source=None, release_group=None, resolution=None, video_codec=None, audio_codec=None, imdb_id=None, hashes=None, size=None, subtitle_languages=None): #: Name or path of the video self.name = name - #: Format of the video (HDTV, WEB-DL, BluRay, ...) - self.format = format + #: Source of the video (HDTV, Web, Blu-ray, ...) + self.source = source #: Release group of the video self.release_group = release_group @@ -176,7 +176,7 @@ def fromguess(cls, name, guess): episode = min(episode_guess) if episode_guess and isinstance(episode_guess, list) else episode_guess return cls(name, guess['title'], guess.get('season', 1), episode, title=guess.get('episode_title'), - year=guess.get('year'), format=guess.get('format'), original_series='year' not in guess, + year=guess.get('year'), source=guess.get('source'), original_series='year' not in guess, release_group=guess.get('release_group'), resolution=guess.get('screen_size'), video_codec=guess.get('video_codec'), audio_codec=guess.get('audio_codec')) @@ -220,7 +220,7 @@ def fromguess(cls, name, guess): if 'title' not in guess: raise ValueError('Insufficient data to process the guess') - return cls(name, guess['title'], format=guess.get('format'), release_group=guess.get('release_group'), + return cls(name, guess['title'], source=guess.get('source'), release_group=guess.get('release_group'), resolution=guess.get('screen_size'), video_codec=guess.get('video_codec'), audio_codec=guess.get('audio_codec'), year=guess.get('year')) diff --git a/medusa/common.py b/medusa/common.py index dd3c6daf0f..acda84a78c 100644 --- a/medusa/common.py +++ b/medusa/common.py @@ -619,42 +619,45 @@ def wanted_quality(new_quality, allowed_qualities, preferred_qualities): """Check if new quality is wanted.""" return new_quality in allowed_qualities + preferred_qualities - # Map guessit screen sizes and formats to our Quality values + # Map guessit screen sizes and sources to our Quality values guessit_map = { '720p': { 'HDTV': HDTV, - 'WEB-DL': HDWEBDL, - 'WEBRip': HDWEBDL, - 'BluRay': HDBLURAY, + 'Web': HDWEBDL, + 'Blu-ray': HDBLURAY, }, '1080i': RAWHDTV, '1080p': { 'HDTV': FULLHDTV, - 'WEB-DL': FULLHDWEBDL, - 'WEBRip': FULLHDWEBDL, - 'BluRay': FULLHDBLURAY + 'Web': FULLHDWEBDL, + 'Blu-ray': FULLHDBLURAY }, - '4K': { + '2160p': { 'HDTV': UHD_4K_TV, - 'WEB-DL': UHD_4K_WEBDL, - 'WEBRip': UHD_4K_WEBDL, - 'BluRay': UHD_4K_BLURAY + 'Web': UHD_4K_WEBDL, + 'Blu-ray': UHD_4K_BLURAY + }, + '4320p': { + 'HDTV': UHD_8K_TV, + 'Web': UHD_8K_WEBDL, + 'Blu-ray': UHD_8K_BLURAY } } - # Consolidate the guessit-supported screen sizes of each format - to_guessit_format_list = [ - ANYHDTV | UHD_4K_TV, - ANYWEBDL | UHD_4K_WEBDL, - ANYBLURAY | UHD_4K_BLURAY - ] + # Consolidate the guessit-supported screen sizes of each source + to_guessit_source_map = { + ANYHDTV | UHD_4K_TV | UHD_8K_TV: 'HDTV', + ANYWEBDL | UHD_4K_WEBDL | UHD_8K_WEBDL: 'Web', + ANYBLURAY | UHD_4K_BLURAY | UHD_8K_BLURAY: 'Blu-ray' + } - # Consolidate the formats of each guessit-supported screen size + # Consolidate the sources of each guessit-supported screen size to_guessit_screen_size_map = { HDTV | HDWEBDL | HDBLURAY: '720p', RAWHDTV: '1080i', FULLHDTV | FULLHDWEBDL | FULLHDBLURAY: '1080p', - UHD_4K_TV | UHD_4K_WEBDL | UHD_4K_BLURAY: '4K', + UHD_4K_TV | UHD_4K_WEBDL | UHD_4K_BLURAY: '2160p', + UHD_8K_TV | UHD_8K_WEBDL | UHD_8K_BLURAY: '4320p', } @staticmethod @@ -668,74 +671,74 @@ def from_guessit(guess): :rtype: int """ screen_size = guess.get('screen_size') - fmt = guess.get('format') + source = guess.get('source') if not screen_size or isinstance(screen_size, list): return Quality.UNKNOWN - format_map = Quality.guessit_map.get(screen_size) - if not format_map: + source_map = Quality.guessit_map.get(screen_size) + if not source_map: return Quality.UNKNOWN - if isinstance(format_map, int): - return format_map + if isinstance(source_map, int): + return source_map - if not fmt or isinstance(fmt, list): + if not source or isinstance(source, list): return Quality.UNKNOWN - quality = format_map.get(fmt) + quality = source_map.get(source) return quality if quality is not None else Quality.UNKNOWN @staticmethod def to_guessit(quality): - """Return a guessit dict containing 'screen_size and format' from a Quality. + """ + Return a guessit dict containing 'screen_size and source' from a Quality. :param quality: a quality :type quality: int - :return: dict {'screen_size': , 'format': } + :return: dict {'screen_size': , 'source': } :rtype: dict (str, str) """ if quality not in Quality.qualityStrings: quality = Quality.UNKNOWN screen_size = Quality.to_guessit_screen_size(quality) - fmt = Quality.to_guessit_format(quality) + source = Quality.to_guessit_source(quality) result = dict() if screen_size: result['screen_size'] = screen_size - if fmt: - result['format'] = fmt + if source: + result['source'] = source return result @staticmethod - def to_guessit_format(quality): - """Return a guessit format from a Quality. + def to_guessit_source(quality): + """ + Return a guessit source from a Quality. :param quality: the quality :type quality: int - :return: guessit format + :return: guessit source :rtype: str """ - for quality_set in Quality.to_guessit_format_list: - if quality_set & quality: # If quality_set contains quality - # Remove all 4K (and above) formats as they are bigger than Quality.ANYBLURAY, - # and they are not part of an "ANY*" bit set - key = quality_set & (Quality.UHD_4K_TV - 1) - return Quality.combinedQualityStrings.get(key) + for quality_set, source in viewitems(Quality.to_guessit_source_map): + if quality_set & quality: + return source @staticmethod def to_guessit_screen_size(quality): - """Return a guessit screen_size from a Quality. + """ + Return a guessit screen_size from a Quality. :param quality: the quality :type quality: int :return: guessit screen_size :rtype: str """ - for key, value in viewitems(Quality.to_guessit_screen_size_map): - if quality & key: - return value + for quality_set, screen_size in viewitems(Quality.to_guessit_screen_size_map): + if quality_set & quality: + return screen_size HD720p = Quality.combine_qualities([Quality.HDTV, Quality.HDWEBDL, Quality.HDBLURAY], []) diff --git a/medusa/name_parser/parser.py b/medusa/name_parser/parser.py index ddc538d298..670f1e0ddb 100644 --- a/medusa/name_parser/parser.py +++ b/medusa/name_parser/parser.py @@ -5,7 +5,6 @@ import logging import time -from builtins import object from collections import OrderedDict import guessit @@ -504,6 +503,9 @@ def __str__(self): total_time=self.total_time)) return helpers.canonical_name(obj, fmt='{key}: {value}', separator=', ') + # Python 2 compatibility + __unicode__ = __str__ + def get_quality(self, guess, extend=False): """Return video quality from guess or name. diff --git a/medusa/name_parser/rules/__init__.py b/medusa/name_parser/rules/__init__.py index ea8b808450..f90536c04a 100644 --- a/medusa/name_parser/rules/__init__.py +++ b/medusa/name_parser/rules/__init__.py @@ -9,15 +9,16 @@ from medusa.name_parser.rules.properties import ( blacklist, container, - format_, other, - screen_size + screen_size, + source ) from medusa.name_parser.rules.rules import rules +default_api.configure({}) default_api.rebulk.rebulk(blacklist()) -default_api.rebulk.rebulk(format_()) +default_api.rebulk.rebulk(source()) default_api.rebulk.rebulk(screen_size()) default_api.rebulk.rebulk(other()) default_api.rebulk.rebulk(container()) diff --git a/medusa/name_parser/rules/properties.py b/medusa/name_parser/rules/properties.py index b304b87810..0d646dd56d 100644 --- a/medusa/name_parser/rules/properties.py +++ b/medusa/name_parser/rules/properties.py @@ -36,24 +36,24 @@ def blacklist(): return rebulk -def format_(): - """Format property. +def source(): + """Source property. :return: :rtype: Rebulk """ rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]) - rebulk.defaults(name='format', tags='video-codec-prefix') + rebulk.defaults(name='source', tags='video-codec-prefix') - # More accurate formats + # More accurate sources rebulk.regex('BD-?Rip', 'BD(?=-?Mux)', value='BDRip', - conflict_solver=lambda match, other: other if other.name == 'format' else '__default__') + conflict_solver=lambda match, other: other if other.name == 'source' else '__default__') rebulk.regex('BD(?!\d)', value='BDRip', validator=seps_surround, - conflict_solver=lambda match, other: other if other.name == 'format' else '__default__') + conflict_solver=lambda match, other: other if other.name == 'source' else '__default__') rebulk.regex('BR-?Rip', 'BR(?=-?Mux)', value='BRRip', - conflict_solver=lambda match, other: other if other.name == 'format' else '__default__') + conflict_solver=lambda match, other: other if other.name == 'source' else '__default__') rebulk.regex('DVD-?Rip', value='DVDRip', - conflict_solver=lambda match, other: other if other.name == 'format' else '__default__') + conflict_solver=lambda match, other: other if other.name == 'source' else '__default__') rebulk.regex('DVD\d', value='DVD') @@ -69,7 +69,8 @@ def screen_size(): rebulk = Rebulk().regex_defaults(flags=re.IGNORECASE) rebulk.defaults(name='screen_size', validator=seps_surround) - rebulk.regex(r'(?:\d{3,}(?:x|\*))?4320(?:p?x?)', value='4320p') + # Discarded: + rebulk.regex(r'(?:\d{3,}(?:x|\*))?4320(?:p?x?)', value='4320p', private=True) return rebulk @@ -102,7 +103,7 @@ def container(): rebulk.defaults(name='container', tags=['extension'], conflict_solver=lambda match, other: other - if other.name in ['format', 'video_codec'] or + if other.name in ['source', 'video_codec'] or other.name == 'container' and 'extension' not in other.tags else '__default__') @@ -114,8 +115,8 @@ def container(): validator=seps_surround, formatter=lambda s: s.upper(), conflict_solver=lambda match, other: match - if other.name in ['format', - 'video_codec'] or other.name == 'container' and 'extension' in other.tags + if other.name in ['source', 'video_codec'] or + other.name == 'container' and 'extension' in other.tags else '__default__') rebulk.string(*nzb, tags=['nzb']) diff --git a/medusa/name_parser/rules/rules.py b/medusa/name_parser/rules/rules.py index e36557d125..2b9ff60f38 100644 --- a/medusa/name_parser/rules/rules.py +++ b/medusa/name_parser/rules/rules.py @@ -31,21 +31,20 @@ import copy import logging import re -from builtins import range from guessit.rules.common.comparators import marker_sorted from guessit.rules.common.formatters import cleanup -from guessit.rules.properties import website -from guessit.rules.properties.release_group import clean_groupname from rebulk.processors import POST_PROCESS from rebulk.rebulk import Rebulk from rebulk.rules import AppendMatch, RemoveMatch, RenameMatch, Rule +from six import text_type +from six.moves import range log = logging.getLogger(__name__) -simple_separator = ('.', 'and', ',.', '.,', '.,.', ',') +simple_separator = ('.', 'and', ',.', '.,', '.,.', ',', '.&.', ' & ') range_separator = ('-', '~', '_-_', 'to', '.to.') @@ -83,7 +82,7 @@ class FixAnimeReleaseGroup(Rule): "season": 4, "episode": 62, "screen_size": "720p", - "video_profile": "10bit", + "color_depth": "10-bit", "release_group": "[SOMEPERSON].[Something]", "type": "episode" } @@ -95,7 +94,7 @@ class FixAnimeReleaseGroup(Rule): "season": 4, "episode": 62, "screen_size": "720p", - "video_profile": "10bit", + "color_depth": "10-bit", "release_group": "RealGroup", "type": "episode" } @@ -103,7 +102,6 @@ class FixAnimeReleaseGroup(Rule): priority = POST_PROCESS consequence = [RemoveMatch, AppendMatch] - website_rebulk = website.website() def when(self, matches, context): """Evaluate the rule. @@ -149,110 +147,47 @@ def when(self, matches, context): return to_remove, to_append -class FixSeasonRangeWithGap(Rule): - """Fix season range with gap. +class FixInvalidAbsoluteReleaseGroups(Rule): + """Fix invalid release groups due to absolute episode numbers range. - guessit -t episode "Show.Name.-.Season.1.3.4-.Mp4.1080p" + Some release names have season/episode defined twice (relative and absolute), and the ending + absolute episode becomes the release_group. This fix will remove the invalid release_group + and add the correct absolute episode ranges. - Without this fix: - For: Show.Name.-.Season.1.3.4-.Mp4.1080p - GuessIt found: { - "title": "Show Name", - "season": 1, - "episode": [ - 3, - 4 - ], - "container": "MP4", - "screen_size": "1080p", - "type": "episode" - } - - with this fix: - For: Show.Name.-.Season.1.3.4-.Mp4.1080p - GuessIt found: { - "title": "Show Name", - "season": [1, 3, 4] - "container": "MP4", - "screen_size": "1080p", - "type": "episode" - } - """ - - priority = POST_PROCESS - consequence = [AppendMatch, RemoveMatch] + e.g.: "Show.Name.s16e03-05.313-315" - def when(self, matches, context): - """Evaluate the rule. - - :param matches: - :type matches: rebulk.match.Matches - :param context: - :type context: dict - :return: - """ - to_remove = [] - to_append = [] - fileparts = matches.markers.named('path') - for filepart in marker_sorted(fileparts, matches): - season = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'season', index=0) - if not season: - continue - - episodes = matches.range(season.end, filepart.end, - predicate=lambda match: match.name == 'episode' and 'weak-episode' in match.tags) - if not episodes: - continue - - if len(episodes) != len(matches.holes(season.end, episodes[-1].start, predicate=lambda hole: hole.raw in simple_separator)): - continue - - for episode in episodes: - new_season = copy.copy(episode) - new_season.name = 'season' - to_append.append(new_season) - to_remove.append(episode) - - return to_append, to_remove - - -class FixInvalidTitleOrAlternativeTitle(Rule): - """Fix invalid title/alternative title due to absolute episode numbers range. - - Some release names have season/episode defined twice (relative and absolute), and one of them becomes an - alternative_title or a suffix in the title. This fix will remove the invalid alternative_title or the - invalid title's suffix. - - e.g.: "Show Name - 313-314 - s16e03-04" - - guessit -t episode "Show Name - 313-314 - s16e03-04" + guessit -t episode "Show.Name.s16e03-05.313-315" without this fix: - For: Show Name - 313-314 - s16e03-04 + For: Show.Name.s16e03-05.313-315 GuessIt found: { "title": "Show Name", - "alternative_title": "313-314", "season": 16, "episode": [ 3, - 4 + 4, + 5 ], + "absolute_episode": 313, + "release_group": "315", "type": "episode" } with this fix: - For: Show Name - 313-314 - s16e03-04 + For: Show.Name.s16e03-05.313-315 GuessIt found: { "title": "Show Name", "season": 16, - "absolute_episode": [ - 313, - 314 - ], "episode": [ 3, - 4 + 4, + 5 + ], + "absolute_episode": [ + 313, + 314, + 315 ], "type": "episode" } @@ -261,7 +196,6 @@ class FixInvalidTitleOrAlternativeTitle(Rule): priority = POST_PROCESS consequence = [RemoveMatch, AppendMatch] absolute_re = re.compile(r'([\W|_]*)(?P\d{2,4})(?:-(?P\d{3,4}))?\W*$') - properties = ('title', 'alternative_title', 'episode_title') def when(self, matches, context): """Evaluate the rule. @@ -274,50 +208,42 @@ def when(self, matches, context): """ fileparts = matches.markers.named('path') for filepart in marker_sorted(fileparts, matches): - # retrieve all problematic titles - problematic_titles = matches.range(filepart.start, filepart.end, - predicate=lambda match: match.name in self.properties) + # retrieve all problematic groups + problematic_groups = matches.range(filepart.start, filepart.end, + predicate=lambda match: match.name == 'release_group') to_remove = [] to_append = [] - for title in problematic_titles: - m = self.absolute_re.search(title.raw) + for group in problematic_groups: + filename = fileparts[-1].raw + m = self.absolute_re.search(filename) if not m: continue - # Remove the problematic title - to_remove.append(title) - - # Remove the title suffix - new_value = title.raw[0: m.start()] - if new_value: - # Add the correct title - new_title = copy.copy(title) - new_title.value = cleanup(new_value) - new_title.end = title.start + m.start() - to_append.append(new_title) + # Remove the problematic group + to_remove.append(group) # and add the absolute episode range g = m.groupdict() - if not g['absolute_episode_end'] and title.name != 'alternative_title': + if not g['absolute_episode_end']: continue absolute_episode_start = int(g['absolute_episode_start']) absolute_episode_end = int(g['absolute_episode_end'] or g['absolute_episode_start']) for i in range(absolute_episode_start, absolute_episode_end + 1): - episode = copy.copy(title) + episode = copy.copy(group) episode.name = 'absolute_episode' episode.value = i if i == absolute_episode_start: - episode.start = title.start + m.start('absolute_episode_start') - episode.end = title.start + m.end('absolute_episode_start') + episode.start = group.start + m.start('absolute_episode_start') + episode.end = group.start + m.end('absolute_episode_start') elif i < absolute_episode_end: - episode.start = title.start + m.end('absolute_episode_start') - episode.end = title.start + m.start('absolute_episode_end') + episode.start = group.start + m.end('absolute_episode_start') + episode.end = group.start + m.start('absolute_episode_end') else: - episode.start = title.start + m.start('absolute_episode_end') - episode.end = title.start + m.end('absolute_episode_end') + episode.start = group.start + m.start('absolute_episode_end') + episode.end = group.start + m.end('absolute_episode_end') to_append.append(episode) @@ -425,8 +351,8 @@ class CreateAliasWithCountryOrYear(Rule): "country": "UNITED STATES", "season": 3, "screen_size": "720p", - "format": "BluRay", - "video_codec": "h264", + "source": "Blu-ray", + "video_codec": "H.264", "release_group": "SuperGroup", "type": "episode" } @@ -439,8 +365,8 @@ class CreateAliasWithCountryOrYear(Rule): "country": "UNITED STATES", "season": 3, "screen_size": "720p", - "format": "BluRay", - "video_codec": "h264", + "source": "Blu-ray", + "video_codec": "H.264", "release_group": "SuperGroup", "type": "episode" } @@ -505,10 +431,10 @@ class FixTvChaosUkWorkaround(Rule): "title": "Show Name", "season": 1, "video_codec": [ - "XviD", - "h264" + "Xvid", + "H.264" ], - "format": "HDTV", + "source": "HDTV", "type": "episode" } @@ -517,8 +443,8 @@ class FixTvChaosUkWorkaround(Rule): GuessIt found: { "title": "Show Name", "season": 1, - "video_codec": "XviD", - "format": "HDTV", + "video_codec": "Xvid", + "source": "HDTV", "type": "episode" } """ @@ -539,21 +465,21 @@ def when(self, matches, context): fileparts = matches.markers.named('path') for filepart in marker_sorted(fileparts, matches): - m_x264 = matches.ending(filepart.end, predicate=lambda match: match.name == 'video_codec' and match.value == 'h264', index=0) + m_x264 = matches.ending(filepart.end, predicate=lambda match: match.name == 'video_codec' and match.value == 'H.264', index=0) if not m_x264: continue - m_hdtv = matches.previous(m_x264, predicate=lambda match: match.name == 'format' and match.value == 'HDTV', index=0) + m_hdtv = matches.previous(m_x264, predicate=lambda match: match.name == 'source' and match.value == 'HDTV', index=0) if not m_hdtv: continue video_codecs = matches.range(filepart.start, filepart.end, lambda match: match.name == 'video_codec') - formats = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'format') + sources = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'source') if len(video_codecs) > 1: to_remove.append(m_x264) - if len(formats) <= 1: + if len(sources) <= 1: m_hdtv.tags.append('tvchaosuk') - if len(formats) > 1: + if len(sources) > 1: to_remove.append(m_hdtv) if len(video_codecs) <= 1: m_x264.tags.append('tvchaosuk') @@ -872,8 +798,8 @@ class PartsAsEpisodeNumbers(Rule): "title": "Show Name", "part": 3, "screen_size": "720p", - "format": "HDTV", - "video_codec": "h264", + "source": "HDTV", + "video_codec": "H.264", "release_group": "Group", "type": "episode" } @@ -884,8 +810,8 @@ class PartsAsEpisodeNumbers(Rule): "title": "Show Name", "episode": 3, "screen_size": "720p", - "format": "HDTV", - "video_codec": "h264", + "source": "HDTV", + "video_codec": "H.264", "release_group": "Group", "type": "episode" } @@ -915,10 +841,174 @@ def when(self, matches, context): return to_rename +class RemoveInvalidEpisodeSeparator(Rule): + """Remove invalid episode title between absolute episode ranges. + + e.g.: [Zero-Raws].Show.Name.493-498.&.500-507.(CX.1280x720.VFR.x264.AAC) + + guessit -t episode "[Zero-Raws].Show.Name.493-498.&.500-507.(CX.1280x720.VFR.x264.AAC)" + + without the rule: + For: [Zero-Raws].Show.Name.493-498.&.500-507.(CX.1280x720.VFR.x264.AAC) + GuessIt found: { + "release_group": "Zero-Raws", + "title": "Show Name", + "episode": [ + 493, + ... + 507 + ], + "episode_title": "&", + "screen_size": "720p", + "aspect_ratio": 1.778, + "subtitle_language": "French", + "video_codec": "H.264", + "audio_codec": "AAC", + "type": "episode" + } + + without the rule: + For: [Zero-Raws].Show.Name.493-498.&.500-507.(CX.1280x720.VFR.x264.AAC) + GuessIt found: { + "release_group": "Zero-Raws", + "title": "Show Name", + "episode": [ + 493, + ... + 507 + ], + "screen_size": "720p", + "aspect_ratio": 1.778, + "subtitle_language": "French", + "video_codec": "H.264", + "audio_codec": "AAC", + "type": "episode" + } + """ + + priority = POST_PROCESS + consequence = RemoveMatch + + def when(self, matches, context): + """Evaluate the rule. + + :param matches: + :type matches: rebulk.match.Matches + :param context: + :type context: dict + :return: + """ + episode_title = matches.named('episode_title') + + if len(episode_title) == 1: + previous = matches.previous(episode_title[0], predicate=lambda match: match.name == 'absolute_episode') + next_match = matches.next(episode_title[0], predicate=lambda match: match.name == 'absolute_episode') + if previous and next_match and episode_title[0].raw in simple_separator: + to_remove = episode_title + return to_remove + + +class RemoveYearAsSeason(Rule): + """Remove invalid season from year. + + Related bug report: https://github.com/guessit-io/guessit/issues/561 + + e.g.: Show.Name.2016.Nice.Title.1080p.SESO.WEBRip.AAC2.0.x264-monkee + + guessit -t episode "Show.Name.2016.Nice.Title.1080p.SESO.WEBRip.AAC2.0.x264-monkee" + + without the rule: + For: Show.Name.2016.Nice.Title.1080p.SESO.WEBRip.AAC2.0.x264-monkee + GuessIt found: { + "title": "Show Name", + "season": 20, + "year": 2016, + "episode_title": "Nice Title", + "screen_size": "1080p", + "streaming_service": "SeeSo", + "source": "Web", + "other": "Rip", + "audio_codec": "AAC", + "audio_channels": "2.0", + "video_codec": "H.264", + "release_group": "monkee", + "type": "episode" + } + + with the rule: + For: Show.Name.2016.Nice.Title.1080p.SESO.WEBRip.AAC2.0.x264-monkee + GuessIt found: { + "title": "Show Name", + "year": 2016, + "episode_title": "Nice Title", + "screen_size": "1080p", + "streaming_service": "SeeSo", + "source": "Web", + "other": "Rip", + "audio_codec": "AAC", + "audio_channels": "2.0", + "video_codec": "H.264", + "release_group": "monkee", + "type": "episode" + } + """ + + priority = POST_PROCESS + consequence = RemoveMatch + + def when(self, matches, context): + """Evaluate the rule. + + :param matches: + :type matches: rebulk.match.Matches + :param context: + :type context: dict + :return: + """ + year = matches.named('year') + if not year: + return + + season = matches.named('season') + if season and season[-1].initiator.value.endswith(text_type(year[0].value)): + to_remove = season[-1] + return to_remove + + class FixMultipleReleaseGroups(Rule): """Fix multiple release groups. - TODO: Document + e.g.: Show.Name.S04E23.Parley.720p.HDTV.x264.DIMENSION.P00/SNLA0423.720p.HDTV.X264-DIMENSION + + guessit -t episode "Show.Name.S04E23.Parley.720p.HDTV.x264.DIMENSION.P00/SNLA0423.720p.HDTV.X264-DIMENSION" + + without the rule: + For: Show.Name.S04E23.Parley.720p.HDTV.x264.DIMENSION.P00/SNLA0423.720p.HDTV.X264-DIMENSION + GuessIt found: { + "title": "Show Name", + "season": 4, + "episode": 23, + "episode_title": "Parley", + "screen_size": "720p", + "source": "HDTV", + "video_codec": "H.264", + "release_group": "DIMENSION.P00", + "type": "episode" + } + + with the rule: + For: Show.Name.S04E23.Parley.720p.HDTV.x264.DIMENSION.P00/SNLA0423.720p.HDTV.X264-DIMENSION + GuessIt found: { + "title": "Show Name", + "season": 4, + "episode": 23, + "episode_title": "Parley", + "screen_size": "720p", + "source": "HDTV", + "video_codec": "H.264", + "release_group": "DIMENSION", + "type": "episode" + } """ priority = POST_PROCESS @@ -948,8 +1038,150 @@ def when(self, matches, context): return to_remove -class FixMultipleFormats(Rule): - """Fix multiple formats. +class FixParentFolderReplacingTitle(Rule): + """Fix folder name replacing title when it ends with digits. + + Related bug report: https://github.com/guessit-io/guessit/issues/565 + + e.g.: /Comedy 23/Funny.Show.S4E19.mkv + + guessit -t episode "/Comedy 23/Funny.Show.S4E19.mkv" + + without the rule: + For: /Comedy 23/Funny.Show.S4E19.mkv + GuessIt found: { + "title": "Comedy", + "episode_title": "Funny Show", + "season": 4, + "episode": 19, + "container": "mkv", + "mimetype": "video/x-matroska", + "type": "episode" + } + + with the rule: + For: /Comedy 23/Funny.Show.S4E19.mkv + GuessIt found: { + "title": "Funny Show", + "season": 4, + "episode": 19, + "container": "mkv", + "mimetype": "video/x-matroska", + "type": "episode" + } + """ + + priority = POST_PROCESS + consequence = [RemoveMatch, AppendMatch] + ends_with_digit = re.compile(r'(_|\W)\d+$') + + def when(self, matches, context): + """Evaluate the rule. + + :param matches: + :type matches: rebulk.match.Matches + :param context: + :type context: dict + :return: + """ + fileparts = matches.markers.named('path') + parts_len = len(fileparts) + if parts_len < 2: + return + + episode_title = matches.named('episode_title') + if episode_title: + second_part = fileparts[parts_len - 2].value + if self.ends_with_digit.search(second_part): + title = matches.named('title') + if not title or second_part.startswith(title[0].value): + episode_title[0].name = 'title' + to_append = episode_title + to_remove = title + + return to_remove, to_append + + +class FixTitleAsAudioProfile(Rule): + """Fix titles being parsed as audio profiles. + + Related bug report: https://github.com/guessit-io/guessit/issues/566 + + e.g.: shes.gotta.have.it.s01e08.720p.web.x264-strife.mkv + + guessit -t episode "shes.gotta.have.it.s01e08.720p.web.x264-strife.mkv" + + without the rule: + For: shes.gotta.have.it.s01e08.720p.web.x264-strife.mkv + GuessIt found: { + "title": "sh", + "audio_profile": "Extended Surround", + "season": 1, + "episode": 8, + "screen_size": "720p", + "source": "Web", + "video_codec": "H.264", + "release_group": "strife", + "container": "mkv", + "mimetype": "video/x-matroska", + "type": "episode" + } + + with the rule: + For: shes.gotta.have.it.s01e08.720p.web.x264-strife.mkv + GuessIt found: { + "title": "shes gotta have it", + "season": 1, + "episode": 8, + "screen_size": "720p", + "source": "Web", + "video_codec": "H.264", + "release_group": "strife", + "container": "mkv", + "mimetype": "video/x-matroska", + "type": "episode" + } + """ + + priority = POST_PROCESS + consequence = [RemoveMatch, AppendMatch] + non_word_chars = re.compile(r'(_+|\W+)') + + def when(self, matches, context): + """Evaluate the rule. + + :param matches: + :type matches: rebulk.match.Matches + :param context: + :type context: dict + :return: + """ + audio_profile = matches.named('audio_profile') + if not audio_profile: + return + + previous_title = matches.previous(audio_profile[0], + predicate=lambda match: match.name == 'title') + if previous_title: + next_match = matches.next(audio_profile[0]) + if next_match: + next_match_start = next_match[0].start - 1 + + fileparts = matches.markers.named('path') + filename_start = fileparts[-1].start + + title = copy.copy(previous_title) + new_title = matches.input_string[filename_start:next_match_start] + title[0].value = self.non_word_chars.sub(' ', new_title).strip() + + to_append = title + to_remove = audio_profile + + return to_remove, to_append + + +class FixMultipleSources(Rule): + """Fix multiple sources. Related to guessit bug: https://github.com/guessit-io/guessit/issues/327 @@ -965,14 +1197,14 @@ class FixMultipleFormats(Rule): "episode": 1, "episode_title": "eps2 0 unm4sk", "part": 1, - "format": [ + "source": [ "Telecine", - "WEB-DL" + "Web" ], "screen_size": "1080p", - "audio_codec": "DolbyDigital", + "audio_codec": "Dolby Digital", "audio_channels": "5.1", - "video_codec": "h264", + "video_codec": "H.264", "release_group": "GROUP", "type": "episode" } @@ -986,11 +1218,11 @@ class FixMultipleFormats(Rule): "episode": 1, "episode_title": "eps2 0 unm4sk", "part": 1, - "format": "WEB-DL", + "source": "Web", "screen_size": "1080p", - "audio_codec": "DolbyDigital", + "audio_codec": "Dolby Digital", "audio_channels": "5.1", - "video_codec": "h264", + "video_codec": "H.264", "release_group": "GROUP", "type": "episode" } @@ -1010,22 +1242,22 @@ def when(self, matches, context): """ fileparts = matches.markers.named('path') for filepart in marker_sorted(fileparts, matches): - formats = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'format') - if len(formats) < 2: + sources = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'source') + if len(sources) < 2: continue - for candidate in reversed(formats): + for candidate in reversed(sources): previous = matches.previous(candidate, predicate=lambda match: match.name == 'screen_size') next_range = matches.range(candidate.end, filepart.end, lambda match: match.name in ('audio_codec', 'video_codec', 'release_group')) - # If we have at least 3 matches near by, then discard the other formats + # If we have at least 3 matches near by, then discard the other sources if len(previous) + len(next_range) > 1: - invalid_formats = {f.value for f in formats[0:-1]} - to_remove = matches.named('format', predicate=lambda m: m.value in invalid_formats) + invalid_sources = {f.value for f in sources[0:-1]} + to_remove = matches.named('source', predicate=lambda m: m.value in invalid_sources) return to_remove if matches.conflicting(candidate): - to_remove = matches.named('format', predicate=lambda m: m.value in candidate.value) + to_remove = matches.named('source', predicate=lambda m: m.value in candidate.value) return to_remove @@ -1042,8 +1274,8 @@ class CreateProperTags(Rule): "episode": 8, "other": "Proper", "proper_count": 2, - "format": "HDTV", - "video_codec": "h264", + "source": "HDTV", + "video_codec": "H.264", "release_group": "GROUP", "type": "episode" } @@ -1057,8 +1289,8 @@ class CreateProperTags(Rule): "other": "Proper", "proper_count": 2, "proper_tag": ["REPACK", "PROPER"] - "format": "HDTV", - "video_codec": "h264", + "source": "HDTV", + "video_codec": "H.264", "release_group": "GROUP", "type": "episode" } @@ -1086,35 +1318,10 @@ def when(self, matches, context): return to_append -class ScreenSizeStandardizer(Rule): - """Standardize the screen size. - - Fix 360i, 480i, 576i, etc which are detected as progressive. - Rename 4K to 2160p - """ - - priority = POST_PROCESS - - def when(self, matches, context): - """Evaluate the rule. - - :param matches: - :type matches: rebulk.match.Matches - :param context: - :type context: dict - :return: - """ - for screen_size in matches.named('screen_size'): - if screen_size.raw.lower().endswith('i'): - screen_size.value = screen_size.value.replace('p', 'i') - elif screen_size.value == '4K': - screen_size.value = '2160p' - - class AudioCodecStandardizer(Rule): - """DolbyDigital is AC3. + """Dolby Digital is AC3. - Rename DolbyDigital to AC3 + Rename Dolby Digital to AC3 """ priority = POST_PROCESS @@ -1131,7 +1338,7 @@ def when(self, matches, context): """ to_remove = [] to_append = [] - for audio_codec in matches.named('audio_codec', predicate=lambda m: m.value in ('DolbyDigital', )): + for audio_codec in matches.named('audio_codec', predicate=lambda m: m.value in ('Dolby Digital', )): new_codec = copy.copy(audio_codec) new_codec.value = 'AC3' to_remove.append(audio_codec) @@ -1140,8 +1347,8 @@ def when(self, matches, context): return to_remove, to_append -class FormatStandardizer(Rule): - """DVB renamed to PDTV.""" +class SourceStandardizer(Rule): + """Digital TV renamed to PDTV.""" priority = POST_PROCESS consequence = [RemoveMatch, AppendMatch] @@ -1157,11 +1364,11 @@ def when(self, matches, context): """ to_remove = [] to_append = [] - for source in matches.named('format', predicate=lambda m: m.value in ('DVB', )): - new_format = copy.copy(source) - new_format.value = 'PDTV' + for source in matches.named('source', predicate=lambda m: m.value in ('Digital TV', )): + new_source = copy.copy(source) + new_source.value = 'PDTV' to_remove.append(source) - to_append.append(new_format) + to_append.append(new_source) return to_remove, to_append @@ -1182,10 +1389,10 @@ def when(self, matches, context): :return: """ to_append = [] - for video_codec in matches.named('video_codec', lambda m: m.value in ('h264', 'h265') and 'x26' in m.raw.lower()): + for video_codec in matches.named('video_codec', lambda m: m.value in ('H.264', 'H.265') and 'x26' in m.raw.lower()): encoder = copy.copy(video_codec) encoder.name = 'video_encoder' - encoder.value = encoder.value.replace('h', 'x') + encoder.value = encoder.value.replace('H.', 'x') to_append.append(encoder) return to_append @@ -1207,7 +1414,7 @@ def when(self, matches, context): :return: """ to_remove = [] - for name in ('episode_title', 'format', 'release_group', 'title'): + for name in ('episode_title', 'source', 'release_group', 'title'): values = matches.named(name) unique_values = {v.value for v in values} if len(unique_values) > 1: @@ -1238,8 +1445,8 @@ class ReleaseGroupPostProcessor(Rule): "season": 2, "episode": 14, "screen_size": "1080p", - "format": "HDTV", - "video_codec": "h264", + "source": "HDTV", + "video_codec": "H.264", "release_group": "GROUP[TRASH]", "type": "episode" } @@ -1252,8 +1459,8 @@ class ReleaseGroupPostProcessor(Rule): "season": 2, "episode": 14, "screen_size": "1080p", - "format": "HDTV", - "video_codec": "h264", + "source": "HDTV", + "video_codec": "H.264", "release_group": "GROUP", "type": "episode" } @@ -1331,7 +1538,7 @@ def when(self, matches, context): to_remove.append(release_group) if value: new_release_group = copy.copy(release_group) - new_release_group.value = clean_groupname(value) + new_release_group.value = value to_append.append(new_release_group) return to_remove, to_append @@ -1353,20 +1560,22 @@ def rules(): BlacklistedReleaseGroup, FixTvChaosUkWorkaround, FixAnimeReleaseGroup, - FixInvalidTitleOrAlternativeTitle, - FixSeasonRangeWithGap, + FixInvalidAbsoluteReleaseGroups, AnimeWithSeasonAbsoluteEpisodeNumbers, AnimeAbsoluteEpisodeNumbers, AbsoluteEpisodeNumbers, PartsAsEpisodeNumbers, + RemoveInvalidEpisodeSeparator, + RemoveYearAsSeason, CreateAliasWithAlternativeTitles, CreateAliasWithCountryOrYear, ReleaseGroupPostProcessor, - FixMultipleFormats, + FixParentFolderReplacingTitle, + FixTitleAsAudioProfile, + FixMultipleSources, FixMultipleReleaseGroups, - ScreenSizeStandardizer, AudioCodecStandardizer, - FormatStandardizer, + SourceStandardizer, VideoEncoderRule, CreateProperTags, AvoidMultipleValuesRule, diff --git a/medusa/refiners/release.py b/medusa/refiners/release.py index 3ae8ac98f2..1f59a1c51d 100644 --- a/medusa/refiners/release.py +++ b/medusa/refiners/release.py @@ -17,7 +17,7 @@ MOVIE_ATTRIBUTES = { 'title': 'title', 'year': 'year', - 'format': 'format', + 'source': 'source', 'release_group': 'release_group', 'resolution': 'screen_size', 'video_codec': 'video_codec', @@ -29,7 +29,7 @@ 'episode': 'episode', 'title': 'episode_title', 'year': 'year', - 'format': 'format', + 'source': 'source', 'release_group': 'release_group', 'resolution': 'screen_size', 'video_codec': 'video_codec', @@ -55,7 +55,7 @@ def refine(video, release_name=None, release_file=None, extension='release', **k * :attr:`~subliminal.video.Video.season` * :attr:`~subliminal.video.Video.episode` * :attr:`~subliminal.video.Video.year` - * :attr:`~subliminal.video.Video.format` + * :attr:`~subliminal.video.Video.source` * :attr:`~subliminal.video.Video.release_group` * :attr:`~subliminal.video.Video.resolution` * :attr:`~subliminal.video.Video.video_codec` diff --git a/medusa/refiners/tv_episode.py b/medusa/refiners/tv_episode.py index df5fd96495..41081b17ec 100644 --- a/medusa/refiners/tv_episode.py +++ b/medusa/refiners/tv_episode.py @@ -70,7 +70,7 @@ def refine(video, tv_episode=None, **kwargs): enrich(EPISODE_MAPPING, video, tv_episode) enrich(ADDITIONAL_MAPPING, video, tv_episode, overwrite=False) guess = Quality.to_guessit(tv_episode.quality) - enrich({'resolution': guess.get('screen_size'), 'format': guess.get('format')}, video, overwrite=False) + enrich({'resolution': guess.get('screen_size'), 'source': guess.get('source')}, video, overwrite=False) def enrich(attributes, target, source=None, overwrite=True): diff --git a/medusa/subtitle_providers/itasa.py b/medusa/subtitle_providers/itasa.py index b9680bddb1..0fd19a6647 100644 --- a/medusa/subtitle_providers/itasa.py +++ b/medusa/subtitle_providers/itasa.py @@ -35,13 +35,13 @@ class ItaSASubtitle(Subtitle): provider_name = 'itasa' - def __init__(self, sub_id, series, season, episode, video_format, year, tvdb_id, full_data): + def __init__(self, sub_id, series, season, episode, video_source, year, tvdb_id, full_data): super(ItaSASubtitle, self).__init__(Language('ita')) self.sub_id = sub_id self.series = series self.season = season self.episode = episode - self.format = video_format + self.source = video_source self.year = year self.tvdb_id = tvdb_id self.full_data = full_data @@ -62,9 +62,9 @@ def get_matches(self, video, hearing_impaired=False): # episode if video.episode and self.episode == video.episode: matches.add('episode') - # format - if video.format and video.format.lower() in self.format.lower(): - matches.add('format') + # source + if video.source and video.source.lower() in self.source.lower(): + matches.add('source') if video.year and self.year == video.year: matches.add('year') if video.series_tvdb_id and self.tvdb_id == video.series_tvdb_id: @@ -262,12 +262,12 @@ def _download_zip(self, sub_id): return r.content - def _get_season_subtitles(self, show_id, season, sub_format): + def _get_season_subtitles(self, show_id, season, sub_source): params = { 'apikey': self.apikey, 'show_id': show_id, 'q': 'Stagione %%%d' % season, - 'version': sub_format + 'version': sub_source } r = self.session.get(self.server_url + 'subtitles/search', params=params, timeout=30) r.raise_for_status() @@ -276,7 +276,7 @@ def _get_season_subtitles(self, show_id, season, sub_format): if int(root.find('data/count').text) == 0: logger.warning('Subtitles for season not found, try with rip suffix') - params['version'] = sub_format + 'rip' + params['version'] = sub_source + 'rip' r = self.session.get(self.server_url + 'subtitles/search', params=params, timeout=30) r.raise_for_status() root = etree.fromstring(r.content) @@ -323,7 +323,7 @@ def _get_season_subtitles(self, show_id, season, sub_format): return subs - def query(self, series, season, episode, video_format, resolution, country=None): + def query(self, series, season, episode, video_source, resolution, country=None): # To make queries you need to be logged in if not self.logged_in: # pragma: no cover @@ -336,18 +336,18 @@ def query(self, series, season, episode, video_format, resolution, country=None) return [] # get the page of the season of the show - logger.info('Getting the subtitle of show id %d, season %d episode %d, format %r', show_id, - season, episode, video_format) + logger.info('Getting the subtitle of show id %d, season %d episode %d, source %r', show_id, + season, episode, video_source) subtitles = [] - # Default format is SDTV - if not video_format or video_format.lower() == 'hdtv': + # Default source is SDTV + if not video_source or video_source.lower() == 'hdtv': if resolution in ('1080i', '1080p', '720p'): - sub_format = resolution + sub_source = resolution else: - sub_format = 'normale' + sub_source = 'normale' else: - sub_format = video_format.lower() + sub_source = video_source.lower() # Look for year params = { @@ -368,8 +368,8 @@ def query(self, series, season, episode, video_format, resolution, country=None) 'apikey': self.apikey, 'show_id': show_id, 'q': '%dx%02d' % (season, episode), - 'version': sub_format - } + 'version': sub_source + } r = self.session.get(self.server_url + 'subtitles/search', params=params, timeout=30) r.raise_for_status() root = etree.fromstring(r.content) @@ -377,7 +377,7 @@ def query(self, series, season, episode, video_format, resolution, country=None) if int(root.find('data/count').text) == 0: logger.warning('Subtitles not found, try with rip suffix') - params['version'] = sub_format + 'rip' + params['version'] = sub_source + 'rip' r = self.session.get(self.server_url + 'subtitles/search', params=params, timeout=30) r.raise_for_status() root = etree.fromstring(r.content) @@ -385,10 +385,10 @@ def query(self, series, season, episode, video_format, resolution, country=None) logger.warning('Subtitles not found, go season mode') # If no subtitle are found for single episode try to download all season zip - subs = self._get_season_subtitles(show_id, season, sub_format) + subs = self._get_season_subtitles(show_id, season, sub_source) if subs: for subtitle in subs: - subtitle.format = video_format + subtitle.source = video_source subtitle.year = year subtitle.tvdb_id = tvdb_id @@ -406,14 +406,15 @@ def query(self, series, season, episode, video_format, resolution, country=None) subtitle.find('version').text) sub = ItaSASubtitle( - int(subtitle.find('id').text), - subtitle.find('show_name').text, - season, - episode, - video_format, - year, - tvdb_id, - subtitle.find('name').text) + int(subtitle.find('id').text), + subtitle.find('show_name').text, + season, + episode, + video_source, + year, + tvdb_id, + subtitle.find('name').text + ) subtitles.append(sub) @@ -441,7 +442,7 @@ def query(self, series, season, episode, video_format, resolution, country=None) subtitle.find('show_name').text, season, episode, - video_format, + video_source, year, tvdb_id, subtitle.find('name').text) @@ -483,7 +484,7 @@ def query(self, series, season, episode, video_format, resolution, country=None) return subtitles + additional_subs def list_subtitles(self, video, languages): - return self.query(video.series, video.season, video.episode, video.format, video.resolution) + return self.query(video.series, video.season, video.episode, video.source, video.resolution) def download_subtitle(self, subtitle): # pragma: no cover pass diff --git a/renovate.json b/renovate.json index 1cec8e2c61..7e3a1123a9 100644 --- a/renovate.json +++ b/renovate.json @@ -30,9 +30,6 @@ }, "python": { "labels": ["Update dep (Py)"], - "ignoreDeps": [ - "guessit" - ], "packageRules": [ { "packageNames": ["tornado"], diff --git a/requirements.txt b/requirements.txt index 8f2cf5b3dc..d9a599b8eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,7 @@ git+https://github.com/kurtmckee/feedparser.git@f1dd1bb923ebfe6482fc2521c1f150b4 future==0.16.0 futures==3.2.0 ; python_version >= '2.6' and python_version < '3' gntp==1.0.3 -guessit==2.1.4 +guessit==3.0.0 html5lib==1.0.1 imdbpie==5.6.2 jsonrpclib-pelix==0.3.1 @@ -34,7 +34,7 @@ rebulk==0.9.0 requests==2.19.1 six==1.11.0 stevedore==1.29.0 -git+https://github.com/Diaoul/subliminal.git@879c0c8d18618e32ad466bb63bd939edb268bc60#egg=subliminal +git+https://github.com/pymedusa/subliminal.git@78687f45d23b1bc47fae0a5493be0198dc1fd5b5#egg=subliminal tornado==5.1 tornroutes==0.5.1 validators==0.12.2 diff --git a/setup.cfg b/setup.cfg index b60ed1bdf9..e6cbec83b6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -161,7 +161,7 @@ flake8-ignore = medusa/show_updater.py D100 D101 D102 D105 medusa/subtitle_providers/__init__.py D104 medusa/subtitle_providers/legendastv.py D100 D102 D103 D105 D204 - medusa/subtitle_providers/itasa.py D100 D101 D102 D105 D400 E123 E126 + medusa/subtitle_providers/itasa.py D100 D101 D102 D105 D400 medusa/subtitle_providers/wizdom.py D100 D102 D204 medusa/system/__init__.py D104 medusa/system/restart.py D100 D101 D102 diff --git a/tests/test_common.py b/tests/test_common.py index 76cb654e3d..d19a033a15 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -7,94 +7,94 @@ @pytest.mark.parametrize('p', [ - { # p0: No screen_size, no format + { # p0: No screen_size, no source 'expected': Quality.UNKNOWN }, - { # p1: screen_size but no format + { # p1: screen_size but no source 'screen_size': '720p', 'expected': Quality.UNKNOWN }, - { # p2: format but no screen_size - 'format': 'HDTV', + { # p2: source but no screen_size + 'source': 'HDTV', 'expected': Quality.UNKNOWN }, { # p3 'screen_size': '720p', - 'format': 'HDTV', + 'source': 'HDTV', 'expected': Quality.HDTV }, { # p4 'screen_size': '720p', - 'format': 'WEB-DL', + 'source': 'Web', 'expected': Quality.HDWEBDL }, { # p5 'screen_size': '720p', - 'format': 'WEBRip', - 'expected': Quality.HDWEBDL - }, - { # p6 - 'screen_size': '720p', - 'format': 'BluRay', + 'source': 'Blu-ray', 'expected': Quality.HDBLURAY }, - { # p7 + { # p6 'screen_size': '1080i', 'expected': Quality.RAWHDTV }, - { # p8 + { # p7 'screen_size': '1080p', - 'format': 'HDTV', + 'source': 'HDTV', 'expected': Quality.FULLHDTV }, - { # p9 + { # p8 'screen_size': '1080p', - 'format': 'WEB-DL', + 'source': 'Web', 'expected': Quality.FULLHDWEBDL }, - { # p10 + { # p9 'screen_size': '1080p', - 'format': 'WEBRip', - 'expected': Quality.FULLHDWEBDL + 'source': 'Blu-ray', + 'expected': Quality.FULLHDBLURAY + }, + { # p10 + 'screen_size': '2160p', + 'source': 'HDTV', + 'expected': Quality.UHD_4K_TV }, { # p11 - 'screen_size': '1080p', - 'format': 'BluRay', - 'expected': Quality.FULLHDBLURAY + 'screen_size': '2160p', + 'source': 'Web', + 'expected': Quality.UHD_4K_WEBDL }, { # p12 - 'screen_size': '4K', - 'format': 'HDTV', - 'expected': Quality.UHD_4K_TV + 'screen_size': '2160p', + 'source': 'Blu-ray', + 'expected': Quality.UHD_4K_BLURAY }, { # p13 - 'screen_size': '4K', - 'format': 'WEB-DL', - 'expected': Quality.UHD_4K_WEBDL + 'screen_size': '4320p', + 'source': 'HDTV', + 'expected': Quality.UHD_8K_TV }, { # p14 - 'screen_size': '4K', - 'format': 'WEBRip', - 'expected': Quality.UHD_4K_WEBDL + 'screen_size': '4320p', + 'source': 'Web', + 'expected': Quality.UHD_8K_WEBDL }, { # p15 - 'screen_size': '4K', - 'format': 'BluRay', - 'expected': Quality.UHD_4K_BLURAY + 'screen_size': '4320p', + 'source': 'Blu-ray', + 'expected': Quality.UHD_8K_BLURAY }, { # p16: multiple screen sizes - 'screen_size': ['4K', '720p'], - 'format': 'BluRay', + 'screen_size': ['2160p', '720p'], + 'source': 'Blu-ray', 'expected': Quality.UNKNOWN }, - { # p17: multiple formats + { # p17: multiple sources 'screen_size': '720p', - 'format': ['HDTV', 'BluRay'], + 'source': ['HDTV', 'Blu-ray'], 'expected': Quality.UNKNOWN }, - { # p18: format not mapped (at least not yet) + { # p18: source not mapped (at least not yet) 'screen_size': '480p', - 'format': 'HDTV', + 'source': 'HDTV', 'expected': Quality.UNKNOWN }, ]) @@ -102,7 +102,7 @@ def test_from_guessit(p): # Given guess = { 'screen_size': p.get('screen_size'), - 'format': p.get('format'), + 'source': p.get('source'), } expected = p['expected'] @@ -130,21 +130,21 @@ def test_from_guessit(p): 'quality': Quality.HDTV, 'expected': { 'screen_size': '720p', - 'format': 'HDTV' + 'source': 'HDTV' } }, { # p4 'quality': Quality.HDWEBDL, 'expected': { 'screen_size': '720p', - 'format': 'WEB-DL', + 'source': 'Web', } }, { # p5 'quality': Quality.HDBLURAY, 'expected': { 'screen_size': '720p', - 'format': 'BluRay', + 'source': 'Blu-ray', } }, { # p6 @@ -157,47 +157,64 @@ def test_from_guessit(p): 'quality': Quality.FULLHDTV, 'expected': { 'screen_size': '1080p', - 'format': 'HDTV', + 'source': 'HDTV', } }, { # p8 'quality': Quality.FULLHDWEBDL, 'expected': { 'screen_size': '1080p', - 'format': 'WEB-DL', + 'source': 'Web', } }, { # p9 'quality': Quality.FULLHDBLURAY, 'expected': { 'screen_size': '1080p', - 'format': 'BluRay', + 'source': 'Blu-ray', } }, { # p10 'quality': Quality.UHD_4K_TV, 'expected': { - 'screen_size': '4K', - 'format': 'HDTV', + 'screen_size': '2160p', + 'source': 'HDTV', } }, { # p11 'quality': Quality.UHD_4K_WEBDL, 'expected': { - 'screen_size': '4K', - 'format': 'WEB-DL', + 'screen_size': '2160p', + 'source': 'Web', } }, { # p12 'quality': Quality.UHD_4K_BLURAY, 'expected': { - 'screen_size': '4K', - 'format': 'BluRay', + 'screen_size': '2160p', + 'source': 'Blu-ray', } }, - { # p13: guessit unsupported quality + { # p13 + 'quality': Quality.UHD_8K_TV, + 'expected': { + 'screen_size': '4320p', + 'source': 'HDTV', + } + }, + { # p14 + 'quality': Quality.UHD_8K_WEBDL, + 'expected': { + 'screen_size': '4320p', + 'source': 'Web', + } + }, + { # p15 'quality': Quality.UHD_8K_BLURAY, - 'expected': dict() + 'expected': { + 'screen_size': '4320p', + 'source': 'Blu-ray', + } } ]) def test_to_guessit(p): diff --git a/tests/test_guessit.yml b/tests/test_guessit.yml index 59a8a6d126..469accf290 100644 --- a/tests/test_guessit.yml +++ b/tests/test_guessit.yml @@ -3,9 +3,9 @@ : title: Show Name season: 1 episode: [2, 3] - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -23,9 +23,9 @@ : title: Show Name season: 1 episode: [2, 3] - format: BluRay + source: Blu-ray screen_size: 1080p - video_codec: h265 + video_codec: H.265 video_encoder: x265 release_group: SuperGroup type: episode @@ -43,9 +43,9 @@ : title: Show Name season: 1 episode: 2 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -71,9 +71,9 @@ : title: Show Name season: 1 episode: [2, 3] - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -98,9 +98,9 @@ : title: Show Name season: 1 episode: 2 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -118,9 +118,9 @@ : title: Show Name season: 1 episode: [2, 3, 4] - format: DVD + source: DVD screen_size: 480p - video_codec: XviD + video_codec: Xvid release_group: SomeGroup type: episode @@ -137,8 +137,8 @@ : title: Show Name season: 4 episode: [8, 9] - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -150,7 +150,7 @@ : title: Show Name season: 4 episode: 8 - format: HDTV + source: HDTV language: ca type: episode @@ -159,8 +159,8 @@ : title: Show Name season: 4 episode: 9 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -170,9 +170,9 @@ ? Show.Name.2010.11.23.HDTV.720p.x264-Group : title: Show Name date: 2010-11-23 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -192,9 +192,9 @@ episode: 0 # ? episode_title: Event date: 2010-11-23 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -203,9 +203,9 @@ ? Show.Name.2011.12.24.HDTV.720p.x264-Group : title: Show Name date: 2011-12-24 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -224,9 +224,9 @@ : title: Show Name Abbreviated season: 1 episode: 2 - video_codec: h264 + video_codec: H.264 video_encoder: x264 - format: BluRay + source: Blu-ray screen_size: 1080p release_group: TPZ container: mkv @@ -245,9 +245,9 @@ ? Show.Name.S01.HDTV.720p.x264-Group : title: Show Name season: 1 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -256,9 +256,9 @@ ? Show.Name.E02-03.HDTV.720p.X264-Group : title: Show Name episode: [2, 3] - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -281,9 +281,9 @@ ? Show.Name.Part.3.HDTV.720p.x264-Group : title: Show Name episode: 3 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -293,9 +293,9 @@ : title: Show Name episode: [1, 2] episode_title: and # guessit issue, but it's not a big problem - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -305,8 +305,8 @@ : title: Show Name episode: 4 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP container: mkv @@ -319,8 +319,8 @@ season: 1 episode: 4 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP container: mkv @@ -332,9 +332,9 @@ : title: Show Name season: 1 episode: 2 - format: HDTV + source: HDTV screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -373,6 +373,7 @@ episode: 727 release_group: SomeGroup screen_size: 720p + aspect_ratio: '1.778' subtitle_language: fr other: HD type: episode @@ -398,7 +399,7 @@ crc32: 2F7B3FA2 release_group: GROUP version: 1 - video_profile: 8bit + color_depth: 8-bit type: episode # anime_french_fansub @@ -409,6 +410,7 @@ absolute_episode: 445 episode: 445 screen_size: 720p + aspect_ratio: '1.778' subtitle_language: fr # TODO: Fix # release_group: Resistance @@ -425,10 +427,11 @@ episode: 15 subtitle_language: fr screen_size: 720p + aspect_ratio: '1.778' # TODO: Fix # release_group: Resistance release_group: version - other: HQ + other: High Quality type: episode # anime_french_fansub @@ -462,7 +465,7 @@ subtitle_language: fr release_group: Y-F other: HD - video_profile: 8bit + color_depth: 8-bit type: episode # anime_french_fansub (FixTitlesContainsNumber) @@ -473,7 +476,7 @@ absolute_episode: 4 episode: 4 subtitle_language: fr - other: FullHD + other: Full HD type: episode # anime_french_fansub @@ -555,8 +558,9 @@ absolute_episode: 12 episode: 12 screen_size: 720p - video_codec: h264 + video_codec: H.264 audio_codec: AAC + aspect_ratio: '1.778' crc32: 379759DB release_group: Group type: episode @@ -567,8 +571,9 @@ absolute_episode: [2, 3] episode: [2, 3] screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 + aspect_ratio: '1.778' audio_codec: AAC release_group: SomeGroup type: episode @@ -591,7 +596,7 @@ absolute_episode: 7 episode: 7 screen_size: 720p - video_codec: h264 + video_codec: H.264 crc32: EB7838FC release_group: SomeOne type: episode @@ -603,7 +608,7 @@ absolute_episode: 7 episode: 7 screen_size: 720p - video_codec: h264 + video_codec: H.264 crc32: EB7838FC version: 2 release_group: SomeOne @@ -616,7 +621,7 @@ absolute_episode: 7 episode: 7 screen_size: 720p - video_codec: h264 + video_codec: H.264 crc32: EB7838FC version: 2 release_group: SomeOne @@ -627,7 +632,7 @@ : title: A Very Long Show Name Here absolute_episode: 10 episode: 10 - video_codec: h264 + video_codec: H.264 screen_size: 720p crc32: 8853B21C release_group: Group-Shikkaku @@ -723,13 +728,6 @@ episode: [3, 4, 5] type: episode -# FixInvalidAlternativeTitle - title case (negative scenario) -? Show Name 315-313 s16e03-05 -: title: Show Name - season: 16 - episode: [3, 4, 5] - type: episode - # anime_and_normal_front # This one doesn't work with both parsers (current nor guessit) #? 165.Show Name.s08e014 @@ -788,7 +786,8 @@ absolute_episode: 6 episode: 6 screen_size: 720p - video_profile: 10bit + color_depth: 10-bit + video_profile: High 10 crc32: 1F5578AC release_group: SuperGroup type: episode @@ -799,7 +798,8 @@ absolute_episode: 6 episode: 6 screen_size: 1080p - video_profile: 10bit + color_depth: 10-bit + video_profile: High 10 crc32: 1F5578AC release_group: SuperGroup type: episode @@ -812,10 +812,10 @@ proper_count: 1 proper_tag: REPACK screen_size: 720p - format: BluRay + source: Blu-ray audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: 4EVERHD type: episode @@ -845,7 +845,7 @@ : title: 11.22.63 season: 1 episode: 6 - format: HDTV + source: HDTV release_group: abc type: episode @@ -902,7 +902,7 @@ # expected_group ? Show.Name.x264-byEMP : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: byEMP type: episode @@ -910,7 +910,7 @@ # expected_group ? Show.Name.x264-ELITETORRENT : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: ELITETORRENT type: episode @@ -918,7 +918,7 @@ # expected_group ? Show.Name.x264-F4ST3R : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: F4ST3R type: episode @@ -926,7 +926,7 @@ # expected_group ? Show.Name.x264-F4ST : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: F4ST type: episode @@ -934,7 +934,7 @@ # expected_group ? Show.Name.x264-TGNF4ST : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: TGNF4ST type: episode @@ -942,7 +942,7 @@ # https://github.com/guessit-io/guessit/issues/316 ? Show.Name.x264-CDD : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: CDD type: episode @@ -950,7 +950,7 @@ # https://github.com/guessit-io/guessit/issues/316 ? Show.Name.x264-CDP : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: CDP type: episode @@ -958,7 +958,7 @@ # https://github.com/guessit-io/guessit/issues/317 ? Show.Name.x264-HDD : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: HDD type: episode @@ -966,7 +966,7 @@ # expected_group ? Show.Name.x264-NovaRip : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: NovaRip type: episode @@ -974,7 +974,7 @@ # expected_group ? Show.Name.x264-PARTiCLE : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: PARTiCLE type: episode @@ -982,7 +982,7 @@ # expected_group ? Show.Name.x264-POURMOi : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: POURMOi type: episode @@ -990,7 +990,7 @@ # expected_group ? Show.Name.x264-RipPourBox : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: RipPourBox type: episode @@ -998,7 +998,7 @@ # expected_group ? Show.Name.x264-RiPRG : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: RiPRG type: episode @@ -1006,7 +1006,7 @@ # expected_group ? Show.Name.x264-TV2LAX9 : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: TV2LAX9 type: episode @@ -1014,7 +1014,7 @@ # expected_group ? Show.Name.x264-AF : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: AF type: episode @@ -1022,7 +1022,7 @@ # expected_group ? Show.Name.x264-AR : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: AR type: episode @@ -1030,7 +1030,7 @@ # expected_group ? Show.Name.x264-CS : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: CS type: episode @@ -1038,7 +1038,7 @@ # expected_group ? Show.Name.x264-DR : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: DR type: episode @@ -1046,7 +1046,7 @@ # expected_group ? Show.Name.x264-MC : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: MC type: episode @@ -1054,7 +1054,7 @@ # expected_group ? Show.Name.x264-NA : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: NA type: episode @@ -1062,7 +1062,7 @@ # expected_group ? Show.Name.x264-TL : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: TL type: episode @@ -1070,7 +1070,7 @@ # expected_group ? Show.Name.x264-YT : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: YT type: episode @@ -1078,7 +1078,7 @@ # expected_group ? Show.Name.x264-ZT : title: Show Name - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: ZT type: episode @@ -1093,8 +1093,8 @@ country: US season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1106,8 +1106,8 @@ country: US season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1119,8 +1119,8 @@ country: US episode: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1132,8 +1132,8 @@ country: US date: 2012-12-12 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1146,8 +1146,8 @@ season: 5 episode: 1 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: ABC type: episode @@ -1159,8 +1159,8 @@ year: 2002 season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1172,8 +1172,8 @@ year: 2002 season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1184,8 +1184,8 @@ country: US season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1196,8 +1196,8 @@ country: US season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1208,8 +1208,8 @@ year: 2005 season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1220,8 +1220,8 @@ year: 2005 season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: SuperGroup type: episode @@ -1234,10 +1234,10 @@ episode: 1 episode_title: Episode Name screen_size: 1080i - format: HDTV + source: HDTV audio_codec: AC3 audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 release_group: GroupName type: episode @@ -1284,8 +1284,7 @@ ? "[Group].Show.Name.-.102.[720p]" : options: {show_type: normal} title: Show Name - season: 1 - episode: 2 + episode: 102 screen_size: 720p release_group: Group type: episode @@ -1312,7 +1311,7 @@ episode: 1 episode_count: 8 episode_title: Title - video_codec: h264 + video_codec: H.264 video_encoder: x264 audio_codec: AAC release_group: Group @@ -1323,8 +1322,8 @@ : title: Some Show episode: 7 screen_size: 1080p - format: HDTV - video_codec: h265 + source: HDTV + video_codec: H.265 video_encoder: x265 release_group: GROUP type: episode @@ -1342,8 +1341,8 @@ : title: Show Name episode: 3 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1355,8 +1354,8 @@ episode_title: Some Name part: 2 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1368,8 +1367,8 @@ episode_title: Some Name part: 2 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1381,8 +1380,8 @@ episode_title: Some Name part: 2 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1395,8 +1394,8 @@ episode_title: Some Name part: 2 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1408,10 +1407,10 @@ : title: Some Show season: 2 episode: 14 - video_codec: h264 + video_codec: H.264 video_encoder: x264 screen_size: 1080p - format: HDTV + source: HDTV type: episode # https://github.com/guessit-io/guessit/issues/295 (h265) @@ -1419,10 +1418,10 @@ : title: Some Show season: 2 episode: 14 - video_codec: h265 + video_codec: H.265 video_encoder: x265 screen_size: 1080p - format: HDTV + source: HDTV type: episode # https://github.com/guessit-io/guessit/issues/295 (negative scenario: xvid) @@ -1430,8 +1429,8 @@ : title: Some Show season: 2 episode: 14 - video_codec: XviD - format: HDTV + video_codec: Xvid + source: HDTV type: episode # https://github.com/guessit-io/guessit/issues/306 @@ -1440,8 +1439,8 @@ : title: Show Name season: 3 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1453,8 +1452,8 @@ season: 3 episode: 2 screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1464,8 +1463,8 @@ : title: Show Name season: 1 screen_size: 720p - format: HDTV - video_codec: h265 + source: HDTV + video_codec: H.265 video_encoder: x265 release_group: Group type: episode @@ -1478,10 +1477,10 @@ season: 6 episode: 4 screen_size: 1080i - format: HDTV + source: HDTV audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: BS666 type: episode @@ -1491,10 +1490,10 @@ season: 6 episode: 4 screen_size: 1080i - format: HDTV + source: HDTV audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: ccs3 type: episode @@ -1504,10 +1503,10 @@ season: 6 episode: 4 screen_size: 1080i - format: HDTV + source: HDTV audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: qqss44 type: episode @@ -1516,9 +1515,10 @@ : title: Show Name season: 6 episode: 14 - format: WEBRip + source: Web release_group: qqss44 container: avi + other: Rip mimetype: video/x-msvideo type: episode @@ -1577,7 +1577,8 @@ ? Show.season_1-10.(DVDrip) : title: Show season: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - format: DVDRip + source: DVDRip + other: Rip type: episode # ReleaseGroupPostProcessor @@ -1586,8 +1587,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -1598,8 +1599,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -1610,8 +1611,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -1622,8 +1623,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 size: 123MB release_group: GROUP @@ -1635,8 +1636,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 size: 4.2GB release_group: GROUP @@ -1651,10 +1652,10 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 - other: ReEncoded + other: Reencoded release_group: GROUP type: episode @@ -1668,8 +1669,8 @@ other: Proper proper_count: 1 proper_tag: PROPER - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 type: episode @@ -1683,8 +1684,8 @@ other: Proper proper_count: 1 proper_tag: PROPER - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 type: episode @@ -1696,8 +1697,8 @@ other: Proper proper_count: 1 proper_tag: PROPER - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 type: episode @@ -1707,8 +1708,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP mimetype: application/rar @@ -1720,8 +1721,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -1732,8 +1733,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 subtitle_language: nl release_group: Group @@ -1746,9 +1747,10 @@ episode: 3 subtitle_language: pl screen_size: 480p - format: WEBRip - video_codec: h264 + source: Web + video_codec: H.264 video_encoder: x264 + other: Rip type: episode # subtitle language (ukranian) @@ -1757,9 +1759,10 @@ season: 10 episode: 15 screen_size: 480p - format: BDRip - video_codec: h264 + source: BDRip + video_codec: H.264 language: uk + other: Rip release_group: hurtom type: episode @@ -1769,8 +1772,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1781,8 +1784,8 @@ season: 2 episode: 14 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -1793,10 +1796,10 @@ season: 3 episode: 16 screen_size: 1080p - format: WEB-DL + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: GOLF68 type: episode @@ -1805,9 +1808,10 @@ : title: Show Name season: 2 episode: 4 - format: WEBRip - video_codec: h264 + source: Web + video_codec: H.264 video_encoder: x264 + other: Rip release_group: NF69 type: episode @@ -1819,8 +1823,8 @@ other: Formula One episode_details: Special screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: C4TV type: episode @@ -1840,8 +1844,8 @@ season: 11 episode: 11 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -1851,8 +1855,8 @@ ? Show.Name.Season.1.2.HDTV.XviD-GoodGroup[SomeTrash] : title: Show Name season: [1, 2] - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: GoodGroup type: episode @@ -1861,8 +1865,8 @@ : title: The Show Name date: 2016-05-18 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -1936,9 +1940,9 @@ season: 3 episode: 19 subtitle_language: fr - other: Fastsub - format: HDTV - video_codec: XviD + other: Fast Subtitled + source: HDTV + video_codec: Xvid release_group: F4ST type: episode @@ -1956,9 +1960,9 @@ episode: 25 episode_title: Episode Name screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 - format: HDTV + source: HDTV release_group: BCDE type: episode @@ -1969,9 +1973,9 @@ episode: 0 episode_title: Episode Name screen_size: 720p - video_codec: h264 + video_codec: H.264 video_encoder: x264 - format: HDTV + source: HDTV release_group: BCDE type: episode @@ -1981,7 +1985,7 @@ season: 1 episode: 12 year: 2014 - video_codec: XviD + video_codec: Xvid audio_codec: AC3 audio_channels: '5.1' subtitle_language: nl @@ -2011,7 +2015,7 @@ episode: 2 episode_details: Special screen_size: 1080p - format: BDRip + source: BDRip release_group: GroupName type: episode @@ -2022,7 +2026,7 @@ absolute_episode: 462 episode: 462 screen_size: 720p - video_profile: 10bit + color_depth: 10-bit release_group: AnimeRG type: episode @@ -2033,7 +2037,7 @@ absolute_episode: 462 episode: 462 screen_size: 720p - video_profile: 10bit + color_depth: 10-bit release_group: AnimeRG type: episode @@ -2044,7 +2048,7 @@ absolute_episode: 462 episode: 462 screen_size: 720p - video_profile: 10bit + color_depth: 10-bit release_group: AnimeRG type: episode @@ -2054,8 +2058,8 @@ : title: Fear The Show Name season: 2 episode: 2 - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: FUM type: episode @@ -2065,8 +2069,8 @@ : title: The Show Name season: 2 episode: 2 - format: HDTV - video_codec: h265 + source: HDTV + video_codec: H.265 release_group: ABC type: episode @@ -2076,8 +2080,8 @@ : title: The Show Name season: 5 episode: 1 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 release_group: GOOD type: episode @@ -2096,9 +2100,9 @@ season: 3 episode: [21, 22] subtitle_language: fr - format: HDTV - video_codec: XviD - other: Fastsub + source: HDTV + video_codec: Xvid + other: Fast Subtitled release_group: GROUP type: episode @@ -2109,8 +2113,8 @@ episode: 5 other: Formula One screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: C4TV language: en @@ -2122,7 +2126,7 @@ : title: 11.22.63 season: 1 episode: 5 - format: HDTV + source: HDTV release_group: abc type: episode @@ -2134,8 +2138,8 @@ season: 1 episode: 2 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -2144,7 +2148,7 @@ # SpanishNewpctReleaseName ? Show.Name.-.Temporada1.[HDTV][Cap.105][Español.Castellano] : title: Show Name - format: HDTV + source: HDTV season: 1 episode: 5 language: ca @@ -2153,7 +2157,7 @@ # SpanishNewpctReleaseName ? Show.Name.-.Temporada1.[HDTV][Cap.105][Español] : title: Show Name - format: HDTV + source: HDTV season: 1 episode: 5 language: es @@ -2165,8 +2169,8 @@ season: 1 episode: [2, 3, 4] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -2178,8 +2182,8 @@ season: 15 episode: 3 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -2191,8 +2195,8 @@ season: 15 episode: [3, 4, 5, 6] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -2204,8 +2208,8 @@ season: 1 episode: 2 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -2217,8 +2221,8 @@ season: 1 episode: 2 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 language: es release_group: NEWPCT @@ -2230,12 +2234,12 @@ season: 1 episode: [12, 13, 14] screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 + episode_details: Final language: es release_group: NEWPCT - other: FINAL type: episode # corner case @@ -2244,7 +2248,7 @@ : title: Show Name season: 6 episode: 5 - video_codec: h265 + video_codec: H.265 video_encoder: x265 audio_codec: AC3 audio_channels: '2.0' @@ -2257,9 +2261,10 @@ : title: Show Name season: 1 episode: 5 - format: WEBRip - video_codec: h264 + source: Web + video_codec: H.264 video_encoder: x264 + other: Rip release_group: GROUP type: episode @@ -2269,8 +2274,8 @@ date: 2016-06-14 episode_title: Some Title screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -2280,10 +2285,10 @@ : title: Show Name season: 2 episode: 19 - video_codec: h264 + video_codec: H.264 language: it audio_codec: AAC - format: WEB-DL + source: Web other: Mux release_group: UBi type: episode @@ -2293,10 +2298,11 @@ : title: Show Name season: 1 episode: 4 - video_codec: h264 + video_codec: H.264 language: it audio_codec: AC3 - format: HDTV + source: HDTV + other: Rip release_group: DEUS TEAM type: episode @@ -2306,9 +2312,9 @@ season: 1 episode: 10 screen_size: 1080p - video_codec: h264 + video_codec: H.264 language: [it, en] - format: WEB-DL + source: Web other: Mux audio_codec: AC3 subtitle_language: [it, en] @@ -2320,10 +2326,10 @@ : title: Show Name season: 4 episode: [7, 8] - video_codec: h264 + video_codec: H.264 language: it audio_codec: AAC - format: HDTV + source: HDTV other: Mux release_group: NovaRip type: episode @@ -2335,9 +2341,9 @@ episode: 18 episode_title: Un Tuffo Nel Passato language: it - format: HDTV + source: HDTV other: Mux - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: NovaRip type: episode @@ -2349,11 +2355,11 @@ year: 2014 season: 2 episode: 23 - video_codec: XviD + video_codec: Xvid language: [it, en] audio_codec: MP3 subtitle_language: [it, en] - format: WEB-DL + source: Web other: Mux release_group: Pir8 type: episode @@ -2364,11 +2370,11 @@ alternative_title: Game Of Thrones season: 6 episode: 7 - video_codec: h264 + video_codec: H.264 language: [it, en] audio_codec: AAC subtitle_language: [it, en] - format: WEB-DL + source: Web other: Mux release_group: sp_54321 type: episode @@ -2378,8 +2384,8 @@ : title: Mellan Bleke Och Storm language: sv screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -2388,8 +2394,8 @@ : title: Show Name year: 1999 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: HDv_0day_Team container: mkv @@ -2400,16 +2406,16 @@ ? 500.Bus.Stops.Series.1.XviD.hdtv.x264 : title: 500 Bus Stops season: 1 - video_codec: XviD - format: HDTV + video_codec: Xvid + source: HDTV type: episode # https://github.com/guessit-io/guessit/issues/310 ? Show.Name.COMPLETE.SERIES.DVDRip.XviD-AR : title: Show Name - other: Complete - format: DVDRip - video_codec: XviD + other: [Complete, Rip] + source: DVDRip + video_codec: Xvid release_group: AR type: episode @@ -2419,8 +2425,8 @@ other: Complete season: [1, 2, 3, 4, 5] screen_size: 720p - format: BluRay - video_codec: h265 + source: Blu-ray + video_codec: H.265 video_encoder: x265 release_group: SUJAIDR type: episode @@ -2432,8 +2438,9 @@ absolute_episode: 2 episode: 2 screen_size: 720p - video_codec: h265 + video_codec: H.265 audio_codec: AAC + aspect_ratio: '1.778' type: episode ? Show.Name.S02E01.MULTi.FRENCH.VOSTFR-EN.1080p.WEB-DL.HEVC.x265-GOLF68 @@ -2443,8 +2450,8 @@ language: [mul, fr, en] subtitle_language: fr screen_size: 1080p - format: WEB-DL - video_codec: h265 + source: Web + video_codec: H.265 video_encoder: x265 release_group: GOLF68 type: episode @@ -2453,22 +2460,21 @@ : title: Show Name season: 3 episode: [21, 22] - other: Fastsub + other: Fast Subtitled subtitle_language: fr - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: F4ST container: avi mimetype: video/x-msvideo type: episode -? Show.Name.Season.1.(x265.10bit.Joy) +? Show.Name.Season.1.(x265.10bit) : title: Show Name season: 1 - video_codec: h265 + video_codec: H.265 video_encoder: x265 - video_profile: 10bit - release_group: Joy + color_depth: 10-bit type: episode ? - Show.Name.S01E01.DVDRip.XviD-W4F @@ -2476,8 +2482,9 @@ : title: Show Name season: 1 episode: 1 - format: DVDRip - video_codec: XviD + source: DVDRip + video_codec: Xvid + other: Rip release_group: W4F type: episode @@ -2486,9 +2493,9 @@ : title: Show Name season: 1 episode: 1 - format: DVDRip - video_codec: XviD - other: Proper + source: DVDRip + video_codec: Xvid + other: [Rip, Proper] proper_count: 1 proper_tag: REPACK release_group: OMiCRON @@ -2500,8 +2507,9 @@ season: 1 episode: 1 year: 2008 - format: BluRay + source: Blu-ray screen_size: 1080p + video_codec: VC-1 audio_channels: '5.1' container: wmv release_group: NOVO @@ -2512,8 +2520,8 @@ : title: Show Name season: 1 episode: 2 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 other: Proper proper_count: 1 @@ -2531,8 +2539,8 @@ episode: 1 episode_title: Pilot episode_details: Pilot - format: DVD - video_codec: h264 + source: DVD + video_codec: H.264 video_encoder: x264 other: [Screener, Preair] release_group: NoGRP @@ -2543,8 +2551,8 @@ : title: Show Name season: 2 episode: 1 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 audio_codec: AAC container: mp4 @@ -2556,11 +2564,11 @@ ? Show.Name.S03.1080p.BluRay.DTS-HD.MA.5.1.AVC.REMUX-FraMeSToR : title: Show Name season: 3 - format: BluRay - audio_codec: DTS - audio_profile: HDMA + source: Blu-ray + audio_codec: DTS-HD + audio_profile: Master Audio audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 other: Remux screen_size: 1080p release_group: FraMeSToR @@ -2572,8 +2580,8 @@ season: [1, 2, 3] other: Complete screen_size: 720p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: PtM type: episode @@ -2585,8 +2593,8 @@ episode: 23 episode_title: Parley screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: DIMENSION type: episode @@ -2596,8 +2604,8 @@ : title: Show Name season: 1 episode: 3 - format: WEB-DL - video_codec: h264 + source: Web + video_codec: H.264 video_encoder: x264 language: hu release_group: nIk @@ -2608,8 +2616,8 @@ : title: Show Name season: 1 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 subtitle_language: en release_group: Hype @@ -2619,7 +2627,7 @@ ? Show.Name.S01.DVD2.NLsubs-QoQ : title: Show Name season: 1 - format: DVD + source: DVD subtitle_language: nl release_group: QoQ type: episode @@ -2642,9 +2650,9 @@ season: 5 episode: 9 episode_title: Some Episode Title - other: WideScreen - format: SATRip - video_codec: h264 + other: Widescreen + source: Satellite + video_codec: H.264 video_encoder: x264 release_group: NY2 type: episode @@ -2655,8 +2663,8 @@ season: 2 episode: 11 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 subtitle_language: ro release_group: Grp @@ -2668,8 +2676,8 @@ season: 6 episode: 16 other: Hardcoded Subtitles - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 subtitle_language: sv type: episode @@ -2698,8 +2706,8 @@ other: Proper proper_count: 1 proper_tag: DIRFIX - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: Group type: episode @@ -2710,8 +2718,8 @@ season: 6 episode: 4 other: Internal - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -2724,7 +2732,8 @@ season: 6 episode: 5 screen_size: 1080p - format: WEBRip + source: Web + other: Rip subtitle_language: pt-BR type: episode @@ -2734,7 +2743,8 @@ season: 6 episode: 5 screen_size: 1080p - format: WEBRip + source: Web + other: Rip subtitle_language: pt type: episode @@ -2744,11 +2754,11 @@ season: 2 episode: 3 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: Belex - other: DualAudio + other: Dual Audio language: und type: episode @@ -2757,11 +2767,11 @@ : title: Show Name season: 5 screen_size: 1080p - format: BluRay - video_codec: h264 + source: Blu-ray + video_codec: H.264 video_encoder: x264 release_group: Belex - other: DualAudio + other: Dual Audio subtitle_language: und type: episode @@ -2772,7 +2782,7 @@ : title: Show Name season: 1 episode: 3 - format: HDTV + source: HDTV subtitle_language: es release_group: SC type: episode @@ -2784,7 +2794,7 @@ season: 2 episode: 8 screen_size: 720p - format: WEB-DL + source: Web subtitle_language: und type: episode @@ -2803,7 +2813,7 @@ episode: 3 language: en screen_size: 720p - format: WEB-DL + source: Web release_group: AnimeRG type: episode @@ -2822,8 +2832,8 @@ : title: Show Name season: 5 episode: 5 - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: AFG subtitle_language: he type: episode @@ -2834,7 +2844,7 @@ season: 1 episode: 6 streaming_service: Netflix - other: UltraHD + other: Ultra HD type: episode # Corner case for size @@ -2843,8 +2853,8 @@ season: 1 episode: 10 screen_size: 480p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 size: 160MB release_group: Micromkv @@ -2855,8 +2865,8 @@ : title: Show Name season: 1 episode: 1 - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 size: 133MB release_group: POOLSTAR @@ -2868,12 +2878,13 @@ season: 2 episode: 1 # episode title and part are not fixed. Not a big issue for us. + episode_title: eps2 part: 1 screen_size: 1080p - format: WEB-DL + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: GROUP container: mkv mimetype: video/x-matroska @@ -2884,13 +2895,13 @@ season: 2 episode: 1 # episode title and part are not fixed. Not a big issue for us. - episode_title: unm4sk + episode_title: eps2 part: 1 screen_size: 1080p - format: WEB-DL + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: GROUP container: mkv mimetype: video/x-matroska @@ -2902,7 +2913,7 @@ season: 6 episode: 9 screen_size: 720p - format: HDTV + source: HDTV size: 450MB release_group: iExTV type: episode @@ -2914,8 +2925,8 @@ episode: 2 episode_title: Episode Title screen_size: 1080p - format: WEB-DL - video_codec: h264 + source: Web + video_codec: H.264 video_encoder: x264 audio_channels: '5.1' release_group: Group @@ -2929,8 +2940,8 @@ other: Proper proper_count: 2 proper_tag: [REPACK, PROPER] - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -2981,7 +2992,8 @@ : title: 11.22.63 season: 1 year: 2016 - format: HDTV + source: HDTV + other: Rip release_group: Group type: episode @@ -3012,9 +3024,9 @@ episode: 20 episode_title: Episode Title screen_size: 720p - format: HDTV + source: HDTV audio_channels: '2.0' - video_codec: h265 + video_codec: H.265 video_encoder: x265 release_group: GROUP container: mkv @@ -3027,9 +3039,10 @@ episode: 8 episode_title: Episode Title screen_size: 720p - format: WEBRip - video_codec: h265 + source: Web + video_codec: H.265 video_encoder: x265 + other: Rip release_group: GROUP container: mkv type: episode @@ -3041,8 +3054,8 @@ episode: 8 episode_title: Episode Title screen_size: 720p - format: HDTV - video_codec: h265 + source: HDTV + video_codec: H.265 video_encoder: x265 type: episode @@ -3053,8 +3066,8 @@ episode: 14 episode_title: Episode Title screen_size: 720p - format: HDTV - video_codec: h265 + source: HDTV + video_codec: H.265 video_encoder: x265 release_group: GROUP container: mkv @@ -3066,8 +3079,8 @@ episode: 3 episode_count: 3 episode_title: Episode Title - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 audio_codec: AC3 screen_size: 1080p @@ -3079,10 +3092,10 @@ season: 1 episode: 5 screen_size: 720p - format: WEB-DL + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 release_group: Group type: episode disabled: true # work in progress @@ -3091,11 +3104,11 @@ ? Show.Name.S02E59.WEB-DLx264-GROUP : episode: 59 season: 2 - format: WEB-DL + source: Web release_group: GROUP title: Show Name type: episode - video_codec: h264 + video_codec: H.264 video_encoder: x264 # https://github.com/guessit-io/guessit/issues/323 @@ -3103,11 +3116,11 @@ : episode: 31 episode_title: Episode Title season: 12 - format: PDTV + source: PDTV release_group: Group title: Show Name type: episode - video_codec: h264 + video_codec: H.264 video_encoder: x264 # https://github.com/guessit-io/guessit/issues/323 @@ -3115,11 +3128,11 @@ : episode: 9 episode_title: Episode Title season: 9 - format: HDTV + source: HDTV release_group: Group title: Show Name type: episode - video_codec: h264 + video_codec: H.264 video_encoder: x264 # https://github.com/guessit-io/guessit/issues/319 @@ -3138,13 +3151,13 @@ : title: Show Name season: 2 episode: 1 - episode_title: title + episode_title: eps2 part: 1 # not a big issue screen_size: 1080p - format: WEB-DL + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 container: mkv mimetype: video/x-matroska type: episode @@ -3173,8 +3186,8 @@ season: 6 episode: 5 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP type: episode @@ -3205,12 +3218,13 @@ episode: 6 episode_title: eps2 4 m4ster-s1ave aes screen_size: 1080p - format: WEBRip + source: Web streaming_service: Amazon Prime audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: GROUP type: episode @@ -3231,8 +3245,8 @@ season: 10 episode: 1 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP container: mkv @@ -3248,8 +3262,8 @@ season: 3 episode: 1 screen_size: 1080p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: GROUP container: mkv @@ -3264,8 +3278,8 @@ edition: Uncensored release_group: 'pseudo' screen_size: 1080p - format: BDRip - video_codec: h265 + source: BDRip + video_codec: H.265 video_encoder: x265 type: episode @@ -3290,8 +3304,8 @@ season: 13 episode: 22 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 release_group: NBY container: mkv @@ -3307,7 +3321,7 @@ season: 3 episode: 2 screen_size: 1080p - video_codec: h265 + video_codec: H.265 video_encoder: x265 type: episode @@ -3319,10 +3333,10 @@ episode: 1 episode_title: Super Title screen_size: 720p - format: WEB-DL + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 container: nzb release_group: AG type: episode @@ -3334,7 +3348,7 @@ season: 1 episode: 7 episode_title: Super, Title - format: WEB-DL + source: Web screen_size: 720p subtitle_language: pt-BR container: srt @@ -3347,9 +3361,9 @@ : title: Show Name season: 1 episode: 10 - video_codec: h264 + video_codec: H.264 video_encoder: x264 - format: WEB-DL + source: Web release_group: HI.C type: episode @@ -3359,7 +3373,7 @@ : title: Show Name season: 3 episode: 3 - format: TV + source: TV release_group: gRoUp container: mp4 mimetype: video/mp4 @@ -3384,9 +3398,10 @@ : title: Show Name season: 1 episode: 6 - format: DVDRip - video_codec: h264 + source: DVDRip + video_codec: H.264 video_encoder: x264 + other: Rip release_group: S4L type: episode @@ -3397,7 +3412,7 @@ episode: 31 episode_title: Episode 55 screen_size: 720p - format: HDTV + source: HDTV type: episode # Regression: HBO is not a release group @@ -3408,10 +3423,11 @@ episode_title: Chestbun screen_size: 720p streaming_service: HBO Go - format: WEBRip + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 + other: Rip type: episode # Regression: date is not detected when followed by a screen_size @@ -3420,10 +3436,11 @@ : title: Show Name date: 2016-10-21 screen_size: 1080p - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: group container: mkv mimetype: video/x-matroska @@ -3438,8 +3455,8 @@ container: mp4 proper_count: 1 proper_tag: REPACK - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 type: episode @@ -3450,8 +3467,8 @@ year: 2016 episode: 15 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 # not a big issue # episode_title: Mammoth Back from the Dead @@ -3467,8 +3484,8 @@ year: 2016 episode: 17 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 # not a big issue # episode_title: 9 11 The Longest War @@ -3482,10 +3499,10 @@ season: 1 episode: 6 screen_size: 720p - format: HDTV + source: HDTV audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: GrOuP container: mkv @@ -3504,36 +3521,50 @@ season: 4 episode: 6 language: fr - format: AHDTV - video_codec: XviD + source: Analog HDTV + video_codec: Xvid + type: episode + +# BD +? Show.Name.BD.720p +: title: Show Name + source: BDRip + screen_size: 720p type: episode # BDRip -? - Show.Name.BD.720p - - Show.Name.BDRip.720p +? - Show.Name.BDRip.720p - Show.Name.BD.Rip.720p - Show.Name.BD-Rip.720p : title: Show Name - format: BDRip + source: BDRip + other: Rip screen_size: 720p type: episode -# BDRip -? - Show.Name.BDMux.720p - - Show.Name.BDRipMux.720p +# BDMux +? Show.Name.BDMux.720p : title: Show Name - format: BDRip + source: BDRip other: Mux screen_size: 720p type: episode +# BDRipMux +? Show.Name.BDRipMux.720p +: title: Show Name + source: BDRip + other: [Rip, Mux] + screen_size: 720p + type: episode + # BluRay (BDRip negative scenario) ? - Show.Name.BD5.720p - Show.Name.BD9.720p - Show.Name.BD25.720p - Show.Name.BD50.720p : title: Show Name - format: BluRay + source: Blu-ray screen_size: 720p type: episode @@ -3542,26 +3573,42 @@ - Show.Name.BR.Rip.720p - Show.Name.BR-Rip.720p : title: Show Name - format: BRRip + source: BRRip screen_size: 720p + other: [Reencoded, Rip] type: episode -# BRRip -? - Show.Name.BRMux.720p - - Show.Name.BRRipMux.720p +# BRMux +? Show.Name.BRMux.720p : title: Show Name - format: BRRip - other: Mux + source: BRRip + other: ['Reencoded', 'Mux'] + screen_size: 720p + type: episode + +# BRRipMux +? Show.Name.BRRipMux.720p +: title: Show Name + other: ['Reencoded', 'Rip', 'Mux'] + source: BRRip screen_size: 720p type: episode -# DVB should be PDTV -? - Show Name S02E11 DVB - - Show Name S02E11 DVBRip +# Digital TV should be PDTV +? Show Name S02E11 DVB +: title: Show Name + source: PDTV + season: 2 + episode: 11 + type: episode + +# Digital TV should be PDTV +? Show Name S02E11 DVBRip : title: Show Name - format: PDTV + source: PDTV season: 2 episode: 11 + other: Rip type: episode # 2160p @@ -3582,8 +3629,8 @@ season: 12 episode: 1 date: 2016-11-16 - format: PDTV - video_codec: h264 + source: PDTV + video_codec: H.264 video_encoder: x264 container: mp4 type: episode @@ -3597,11 +3644,12 @@ episode: 1 screen_size: 2160p streaming_service: Amazon Prime - format: WEBRip - audio_codec: EAC3 + source: Web + audio_codec: Dolby Digital Plus audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: Group type: episode @@ -3613,11 +3661,12 @@ episode_title: Service screen_size: 1080p streaming_service: Amazon Prime - format: WEBRip - audio_codec: EAC3 + source: Web + audio_codec: Dolby Digital Plus audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip type: episode # Streaming service: Comedy Central @@ -3628,11 +3677,12 @@ edition: Extended screen_size: 1080p streaming_service: Comedy Central - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3646,11 +3696,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: The CW - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3661,11 +3712,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: ABC - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3674,10 +3726,11 @@ : title: Show Name screen_size: 720p streaming_service: History - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3688,10 +3741,11 @@ episode_title: Nice Title screen_size: 1080p streaming_service: PBS - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3702,11 +3756,12 @@ episode_title: Nice Title screen_size: 1080p streaming_service: SeeSo - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3718,11 +3773,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: Discovery - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: NTb type: episode @@ -3733,10 +3789,11 @@ episode_title: Nice Title streaming_service: BBC iPlayer screen_size: 720p - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3748,10 +3805,11 @@ episode_title: Nice Title screen_size: 720p streaming_service: A&E - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3763,10 +3821,11 @@ episode_title: Nice Title screen_size: 1080p streaming_service: Adult Swim - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3779,11 +3838,12 @@ episode: 3 screen_size: 1080p streaming_service: Netflix - format: WEBRip + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: NTb container: mkv mimetype: video/x-matroska @@ -3796,11 +3856,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: CBS - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3811,10 +3872,11 @@ episode_title: Team A vs Team B screen_size: 720p streaming_service: NBA TV - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3827,10 +3889,11 @@ part: 4 screen_size: 720p streaming_service: ePix - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 + other: Rip release_group: monkee type: episode @@ -3842,11 +3905,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: NBC - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3858,11 +3922,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: Syfy - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3874,11 +3939,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: Spike TV - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3890,11 +3956,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: IFC - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3906,11 +3973,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: National Geographic - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3922,11 +3990,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: NFL - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3938,11 +4007,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: UFC - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3954,11 +4024,12 @@ episode_title: Nice Title screen_size: 720p streaming_service: TV Land - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: group type: episode @@ -3968,11 +4039,12 @@ season: 1 screen_size: 1080p streaming_service: Crunchy Roll - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3982,11 +4054,12 @@ season: 1 screen_size: 1080p streaming_service: Disney - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -3996,11 +4069,12 @@ season: 1 screen_size: 1080p streaming_service: Nickelodeon - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -4010,11 +4084,12 @@ season: 1 screen_size: 1080p streaming_service: TFou - format: WEBRip + source: Web audio_codec: AAC audio_channels: '2.0' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: monkee type: episode @@ -4024,8 +4099,8 @@ season: 10 episode: 6 date: 2016-11-18 - format: PDTV - video_codec: XviD + source: PDTV + video_codec: Xvid type: episode # Regression: guessit issue #359 @@ -4033,10 +4108,10 @@ : title: Show Name season: 1 screen_size: 720p - format: HDTV + source: HDTV audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 release_group: Group episode: 5 @@ -4050,8 +4125,8 @@ episode: [476, 477, 478, 479] year: 2007 release_group: HorribleSubs - format: WEBRip - other: HD + source: Web + other: [Rip, HD] screen_size: 720p type: episode @@ -4062,8 +4137,8 @@ year: 2016 release_group: RH language: en - format: WEBRip - other: HD + source: Web + other: [Rip, HD] screen_size: 1080p type: episode @@ -4073,8 +4148,8 @@ episode: 10 year: 2016 release_group: HorribleSubs - format: WEBRip - other: HD + source: Web + other: [Rip, HD] screen_size: 720p type: episode @@ -4082,11 +4157,12 @@ : title: Show Name season: 1 screen_size: 720p - format: WEBRip + source: Web audio_codec: AC3 audio_channels: '5.1' - video_codec: h264 + video_codec: H.264 video_encoder: x264 + other: Rip release_group: MiNiGRiP type: episode @@ -4096,7 +4172,7 @@ year: 2016 season: 1 episode: 2 - format: HDTV + source: HDTV subtitle_language: es release_group: SC type: episode @@ -4105,8 +4181,8 @@ : title: Show Name season: 1 episode: 2 - format: HDTV - video_codec: XviD + source: HDTV + video_codec: Xvid release_group: 2HD screen_size: 720p type: episode @@ -4118,18 +4194,20 @@ episode: 722 other: HD screen_size: 720p + aspect_ratio: '1.778' container: mp4 mimetype: video/mp4 type: episode -# TODO: Fix anime release group ? "[Zero-Raws].Show.Name.493-498.&.500-507.(CX.1280x720.VFR.x264.AAC)" : title: Show Name absolute_episode: [493, 494, 495, 496, 497, 498, 500, 501, 502, 503, 504, 505, 506, 507] - episode: [500, 501, 502, 503, 504, 505, 506, 507] + episode: [493, 494, 495, 496, 497, 498, 500, 501, 502, 503, 504, 505, 506, 507] screen_size: 720p - release_group: VFR - video_codec: h264 + release_group: Zero-Raws + aspect_ratio: '1.778' + subtitle_language: fr + video_codec: H.264 video_encoder: x264 audio_codec: AAC type: episode @@ -4140,9 +4218,10 @@ episode: 5 absolute_episode: 5 screen_size: 720p - video_profile: 10bit - other: DualAudio - format: TV + color_depth: 10-bit + other: Dual Audio + source: TV + video_profile: High 10 language: und crc32: EDA6E7F1 type: episode @@ -4152,9 +4231,10 @@ season: 7 episode: 13 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 + other: Obfuscated release_group: AVS uuid: 1e5e2f3464df439b92afea14932a87a4 type: episode @@ -4164,27 +4244,26 @@ season: 7 episode: 13 screen_size: 720p - format: HDTV - video_codec: h264 + source: HDTV + video_codec: H.264 video_encoder: x264 + other: Obfuscated release_group: AVS uuid: 1e5e2f3464df439b92afea14932a87a4 type: episode -# TODO: Guessit 3 to handle HDR, BT2020 and more ? Doctor.Estraño.HDR.VISIONPLUS.1000.[4K.UHD.2160p.HEVC.X265][BT2020][DTS-5.1.Castellano.DTS-HD.7.1-Ingles+Subs][ES-EN].x264-NEWPCT -: title: Doctor Estraño HDR VISIONPLUS +: title: Doctor Estraño absolute_episode: 1000 episode: 1000 screen_size: 2160p - other: [UltraHD, HD] - video_codec: [h265, h264] + other: [HDR10, Ultra HD, BT.2020] + video_codec: [H.265, H.264] video_encoder: [x265, x264] - audio_codec: DTS + audio_codec: [DTS, DTS-HD] audio_channels: ['5.1', '7.1'] language: ca - audio_profile: HD - subtitle_language: [es, en] + subtitle_language: [und, es, en] release_group: NEWPCT type: episode @@ -4194,7 +4273,7 @@ episode: 76 absolute_episode: 76 screen_size: 1080p - format: BluRay + source: Blu-ray release_group: Yomi container: mkv type: episode @@ -4204,7 +4283,28 @@ : title: Show Name season: 6 screen_size: 480p - video_codec: h264 + video_codec: H.264 release_group: 20-40 - format: WEB-DL + source: Web + type: episode + +? /Comedy 23/Funny.Show.S4E19.mkv +: title: Funny Show + season: 4 + episode: 19 + container: mkv + mimetype: video/x-matroska + type: episode + +? shes.gotta.have.it.s01e08.720p.web.x264-strife.mkv +: title: shes gotta have it + season: 1 + episode: 8 + screen_size: 720p + source: Web + video_codec: H.264 + video_encoder: x264 + release_group: strife + container: mkv + mimetype: video/x-matroska type: episode diff --git a/tests/test_release_refiner.py b/tests/test_release_refiner.py index 66c811c372..a6a3d72375 100644 --- a/tests/test_release_refiner.py +++ b/tests/test_release_refiner.py @@ -18,10 +18,10 @@ def data(): 'episode': 2, 'title': 'Episode Title', 'year': 2012, - 'format': 'HDTV', + 'source': 'HDTV', 'resolution': '1080p', 'release_group': 'Group', - 'video_codec': 'h265', + 'video_codec': 'H.265', 'audio_codec': 'AC3' }, 'another_release_name': 'Different.Show.2013.S03E04.Another.Episode.720p.BluRay.x264-NoGroup', @@ -32,7 +32,7 @@ def data(): 'episode': 2, 'title': None, 'year': None, - 'format': None, + 'source': None, 'resolution': None, 'release_group': None, 'video_codec': None, @@ -48,7 +48,7 @@ def _to_properties(video): 'episode': video.episode, 'title': video.title, 'year': video.year, - 'format': video.format, + 'source': video.source, 'resolution': video.resolution, 'release_group': video.release_group, 'video_codec': video.video_codec, diff --git a/tests/test_tvepisode_refiner.py b/tests/test_tvepisode_refiner.py index b924b371b6..fc7455cadc 100644 --- a/tests/test_tvepisode_refiner.py +++ b/tests/test_tvepisode_refiner.py @@ -29,7 +29,7 @@ def data(create_tvshow, create_tvepisode): 'episode': tvepisode.episode, 'title': tvepisode.name, 'resolution': '1080p', - 'format': 'BluRay', + 'source': 'Blu-ray', 'release_group': tvepisode.release_group, 'size': tvepisode.file_size, 'tvdb_id': tvepisode.tvdb_id, @@ -42,7 +42,7 @@ def data(create_tvshow, create_tvepisode): 'title': None, 'year': None, 'resolution': None, - 'format': None, + 'source': None, 'release_group': None, 'size': None, 'series_tvdb_id': None, @@ -60,7 +60,7 @@ def _to_properties(video): 'title': video.title, 'year': video.year, 'resolution': video.resolution, - 'format': video.format, + 'source': video.source, 'size': video.size, 'release_group': video.release_group, 'series_tvdb_id': video.series_tvdb_id, @@ -114,11 +114,11 @@ def test_refine__with_tvepisode_not_overwriting_resolution_format_and_release_gr # Given video = data['video'] video.resolution = '720p' - video.format = 'HDTV' + video.source = 'HDTV' video.release_group = 'AnotherGroup' tvepisode = data['tvepisode'] expected = dict(data['tvshow_properties'], **data['tvepisode_properties']) - expected = dict(expected, resolution=video.resolution, format=video.format, release_group=video.release_group, + expected = dict(expected, resolution=video.resolution, source=video.source, release_group=video.release_group, season=video.season, episode=video.episode) # When