diff --git a/CHANGES.md b/CHANGES.md index 281caf6..aa31a8b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,10 @@ -### 0.23.20 (2020-05-13 18:35:00 UTC) +### 0.23.21 (2020-05-17 10:20:00 UTC) + +* Fix provider Nebulance +* Fix provider MoreThan + + +### 0.23.20 (2020-05-13 18:35:00 UTC) * Fix restart to release and free resources from previous run process * Change fanart lib to get_url diff --git a/sickbeard/providers/morethan.py b/sickbeard/providers/morethan.py index 3f327b7..b2622fb 100644 --- a/sickbeard/providers/morethan.py +++ b/sickbeard/providers/morethan.py @@ -67,7 +67,7 @@ class MoreThanProvider(generic.TorrentProvider): for (k, v) in iteritems({'info': r'torrents.php\?id', 'get': 'download', 'nuked': 'nuked'})]) for mode in search_params: for search_string in search_params[mode]: - search_string = unidecode(search_string) + search_string = unidecode(search_string).replace('.', ' ') search_url = self.urls['search'] % (search_string, self._categories_string(mode, template='filter_cat[%s]=1')) diff --git a/sickbeard/providers/nebulance.py b/sickbeard/providers/nebulance.py index bf3b78a..4882bb4 100644 --- a/sickbeard/providers/nebulance.py +++ b/sickbeard/providers/nebulance.py @@ -15,6 +15,10 @@ # You should have received a copy of the GNU General Public License # along with SickGear. If not, see . +try: + import json +except ImportError: + from lib import simplejson as json import re import traceback @@ -24,7 +28,7 @@ from ..helpers import try_int from bs4_parser import BS4Parser -from _23 import filter_list, unidecode +from _23 import filter_list, unidecode, unquote_plus from six import iteritems @@ -37,15 +41,18 @@ class NebulanceProvider(generic.TorrentProvider): self.urls = {'config_provider_home_uri': self.url_base, 'login_action': self.url_base + 'login.php', 'user': self.url_base + 'ajax.php?action=index', + 'api_key': self.url_base + 'user.php?action=edit&userid=%s', + 'api': self.url_base + 'api.php', 'browse': self.url_base + 'ajax.php?action=browse&auth=%s&passkey=%s', 'search': '&searchstr=%s', 'get': self.url_base + 'torrents.php?action=download&authkey=%s&torrent_pass=%s&id=%s'} self.url = self.urls['config_provider_home_uri'] - self.user_authkey, self.user_passkey = 2 * [None] + self.user_authkey, self.user_passkey, self.uid = 3 * [None] self.chk_td = True - self.username, self.password, self.freeleech, self.scene, self.minseed, self.minleech = 6 * [None] + self.username, self.password, self.api_key, self.scene, self.minseed, self.minleech = 6 * [None] + self.api_priority = False def _authorised(self, **kwargs): @@ -58,11 +65,18 @@ class NebulanceProvider(generic.TorrentProvider): if self.should_skip(): return False if 'response' in response: - self.user_authkey, self.user_passkey = [response['response'].get(v) for v in ('authkey', 'passkey')] + self.user_authkey, self.user_passkey, self.uid = [response['response'].get(v) + for v in ('authkey', 'passkey', 'id')] return self.user_authkey def _search_provider(self, search_params, **kwargs): + if self.api_priority: + return self.api_key and self._search_rpc(search_params) or self._search(search_params) + return self._search(search_params) or self.api_key and self._search_rpc(search_params) or [] + + def _search(self, search_params): + results = [] if not self._authorised(): return results @@ -85,25 +99,23 @@ class NebulanceProvider(generic.TorrentProvider): cnt = len(items[mode]) try: for item in data_json.get('response', {}).get('results', []): - if self.freeleech and not item.get('isFreeleech'): - continue - - seeders, leechers, group_name, torrent_id, size = [try_int(n, n) for n in [ - item.get(x) for x in ['seeders', 'leechers', 'groupName', 'torrentId', 'size']]] + seeders, leechers, group_name, torrent_id, size, title = [try_int(n, n) for n in [ + item.get(x) for x in ['seeders', 'leechers', 'groupName', 'torrentId', 'size', 'rlsName']]] if self._reject_item(seeders, leechers): continue - try: - title_parts = group_name.split('[') - maybe_res = re.findall(r'((?:72|108|216)0\w)', title_parts[1]) - maybe_ext = re.findall('(?i)(%s)' % '|'.join(common.mediaExtensions), title_parts[1]) - detail = title_parts[1].split('/') - detail[1] = detail[1].strip().lower().replace('mkv', 'x264') - title = '%s.%s' % (BS4Parser(title_parts[0].strip()).soup.string, '.'.join( - (maybe_res and [maybe_res[0]] or []) + - [detail[0].strip(), detail[1], maybe_ext and maybe_ext[0].lower() or 'mkv'])) - except (IndexError, KeyError): - title = self.regulate_title(item, group_name) + if None is title: + try: + title_parts = group_name.split('[') + maybe_res = re.findall(r'((?:72|108|216)0\w)', title_parts[1]) + maybe_ext = re.findall('(?i)(%s)' % '|'.join(common.mediaExtensions), title_parts[1]) + detail = title_parts[1].split('/') + detail[1] = detail[1].strip().lower().replace('mkv', 'x264') + title = '%s.%s' % (BS4Parser(title_parts[0].strip()).soup.string, '.'.join( + (maybe_res and [maybe_res[0]] or []) + + [detail[0].strip(), detail[1], maybe_ext and maybe_ext[0].lower() or 'mkv'])) + except (IndexError, KeyError): + title = self.regulate_title(item, group_name) download_url = self.urls['get'] % (self.user_authkey, self.user_passkey, torrent_id) if title and download_url: @@ -164,5 +176,59 @@ class NebulanceProvider(generic.TorrentProvider): title += + any(tags[4]) and ('.%s' % tags[4][0]) or '' return title + def _search_rpc(self, search_params): + + results = [] + + items = {'Cache': [], 'Season': [], 'Episode': [], 'Propers': []} + + json_rpc = (lambda args: + '{"jsonrpc": "2.0", "id": 1, "method": "getTorrents", "params": ["%s", %s, %s, %s, %s]}' % + (self.api_key, json.dumps(args.get('params', '')), 100, args.get('page', 0), 0)) + + for mode in search_params: + for search_string in search_params[mode]: + search_string = unquote_plus(unidecode(search_string)) + + params = {'release': search_string} + if 'Cache' == mode: + params = {'age': '< %s' % (24 * 60 * 60)} + elif 'Propers' == mode: + params.update({'age': '< %s' % (4 * 24 * 60 * 60)}) + + response = self.get_url(self.urls['api'], post_data=json_rpc({'params': params}), parse_json=True) + if self.should_skip(): + return results + + data_json = response and response.get('result', {}).get('items') or [] + + cnt = len(items[mode]) + for cur_item in data_json: + seeders, leechers, size, download = [try_int(n, n) for n in [ + cur_item.get(x) for x in ['seed', 'leech', 'size', 'download']]] + if not self._reject_item(seeders, leechers): + items[mode].append((cur_item.get('rls_name'), '%s%s' % (self.url_base.rstrip('/'), download), + seeders, self._bytesizer(size))) + + self._log_search(mode, len(items[mode]) - cnt, + ('search_string: ' + str(search_string), self.name)['Cache' == mode]) + + results = self._sort_seeding(mode, results + items[mode]) + + return results + + def ui_string(self, key): + profile_page = 'profile page' + if self._authorised(): + profile_page = '%s' % (self.urls['api_key'] % self.uid, profile_page) + + return ('%s_api_key' % self.get_id()) == key and 'API key' or \ + ('%s_api_key_tip' % self.get_id()) == key and \ + '\'API key\' is at %s %s with "Download" enabled
' \ + '%s has no result or is not set' \ + % (self.name, profile_page, + ('and is used if Username/Password', 'Username/Password is used if API')[self.api_priority]) \ + or '' + provider = NebulanceProvider() diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 20fec54..c38ef30 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -8332,15 +8332,14 @@ class EventLogs(MainHandler): self.set_header('Content-Length', ek.ek(os.path.getsize, logfile_name)) self.set_header('Content-Disposition', 'attachment; filename=sickgear.log') with open(logfile_name, 'rb') as logfile: - try: - while True: + while True: + try: data = logfile.read(4096) if not data: break self.write(data) - self.finish() - except (BaseException, Exception): - return + except (BaseException, Exception): + break def view_log(self, min_level=logger.MESSAGE, max_lines=500):