diff --git a/couchpotato/core/downloaders/nzbget/__init__.py b/couchpotato/core/downloaders/nzbget/__init__.py index 19483713..00763cfb 100644 --- a/couchpotato/core/downloaders/nzbget/__init__.py +++ b/couchpotato/core/downloaders/nzbget/__init__.py @@ -12,6 +12,7 @@ config = [{ 'name': 'nzbget', 'label': 'NZBGet', 'description': 'Use NZBGet to download NZBs.', + 'wizard': True, 'options': [ { 'name': 'enabled', diff --git a/couchpotato/core/downloaders/rtorrent/__init__.py b/couchpotato/core/downloaders/rtorrent/__init__.py index efc2234b..b04e6898 100755 --- a/couchpotato/core/downloaders/rtorrent/__init__.py +++ b/couchpotato/core/downloaders/rtorrent/__init__.py @@ -35,6 +35,11 @@ config = [{ 'name': 'label', 'description': 'Label to apply on added torrents.', }, + { + 'name': 'directory', + 'type': 'directory', + 'description': 'Directory where rtorrent should download the files too.', + }, { 'name': 'remove_complete', 'label': 'Remove torrent', @@ -43,6 +48,14 @@ config = [{ 'type': 'bool', 'description': 'Remove the torrent after it finishes seeding.', }, + { + 'name': 'append_label', + 'label': 'Append Label', + 'default': False, + 'advanced': True, + 'type': 'bool', + 'description': 'Append label to download location. Requires you to set the download location above.', + }, { 'name': 'delete_files', 'label': 'Remove files', diff --git a/couchpotato/core/downloaders/rtorrent/main.py b/couchpotato/core/downloaders/rtorrent/main.py index 161c671a..caf64d52 100755 --- a/couchpotato/core/downloaders/rtorrent/main.py +++ b/couchpotato/core/downloaders/rtorrent/main.py @@ -7,7 +7,7 @@ from datetime import timedelta from hashlib import sha1 from rtorrent import RTorrent from rtorrent.err import MethodError -import shutil +import shutil, os log = CPLog(__name__) @@ -91,6 +91,7 @@ class rTorrent(Downloader): if self.conf('label'): torrent_params['label'] = self.conf('label') + if not filedata and data.get('protocol') == 'torrent': log.error('Failed sending torrent, no data') return False @@ -116,10 +117,19 @@ class rTorrent(Downloader): # Send torrent to rTorrent torrent = self.rt.load_torrent(filedata) + if not torrent: + log.error('Unable to find the torrent, did it fail to load?') + return False + # Set label if self.conf('label'): torrent.set_custom(1, self.conf('label')) + if self.conf('directory') and self.conf('append_label'): + torrent.set_directory(os.path.join(self.conf('directory'), self.conf('label'))) + elif self.conf('directory'): + torrent.set_directory(self.conf('directory')) + # Set Ratio Group torrent.set_visible(group_name) diff --git a/couchpotato/core/downloaders/sabnzbd/main.py b/couchpotato/core/downloaders/sabnzbd/main.py index 08ee409c..41f9f709 100644 --- a/couchpotato/core/downloaders/sabnzbd/main.py +++ b/couchpotato/core/downloaders/sabnzbd/main.py @@ -90,9 +90,14 @@ class Sabnzbd(Downloader): # Get busy releases for item in queue.get('slots', []): + status = 'busy' + if 'ENCRYPTED / ' in item['filename']: + status = 'failed' + statuses.append({ 'id': item['nzo_id'], 'name': item['filename'], + 'status': status, 'original_status': item['status'], 'timeleft': item['timeleft'] if not queue['paused'] else -1, }) @@ -122,6 +127,12 @@ class Sabnzbd(Downloader): log.info('%s failed downloading, deleting...', item['name']) try: + self.call({ + 'mode': 'queue', + 'name': 'delete', + 'del_files': '1', + 'value': item['id'] + }, use_json = False) self.call({ 'mode': 'history', 'name': 'delete', diff --git a/couchpotato/core/media/_base/searcher/main.py b/couchpotato/core/media/_base/searcher/main.py index f09be64b..934a1472 100644 --- a/couchpotato/core/media/_base/searcher/main.py +++ b/couchpotato/core/media/_base/searcher/main.py @@ -60,7 +60,7 @@ class Searcher(SearcherBase): if downloader_enabled: - snatched_status = fireEvent('status.get', 'snatched', single = True) + snatched_status, done_status, active_status = fireEvent('status.get', ['snatched', 'done', 'active'], single = True) # Download movie to temp filedata = None @@ -79,9 +79,7 @@ class Searcher(SearcherBase): rls = db.query(Release).filter_by(identifier = md5(data['url'])).first() if rls: renamer_enabled = Env.setting('enabled', 'renamer') - - done_status = fireEvent('status.get', 'done', single = True) - rls.status_id = done_status.get('id') if not renamer_enabled else snatched_status.get('id') + fireEvent('release.update_status', rls.id, status = done_status if not renamer_enabled else snatched_status, single = True) # Save download-id info if returned if isinstance(download_result, dict): @@ -100,20 +98,12 @@ class Searcher(SearcherBase): # If renamer isn't used, mark movie done if not renamer_enabled: - active_status = fireEvent('status.get', 'active', single = True) - done_status = fireEvent('status.get', 'done', single = True) try: if movie['status_id'] == active_status.get('id'): for profile_type in movie['profile']['types']: if profile_type['quality_id'] == rls.quality.id and profile_type['finish']: - log.info('Renamer disabled, marking movie as finished: %s', log_movie) - - # Mark release done - rls.status_id = done_status.get('id') - rls.last_edit = int(time.time()) - db.commit() - # Mark movie done + log.info('Renamer disabled, marking movie as finished: %s', log_movie) mvie = db.query(Movie).filter_by(id = movie['id']).first() mvie.status_id = done_status.get('id') mvie.last_edit = int(time.time()) diff --git a/couchpotato/core/media/movie/_base/static/movie.actions.js b/couchpotato/core/media/movie/_base/static/movie.actions.js index e9f6141f..9dd6bdfe 100644 --- a/couchpotato/core/media/movie/_base/static/movie.actions.js +++ b/couchpotato/core/media/movie/_base/static/movie.actions.js @@ -241,7 +241,6 @@ MA.Release = new Class({ } }) ).inject(self.release_container); - release['el'] = item; if(status.identifier == 'ignored' || status.identifier == 'failed' || status.identifier == 'snatched'){ @@ -251,6 +250,30 @@ MA.Release = new Class({ else if(!self.next_release && status.identifier == 'available'){ self.next_release = release; } + + var update_handle = function(notification) { + var q = self.movie.quality.getElement('.q_id' + release.quality_id), + status = Status.get(release.status_id), + new_status = Status.get(notification.data); + + release.status_id = new_status.id + release.el.set('class', 'item ' + new_status.identifier); + + var status_el = release.el.getElement('.release_status'); + status_el.set('class', 'release_status ' + new_status.identifier); + status_el.set('text', new_status.identifier); + + if(!q && (new_status.identifier == 'snatched' || new_status.identifier == 'seeding' || new_status.identifier == 'done')) + var q = self.addQuality(release.quality_id); + + if(new_status && q && !q.hasClass(new_status.identifier)) { + q.removeClass(status.identifier).addClass(new_status.identifier); + q.set('title', q.get('title').replace(status.label, new_status.label)); + } + } + + App.addEvent('release.update_status.' + release.id, update_handle); + }); if(self.last_release) @@ -397,17 +420,6 @@ MA.Release = new Class({ 'data': { 'id': release.id }, - 'onComplete': function(){ - var el = release.el; - if(el && (el.hasClass('failed') || el.hasClass('ignored'))){ - el.removeClass('failed').removeClass('ignored'); - el.getElement('.release_status').set('text', 'available'); - } - else if(el) { - el.addClass('ignored'); - el.getElement('.release_status').set('text', 'ignored'); - } - } }) }, diff --git a/couchpotato/core/media/movie/_base/static/movie.css b/couchpotato/core/media/movie/_base/static/movie.css index 0200417c..c72eb136 100644 --- a/couchpotato/core/media/movie/_base/static/movie.css +++ b/couchpotato/core/media/movie/_base/static/movie.css @@ -419,22 +419,25 @@ } .movies .data .quality .available, - .movies .data .quality .snatched { + .movies .data .quality .snatched, + .movies .data .quality .seeding { opacity: 1; cursor: pointer; } .movies .data .quality .available { background-color: #578bc3; } - .movies .data .quality .failed { background-color: #a43d34; } + .movies .data .quality .failed, + .movies .data .quality .missing, + .movies .data .quality .ignored { background-color: #a43d34; } .movies .data .quality .snatched { background-color: #a2a232; } - .movies .data .quality .seeding { background-color: #0a6819; } .movies .data .quality .done { background-color: #369545; opacity: 1; } + .movies .data .quality .seeding { background-color: #0a6819; } .movies .data .quality .finish { background-image: url('../images/sprite.png'); - background-repeat: no-repeat; + background-repeat: no-repeat; background-position: 0 2px; padding-left: 14px; background-size: 14px @@ -646,7 +649,7 @@ margin-top: 25px; } } - + .trailer_container.hide { height: 0 !important; } @@ -1029,7 +1032,7 @@ .movies .progress > div .folder { display: inline-block; padding: 5px 20px 5px 0; - white-space: nowrap; + white-space: nowrap; text-overflow: ellipsis; overflow: hidden; width: 85%; diff --git a/couchpotato/core/media/movie/_base/static/movie.js b/couchpotato/core/media/movie/_base/static/movie.js index 6defc2ad..a865325b 100644 --- a/couchpotato/core/media/movie/_base/static/movie.js +++ b/couchpotato/core/media/movie/_base/static/movie.js @@ -185,7 +185,7 @@ var Movie = new Class({ var q = self.quality.getElement('.q_id'+ release.quality_id), status = Status.get(release.status_id); - if(!q && (status.identifier == 'snatched' || status.identifier == 'done')) + if(!q && (status.identifier == 'snatched' || status.identifier == 'seeding' || status.identifier == 'done')) var q = self.addQuality(release.quality_id) if (status && q && !q.hasClass(status.identifier)){ diff --git a/couchpotato/core/notifications/plex/main.py b/couchpotato/core/notifications/plex/main.py index 5558289d..19ca670d 100755 --- a/couchpotato/core/notifications/plex/main.py +++ b/couchpotato/core/notifications/plex/main.py @@ -52,7 +52,7 @@ class Plex(Notification): clients.remove(server.get('name').lower()) protocol = server.get('protocol', 'xbmchttp') - if protocol in ['xbmcjson', 'xbmchttp']: + if protocol in ['plex', 'xbmcjson', 'xbmchttp']: self.clients[server.get('name')] = { 'name': server.get('name'), 'address': server.get('address'), @@ -164,7 +164,7 @@ class Plex(Notification): } for name, client in self.clients.items(): - if client['protocol'] == 'xbmcjson': + if client['protocol'] in ['xbmcjson', 'plex']: total += 1 if self.sendJSON('GUI.ShowNotification', params, client): successful += 1 diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 46857adf..e8d1815f 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -10,6 +10,7 @@ from sqlalchemy.orm import joinedload_all from sqlalchemy.sql.expression import and_, or_ import os import traceback +import time log = CPLog(__name__) @@ -47,6 +48,7 @@ class Release(Plugin): addEvent('release.for_movie', self.forMovie) addEvent('release.delete', self.delete) addEvent('release.clean', self.clean) + addEvent('release.update_status', self.updateStatus) def add(self, group): @@ -159,8 +161,7 @@ class Release(Plugin): rel = db.query(Relea).filter_by(id = id).first() if rel: ignored_status, failed_status, available_status = fireEvent('status.get', ['ignored', 'failed', 'available'], single = True) - rel.status_id = available_status.get('id') if rel.status_id in [ignored_status.get('id'), failed_status.get('id')] else ignored_status.get('id') - db.commit() + self.updateStatus(id, available_status if rel.status_id in [ignored_status.get('id'), failed_status.get('id')] else ignored_status) return { 'success': True @@ -199,14 +200,9 @@ class Release(Plugin): if success: db.expunge_all() - rel = db.query(Relea).filter_by(id = id).first() # Get release again - - if rel.status_id != done_status.get('id'): - rel.status_id = snatched_status.get('id') - db.commit() + rel = db.query(Relea).filter_by(id = id).first() # Get release again @RuudBurger why do we need to get it again?? fireEvent('notify.frontend', type = 'release.download', data = True, message = 'Successfully snatched "%s"' % item['name']) - return { 'success': success } @@ -241,3 +237,23 @@ class Release(Plugin): 'success': True } + def updateStatus(self, id, status = None): + if not status: return + + db = get_session() + + rel = db.query(Relea).filter_by(id = id).first() + if rel and status and rel.status_id != status.get('id'): + + item = {} + for info in rel.info: + item[info.identifier] = info.value + + #update status in Db + log.debug('Marking release %s as %s', (item['name'], status.get("label"))) + rel.status_id = status.get('id') + rel.last_edit = int(time.time()) + db.commit() + + #Update all movie info as there is no release update function + fireEvent('notify.frontend', type = 'release.update_status.%s' % rel.id, data = status.get('id')) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index ad7df1cf..28d5eef7 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -395,14 +395,8 @@ class Renamer(Plugin): break elif release.status_id is snatched_status.get('id'): if release.quality.id is group['meta_data']['quality']['id']: - log.debug('Marking release as downloaded') - try: - release.status_id = downloaded_status.get('id') - release.last_edit = int(time.time()) - except Exception, e: - log.error('Failed marking release as finished: %s %s', (e, traceback.format_exc())) - - db.commit() + # Set the release to downloaded + fireEvent('release.update_status', release.id, status = downloaded_status, single = True) # Remove leftover files if not remove_leftovers: # Don't remove anything @@ -476,11 +470,18 @@ class Renamer(Plugin): log.error('Failed removing %s: %s', (release.identifier, traceback.format_exc())) if group['dirname'] and group['parentdir'] and not self.downloadIsTorrent(download_info): + if movie_folder: + # Delete the movie folder + group_folder = movie_folder + else: + # Delete the first empty subfolder in the tree relative to the 'from' folder + group_folder = os.path.join(self.conf('from'), os.path.relpath(group['parentdir'], self.conf('from')).split(os.path.sep)[0]) + try: - log.info('Deleting folder: %s', group['parentdir']) - self.deleteEmptyFolder(group['parentdir']) + log.info('Deleting folder: %s', group_folder) + self.deleteEmptyFolder(group_folder) except: - log.error('Failed removing %s: %s', (group['parentdir'], traceback.format_exc())) + log.error('Failed removing %s: %s', (group_folder, traceback.format_exc())) # Notify on download, search for trailers etc download_message = 'Downloaded %s (%s)' % (movie_title, replacements['quality']) @@ -656,12 +657,13 @@ Remove it if you want it to be renamed (again, or at least let it try again) self.checking_snatched = True - snatched_status, ignored_status, failed_status, done_status, seeding_status, downloaded_status = \ - fireEvent('status.get', ['snatched', 'ignored', 'failed', 'done', 'seeding', 'downloaded'], single = True) + snatched_status, ignored_status, failed_status, done_status, seeding_status, downloaded_status, missing_status = \ + fireEvent('status.get', ['snatched', 'ignored', 'failed', 'done', 'seeding', 'downloaded', 'missing'], single = True) db = get_session() - rels = db.query(Release).filter_by(status_id = snatched_status.get('id')).all() - rels.extend(db.query(Release).filter_by(status_id = seeding_status.get('id')).all()) + rels = db.query(Release).filter( + Release.status_id.in_([snatched_status.get('id'), seeding_status.get('id'), missing_status.get('id')]) + ).all() scan_items = [] scan_required = False @@ -677,7 +679,6 @@ Remove it if you want it to be renamed (again, or at least let it try again) try: for rel in rels: rel_dict = rel.to_dict({'info': {}}) - movie_dict = fireEvent('movie.get', rel.movie_id, single = True) # check status @@ -699,39 +700,36 @@ Remove it if you want it to be renamed (again, or at least let it try again) log.debug('Found %s: %s, time to go: %s', (item['name'], item['status'].upper(), timeleft)) if item['status'] == 'busy': + # Set the release to snatched if it was missing before + fireEvent('release.update_status', rel.id, status = snatched_status, single = True) + # Tag folder if it is in the 'from' folder and it will not be processed because it is still downloading if item['folder'] and self.conf('from') in item['folder']: self.tagDir(item['folder'], 'downloading') elif item['status'] == 'seeding': + # Set the release to seeding + fireEvent('release.update_status', rel.id, status = seeding_status, single = True) #If linking setting is enabled, process release - if self.conf('file_action') != 'move' and not rel.movie.status_id == done_status.get('id') and self.statusInfoComplete(item): + if self.conf('file_action') != 'move' and not rel.status_id == seeding_status.get('id') and self.statusInfoComplete(item): log.info('Download of %s completed! It is now being processed while leaving the original files alone for seeding. Current ratio: %s.', (item['name'], item['seed_ratio'])) # Remove the downloading tag self.untagDir(item['folder'], 'downloading') - rel.status_id = seeding_status.get('id') - rel.last_edit = int(time.time()) - db.commit() - # Scan and set the torrent to paused if required item.update({'pause': True, 'scan': True, 'process_complete': False}) scan_items.append(item) else: - if rel.status_id != seeding_status.get('id'): - rel.status_id = seeding_status.get('id') - rel.last_edit = int(time.time()) - db.commit() - #let it seed log.debug('%s is seeding with ratio: %s', (item['name'], item['seed_ratio'])) + elif item['status'] == 'failed': + # Set the release to failed + fireEvent('release.update_status', rel.id, status = failed_status, single = True) + fireEvent('download.remove_failed', item, single = True) - rel.status_id = failed_status.get('id') - rel.last_edit = int(time.time()) - db.commit() if self.conf('next_on_failed'): fireEvent('movie.searcher.try_next_release', movie_id = rel.movie_id) @@ -743,24 +741,23 @@ Remove it if you want it to be renamed (again, or at least let it try again) if rel.status_id == seeding_status.get('id'): if rel.movie.status_id == done_status.get('id'): # Set the release to done as the movie has already been renamed - rel.status_id = downloaded_status.get('id') - rel.last_edit = int(time.time()) - db.commit() + fireEvent('release.update_status', rel.id, status = downloaded_status, single = True) # Allow the downloader to clean-up item.update({'pause': False, 'scan': False, 'process_complete': True}) scan_items.append(item) else: # Set the release to snatched so that the renamer can process the release as if it was never seeding - rel.status_id = snatched_status.get('id') - rel.last_edit = int(time.time()) - db.commit() + fireEvent('release.update_status', rel.id, status = snatched_status, single = True) # Scan and Allow the downloader to clean-up item.update({'pause': False, 'scan': True, 'process_complete': True}) scan_items.append(item) else: + # Set the release to snatched if it was missing before + fireEvent('release.update_status', rel.id, status = snatched_status, single = True) + # Remove the downloading tag self.untagDir(item['folder'], 'downloading') @@ -776,6 +773,14 @@ Remove it if you want it to be renamed (again, or at least let it try again) if not found: log.info('%s not found in downloaders', nzbname) + #Check status if already missing and for how long, if > 1 week, set to ignored else to missing + if rel.status_id == missing_status.get('id'): + if rel.last_edit < int(time.time()) - 7 * 24 * 60 * 60: + fireEvent('release.update_status', rel.id, status = ignored_status, single = True) + else: + # Set the release to missing + fireEvent('release.update_status', rel.id, status = missing_status, single = True) + except: log.error('Failed checking for release in downloader: %s', traceback.format_exc()) diff --git a/couchpotato/core/plugins/status/main.py b/couchpotato/core/plugins/status/main.py index 7546c651..b3b37bdc 100644 --- a/couchpotato/core/plugins/status/main.py +++ b/couchpotato/core/plugins/status/main.py @@ -24,6 +24,7 @@ class StatusPlugin(Plugin): 'available': 'Available', 'suggest': 'Suggest', 'seeding': 'Seeding', + 'missing': 'Missing', } status_cached = {} diff --git a/couchpotato/core/providers/torrent/ilovetorrents/__init__.py b/couchpotato/core/providers/torrent/ilovetorrents/__init__.py new file mode 100644 index 00000000..c6702d7f --- /dev/null +++ b/couchpotato/core/providers/torrent/ilovetorrents/__init__.py @@ -0,0 +1,60 @@ +from main import ILoveTorrents + +def start(): + return ILoveTorrents() + +config = [{ + 'name': 'ilovetorrents', + 'groups': [ + { + 'tab': 'searcher', + 'list': 'torrent_providers', + 'name': 'ILoveTorrents', + 'description': 'Where the Love of Torrents is Born', + 'wizard': True, + 'options': [ + { + 'name': 'enabled', + 'type': 'enabler', + 'default': False + }, + { + 'name': 'username', + 'label': 'Username', + 'type': 'string', + 'default': '', + 'description': 'The user name for your ILT account', + }, + { + 'name': 'password', + 'label': 'Password', + 'type': 'password', + 'default': '', + 'description': 'The password for your ILT account.', + }, + { + 'name': 'seed_ratio', + 'label': 'Seed ratio', + 'type': 'float', + 'default': 1, + 'description': 'Will not be (re)moved until this seed ratio is met.', + }, + { + 'name': 'seed_time', + 'label': 'Seed time', + 'type': 'int', + 'default': 40, + 'description': 'Will not be (re)moved until this seed time (in hours) is met.', + }, + { + 'name': 'extra_score', + 'advanced': True, + 'label': 'Extra Score', + 'type': 'int', + 'default': 0, + 'description': 'Starting score for each release found via this provider.', + } + ], + } + ] +}] diff --git a/couchpotato/core/providers/torrent/ilovetorrents/main.py b/couchpotato/core/providers/torrent/ilovetorrents/main.py new file mode 100644 index 00000000..8c060ec3 --- /dev/null +++ b/couchpotato/core/providers/torrent/ilovetorrents/main.py @@ -0,0 +1,128 @@ +from bs4 import BeautifulSoup +from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode +from couchpotato.core.helpers.variable import tryInt +from couchpotato.core.logger import CPLog +from couchpotato.core.providers.torrent.base import TorrentProvider +import re +import traceback + +log = CPLog(__name__) + + +class ILoveTorrents(TorrentProvider): + + urls = { + 'download': 'http://www.ilovetorrents.me/%s', + 'detail': 'http://www.ilovetorrents.me/%s', + 'search': 'http://www.ilovetorrents.me/browse.php?search=%s&page=%s&cat=%s', + 'test' : 'http://www.ilovetorrents.me/', + 'login' : 'http://www.ilovetorrents.me/takelogin.php', + 'login_check' : 'http://www.ilovetorrents.me' + } + + cat_ids = [ + (['41'], ['720p', '1080p', 'brrip']), + (['19'], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']), + (['20'], ['dvdr']) + ] + + cat_backup_id = 200 + disable_provider = False + http_time_between_calls = 1 + + def _searchOnTitle(self, title, movie, quality, results): + + page = 0 + total_pages = 1 + cats = self.getCatId(quality['identifier']) + + while page < total_pages: + + movieTitle = tryUrlencode('"%s" %s' % (title, movie['library']['year'])) + search_url = self.urls['search'] % (movieTitle, page, cats[0]) + page += 1 + + data = self.getHTMLData(search_url, opener = self.login_opener) + if data: + try: + soup = BeautifulSoup(data) + + results_table = soup.find('table', attrs = {'class': 'koptekst'}) + if not results_table: + return + + try: + pagelinks = soup.findAll(href = re.compile('page')) + pageNumbers = [int(re.search('page=(?P.+'')', i['href']).group('pageNumber')) for i in pagelinks] + total_pages = max(pageNumbers) + + except: + pass + + entries = results_table.find_all('tr') + + for result in entries[1:]: + prelink = result.find(href = re.compile('details.php')) + link = prelink['href'] + download = result.find('a', href = re.compile('download.php'))['href'] + + if link and download: + + def extra_score(item): + trusted = (0, 10)[result.find('img', alt = re.compile('Trusted')) is not None] + vip = (0, 20)[result.find('img', alt = re.compile('VIP')) is not None] + confirmed = (0, 30)[result.find('img', alt = re.compile('Helpers')) is not None] + moderated = (0, 50)[result.find('img', alt = re.compile('Moderator')) is not None] + + return confirmed + trusted + vip + moderated + + id = re.search('id=(?P\d+)&', link).group('id') + url = self.urls['download'] % (download) + + fileSize = self.parseSize(result.select('td.rowhead')[5].text) + results.append({ + 'id': id, + 'name': toUnicode(prelink.find('b').text), + 'url': url, + 'detail_url': self.urls['detail'] % link, + 'size': fileSize, + 'seeders': tryInt(result.find_all('td')[2].string), + 'leechers': tryInt(result.find_all('td')[3].string), + 'extra_score': extra_score, + 'get_more_info': self.getMoreInfo + }) + + except: + log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc())) + + def getLoginParams(self): + return tryUrlencode({ + 'username': self.conf('username'), + 'password': self.conf('password'), + 'submit': 'Welcome to ILT', + }) + + def getMoreInfo(self, item): + cache_key = 'ilt.%s' % item['id'] + description = self.getCache(cache_key) + + if not description: + + try: + full_description = self.getHTMLData(item['detail_url'], opener = self.login_opener) + html = BeautifulSoup(full_description) + nfo_pre = html.find('td', attrs = {'class':'main'}).findAll('table')[1] + description = toUnicode(nfo_pre.text) if nfo_pre else '' + except: + log.error('Failed getting more info for %s', item['name']) + description = '' + + self.setCache(cache_key, description, timeout = 25920000) + + item['description'] = description + return item + + def loginSuccess(self, output): + return 'logout.php' in output.lower() + + loginCheckSuccess = loginSuccess diff --git a/couchpotato/core/providers/torrent/thepiratebay/__init__.py b/couchpotato/core/providers/torrent/thepiratebay/__init__.py index 83de7a94..8cf9f86c 100644 --- a/couchpotato/core/providers/torrent/thepiratebay/__init__.py +++ b/couchpotato/core/providers/torrent/thepiratebay/__init__.py @@ -16,7 +16,7 @@ config = [{ { 'name': 'enabled', 'type': 'enabler', - 'default': True + 'default': False }, { 'name': 'domain', diff --git a/couchpotato/core/providers/torrent/torrentbytes/main.py b/couchpotato/core/providers/torrent/torrentbytes/main.py index a5849a91..02b86abb 100644 --- a/couchpotato/core/providers/torrent/torrentbytes/main.py +++ b/couchpotato/core/providers/torrent/torrentbytes/main.py @@ -12,7 +12,7 @@ class TorrentBytes(TorrentProvider): urls = { 'test' : 'https://www.torrentbytes.net/', - 'login' : 'https://www.torrentbytes.net/takelogin.php', + 'login' : 'https://www.torrentbytes.net/login.php', 'login_check' : 'https://www.torrentbytes.net/inbox.php', 'detail' : 'https://www.torrentbytes.net/details.php?id=%s', 'search' : 'https://www.torrentbytes.net/browse.php?search=%s&cat=%d', diff --git a/libs/rtorrent/__init__.py b/libs/rtorrent/__init__.py index d19c78b4..b6ff73a0 100755 --- a/libs/rtorrent/__init__.py +++ b/libs/rtorrent/__init__.py @@ -71,12 +71,10 @@ class RTorrent: def _verify_conn(self): # check for rpc methods that should be available - assert {"system.client_version", - "system.library_version"}.issubset(set(self._get_rpc_methods())),\ - "Required RPC methods not available." + assert "system.client_version" in self._get_rpc_methods(), "Required RPC method not available." + assert "system.library_version" in self._get_rpc_methods(), "Required RPC method not available." # minimum rTorrent version check - assert self._meets_version_requirement() is True,\ "Error: Minimum rTorrent version required is {0}".format( MIN_RTORRENT_VERSION_STR) diff --git a/libs/rtorrent/lib/torrentparser.py b/libs/rtorrent/lib/torrentparser.py index 19dd12aa..30170d32 100755 --- a/libs/rtorrent/lib/torrentparser.py +++ b/libs/rtorrent/lib/torrentparser.py @@ -90,9 +90,10 @@ class TorrentParser(): def _calc_info_hash(self): self.info_hash = None if "info" in self._torrent_decoded.keys(): - info_dict = self._torrent_decoded["info"] - self.info_hash = hashlib.sha1(bencode.encode( - info_dict)).hexdigest().upper() + info_encoded = bencode.encode(self._torrent_decoded["info"]) + + if info_encoded: + self.info_hash = hashlib.sha1(info_encoded).hexdigest().upper() return(self.info_hash)