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 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..02d91d56 --- /dev/null +++ b/couchpotato/core/downloaders/synology/main.py @@ -0,0 +1,108 @@ +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 urllib +import urllib2 + + +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.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' + + 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.auth_url, args) + if response['success'] == True: + self.sid = response['data']['sid'] + log.debug('Sid=%s', self.sid) + return response + elif self.username or self.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, '_sid':self.sid} + return self._req(self.auth_url, args) + + def _req(self, url, args): + req_url = url + '?' + urllib.urlencode(args) + 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) + 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.download_url, args) + self._logout() + else: + log.error('Couldn\'t login to Synology, %s', login) + return response + + 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: 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 + ) + } } 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..ba8b547e 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' + 'text': json.added ? 'Movie successfully 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') 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'] 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): 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/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/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/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 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 06a09a94..00000000 --- a/couchpotato/core/providers/nzb/newzbin/main.py +++ /dev/null @@ -1,156 +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: - for attr in nzb.find('{%s}attributes' % REPORT_NS): - 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 False - - 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') 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')) diff --git a/couchpotato/core/providers/torrent/thepiratebay/main.py b/couchpotato/core/providers/torrent/thepiratebay/main.py index a4ce3631..b569fd6a 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,12 +88,20 @@ 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:]: + 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): 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) 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){ 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}"