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)