From 6dc3c8d69d2b6b6f1dabcb8cd0bd292a28cc7200 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 11 Nov 2012 22:22:38 +0100 Subject: [PATCH 01/23] Filmweb.pl userscript. closes #1029 Thanks @kempniu --- .../providers/userscript/filmweb/__init__.py | 6 ++++ .../core/providers/userscript/filmweb/main.py | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 couchpotato/core/providers/userscript/filmweb/__init__.py create mode 100644 couchpotato/core/providers/userscript/filmweb/main.py diff --git a/couchpotato/core/providers/userscript/filmweb/__init__.py b/couchpotato/core/providers/userscript/filmweb/__init__.py new file mode 100644 index 00000000..8ead54d6 --- /dev/null +++ b/couchpotato/core/providers/userscript/filmweb/__init__.py @@ -0,0 +1,6 @@ +from .main import Filmweb + +def start(): + return Filmweb() + +config = [] diff --git a/couchpotato/core/providers/userscript/filmweb/main.py b/couchpotato/core/providers/userscript/filmweb/main.py new file mode 100644 index 00000000..5e6adbe1 --- /dev/null +++ b/couchpotato/core/providers/userscript/filmweb/main.py @@ -0,0 +1,28 @@ +from couchpotato.core.providers.userscript.base import UserscriptBase +import re + + +class Filmweb(UserscriptBase): + + includes = ['http://www.filmweb.pl/*'] + + def getMovie(self, url): + + cookie = {'Cookie': 'welcomeScreen=welcome_screen'} + + try: + data = self.urlopen(url, headers = cookie) + except: + return + + name = re.search("(?P[^<]+)", data) + + if name is None: + name = re.search("(?P[^<]+)", data) + + name = name.group('name').decode('string_escape') + + year = re.search("\((?P[^\)]+)\).*?", data) + year = year.group('year') + + return self.search(name, year) From 68c0496f8ea8c3beaa30f6592118d69268b70491 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 13 Nov 2012 20:24:58 +0100 Subject: [PATCH 02/23] Don't hide partial keyword log. closes #1043 --- couchpotato/core/logger.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/logger.py b/couchpotato/core/logger.py index 09875a67..3ad33aa0 100644 --- a/couchpotato/core/logger.py +++ b/couchpotato/core/logger.py @@ -56,7 +56,8 @@ class CPLog(object): if not Env.get('dev'): for replace in self.replace_private: - msg = re.sub('(%s=)[^\&]+' % replace, '%s=xxx' % replace, msg) + msg = re.sub('(\?%s=)[^\&]+' % replace, '?%s=xxx' % replace, msg) + msg = re.sub('(&%s=)[^\&]+' % replace, '&%s=xxx' % replace, msg) # Replace api key try: From 71cca6b87f30ee7327af94090bbdab65dbeb2761 Mon Sep 17 00:00:00 2001 From: clinton-hall Date: Tue, 13 Nov 2012 18:43:31 -0800 Subject: [PATCH 03/23] Removed excess tags from title Now only adds "Source", "Video Format", "Audio Format", and "Language" --- couchpotato/core/providers/nzb/newzbin/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/providers/nzb/newzbin/main.py b/couchpotato/core/providers/nzb/newzbin/main.py index 06a09a94..55019ad5 100644 --- a/couchpotato/core/providers/nzb/newzbin/main.py +++ b/couchpotato/core/providers/nzb/newzbin/main.py @@ -94,8 +94,10 @@ class Newzbin(NZBProvider, RSS): # Add attributes to name try: + use_attr = ['Source', 'Video Fmt', 'Audio Fmt', 'Language'] for attr in nzb.find('{%s}attributes' % REPORT_NS): - title += ' ' + attr.text + if attr.get("type") in use_attr: + title += ' ' + attr.text except: pass From 3635da1f59324888d8a4348bafb2584186ec8c35 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 14 Nov 2012 13:43:38 +0100 Subject: [PATCH 04/23] Add new api for upcoming extension --- couchpotato/core/plugins/userscript/main.py | 8 ++++++++ couchpotato/templates/_desktop.html | 2 ++ 2 files changed, 10 insertions(+) diff --git a/couchpotato/core/plugins/userscript/main.py b/couchpotato/core/plugins/userscript/main.py index e5999ab3..3ff7fb07 100644 --- a/couchpotato/core/plugins/userscript/main.py +++ b/couchpotato/core/plugins/userscript/main.py @@ -21,6 +21,7 @@ class Userscript(Plugin): addApiView('userscript.get//', self.getUserScript, static = True) addApiView('userscript', self.iFrame) addApiView('userscript.add_via_url', self.getViaUrl) + addApiView('userscript.includes', self.getIncludes) addApiView('userscript.bookmark', self.bookmark) addEvent('userscript.get_version', self.getVersion) @@ -35,6 +36,13 @@ class Userscript(Plugin): return self.renderTemplate(__file__, 'bookmark.js', **params) + def getIncludes(self): + + return jsonified({ + 'includes': fireEvent('userscript.get_includes', merge = True), + 'excludes': fireEvent('userscript.get_excludes', merge = True), + }) + def getUserScript(self, random = '', filename = ''): params = { diff --git a/couchpotato/templates/_desktop.html b/couchpotato/templates/_desktop.html index 77ace530..8689b666 100644 --- a/couchpotato/templates/_desktop.html +++ b/couchpotato/templates/_desktop.html @@ -55,6 +55,8 @@ 'is_remote': false }); + $(document.body).set('data-api', window.location.protocol + '//' + window.location.host + Api.createUrl().replace('/default/', '/')); + // Catch errors window.onerror = function(message, file, line){ From 4224a25e540c51ace60c11914930bb03aea9012f Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 14 Nov 2012 13:44:26 +0100 Subject: [PATCH 05/23] Sabnzbd, show what is in filedata. --- couchpotato/core/downloaders/sabnzbd/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/downloaders/sabnzbd/main.py b/couchpotato/core/downloaders/sabnzbd/main.py index 9bd6922d..e9b4c0ae 100644 --- a/couchpotato/core/downloaders/sabnzbd/main.py +++ b/couchpotato/core/downloaders/sabnzbd/main.py @@ -28,7 +28,7 @@ class Sabnzbd(Downloader): if filedata: if len(filedata) < 50: - log.error('No proper nzb available!') + log.error('No proper nzb available: %s', (filedata)) return False # If it's a .rar, it adds the .rar extension, otherwise it stays .nzb From e53a9ed30a17b82f0a28475c9372f78238208867 Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 15 Nov 2012 18:30:45 +0100 Subject: [PATCH 06/23] Try next on failed download from provider --- couchpotato/core/plugins/searcher/main.py | 2 +- couchpotato/core/providers/base.py | 8 +++++++- couchpotato/core/providers/nzb/newzbin/main.py | 3 ++- couchpotato/core/providers/nzb/newznab/main.py | 3 ++- couchpotato/core/providers/nzb/nzbmatrix/main.py | 3 --- couchpotato/core/providers/nzb/nzbsrus/main.py | 3 --- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index 312d2388..55115122 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -239,7 +239,7 @@ class Searcher(Plugin): filedata = None if data.get('download') and (ismethod(data.get('download')) or isfunction(data.get('download'))): filedata = data.get('download')(url = data.get('url'), nzb_id = data.get('id')) - if filedata is 'try_next': + if filedata == 'try_next': return filedata successful = fireEvent('download', data = data, movie = movie, manual = manual, filedata = filedata, single = True) diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py index 17ccb2a5..50a659b0 100644 --- a/couchpotato/core/providers/base.py +++ b/couchpotato/core/providers/base.py @@ -6,6 +6,7 @@ from couchpotato.environment import Env from urlparse import urlparse import re import time +import traceback log = CPLog(__name__) @@ -56,7 +57,12 @@ class YarrProvider(Provider): addEvent('nzb.feed', self.feed) def download(self, url = '', nzb_id = ''): - return self.urlopen(url) + try: + return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}, show_error = False) + except: + log.error('Failed getting nzb from %s: %s', (self.getName(), traceback.format_exc())) + + return 'try_next' def feed(self): return [] diff --git a/couchpotato/core/providers/nzb/newzbin/main.py b/couchpotato/core/providers/nzb/newzbin/main.py index 55019ad5..7359bfdc 100644 --- a/couchpotato/core/providers/nzb/newzbin/main.py +++ b/couchpotato/core/providers/nzb/newzbin/main.py @@ -144,7 +144,8 @@ class Newzbin(NZBProvider, RSS): }, show_error = False) except Exception, e: log.error('Failed downloading from newzbin, check credit: %s', e) - return False + + return 'try_next' def getFormatId(self, format): for id, quality in self.format_ids.iteritems(): diff --git a/couchpotato/core/providers/nzb/newznab/main.py b/couchpotato/core/providers/nzb/newznab/main.py index 2ea36a3b..43ea2bd0 100644 --- a/couchpotato/core/providers/nzb/newznab/main.py +++ b/couchpotato/core/providers/nzb/newznab/main.py @@ -219,4 +219,5 @@ class Newznab(NZBProvider, RSS): return 'try_next' log.error('Failed download from %s', (host, traceback.format_exc())) - raise + + return 'try_next' diff --git a/couchpotato/core/providers/nzb/nzbmatrix/main.py b/couchpotato/core/providers/nzb/nzbmatrix/main.py index 9539eac1..4da2fbd9 100644 --- a/couchpotato/core/providers/nzb/nzbmatrix/main.py +++ b/couchpotato/core/providers/nzb/nzbmatrix/main.py @@ -98,9 +98,6 @@ class NZBMatrix(NZBProvider, RSS): return results - def download(self, url = '', nzb_id = ''): - return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}) - def getApiExt(self): return '&username=%s&apikey=%s' % (self.conf('username'), self.conf('api_key')) diff --git a/couchpotato/core/providers/nzb/nzbsrus/main.py b/couchpotato/core/providers/nzb/nzbsrus/main.py index 20a51d56..b92d6774 100644 --- a/couchpotato/core/providers/nzb/nzbsrus/main.py +++ b/couchpotato/core/providers/nzb/nzbsrus/main.py @@ -97,8 +97,5 @@ class Nzbsrus(NZBProvider, RSS): return results - def download(self, url = '', nzb_id = ''): - return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}) - def getApiExt(self): return '/%s/' % (self.conf('userid')) From 95c5db2d176690af685f371037c58df1247efa31 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 20 Nov 2012 20:36:52 +0100 Subject: [PATCH 07/23] Use css for search animations --- .../core/plugins/movie/static/search.css | 24 +++++-- .../core/plugins/movie/static/search.js | 72 +++++++------------ 2 files changed, 43 insertions(+), 53 deletions(-) diff --git a/couchpotato/core/plugins/movie/static/search.css b/couchpotato/core/plugins/movie/static/search.css index 76130cb0..af942295 100644 --- a/couchpotato/core/plugins/movie/static/search.css +++ b/couchpotato/core/plugins/movie/static/search.css @@ -91,10 +91,15 @@ .movie_result { overflow: hidden; height: 140px; + position: relative; } .movie_result .options { - height: 140px; + position: absolute; + height: 100%; + width: 100%; + top: 0; + left: 0; border: 1px solid transparent; border-width: 1px 0; border-radius: 0; @@ -133,17 +138,21 @@ .movie_result .data { padding: 0 15px; - width: 470px; - position: relative; - height: 140px; + position: absolute; + height: 100%; + width: 100%; top: 0; - margin: -140px 0 0 0; + left: 0; background: #5c697b; cursor: pointer; border-bottom: 1px solid #333; border-top: 1px solid rgba(255,255,255, 0.15); + transition: all .6s cubic-bezier(0.9,0,0.1,1); } + .movie_result .data.open { + left: 100%; + } .movie_result:last-child .data { border-bottom: 0; } @@ -193,4 +202,9 @@ .search_form .mask { border-radius: 3px; + position: absolute; + height: 100%; + width: 100%; + left: 0; + top: 0; } \ No newline at end of file diff --git a/couchpotato/core/plugins/movie/static/search.js b/couchpotato/core/plugins/movie/static/search.js index 2115ef4d..222a93ce 100644 --- a/couchpotato/core/plugins/movie/static/search.js +++ b/couchpotato/core/plugins/movie/static/search.js @@ -19,7 +19,9 @@ Block.Search = new Class({ self.hideResults(false) }, 'blur': function(){ - self.el.removeClass('focused') + (function(){ + self.el.removeClass('focused') + }).delay(2000); } } }), @@ -117,7 +119,7 @@ Block.Search = new Class({ self.hideResults(false); if(!cache){ - self.positionMask().fade('in'); + self.mask.fade('in'); if(!self.spinner) self.spinner = createSpinner(self.mask); @@ -139,7 +141,6 @@ Block.Search = new Class({ fill: function(q, json){ var self = this; - self.positionMask() self.cache[q] = json self.movies = {} @@ -168,19 +169,6 @@ Block.Search = new Class({ }, - positionMask: function(){ - var self = this; - - var s = self.result_container.getSize() - - return self.mask.setStyles({ - 'width': s.x, - 'height': s.y - }).position({ - 'relativeTo': self.result_container - }) - }, - loading: function(bool){ this.el[bool ? 'addClass' : 'removeClass']('loading') }, @@ -193,7 +181,7 @@ Block.Search = new Class({ Block.Search.Item = new Class({ - initialize: function(info){ + initialize: function(info, options){ var self = this; self.info = info; @@ -203,14 +191,13 @@ Block.Search.Item = new Class({ }, create: function(){ - var self = this; - - var info = self.info; + var self = this, + info = self.info; self.el = new Element('div.movie_result', { 'id': info.imdb }).adopt( - self.options = new Element('div.options.inlay'), + self.options_el = new Element('div.options.inlay'), self.data_container = new Element('div.data', { 'tween': { duration: 400, @@ -273,11 +260,7 @@ Block.Search.Item = new Class({ self.createOptions(); - if(!self.width) - self.width = self.data_container.getCoordinates().width - - self.data_container.tween('left', 0, self.width); - + self.data_container.addClass('open'); self.el.addEvent('outerClick', self.closeOptions.bind(self)) }, @@ -285,7 +268,7 @@ Block.Search.Item = new Class({ closeOptions: function(){ var self = this; - self.data_container.tween('left', self.width, 0); + self.data_container.removeClass('open'); self.el.removeEvents('outerClick') }, @@ -302,28 +285,31 @@ Block.Search.Item = new Class({ 'profile_id': self.profile_select.get('value') }, 'onComplete': function(json){ - self.options.empty(); - self.options.adopt( + self.options_el.empty(); + self.options_el.adopt( new Element('div.message', { 'text': json.added ? 'Movie succesfully added.' : 'Movie didn\'t add properly. Check logs' }) ); + self.mask.fade('out'); }, 'onFailure': function(){ - self.options.empty(); - self.options.adopt( + self.options_el.empty(); + self.options_el.adopt( new Element('div.message', { 'text': 'Something went wrong, check the logs for more info.' }) ); + self.mask.fade('out'); } }); }, createOptions: function(){ - var self = this; + var self = this, + info = self.info; - if(!self.options.hasClass('set')){ + if(!self.options_el.hasClass('set')){ if(self.info.in_library){ var in_library = []; @@ -332,10 +318,10 @@ Block.Search.Item = new Class({ }); } - self.options.adopt( + self.options_el.grab( new Element('div').adopt( - self.option_thumbnail = self.info.images && self.info.images.poster.length > 0 ? new Element('img.thumbnail', { - 'src': self.info.images.poster[0], + self.thumbnail = (info.images && info.images.poster.length > 0) ? new Element('img.thumbnail', { + 'src': info.images.poster[0], 'height': null, 'width': null }) : null, @@ -372,7 +358,7 @@ Block.Search.Item = new Class({ }).inject(self.profile_select) }); - self.options.addClass('set'); + self.options_el.addClass('set'); } }, @@ -380,17 +366,7 @@ Block.Search.Item = new Class({ loadingMask: function(){ var self = this; - var s = self.options.getSize(); - - self.mask = new Element('span.mask', { - 'styles': { - 'position': 'relative', - 'width': s.x, - 'height': s.y, - 'top': -s.y, - 'display': 'block' - } - }).inject(self.options).fade('hide') + self.mask = new Element('span.mask').inject(self.el).fade('hide') createSpinner(self.mask) self.mask.fade('in') From daaa2154e578b451cd22284e93811a0586cd22f5 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 20 Nov 2012 21:07:21 +0100 Subject: [PATCH 08/23] Return when no table is returned. fix #1053 --- couchpotato/core/providers/torrent/thepiratebay/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/providers/torrent/thepiratebay/main.py b/couchpotato/core/providers/torrent/thepiratebay/main.py index a4ce3631..29a8c8ef 100644 --- a/couchpotato/core/providers/torrent/thepiratebay/main.py +++ b/couchpotato/core/providers/torrent/thepiratebay/main.py @@ -57,7 +57,7 @@ class ThePirateBay(TorrentProvider): data = '' try: - data = self.urlopen(proxy, timeout = 3) + data = self.urlopen(proxy, timeout = 3, show_error = False) except: log.debug('Failed tpb proxy %s', proxy) @@ -88,6 +88,10 @@ class ThePirateBay(TorrentProvider): try: soup = BeautifulSoup(data) results_table = soup.find('table', attrs = {'id': 'searchResult'}) + + if not results_table: + return results + entries = results_table.find_all('tr') for result in entries[1:]: link = result.find(href = re.compile('torrent\/\d+\/')) From 723f7202801e91fc243204748a7d4d24a54eaaf0 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 20 Nov 2012 21:15:22 +0100 Subject: [PATCH 09/23] Ignore header in TPB results --- couchpotato/core/providers/torrent/thepiratebay/main.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/providers/torrent/thepiratebay/main.py b/couchpotato/core/providers/torrent/thepiratebay/main.py index 29a8c8ef..b569fd6a 100644 --- a/couchpotato/core/providers/torrent/thepiratebay/main.py +++ b/couchpotato/core/providers/torrent/thepiratebay/main.py @@ -93,11 +93,15 @@ class ThePirateBay(TorrentProvider): return results entries = results_table.find_all('tr') - for result in entries[1:]: + for result in entries[2:]: link = result.find(href = re.compile('torrent\/\d+\/')) download = result.find(href = re.compile('magnet:')) - size = re.search('Size (?P.+),', unicode(result.select('font.detDesc')[0])).group('size') + try: + size = re.search('Size (?P.+),', unicode(result.select('font.detDesc')[0])).group('size') + except: + continue + if link and download: def extra_score(item): From 2ed72c9098fd26d6261c05e53cb698d7e761b2a0 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 20 Nov 2012 21:15:43 +0100 Subject: [PATCH 10/23] Don't show button bar when there aren't any releases --- .../core/plugins/movie/static/movie.js | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/couchpotato/core/plugins/movie/static/movie.js b/couchpotato/core/plugins/movie/static/movie.js index b10b5b1b..5a49e416 100644 --- a/couchpotato/core/plugins/movie/static/movie.js +++ b/couchpotato/core/plugins/movie/static/movie.js @@ -479,29 +479,32 @@ var ReleaseAction = new Class({ self.release_container.getElement('#release_'+self.next_release.id).addClass('next_release'); } - self.trynext_container.adopt( - new Element('span.or', { - 'text': 'This movie is snatched, if anything went wrong, download' - }), - self.last_release ? new Element('a.button.orange', { - 'text': 'the same release again', - 'events': { - 'click': self.trySameRelease.bind(self) - } - }) : null, - self.next_release && self.last_release ? new Element('span.or', { - 'text': ',' - }) : null, - self.next_release ? [new Element('a.button.green', { - 'text': self.last_release ? 'another release' : 'the best release', - 'events': { - 'click': self.tryNextRelease.bind(self) - } - }), - new Element('span.or', { - 'text': 'or pick one below' - })] : null - ) + if(self.next_release || self.last_release){ + + self.trynext_container.adopt( + new Element('span.or', { + 'text': 'This movie is snatched, if anything went wrong, download' + }), + self.last_release ? new Element('a.button.orange', { + 'text': 'the same release again', + 'events': { + 'click': self.trySameRelease.bind(self) + } + }) : null, + self.next_release && self.last_release ? new Element('span.or', { + 'text': ',' + }) : null, + self.next_release ? [new Element('a.button.green', { + 'text': self.last_release ? 'another release' : 'the best release', + 'events': { + 'click': self.tryNextRelease.bind(self) + } + }), + new Element('span.or', { + 'text': 'or pick one below' + })] : null + ) + } } From 9f19902221dbdf30b74b254d6047a90c604631e6 Mon Sep 17 00:00:00 2001 From: Randall Ma Date: Thu, 22 Nov 2012 17:34:44 -0800 Subject: [PATCH 11/23] fixed typo of "successfully" --- couchpotato/core/plugins/movie/static/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/movie/static/search.js b/couchpotato/core/plugins/movie/static/search.js index 222a93ce..ba8b547e 100644 --- a/couchpotato/core/plugins/movie/static/search.js +++ b/couchpotato/core/plugins/movie/static/search.js @@ -288,7 +288,7 @@ Block.Search.Item = new Class({ self.options_el.empty(); self.options_el.adopt( new Element('div.message', { - 'text': json.added ? 'Movie succesfully added.' : 'Movie didn\'t add properly. Check logs' + 'text': json.added ? 'Movie successfully added.' : 'Movie didn\'t add properly. Check logs' }) ); self.mask.fade('out'); From 3464435a5c07605f7f29dd232ac3d817dea5c783 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 24 Nov 2012 16:53:38 +0100 Subject: [PATCH 12/23] Imdb url only in XBMC meta data --- couchpotato/core/providers/metadata/xbmc/__init__.py | 8 ++++++++ couchpotato/core/providers/metadata/xbmc/main.py | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/couchpotato/core/providers/metadata/xbmc/__init__.py b/couchpotato/core/providers/metadata/xbmc/__init__.py index 71de827a..ea426dba 100644 --- a/couchpotato/core/providers/metadata/xbmc/__init__.py +++ b/couchpotato/core/providers/metadata/xbmc/__init__.py @@ -31,6 +31,14 @@ config = [{ 'advanced': True, 'description': '%s is the rootname of the movie. For example "/path/to/movie cd1.mkv" will be "/path/to/movie"' }, + { + 'name': 'meta_url_only', + 'label': 'Only IMDB URL', + 'default': False, + 'advanced': True, + 'description': 'Create a nfo with only the IMDB url inside', + 'type': 'bool', + }, { 'name': 'meta_fanart', 'label': 'Fanart', diff --git a/couchpotato/core/providers/metadata/xbmc/main.py b/couchpotato/core/providers/metadata/xbmc/main.py index 361ec120..1fd95846 100644 --- a/couchpotato/core/providers/metadata/xbmc/main.py +++ b/couchpotato/core/providers/metadata/xbmc/main.py @@ -28,6 +28,11 @@ class XBMC(MetaDataBase): return os.path.join(root, basename.replace('%s', name)) def getNfo(self, movie_info = {}, data = {}): + + # return imdb url only + if self.conf('meta_url_only'): + return 'http://www.imdb.com/title/%s/' % toUnicode(data['library']['identifier']) + nfoxml = Element('movie') # Title From eafc3db74da372f00639d78eda856cdabab5d538 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 30 Nov 2012 21:11:34 +0100 Subject: [PATCH 13/23] Add HDTS as alternative tag. #1097 --- couchpotato/core/plugins/quality/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index 7964fb18..0534cd1b 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -26,7 +26,7 @@ class QualityPlugin(Plugin): {'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip'], 'allow': ['dvdr', 'dvd'], 'ext':['avi', 'mpg', 'mpeg']}, {'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': [], 'allow': ['dvdr'], 'ext':['avi', 'mpg', 'mpeg']}, {'identifier': 'tc', 'size': (600, 1000), 'label': 'TeleCine', 'alternative': ['telecine'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}, - {'identifier': 'ts', 'size': (600, 1000), 'label': 'TeleSync', 'alternative': ['telesync'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}, + {'identifier': 'ts', 'size': (600, 1000), 'label': 'TeleSync', 'alternative': ['telesync', 'hdts'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}, {'identifier': 'cam', 'size': (600, 1000), 'label': 'Cam', 'alternative': ['camrip', 'hdcam'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']} ] pre_releases = ['cam', 'ts', 'tc', 'r5', 'scr'] From 81b7ebaf5173920b1dfa4fed6bf1fac327102d9f Mon Sep 17 00:00:00 2001 From: Alexej Haak Date: Thu, 29 Nov 2012 18:31:21 +0100 Subject: [PATCH 14/23] Kere.ws Implementation from Pheelee Implementation by Pheelee he closed the pull request some time ago and I dont know why.. Using this for some time now with no problems at all --- .../core/providers/nzb/kere/__init__.py | 32 ++++++ couchpotato/core/providers/nzb/kere/main.py | 101 ++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 couchpotato/core/providers/nzb/kere/__init__.py create mode 100644 couchpotato/core/providers/nzb/kere/main.py diff --git a/couchpotato/core/providers/nzb/kere/__init__.py b/couchpotato/core/providers/nzb/kere/__init__.py new file mode 100644 index 00000000..394c1125 --- /dev/null +++ b/couchpotato/core/providers/nzb/kere/__init__.py @@ -0,0 +1,32 @@ +from .main import Kere + +def start(): + return Kere() + +config = [{ + 'name': 'kere', + 'groups': [ + { + 'tab': 'searcher', + 'subtab': 'nzb_providers', + 'name': 'kere', + 'label': 'Kere', + 'description': 'See Kere', + 'wizard': True, + 'options': [ + { + 'name': 'enabled', + 'type': 'enabler', + }, + { + 'name': 'username', + }, + { + 'name': 'api_key', + 'default': '', + 'label': 'Api Key', + }, + ], + }, + ], +}] \ No newline at end of file diff --git a/couchpotato/core/providers/nzb/kere/main.py b/couchpotato/core/providers/nzb/kere/main.py new file mode 100644 index 00000000..10b1b877 --- /dev/null +++ b/couchpotato/core/providers/nzb/kere/main.py @@ -0,0 +1,101 @@ +from couchpotato.core.event import fireEvent +from couchpotato.core.helpers.encoding import tryUrlencode +from couchpotato.core.helpers.rss import RSS +from couchpotato.core.logger import CPLog +from couchpotato.core.providers.nzb.base import NZBProvider +from couchpotato.environment import Env +from libs.dateutil.parser import parse +import time +import xml.etree.ElementTree as XMLTree + +log = CPLog(__name__) + + +class Kere(NZBProvider, RSS): + + urls = { + 'download': 'http://kere.ws/api?t=get&id=%s', + 'detail': 'http://kere.ws/api?t=details&id=%s', + 'search': 'http://kere.ws/api', + } + + cat_ids = [ + ([1000], ['720p', '1080p','cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip', 'dvdr']), + ] + cat_backup_id = 2 + + def search(self, movie, quality): + + results = [] + + if self.isDisabled(): + return results + + cat_ids = ','.join(['%s' % x for x in self.getCatId(quality.get('identifier'))]) + + arguments = tryUrlencode({ + 't' : 'movie', + 'imdbid': movie['library']['identifier'].replace('tt',''), + 'cat': cat_ids, + 'apikey': self.conf('api_key'), + }) + url = "%s?%s" % (self.urls['search'], arguments) + + cache_key = 'kere.%s.%s' % (movie['library'].get('identifier'), cat_ids) + + data = self.getCache(cache_key, url, cache_timeout = 1800, headers = {'User-Agent': Env.getIdentifier()}) + if data: + try: + try: + data = XMLTree.fromstring(data) + nzbs = self.getElements(data, 'channel/item') + except Exception, e: + log.debug('%s, %s', (self.getName(), e)) + return results + + for nzb in nzbs: + + title = self.getTextElement(nzb, "title") + if 'error' in title.lower(): continue + + id = self.getTextElement(nzb, "link").replace('http://kere.ws/getnzb/','').split('.')[0] + size = '%f KB' % (float(str(nzb.find('enclosure').attrib).split("'length': ")[1].split(',')[0].strip("'").strip()) / 1024) + date = str(self.getTextElement(nzb, "pubDate")) + + new = { + 'id': str(id), + 'type': 'nzb', + 'provider': self.getName(), + 'name': title, + 'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))), + 'size': self.parseSize(size), + 'url': self.urls['download'] % id + self.getApiExt(), + 'download': self.download, + 'detail_url': self.urls['detail'] % id, + 'description': self.getTextElement(nzb, "description"), + 'check_nzb': True, + } + + is_correct_movie = fireEvent('searcher.correct_movie', + nzb = new, movie = movie, quality = quality, + imdb_results = True, single = True) + + if is_correct_movie: + new['score'] = fireEvent('score.calculate', new, movie, single = True) + results.append(new) + self.found(new) + + return results + except SyntaxError: + log.error('Failed to parse XML response from Kere.ws') + + return results + + def download(self, url = '', nzb_id = ''): + return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}) + + def getApiExt(self): + return '&username=%s&apikey=%s' % (self.conf('username'), self.conf('api_key')) + + def isEnabled(self): + return NZBProvider.isEnabled(self) and self.conf('username') and self.conf('api_key') \ No newline at end of file From fdd0826b4f567caa779a4f1239c64d74e78e0b33 Mon Sep 17 00:00:00 2001 From: Alexej Haak Date: Thu, 29 Nov 2012 18:52:10 +0100 Subject: [PATCH 15/23] Added custom categories less big api requests this way and better results (the cats include audio quality filter) --- couchpotato/core/providers/nzb/kere/main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/providers/nzb/kere/main.py b/couchpotato/core/providers/nzb/kere/main.py index 10b1b877..50149ab8 100644 --- a/couchpotato/core/providers/nzb/kere/main.py +++ b/couchpotato/core/providers/nzb/kere/main.py @@ -20,7 +20,12 @@ class Kere(NZBProvider, RSS): } cat_ids = [ - ([1000], ['720p', '1080p','cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip', 'dvdr']), + ([1000], [ 'cam', 'ts', 'tc', 'scr']), + ([1010], [ 'r5' ]), + ([1020], [ 'dvdrip', 'brrip' ]), + ([1030], [ 'dvdr' ]), + ([1050], [ '720p' ]), + ([1060], [ '1080p' ]), ] cat_backup_id = 2 From c29a8b47d6bfcef0aba679bc79058bc00370c6d8 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Fri, 2 Nov 2012 08:12:53 +0100 Subject: [PATCH 16/23] Basic support of Synology DownloadStation API VERY basic. We're not logging out at the moment, and we keep the session open. No verification of the protocol version either (I assume DSM 4.1). Very basic, indeed --- .../core/downloaders/Synology/__init__.py | 44 ++++++++ couchpotato/core/downloaders/Synology/main.py | 106 ++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 couchpotato/core/downloaders/Synology/__init__.py create mode 100644 couchpotato/core/downloaders/Synology/main.py diff --git a/couchpotato/core/downloaders/Synology/__init__.py b/couchpotato/core/downloaders/Synology/__init__.py new file mode 100644 index 00000000..2b4757a5 --- /dev/null +++ b/couchpotato/core/downloaders/Synology/__init__.py @@ -0,0 +1,44 @@ +from .main import Synology + +def start(): + return Synology() + +config = [{ + 'name': 'synology', + 'groups': [ + { + 'tab': 'downloaders', + 'name': 'synology', + 'label': 'Synology', + 'description': 'Send torrents to Synology\'s Download Station.', + 'wizard': True, + 'options': [ + { + 'name': 'enabled', + 'default': 0, + 'type': 'enabler', + 'radio_group': 'torrent', + }, + { + 'name': 'host', + 'default': 'localhost:5000', + 'description': 'Hostname with port. Usually localhost:5000', + }, + { + 'name': 'username', + }, + { + 'name': 'password', + 'type': 'password', + }, + { + 'name': 'manual', + 'default': 0, + 'type': 'bool', + 'advanced': True, + 'description': 'Disable this downloader for automated searches, but use it when I manually send a release.', + }, + ], + } + ], +}] diff --git a/couchpotato/core/downloaders/Synology/main.py b/couchpotato/core/downloaders/Synology/main.py new file mode 100644 index 00000000..764c0112 --- /dev/null +++ b/couchpotato/core/downloaders/Synology/main.py @@ -0,0 +1,106 @@ +from base64 import b64encode +from couchpotato.core.downloaders.base import Downloader +from couchpotato.core.helpers.encoding import isInt +from couchpotato.core.logger import CPLog +import httplib +import json +import os.path +import re +import urllib2 +import urllib + +log = CPLog(__name__) + +class Synology(Downloader): + + type = ['torrent_magnet'] + log = CPLog(__name__) + + def download(self, data, movie, manual = False, filedata = None): + + if self.isDisabled(manual) or not self.isCorrectType(data.get('type')): + return + + log.error('Sending "%s" (%s) to Synology.', (data.get('name'), data.get('type'))) + + # Load host from config and split out port. + host = self.conf('host').split(':') + if not isInt(host[1]): + log.error('Config properties are not filled in correctly, port is missing.') + return False + + if data.get('type') == 'torrent': + log.error('Can\'t add binary torrent file') + return False + + try: + # Send request to Transmission + srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password')) + remote_torrent = srpc.add_torrent_uri(data.get('url')) + log.info("Response: %s", remote_torrent) + return remote_torrent['success'] + except Exception, err: + log.error("Exception while adding torrent: %s", err) + return False + + +class SynologyRPC(object): + + """SynologyRPC lite library""" + + def __init__(self, host = 'localhost', port = 5000, username = None, password = None): + + super(SynologyRPC, self).__init__() + + self.DLurl = 'http://' + host + ':' + str(port) + '/webapi/DownloadStation/task.cgi' + self.Authurl = 'http://' + host + ':' + str(port) + '/webapi/auth.cgi' + self.username = username + self.password = password + self.session_name = "DownloadStation" + if username and password: + if self._login() == True: + log.info( ">Login ok" ) + else: + log.error( ">Login failed" ) + elif username or password: + log.error('User or password missing, not using authentication.') + + def _login(self): + args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, + 'method': 'login', 'session': self.session_name, 'format': 'sid'} + response = self._req(self.Authurl, args) + if response['success'] == True: + self.sid = response['data']['sid'] + log.info( "Sid=%s", self.sid) + return response['success'] + + def _logout(self): + args = {'api':'SYNO.API.Auth', 'version':1, 'method':'logout', 'session':self.session_name} + response = self._req(self.Authurl, args) + return response['success'] + + def _req(self, url, args): + req_url = url + '?' + urllib.urlencode(args) + #print "Trying URL: ", req_url + try: + req_open = urllib2.urlopen(req_url) + response = json.loads(req_open.read()) + if response['success'] == True: + log.info('Synology action successfull') + return response + except httplib.InvalidURL, err: + log.error('Invalid Transmission host, check your config %s', err) + return False + except urllib2.HTTPError, err: + log.error('SynologyRPC HTTPError: %s', err) + return False + except urllib2.URLError, err: + log.error('Unable to connect to Synology %s', err) + return False + + def add_torrent_uri(self, torrent): + log.info( "Adding torrent URL %s", torrent) + args = {'api':'SYNO.DownloadStation.Task', 'version':1, 'method':'create', 'uri':torrent, '_sid':self.sid} + response = self._req(self.DLurl, args) + return response + From afea12c7c01ce75572b8c5cc18da2ec7ae6b3b4a Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Tue, 27 Nov 2012 21:01:37 +0100 Subject: [PATCH 17/23] Log out when finished --- couchpotato/core/downloaders/Synology/main.py | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/couchpotato/core/downloaders/Synology/main.py b/couchpotato/core/downloaders/Synology/main.py index 764c0112..2d66aa51 100644 --- a/couchpotato/core/downloaders/Synology/main.py +++ b/couchpotato/core/downloaders/Synology/main.py @@ -57,31 +57,26 @@ class SynologyRPC(object): self.username = username self.password = password self.session_name = "DownloadStation" - if username and password: - if self._login() == True: - log.info( ">Login ok" ) - else: - log.error( ">Login failed" ) - elif username or password: - log.error('User or password missing, not using authentication.') def _login(self): - args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, + if self.username and self.password: + args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, 'method': 'login', 'session': self.session_name, 'format': 'sid'} - response = self._req(self.Authurl, args) - if response['success'] == True: - self.sid = response['data']['sid'] - log.info( "Sid=%s", self.sid) - return response['success'] + response = self._req(self.Authurl, args) + if response['success'] == True: + self.sid = response['data']['sid'] + log.debug( "Sid=%s", self.sid) + return response + elif username or password: + log.error('User or password missing, not using authentication.') + return False def _logout(self): - args = {'api':'SYNO.API.Auth', 'version':1, 'method':'logout', 'session':self.session_name} - response = self._req(self.Authurl, args) - return response['success'] + args = {'api':'SYNO.API.Auth', 'version':1, 'method':'logout', 'session':self.session_name, '_sid':self.sid} + return self._req(self.Authurl, args) def _req(self, url, args): req_url = url + '?' + urllib.urlencode(args) - #print "Trying URL: ", req_url try: req_open = urllib2.urlopen(req_url) response = json.loads(req_open.read()) @@ -100,7 +95,16 @@ class SynologyRPC(object): def add_torrent_uri(self, torrent): log.info( "Adding torrent URL %s", torrent) - args = {'api':'SYNO.DownloadStation.Task', 'version':1, 'method':'create', 'uri':torrent, '_sid':self.sid} - response = self._req(self.DLurl, args) + response = {} + # login + login = self._login() + if len(login) > 0 and login['success'] == True: + log.info("Login success, adding torrent") + args = {'api':'SYNO.DownloadStation.Task', 'version':1, 'method':'create', 'uri':torrent, '_sid':self.sid} + response = self._req(self.DLurl, args) + self._logout() + else: + log.error("Couldn't login to Synology, %s", login) return response + From e36c8ec3abb07ebc0d3c0f519c06923211c8a7ee Mon Sep 17 00:00:00 2001 From: Guillaume Bienkowski Date: Wed, 28 Nov 2012 14:23:35 +0100 Subject: [PATCH 18/23] Fixed typo --- couchpotato/core/downloaders/Synology/main.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/couchpotato/core/downloaders/Synology/main.py b/couchpotato/core/downloaders/Synology/main.py index 2d66aa51..afed59c7 100644 --- a/couchpotato/core/downloaders/Synology/main.py +++ b/couchpotato/core/downloaders/Synology/main.py @@ -1,11 +1,9 @@ -from base64 import b64encode from couchpotato.core.downloaders.base import Downloader from couchpotato.core.helpers.encoding import isInt from couchpotato.core.logger import CPLog import httplib import json -import os.path -import re + import urllib2 import urllib @@ -60,14 +58,14 @@ class SynologyRPC(object): def _login(self): if self.username and self.password: - args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, + args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, 'method': 'login', 'session': self.session_name, 'format': 'sid'} response = self._req(self.Authurl, args) if response['success'] == True: self.sid = response['data']['sid'] log.debug( "Sid=%s", self.sid) return response - elif username or password: + elif self.username or self.password: log.error('User or password missing, not using authentication.') return False From c852949591d1cce0bef3af097619be0bdf0ccb50 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 30 Nov 2012 21:36:33 +0100 Subject: [PATCH 19/23] To lower case --- couchpotato/core/downloaders/{Synology => synology}/__init__.py | 0 couchpotato/core/downloaders/{Synology => synology}/main.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename couchpotato/core/downloaders/{Synology => synology}/__init__.py (100%) rename couchpotato/core/downloaders/{Synology => synology}/main.py (100%) diff --git a/couchpotato/core/downloaders/Synology/__init__.py b/couchpotato/core/downloaders/synology/__init__.py similarity index 100% rename from couchpotato/core/downloaders/Synology/__init__.py rename to couchpotato/core/downloaders/synology/__init__.py diff --git a/couchpotato/core/downloaders/Synology/main.py b/couchpotato/core/downloaders/synology/main.py similarity index 100% rename from couchpotato/core/downloaders/Synology/main.py rename to couchpotato/core/downloaders/synology/main.py From 929c6fe3f9c32cbb38c81e8954bf3415312d15f9 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 30 Nov 2012 21:42:18 +0100 Subject: [PATCH 20/23] Don't run schedules when it's 0 --- couchpotato/core/plugins/renamer/main.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index acb98ae5..8f0fa7ec 100644 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -34,8 +34,11 @@ class Renamer(Plugin): addEvent('app.load', self.scan) - fireEvent('schedule.interval', 'renamer.check_snatched', self.checkSnatched, minutes = self.conf('run_every')) - fireEvent('schedule.interval', 'renamer.check_snatched_forced', self.scan, hours = self.conf('force_every')) + if self.conf('run_every') > 0: + fireEvent('schedule.interval', 'renamer.check_snatched', self.checkSnatched, minutes = self.conf('run_every')) + + if self.conf('force_every') > 0: + fireEvent('schedule.interval', 'renamer.check_snatched_forced', self.scan, hours = self.conf('force_every')) def scanView(self): From 3aabcbf8f159143fd89a7c1c56c05f6efd8443fa Mon Sep 17 00:00:00 2001 From: iamnos Date: Thu, 22 Nov 2012 14:18:35 -0600 Subject: [PATCH 21/23] Update init/fedora The config file should be read after the defaults are set, or the options set in the config file are never used. --- init/fedora | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/init/fedora b/init/fedora index c9ebbf2e..791b676d 100644 --- a/init/fedora +++ b/init/fedora @@ -11,11 +11,6 @@ # Source function library. . /etc/init.d/functions -# Source couchpotato configuration -if [ -f /etc/sysconfig/couchpotato ]; then - . /etc/sysconfig/couchpotato -fi - prog=couchpotato lockfile=/var/lock/subsys/$prog @@ -27,6 +22,11 @@ datadir=${CP_DATA-~/.couchpotato} pidfile=${CP_PIDFILE-/var/run/couchpotato/couchpotato.pid} ## +# Source couchpotato configuration +if [ -f /etc/sysconfig/couchpotato ]; then + . /etc/sysconfig/couchpotato +fi + pidpath=`dirname ${pidfile}` options=" --daemon --pid_file=${pidfile} --data_dir=${datadir}" From 618845a0219433b521a64781a914334e1fd1d347 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 30 Nov 2012 22:37:23 +0100 Subject: [PATCH 22/23] Code formatting --- couchpotato/core/downloaders/synology/main.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/couchpotato/core/downloaders/synology/main.py b/couchpotato/core/downloaders/synology/main.py index afed59c7..02d91d56 100644 --- a/couchpotato/core/downloaders/synology/main.py +++ b/couchpotato/core/downloaders/synology/main.py @@ -3,9 +3,9 @@ from couchpotato.core.helpers.encoding import isInt from couchpotato.core.logger import CPLog import httplib import json - -import urllib2 import urllib +import urllib2 + log = CPLog(__name__) @@ -35,35 +35,35 @@ class Synology(Downloader): # Send request to Transmission srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password')) remote_torrent = srpc.add_torrent_uri(data.get('url')) - log.info("Response: %s", remote_torrent) + log.info('Response: %s', remote_torrent) return remote_torrent['success'] except Exception, err: - log.error("Exception while adding torrent: %s", err) + log.error('Exception while adding torrent: %s', err) return False class SynologyRPC(object): - """SynologyRPC lite library""" + '''SynologyRPC lite library''' def __init__(self, host = 'localhost', port = 5000, username = None, password = None): super(SynologyRPC, self).__init__() - self.DLurl = 'http://' + host + ':' + str(port) + '/webapi/DownloadStation/task.cgi' - self.Authurl = 'http://' + host + ':' + str(port) + '/webapi/auth.cgi' + self.download_url = 'http://%s:%s/webapi/DownloadStation/task.cgi' % (host, port) + self.auth_url = 'http://%s:%s/webapi/auth.cgi' % (host, port) self.username = username self.password = password - self.session_name = "DownloadStation" + self.session_name = 'DownloadStation' def _login(self): if self.username and self.password: args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, 'method': 'login', 'session': self.session_name, 'format': 'sid'} - response = self._req(self.Authurl, args) + response = self._req(self.auth_url, args) if response['success'] == True: self.sid = response['data']['sid'] - log.debug( "Sid=%s", self.sid) + log.debug('Sid=%s', self.sid) return response elif self.username or self.password: log.error('User or password missing, not using authentication.') @@ -71,7 +71,7 @@ class SynologyRPC(object): def _logout(self): args = {'api':'SYNO.API.Auth', 'version':1, 'method':'logout', 'session':self.session_name, '_sid':self.sid} - return self._req(self.Authurl, args) + return self._req(self.auth_url, args) def _req(self, url, args): req_url = url + '?' + urllib.urlencode(args) @@ -92,17 +92,17 @@ class SynologyRPC(object): return False def add_torrent_uri(self, torrent): - log.info( "Adding torrent URL %s", torrent) + log.info('Adding torrent URL %s', torrent) response = {} # login login = self._login() if len(login) > 0 and login['success'] == True: - log.info("Login success, adding torrent") + log.info('Login success, adding torrent') args = {'api':'SYNO.DownloadStation.Task', 'version':1, 'method':'create', 'uri':torrent, '_sid':self.sid} - response = self._req(self.DLurl, args) + response = self._req(self.download_url, args) self._logout() else: - log.error("Couldn't login to Synology, %s", login) + log.error('Couldn\'t login to Synology, %s', login) return response From 77d57f5a09aa2af7d4a9ee9a57ab235f58fddef7 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 30 Nov 2012 22:49:22 +0100 Subject: [PATCH 23/23] Removed stopped providers --- .../core/providers/nzb/kere/__init__.py | 32 ---- couchpotato/core/providers/nzb/kere/main.py | 106 ------------ .../core/providers/nzb/mysterbin/__init__.py | 23 --- .../core/providers/nzb/mysterbin/main.py | 102 ----------- .../core/providers/nzb/newzbin/__init__.py | 32 ---- .../core/providers/nzb/newzbin/main.py | 159 ------------------ 6 files changed, 454 deletions(-) delete mode 100644 couchpotato/core/providers/nzb/kere/__init__.py delete mode 100644 couchpotato/core/providers/nzb/kere/main.py delete mode 100644 couchpotato/core/providers/nzb/mysterbin/__init__.py delete mode 100644 couchpotato/core/providers/nzb/mysterbin/main.py delete mode 100644 couchpotato/core/providers/nzb/newzbin/__init__.py delete mode 100644 couchpotato/core/providers/nzb/newzbin/main.py diff --git a/couchpotato/core/providers/nzb/kere/__init__.py b/couchpotato/core/providers/nzb/kere/__init__.py deleted file mode 100644 index 394c1125..00000000 --- a/couchpotato/core/providers/nzb/kere/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -from .main import Kere - -def start(): - return Kere() - -config = [{ - 'name': 'kere', - 'groups': [ - { - 'tab': 'searcher', - 'subtab': 'nzb_providers', - 'name': 'kere', - 'label': 'Kere', - 'description': 'See Kere', - 'wizard': True, - 'options': [ - { - 'name': 'enabled', - 'type': 'enabler', - }, - { - 'name': 'username', - }, - { - 'name': 'api_key', - 'default': '', - 'label': 'Api Key', - }, - ], - }, - ], -}] \ No newline at end of file diff --git a/couchpotato/core/providers/nzb/kere/main.py b/couchpotato/core/providers/nzb/kere/main.py deleted file mode 100644 index 50149ab8..00000000 --- a/couchpotato/core/providers/nzb/kere/main.py +++ /dev/null @@ -1,106 +0,0 @@ -from couchpotato.core.event import fireEvent -from couchpotato.core.helpers.encoding import tryUrlencode -from couchpotato.core.helpers.rss import RSS -from couchpotato.core.logger import CPLog -from couchpotato.core.providers.nzb.base import NZBProvider -from couchpotato.environment import Env -from libs.dateutil.parser import parse -import time -import xml.etree.ElementTree as XMLTree - -log = CPLog(__name__) - - -class Kere(NZBProvider, RSS): - - urls = { - 'download': 'http://kere.ws/api?t=get&id=%s', - 'detail': 'http://kere.ws/api?t=details&id=%s', - 'search': 'http://kere.ws/api', - } - - cat_ids = [ - ([1000], [ 'cam', 'ts', 'tc', 'scr']), - ([1010], [ 'r5' ]), - ([1020], [ 'dvdrip', 'brrip' ]), - ([1030], [ 'dvdr' ]), - ([1050], [ '720p' ]), - ([1060], [ '1080p' ]), - ] - cat_backup_id = 2 - - def search(self, movie, quality): - - results = [] - - if self.isDisabled(): - return results - - cat_ids = ','.join(['%s' % x for x in self.getCatId(quality.get('identifier'))]) - - arguments = tryUrlencode({ - 't' : 'movie', - 'imdbid': movie['library']['identifier'].replace('tt',''), - 'cat': cat_ids, - 'apikey': self.conf('api_key'), - }) - url = "%s?%s" % (self.urls['search'], arguments) - - cache_key = 'kere.%s.%s' % (movie['library'].get('identifier'), cat_ids) - - data = self.getCache(cache_key, url, cache_timeout = 1800, headers = {'User-Agent': Env.getIdentifier()}) - if data: - try: - try: - data = XMLTree.fromstring(data) - nzbs = self.getElements(data, 'channel/item') - except Exception, e: - log.debug('%s, %s', (self.getName(), e)) - return results - - for nzb in nzbs: - - title = self.getTextElement(nzb, "title") - if 'error' in title.lower(): continue - - id = self.getTextElement(nzb, "link").replace('http://kere.ws/getnzb/','').split('.')[0] - size = '%f KB' % (float(str(nzb.find('enclosure').attrib).split("'length': ")[1].split(',')[0].strip("'").strip()) / 1024) - date = str(self.getTextElement(nzb, "pubDate")) - - new = { - 'id': str(id), - 'type': 'nzb', - 'provider': self.getName(), - 'name': title, - 'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))), - 'size': self.parseSize(size), - 'url': self.urls['download'] % id + self.getApiExt(), - 'download': self.download, - 'detail_url': self.urls['detail'] % id, - 'description': self.getTextElement(nzb, "description"), - 'check_nzb': True, - } - - is_correct_movie = fireEvent('searcher.correct_movie', - nzb = new, movie = movie, quality = quality, - imdb_results = True, single = True) - - if is_correct_movie: - new['score'] = fireEvent('score.calculate', new, movie, single = True) - results.append(new) - self.found(new) - - return results - except SyntaxError: - log.error('Failed to parse XML response from Kere.ws') - - return results - - def download(self, url = '', nzb_id = ''): - return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}) - - def getApiExt(self): - return '&username=%s&apikey=%s' % (self.conf('username'), self.conf('api_key')) - - def isEnabled(self): - return NZBProvider.isEnabled(self) and self.conf('username') and self.conf('api_key') \ No newline at end of file diff --git a/couchpotato/core/providers/nzb/mysterbin/__init__.py b/couchpotato/core/providers/nzb/mysterbin/__init__.py deleted file mode 100644 index a28d9a88..00000000 --- a/couchpotato/core/providers/nzb/mysterbin/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -from .main import Mysterbin - -def start(): - return Mysterbin() - -config = [{ - 'name': 'mysterbin', - 'groups': [ - { - 'tab': 'searcher', - 'subtab': 'nzb_providers', - 'name': 'Mysterbin', - 'description': 'Free provider, less accurate. See Mysterbin', - 'options': [ - { - 'name': 'enabled', - 'type': 'enabler', - 'default': True, - }, - ], - }, - ], -}] diff --git a/couchpotato/core/providers/nzb/mysterbin/main.py b/couchpotato/core/providers/nzb/mysterbin/main.py deleted file mode 100644 index edf2c70e..00000000 --- a/couchpotato/core/providers/nzb/mysterbin/main.py +++ /dev/null @@ -1,102 +0,0 @@ -from bs4 import BeautifulSoup -from couchpotato.core.event import fireEvent -from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode, \ - simplifyString -from couchpotato.core.helpers.variable import tryInt, getTitle -from couchpotato.core.logger import CPLog -from couchpotato.core.providers.nzb.base import NZBProvider -from couchpotato.environment import Env - -log = CPLog(__name__) - - -class Mysterbin(NZBProvider): - - urls = { - 'search': 'https://www.mysterbin.com/advsearch?%s', - 'download': 'https://www.mysterbin.com/nzb?c=%s', - 'nfo': 'https://www.mysterbin.com/nfo?c=%s', - } - - http_time_between_calls = 1 #seconds - - def search(self, movie, quality): - - results = [] - if self.isDisabled(): - return results - - q = '"%s" %s %s' % (simplifyString(getTitle(movie['library'])), movie['library']['year'], quality.get('identifier')) - for ignored in Env.setting('ignored_words', 'searcher').split(','): - if len(q) + len(ignored.strip()) > 126: - break - q = '%s -%s' % (q, ignored.strip()) - - params = { - 'q': q, - 'match': 'normal', - 'minSize': quality.get('size_min'), - 'maxSize': quality.get('size_max'), - 'complete': 2, - 'maxAge': Env.setting('retention', 'nzb'), - 'nopasswd': 'on', - } - - cache_key = 'mysterbin.%s.%s.%s' % (movie['library']['identifier'], quality.get('identifier'), q) - data = self.getCache(cache_key, self.urls['search'] % tryUrlencode(params)) - if data: - - try: - html = BeautifulSoup(data) - resultable = html.find('table', attrs = {'class':'t'}) - for result in resultable.find_all('tr'): - - try: - myster_id = result.find('input', attrs = {'class': 'check4nzb'})['value'] - - # Age - age = '' - for temp in result.find('td', attrs = {'class': 'cdetail'}).find_all(text = True): - if 'days' in temp: - age = tryInt(temp.split(' ')[0]) - break - - # size - size = None - for temp in result.find('div', attrs = {'class': 'cdetail'}).find_all(text = True): - if 'gb' in temp.lower() or 'mb' in temp.lower() or 'kb' in temp.lower(): - size = self.parseSize(temp) - break - - description = '' - if result.find('a', text = 'View NFO'): - description = toUnicode(self.getCache('mysterbin.%s' % myster_id, self.urls['nfo'] % myster_id, cache_timeout = 25920000)) - - new = { - 'id': myster_id, - 'name': ''.join(result.find('span', attrs = {'class': 'cname'}).find_all(text = True)), - 'type': 'nzb', - 'provider': self.getName(), - 'age': age, - 'size': size, - 'url': self.urls['download'] % myster_id, - 'description': description, - 'download': self.download, - 'check_nzb': False, - } - - new['score'] = fireEvent('score.calculate', new, movie, single = True) - is_correct_movie = fireEvent('searcher.correct_movie', - nzb = new, movie = movie, quality = quality, - imdb_results = False, single = True) - if is_correct_movie: - results.append(new) - self.found(new) - except: - pass - - return results - except AttributeError: - log.debug('No search results found.') - - return results diff --git a/couchpotato/core/providers/nzb/newzbin/__init__.py b/couchpotato/core/providers/nzb/newzbin/__init__.py deleted file mode 100644 index 11292339..00000000 --- a/couchpotato/core/providers/nzb/newzbin/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -from .main import Newzbin - -def start(): - return Newzbin() - -config = [{ - 'name': 'newzbin', - 'groups': [ - { - 'tab': 'searcher', - 'subtab': 'nzb_providers', - 'name': 'newzbin', - 'description': 'See Newzbin', - 'wizard': True, - 'options': [ - { - 'name': 'enabled', - 'type': 'enabler', - }, - { - 'name': 'username', - 'default': '', - }, - { - 'name': 'password', - 'default': '', - 'type': 'password', - }, - ], - }, - ], -}] diff --git a/couchpotato/core/providers/nzb/newzbin/main.py b/couchpotato/core/providers/nzb/newzbin/main.py deleted file mode 100644 index 7359bfdc..00000000 --- a/couchpotato/core/providers/nzb/newzbin/main.py +++ /dev/null @@ -1,159 +0,0 @@ -from couchpotato.core.event import fireEvent -from couchpotato.core.helpers.encoding import tryUrlencode -from couchpotato.core.helpers.rss import RSS -from couchpotato.core.logger import CPLog -from couchpotato.core.providers.nzb.base import NZBProvider -from dateutil.parser import parse -import base64 -import time -import xml.etree.ElementTree as XMLTree - -log = CPLog(__name__) - - -class Newzbin(NZBProvider, RSS): - - urls = { - 'download': 'https://www.newzbin2.es/api/dnzb/', - 'search': 'https://www.newzbin2.es/search/', - } - - format_ids = { - 2: ['scr'], - 1: ['cam'], - 4: ['tc'], - 8: ['ts'], - 1024: ['r5'], - } - cat_ids = [ - ([262144], ['bd50']), - ([2097152], ['1080p']), - ([524288], ['720p']), - ([262144], ['brrip']), - ([2], ['dvdr']), - ] - cat_backup_id = -1 - - http_time_between_calls = 3 # Seconds - - def search(self, movie, quality): - - results = [] - if self.isDisabled(): - return results - - format_id = self.getFormatId(type) - cat_id = self.getCatId(type) - - arguments = tryUrlencode({ - 'searchaction': 'Search', - 'u_url_posts_only': '0', - 'u_show_passworded': '0', - 'q_url': 'imdb.com/title/' + movie['library']['identifier'], - 'sort': 'ps_totalsize', - 'order': 'asc', - 'u_post_results_amt': '100', - 'feed': 'rss', - 'category': '6', - 'ps_rb_video_format': str(cat_id), - 'ps_rb_source': str(format_id), - 'u_post_larger_than': quality.get('size_min'), - 'u_post_smaller_than': quality.get('size_max'), - }) - - url = "%s?%s" % (self.urls['search'], arguments) - cache_key = str('newzbin.%s.%s.%s' % (movie['library']['identifier'], str(format_id), str(cat_id))) - - data = self.getCache(cache_key) - if not data: - - headers = { - 'Authorization': "Basic %s" % base64.encodestring('%s:%s' % (self.conf('username'), self.conf('password')))[:-1] - } - try: - data = self.urlopen(url, headers = headers) - self.setCache(cache_key, data) - except: - return results - - if data: - try: - try: - data = XMLTree.fromstring(data) - nzbs = self.getElements(data, 'channel/item') - except Exception, e: - log.debug('%s, %s', (self.getName(), e)) - return results - - for nzb in nzbs: - - title = self.getTextElement(nzb, "title") - if 'error' in title.lower(): continue - - REPORT_NS = 'http://www.newzbin2.es/DTD/2007/feeds/report/'; - - # Add attributes to name - try: - use_attr = ['Source', 'Video Fmt', 'Audio Fmt', 'Language'] - for attr in nzb.find('{%s}attributes' % REPORT_NS): - if attr.get("type") in use_attr: - title += ' ' + attr.text - except: - pass - - id = int(self.getTextElement(nzb, '{%s}id' % REPORT_NS)) - size = str(int(self.getTextElement(nzb, '{%s}size' % REPORT_NS)) / 1024 / 1024) + ' mb' - date = str(self.getTextElement(nzb, '{%s}postdate' % REPORT_NS)) - - new = { - 'id': id, - 'type': 'nzb', - 'provider': self.getName(), - 'name': title, - 'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))), - 'size': self.parseSize(size), - 'url': str(self.getTextElement(nzb, '{%s}nzb' % REPORT_NS)), - 'download': self.download, - 'detail_url': str(self.getTextElement(nzb, 'link')), - 'description': self.getTextElement(nzb, "description"), - 'check_nzb': False, - } - - is_correct_movie = fireEvent('searcher.correct_movie', - nzb = new, movie = movie, quality = quality, - imdb_results = True, single = True) - if is_correct_movie: - new['score'] = fireEvent('score.calculate', new, movie, single = True) - results.append(new) - self.found(new) - - return results - except SyntaxError: - log.error('Failed to parse XML response from newzbin') - - return results - - def download(self, url = '', nzb_id = ''): - try: - log.info('Download nzb from newzbin, report id: %s ', nzb_id) - - return self.urlopen(self.urls['download'], params = { - 'username' : self.conf('username'), - 'password' : self.conf('password'), - 'reportid' : nzb_id - }, show_error = False) - except Exception, e: - log.error('Failed downloading from newzbin, check credit: %s', e) - - return 'try_next' - - def getFormatId(self, format): - for id, quality in self.format_ids.iteritems(): - for q in quality: - if q == format: - return id - - return self.cat_backup_id - - def isEnabled(self): - return NZBProvider.isEnabled(self) and self.conf('enabled') and self.conf('username') and self.conf('password')