diff --git a/CHANGES.md b/CHANGES.md index d4c1b2a..c1b93e5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,10 @@ -### 0.18.20 (2019-04-23 12:20:00 UTC) +### 0.18.20 (2019-04-23 23:10:00 UTC) * Add NinjaCentral usenet provider * Remove Nzb.org usenet provider (r.i.p) * Remove Milkie torrent provider (last activity > 3 months) +* Fix setting ignore/require words in webapi +* Change handle TVDb api returns None for some shows as 'seriesName' ### 0.18.19 (2019-04-19 02:00:00 UTC) diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index 4bb7ebf..2a4fb64 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -659,6 +659,14 @@ class Tvdb: v = '' else: v = clean_data(v) + else: + if 'seriesname' == k: + if isinstance(data.get('aliases'), list) and 0 < len(data.get('aliases')): + v = data['aliases'].pop(0) + # this is a invalid show, it has no Name + if None is v: + return None + if k in map_show: k = map_show[k] if k_org is not k: @@ -677,9 +685,13 @@ class Tvdb: if isinstance(resp['data'], dict): resp['data'] = map_show_keys(resp['data']) elif isinstance(resp['data'], list): + data_list = [] for idx, row in enumerate(resp['data']): if isinstance(row, dict): - resp['data'][idx] = map_show_keys(row) + cr = map_show_keys(row) + if None is not cr: + data_list.append(cr) + resp['data'] = data_list return resp return dict([(u'data', None)]) diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py index 89a8bc7..0e58daf 100644 --- a/sickbeard/webapi.py +++ b/sickbeard/webapi.py @@ -92,6 +92,13 @@ quality_map = {'sdtv': Quality.SDTV, quality_map_inversed = {v: k for k, v in quality_map.iteritems()} +class PythonObjectEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, set): + return list(obj) + return json.JSONEncoder.default(self, obj) + + class Api(webserve.BaseHandler): """ api class that returns json results """ version = 10 # use an int since float-point is unpredictible @@ -182,7 +189,7 @@ class Api(webserve.BaseHandler): def _out_as_json(self, dict): self.set_header('Content-Type', 'application/json; charset=UTF-8') try: - out = json.dumps(dict, indent=self.intent, sort_keys=True) + out = json.dumps(dict, indent=self.intent, sort_keys=True, cls=PythonObjectEncoder) callback = self.get_query_argument('callback', None) or self.get_query_argument('jsonp', None) if None is not callback: out = '%s(%s);' % (callback, out) # wrap with JSONP call if requested @@ -2684,7 +2691,7 @@ class CMD_SickGearListIgnoreWords(ApiCall): return_type = 'Global' return_data['use regex'] = ignore_words.startswith('regex:') - return_data['ignore words'] = [w.strip() for w in ignore_words.replace('regex:', '').split(',')] + return_data['ignore words'] = [w.strip() for w in ignore_words.replace('regex:', '').split(',') if w.strip()] return _responds(RESULT_SUCCESS, data=return_data, msg="%s ignore words" % return_type) @@ -2717,20 +2724,22 @@ class CMD_SickGearSetIgnoreWords(ApiCall): def _create_ignore_words(): use_regex = ignore_words.startswith('regex:') - ignore_list = [w.strip() for w in ignore_words.replace('regex:', '').split(',')] + ignore_list = {w.strip() for w in ignore_words.replace('regex:', '').split(',') if w.strip()} if None is not self.regex: use_regex = self.regex if self.add: for a in self.add: - ignore_list.append(a) + ignore_list.add(a.strip()) if self.remove: for r in self.remove: try: ignore_list.remove(r) - except ValueError: + except KeyError: pass - return use_regex, ignore_list, '%s%s' % (('', 'regex:')[use_regex], ', '.join(ignore_list)) + return use_regex, ignore_list, \ + ('', '%s%s' % (('', 'regex:')[use_regex], + ', '.join([i.strip() for i in ignore_list if i.strip()])))[0 < len(ignore_list)] if self.indexer and self.indexerid: showObj = helpers.find_show_by_id(sickbeard.showList, {self.indexer: self.indexerid}) @@ -2804,7 +2813,7 @@ class CMD_SickGearListRequireWords(ApiCall): return_type = 'Global' return_data['use regex'] = required_words.startswith('regex:') - return_data['required words'] = [w.strip() for w in required_words.replace('regex:', '').split(',')] + return_data['required words'] = [w.strip() for w in required_words.replace('regex:', '').split(',') if w.strip()] return _responds(RESULT_SUCCESS, data=return_data, msg="%s required words" % return_type) @@ -2831,26 +2840,28 @@ class CMD_SickGearSetRequrieWords(ApiCall): ApiCall.__init__(self, handler, args, kwargs) def run(self): - """ set ignore words """ + """ set require words """ if not self.add and not self.remove: return _responds(RESULT_FAILURE, msg="No words to add/remove provided") def _create_required_words(): use_regex = requried_words.startswith('regex:') - require_list = [w.strip() for w in requried_words.replace('regex:', '').split(',')] + require_list = {w.strip() for w in requried_words.replace('regex:', '').split(',') if w.strip()} if None is not self.regex: use_regex = self.regex if self.add: for a in self.add: - require_list.append(a) + require_list.add(a.strip()) if self.remove: for r in self.remove: try: require_list.remove(r) - except ValueError: + except KeyError: pass - return use_regex, require_list, '%s%s' % (('', 'regex:')[use_regex], ', '.join(require_list)) + return use_regex, require_list, \ + ('', '%s%s' % (('', 'regex:')[use_regex], + ', '.join([r.strip() for r in require_list if r.strip()])))[0 < len(require_list)] if self.indexer and self.indexerid: showObj = helpers.find_show_by_id(sickbeard.showList, {self.indexer: self.indexerid})