def test_cache(self, mocked_expired, execute_task): persist['auth_tokens'] = {'default': None} task = execute_task('test_search_cache') entry = task.find_entry(tvdb_id=73255) # Force tvdb lazy eval assert entry['afield'] with Session() as session: # Ensure search cache was added search_results = session.query(TVDBSearchResult).all() assert len(search_results) == 3 aliases = ['house', 'house m.d.', 'house md'] for search_result in search_results: assert search_result.series assert search_result.search in aliases # No requests should be sent as we restore from cache with mock.patch( 'requests.sessions.Session.request', side_effect=Exception('TVDB should restore from cache'), ): lookup_series('house m.d.', session=session)
def items(self): if self._items is None: try: req = plugin_api_tvdb.TVDBRequest( username=self.config['username'], account_id=self.config['account_id'], api_key=self.config['api_key'], ).get('user/favorites') series_ids = [int(f_id) for f_id in req['favorites'] if f_id != ''] except RequestException as e: raise PluginError('Error retrieving favorites from thetvdb: %s' % str(e)) self._items = [] for series_id in series_ids: # Lookup the series name from the id try: series = plugin_api_tvdb.lookup_series( tvdb_id=series_id, language=self.config.get('language') ) except LookupError as e: log.error('Error looking up %s from thetvdb: %s' % (series_id, e.args[0])) else: series_name = series.name if self.config.get('strip_dates'): # Remove year from end of series name if present series_name, _ = split_title_year(series_name) entry = Entry() entry['title'] = entry['series_name'] = series_name entry['url'] = 'http://thetvdb.com/index.php?tab=series&id={}'.format( str(series.id) ) entry['tvdb_id'] = str(series.id) self._items.append(entry) return self._items
def get(self, title, session=None): """TheTVDB series lookup""" args = series_parser.parse_args() language = args['language'] try: tvdb_id = int(title) except ValueError: tvdb_id = None kwargs = {'session': session, 'language': language} if tvdb_id: kwargs['tvdb_id'] = tvdb_id else: kwargs['name'] = title try: series = lookup_series(**kwargs) except LookupError as e: raise NotFoundError(e.args[0]) result = series.to_dict() if args.get('include_actors'): result['actors'] = series.actors return jsonify(result)
def series_lookup(self, entry, language, field_map, session=None): try: series = plugin_api_tvdb.lookup_series( entry.get('series_name', eval_lazy=False), tvdb_id=entry.get('tvdb_id', eval_lazy=False), language=entry.get('language', language), session=session, ) entry.update_using_map(field_map, series) except LookupError as e: logger.debug('Error looking up tvdb series information for {}: {}', entry['title'], e.args[0]) return entry
def series_lookup(self, entry, language, field_map, session=None): try: series = plugin_api_tvdb.lookup_series( entry.get('series_name', eval_lazy=False), tvdb_id=entry.get('tvdb_id', eval_lazy=False), language=entry.get('language', language), session=session, ) entry.update_using_map(field_map, series) except LookupError as e: log.debug( 'Error looking up tvdb series information for %s: %s', entry['title'], e.args[0] ) return entry
def process(self): imdb_lookup = plugin.get_plugin_by_name('imdb_lookup').instance self.changes.sort() udata = load_uoccin_data(self.folder) for line in self.changes: tmp = line.split('|') typ = tmp[1] tid = tmp[2] fld = tmp[3] val = tmp[4] self.log.verbose( 'processing: type=%s, target=%s, field=%s, value=%s' % (typ, tid, fld, val)) if typ == 'movie': # default mov = udata['movies'].setdefault( tid, { 'name': 'N/A', 'watchlist': False, 'collected': False, 'watched': False }) # movie title is unknown at this time fake = Entry() fake['url'] = 'http://www.imdb.com/title/' + tid fake['imdb_id'] = tid try: imdb_lookup.lookup(fake) mov['name'] = fake.get('imdb_name') except plugin.PluginError: self.log.warning( 'Unable to lookup movie %s from imdb, using raw name.' % tid) # setting if fld == 'watchlist': mov['watchlist'] = val == 'true' elif fld == 'collected': mov['collected'] = val == 'true' elif fld == 'watched': mov['watched'] = val == 'true' elif fld == 'tags': mov['tags'] = re.split(',\s*', val) elif fld == 'subtitles': mov['subtitles'] = re.split(',\s*', val) elif fld == 'rating': mov['rating'] = int(val) # cleaning if not (mov['watchlist'] or mov['collected'] or mov['watched']): self.log.verbose('deleting unused section: movies\%s' % tid) udata['movies'].pop(tid) elif typ == 'series': tmp = tid.split('.') sid = tmp[0] sno = tmp[1] if len(tmp) > 2 else None eno = tmp[2] if len(tmp) > 2 else None # default ser = udata['series'].setdefault( sid, { 'name': 'N/A', 'watchlist': False, 'collected': {}, 'watched': {} }) # series name is unknown at this time try: series = lookup_series(tvdb_id=sid) ser['name'] = series.name except LookupError: self.log.warning( 'Unable to lookup series %s from tvdb, using raw name.' % sid) # setting if fld == 'watchlist': ser['watchlist'] = val == 'true' elif fld == 'tags': ser['tags'] = re.split(',\s*', val) elif fld == 'rating': ser['rating'] = int(val) elif sno is None or eno is None: self.log.warning( 'invalid line "%s": season and episode numbers are required' % line) elif fld == 'collected': season = ser['collected'].setdefault(sno, {}) if val == 'true': season.setdefault(eno, []) else: if eno in season: season.pop(eno) if not season: self.log.verbose( 'deleting unused section: series\%s\collected\%s' % (sid, sno)) ser['collected'].pop(sno) elif fld == 'subtitles': ser['collected'].setdefault(sno, {})[eno] = re.split( ',\s*', val) elif fld == 'watched': season = ser['watched'].setdefault(sno, []) if val == 'true': season = ser['watched'][sno] = list( set(season) | set([int(eno)])) elif int(eno) in season: season.remove(int(eno)) season.sort() if not season: self.log.debug( 'deleting unused section: series\%s\watched\%s' % (sid, sno)) ser['watched'].pop(sno) # cleaning if not (ser['watchlist'] or ser['collected'] or ser['watched']): self.log.debug('deleting unused section: series\%s' % sid) udata['series'].pop(sid) else: self.log.warning('invalid element type "%s"' % typ) # save the updated uoccin.json ufile = os.path.join(self.folder, 'uoccin.json') try: text = json.dumps(udata, sort_keys=True, indent=4, separators=(',', ': ')) with open(ufile, 'w') as f: f.write(text) except Exception as err: self.log.debug('error writing %s: %s' % (ufile, err)) raise plugin.PluginError('error writing %s: %s' % (ufile, err))
def process(self): imdb_lookup = plugin.get_plugin_by_name('imdb_lookup').instance self.changes.sort() udata = load_uoccin_data(self.folder) for line in self.changes: tmp = line.split('|') typ = tmp[1] tid = tmp[2] fld = tmp[3] val = tmp[4] self.log.verbose('processing: type=%s, target=%s, field=%s, value=%s' % (typ, tid, fld, val)) if typ == 'movie': # default mov = udata['movies'].setdefault(tid, {'name': 'N/A', 'watchlist': False, 'collected': False, 'watched': False}) # movie title is unknown at this time fake = Entry() fake['url'] = 'http://www.imdb.com/title/' + tid fake['imdb_id'] = tid try: imdb_lookup.lookup(fake) mov['name'] = fake.get('imdb_name') except plugin.PluginError: self.log.warning('Unable to lookup movie %s from imdb, using raw name.' % tid) # setting if fld == 'watchlist': mov['watchlist'] = val == 'true' elif fld == 'collected': mov['collected'] = val == 'true' elif fld == 'watched': mov['watched'] = val == 'true' elif fld == 'tags': mov['tags'] = re.split(',\s*', val) elif fld == 'subtitles': mov['subtitles'] = re.split(',\s*', val) elif fld == 'rating': mov['rating'] = int(val) # cleaning if not (mov['watchlist'] or mov['collected'] or mov['watched']): self.log.verbose('deleting unused section: movies\%s' % tid) udata['movies'].pop(tid) elif typ == 'series': tmp = tid.split('.') sid = tmp[0] sno = tmp[1] if len(tmp) > 2 else None eno = tmp[2] if len(tmp) > 2 else None # default ser = udata['series'].setdefault(sid, {'name': 'N/A', 'watchlist': False, 'collected': {}, 'watched': {}}) # series name is unknown at this time try: series = lookup_series(tvdb_id=sid) ser['name'] = series.name except LookupError: self.log.warning('Unable to lookup series %s from tvdb, using raw name.' % sid) # setting if fld == 'watchlist': ser['watchlist'] = val == 'true' elif fld == 'tags': ser['tags'] = re.split(',\s*', val) elif fld == 'rating': ser['rating'] = int(val) elif sno is None or eno is None: self.log.warning('invalid line "%s": season and episode numbers are required' % line) elif fld == 'collected': season = ser['collected'].setdefault(sno, {}) if val == 'true': season.setdefault(eno, []) else: if eno in season: season.pop(eno) if not season: self.log.verbose('deleting unused section: series\%s\collected\%s' % (sid, sno)) ser['collected'].pop(sno) elif fld == 'subtitles': ser['collected'].setdefault(sno, {})[eno] = re.split(',\s*', val) elif fld == 'watched': season = ser['watched'].setdefault(sno, []) if val == 'true': season = ser['watched'][sno] = list(set(season) | set([int(eno)])) elif int(eno) in season: season.remove(int(eno)) season.sort() if not season: self.log.debug('deleting unused section: series\%s\watched\%s' % (sid, sno)) ser['watched'].pop(sno) # cleaning if not (ser['watchlist'] or ser['collected'] or ser['watched']): self.log.debug('deleting unused section: series\%s' % sid) udata['series'].pop(sid) else: self.log.warning('invalid element type "%s"' % typ) # save the updated uoccin.json ufile = os.path.join(self.folder, 'uoccin.json') try: text = json.dumps(udata, sort_keys=True, indent=4, separators=(',', ': ')) with open(ufile, 'w') as f: f.write(text) except Exception as err: self.log.debug('error writing %s: %s' % (ufile, err)) raise plugin.PluginError('error writing %s: %s' % (ufile, err))
def on_task_input(self, task, config): """Creates an entry for each item in your uoccin watchlist. Example:: uoccin_emit: path: /path/to/gdrive/uoccin type: series tags: [ 'favorite', 'hires' ] check_tags: all Options path and type are required while the others are for filtering: - 'any' will include all the items marked with one or more tags in the list - 'all' will only include the items marked with all the listed tags - 'none' will only include the items not marked with any of the listed tags. The entries created will have a valid imdb/tvdb url and id. """ imdb_lookup = plugin.get_plugin_by_name('imdb_lookup').instance udata = load_uoccin_data(config['path']) section = udata['movies'] if config['type'] == 'movies' else udata['series'] entries = [] for eid, itm in list(section.items()): if not itm['watchlist']: continue if 'tags' in config: n = len(set(config['tags']) & set(itm.get('tags', []))) if config['check_tags'] == 'any' and n <= 0: continue if config['check_tags'] == 'all' and n != len(config['tags']): continue if config['check_tags'] == 'none' and n > 0: continue if config['type'] == 'movies': entry = Entry() entry['url'] = 'http://www.imdb.com/title/' + eid entry['imdb_id'] = eid if itm['name'] != 'N/A': entry['title'] = itm['name'] else: try: imdb_lookup.lookup(entry) except plugin.PluginError as e: self.log.trace('entry %s imdb failed (%s)' % (entry['imdb_id'], e.value)) continue entry['title'] = entry.get('imdb_name') if 'tags' in itm: entry['uoccin_tags'] = itm['tags'] if entry.isvalid(): entries.append(entry) else: self.log.debug('Invalid entry created? %s' % entry) else: sname = itm['name'] try: sname = lookup_series(tvdb_id=eid).name except LookupError: self.log.warning('Unable to lookup series %s from tvdb, using raw name.' % eid) surl = 'http://thetvdb.com/?tab=series&id=' + eid if config['type'] == 'series': entry = Entry() entry['url'] = surl entry['title'] = sname entry['tvdb_id'] = eid if 'tags' in itm: entry['uoccin_tags'] = itm['tags'] if entry.isvalid(): entries.append(entry) else: self.log.debug('Invalid entry created? %s' % entry) elif config['ep_flags'] == 'collected': slist = itm.get('collected', {}) for sno in list(slist.keys()): for eno in slist[sno]: entry = Entry() entry['url'] = surl entry['title'] = '%s S%02dE%02d' % (sname, int(sno), int(eno)) entry['tvdb_id'] = eid if entry.isvalid(): entries.append(entry) else: self.log.debug('Invalid entry created? %s' % entry) else: slist = itm.get('watched', {}) for sno in list(slist.keys()): for eno in slist[sno]: entry = Entry() entry['url'] = surl entry['title'] = '%s S%02dE%02d' % (sname, int(sno), eno) entry['tvdb_id'] = eid if entry.isvalid(): entries.append(entry) else: self.log.debug('Invalid entry created? %s' % entry) entries.sort(key=lambda x: x['title']) return entries