def on_task_output(self, task, config): """Add accepted episodes and/or movies to uoccin's collection""" series = {} movies = {} for entry in task.accepted: if all(field in entry for field in ['tvdb_id', 'series_season', 'series_episode']): eid = '%s.S%02dE%02d' % (entry['tvdb_id'], entry['series_season'], entry['series_episode']) if not eid in series: # we can have more than one (different release/quality) series[eid] = [] if self.acquire and 'subtitles' in entry: subs = series[eid] series[eid] = list(set(subs + entry['subtitles'])) elif all(field in entry for field in ['imdb_id', 'movie_name']): eid = entry['imdb_id'] if not eid in movies: # we can have more than one (different release/quality) movies[eid] = {'name': entry.get('imdb_name', entry['movie_name'])} if self.acquire and 'subtitles' in entry: subs = movies[eid]['subtitles'] if 'subtitles' in movies[eid] else [] movies[eid]['subtitles'] = list(set(subs + entry['subtitles'])) if series: dest = os.path.join(config, 'series.collected.json') data = {} if os.path.exists(dest): with open(dest, 'r') as f: data = json.load(f) for eid in series: if self.acquire: log.info('adding/updating episode %s to Uoccin collection' % eid) data[eid] = series[eid] elif eid in data: log.info('removing episode %s from Uoccin collection' % eid) data.pop(eid) text = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) with open(dest, 'w') as f: f.write(text) log.debug('Uoccin episodes collection updated') if movies: dest = os.path.join(config, 'movies.collected.json') data = {} if os.path.exists(dest): with open(dest, 'r') as f: data = json.load(f) for eid in movies: if self.acquire: log.info('adding/updating movie %s to Uoccin collection' % eid) data[eid] = movies[eid] elif eid in data: log.info('removing movie %s from Uoccin collection' % eid) data.pop(eid) text = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) with open(dest, 'w') as f: f.write(text) log.debug('Uoccin movies collection updated')
def load_uoccin_data(path): udata = {} ufile = os.path.join(path, 'uoccin.json') if os.path.exists(ufile): try: with open(ufile, 'r') as f: udata = json.load(f) except Exception as err: raise plugin.PluginError('error reading %s: %s' % (ufile, err)) udata.setdefault('movies', {}) udata.setdefault('series', {}) return udata
def get_json(url): try: log.debug('fetching json at %s' % url) data = urlopener(url, log) except URLError as e: log.warning('Request failed %s' % url) return try: result = json.load(data) except ValueError: log.warning('Rotten Tomatoes returned invalid json at: %s' % url) return return result
def on_feed_input(self, feed, config): if 'movies' in config and 'series' in config: raise PluginError('Cannot use both series list and movies list in the same feed.') if 'movies' in config: config['data_type'] = 'movies' config['list_type'] = config['movies'] map = self.movie_map elif 'series' in config: config['data_type'] = 'shows' config['list_type'] = config['series'] map = self.series_map elif 'custom' in config: config['data_type'] = 'custom' # Do some translation from visible list name to prepare for use in url list_name = config['custom'] # These characters are just stripped in the url for char in '!@#$%^*()[]{}/=?+\\|-_': list_name = list_name.replace(char, '') # These characters get replaced list_name = list_name.replace('&', 'and') list_name = list_name.replace(' ', '-') config['list_type'] = list_name # Map type is per item in custom lists else: raise PluginError('Must define movie or series lists to retrieve from trakt.') url = 'http://api.trakt.tv/user/' if config['data_type'] == 'custom': url += 'list.json/%(api_key)s/%(username)s/%(list_type)s' elif config['list_type'] == 'watchlist': url += 'watchlist/%(data_type)s.json/%(api_key)s/%(username)s' else: url += 'library/%(data_type)s/%(list_type)s.json/%(api_key)s/%(username)s' url = url % config if 'password' in config: auth = {'username': config['username'], 'password': hashlib.sha1(config['password']).hexdigest()} url = urllib2.Request(url, json.dumps(auth), {'content-type': 'application/json'}) entries = [] log.verbose('Retrieving list %s %s...' % (config['data_type'], config['list_type'])) try: data = json.load(urlopener(url, log, retries=2)) except urllib2.URLError, e: raise PluginError('Could not retrieve list from trakt (%s)' % e)
def on_task_metainfo(self, task, config): if not task.entries: return udata = {} ufile = os.path.join(config, 'uoccin.json') if os.path.exists(ufile): try: self.log.verbose('loading file %s' % ufile) with open(ufile, 'r') as f: udata = json.load(f) except Exception as err: self.log.debug('error reading %s: %s' % (ufile, err)) raise plugin.PluginError('error reading %s: %s' % (ufile, err)) movies = udata.setdefault('movies', {}) series = udata.setdefault('series', {}) if not (movies or series): return for entry in task.entries: entry['uoccin_watchlist'] = False entry['uoccin_collected'] = False entry['uoccin_watched'] = False entry['uoccin_rating'] = None entry['uoccin_tags'] = [] entry['uoccin_subtitles'] = [] if 'tvdb_id' in entry and series: ser = series.setdefault(str(entry['tvdb_id']), {}) entry['uoccin_watchlist'] = ser.get('watchlist', False) entry['uoccin_rating'] = ser.get('rating') entry['uoccin_tags'] = ser.get('tags', []) if all(field in entry for field in ['series_season', 'series_episode']): season = str(entry['series_season']) episode = entry['series_episode'] edata = ser.get('collected', {}).get(season, {}).get(str(episode)) entry['uoccin_collected'] = isinstance(edata, list) entry['uoccin_subtitles'] = edata if entry['uoccin_collected'] else [] entry['uoccin_watched'] = episode in ser.get('watched', {}).get(season, []) elif 'imdb_id' in entry and movies: mov = movies.setdefault(str(entry['imdb_id']), {}) entry['uoccin_watchlist'] = mov.get('watchlist', False) entry['uoccin_collected'] = mov.get('collected', False) entry['uoccin_watched'] = mov.get('watched', False) entry['uoccin_rating'] = mov.get('rating') entry['uoccin_tags'] = mov.get('tags', []) entry['uoccin_subtitles'] = mov.get('tags', [])
def on_task_input(self, task, config): file = Path(config['file']) field_map = config.get('field_map', {}) # Switch the field map to map from json to flexget fields field_map = {v: k for k, v in field_map.items()} with file.open(encoding=config.get('encoding', 'utf-8')) as data: contents = json.load(data) for item in contents: entry = Entry() for field, value in item.items(): if field in field_map: entry[field_map[field]] = self.ds_dt(value) else: entry[field] = self.ds_dt(value) if not entry.isvalid(): logger.error( 'No title and url defined for entry, you may need to use field_map to map them.' ) yield Entry(item)
def get_first_result(tmdb_function, value): if isinstance(value, basestring): value = quote(value.encode('utf-8'), safe='') url = '%s/2.1/Movie.%s/%s/json/%s/%s' % (server, tmdb_function, lang, api_key, value) try: data = urlopener(url, log) except URLError: log.warning('Request failed %s' % url) return try: result = json.load(data) except ValueError: log.warning('TMDb returned invalid json.') return # Make sure there is a valid result to return if isinstance(result, list) and len(result): result = result[0] if isinstance(result, dict) and result.get('id'): return result
def on_task_input(self, task, config): """asd""" src = os.path.join(config['path'], config['type'] + '.watchlist.json') if not os.path.exists(src): self.log.warning('Uoccin %s watchlist not found.' % config['type']) return with open(src, 'r') as f: data = json.load(f) entries = [] for eid, itm in data.items(): if 'tags' in config: if not 'tags' in itm: self.log.debug('No tags in watchlist item, skipping %s' % itm['name']) continue n = len(set(config['tags']) & set(itm['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 entry = Entry() entry['title'] = itm['name'] if config['type'] == 'movies': entry['url'] = 'http://www.imdb.com/title/' + eid entry['imdb_id'] = eid else: entry['url'] = 'http://thetvdb.com/?tab=series&id=' + eid entry['tvdb_id'] = eid if 'tags' in itm: entry['uoccin_tags'] = itm['tags'] if 'quality' in itm: entry['uoccin_quality'] = itm['quality'] if entry.isvalid(): entries.append(entry) else: self.log.debug('Invalid entry created? %s' % entry) return entries
def movies_search(q, page_limit=None, page=None): if isinstance(q, basestring): q = q.replace(" ", "+").encode("utf-8") url = "%s/%s/movies.json?q=%s&apikey=%s" % (SERVER, API_VER, q, API_KEY) if page_limit: url += "&page_limit=%i" % (page_limit) if page: url += "&page=%i" % (page) results = get_json(url) if isinstance(results, dict) and results.get("total") and len(results.get("movies")): return results def get_json(url): try: log.debug("fetching json at %s" % url) data = urlopener(url, log) except URLError, e: log.warning("Request failed %s" % url) return try: result = json.load(data) except ValueError: log.warning("Rotten Tomatoes returned invalid json at: %s" % url) return return result
def get_json(self, config, filename): fn = os.path.join(config, filename) if os.path.exists(fn): with open(fn, 'r') as f: return json.load(f) return {}
def on_task_output(self, task, config): """Add accepted series and/or movies to uoccin's watchlist""" series = {} movies = {} for entry in task.accepted: if all(field in entry for field in ['tvdb_id', 'series_name']): series[str(entry['tvdb_id'])] = entry['series_name'] elif all(field in entry for field in ['imdb_id', 'movie_name']): movies[entry['imdb_id']] = entry['movie_name'] if series: dest = os.path.join(config if self.remove else config['path'], 'series.watchlist.json') data = {} if os.path.exists(dest): with open(dest, 'r') as f: data = json.load(f) n = 0 for tvdb_id, title in series.items(): if self.remove: try: data.pop(tvdb_id) n += 1 self.log.verbose('Series %s (%s) removed from Uoccin watchlist' % (tvdb_id, title)) except: pass elif not tvdb_id in data.keys(): data[tvdb_id] = { 'name': title } if 'tags' in config: data[tvdb_id]['tags'] = [tag for tag in config['tags']] if 'quality' in config: data[tvdb_id]['quality'] = config['quality'] n += 1 self.log.verbose('Series %s (%s) added to Uoccin watchlist' % (tvdb_id, title)) if n > 0: text = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) with open(dest, 'w') as f: f.write(text) self.log.info('Uoccin watchlist updated (%d series %s)' % (n, 'removed' if self.remove else 'added')) if movies: dest = os.path.join(config if self.remove else config['path'], 'movies.watchlist.json') data = {} if os.path.exists(dest): with open(dest, 'r') as f: data = json.load(f) n = 0 for imdb_id, title in movies.items(): if self.remove: try: data.pop(imdb_id) n += 1 self.log.verbose('Movie %s (%s) removed from Uoccin watchlist' % (imdb_id, title)) except: pass elif not imdb_id in data.keys(): data[imdb_id] = { 'name': title } if 'tags' in config: data[imdb_id]['tags'] = [tag for tag in config['tags']] if 'quality' in config: data[imdb_id]['quality'] = config['quality'] n += 1 self.log.verbose('Movie %s (%s) added to Uoccin watchlist' % (imdb_id, title)) if n > 0: text = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) with open(dest, 'w') as f: f.write(text) self.log.info('Uoccin watchlist updated (%d movies %s)' % (n, 'removed' if self.remove else 'added'))
def process(self): self.changes.sort() udata = {} ufile = os.path.join(self.folder, 'uoccin.json') if os.path.exists(ufile): try: self.log.verbose('loading file %s' % ufile) with open(ufile, 'r') as f: udata = json.load(f) except Exception as err: self.log.debug('error reading %s: %s' % (ufile, err)) raise plugin.PluginError('error reading %s: %s' % (ufile, err)) udata.setdefault('movies', {}) udata.setdefault('series', {}) 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}) # 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':{}}) # 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, []) elif 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 eno in season: season.remove(int(eno)) season.sort() if not season: self.log.verbose('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.verbose('deleting unused section: series\%s' % sid) udata['series'].pop(sid) else: self.log.warning('invalid element type "%s"' % typ) try: self.log.verbose('saving file %s' % ufile) 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 movies_search(q, page_limit=None, page=None): if isinstance(q, basestring): q = q.replace(' ', '+').encode('utf-8') url = '%s/%s/movies.json?q=%s&apikey=%s' % (SERVER, API_VER, q, API_KEY) if page_limit: url += '&page_limit=%i' % (page_limit) if page: url += '&page=%i' % (page) results = get_json(url) if isinstance(results, dict) and results.get('total') and len( results.get('movies')): return results def get_json(url): try: log.debug('fetching json at %s' % url) data = urlopener(url, log) except URLError, e: log.warning('Request failed %s' % url) return try: result = json.load(data) except ValueError: log.warning('Rotten Tomatoes returned invalid json at: %s' % url) return return result