diff --git a/pythonbits/bb.py b/pythonbits/bb.py index a02f893..54ddf99 100644 --- a/pythonbits/bb.py +++ b/pythonbits/bb.py @@ -24,7 +24,8 @@ from .submission import (Submission, form_field, finalize, SubmissionAttributeError) from .tracker import Tracker -from .scene import is_scene_crc, query_scene_fname +from . import scene +from . import prompt def format_tag(tag): @@ -76,28 +77,48 @@ def submit(payload): t = Tracker() return t.upload(**payload) - @form_field('scene', 'checkbox') - def _render_scene(self): - # todo: if path is directory, choose file for crc - path = os.path.normpath(self['path']) # removes trailing slash - try: - try: - if os.path.exists(path) and not os.path.isdir(path): - return is_scene_crc(path) - except KeyboardInterrupt: - sys.stdout.write('...skipped\n') - - query_scene_fname(path) - except HTTPError as e: - log.notice(e) + # TODO: These should be detected as scene releases and produce an error message + # because they must be in a directory named after the release: - while True: - choice = input('Is this a scene release? [y/N] ') + # voa-the_omega_man_x264_bluray.mkv -> The.Omega.Man.1971.1080p.BluRay.x264-VOA/voa-the_omega_man_x264_bluray.mkv + # hd1080-wtl.mkv -> Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080/hd1080-wtl.mkv - if not choice or choice.lower() == 'n': - return False - elif choice.lower() == 'y': - return True + @form_field('scene', 'checkbox') + def _render_scene(self): + def ask_user(): + return prompt.yesno('Is this a scene release?', default=False) + + def handle_error(filepath, error): + log.error(str(error)) + + path = self['path'] + modified = scene.check_integrity(path, on_error=handle_error) + # modified is True, False or None (unknown) + if modified is False: + return True + elif modified is True: + if prompt.yesno('Abort?', default=True): + # The return statement is there because sys.exit() is mocked in tests. + log.debug('Aborting') + return sys.exit(1) + else: + log.debug('Asking user') + return ask_user() + + # Check if release was renamed + release_names = scene.release_names(path) + if not release_names: + return False + elif release_names: + print('Existing releases:') + for release_name in release_names: + print(' * {}'.format(release_name)) + log.error('This release was very likely modified and should not be uploaded like this.') + if prompt.yesno('Abort?', default=True): + # The return statement is there because sys.exit() is mocked in tests. + return sys.exit(1) + else: + return ask_user() def data_method(self, source, target): def copy(source, target): diff --git a/pythonbits/prompt.py b/pythonbits/prompt.py new file mode 100644 index 0000000..5583cde --- /dev/null +++ b/pythonbits/prompt.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + + +def yesno(question, default): + while True: + choices = '[Y/n]' if default else '[y/N]' + choice = input('%s %s ' % (question, choices)) + if not choice: + return default + elif choice.casefold() == 'y': + return True + elif choice.casefold() == 'n': + return False diff --git a/pythonbits/scene.py b/pythonbits/scene.py index 90345e6..6f6618c 100644 --- a/pythonbits/scene.py +++ b/pythonbits/scene.py @@ -1,81 +1,382 @@ # -*- coding: utf-8 -*- import os import requests -import progressbar from base64 import b64decode -from zlib import crc32 +from bs4 import BeautifulSoup +import re +import guessit +import functools +import pprint from .logging import log + srrdb = b64decode('aHR0cHM6Ly9zcnJkYi5jb20v').decode('utf8') -def check_scene_rename(fname, release): - release_url = srrdb + "release/details/{}".format(release) - r = requests.get(release_url) - - if fname not in r.text: - log.warning('Possibly renamed scene file!\n' - '\tFilename {}\n\tnot found at {}', - fname, release_url) - - -def crc(path): - log.debug('Calculating CRC32 value') - checksum = 0 - fsize = os.path.getsize(path) - i = 0 - chunk_size = 4 * 2**20 - with open(path, 'rb') as f: - with progressbar.DataTransferBar(max_value=fsize, - max_error=False) as bar: - while True: - i += 1 - data = f.read(chunk_size) - if not data: - return checksum & 0xFFFFFFFF - - bar.update(i*chunk_size) - checksum = crc32(data, checksum) - - -def is_scene_crc(path): - checksum = crc(path) - log.debug('CRC32 {:08X}', checksum) - r = requests.get(srrdb + 'api/search/archive-crc:%08X' % checksum) - r.raise_for_status() - - scene = int(r.json()['resultsCount']) != 0 - if int(r.json()['resultsCount']) > 1: - log.warning('More than one srrDB result for CRC32 query') - log.info('Scene checkbox set to {} ' - 'due to CRC query result'.format(scene)) - - if scene: - release = r.json()['results'][0]['release'] - fname = os.path.basename(path) - check_scene_rename(fname, release) - - return scene - - -def query_scene_fname(path): - if os.path.isfile(path): - query = os.path.splitext(os.path.basename(path))[0] - elif os.path.isdir(path): - query = os.path.basename(path) - elif not os.path.exists(path): - raise FileNotFoundError('File or directory not found: %s' % (path,)) +class SceneError(Exception): + pass + + +class APIError(Exception): + pass + + +# FIXME: "hd1080-wtl.mkv" (from Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080) +# should report an error, but it's not found on any scene indexers. + + +def check_integrity(path, on_error=None): + """ + Check if `path` (file or directory) was modified + + Files that are not part of a scene release are ignored. + + Return True/False if this release was (not) modified or None if not sure. + """ + errors_found = False + something_found = False + if _isdir(path): + dirname = os.path.basename(path) else: - raise Exception('wat') + dirname = '' + log.debug('Base path for {}: {}', path, dirname) + + guess = _guessit(path) + if 'release_group' not in guess: + log.debug('No release group found - cannot find scene release: {}', guess) + return None + + try: + if _isdir(path): + try: + _check_dir(path) + except SceneError as e: + errors_found = True + something_found = True + if on_error is not None: + on_error(dirname, e) + else: + raise + + for info in _yield_file_info(path): + log.debug('Scene info: {}', info) + # Allow mixed scene/non-scene releases by only checking known scene releases + if info['size'] and info['crc']: + something_found = True + relpath = os.path.join(dirname, info['filename']) + if dirname: + fspath = os.path.join(path, info['filename']) + else: + fspath = path + log.debug('Torrent path: {}', relpath) + log.debug('File system path: {}', fspath) + try: + _check_file(relpath, fspath, info) + except SceneError as e: + errors_found = True + if on_error is not None: + on_error(relpath, e) + else: + raise + except APIError as e: + # Connection failed; we can't tell + log.debug('Ignoring error: {}', e) + if on_error is not None: + on_error(dirname or os.path.basename(path), e) + else: + raise + else: + log.debug('Something found: {}', something_found) + log.debug('Errors found: {}', errors_found) + if something_found: + return errors_found + + +def _check_dir(path): + """ + Return True if `path` was not modified or None if not sure - # full search (slow) - r = requests.get(srrdb + "api/search/{}".format(query)) - r.raise_for_status() - results = r.json()['results'] + Raise SceneError if `path` does not match scene release + """ + try: + release_name, files = get_details(path) + except APIError: + return None + log.debug('Checking directory: {}', path) + log.debug('release_name: {}', release_name) + log.debug('files: {}', files) + if files: + basename = _get_basename_noext(path) + log.debug('Base name should be {}: {}', release_name, basename) + if release_name != basename: + raise SceneError('%s was renamed to %s' % (release_name, basename)) + else: + return True - if results: - print('Found srrDB results for filename:') - print("\t" + "\n".join(r['release'] for r in results)) + +def _check_file(relpath, fspath, info): + """ + Return True if file was not renamed and has the correct size + + relpath: Relative path that starts with the release name + fspath: Path that exists in the file system + info: Dictionary from _yield_file_info() + + Raise SceneError if `path` does not match `info` + """ + log.debug('Checking file: {}: {}', relpath, fspath) + log.debug('Info: {}', info) + + if info['release_name'] is None: + log.debug('No info to check') + return None + + release_type = 'file' if relpath == os.path.basename(relpath) else 'directory' + log.debug('Release is {}', release_type) + + # File release names are identical to file name sans extension. + scene_release_type = 'file' if info['release_name'] == _get_basename_noext(info['filename']) else 'directory' + log.debug('Scene release is {}', scene_release_type) + + if scene_release_type == 'file': + # Scene released file so we don't care about our own directory name + filename = os.path.basename(fspath) + exp_filenames = (info['filename'],) + log.debug('Existing filename: {}', filename) + log.debug('Expected filename: {}', exp_filenames) + if filename not in exp_filenames: + raise SceneError('%s was renamed to %s' % (exp_filenames[0], filename)) else: - print('No results found in srrDB for query "{}"'.format(query)) + # Scene released directory + if release_type == 'file': + # Don't check directory name + filename = os.path.basename(fspath) + exp_filenames = (info['filename'], + info['release_name'] + '.mkv') + else: + # Check full internal/relative path + filename = os.path.join(os.path.basename(os.path.dirname(fspath)), + os.path.basename(fspath)) + exp_filenames = (os.path.join(info['release_name'], info['filename']),) + log.debug('Existing filename: {}', filename) + log.debug('Expected filename: {}', exp_filenames) + if filename not in exp_filenames: + raise SceneError('%s was renamed to %s' % (exp_filenames[0], filename)) + + if not _path_exists(fspath): + raise SceneError('%s: Missing file' % (fspath,)) + + try: + filesize = _path_getsize(fspath) + except OSError as e: + raise SceneError('%s: Unable to get file size: %s' % (fspath, e.strerror)) + log.debug('File size of {}: {} bytes', fspath, filesize) + if filesize != info['size']: + raise SceneError('%s: Wrong size: %s instead of %s bytes' % + (info['filename'], filesize, info['size'])) + + return True + + +def release_names(path): + """ + Get release information from guess it. If we know the title, release group and year or season + Search for release title, resolution, release_group and season/episode or year. If the + last segment in `path` is not in the results, return them. Otherwise return an empty + list. + """ + guess = _guessit(path) + # If we don't have enough information, don't bother searching. + log.debug('Guess: {}', guess) + if 'release_group' not in guess or 'title' not in guess: + return [] + + log.debug('Looking for release names matching: {}', guess) + results = search(guess) + if not results and 'season' in guess and 'episode' in guess: + # Try again, search for season pack + guess.pop('episode', None) + log.debug('Looking for release names matching: {}', guess) + results = search(guess) + return results + + +def search(guess): + """ + Search for scene releases + + guess: Dictionary from guessit.guessit() + + Return a list of release names + """ + log.debug('Searching for {}', guess) + # Make search query + query = list(guess['title'].split(' ')) + # Use guess.get(...) to ignore non-existing values as well as None and "" + if guess.get('release_group'): + query.append('group:' + guess['release_group']) + if guess.get('other'): + query.append(guess['other']) + if guess.get('screen_size'): + query.append(guess['screen_size']) + if guess.get('type') == 'movie': + if guess.get('year'): + query.append(guess['year']) + elif guess.get('type') == 'episode': + episode_info = [] + if guess.get('season'): + episode_info.append('S%02d' % (guess['season'],)) + if guess.get('episode'): + episode_info.append('E%02d' % (guess['episode'],)) + if episode_info: + query.append(''.join(episode_info)) + + query_str = '/'.join(str(q) for q in query) + + # Make request + try: + r = _get("api/search/" + query_str) + except APIError: + return [] + + # Parse response + try: + json = r.json() + except ValueError: + log.debug('Invalid JSON: {}', r.text) + else: + log.debug('Scene search result:\n{}', pprint.pformat(json)) + if json.get('results'): + return [r['release'] for r in json['results']] + return [] + + +def get_details(path): + """ + Find release info for file or directory at `path` + + Return the release name and a dictionary that maps file names to dictionaries with the + keys "release_name", "filename", "size" and "crc". + """ + r = _get('api/details/' + _get_basename_noext(path)) + # log.debug('Response:\n{}', r.text) + try: + json = r.json() + except ValueError: + # The API fixes our release name by capitalizing it correctly, removing file + # extension, etc and redirecting us to the releases web page. Try to find the + # correct release name in the HTML and make another API request with that. + log.debug('Finding real release name in HTML:') + soup = BeautifulSoup(r.text, features="html.parser") + # log.debug(soup.prettify()) + release_name_tag = soup.find(id='release-name') + if release_name_tag is not None: + release_name = release_name_tag.get('value') + if release_name: + log.debug('Found correct release name: {}', release_name) + return get_details(release_name) + else: + log.debug('Getting info from JSON:') + files = json.get('archived-files', []) + files_sorted = sorted(files, key=lambda f: f['name'].casefold()) + return json['name'], {f['name']: {'release_name': json['name'], + 'filename': f['name'], + 'size': f['size'], + 'crc': f['crc']} + for f in files_sorted} + return '', {} + + +def _yield_file_info(path): + """ + For each file in `path` yield a dictionary with the keys "release_name", "filename", + "size" and "crc" + + If no info can be found, all values except for "filename" are `None` and "filename" is + taken from `path` instead of the info returned by `get_details`. + + Raise APIError in case of connection or file system error. + """ + # Cover the following cases: + # - path is directory (season) and scene released directory + # - path is directory and scene released individual file (episodes) + # - path is file and scene released individual file + # - path is file and scene released directory + _, files = get_details(path) + + def default(filepath): + return {'release_name': None, 'filename': os.path.basename(filepath), 'size': None, 'crc': None} + + if files: + # Scene release is the same as this release (season pack or single episode) + yield from files.values() + + elif not _isdir(path): + # path is episode and scene release is season pack + log.debug('Looking for episode from season pack') + guess = _guessit(path) + # Try to find whole season if we searched for single episode + if 'release_group' in guess and 'season' in guess and 'episode' in guess: + guess.pop('episode', None) + results = search(guess) + # If we find the exact season, pick episode info + if len(results) == 1: + _, files = get_details(results[0]) + yield files.get(os.path.basename(path), default(path)) + else: + yield default(path) + else: + yield default(path) + + else: + log.debug('Making season pack from individual episodes') + # path is season and scene released single episodes + try: + files = _os_listdir(path) + except OSError as e: + raise APIError('%s: %s' % (path, e.strerror)) + else: + log.debug('Found files:', files) + for filename in sorted(files): + _, files = get_details(filename) + yield files.get(filename, default(filename)) + + +@functools.lru_cache() +def _guessit(filepath): + release_name = os.path.basename(filepath) + if release_name.islower(): + match = re.search(r'^([a-z0-9]+)-(.+)\.([a-z0-9]{1,3})$', release_name) + if match: + release_name = '%s-%s.%s' % (match.group(2), match.group(1), match.group(3)) + return dict(guessit.guessit(release_name)) + + +@functools.lru_cache() +def _get(path): + url = srrdb + path + log.debug('Requesting URL: {}', url) + try: + return requests.get(url) + except requests.RequestException as e: + log.debug('Request failed: {}', e) + raise APIError(e) + + +def _get_basename_noext(path): + # os.path.splitext() removes anything after the rightmost "." which is no good for + # scene release names. + return re.sub(r'\.[a-z0-9]{1,3}$$', '', os.path.basename(path)) + + +def _isdir(path): + # Not using system calls makes testing easier and just looking for file extension + # should work pretty much always. + return not bool(re.search(r'\.[a-zA-Z0-9]{1,3}$', os.path.basename(path))) + + +# Allow patching in texts without side effects. +_path_exists = os.path.exists +_path_getsize = os.path.getsize +_os_listdir = os.listdir diff --git a/setup.py b/setup.py index 8ec411e..e222299 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,7 @@ def find_version(*file_paths): "logbook~=1.2", "pyreadline~=2.1", "progressbar2~=3.38", + "beautifulsoup4~=4.9", ], python_requires=">=3.5,<4.0", tests_require=['tox', 'pytest', 'flake8'], diff --git a/tests/scene_responses/api_details_12 rounds.reloaded.2013.1080p.bluray.x264-rovers.response b/tests/scene_responses/api_details_12 rounds.reloaded.2013.1080p.bluray.x264-rovers.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS.response b/tests/scene_responses/api_details_12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS.response new file mode 100644 index 0000000..8f3dd5f --- /dev/null +++ b/tests/scene_responses/api_details_12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS.response @@ -0,0 +1 @@ +{"name":"12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS","files":[{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.nfo","size":5400,"crc":"22B0C584"},{"name":"Proof\/12.rounds.reloaded.2013.1080p.bluray.x264-rovers.proof.jpg","size":3810735,"crc":"FEF4344D"},{"name":"Sample\/12.rounds.reloaded.2013.1080p.bluray.x264-rovers.sample.mkv","size":71743141,"crc":"4540D966"},{"name":"Subs\/12.rounds.reloaded.2013.1080p.bluray.x264-rovers.subs.rar","size":4602299,"crc":"D4BB0CC4"},{"name":"Subs\/12.rounds.reloaded.2013.1080p.bluray.x264-rovers.subs.sfv","size":68,"crc":"82AA528E"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.sfv","size":4473,"crc":"82A6BD59"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.rar","size":100000000,"crc":"52E3890D"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r00","size":100000000,"crc":"757269B9"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r01","size":100000000,"crc":"D919BE59"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r02","size":100000000,"crc":"F30146C0"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r03","size":100000000,"crc":"602E8C5B"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r04","size":100000000,"crc":"90C7365F"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r05","size":100000000,"crc":"BE85054C"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r06","size":100000000,"crc":"EB33198B"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r07","size":100000000,"crc":"E4CB58AC"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r08","size":100000000,"crc":"DEDBA13F"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r09","size":100000000,"crc":"9B2A7FD8"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r10","size":100000000,"crc":"6163D203"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r11","size":100000000,"crc":"485049A4"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r12","size":100000000,"crc":"DA8686DD"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r13","size":100000000,"crc":"2068F66E"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r14","size":100000000,"crc":"B7076821"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r15","size":100000000,"crc":"CE92CACF"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r16","size":100000000,"crc":"B66A5439"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r17","size":100000000,"crc":"4C31D7C7"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r18","size":100000000,"crc":"D64FB681"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r19","size":100000000,"crc":"D7CC6CF9"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r20","size":100000000,"crc":"312B1125"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r21","size":100000000,"crc":"D9FA2B12"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r22","size":100000000,"crc":"D5177D64"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r23","size":100000000,"crc":"F713DC2C"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r24","size":100000000,"crc":"2984FAEB"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r25","size":100000000,"crc":"DA143F05"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r26","size":100000000,"crc":"FD12BC74"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r27","size":100000000,"crc":"B49CAE47"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r28","size":100000000,"crc":"7DAB6892"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r29","size":100000000,"crc":"69E149F6"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r30","size":100000000,"crc":"C4069A0F"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r31","size":100000000,"crc":"77D1E410"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r32","size":100000000,"crc":"06192ED4"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r33","size":100000000,"crc":"E18A1302"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r34","size":100000000,"crc":"74C3A397"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r35","size":100000000,"crc":"A03FFF8C"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r36","size":100000000,"crc":"4ECDA98B"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r37","size":100000000,"crc":"78E32A87"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r38","size":100000000,"crc":"082F0074"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r39","size":100000000,"crc":"0C609FE6"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r40","size":100000000,"crc":"C176342D"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r41","size":100000000,"crc":"CB5A543C"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r42","size":100000000,"crc":"60FE8B7E"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r43","size":100000000,"crc":"CD54DEBB"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r44","size":100000000,"crc":"3ABF4FE9"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r45","size":100000000,"crc":"5E71B5B4"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r46","size":100000000,"crc":"CE0C2098"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r47","size":100000000,"crc":"676D6D65"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r48","size":100000000,"crc":"9D525033"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r49","size":100000000,"crc":"481D6B88"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r50","size":100000000,"crc":"21BDE9E1"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r51","size":100000000,"crc":"3CA0ED33"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r52","size":100000000,"crc":"23630486"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r53","size":100000000,"crc":"E7D08129"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r54","size":100000000,"crc":"8F98C957"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r55","size":100000000,"crc":"CEC04178"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r56","size":100000000,"crc":"E6E859E6"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r57","size":100000000,"crc":"9ECA210E"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r58","size":100000000,"crc":"E24CF488"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r59","size":100000000,"crc":"E36B4D89"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r60","size":100000000,"crc":"77C582EB"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r61","size":100000000,"crc":"4DBDB3D0"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r62","size":100000000,"crc":"D2F83E80"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r63","size":100000000,"crc":"09451974"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r64","size":100000000,"crc":"65B4ECA8"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r65","size":100000000,"crc":"38DA416B"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r66","size":100000000,"crc":"C39ADA3F"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r67","size":100000000,"crc":"70FBB9B6"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r68","size":100000000,"crc":"776C13E1"},{"name":"12.rounds.reloaded.2013.1080p.bluray.x264-rovers.r69","size":37070832,"crc":"4F5EA88F"}],"archived-files":[{"name":"12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS.mkv","size":7037061105,"crc":"8EB4C867"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..1d0f250 --- /dev/null +++ b/tests/scene_responses/api_details_Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT.response @@ -0,0 +1 @@ +{"name":"Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT","files":[{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.nfo","size":9661,"crc":"5FC023C0"},{"name":"Sample\/bored.to.death.s01.extras.720p.bluray.x264-ingot.sample.mkv","size":45583011,"crc":"7B822E59"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.sfv","size":2016,"crc":"BC37A6D9"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.rar","size":50000000,"crc":"5D2EDF71"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r00","size":50000000,"crc":"BFEC2725"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r01","size":50000000,"crc":"F793EE26"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r02","size":50000000,"crc":"17D8772C"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r03","size":50000000,"crc":"B40E403B"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r04","size":50000000,"crc":"03E5B11D"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r05","size":50000000,"crc":"764F7BA4"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r06","size":50000000,"crc":"B718D156"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r07","size":50000000,"crc":"C7D3E81F"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r08","size":50000000,"crc":"CA6D2A99"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r09","size":50000000,"crc":"65C3EFDB"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r10","size":50000000,"crc":"42BAE872"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r11","size":50000000,"crc":"03E2DBE2"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r12","size":50000000,"crc":"E6C6B0F4"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r13","size":50000000,"crc":"25151B6E"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r14","size":50000000,"crc":"9D7EEEE5"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r15","size":50000000,"crc":"0C1DA53E"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r16","size":50000000,"crc":"BAFD0932"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r17","size":50000000,"crc":"8717D3EE"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r18","size":50000000,"crc":"87A9C45D"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r19","size":50000000,"crc":"E906DBAB"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r20","size":50000000,"crc":"5B717CB2"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r21","size":50000000,"crc":"66667D9B"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r22","size":50000000,"crc":"DE738AFA"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r23","size":50000000,"crc":"9629BB7D"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r24","size":50000000,"crc":"9ABE918C"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r25","size":50000000,"crc":"CA6B3445"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r26","size":50000000,"crc":"D89C4380"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r27","size":50000000,"crc":"D9E1B763"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r28","size":50000000,"crc":"E2D6B514"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r29","size":50000000,"crc":"3F51A592"},{"name":"bored.to.death.s01.extras.720p.bluray.x264-ingot.r30","size":31018792,"crc":"735D3CAE"}],"archived-files":[{"name":"Bored.to.Death.S01.Jonathan.Amess.Brooklyn.720p.BluRay.x264-iNGOT.mkv","size":518652629,"crc":"497277ED"},{"name":"Bored.to.Death.S01.Making.of.720p.BluRay.x264-iNGOT.mkv","size":779447228,"crc":"8C8C0AE7"},{"name":"Bored.to.Death.S01E03.Deleted.Scene.720p.BluRay.x264-iNGOT.mkv","size":30779540,"crc":"0ECBEBE8"},{"name":"Bored.to.Death.S01E04.Deleted.Scene.720p.BluRay.x264-iNGOT.mkv","size":138052914,"crc":"E4E41C29"},{"name":"Bored.to.Death.S01E08.Deleted.Scene.1.720p.BluRay.x264-iNGOT.mkv","size":68498554,"crc":"085C6946"},{"name":"Bored.to.Death.S01E08.Deleted.Scene.2.720p.BluRay.x264-iNGOT.mkv","size":45583011,"crc":"7B822E59"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01.Jonathan.Amess.Brooklyn.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01.Jonathan.Amess.Brooklyn.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01.Making.of.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01.Making.of.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01E03.Deleted.Scene.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01E03.Deleted.Scene.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01E04.Deleted.Scene.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01E04.Deleted.Scene.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01E08.Deleted.Scene.1.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01E08.Deleted.Scene.1.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Bored.to.Death.S01E08.Deleted.Scene.2.720p.BluRay.x264-iNGOT.response b/tests/scene_responses/api_details_Bored.to.Death.S01E08.Deleted.Scene.2.720p.BluRay.x264-iNGOT.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Damnation.S01.720p.AMZN.WEB-DL.DDP5.1.H.264-AJP69.response b/tests/scene_responses/api_details_Damnation.S01.720p.AMZN.WEB-DL.DDP5.1.H.264-AJP69.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Damnation.S01E03.One.Penny.720p.AMZN.WEB-DL.DD+5.1.H.264-AJP69.response b/tests/scene_responses/api_details_Damnation.S01E03.One.Penny.720p.AMZN.WEB-DL.DD+5.1.H.264-AJP69.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..23e78ad --- /dev/null +++ b/tests/scene_responses/api_details_Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD.response @@ -0,0 +1 @@ +{"name":"Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD","files":[{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.nfo","size":6024,"crc":"2BCB1C7C"},{"name":"Proof\/fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.proof.jpg","size":132556,"crc":"1B25A106"},{"name":"Sample\/fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.sample.mkv","size":64895080,"crc":"C4AEDC57"},{"name":"Subs\/fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.subs.rar","size":1436125,"crc":"69DC91C0"},{"name":"Subs\/fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.subs.sfv","size":69,"crc":"F0EB0D53"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.sfv","size":3008,"crc":"BA225C68"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.rar","size":50000000,"crc":"FAABAA0E"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r00","size":50000000,"crc":"78518B4F"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r01","size":50000000,"crc":"6DAE2648"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r02","size":50000000,"crc":"885018D7"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r03","size":50000000,"crc":"4D96679C"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r04","size":50000000,"crc":"BC6A7099"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r05","size":50000000,"crc":"D8033B36"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r06","size":50000000,"crc":"796180CF"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r07","size":50000000,"crc":"0DEF3A3E"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r08","size":50000000,"crc":"B91B6E0A"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r09","size":50000000,"crc":"30B9DFAC"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r10","size":50000000,"crc":"D3C1DC71"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r11","size":50000000,"crc":"87EEEB17"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r12","size":50000000,"crc":"B72DF7AA"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r13","size":50000000,"crc":"98599B96"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r14","size":50000000,"crc":"41B41202"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r15","size":50000000,"crc":"0A566C30"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r16","size":50000000,"crc":"32388121"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r17","size":50000000,"crc":"F0CBED55"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r18","size":50000000,"crc":"A1AC0873"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r19","size":50000000,"crc":"19CA1E6F"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r20","size":50000000,"crc":"CF00D162"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r21","size":50000000,"crc":"142CF26F"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r22","size":50000000,"crc":"7E58CC8E"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r23","size":50000000,"crc":"DBC51F24"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r24","size":50000000,"crc":"E62772BF"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r25","size":50000000,"crc":"E2AFC069"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r26","size":50000000,"crc":"655EBCD3"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r27","size":50000000,"crc":"19AB9CE0"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r28","size":50000000,"crc":"3DACAF2D"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r29","size":50000000,"crc":"EF86BA0D"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r30","size":50000000,"crc":"3B1D3E24"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r31","size":50000000,"crc":"D7B6591C"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r32","size":50000000,"crc":"94639D03"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r33","size":50000000,"crc":"ACCC1133"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r34","size":50000000,"crc":"65C1B0B2"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r35","size":50000000,"crc":"30A51990"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r36","size":50000000,"crc":"F7C418D9"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r37","size":50000000,"crc":"4D451CEF"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r38","size":50000000,"crc":"AF7DD283"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r39","size":50000000,"crc":"AC8CC3F6"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r40","size":50000000,"crc":"60532E1D"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r41","size":50000000,"crc":"D96A7C17"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r42","size":50000000,"crc":"9A61AB95"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r43","size":50000000,"crc":"B2AAF6B7"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r44","size":50000000,"crc":"9410CC93"},{"name":"fawlty.towers.s01e01.1080p.bluray.x264-shortbrehd.r45","size":42668734,"crc":"E1E81D07"}],"archived-files":[{"name":"Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD.mkv","size":2342662389,"crc":"95042F83"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..c97674e --- /dev/null +++ b/tests/scene_responses/api_details_Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD.response @@ -0,0 +1 @@ +{"name":"Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD","files":[{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.nfo","size":6024,"crc":"7F289228"},{"name":"Proof\/fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.proof.jpg","size":132556,"crc":"1B25A106"},{"name":"Sample\/fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.sample.mkv","size":104016055,"crc":"1121F745"},{"name":"Subs\/fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.subs.rar","size":1468376,"crc":"A9F0324C"},{"name":"Subs\/fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.subs.sfv","size":69,"crc":"7202B623"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.sfv","size":3008,"crc":"988D4C4E"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.rar","size":50000000,"crc":"EA877519"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r00","size":50000000,"crc":"F18895F5"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r01","size":50000000,"crc":"2DA5F9F3"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r02","size":50000000,"crc":"1BFC3074"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r03","size":50000000,"crc":"0191B7FB"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r04","size":50000000,"crc":"924EFE2F"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r05","size":50000000,"crc":"D9A34689"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r06","size":50000000,"crc":"84681F38"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r07","size":50000000,"crc":"EFD83BDB"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r08","size":50000000,"crc":"CF701C23"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r09","size":50000000,"crc":"5F976555"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r10","size":50000000,"crc":"DB002D93"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r11","size":50000000,"crc":"CB9A502E"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r12","size":50000000,"crc":"9B0FF6FF"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r13","size":50000000,"crc":"29BCC161"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r14","size":50000000,"crc":"4654CF1B"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r15","size":50000000,"crc":"AAD7677C"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r16","size":50000000,"crc":"4EC4231D"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r17","size":50000000,"crc":"AE47B2B2"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r18","size":50000000,"crc":"7D18031A"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r19","size":50000000,"crc":"E77569CF"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r20","size":50000000,"crc":"728C9864"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r21","size":50000000,"crc":"6CA3DDE5"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r22","size":50000000,"crc":"FC7B899B"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r23","size":50000000,"crc":"49A6C138"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r24","size":50000000,"crc":"81369D49"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r25","size":50000000,"crc":"FBCFC823"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r26","size":50000000,"crc":"DADD3D36"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r27","size":50000000,"crc":"29E298D8"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r28","size":50000000,"crc":"AEF00A66"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r29","size":50000000,"crc":"BA6C2C09"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r30","size":50000000,"crc":"23D887FC"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r31","size":50000000,"crc":"7A63CE26"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r32","size":50000000,"crc":"BA625803"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r33","size":50000000,"crc":"295A198F"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r34","size":50000000,"crc":"9787DEB1"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r35","size":50000000,"crc":"CDB2B19F"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r36","size":50000000,"crc":"91066016"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r37","size":50000000,"crc":"F959DD37"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r38","size":50000000,"crc":"87D7AED4"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r39","size":50000000,"crc":"3C8F6E45"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r40","size":50000000,"crc":"A93AC42C"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r41","size":50000000,"crc":"9754BB75"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r42","size":50000000,"crc":"E7A757EC"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r43","size":50000000,"crc":"E9617617"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r44","size":50000000,"crc":"A39D695C"},{"name":"fawlty.towers.s01e02.1080p.bluray.x264-shortbrehd.r45","size":42812680,"crc":"49F78220"}],"archived-files":[{"name":"Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD.mkv","size":2342806335,"crc":"821D6BF2"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..a514ed0 --- /dev/null +++ b/tests/scene_responses/api_details_Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD.response @@ -0,0 +1 @@ +{"name":"Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD","files":[{"name":"Proof\/fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.proof.jpg","size":132556,"crc":"1B25A106"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.nfo","size":6024,"crc":"959D7AB0"},{"name":"Sample\/fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.sample.mkv","size":116203981,"crc":"13B34A70"},{"name":"Subs\/fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.subs.rar","size":1689149,"crc":"3E83993B"},{"name":"Subs\/fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.subs.sfv","size":69,"crc":"E4AEF055"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.sfv","size":3648,"crc":"F566EAAE"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.rar","size":50000000,"crc":"EF1BC434"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r00","size":50000000,"crc":"1468E6A4"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r01","size":50000000,"crc":"EEF9AF34"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r02","size":50000000,"crc":"35D982F0"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r03","size":50000000,"crc":"C50AF12A"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r04","size":50000000,"crc":"20A23CD5"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r05","size":50000000,"crc":"1E4AA7BF"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r06","size":50000000,"crc":"18BF9BAE"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r07","size":50000000,"crc":"FAECB584"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r08","size":50000000,"crc":"D674F84A"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r09","size":50000000,"crc":"62F8E686"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r10","size":50000000,"crc":"E8046D4C"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r11","size":50000000,"crc":"786F3308"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r12","size":50000000,"crc":"0D003810"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r13","size":50000000,"crc":"CC5547B8"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r14","size":50000000,"crc":"3CEDA0F5"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r15","size":50000000,"crc":"5AEA05AF"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r16","size":50000000,"crc":"DCC39D4C"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r17","size":50000000,"crc":"EBFA4ED8"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r18","size":50000000,"crc":"3C32BE6A"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r19","size":50000000,"crc":"5228C697"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r20","size":50000000,"crc":"0AEB78E8"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r21","size":50000000,"crc":"FA0BA4EC"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r22","size":50000000,"crc":"278975A6"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r23","size":50000000,"crc":"F385C81D"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r24","size":50000000,"crc":"29BD00D1"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r25","size":50000000,"crc":"6DD0BA5C"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r26","size":50000000,"crc":"3067D665"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r27","size":50000000,"crc":"E4220524"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r28","size":50000000,"crc":"D61838A5"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r29","size":50000000,"crc":"2568FBF9"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r30","size":50000000,"crc":"FC49F3EE"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r31","size":50000000,"crc":"7E8421DC"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r32","size":50000000,"crc":"8E166003"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r33","size":50000000,"crc":"14ADC7F6"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r34","size":50000000,"crc":"F56FBA2D"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r35","size":50000000,"crc":"76D2B824"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r36","size":50000000,"crc":"0F2E3C85"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r37","size":50000000,"crc":"9890DD9B"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r38","size":50000000,"crc":"D9D86316"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r39","size":50000000,"crc":"61F7079D"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r40","size":50000000,"crc":"7ABCA452"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r41","size":50000000,"crc":"7383AE2D"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r42","size":50000000,"crc":"BE744CE8"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r43","size":50000000,"crc":"2A5DA82E"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r44","size":50000000,"crc":"AE4D367C"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r45","size":50000000,"crc":"8E81E889"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r46","size":50000000,"crc":"0CA24B6B"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r47","size":50000000,"crc":"6E4811D7"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r48","size":50000000,"crc":"48F2736D"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r49","size":50000000,"crc":"4C3CB5EB"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r50","size":50000000,"crc":"D2A8FE26"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r51","size":50000000,"crc":"FE67C5D4"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r52","size":50000000,"crc":"73FEA061"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r53","size":50000000,"crc":"C3F4691B"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r54","size":50000000,"crc":"F2B04FD6"},{"name":"fawlty.towers.s01e03.1080p.bluray.x264-shortbrehd.r55","size":38660735,"crc":"0772D264"}],"archived-files":[{"name":"Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD.mkv","size":2838653040,"crc":"45B8BD8D"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..9543143 --- /dev/null +++ b/tests/scene_responses/api_details_Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD.response @@ -0,0 +1 @@ +{"name":"Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD","files":[{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.nfo","size":6024,"crc":"C8F30C7D"},{"name":"Proof\/fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.proof.jpg","size":132556,"crc":"1B25A106"},{"name":"Sample\/fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.sample.mkv","size":89605969,"crc":"A42AC758"},{"name":"Subs\/fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.subs.rar","size":1705346,"crc":"B31AA311"},{"name":"Subs\/fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.subs.sfv","size":69,"crc":"5CDE4D66"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.sfv","size":3008,"crc":"7BC0E337"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.rar","size":50000000,"crc":"988FE795"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r00","size":50000000,"crc":"FF17B47B"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r01","size":50000000,"crc":"22F47221"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r02","size":50000000,"crc":"734CC65F"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r03","size":50000000,"crc":"289885A2"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r04","size":50000000,"crc":"30AA29A7"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r05","size":50000000,"crc":"AF20445A"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r06","size":50000000,"crc":"6AB6977D"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r07","size":50000000,"crc":"00927923"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r08","size":50000000,"crc":"9F8870D4"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r09","size":50000000,"crc":"891951B5"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r10","size":50000000,"crc":"469BB411"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r11","size":50000000,"crc":"A9C68F6D"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r12","size":50000000,"crc":"F3B668FC"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r13","size":50000000,"crc":"D4E0F508"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r14","size":50000000,"crc":"0D0314A4"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r15","size":50000000,"crc":"79B5BDC0"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r16","size":50000000,"crc":"B7A251FC"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r17","size":50000000,"crc":"1813A8A0"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r18","size":50000000,"crc":"5F1ECBD1"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r19","size":50000000,"crc":"8565F3E6"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r20","size":50000000,"crc":"BF63AADB"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r21","size":50000000,"crc":"52BFC613"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r22","size":50000000,"crc":"D9B77D74"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r23","size":50000000,"crc":"568773AB"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r24","size":50000000,"crc":"BA038B82"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r25","size":50000000,"crc":"199940B8"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r26","size":50000000,"crc":"E143A5A9"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r27","size":50000000,"crc":"46BCADBB"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r28","size":50000000,"crc":"142AB8E8"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r29","size":50000000,"crc":"DAE0E633"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r30","size":50000000,"crc":"991FEEC4"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r31","size":50000000,"crc":"BD058ECA"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r32","size":50000000,"crc":"F04BB7EE"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r33","size":50000000,"crc":"7E4893B7"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r34","size":50000000,"crc":"2D06A56B"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r35","size":50000000,"crc":"96CB3800"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r36","size":50000000,"crc":"C91808EA"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r37","size":50000000,"crc":"D989E69A"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r38","size":50000000,"crc":"126D362D"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r39","size":50000000,"crc":"DF0FABB2"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r40","size":50000000,"crc":"1C19EF70"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r41","size":50000000,"crc":"3B468F82"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r42","size":50000000,"crc":"BD25FAAE"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r43","size":50000000,"crc":"58BE10FF"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r44","size":50000000,"crc":"A7B80EDB"},{"name":"fawlty.towers.s01e04.1080p.bluray.x264-shortbrehd.r45","size":43653536,"crc":"F9380291"}],"archived-files":[{"name":"Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD.mkv","size":2343647191,"crc":"8C00A91C"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..65147af --- /dev/null +++ b/tests/scene_responses/api_details_Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD.response @@ -0,0 +1 @@ +{"name":"Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD","files":[{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.nfo","size":6024,"crc":"FF14629D"},{"name":"Proof\/fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.proof.jpg","size":132556,"crc":"1B25A106"},{"name":"Sample\/fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.sample.mkv","size":71630278,"crc":"27F9D5C2"},{"name":"Subs\/fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.subs.rar","size":1433304,"crc":"9FB15FEC"},{"name":"Subs\/fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.subs.sfv","size":69,"crc":"151958F2"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.sfv","size":3008,"crc":"560D75D1"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.rar","size":50000000,"crc":"D6A30A99"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r00","size":50000000,"crc":"94E30144"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r01","size":50000000,"crc":"3A7E94E3"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r02","size":50000000,"crc":"EC3FE554"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r03","size":50000000,"crc":"1FA3B62F"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r04","size":50000000,"crc":"560AD131"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r05","size":50000000,"crc":"F174FEE3"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r06","size":50000000,"crc":"4310770F"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r07","size":50000000,"crc":"44D7009D"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r08","size":50000000,"crc":"B43B51D4"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r09","size":50000000,"crc":"882E6C7D"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r10","size":50000000,"crc":"A6F39F10"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r11","size":50000000,"crc":"1205D268"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r12","size":50000000,"crc":"96D0407C"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r13","size":50000000,"crc":"82962DD9"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r14","size":50000000,"crc":"E361AF5B"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r15","size":50000000,"crc":"8536B906"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r16","size":50000000,"crc":"74294C3B"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r17","size":50000000,"crc":"02771934"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r18","size":50000000,"crc":"F00926D4"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r19","size":50000000,"crc":"E972CB9D"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r20","size":50000000,"crc":"512F3E49"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r21","size":50000000,"crc":"8D41B4A7"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r22","size":50000000,"crc":"38BF3E60"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r23","size":50000000,"crc":"058C5455"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r24","size":50000000,"crc":"BC341BB8"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r25","size":50000000,"crc":"5365F4EA"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r26","size":50000000,"crc":"44392B0D"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r27","size":50000000,"crc":"14DDFEB9"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r28","size":50000000,"crc":"350A5ED7"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r29","size":50000000,"crc":"40F6E315"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r30","size":50000000,"crc":"9CFCB5FC"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r31","size":50000000,"crc":"401D871E"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r32","size":50000000,"crc":"3F9D244B"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r33","size":50000000,"crc":"1918ECCF"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r34","size":50000000,"crc":"C6103CE0"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r35","size":50000000,"crc":"3D0BC670"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r36","size":50000000,"crc":"3065F9F6"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r37","size":50000000,"crc":"0A6CAF2F"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r38","size":50000000,"crc":"F5430120"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r39","size":50000000,"crc":"E77D90A8"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r40","size":50000000,"crc":"84047BDC"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r41","size":50000000,"crc":"F128F545"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r42","size":50000000,"crc":"E5D57422"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r43","size":50000000,"crc":"08679DB7"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r44","size":50000000,"crc":"EAF26C91"},{"name":"fawlty.towers.s01e05.1080p.bluray.x264-shortbrehd.r45","size":42964506,"crc":"25E39C43"}],"archived-files":[{"name":"Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD.mkv","size":2342958161,"crc":"C4F1BA16"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD.response b/tests/scene_responses/api_details_Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD.response new file mode 100644 index 0000000..d43ff3b --- /dev/null +++ b/tests/scene_responses/api_details_Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD.response @@ -0,0 +1 @@ +{"name":"Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD","files":[{"name":"Proof\/fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.proof.jpg","size":132556,"crc":"1B25A106"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.nfo","size":6024,"crc":"08FF1EDF"},{"name":"Sample\/fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.sample.mkv","size":73779293,"crc":"132633F2"},{"name":"Subs\/fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.subs.rar","size":1689863,"crc":"EA1CC8A4"},{"name":"Subs\/fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.subs.sfv","size":69,"crc":"51F44636"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.sfv","size":3008,"crc":"D89BDC9A"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.rar","size":50000000,"crc":"56BE09AA"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r00","size":50000000,"crc":"7C73CDA3"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r01","size":50000000,"crc":"EFE5E877"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r02","size":50000000,"crc":"3129DC4F"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r03","size":50000000,"crc":"BA22CD9E"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r04","size":50000000,"crc":"F0F928F2"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r05","size":50000000,"crc":"266F5149"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r06","size":50000000,"crc":"38426F01"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r07","size":50000000,"crc":"C55B99DE"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r08","size":50000000,"crc":"34F2C1FB"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r09","size":50000000,"crc":"DCF37C32"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r10","size":50000000,"crc":"AE1DA90E"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r11","size":50000000,"crc":"C566729E"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r12","size":50000000,"crc":"C9931C53"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r13","size":50000000,"crc":"FA455B87"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r14","size":50000000,"crc":"51007CBA"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r15","size":50000000,"crc":"EA1E72FC"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r16","size":50000000,"crc":"7992F41A"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r17","size":50000000,"crc":"DF850216"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r18","size":50000000,"crc":"212E6F79"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r19","size":50000000,"crc":"E28A40E0"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r20","size":50000000,"crc":"D6F877A1"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r21","size":50000000,"crc":"0E3B3BAD"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r22","size":50000000,"crc":"E38EC93B"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r23","size":50000000,"crc":"7422D333"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r24","size":50000000,"crc":"4C835128"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r25","size":50000000,"crc":"6E038905"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r26","size":50000000,"crc":"47440B67"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r27","size":50000000,"crc":"B0C6E03F"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r28","size":50000000,"crc":"9BE4CE04"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r29","size":50000000,"crc":"AA803DF9"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r30","size":50000000,"crc":"DB0DB38C"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r31","size":50000000,"crc":"5E7AA746"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r32","size":50000000,"crc":"7664C823"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r33","size":50000000,"crc":"9BC501E6"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r34","size":50000000,"crc":"30B605F9"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r35","size":50000000,"crc":"52E43BE8"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r36","size":50000000,"crc":"4613909E"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r37","size":50000000,"crc":"7E8FC550"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r38","size":50000000,"crc":"72EFD02A"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r39","size":50000000,"crc":"83BB0348"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r40","size":50000000,"crc":"EC5FFAB1"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r41","size":50000000,"crc":"9A0C8E22"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r42","size":50000000,"crc":"2D9E031A"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r43","size":50000000,"crc":"8AA9083F"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r44","size":50000000,"crc":"3707D8B0"},{"name":"fawlty.towers.s01e06.1080p.bluray.x264-shortbrehd.r45","size":42533545,"crc":"C59FFB74"}],"archived-files":[{"name":"Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD.mkv","size":2342527200,"crc":"8AB9CB7C"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_La.Bamba.1987.LE.Bluray.1080p.DTS-HD.x264-Grym.response b/tests/scene_responses/api_details_La.Bamba.1987.LE.Bluray.1080p.DTS-HD.x264-Grym.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Rampart.2011.1080p.Bluray.DD5.1.x264-DON.response b/tests/scene_responses/api_details_Rampart.2011.1080p.Bluray.DD5.1.x264-DON.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_Side.Effects.2013.720p.BluRay.x264-SPARKS.response b/tests/scene_responses/api_details_Side.Effects.2013.720p.BluRay.x264-SPARKS.response new file mode 100644 index 0000000..3d197fc --- /dev/null +++ b/tests/scene_responses/api_details_Side.Effects.2013.720p.BluRay.x264-SPARKS.response @@ -0,0 +1 @@ +{"name":"Side.Effects.2013.720p.BluRay.x264-SPARKS","files":[{"name":"Sample\/sparks-se2013-720.sample.mkv","size":38590319,"crc":"024774B7"},{"name":"Proof\/sparks-se2013-720-proof.jpg","size":31734,"crc":"752D47B0"},{"name":"sparks-se2013-720.nfo","size":4304,"crc":"44FDACC0"},{"name":"sparks-se2013-720.sfv","size":3008,"crc":"708DD41C"},{"name":"sparks-se2013-720.rar","size":50000000,"crc":"0233504F"},{"name":"sparks-se2013-720.r00","size":50000000,"crc":"0677299D"},{"name":"sparks-se2013-720.r01","size":50000000,"crc":"EC01531C"},{"name":"sparks-se2013-720.r02","size":50000000,"crc":"C044ED66"},{"name":"sparks-se2013-720.r03","size":50000000,"crc":"FA484708"},{"name":"sparks-se2013-720.r04","size":50000000,"crc":"41725205"},{"name":"sparks-se2013-720.r05","size":50000000,"crc":"A9F30BF5"},{"name":"sparks-se2013-720.r06","size":50000000,"crc":"840C9399"},{"name":"sparks-se2013-720.r07","size":50000000,"crc":"2BAC7066"},{"name":"sparks-se2013-720.r08","size":50000000,"crc":"A7F4142A"},{"name":"sparks-se2013-720.r09","size":50000000,"crc":"D0A04760"},{"name":"sparks-se2013-720.r10","size":50000000,"crc":"6BD558B2"},{"name":"sparks-se2013-720.r11","size":50000000,"crc":"6E178796"},{"name":"sparks-se2013-720.r12","size":50000000,"crc":"19E7E43D"},{"name":"sparks-se2013-720.r13","size":50000000,"crc":"FFCC1F83"},{"name":"sparks-se2013-720.r14","size":50000000,"crc":"A970D95B"},{"name":"sparks-se2013-720.r15","size":50000000,"crc":"87F617A5"},{"name":"sparks-se2013-720.r16","size":50000000,"crc":"0A7C2AD4"},{"name":"sparks-se2013-720.r17","size":50000000,"crc":"7277867D"},{"name":"sparks-se2013-720.r18","size":50000000,"crc":"C79F4001"},{"name":"sparks-se2013-720.r19","size":50000000,"crc":"7E6BA438"},{"name":"sparks-se2013-720.r20","size":50000000,"crc":"3671EF14"},{"name":"sparks-se2013-720.r21","size":50000000,"crc":"BBCBC8B5"},{"name":"sparks-se2013-720.r22","size":50000000,"crc":"BCF190DD"},{"name":"sparks-se2013-720.r23","size":50000000,"crc":"27D0767C"},{"name":"sparks-se2013-720.r24","size":50000000,"crc":"B00EE001"},{"name":"sparks-se2013-720.r25","size":50000000,"crc":"073DC106"},{"name":"sparks-se2013-720.r26","size":50000000,"crc":"8B9A046A"},{"name":"sparks-se2013-720.r27","size":50000000,"crc":"D802F557"},{"name":"sparks-se2013-720.r28","size":50000000,"crc":"DCB7BC5B"},{"name":"sparks-se2013-720.r29","size":50000000,"crc":"23D37257"},{"name":"sparks-se2013-720.r30","size":50000000,"crc":"0C664E2C"},{"name":"sparks-se2013-720.r31","size":50000000,"crc":"403648C1"},{"name":"sparks-se2013-720.r32","size":50000000,"crc":"76512350"},{"name":"sparks-se2013-720.r33","size":50000000,"crc":"5352710E"},{"name":"sparks-se2013-720.r34","size":50000000,"crc":"A92EA8C3"},{"name":"sparks-se2013-720.r35","size":50000000,"crc":"9564FE74"},{"name":"sparks-se2013-720.r36","size":50000000,"crc":"6DC41C50"},{"name":"sparks-se2013-720.r37","size":50000000,"crc":"4BD37672"},{"name":"sparks-se2013-720.r38","size":50000000,"crc":"02DEB28D"},{"name":"sparks-se2013-720.r39","size":50000000,"crc":"FAF71B1F"},{"name":"sparks-se2013-720.r40","size":50000000,"crc":"40FAC16E"},{"name":"sparks-se2013-720.r41","size":50000000,"crc":"E65420F9"},{"name":"sparks-se2013-720.r42","size":50000000,"crc":"C51D24B5"},{"name":"sparks-se2013-720.r43","size":50000000,"crc":"616F033A"},{"name":"sparks-se2013-720.r44","size":50000000,"crc":"2AB3A89C"},{"name":"sparks-se2013-720.r45","size":50000000,"crc":"84338566"},{"name":"sparks-se2013-720.r46","size":50000000,"crc":"7EA3F06F"},{"name":"sparks-se2013-720.r47","size":50000000,"crc":"DF40C499"},{"name":"sparks-se2013-720.r48","size":50000000,"crc":"CB54903C"},{"name":"sparks-se2013-720.r49","size":50000000,"crc":"CEE9C201"},{"name":"sparks-se2013-720.r50","size":50000000,"crc":"2BA64EA6"},{"name":"sparks-se2013-720.r51","size":50000000,"crc":"01C346EC"},{"name":"sparks-se2013-720.r52","size":50000000,"crc":"39F39945"},{"name":"sparks-se2013-720.r53","size":50000000,"crc":"F38AC573"},{"name":"sparks-se2013-720.r54","size":50000000,"crc":"F676B007"},{"name":"sparks-se2013-720.r55","size":50000000,"crc":"CA5BCAB7"},{"name":"sparks-se2013-720.r56","size":50000000,"crc":"7B4560FD"},{"name":"sparks-se2013-720.r57","size":50000000,"crc":"46F0BAE7"},{"name":"sparks-se2013-720.r58","size":50000000,"crc":"1306CAA0"},{"name":"sparks-se2013-720.r59","size":50000000,"crc":"874690DC"},{"name":"sparks-se2013-720.r60","size":50000000,"crc":"DD04B043"},{"name":"sparks-se2013-720.r61","size":50000000,"crc":"1549577C"},{"name":"sparks-se2013-720.r62","size":50000000,"crc":"CBB032CE"},{"name":"sparks-se2013-720.r63","size":50000000,"crc":"A59AE9B9"},{"name":"sparks-se2013-720.r64","size":50000000,"crc":"1529019F"},{"name":"sparks-se2013-720.r65","size":50000000,"crc":"0E1AB989"},{"name":"sparks-se2013-720.r66","size":50000000,"crc":"64F9FEFD"},{"name":"sparks-se2013-720.r67","size":50000000,"crc":"355D31A5"},{"name":"sparks-se2013-720.r68","size":50000000,"crc":"D416E0D5"},{"name":"sparks-se2013-720.r69","size":50000000,"crc":"6AB89D1A"},{"name":"sparks-se2013-720.r70","size":50000000,"crc":"58025821"},{"name":"sparks-se2013-720.r71","size":50000000,"crc":"BE9DA1A0"},{"name":"sparks-se2013-720.r72","size":50000000,"crc":"34848609"},{"name":"sparks-se2013-720.r73","size":50000000,"crc":"E4567113"},{"name":"sparks-se2013-720.r74","size":50000000,"crc":"80FD596E"},{"name":"sparks-se2013-720.r75","size":50000000,"crc":"C11432EC"},{"name":"sparks-se2013-720.r76","size":50000000,"crc":"A9026355"},{"name":"sparks-se2013-720.r77","size":50000000,"crc":"3848AA5B"},{"name":"sparks-se2013-720.r78","size":50000000,"crc":"D9E3E607"},{"name":"sparks-se2013-720.r79","size":50000000,"crc":"5107125B"},{"name":"sparks-se2013-720.r80","size":50000000,"crc":"E2CD502C"},{"name":"sparks-se2013-720.r81","size":50000000,"crc":"D90792E8"},{"name":"sparks-se2013-720.r82","size":50000000,"crc":"F04B5266"},{"name":"sparks-se2013-720.r83","size":50000000,"crc":"55AE2CFA"},{"name":"sparks-se2013-720.r84","size":50000000,"crc":"7294E926"},{"name":"sparks-se2013-720.r85","size":50000000,"crc":"62DE8D51"},{"name":"sparks-se2013-720.r86","size":50000000,"crc":"57A38E30"},{"name":"sparks-se2013-720.r87","size":50000000,"crc":"21733A9C"},{"name":"sparks-se2013-720.r88","size":50000000,"crc":"C2F39A6D"},{"name":"sparks-se2013-720.r89","size":50000000,"crc":"7BEC3B11"},{"name":"sparks-se2013-720.r90","size":50000000,"crc":"E71C6F28"},{"name":"sparks-se2013-720.r91","size":50000000,"crc":"6E15D50F"},{"name":"sparks-se2013-720.r92","size":40537059,"crc":"085101CE"}],"archived-files":[{"name":"side.effects.2013.720p.bluray.x264-sparks.mkv","size":4690527189,"crc":"EF39A8F0"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080.response b/tests/scene_responses/api_details_Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080.response new file mode 100644 index 0000000..ced201f --- /dev/null +++ b/tests/scene_responses/api_details_Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080.response @@ -0,0 +1 @@ +{"name":"Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080","files":[{"name":"hd1080-wtl.nfo","size":421,"crc":"F2BFEEE4"},{"name":"Sample\/hd1080-wtl.sample.mkv","size":76708092,"crc":"2B9D474E"},{"name":"hd1080-wtl.sfv","size":2000,"crc":"10D2EEFB"},{"name":"hd1080-wtl.rar","size":150000000,"crc":"87796979"},{"name":"hd1080-wtl.r00","size":150000000,"crc":"EAEAB676"},{"name":"hd1080-wtl.r01","size":150000000,"crc":"1D072421"},{"name":"hd1080-wtl.r02","size":150000000,"crc":"9604A1E1"},{"name":"hd1080-wtl.r03","size":150000000,"crc":"4508436A"},{"name":"hd1080-wtl.r04","size":150000000,"crc":"487D8751"},{"name":"hd1080-wtl.r05","size":150000000,"crc":"FD8C4E78"},{"name":"hd1080-wtl.r06","size":150000000,"crc":"87E33B7D"},{"name":"hd1080-wtl.r07","size":150000000,"crc":"D0E25933"},{"name":"hd1080-wtl.r08","size":150000000,"crc":"28BBCBB8"},{"name":"hd1080-wtl.r09","size":150000000,"crc":"BC378AE7"},{"name":"hd1080-wtl.r10","size":150000000,"crc":"32A1CD68"},{"name":"hd1080-wtl.r11","size":150000000,"crc":"102F8F06"},{"name":"hd1080-wtl.r12","size":150000000,"crc":"930C1D64"},{"name":"hd1080-wtl.r13","size":150000000,"crc":"4368DBA7"},{"name":"hd1080-wtl.r14","size":150000000,"crc":"2A0734C3"},{"name":"hd1080-wtl.r15","size":150000000,"crc":"33CF1F4B"},{"name":"hd1080-wtl.r16","size":150000000,"crc":"1B783401"},{"name":"hd1080-wtl.r17","size":150000000,"crc":"AEAD3C1A"},{"name":"hd1080-wtl.r18","size":150000000,"crc":"7C241AF5"},{"name":"hd1080-wtl.r19","size":150000000,"crc":"BC527C1E"},{"name":"hd1080-wtl.r20","size":150000000,"crc":"A96B0169"},{"name":"hd1080-wtl.r21","size":150000000,"crc":"AC697BE5"},{"name":"hd1080-wtl.r22","size":150000000,"crc":"760623F1"},{"name":"hd1080-wtl.r23","size":150000000,"crc":"7A05967E"},{"name":"hd1080-wtl.r24","size":150000000,"crc":"3A73211D"},{"name":"hd1080-wtl.r25","size":150000000,"crc":"59390918"},{"name":"hd1080-wtl.r26","size":150000000,"crc":"96148FD7"},{"name":"hd1080-wtl.r27","size":150000000,"crc":"75A5AF4C"},{"name":"hd1080-wtl.r28","size":150000000,"crc":"C32AB57E"},{"name":"hd1080-wtl.r29","size":150000000,"crc":"60FDBE90"},{"name":"hd1080-wtl.r30","size":150000000,"crc":"A1BA7AB6"},{"name":"hd1080-wtl.r31","size":150000000,"crc":"716B3761"},{"name":"hd1080-wtl.r32","size":150000000,"crc":"5288DDA1"},{"name":"hd1080-wtl.r33","size":150000000,"crc":"61BB1C38"},{"name":"hd1080-wtl.r34","size":150000000,"crc":"4CD39909"},{"name":"hd1080-wtl.r35","size":150000000,"crc":"DC8D618A"},{"name":"hd1080-wtl.r36","size":150000000,"crc":"C2EA7D5A"},{"name":"hd1080-wtl.r37","size":150000000,"crc":"805EF795"},{"name":"hd1080-wtl.r38","size":150000000,"crc":"2593591C"},{"name":"hd1080-wtl.r39","size":150000000,"crc":"5E0CD74E"},{"name":"hd1080-wtl.r40","size":150000000,"crc":"D89FD277"},{"name":"hd1080-wtl.r41","size":150000000,"crc":"41E14C60"},{"name":"hd1080-wtl.r42","size":150000000,"crc":"0255C933"},{"name":"hd1080-wtl.r43","size":150000000,"crc":"35E93905"},{"name":"hd1080-wtl.r44","size":150000000,"crc":"3FD72F27"},{"name":"hd1080-wtl.r45","size":150000000,"crc":"E168FC38"},{"name":"hd1080-wtl.r46","size":150000000,"crc":"28C457E0"},{"name":"hd1080-wtl.r47","size":150000000,"crc":"AA91C95F"},{"name":"hd1080-wtl.r48","size":150000000,"crc":"6750E338"},{"name":"hd1080-wtl.r49","size":150000000,"crc":"6D808BE1"},{"name":"hd1080-wtl.r50","size":150000000,"crc":"BB0983AD"},{"name":"hd1080-wtl.r51","size":150000000,"crc":"435C62A0"},{"name":"hd1080-wtl.r52","size":150000000,"crc":"04BF75DC"},{"name":"hd1080-wtl.r53","size":150000000,"crc":"90A1B36A"},{"name":"hd1080-wtl.r54","size":150000000,"crc":"5196D672"},{"name":"hd1080-wtl.r55","size":150000000,"crc":"7412A39F"},{"name":"hd1080-wtl.r56","size":150000000,"crc":"518315DA"},{"name":"hd1080-wtl.r57","size":150000000,"crc":"7907C6A8"},{"name":"hd1080-wtl.r58","size":150000000,"crc":"8D6A9322"},{"name":"hd1080-wtl.r59","size":150000000,"crc":"839A1099"},{"name":"hd1080-wtl.r60","size":150000000,"crc":"BEFA2C9C"},{"name":"hd1080-wtl.r61","size":150000000,"crc":"1D6B95C6"},{"name":"hd1080-wtl.r62","size":150000000,"crc":"5B8D4D2B"},{"name":"hd1080-wtl.r63","size":150000000,"crc":"FC1E166C"},{"name":"hd1080-wtl.r64","size":150000000,"crc":"411BCC7A"},{"name":"hd1080-wtl.r65","size":150000000,"crc":"FE8EB8B0"},{"name":"hd1080-wtl.r66","size":150000000,"crc":"DF25B20D"},{"name":"hd1080-wtl.r67","size":150000000,"crc":"47814BDD"},{"name":"hd1080-wtl.r68","size":150000000,"crc":"028710C8"},{"name":"hd1080-wtl.r69","size":150000000,"crc":"D6273B8C"},{"name":"hd1080-wtl.r70","size":150000000,"crc":"B0B2CF90"},{"name":"hd1080-wtl.r71","size":150000000,"crc":"E0C8B238"},{"name":"hd1080-wtl.r72","size":150000000,"crc":"FF615FCD"},{"name":"hd1080-wtl.r73","size":150000000,"crc":"6D89CB3A"},{"name":"hd1080-wtl.r74","size":150000000,"crc":"20291A5C"},{"name":"hd1080-wtl.r75","size":150000000,"crc":"DCA66420"},{"name":"hd1080-wtl.r76","size":150000000,"crc":"623D622D"},{"name":"hd1080-wtl.r77","size":150000000,"crc":"A2F8CBBA"},{"name":"hd1080-wtl.r78","size":10470851,"crc":"B772CF1F"}],"archived-files":[{"name":"hd1080-wtl.mkv","size":11743374939,"crc":"20C561A5"}],"adds":[]} \ No newline at end of file diff --git a/tests/scene_responses/api_details_bored to.death.s01.extras.720p.bluray.x264-ingot.response b/tests/scene_responses/api_details_bored to.death.s01.extras.720p.bluray.x264-ingot.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_bored to.death.s01e03.deleted.scene.720p.bluray.x264-ingot.response b/tests/scene_responses/api_details_bored to.death.s01e03.deleted.scene.720p.bluray.x264-ingot.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_fawlty towers.s01.1080p.bluray.x264-shortbrehd.response b/tests/scene_responses/api_details_fawlty towers.s01.1080p.bluray.x264-shortbrehd.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_fawlty towers.s01e01.1080p.bluray.x264-shortbrehd.response b/tests/scene_responses/api_details_fawlty towers.s01e01.1080p.bluray.x264-shortbrehd.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_hd1080-wtl.response b/tests/scene_responses/api_details_hd1080-wtl.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_side effects.2013.720p.bluray.x264-sparks.response b/tests/scene_responses/api_details_side effects.2013.720p.bluray.x264-sparks.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_side.effects.2013.720p.bluray.x264-sparks.response b/tests/scene_responses/api_details_side.effects.2013.720p.bluray.x264-sparks.response new file mode 100644 index 0000000..180bfa8 --- /dev/null +++ b/tests/scene_responses/api_details_side.effects.2013.720p.bluray.x264-sparks.response @@ -0,0 +1,954 @@ + + + + + + + + + +Side.Effects.2013.720p.BluRay.x264-SPARKS - Release Information - srrDB + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+

srrDB

+
+
+
+ Upload +
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+ 1439 +
+
+
+ Uploads today +
+
+
+
+ 100% + + Bitcoin logo + +
+
+
+ Completed daily pres +
+
+
+
+ +No downloads here. + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+ +
+
    +
  • + U: Anonymous
  • +
  • D: 2013-05-08 03:56:18
  • +
  • C: X264 +
  • +
+
+
+
+
+
+
+
+ You were redirected to this page (side.effects.2013.720p.bluray.x264-sparks) +
+ + +
+
+

+ MOVIE > + +

+
+
+
+ + + + + + +
+ Rating:
+ 7.2/10 (43,135 votes)
+ Genre:
+ Thriller, +Drama, +Crime
+ Runtime:
+ 106 min +
+ Country:
+ USA
+ Language:
+ French, +English
+ More releases:
+ tt2053463 + +
+ + A young woman's world unravels when a drug prescribed by her psychiatrist has unexpected side effects.
+
+
+
+ +
+
+

RELEASE >

+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ReScene versionpyReScene 0.5 + SPARKS + + File sizeCRC
Download + + + + + + +
74,430 +
+
+ Stored files + +
+ + + + + + + + + + + + + + + + + + + + + + + +
22,440 + 54DD7DA9 +
31,734 + 752D47B0 +
4,304 + 44FDACC0 +
3,008 + 708DD41C +
+
RAR-files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sparks-se2013-720.rar50,000,0000233504F
sparks-se2013-720.r0050,000,0000677299D
sparks-se2013-720.r0150,000,000EC01531C
sparks-se2013-720.r0250,000,000C044ED66
sparks-se2013-720.r0350,000,000FA484708
sparks-se2013-720.r0450,000,00041725205
sparks-se2013-720.r0550,000,000A9F30BF5
sparks-se2013-720.r0650,000,000840C9399
sparks-se2013-720.r0750,000,0002BAC7066
sparks-se2013-720.r0850,000,000A7F4142A
sparks-se2013-720.r0950,000,000D0A04760
sparks-se2013-720.r1050,000,0006BD558B2
sparks-se2013-720.r1150,000,0006E178796
sparks-se2013-720.r1250,000,00019E7E43D
sparks-se2013-720.r1350,000,000FFCC1F83
sparks-se2013-720.r1450,000,000A970D95B
sparks-se2013-720.r1550,000,00087F617A5
sparks-se2013-720.r1650,000,0000A7C2AD4
sparks-se2013-720.r1750,000,0007277867D
sparks-se2013-720.r1850,000,000C79F4001
sparks-se2013-720.r1950,000,0007E6BA438
sparks-se2013-720.r2050,000,0003671EF14
sparks-se2013-720.r2150,000,000BBCBC8B5
sparks-se2013-720.r2250,000,000BCF190DD
sparks-se2013-720.r2350,000,00027D0767C
sparks-se2013-720.r2450,000,000B00EE001
sparks-se2013-720.r2550,000,000073DC106
sparks-se2013-720.r2650,000,0008B9A046A
sparks-se2013-720.r2750,000,000D802F557
sparks-se2013-720.r2850,000,000DCB7BC5B
sparks-se2013-720.r2950,000,00023D37257
sparks-se2013-720.r3050,000,0000C664E2C
sparks-se2013-720.r3150,000,000403648C1
sparks-se2013-720.r3250,000,00076512350
sparks-se2013-720.r3350,000,0005352710E
sparks-se2013-720.r3450,000,000A92EA8C3
sparks-se2013-720.r3550,000,0009564FE74
sparks-se2013-720.r3650,000,0006DC41C50
sparks-se2013-720.r3750,000,0004BD37672
sparks-se2013-720.r3850,000,00002DEB28D
sparks-se2013-720.r3950,000,000FAF71B1F
sparks-se2013-720.r4050,000,00040FAC16E
sparks-se2013-720.r4150,000,000E65420F9
sparks-se2013-720.r4250,000,000C51D24B5
sparks-se2013-720.r4350,000,000616F033A
sparks-se2013-720.r4450,000,0002AB3A89C
sparks-se2013-720.r4550,000,00084338566
sparks-se2013-720.r4650,000,0007EA3F06F
sparks-se2013-720.r4750,000,000DF40C499
sparks-se2013-720.r4850,000,000CB54903C
sparks-se2013-720.r4950,000,000CEE9C201
sparks-se2013-720.r5050,000,0002BA64EA6
sparks-se2013-720.r5150,000,00001C346EC
sparks-se2013-720.r5250,000,00039F39945
sparks-se2013-720.r5350,000,000F38AC573
sparks-se2013-720.r5450,000,000F676B007
sparks-se2013-720.r5550,000,000CA5BCAB7
sparks-se2013-720.r5650,000,0007B4560FD
sparks-se2013-720.r5750,000,00046F0BAE7
sparks-se2013-720.r5850,000,0001306CAA0
sparks-se2013-720.r5950,000,000874690DC
sparks-se2013-720.r6050,000,000DD04B043
sparks-se2013-720.r6150,000,0001549577C
sparks-se2013-720.r6250,000,000CBB032CE
sparks-se2013-720.r6350,000,000A59AE9B9
sparks-se2013-720.r6450,000,0001529019F
sparks-se2013-720.r6550,000,0000E1AB989
sparks-se2013-720.r6650,000,00064F9FEFD
sparks-se2013-720.r6750,000,000355D31A5
sparks-se2013-720.r6850,000,000D416E0D5
sparks-se2013-720.r6950,000,0006AB89D1A
sparks-se2013-720.r7050,000,00058025821
sparks-se2013-720.r7150,000,000BE9DA1A0
sparks-se2013-720.r7250,000,00034848609
sparks-se2013-720.r7350,000,000E4567113
sparks-se2013-720.r7450,000,00080FD596E
sparks-se2013-720.r7550,000,000C11432EC
sparks-se2013-720.r7650,000,000A9026355
sparks-se2013-720.r7750,000,0003848AA5B
sparks-se2013-720.r7850,000,000D9E3E607
sparks-se2013-720.r7950,000,0005107125B
sparks-se2013-720.r8050,000,000E2CD502C
sparks-se2013-720.r8150,000,000D90792E8
sparks-se2013-720.r8250,000,000F04B5266
sparks-se2013-720.r8350,000,00055AE2CFA
sparks-se2013-720.r8450,000,0007294E926
sparks-se2013-720.r8550,000,00062DE8D51
sparks-se2013-720.r8650,000,00057A38E30
sparks-se2013-720.r8750,000,00021733A9C
sparks-se2013-720.r8850,000,000C2F39A6D
sparks-se2013-720.r8950,000,0007BEC3B11
sparks-se2013-720.r9050,000,000E71C6F28
sparks-se2013-720.r9150,000,0006E15D50F
sparks-se2013-720.r9240,537,059085101CE

Total size:4,690,537,059
+
Archived files + + + + + + + +
+ side.effects.2013.720p.bluray.x264-sparks.mkv [89e90bf7d04a0776] + 4,690,527,189EF39A8F0
+
Video files + + + + + + + + + + + + +
Sample
sparks-se2013-720.sample.mkv38,590,319024774B7
+
RAR Recovery + + + + + + +
Not Present
+
LabelsVIDEO, MOVIE, HD READY, BLURAY, RETAIL, H264
Warnings (94) + MHD_FIRSTVOLUME flag set for sparks-se2013-720.r00.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r01.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r02.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r03.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r04.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r05.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r06.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r07.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r08.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r09.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r10.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r11.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r12.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r13.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r14.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r15.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r16.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r17.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r18.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r19.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r20.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r21.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r22.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r23.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r24.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r25.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r26.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r27.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r28.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r29.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r30.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r31.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r32.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r33.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r34.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r35.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r36.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r37.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r38.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r39.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r40.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r41.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r42.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r43.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r44.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r45.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r46.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r47.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r48.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r49.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r50.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r51.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r52.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r53.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r54.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r55.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r56.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r57.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r58.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r59.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r60.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r61.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r62.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r63.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r64.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r65.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r66.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r67.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r68.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r69.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r70.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r71.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r72.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r73.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r74.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r75.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r76.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r77.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r78.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r79.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r80.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r81.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r82.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r83.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r84.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r85.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r86.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r87.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r88.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r89.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r90.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r91.
+ MHD_FIRSTVOLUME flag set for sparks-se2013-720.r92.
+ Custom RAR packer detected.
+
+
+
+
+
+ +
+
+
+
+ + + + diff --git a/tests/scene_responses/api_details_voa-the_omega_man_x264_bluray.response b/tests/scene_responses/api_details_voa-the_omega_man_x264_bluray.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_details_walk the.line.extended.cut.2005.1080p.bluray.x264-hd1080.response b/tests/scene_responses/api_details_walk the.line.extended.cut.2005.1080p.bluray.x264-hd1080.response new file mode 100644 index 0000000..e69de29 diff --git a/tests/scene_responses/api_search_12_rounds_reloaded_group:rovers_1080p_2013.response b/tests/scene_responses/api_search_12_rounds_reloaded_group:rovers_1080p_2013.response new file mode 100644 index 0000000..6103bb8 --- /dev/null +++ b/tests/scene_responses/api_search_12_rounds_reloaded_group:rovers_1080p_2013.response @@ -0,0 +1 @@ +{"results":[{"release":"12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS","date":"2013-05-24 13:52:33","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%12%","%rounds%","%reloaded%","rovers","%1080p%","%2013%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_Bored_to_Death_group:iNGOT_720p_S01.response b/tests/scene_responses/api_search_Bored_to_Death_group:iNGOT_720p_S01.response new file mode 100644 index 0000000..f80beee --- /dev/null +++ b/tests/scene_responses/api_search_Bored_to_Death_group:iNGOT_720p_S01.response @@ -0,0 +1 @@ +{"results":[{"release":"Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT","date":"2011-10-07 00:00:00","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%Bored%","%to%","%Death%","iNGOT","%720p%","%S01%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_Damnation_group:AJP69_720p_S01.response b/tests/scene_responses/api_search_Damnation_group:AJP69_720p_S01.response new file mode 100644 index 0000000..9ca2d9f --- /dev/null +++ b/tests/scene_responses/api_search_Damnation_group:AJP69_720p_S01.response @@ -0,0 +1 @@ +{"results":[],"resultsCount":"0","warnings":[],"query":["%Damnation%","AJP69","%720p%","%S01%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_La_Bamba_group:Grym_1080p_1987.response b/tests/scene_responses/api_search_La_Bamba_group:Grym_1080p_1987.response new file mode 100644 index 0000000..0f11e1b --- /dev/null +++ b/tests/scene_responses/api_search_La_Bamba_group:Grym_1080p_1987.response @@ -0,0 +1 @@ +{"results":[],"resultsCount":"0","warnings":[],"query":["%La%","%Bamba%","Grym","%1080p%","%1987%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_Rampart_group:DON_1080p_2011.response b/tests/scene_responses/api_search_Rampart_group:DON_1080p_2011.response new file mode 100644 index 0000000..c2bfe04 --- /dev/null +++ b/tests/scene_responses/api_search_Rampart_group:DON_1080p_2011.response @@ -0,0 +1 @@ +{"results":[],"resultsCount":"0","warnings":[],"query":["%Rampart%","DON","%1080p%","%2011%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_bored_to_death_group:ingot_720p_S01.response b/tests/scene_responses/api_search_bored_to_death_group:ingot_720p_S01.response new file mode 100644 index 0000000..b9d3714 --- /dev/null +++ b/tests/scene_responses/api_search_bored_to_death_group:ingot_720p_S01.response @@ -0,0 +1 @@ +{"results":[{"release":"Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT","date":"2011-10-07 00:00:00","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%bored%","%to%","%death%","ingot","%720p%","%S01%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_bored_to_death_group:ingot_Extras_720p_S01.response b/tests/scene_responses/api_search_bored_to_death_group:ingot_Extras_720p_S01.response new file mode 100644 index 0000000..01bd19a --- /dev/null +++ b/tests/scene_responses/api_search_bored_to_death_group:ingot_Extras_720p_S01.response @@ -0,0 +1 @@ +{"results":[{"release":"Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT","date":"2011-10-07 00:00:00","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%bored%","%to%","%death%","ingot","%Extras%","%720p%","%S01%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_fawlty_towers_group:shortbrehd_1080p_S01.response b/tests/scene_responses/api_search_fawlty_towers_group:shortbrehd_1080p_S01.response new file mode 100644 index 0000000..6c72b4e --- /dev/null +++ b/tests/scene_responses/api_search_fawlty_towers_group:shortbrehd_1080p_S01.response @@ -0,0 +1 @@ +{"results":[{"release":"Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD","date":"2019-11-20 13:02:14","hasNFO":"yes","hasSRS":"yes"},{"release":"Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD","date":"2019-11-20 13:14:50","hasNFO":"yes","hasSRS":"yes"},{"release":"Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD","date":"2019-11-20 13:17:02","hasNFO":"yes","hasSRS":"yes"},{"release":"Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD","date":"2019-11-20 13:14:14","hasNFO":"yes","hasSRS":"yes"},{"release":"Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD","date":"2019-11-20 13:11:40","hasNFO":"yes","hasSRS":"yes"},{"release":"Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD","date":"2019-11-20 13:15:06","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"6","warnings":[],"query":["%fawlty%","%towers%","shortbrehd","%1080p%","%S01%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_side_effects_group:sparks_720p_2013.response b/tests/scene_responses/api_search_side_effects_group:sparks_720p_2013.response new file mode 100644 index 0000000..28d2de3 --- /dev/null +++ b/tests/scene_responses/api_search_side_effects_group:sparks_720p_2013.response @@ -0,0 +1 @@ +{"results":[{"release":"Side.Effects.2013.720p.BluRay.x264-SPARKS","date":"2013-05-08 03:56:18","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%side%","%effects%","sparks","%720p%","%2013%"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_the_omega_man_group:voa.response b/tests/scene_responses/api_search_the_omega_man_group:voa.response new file mode 100644 index 0000000..4692d3c --- /dev/null +++ b/tests/scene_responses/api_search_the_omega_man_group:voa.response @@ -0,0 +1 @@ +{"results":[{"release":"The.Omega.Man.1971.1080p.BluRay.x264-VOA","date":"2011-12-24 00:00:00","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%the%","%omega%","%man%","voa"]} \ No newline at end of file diff --git a/tests/scene_responses/api_search_walk_the_line_group:hd1080_1080p_2005.response b/tests/scene_responses/api_search_walk_the_line_group:hd1080_1080p_2005.response new file mode 100644 index 0000000..3705970 --- /dev/null +++ b/tests/scene_responses/api_search_walk_the_line_group:hd1080_1080p_2005.response @@ -0,0 +1 @@ +{"results":[{"release":"Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080","date":"2012-05-28 00:00:00","hasNFO":"yes","hasSRS":"yes"}],"resultsCount":"1","warnings":[],"query":["%walk%","%the%","%line%","hd1080","%1080p%","%2005%"]} \ No newline at end of file diff --git a/tests/test_scene.py b/tests/test_scene.py new file mode 100644 index 0000000..dad144b --- /dev/null +++ b/tests/test_scene.py @@ -0,0 +1,638 @@ +from pythonbits import scene, bb +from unittest.mock import patch, Mock, call +import pytest + +import json +import os +import contextlib + +# Silence guessit +import logging +logging.getLogger('rebulk.rebulk').setLevel(logging.INFO) +logging.getLogger('rebulk.rules').setLevel(logging.INFO) +logging.getLogger('rebulk.processors').setLevel(logging.INFO) + + +def mock_response(text): + return Mock(text=text, json=lambda: json.loads(text)) + +def mock_html(body): + return ('' + '' + '%s' + '') % (body,) + + +@patch('pythonbits.scene._yield_file_info') +@patch('pythonbits.scene._check_dir') +def test_check_integrity_expects_APIError_from_check_dir(mock_check_dir, mock_yield_file_info): + mock_check_dir.side_effect = scene.APIError('Owie!') + mock_yield_file_info.return_value = () + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01.x264-ABC', on_error=cb) is None + assert mock_check_dir.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_yield_file_info.call_args_list == [] + assert [repr(arg) for arg in cb.call_args_list] == [repr(call('Foo.S01.x264-ABC', scene.APIError('Owie!')))] + +@patch('pythonbits.scene._yield_file_info') +@patch('pythonbits.scene._check_dir') +def test_check_integrity_expects_APIError_from_yield_file_info_with_file_release(mock_check_dir, mock_yield_file_info): + mock_check_dir.return_value = None + mock_yield_file_info.side_effect = scene.APIError('Ooophff!') + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01E02.x264-ABC.mkv', on_error=cb) is None + assert mock_check_dir.call_args_list == [] + assert mock_yield_file_info.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert [repr(arg) for arg in cb.call_args_list] == [repr(call('Foo.S01E02.x264-ABC.mkv', scene.APIError('Ooophff!')))] + +@patch('pythonbits.scene._yield_file_info') +@patch('pythonbits.scene._check_dir') +def test_check_integrity_expects_APIError_from_yield_file_info_with_directory_release(mock_check_dir, mock_yield_file_info): + mock_check_dir.return_value = None + mock_yield_file_info.side_effect = scene.APIError('Ooophff!') + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01.x264-ABC', on_error=cb) is None + assert mock_check_dir.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_yield_file_info.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert [repr(arg) for arg in cb.call_args_list] == [repr(call('Foo.S01.x264-ABC', scene.APIError('Ooophff!')))] + +@patch('pythonbits.scene._yield_file_info') +@patch('pythonbits.scene._check_dir') +def test_check_integrity_expects_SceneError_from_check_dir(mock_check_dir, mock_yield_file_info): + mock_check_dir.side_effect = scene.SceneError('Nooo!') + mock_yield_file_info.return_value = () + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01.x264-ABC', on_error=cb) is True + assert mock_check_dir.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_yield_file_info.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert [repr(arg) for arg in cb.call_args_list] == [repr(call('Foo.S01.x264-ABC', scene.SceneError('Nooo!')))] + +@patch('pythonbits.scene._check_dir') +@patch('pythonbits.scene._check_file') +@patch('pythonbits.scene._yield_file_info') +def test_check_integrity_expects_SceneError_from_check_file(mock_yield_file_info, mock_check_file, mock_check_dir): + mock_check_file.side_effect = scene.SceneError('Argh!') + infos = ({'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'}, + {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 234, 'crc': 'ABCD1234'}) + mock_yield_file_info.return_value = infos + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01.x264-ABC', on_error=cb) is True + assert mock_check_dir.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_yield_file_info.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_check_file.call_args_list == [ + call('Foo.S01.x264-ABC/Foo.S01E01.x264-ABC.mkv', 'path/to/Foo.S01.x264-ABC/Foo.S01E01.x264-ABC.mkv', infos[0]), + call('Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', infos[1])] + assert [repr(arg) for arg in cb.call_args_list] == [repr(call('Foo.S01.x264-ABC/Foo.S01E01.x264-ABC.mkv', + scene.SceneError('Argh!'))), + repr(call('Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', + scene.SceneError('Argh!')))] + +@patch('pythonbits.scene._check_dir') +@patch('pythonbits.scene._check_file') +@patch('pythonbits.scene._yield_file_info') +def test_check_integrity_calls_check_file_correctly_for_directory_release(mock_yield_file_info, mock_check_file, mock_check_dir): + infos = ({'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'}, + {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 234, 'crc': 'ABCD1234'}) + mock_yield_file_info.return_value = infos + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01.x264-ABC', on_error=cb) is False + assert mock_check_dir.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_yield_file_info.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_check_file.call_args_list == [ + call('Foo.S01.x264-ABC/Foo.S01E01.x264-ABC.mkv', 'path/to/Foo.S01.x264-ABC/Foo.S01E01.x264-ABC.mkv', infos[0]), + call('Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', infos[1])] + assert [repr(arg) for arg in cb.call_args_list] == [] + +@patch('pythonbits.scene._check_dir') +@patch('pythonbits.scene._check_file') +@patch('pythonbits.scene._yield_file_info') +def test_check_integrity_calls_check_file_correctly_for_file_release(mock_yield_file_info, mock_check_file, mock_check_dir): + infos = ({'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'},) + mock_yield_file_info.return_value = infos + cb = Mock() + assert scene.check_integrity('path/to/Foo.S01E02.x264-ABC.mkv', on_error=cb) is False + assert mock_check_dir.call_args_list == [] + assert mock_check_file.call_args_list == [call('Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01E02.x264-ABC.mkv', infos[0])] + assert mock_yield_file_info.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert [repr(arg) for arg in cb.call_args_list] == [] + + +@patch('pythonbits.scene.search') +@patch('pythonbits.scene._guessit') +def test_release_names_returns_no_results_if_no_release_group(mock_guessit, mock_search): + mock_guessit.return_value = {'title': 'The Foo', 'season': 1, 'episode': 2} + assert scene.release_names('path/to/The.Foo.S01E02.x264.mkv') == [] + assert mock_guessit.call_args_list == [call('path/to/The.Foo.S01E02.x264.mkv')] + assert mock_search.call_args_list == [] + +@patch('pythonbits.scene.search') +@patch('pythonbits.scene._guessit') +def test_release_names_returns_no_results_if_no_title(mock_guessit, mock_search): + mock_guessit.return_value = {'release_group': 'ABC', 'season': 1, 'episode': 2} + assert scene.release_names('path/to/S01E02.x264-ABC.mkv') == [] + assert mock_guessit.call_args_list == [call('path/to/S01E02.x264-ABC.mkv')] + assert mock_search.call_args_list == [] + +@patch('pythonbits.scene.search') +@patch('pythonbits.scene._guessit') +def test_release_names_finds_something_on_first_try(mock_guessit, mock_search): + mock_guessit.return_value = {'title': 'The Foo', 'release_group': 'ABC', 'season': 1, 'episode': 2} + mock_search.return_value = ['The.Foo.S01E02.x264-ABC.mkv'] + assert scene.release_names('path/to/The.Foo.S01E02.x264-ABC.mkv') == mock_search.return_value + assert mock_guessit.call_args_list == [call('path/to/The.Foo.S01E02.x264-ABC.mkv')] + assert mock_search.call_args_list == [call(mock_guessit.return_value)] + +@patch('pythonbits.scene.search') +@patch('pythonbits.scene._guessit') +def test_release_names_finds_looks_for_season_release_on_second_try(mock_guessit, mock_search): + mock_guessit.return_value = {'title': 'The Foo', 'release_group': 'ABC', 'season': 1, 'episode': 2} + mock_search.side_effect = ([], ['The.Foo.S01.x264-ABC.mkv']) + assert scene.release_names('path/to/The.Foo.S01E02.x264-ABC.mkv') == ['The.Foo.S01.x264-ABC.mkv'] + assert mock_guessit.call_args_list == [call('path/to/The.Foo.S01E02.x264-ABC.mkv')] + assert mock_search.call_args_list == [ + call(mock_guessit.return_value), + call({'title': 'The Foo', 'release_group': 'ABC', 'season': 1})] + + +def test_check_file_on_nonscene_file_release(): + info = {'release_name': None, 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': None, 'crc': None} + assert scene._check_file('Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01E02.x264-ABC.mkv', info) is None + +def test_check_file_on_nonscene_directory_release(): + info = {'release_name': None, 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': None, 'crc': None} + assert scene._check_file('Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv', info) is None + +def test_check_file_reports_wrong_filename_in_file_release_of_original_file_release(): + info = {'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'} + msg = r'^Foo.S01E02.x264-ABC.mkv was renamed to Foo S01E02 x264-ABC.mkv$' + with pytest.raises(scene.SceneError, match=msg): + scene._check_file('Foo S01E02 x264-ABC.mkv', 'path/to/Foo S01E02 x264-ABC.mkv', info) + +def test_check_file_reports_wrong_dirname_in_directory_release_of_original_directory_release(): + info = {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'} + msg = r'^Foo.S01.x264-ABC/Foo.S01E02.x264-ABC.mkv was renamed to Foo S01 x264-ABC/Foo.S01E02.x264-ABC.mkv$' + with pytest.raises(scene.SceneError, match=msg): + scene._check_file('Foo S01 x264-ABC/Foo.S01E02.x264-ABC.mkv', 'path/to/Foo S01 x264-ABC/Foo.S01E02.x264-ABC.mkv', info) + +@patch('pythonbits.scene._path_exists', Mock(return_value=True)) +@patch('pythonbits.scene._path_getsize', Mock(return_value=123)) +def test_check_file_ignores_dirname_in_directory_release_of_original_file_release(): + info = {'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'} + assert scene._check_file('Foo S01 x264/Foo.S01E02.x264-ABC.mkv', 'path/to/Foo S01 x264/Foo.S01E02.x264-ABC.mkv', info) is True + +@patch('pythonbits.scene._path_exists', Mock(return_value=True)) +@patch('pythonbits.scene._path_getsize', Mock(return_value=123)) +def test_check_file_ignores_dirname_in_file_release_of_original_directory_release(): + info = {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '1234ABCD'} + assert scene._check_file('Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01E02.x264-ABC.mkv', info) is True + +@patch('pythonbits.scene._path_exists', Mock(return_value=True)) +@patch('pythonbits.scene._path_getsize') +def test_check_file_finds_wrong_filesize(mock_getsize): + mock_getsize.return_value = 124 + info = {'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '12345678'} + with pytest.raises(scene.SceneError, match=r'^Foo.S01E02.x264-ABC.mkv: Wrong size: 124 instead of 123 bytes$'): + scene._check_file('Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01E02.x264-ABC.mkv', info) + assert mock_getsize.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + +@patch('pythonbits.scene._path_exists', Mock(return_value=True)) +@patch('pythonbits.scene._path_getsize') +def test_check_file_finds_unmodified_release(mock_getsize): + mock_getsize.return_value = 123 + info = {'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 123, 'crc': '12345678'} + assert scene._check_file('Foo.S01E02.x264-ABC.mkv', 'path/to/Foo.S01E02.x264-ABC.mkv', info) is True + assert mock_getsize.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + + +@patch('pythonbits.scene.get_details') +def test_check_dir_finds_wrong_dirname(mock_get_details): + mock_get_details.return_value = ( + 'Foo.S01.x264-ABC', + {'Foo.S01E01.x264-ABC.mkv': {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', 'size': 123, 'crc': '12345678'}, + 'Foo.S01E02.x264-ABC.mkv': {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 234, 'crc': 'ABCD1234'}}) + with pytest.raises(scene.SceneError, match=r'^Foo.S01.x264-ABC was renamed to Foo S01 x264-ABC$'): + scene._check_dir('path/to/Foo S01 x264-ABC') + +@patch('pythonbits.scene.get_details') +def test_check_dir_finds_correct_dirname(mock_get_details): + mock_get_details.return_value = ( + 'Foo.S01.x264-ABC', + {'Foo.S01E01.x264-ABC.mkv': {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', 'size': 123, 'crc': '12345678'}, + 'Foo.S01E02.x264-ABC.mkv': {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 234, 'crc': 'ABCD1234'}}) + assert scene._check_dir('path/to/Foo.S01.x264-ABC') is True + +@patch('pythonbits.scene.get_details') +def test_check_dir_fails_to_connect(mock_get_details): + mock_get_details.side_effect = scene.APIError() + assert scene._check_dir('path/to/Foo.S01.x264-ABC') is None + + +@patch('pythonbits.scene._get') +def test_get_details_fails_to_connect(mock_get): + mock_get.side_effect = scene.APIError('Something went wrong') + with pytest.raises(scene.APIError, match='^Something went wrong$'): + scene.get_details('path/to/foo.txt') + assert mock_get.call_args_list == [call('api/details/foo')] + + +@patch('pythonbits.scene._get') +def test_get_details_finds_release(mock_get): + mock_get.return_value = mock_response(json.dumps({'name': 'Foo', + 'archived-files': [{'name': 'Foo.png', + 'size': 123, + 'crc': '1234ABCD'}]})) + assert scene.get_details('path/to/foo.txt') == ('Foo', {'Foo.png': {'release_name': 'Foo', + 'filename': 'Foo.png', + 'size': 123, + 'crc': '1234ABCD'}}) + assert mock_get.call_args_list == [call('api/details/foo')] + +@patch('pythonbits.scene._get') +def test_get_details_is_redirected_to_correct_web_page(mock_get): + mock_get.side_effect = (mock_response(mock_html('')), + mock_response(json.dumps({'name': 'Foo', + 'archived-files': [{'name': 'Foo.png', + 'size': 123, + 'crc': '1234ABCD'}]}))) + assert scene.get_details('foo') == ('Foo', {'Foo.png': {'release_name': 'Foo', + 'filename': 'Foo.png', + 'size': 123, + 'crc': '1234ABCD'}}) + assert mock_get.call_args_list == [call('api/details/foo'), + call('api/details/Foo-Bar')] + +@patch('pythonbits.scene._get') +def test_get_details_finds_nothing(mock_get): + mock_get.return_value = mock_response('') + assert scene.get_details('foo') == ('', {}) + assert mock_get.call_args_list == [call('api/details/foo')] + + +@patch('pythonbits.scene._get') +def test_search_fails_to_connect(mock_get): + mock_get.side_effect = scene.APIError() + guess = {'title': 'Foo Bar Baz'} + assert scene.search(guess) == [] + assert mock_get.call_args_list == [call('api/search/Foo/Bar/Baz')] + +@patch('pythonbits.scene._get') +def test_search_for_movie(mock_get): + mock_get.return_value = mock_response( + json.dumps({'results': [{'release': 'The Foo, the Bar and the Bazzy'}, + {'release': 'Foo Bar goes to Baz'}]})) + guess = {'title': 'Foo Bar Baz', + 'type': 'movie', + 'year': 2005, + 'release_group': 'TEHFOO'} + assert scene.search(guess) == ['The Foo, the Bar and the Bazzy', + 'Foo Bar goes to Baz'] + assert mock_get.call_args_list == [call('api/search/Foo/Bar/Baz/group:TEHFOO/2005')] + +@patch('pythonbits.scene._get') +def test_search_for_episode(mock_get): + mock_get.return_value = mock_response( + json.dumps({'results': [{'release': 'The Foo, the Bar and the Bazzy'}, + {'release': 'Foo Bar goes to Baz'}]})) + guess = {'title': 'Foo Bar Baz', + 'type': 'episode', + 'season': 3, 'episode': 5, + 'release_group': 'TEHFOO'} + assert scene.search(guess) == ['The Foo, the Bar and the Bazzy', + 'Foo Bar goes to Baz'] + assert mock_get.call_args_list == [call('api/search/Foo/Bar/Baz/group:TEHFOO/S03E05')] + +@patch('pythonbits.scene._get') +def test_search_for_season(mock_get): + mock_get.return_value = mock_response( + json.dumps({'results': [{'release': 'The Foo, the Bar and the Bazzy'}, + {'release': 'Foo Bar goes to Baz'}]})) + guess = {'title': 'Foo Bar Baz', + 'type': 'episode', + 'season': 3, + 'release_group': 'TEHFOO'} + assert scene.search(guess) == ['The Foo, the Bar and the Bazzy', + 'Foo Bar goes to Baz'] + assert mock_get.call_args_list == [call('api/search/Foo/Bar/Baz/group:TEHFOO/S03')] + + +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_season_release_of_original_season_release(mock_get_details): + mock_get_details.return_value = ( + 'Foo.S01', + {'Foo.S01E01.mkv': {'release_name': 'Foo.S01', 'filename': 'Foo.S01E01.mkv', 'size': 123, 'crc': '12345678'}, + 'Foo.S01E02.mkv': {'release_name': 'Foo.S01', 'filename': 'Foo.S01E02.mkv', 'size': 234, 'crc': 'ABCD1234'}}) + infos = tuple(scene._yield_file_info('path/to/Foo.S01')) + assert infos == ({'release_name': 'Foo.S01', 'filename': 'Foo.S01E01.mkv', 'size': 123, 'crc': '12345678'}, + {'release_name': 'Foo.S01', 'filename': 'Foo.S01E02.mkv', 'size': 234, 'crc': 'ABCD1234'}) + +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_episode_release_of_original_episode_release(mock_get_details): + mock_get_details.return_value = ( + 'Foo.S01E01', + {'Foo.S01E01.mkv': {'release_name': 'Foo.S01E01', 'filename': 'Foo.S01E01.mkv', 'size': 123, 'crc': '12345678'}}) + infos = tuple(scene._yield_file_info('path/to/Foo.S01E01.mkv')) + assert infos == ({'release_name': 'Foo.S01E01', 'filename': 'Foo.S01E01.mkv', 'size': 123, 'crc': '12345678'},) + +@patch('pythonbits.scene._os_listdir') +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_season_release_of_original_episode_release(mock_get_details, mock_listdir): + mock_get_details.side_effect = ( + ('', {}), + ('Foo.S01E01.x264-ABC', + {'Foo.S01E01.x264-ABC.mkv': {'release_name': 'Foo.S01E01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', + 'size': 123, 'crc': '12345678'}}), + ('Foo.S01E02.x264-ABC', + {'Foo.S01E02.x264-ABC.mkv': {'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', + 'size': 234, 'crc': 'ABCD1234'}}), + ('', {}), + ) + mock_listdir.return_value = ['Foo.S01E01.x264-ABC.mkv', 'Foo.S01E02.x264-ABC.mkv', 'unknown file'] + infos = tuple(scene._yield_file_info('path/to/Foo.S01.x264-ABC')) + assert infos == ({'release_name': 'Foo.S01E01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', 'size': 123, 'crc': '12345678'}, + {'release_name': 'Foo.S01E02.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 234, 'crc': 'ABCD1234'}, + {'release_name': None, 'filename': 'unknown file', 'size': None, 'crc': None}) + assert mock_listdir.call_args_list == [call('path/to/Foo.S01.x264-ABC')] + assert mock_get_details.call_args_list == [call('path/to/Foo.S01.x264-ABC'), + call('Foo.S01E01.x264-ABC.mkv'), + call('Foo.S01E02.x264-ABC.mkv'), + call('unknown file')] + +@patch('pythonbits.scene._guessit') +@patch('pythonbits.scene.search') +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_episode_release_of_original_season_release_with_enough_information( + mock_get_details, mock_search, mock_guessit): + mock_get_details.side_effect = ( + ('', {}), + ('Foo.S01.x264-ABC', + {'Foo.S01E01.x264-ABC.mkv': {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E01.x264-ABC.mkv', + 'size': 123, 'crc': '12345678'}, + 'Foo.S01E02.x264-ABC.mkv': {'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', + 'size': 234, 'crc': 'ABCD1234'}}) + ) + mock_guessit.return_value = {'release_group': 'TEHFOO', 'season': 1, 'episode': 2} + mock_search.return_value = ['Foo.S01.x264-ABC'] + infos = tuple(scene._yield_file_info('path/to/Foo.S01E02.x264-ABC.mkv')) + assert infos == ({'release_name': 'Foo.S01.x264-ABC', 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': 234, 'crc': 'ABCD1234'},) + assert mock_get_details.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv'), call('Foo.S01.x264-ABC')] + assert mock_guessit.called_with('path/to/Foo.S01E02.x264-ABC.mkv') + assert mock_search.call_args_list == [call({'release_group': 'TEHFOO', 'season': 1})] + +@patch('pythonbits.scene._guessit') +@patch('pythonbits.scene.search') +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_episode_release_of_original_season_release_with_enough_information_no_retry( + mock_get_details, mock_search, mock_guessit): + mock_get_details.return_value = ('', {}) + mock_guessit.return_value = {'release_group': 'TEHFOO', 'season': 1} + infos = tuple(scene._yield_file_info('path/to/Foo.S01E02.x264-ABC.mkv')) + assert infos == ({'release_name': None, 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': None, 'crc': None},) + assert mock_get_details.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert mock_guessit.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert mock_search.call_args_list == [] + +@patch('pythonbits.scene._guessit') +@patch('pythonbits.scene.search') +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_episode_release_of_original_season_release_with_enough_information_no_search_results( + mock_get_details, mock_search, mock_guessit): + mock_get_details.return_value = ('', {}) + mock_guessit.return_value = {'release_group': 'TEHFOO', 'season': 1, 'episode': 2} + mock_search.return_value = [] + infos = tuple(scene._yield_file_info('path/to/Foo.S01E02.x264-ABC.mkv')) + assert infos == ({'release_name': None, 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': None, 'crc': None},) + assert mock_get_details.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert mock_guessit.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert mock_search.call_args_list == [call({'release_group': 'TEHFOO', 'season': 1})] + +@patch('pythonbits.scene._guessit') +@patch('pythonbits.scene.search') +@patch('pythonbits.scene.get_details') +def test_yield_file_info_for_episode_release_of_original_season_release_with_enough_information_no_group( + mock_get_details, mock_search, mock_guessit): + mock_get_details.return_value = ('', {}) + mock_guessit.return_value = {'season': 1, 'episode': 2} + mock_search.return_value = [] + infos = tuple(scene._yield_file_info('path/to/Foo.S01E02.x264-ABC.mkv')) + assert infos == ({'release_name': None, 'filename': 'Foo.S01E02.x264-ABC.mkv', 'size': None, 'crc': None},) + assert mock_get_details.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert mock_guessit.call_args_list == [call('path/to/Foo.S01E02.x264-ABC.mkv')] + assert mock_search.call_args_list == [] + + +# Integration tests + +# The first item is the release name, all following items are file (name, size) tuples. If +# there is only one item, it's a single-file release. File size of directories is ignored. +scene_releases = ( + # Movie in release name directory + (('Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080', -1), + ('Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080/hd1080-wtl.mkv', 11743374939)), + + # Release name is identical to name of only file + extension + (('12.Rounds.Reloaded.2013.1080p.BluRay.x264-ROVERS.mkv', 7037061105),), + + # Release name is identical to name of only file + extension in lower case + (('side.effects.2013.720p.bluray.x264-sparks.mkv', 4690527189),), + + # Same as above but in directory with proper release name + (('Side.Effects.2013.720p.BluRay.x264-SPARKS', -1), + ('Side.Effects.2013.720p.BluRay.x264-SPARKS/side.effects.2013.720p.bluray.x264-sparks.mkv', 4690527189),), + + # Single episode release + (('Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD.mkv', 2342662389),), + + # Season pack of single episode releases + (('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD', -1), + ('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD/Fawlty.Towers.S01E01.1080p.BluRay.x264-SHORTBREHD.mkv', 2342662389), + ('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD/Fawlty.Towers.S01E02.1080p.BluRay.x264-SHORTBREHD.mkv', 2342806335), + ('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD/Fawlty.Towers.S01E03.1080p.BluRay.x264-SHORTBREHD.mkv', 2838653040), + ('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD/Fawlty.Towers.S01E04.1080p.BluRay.x264-SHORTBREHD.mkv', 2343647191), + ('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD/Fawlty.Towers.S01E05.1080p.BluRay.x264-SHORTBREHD.mkv', 2342958161), + ('Fawlty.Towers.S01.1080p.BluRay.x264-SHORTBREHD/Fawlty.Towers.S01E06.1080p.BluRay.x264-SHORTBREHD.mkv', 2342527200)), + + # Season pack release + (('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT', -1), + ('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT/Bored.to.Death.S01.Jonathan.Amess.Brooklyn.720p.BluRay.x264-iNGOT.mkv', 518652629), + ('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT/Bored.to.Death.S01.Making.of.720p.BluRay.x264-iNGOT.mkv', 779447228), + ('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT/Bored.to.Death.S01E03.Deleted.Scene.720p.BluRay.x264-iNGOT.mkv', 30779540), + ('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT/Bored.to.Death.S01E04.Deleted.Scene.720p.BluRay.x264-iNGOT.mkv', 138052914), + ('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT/Bored.to.Death.S01E08.Deleted.Scene.1.720p.BluRay.x264-iNGOT.mkv', 68498554), + ('Bored.to.Death.S01.EXTRAS.720p.BluRay.x264-iNGOT/Bored.to.Death.S01E08.Deleted.Scene.2.720p.BluRay.x264-iNGOT.mkv', 45583011)), + + # Single episode from season pack release + (('Bored.to.Death.S01E03.Deleted.Scene.720p.BluRay.x264-iNGOT.mkv', 30779540),), +) + +non_scene_releases = ( + ('Rampart.2011.1080p.Bluray.DD5.1.x264-DON.mkv', 123), + ('La.Bamba.1987.LE.Bluray.1080p.DTS-HD.x264-Grym.mkv', 123), + ('Damnation.S01.720p.AMZN.WEB-DL.DDP5.1.H.264-AJP69', 123), + ('Damnation.S01E03.One.Penny.720p.AMZN.WEB-DL.DD+5.1.H.264-AJP69.mkv', 123), + ('The Film Without a Group (1984).mkv', 123), +) + +capture_requests = False +real_scene_get = scene._get +capture_dir = os.path.join(os.path.dirname(__file__), 'scene_responses') + +def capture_request(path): + filepath = os.path.join(capture_dir, path.replace('/', '_') + '.response') + if not capture_requests and os.path.exists(filepath): + with open(filepath, 'r') as f: + return mock_response(f.read()) + else: + response = real_scene_get(path) + if not os.path.exists(capture_dir): + os.mkdir(capture_dir) + with open(filepath, 'w') as f: + f.write(response.text) + return response + +@contextlib.contextmanager +def mock_files(*filespecs, path_prefix=''): + print('Mocking files:') + for fs in filespecs: + print(fs) + + def mock_exists(path): + for path_,size in filespecs: + if os.path.join(path_prefix, path_) == path: + return True + return False + + def mock_getsize(path): + for path_,size in filespecs: + if os.path.join(path_prefix, path_) == path: + return size + raise FileNotFoundError(path) + + exists_p = patch('pythonbits.scene._path_exists', mock_exists) + filesize_p = patch('pythonbits.scene._path_getsize', mock_getsize) + exists_p.start() + filesize_p.start() + yield + exists_p.stop() + filesize_p.stop() + +@pytest.mark.parametrize('content', scene_releases, ids=(fs[0][0] for fs in scene_releases)) +@patch('pythonbits.scene._get', capture_request) +@patch('pythonbits.bb.prompt.yesno') +@patch('pythonbits.scene._os_listdir') +def test_detection_of_unmodified_scene_release(mock_listdir, mock_prompt_yesno, content): + release_name = content[0][0] + mock_listdir.return_value = [os.path.basename(fs[0]) for fs in content[1:]] + s = bb.VideoSubmission(path='path/to/' + release_name) + with mock_files(*content, path_prefix='path/to'): + assert s['scene'] is True + assert mock_prompt_yesno.call_args_list == [] + +@pytest.mark.parametrize('content', scene_releases, ids=(fs[0][0] for fs in scene_releases)) +@patch('pythonbits.scene._get', capture_request) +@patch('sys.exit') +@patch('pythonbits.bb.prompt.yesno') +@patch('pythonbits.scene._os_listdir') +def test_detection_of_scene_release_with_wrong_file_size(mock_listdir, mock_prompt_yesno, mock_exit, content): + mock_prompt_yesno.return_value = False + mock_exit.return_value = '' + mock_listdir.return_value = [os.path.basename(fs[0]) for fs in content[1:]] + release_name = content[0][0] + modified_content = ((relpath, size - 1) for relpath,size in content) + with mock_files(*modified_content, path_prefix='path/to'): + # User wants to abort + mock_prompt_yesno.side_effect = (True,) + assert bb.VideoSubmission(path='path/to/' + release_name)['scene'] == '' + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True)] + assert mock_exit.call_args_list == [call(1)] + mock_prompt_yesno.reset_mock() + mock_exit.reset_mock() + + # User wants to submit anyway but not as scene + mock_prompt_yesno.side_effect = (False, False) + assert bb.VideoSubmission(path='path/to/' + release_name)['scene'] is False + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True), + call('Is this a scene release?', default=False)] + assert mock_exit.call_args_list == [] + mock_prompt_yesno.reset_mock() + mock_exit.reset_mock() + + # User wants to submit anyway and insists on scene release + mock_prompt_yesno.side_effect = (False, True) + assert bb.VideoSubmission(path='path/to/' + release_name)['scene'] is True + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True), + call('Is this a scene release?', default=False)] + assert mock_exit.call_args_list == [] + +@pytest.mark.parametrize('content', scene_releases, ids=(fs[0][0] for fs in scene_releases)) +@patch('pythonbits.scene._get', capture_request) +@patch('sys.exit') +@patch('pythonbits.bb.prompt.yesno') +@patch('pythonbits.scene._os_listdir') +def test_detection_of_scene_release_with_wrong_release_name(mock_listdir, mock_prompt_yesno, mock_exit, content): + mock_prompt_yesno.return_value = False + mock_exit.return_value = '' + mock_listdir.return_value = [os.path.basename(fs[0]) for fs in content[1:]] + correct_release_name = content[0][0] + wrong_release_name = correct_release_name.lower().replace('.', ' ', 1) + with mock_files(*content, path_prefix='path/to'): + # User wants to abort + mock_prompt_yesno.side_effect = (True,) + assert bb.VideoSubmission(path='path/to/' + wrong_release_name)['scene'] == '' + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True)] + assert mock_exit.call_args_list == [call(1)] + mock_prompt_yesno.reset_mock() + mock_exit.reset_mock() + + # User wants to submit anyway but not as scene + mock_prompt_yesno.side_effect = (False, False) + assert bb.VideoSubmission(path='path/to/' + wrong_release_name)['scene'] is False + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True), + call('Is this a scene release?', default=False)] + assert mock_exit.call_args_list == [] + mock_prompt_yesno.reset_mock() + mock_exit.reset_mock() + + # User wants to submit anyway and insists on scene release + mock_prompt_yesno.side_effect = (False, True) + assert bb.VideoSubmission(path='path/to/' + wrong_release_name)['scene'] is True + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True), + call('Is this a scene release?', default=False)] + assert mock_exit.call_args_list == [] + +@pytest.mark.parametrize('content', non_scene_releases, ids=(fs[0] for fs in non_scene_releases)) +@patch('pythonbits.scene._get', capture_request) +@patch('sys.exit') +@patch('pythonbits.bb.prompt.yesno') +@patch('pythonbits.scene._os_listdir') +def test_detection_of_non_scene_release(mock_listdir, mock_prompt_yesno, mock_exit, content): + release_name = content[0] + s = bb.VideoSubmission(path='path/to/' + release_name) + with mock_files(*content, path_prefix='path/to'): + assert s['scene'] is False + assert mock_prompt_yesno.call_args_list == [] + +@patch('pythonbits.scene._get', capture_request) +@patch('sys.exit') +@patch('pythonbits.bb.prompt.yesno') +def test_workaround_for_group_in_front(mock_prompt_yesno, mock_exit): + mock_prompt_yesno.side_effect = (True,) + mock_exit.return_value = '' + wrong_release_name = 'voa-the_omega_man_x264_bluray.mkv' + content = (wrong_release_name, 123) + with mock_files(content, path_prefix='path/to'): + assert bb.VideoSubmission(path='path/to/' + wrong_release_name)['scene'] == '' + assert mock_prompt_yesno.call_args_list == [call('Abort?', default=True)] + assert mock_exit.call_args_list == [call(1)] + +@patch('pythonbits.scene._get', capture_request) +@patch('sys.exit') +@patch('pythonbits.bb.prompt.yesno') +def test_renaming_is_ok_if_file_name_is_release_name(mock_prompt_yesno, mock_exit): + mock_prompt_yesno.return_value = False + mock_exit.return_value = '' + acceptable_release_name = 'Walk.the.Line.Extended.Cut.2005.1080p.BluRay.x264-HD1080.mkv' + content = (acceptable_release_name, 11743374939) + with mock_files(content, path_prefix='path/to'): + assert bb.VideoSubmission(path='path/to/' + acceptable_release_name)['scene'] is True + assert mock_prompt_yesno.call_args_list == [] + assert mock_exit.call_args_list == []