def resource_get_failed(self): """Get data from the failed.db/failed table.""" limit = self.get_argument('limit' '').strip() failed_db_con = db.DBConnection('failed.db') if int(limit): sql_results = failed_db_con.select( 'SELECT ROWID AS id, release, size, provider ' 'FROM failed ' 'LIMIT ?', [limit]) else: sql_results = failed_db_con.select( 'SELECT ROWID AS id, release, size, provider ' 'FROM failed') results = [] for result in sql_results: provider = providers.get_provider_class( GenericProvider.make_id(result['provider'])) results.append({ 'id': result['id'], 'release': result['release'], 'size': result['size'], 'provider': { 'id': provider.get_id(), 'name': provider.name, 'imageName': provider.image_name() } }) return self._ok(data=results)
def test_make_id(self): test_cases = { None: '', 123: '123', 12.3: '12_3', 0: '', -123: '_123', -12.3: '_12_3', '': '', ' ': '', '123': '123', ' 123 ': '123', '12.3': '12_3', ' 12.3 ': '12_3', '0': '0', ' 0 ': '0', '-123': '_123', ' -123 ': '_123', '-12.3': '_12_3', ' -12.3 ': '_12_3', 'abc': 'abc', ' abc ': 'abc', 'ABC': 'abc', ' ABC ': 'abc', '.def': '_def', 'g,hi': 'g_hi', 'jk!l': 'jk_l', 'mno?': 'mno_', '_pqr$': '_pqr_', } unicode_test_cases = { u'': '', u' ': '', u'123': '123', u' 123 ': '123', u'12.3': '12_3', u' 12.3 ': '12_3', u'0': '0', u' 0 ': '0', u'-123': '_123', u' -123 ': '_123', u'-12.3': '_12_3', u' -12.3 ': '_12_3', u'abc': 'abc', u' abc ': 'abc', u'ABC': 'abc', u' ABC ': 'abc', u'.def': '_def', u'g,hi': 'g_hi', u'jk!l': 'jk_l', u'mno?': 'mno_', u'_pqr$': '_pqr_', } for test in test_cases, unicode_test_cases: for (name, result) in iteritems(test): self.assertEqual(GenericProvider.make_id(name), result)
def test_make_id(self): test_cases = { None: '', 123: '123', 12.3: '12_3', 0: '', -123: '_123', -12.3: '_12_3', '': '', ' ': '', '123': '123', ' 123 ': '123', '12.3': '12_3', ' 12.3 ': '12_3', '0': '0', ' 0 ': '0', '-123': '_123', ' -123 ': '_123', '-12.3': '_12_3', ' -12.3 ': '_12_3', 'abc': 'abc', ' abc ': 'abc', 'ABC': 'abc', ' ABC ': 'abc', '.def': '_def', 'g,hi': 'g_hi', 'jk!l': 'jk_l', 'mno?': 'mno_', '_pqr$': '_pqr_', } unicode_test_cases = { u'': '', u' ': '', u'123': '123', u' 123 ': '123', u'12.3': '12_3', u' 12.3 ': '12_3', u'0': '0', u' 0 ': '0', u'-123': '_123', u' -123 ': '_123', u'-12.3': '_12_3', u' -12.3 ': '_12_3', u'abc': 'abc', u' abc ': 'abc', u'ABC': 'abc', u' ABC ': 'abc', u'.def': '_def', u'g,hi': 'g_hi', u'jk!l': 'jk_l', u'mno?': 'mno_', u'_pqr$': '_pqr_', } for test in test_cases, unicode_test_cases: for (name, result) in iteritems(test): self.assertEqual(GenericProvider.make_id(name), result)
def data_generator(): """Read and paginate history records.""" start = arg_limit * (arg_page - 1) for item in results[start:start + arg_limit]: provider = {} release_group = None release_name = None file_name = None subtitle_language = None if item['action'] in (SNATCHED, FAILED): provider.update({ 'id': GenericProvider.make_id(item['provider']), 'name': item['provider'] }) release_name = item['resource'] if item['action'] == DOWNLOADED: release_group = item['provider'] file_name = item['resource'] if item['action'] == SUBTITLED: subtitle_language = item['resource'] if item['action'] == SUBTITLED: subtitle_language = item['resource'] yield { 'id': item['rowid'], 'series': SeriesIdentifier.from_id(item['indexer_id'], item['showid']).slug, 'status': item['action'], 'statusName': statusStrings.get(item['action']), 'actionDate': item['date'], 'quality': item['quality'], 'resource': basename(item['resource']), 'size': item['size'], 'properTags': item['proper_tags'], 'season': item['season'], 'episode': item['episode'], 'manuallySearched': bool(item['manually_searched']), 'infoHash': item['info_hash'], 'provider': provider, 'release_name': release_name, 'releaseGroup': release_group, 'fileName': file_name, 'subtitleLanguage': subtitle_language }
def create_history_item(history_row, compact=False): """ Create a history object, using the data from a history db row item. Calculate additional data, where needed. :param history_row: a main.db history row. :param compact: A boolean indicating if this is used for a compact layout. :returns: A dict with history information. """ from medusa.providers import get_provider_class from medusa.providers.generic_provider import GenericProvider from medusa.tv.series import Series, SeriesIdentifier provider = {} release_group = None release_name = None file_name = None subtitle_language = None show_slug = None client_status = None show_slug = None show_title = 'Missing Show' if history_row['action'] in (SNATCHED, FAILED): provider_id = GenericProvider.make_id(history_row['provider']) provider_class = get_provider_class(provider_id) if provider_class: provider.update({ 'id': provider_class.get_id(), 'name': provider_class.name, 'imageName': provider_class.image_name() }) else: provider.update({ 'id': provider_id, 'name': history_row['provider'], 'imageName': f'{provider_id}.png' }) release_name = history_row['resource'] if history_row['action'] == DOWNLOADED: release_group = history_row['provider'] file_name = history_row['resource'] if history_row['action'] == SUBTITLED: subtitle_language = history_row['resource'] provider['name'] = history_row['provider'] if history_row['client_status'] is not None: status = ClientStatus(status=history_row['client_status']) client_status = { 'status': [s.value for s in status], 'string': status.status_to_array_string() } if history_row['indexer_id'] and history_row['showid']: identifier = SeriesIdentifier.from_id(history_row['indexer_id'], history_row['showid']) show_slug = identifier.slug show = Series.find_by_identifier(identifier) if show: show_title = show.title history_row['episodeTitle'] = '{0} - s{1:02d}e{2:02d}'.format( show_title, history_row['season'], history_row['episode']) return { 'series': show_slug, 'status': history_row['action'], 'statusName': statusStrings.get(history_row['action']), 'actionDate': history_row['date'], 'quality': history_row['quality'], 'resource': basename(history_row['resource']), 'size': history_row['size'], 'properTags': history_row['proper_tags'], 'season': history_row['season'], 'episode': history_row['episode'], 'episodeTitle': history_row['episodeTitle'], 'manuallySearched': bool(history_row['manually_searched']), 'infoHash': history_row['info_hash'], 'provider': provider, 'releaseName': release_name, 'releaseGroup': release_group, 'fileName': file_name, 'subtitleLanguage': subtitle_language, 'showSlug': show_slug, 'showTitle': show_title, 'providerType': history_row['provider_type'], 'clientStatus': client_status, 'partOfBatch': bool(history_row['part_of_batch']) }
def _check_torrent_ratio(self, client): """Perform configured action after seed ratio reached (or by configuration).""" if app.TORRENT_SEED_ACTION == '': log.debug( 'No global ratio or provider ratio configured for {client}, skipping actions.', {'client': client.name}) return # The base ClienStatus to include in the query. include = [ ClientStatusEnum.COMPLETED.value | ClientStatusEnum.POSTPROCESSED.value ] from medusa.providers import get_provider_class from medusa.providers.generic_provider import GenericProvider for history_result in self._get_history_results_from_db( 'torrent', include_status=include, ): provider_id = GenericProvider.make_id(history_result['provider']) provider = get_provider_class(provider_id) if not provider: log.debug( 'Skip provider {provider} with id: {provider_id}', { 'provider': history_result['provider'], 'provider_id': provider_id }) continue provider_ratio = -1 if provider.ratio == '' else provider.ratio try: desired_ratio = provider_ratio if provider_ratio > -1 else app.TORRENT_SEED_RATIO except TypeError: log.warning( 'could not get provider ratio {ratio} for provider {provider}', { 'ratio': provider_ratio, 'provider': provider_id }) desired_ratio = app.TORRENT_SEED_RATIO if desired_ratio == -1: # Not sure if this option is of use. continue try: status = client.get_status(history_result['info_hash']) except DownloadClientConnectionException as error: log.warning( 'The client cannot be reached or authentication is failing.' '\nAbandon check torrent ratio. error: {error}', {'error': error}) continue if not status: continue action_after_seeding = desired_ratio * 1.0 > 0.0 if status.ratio < desired_ratio * action_after_seeding: continue if not action_after_seeding: log.debug('Action after seeding disabled') log.debug( 'Ratio of ({ratio}) reached for torrent {info_hash}, starting action: {action}.', { 'ratio': status.ratio, 'info_hash': history_result['info_hash'], 'action': app.TORRENT_SEED_ACTION }) hash = history_result['info_hash'] # Perform configured action. if app.TORRENT_SEED_ACTION == 'remove': # Remove torrent from client client.remove_torrent(hash) elif app.TORRENT_SEED_ACTION == 'pause': # Pause torrent on client client.pause_torrent(hash) elif app.TORRENT_SEED_ACTION == 'remove_with_data': # Remove torrent and all files from disk (not implemented for each client!) client.remove_torrent_data(hash) else: log.debug('Invalid action {action}', {'action': app.TORRENT_SEED_ACTION}) continue self.save_status_to_history( history_result, ClientStatus(status_string='SeededAction'))
def data_generator_compact(): """ Read and paginate history records. Results are provided grouped per showid+season+episode. The results are flattened into a structure of [{'actionDate': .., 'showSlug':.., 'rows':Array(history_items)},] """ start = arg_limit * (arg_page - 1) for compact_item in list(results.values())[start:start + arg_limit]: return_item = {'rows': []} for item in compact_item: provider = {} release_group = None release_name = None file_name = None subtitle_language = None if item['action'] in (SNATCHED, FAILED): provider_id = GenericProvider.make_id(item['provider']) provider_class = get_provider_class(provider_id) if provider_class: provider.update({ 'id': provider_class.get_id(), 'name': provider_class.name, 'imageName': provider_class.image_name() }) else: provider.update({ 'id': provider_id, 'name': item['provider'], 'imageName': f'{provider_id}.png' }) release_name = item['resource'] if item['action'] == DOWNLOADED: release_group = item['provider'] file_name = item['resource'] if item['action'] == SUBTITLED: subtitle_language = item['resource'] provider['name'] = item['provider'] item['showSlug'] = None item['showTitle'] = 'Missing Show' if item['indexer_id'] and item['showid']: identifier = SeriesIdentifier.from_id( item['indexer_id'], item['showid']) item['showSlug'] = identifier.slug show = Series.find_by_identifier(identifier) if show: item['showTitle'] = show.title return_item['actionDate'] = item['date'] return_item['showSlug'] = item['showslug'] return_item[ 'episodeTitle'] = '{0} - s{1:02d}e{2:02d}'.format( item['showTitle'], item['season'], item['episode']) return_item['quality'] = item['quality'] return_item['rows'].append({ 'actionDate': item['date'], 'id': item['rowid'], 'series': item['showSlug'], 'status': item['action'], 'statusName': statusStrings.get(item['action']), 'quality': item['quality'], 'resource': basename(item['resource']), 'size': item['size'], 'properTags': item['proper_tags'], 'season': item['season'], 'episode': item['episode'], 'manuallySearched': bool(item['manually_searched']), 'infoHash': item['info_hash'], 'provider': provider, 'release_name': release_name, 'releaseGroup': release_group, 'fileName': file_name, 'subtitleLanguage': subtitle_language, 'showSlug': item['showslug'], 'showTitle': item['showTitle'] }) yield return_item
def data_generator(): """Read and paginate history records.""" start = arg_limit * (arg_page - 1) for item in results[start:start + arg_limit]: provider = {} release_group = None release_name = None file_name = None subtitle_language = None show_slug = None client_status = None show_slug = None show_title = 'Missing Show' if item['action'] in (SNATCHED, FAILED): provider_id = GenericProvider.make_id(item['provider']) provider_class = get_provider_class(provider_id) if provider_class: provider.update({ 'id': provider_class.get_id(), 'name': provider_class.name, 'imageName': provider_class.image_name() }) else: provider.update({ 'id': provider_id, 'name': item['provider'], 'imageName': f'{provider_id}.png' }) release_name = item['resource'] if item['action'] == DOWNLOADED: release_group = item['provider'] file_name = item['resource'] if item['action'] == SUBTITLED: subtitle_language = item['resource'] provider['name'] = item['provider'] if item['client_status'] is not None: status = ClientStatus(status=item['client_status']) client_status = { 'status': [s.value for s in status], 'string': status.status_to_array_string() } if item['indexer_id'] and item['showid']: identifier = SeriesIdentifier.from_id( item['indexer_id'], item['showid']) show_slug = identifier.slug show = Series.find_by_identifier(identifier) if show: show_title = show.title item['episodeTitle'] = '{0} - s{1:02d}e{2:02d}'.format( show_title, item['season'], item['episode']) yield { 'id': item['rowid'], 'series': show_slug, 'status': item['action'], 'statusName': statusStrings.get(item['action']), 'actionDate': item['date'], 'quality': item['quality'], 'resource': basename(item['resource']), 'size': item['size'], 'properTags': item['proper_tags'], 'season': item['season'], 'episode': item['episode'], 'episodeTitle': item['episodeTitle'], 'manuallySearched': bool(item['manually_searched']), 'infoHash': item['info_hash'], 'provider': provider, 'releaseName': release_name, 'releaseGroup': release_group, 'fileName': file_name, 'subtitleLanguage': subtitle_language, 'showSlug': show_slug, 'showTitle': show_title, 'providerType': item['provider_type'], 'clientStatus': client_status, 'partOfBatch': bool(item['part_of_batch']) }