From 14e0219e626023be3511685063cb4699eea6a883 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 7 Jan 2013 23:10:06 +0100 Subject: [PATCH 01/19] Urlencode spotweb id. fix #1213 --- couchpotato/core/providers/nzb/newznab/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/providers/nzb/newznab/main.py b/couchpotato/core/providers/nzb/newznab/main.py index f1f0d48e..b1e93bcd 100644 --- a/couchpotato/core/providers/nzb/newznab/main.py +++ b/couchpotato/core/providers/nzb/newznab/main.py @@ -73,8 +73,8 @@ class Newznab(NZBProvider, RSS): 'name': self.getTextElement(nzb, 'title'), 'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))), 'size': int(self.getElement(nzb, 'enclosure').attrib['length']) / 1024 / 1024, - 'url': (self.getUrl(host['host'], self.urls['download']) % nzb_id) + self.getApiExt(host), - 'detail_url': '%sdetails/%s' % (cleanHost(host['host']), nzb_id), + 'url': (self.getUrl(host['host'], self.urls['download']) % tryUrlencode(nzb_id)) + self.getApiExt(host), + 'detail_url': '%sdetails/%s' % (cleanHost(host['host']), tryUrlencode(nzb_id)), 'content': self.getTextElement(nzb, 'description'), }) From 87574a18109e4379f43382f351e31db1320cd68d Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 8 Jan 2013 20:28:59 +0100 Subject: [PATCH 02/19] Allow spotweb url without rewriterule. fix #1248 --- couchpotato/core/providers/nzb/newznab/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/couchpotato/core/providers/nzb/newznab/main.py b/couchpotato/core/providers/nzb/newznab/main.py index b1e93bcd..e6529733 100644 --- a/couchpotato/core/providers/nzb/newznab/main.py +++ b/couchpotato/core/providers/nzb/newznab/main.py @@ -104,6 +104,9 @@ class Newznab(NZBProvider, RSS): return result def getUrl(self, host, type): + if '?page=newznabapi' in host: + return cleanHost(host)[:-1] + '&t=' + type + return cleanHost(host) + 'api?t=' + type def isDisabled(self, host): From 8892ace3c2c833f10b2004d79adf384b2c63c0d0 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 9 Jan 2013 20:26:02 +0100 Subject: [PATCH 03/19] OMGWTF proper link in settings --- couchpotato/core/providers/nzb/omgwtfnzbs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/providers/nzb/omgwtfnzbs/__init__.py b/couchpotato/core/providers/nzb/omgwtfnzbs/__init__.py index 8e8af499..089b72c6 100644 --- a/couchpotato/core/providers/nzb/omgwtfnzbs/__init__.py +++ b/couchpotato/core/providers/nzb/omgwtfnzbs/__init__.py @@ -10,7 +10,7 @@ config = [{ 'tab': 'searcher', 'subtab': 'nzb_providers', 'name': 'OMGWTFNZBs', - 'description': 'See OMGWTFNZBs', + 'description': 'See OMGWTFNZBs', 'options': [ { 'name': 'enabled', From 3c728608e9aede50ec92c739f16716bf01a211b5 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 9 Jan 2013 20:42:33 +0100 Subject: [PATCH 04/19] FTDWorld use simple login Add size --- couchpotato/core/providers/nzb/ftdworld/main.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/providers/nzb/ftdworld/main.py b/couchpotato/core/providers/nzb/ftdworld/main.py index c5a06652..bd2a3ee2 100644 --- a/couchpotato/core/providers/nzb/ftdworld/main.py +++ b/couchpotato/core/providers/nzb/ftdworld/main.py @@ -4,6 +4,7 @@ from couchpotato.core.logger import CPLog from couchpotato.core.providers.nzb.base import NZBProvider from couchpotato.environment import Env from dateutil.parser import parse +import json import traceback log = CPLog(__name__) @@ -15,7 +16,7 @@ class FTDWorld(NZBProvider): 'search': 'http://ftdworld.net/api/index.php?%s', 'detail': 'http://ftdworld.net/spotinfo.php?id=%s', 'download': 'http://ftdworld.net/cgi-bin/nzbdown.pl?fileID=%s', - 'login': 'http://ftdworld.net/index.php', + 'login': 'http://ftdworld.net/api/login.php', } http_time_between_calls = 3 #seconds @@ -56,6 +57,7 @@ class FTDWorld(NZBProvider): 'id': nzb_id, 'name': toUnicode(item.get('Title')), 'age': self.calculateAge(tryInt(item.get('Created'))), + 'size': item.get('Size', 0), 'url': self.urls['download'] % nzb_id, 'download': self.loginDownload, 'detail_url': self.urls['detail'] % nzb_id, @@ -73,4 +75,7 @@ class FTDWorld(NZBProvider): }) def loginSuccess(self, output): - return 'password is incorrect' not in output + try: + return json.loads(output).get('goodToGo', False) + except: + return False From 432852cf5d88e28cdd687fe730ef3ea4670a8251 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 9 Jan 2013 21:20:27 +0100 Subject: [PATCH 05/19] Enable added combined list by default --- couchpotato/static/scripts/page/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/static/scripts/page/settings.js b/couchpotato/static/scripts/page/settings.js index 44ae0f6b..11f1aa44 100644 --- a/couchpotato/static/scripts/page/settings.js +++ b/couchpotato/static/scripts/page/settings.js @@ -1311,7 +1311,7 @@ Option.Combined = new Class({ if(has_empty > 0) return; self.add_empty_timeout = setTimeout(function(){ - self.createItem(false, null); + self.createItem({'use': true}); }, 10); }, From cfaffe2bcb83d8b0017093102e9cce65309c7546 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 9 Jan 2013 23:29:54 +0100 Subject: [PATCH 06/19] SSL support --- couchpotato/core/_base/_core/__init__.py | 18 ++++++++++-------- couchpotato/runner.py | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/couchpotato/core/_base/_core/__init__.py b/couchpotato/core/_base/_core/__init__.py index 8d702f18..c8c3fda6 100644 --- a/couchpotato/core/_base/_core/__init__.py +++ b/couchpotato/core/_base/_core/__init__.py @@ -23,20 +23,22 @@ config = [{ 'default': '', 'type': 'password', }, - { - 'name': 'host', - 'advanced': True, - 'default': '0.0.0.0', - 'hidden': True, - 'label': 'IP', - 'description': 'Host that I should listen to. "0.0.0.0" listens to all ips.', - }, { 'name': 'port', 'default': 5050, 'type': 'int', 'description': 'The port I should listen to.', }, + { + 'name': 'ssl_cert', + 'description': 'Path to SSL server.crt', + 'advanced': True, + }, + { + 'name': 'ssl_key', + 'description': 'Path to SSL server.key', + 'advanced': True, + }, { 'name': 'launch_browser', 'default': True, diff --git a/couchpotato/runner.py b/couchpotato/runner.py index c0b7eb86..d3a49f02 100644 --- a/couchpotato/runner.py +++ b/couchpotato/runner.py @@ -4,6 +4,7 @@ from couchpotato.api import api, NonBlockHandler from couchpotato.core.event import fireEventAsync, fireEvent from couchpotato.core.helpers.variable import getDataDir, tryInt from logging import handlers +from tornado.httpserver import HTTPServer from tornado.web import Application, FallbackHandler from tornado.wsgi import WSGIContainer from werkzeug.contrib.cache import FileSystemCache @@ -210,8 +211,9 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En # app.debug = development config = { 'use_reloader': reloader, - 'host': Env.setting('host', default = '0.0.0.0'), - 'port': tryInt(Env.setting('port', default = 5000)) + 'port': tryInt(Env.setting('port', default = 5000)), + 'ssl_cert': Env.setting('ssl_cert', default = None), + 'ssl_key': Env.setting('ssl_key', default = None), } # Static path @@ -243,12 +245,20 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En debug = config['use_reloader'] ) + if config['ssl_cert'] and config['ssl_key']: + server = HTTPServer(application, no_keep_alive = True, ssl_options = { + "certfile": config['ssl_cert'], + "keyfile": config['ssl_key'], + }) + else: + server = HTTPServer(application, no_keep_alive = True) + try_restart = True restart_tries = 5 while try_restart: try: - application.listen(config['port'], config['host'], no_keep_alive = True) + server.listen(config['port']) loop.start() except Exception, e: try: From 28ce083f485a6f85d77866d9aa2e70c61cfc471a Mon Sep 17 00:00:00 2001 From: Prinz23 Date: Tue, 8 Jan 2013 15:46:34 +0100 Subject: [PATCH 07/19] nzbget priority support --- couchpotato/core/downloaders/nzbget/__init__.py | 6 ++++++ couchpotato/core/downloaders/nzbget/main.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/downloaders/nzbget/__init__.py b/couchpotato/core/downloaders/nzbget/__init__.py index 4f5afb36..50afa0b1 100644 --- a/couchpotato/core/downloaders/nzbget/__init__.py +++ b/couchpotato/core/downloaders/nzbget/__init__.py @@ -33,6 +33,12 @@ config = [{ 'default': 'Movies', 'description': 'The category CP places the nzb in. Like movies or couchpotato', }, + { + 'name': 'priority', + 'default': '0', + 'type': 'dropdown', + 'values': [('Very Low', -100), ('Low', -50), ('Normal', 0), ('High', 50), ('Very High', 100)] + }, { 'name': 'manual', 'default': 0, diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index 0d9c52aa..a799482d 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -44,7 +44,7 @@ class NZBGet(Downloader): log.error('Protocol Error: %s', e) return False - if rpc.append(nzb_name, self.conf('category'), False, standard_b64encode(filedata.strip())): + if rpc.append(nzb_name, self.conf('category'), int(self.conf('priority')), False, standard_b64encode(filedata.strip())): log.info('NZB sent successfully to NZBGet') return True else: From 0f389f18cbd13972428a429cc8b6486480b7f4ba Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 9 Jan 2013 23:41:47 +0100 Subject: [PATCH 08/19] NZBGet: Don't use priority when set to normal. --- couchpotato/core/downloaders/nzbget/__init__.py | 3 ++- couchpotato/core/downloaders/nzbget/main.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/downloaders/nzbget/__init__.py b/couchpotato/core/downloaders/nzbget/__init__.py index 50afa0b1..4fdac265 100644 --- a/couchpotato/core/downloaders/nzbget/__init__.py +++ b/couchpotato/core/downloaders/nzbget/__init__.py @@ -37,7 +37,8 @@ config = [{ 'name': 'priority', 'default': '0', 'type': 'dropdown', - 'values': [('Very Low', -100), ('Low', -50), ('Normal', 0), ('High', 50), ('Very High', 100)] + 'values': [('Very Low', -100), ('Low', -50), ('Normal', 0), ('High', 50), ('Very High', 100)], + 'description': 'Only change this if you are using NZBget 9.0 or higher', }, { 'name': 'manual', diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index a799482d..43a6fe7f 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -1,7 +1,7 @@ from base64 import standard_b64encode from couchpotato.core.downloaders.base import Downloader +from couchpotato.core.helpers.variable import tryInt from couchpotato.core.logger import CPLog -from inspect import isfunction import socket import traceback import xmlrpclib @@ -44,7 +44,13 @@ class NZBGet(Downloader): log.error('Protocol Error: %s', e) return False - if rpc.append(nzb_name, self.conf('category'), int(self.conf('priority')), False, standard_b64encode(filedata.strip())): + priority = tryInt(self.conf('priority')) + if priority != 0: + xml_response = rpc.append(nzb_name, self.conf('category'), False, standard_b64encode(filedata.strip())) + else: + xml_response = rpc.append(nzb_name, self.conf('category'), priority, False, standard_b64encode(filedata.strip())) + + if xml_response: log.info('NZB sent successfully to NZBGet') return True else: From 17eaba3e2a17b019248e7f531b549477d92603b9 Mon Sep 17 00:00:00 2001 From: Kris Kater Date: Wed, 9 Jan 2013 22:37:38 +0100 Subject: [PATCH 09/19] Added rottentomatoes automation --- .../automation/rottentomatoes_com/__init__.py | 28 +++++++++ .../automation/rottentomatoes_com/main.py | 58 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 couchpotato/core/providers/automation/rottentomatoes_com/__init__.py create mode 100644 couchpotato/core/providers/automation/rottentomatoes_com/main.py diff --git a/couchpotato/core/providers/automation/rottentomatoes_com/__init__.py b/couchpotato/core/providers/automation/rottentomatoes_com/__init__.py new file mode 100644 index 00000000..92ff7870 --- /dev/null +++ b/couchpotato/core/providers/automation/rottentomatoes_com/__init__.py @@ -0,0 +1,28 @@ +from .main import Rottentomatoes + +def start(): + return Rottentomatoes() + +config = [{ + 'name': 'rottentomatoes', + 'groups': [ + { + 'tab': 'automation', + 'name': 'rottentomatoes_automation', + 'label': 'Rottentomatoes', + 'description': 'Imports movies from the rottentomatoes in theaters rss feed.', + 'options': [ + { + 'name': 'automation_enabled', + 'default': False, + 'type': 'enabler', + }, + { + 'name': 'tomatometer_percent', + 'default': '80', + 'label': 'Tomatometer' + } + ], + }, + ], +}] diff --git a/couchpotato/core/providers/automation/rottentomatoes_com/main.py b/couchpotato/core/providers/automation/rottentomatoes_com/main.py new file mode 100644 index 00000000..302056d5 --- /dev/null +++ b/couchpotato/core/providers/automation/rottentomatoes_com/main.py @@ -0,0 +1,58 @@ +from couchpotato.core.helpers.rss import RSS +from couchpotato.core.helpers.variable import md5 +from couchpotato.core.logger import CPLog +from couchpotato.core.providers.automation.base import Automation +from xml.etree.ElementTree import QName +import datetime +import xml.etree.ElementTree as XMLTree +import re + +log = CPLog(__name__) + +class Rottentomatoes(Automation, RSS): + + interval = 1800 + rss_url = 'http://www.rottentomatoes.com/syndication/rss/in_theaters.xml' + + def getIMDBids(self): + + if self.isDisabled(): + return + + movies = [] + + cache_key = 'rottentomatoes.%s' % md5(self.rss_url) + rss_data = self.getCache(cache_key, self.rss_url) + data = XMLTree.fromstring(rss_data) + + if data: + + namespace = 'http://www.rottentomatoes.com/xmlns/rtmovie/' + rating_tag = str(QName(namespace, 'tomatometer_percent')) + rss_movies = self.getElements(data, 'channel/item') + + for movie in rss_movies: + + value = self.getTextElement(movie, "title") + result = re.search('(?<=%\s).*', value) + + if result: + + log.info('Something smells...') + rating = int(self.getTextElement(movie, rating_tag)) + name = result.group(0) + + if rating < int(self.conf('tomatometer_percent')): + + log.info('%s seems to be rotten...' % name) + + else: + + log.info('You find %s fresh enough though, enqueuing: %s' % (rating, name)) + year = datetime.datetime.now().strftime("%Y") + imdb = self.search(name, year) + + if imdb: + movies.append(imdb['imdb']) + + return movies From df53d0c57817f787b1ef3323e2e6ddb1a52f7006 Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 10 Jan 2013 07:29:48 +0100 Subject: [PATCH 10/19] Rename RT folder --- .../automation/{rottentomatoes_com => rottentomatoes}/__init__.py | 0 .../automation/{rottentomatoes_com => rottentomatoes}/main.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename couchpotato/core/providers/automation/{rottentomatoes_com => rottentomatoes}/__init__.py (100%) rename couchpotato/core/providers/automation/{rottentomatoes_com => rottentomatoes}/main.py (100%) diff --git a/couchpotato/core/providers/automation/rottentomatoes_com/__init__.py b/couchpotato/core/providers/automation/rottentomatoes/__init__.py similarity index 100% rename from couchpotato/core/providers/automation/rottentomatoes_com/__init__.py rename to couchpotato/core/providers/automation/rottentomatoes/__init__.py diff --git a/couchpotato/core/providers/automation/rottentomatoes_com/main.py b/couchpotato/core/providers/automation/rottentomatoes/main.py similarity index 100% rename from couchpotato/core/providers/automation/rottentomatoes_com/main.py rename to couchpotato/core/providers/automation/rottentomatoes/main.py From 94478336530963cd43742538ec567d093f53d382 Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 10 Jan 2013 07:42:15 +0100 Subject: [PATCH 11/19] RT cleanup --- .../automation/rottentomatoes/__init__.py | 2 +- .../automation/rottentomatoes/main.py | 54 ++++++++----------- 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/couchpotato/core/providers/automation/rottentomatoes/__init__.py b/couchpotato/core/providers/automation/rottentomatoes/__init__.py index 92ff7870..f3c12919 100644 --- a/couchpotato/core/providers/automation/rottentomatoes/__init__.py +++ b/couchpotato/core/providers/automation/rottentomatoes/__init__.py @@ -10,7 +10,7 @@ config = [{ 'tab': 'automation', 'name': 'rottentomatoes_automation', 'label': 'Rottentomatoes', - 'description': 'Imports movies from the rottentomatoes in theaters rss feed.', + 'description': 'Imports movies from the rottentomatoes "in theaters"-feed.', 'options': [ { 'name': 'automation_enabled', diff --git a/couchpotato/core/providers/automation/rottentomatoes/main.py b/couchpotato/core/providers/automation/rottentomatoes/main.py index 302056d5..053b79e8 100644 --- a/couchpotato/core/providers/automation/rottentomatoes/main.py +++ b/couchpotato/core/providers/automation/rottentomatoes/main.py @@ -1,10 +1,9 @@ from couchpotato.core.helpers.rss import RSS -from couchpotato.core.helpers.variable import md5 +from couchpotato.core.helpers.variable import tryInt from couchpotato.core.logger import CPLog from couchpotato.core.providers.automation.base import Automation from xml.etree.ElementTree import QName import datetime -import xml.etree.ElementTree as XMLTree import re log = CPLog(__name__) @@ -12,47 +11,38 @@ log = CPLog(__name__) class Rottentomatoes(Automation, RSS): interval = 1800 - rss_url = 'http://www.rottentomatoes.com/syndication/rss/in_theaters.xml' + urls = { + 'namespace': 'http://www.rottentomatoes.com/xmlns/rtmovie/', + 'theater': 'http://www.rottentomatoes.com/syndication/rss/in_theaters.xml', + } def getIMDBids(self): - if self.isDisabled(): - return - movies = [] - cache_key = 'rottentomatoes.%s' % md5(self.rss_url) - rss_data = self.getCache(cache_key, self.rss_url) - data = XMLTree.fromstring(rss_data) + rss_movies = self.getRSSData(self.urls['theater']) + rating_tag = str(QName(self.urls['namespace'], 'tomatometer_percent')) - if data: + for movie in rss_movies: - namespace = 'http://www.rottentomatoes.com/xmlns/rtmovie/' - rating_tag = str(QName(namespace, 'tomatometer_percent')) - rss_movies = self.getElements(data, 'channel/item') + value = self.getTextElement(movie, "title") + result = re.search('(?<=%\s).*', value) - for movie in rss_movies: + if result: - value = self.getTextElement(movie, "title") - result = re.search('(?<=%\s).*', value) + log.info2('Something smells...') + rating = tryInt(self.getTextElement(movie, rating_tag)) + name = result.group(0) - if result: + if rating < tryInt(self.conf('tomatometer_percent')): + log.info2('%s seems to be rotten...' % name) + else: - log.info('Something smells...') - rating = int(self.getTextElement(movie, rating_tag)) - name = result.group(0) + log.info2('Found %s fresh enough movies, enqueuing: %s' % (rating, name)) + year = datetime.datetime.now().strftime("%Y") + imdb = self.search(name, year) - if rating < int(self.conf('tomatometer_percent')): - - log.info('%s seems to be rotten...' % name) - - else: - - log.info('You find %s fresh enough though, enqueuing: %s' % (rating, name)) - year = datetime.datetime.now().strftime("%Y") - imdb = self.search(name, year) - - if imdb: - movies.append(imdb['imdb']) + if imdb: + movies.append(imdb['imdb']) return movies From 300f4738a0303cc5346a1517179d28bbdde046f7 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 11 Jan 2013 20:12:12 +0100 Subject: [PATCH 12/19] Randomize wanted search. fix #1261 --- couchpotato/core/plugins/searcher/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index 805affcf..e18e0a5b 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -12,6 +12,7 @@ from couchpotato.environment import Env from inspect import ismethod, isfunction from sqlalchemy.exc import InterfaceError import datetime +import random import re import time import traceback @@ -83,6 +84,7 @@ class Searcher(Plugin): movies = db.query(Movie).filter( Movie.status.has(identifier = 'active') ).all() + random.shuffle(movies) self.in_progress = { 'total': len(movies), From 36e5c49147790d1f7eb74b9373bd2d46726a005f Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 11 Jan 2013 20:50:38 +0100 Subject: [PATCH 13/19] TorrentDay: decoding error. fix #1260 --- couchpotato/core/downloaders/utorrent/main.py | 4 ++-- couchpotato/core/providers/torrent/torrentday/main.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/downloaders/utorrent/main.py b/couchpotato/core/downloaders/utorrent/main.py index 983afbf9..7e703d0c 100644 --- a/couchpotato/core/downloaders/utorrent/main.py +++ b/couchpotato/core/downloaders/utorrent/main.py @@ -1,6 +1,6 @@ from bencode import bencode, bdecode from couchpotato.core.downloaders.base import Downloader -from couchpotato.core.helpers.encoding import isInt +from couchpotato.core.helpers.encoding import isInt, ss from couchpotato.core.logger import CPLog from hashlib import sha1 from multipartpost import MultipartPostHandler @@ -125,7 +125,7 @@ class uTorrentAPI(object): def add_torrent_file(self, filename, filedata): action = "action=add-file" - return self._request(action, {"torrent_file": (filename, filedata)}) + return self._request(action, {"torrent_file": (ss(filename), filedata)}) def set_torrent(self, hash, params): action = "action=setprops&hash=%s" % hash diff --git a/couchpotato/core/providers/torrent/torrentday/main.py b/couchpotato/core/providers/torrent/torrentday/main.py index 8b29f320..5e207c1e 100644 --- a/couchpotato/core/providers/torrent/torrentday/main.py +++ b/couchpotato/core/providers/torrent/torrentday/main.py @@ -59,3 +59,6 @@ class TorrentDay(TorrentProvider): 'password': self.conf('password'), 'submit': 'submit', }) + + def loginSuccess(self, output): + return 'Password not correct' not in output From cdd681ad4899253378723c0f211e82d831af1c9f Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 11 Jan 2013 21:02:22 +0100 Subject: [PATCH 14/19] XBMC icon image --- couchpotato/core/notifications/xbmc/main.py | 9 +++++---- couchpotato/static/images/xbmc-notify.png | Bin 0 -> 1257 bytes 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 couchpotato/static/images/xbmc-notify.png diff --git a/couchpotato/core/notifications/xbmc/main.py b/couchpotato/core/notifications/xbmc/main.py index eef94695..a1987bfa 100755 --- a/couchpotato/core/notifications/xbmc/main.py +++ b/couchpotato/core/notifications/xbmc/main.py @@ -13,6 +13,7 @@ class XBMC(Notification): listen_to = ['renamer.after'] use_json_notifications = {} + couch_logo_url = 'https://raw.github.com/RuudBurger/CouchPotatoServer/master/couchpotato/static/images/xbmc-notify.png' def notify(self, message = '', data = {}, listener = None): if self.isDisabled(): return @@ -27,7 +28,7 @@ class XBMC(Notification): if self.use_json_notifications.get(host): response = self.request(host, [ - ('GUI.ShowNotification', {'title':self.default_title, 'message':message}), + ('GUI.ShowNotification', {'title': self.default_title, 'message': message, 'image': self.couch_logo_url}), ('VideoLibrary.Scan', {}), ]) else: @@ -89,7 +90,7 @@ class XBMC(Notification): self.use_json_notifications[host] = True # send the text message - resp = self.request(host, [('GUI.ShowNotification', {'title':self.default_title, 'message':message})]) + resp = self.request(host, [('GUI.ShowNotification', {'title':self.default_title, 'message':message, 'image':self.couch_logo_url})]) for result in resp: if (result.get('result') and result['result'] == 'OK'): log.debug('Message delivered successfully!') @@ -111,8 +112,8 @@ class XBMC(Notification): server = 'http://%s/xbmcCmds/' % host - # title, message [, timeout , image #can be added!] - cmd = "xbmcHttp?command=ExecBuiltIn(Notification('%s','%s'))" % (urllib.quote(data['title']), urllib.quote(data['message'])) + # Notification(title, message [, timeout , image]) + cmd = "xbmcHttp?command=ExecBuiltIn(Notification(%s,%s,'',%s))" % (urllib.quote(data['title']), urllib.quote(data['message']), urllib.quote(self.couch_logo_url)) server += cmd # I have no idea what to set to, just tried text/plain and seems to be working :) diff --git a/couchpotato/static/images/xbmc-notify.png b/couchpotato/static/images/xbmc-notify.png new file mode 100644 index 0000000000000000000000000000000000000000..6b7959f43fc2e7287a260e12282eec6910e04142 GIT binary patch literal 1257 zcmV=P)5000EANklS7SYc-@|LQ;gCmwp53^O5p>nCGp%n51m_P$>Ze!utB zV}F?a+2EtShmTx3(s|@EoJIf>#=oli)mgvlKMI$_KYN#Z&$N&4k;t@<=iu)S_S}@s zF#$}N-1>n%2mTAdCG<#SSZKs;u6o?M9H1jy-w~(67mLRh?*QnuBHw_VEu1mSU!dU= zHo5r|OrH@D^lWCn?2miYs;z4U!+0IwZ)`^!Gc!qAICSVWXYQqr z%SK;}M*dn=h1o*R-?nPyc{ljWsp^#*d&G2!qCpPk*ZBKV#wX|gIMW?`=u|!)A%F)$ zgxbNH4@_d@o}?!`oqRAoos}`n1ZRJK<@3+qYlZB6$c{^4@z4`*WdB)uC;ADyfx9@a z0{elxbFi`;x$n&^P>y3yEX5eABuVcl|db8PlXZ~N>soN z6T2hyfnCll07GXZ61ixootc1~CNKhrWlYP+9CTLTx%r%z|-zpOn_peZ> Date: Fri, 11 Jan 2013 21:45:25 +0100 Subject: [PATCH 15/19] NZBget version check --- couchpotato/core/downloaders/nzbget/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index 43a6fe7f..75a48130 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -2,6 +2,7 @@ from base64 import standard_b64encode from couchpotato.core.downloaders.base import Downloader from couchpotato.core.helpers.variable import tryInt from couchpotato.core.logger import CPLog +import re import socket import traceback import xmlrpclib @@ -44,11 +45,10 @@ class NZBGet(Downloader): log.error('Protocol Error: %s', e) return False - priority = tryInt(self.conf('priority')) - if priority != 0: + if re.search(r"^0", rpc.version()): xml_response = rpc.append(nzb_name, self.conf('category'), False, standard_b64encode(filedata.strip())) else: - xml_response = rpc.append(nzb_name, self.conf('category'), priority, False, standard_b64encode(filedata.strip())) + xml_response = rpc.append(nzb_name, self.conf('category'), tryInt(self.conf('priority')), False, standard_b64encode(filedata.strip())) if xml_response: log.info('NZB sent successfully to NZBGet') From a264c75f8c13eb7aebb921b6f22b123534ff731c Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 11 Jan 2013 22:31:19 +0100 Subject: [PATCH 16/19] Remove releases that aren't found in latest search --- couchpotato/core/plugins/searcher/main.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index e18e0a5b..d5e1f672 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -130,6 +130,8 @@ class Searcher(Plugin): available_status = fireEvent('status.get', 'available', single = True) ignored_status = fireEvent('status.get', 'ignored', single = True) + found_releases = [] + default_title = getTitle(movie['library']) if not default_title: log.error('No proper info found for movie, removing it from library to cause it from having more issues.') @@ -174,10 +176,13 @@ class Searcher(Plugin): # Add them to this movie releases list for nzb in sorted_results: - rls = db.query(Release).filter_by(identifier = md5(nzb['url'])).first() + nzb_identifier = md5(nzb['url']) + found_releases.append(nzb_identifier) + + rls = db.query(Release).filter_by(identifier = nzb_identifier).first() if not rls: rls = Release( - identifier = md5(nzb['url']), + identifier = nzb_identifier, movie_id = movie.get('id'), quality_id = quality_type.get('quality_id'), status_id = available_status.get('id') @@ -234,6 +239,11 @@ class Searcher(Plugin): if self.shuttingDown() or ret: break + # Remove releases that aren't found anymore + for release in movie.get('releases', []): + if release.get('identifier') not in found_releases: + fireEvent('release.delete', release.get('id'), single = True) + fireEvent('notify.frontend', type = 'searcher.ended.%s' % movie['id'], data = True) return ret From a0dc5c075a34b787fc9e938db7d78d6c3f9cd6cb Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 12 Jan 2013 16:05:54 +0100 Subject: [PATCH 17/19] Remove print --- couchpotato/core/plugins/manage/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/couchpotato/core/plugins/manage/main.py b/couchpotato/core/plugins/manage/main.py index 40336e5f..ead5b6ea 100644 --- a/couchpotato/core/plugins/manage/main.py +++ b/couchpotato/core/plugins/manage/main.py @@ -135,7 +135,6 @@ class Manage(Plugin): already_used = used_files.get(release_file['path']) if already_used: - print already_used, release['id'] if already_used < release['id']: fireEvent('release.delete', release['id'], single = True) # delete this one else: From 71b22345bc55aef14aad4784de7dfb6f18670048 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 12 Jan 2013 16:07:11 +0100 Subject: [PATCH 18/19] Make sure downloaders and providers match Remove releases not found anymore on new searches --- couchpotato/core/downloaders/base.py | 46 ++++- .../core/downloaders/blackhole/main.py | 19 +- couchpotato/core/downloaders/nzbget/main.py | 5 +- .../core/downloaders/nzbvortex/main.py | 14 +- .../core/downloaders/pneumatic/main.py | 4 +- couchpotato/core/downloaders/sabnzbd/main.py | 10 +- couchpotato/core/downloaders/synology/main.py | 5 +- .../core/downloaders/transmission/main.py | 5 +- couchpotato/core/downloaders/utorrent/main.py | 5 +- couchpotato/core/event.py | 3 +- couchpotato/core/plugins/searcher/main.py | 188 +++++++++++------- couchpotato/core/providers/base.py | 8 + .../core/providers/nzb/newznab/main.py | 12 +- 13 files changed, 200 insertions(+), 124 deletions(-) diff --git a/couchpotato/core/downloaders/base.py b/couchpotato/core/downloaders/base.py index 7a695e21..377e6062 100644 --- a/couchpotato/core/downloaders/base.py +++ b/couchpotato/core/downloaders/base.py @@ -33,17 +33,36 @@ class Downloader(Provider): ] def __init__(self): - addEvent('download', self.download) - addEvent('download.status', self.getAllDownloadStatus) - addEvent('download.remove_failed', self.removeFailed) + addEvent('download', self._download) + addEvent('download.enabled', self._isEnabled) + addEvent('download.enabled_types', self.getEnabledDownloadType) + addEvent('download.status', self._getAllDownloadStatus) + addEvent('download.remove_failed', self._removeFailed) - def download(self, data = {}, movie = {}, manual = False, filedata = None): - pass + def getEnabledDownloadType(self): + for download_type in self.type: + if self.isEnabled(manual = True, data = {'type': download_type}): + return self.type - def getAllDownloadStatus(self): + return [] + + def _download(self, data = {}, movie = {}, manual = False, filedata = None): + if self.isDisabled(manual, data): + return + return self.download(data = data, movie = movie, filedata = filedata) + + def _getAllDownloadStatus(self): + if self.isDisabled(manual = True, data = {}): + return + + return self.getAllDownloadStatus() + + def _removeFailed(self, item): + if self.conf('delete_failed', default = True): + return self.removeFailed(self, item) return False - def removeFailed(self, name = {}, nzo_id = {}): + def removeFailed(self, item): return False def isCorrectType(self, item_type): @@ -77,9 +96,14 @@ class Downloader(Provider): log.error('Failed converting magnet url to torrent: %s', (torrent_hash)) return False - def isDisabled(self, manual): - return not self.isEnabled(manual) + def isDisabled(self, manual, data): + return not self.isEnabled(manual, data) - def isEnabled(self, manual): + def _isEnabled(self, manual, data = {}): + if not self.isEnabled(manual, data): + return + return True + + def isEnabled(self, manual, data = {}): d_manual = self.conf('manual', default = False) - return super(Downloader, self).isEnabled() and ((d_manual and manual) or (d_manual is False)) + return super(Downloader, self).isEnabled() and ((d_manual and manual) or (d_manual is False)) and self.isCorrectType(data.get('type')) diff --git a/couchpotato/core/downloaders/blackhole/main.py b/couchpotato/core/downloaders/blackhole/main.py index ca38fc49..402e607a 100644 --- a/couchpotato/core/downloaders/blackhole/main.py +++ b/couchpotato/core/downloaders/blackhole/main.py @@ -10,11 +10,7 @@ class Blackhole(Downloader): type = ['nzb', 'torrent', 'torrent_magnet'] - def download(self, data = {}, movie = {}, manual = False, filedata = None): - if self.isDisabled(manual) or \ - (not self.isCorrectType(data.get('type')) or \ - (not self.conf('use_for') in ['both', 'torrent' if 'torrent' in data.get('type') else data.get('type')])): - return + def download(self, data = {}, movie = {}, filedata = None): directory = self.conf('directory') if not directory or not os.path.isdir(directory): @@ -52,4 +48,17 @@ class Blackhole(Downloader): except: log.info('Failed to download file %s: %s', (data.get('name'), traceback.format_exc())) return False + return False + + def getEnabledDownloadType(self): + if self.conf('use_for') == 'both': + return super(Blackhole, self).getEnabledDownloadType() + elif self.conf('use_for') == 'torrent': + return ['torrent', 'torrent_magnet'] + else: + return ['nzb'] + + def isEnabled(self, manual, data = {}): + return super(Blackhole, self).isEnabled(manual, data) and \ + ((self.conf('use_for') in ['both', 'torrent' if 'torrent' in data.get('type') else data.get('type')])) diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index 75a48130..c3b9703e 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -15,10 +15,7 @@ class NZBGet(Downloader): url = 'http://nzbget:%(password)s@%(host)s/xmlrpc' - def download(self, data = {}, movie = {}, manual = False, filedata = None): - - if self.isDisabled(manual) or not self.isCorrectType(data.get('type')): - return + def download(self, data = {}, movie = {}, filedata = None): if not filedata: log.error('Unable to get NZB file: %s', traceback.format_exc()) diff --git a/couchpotato/core/downloaders/nzbvortex/main.py b/couchpotato/core/downloaders/nzbvortex/main.py index 32b1e6e8..1462c678 100644 --- a/couchpotato/core/downloaders/nzbvortex/main.py +++ b/couchpotato/core/downloaders/nzbvortex/main.py @@ -22,10 +22,7 @@ class NZBVortex(Downloader): api_level = None session_id = None - def download(self, data = {}, movie = {}, manual = False, filedata = None): - - if self.isDisabled(manual) or not self.isCorrectType(data.get('type')) or not self.getApiLevel(): - return + def download(self, data = {}, movie = {}, filedata = None): # Send the nzb try: @@ -39,9 +36,6 @@ class NZBVortex(Downloader): def getAllDownloadStatus(self): - if self.isDisabled(manual = True): - return False - raw_statuses = self.call('nzb') statuses = [] @@ -66,9 +60,6 @@ class NZBVortex(Downloader): def removeFailed(self, item): - if not self.conf('delete_failed', default = True): - return False - log.info('%s failed downloading, deleting...', item['name']) try: @@ -153,6 +144,9 @@ class NZBVortex(Downloader): return self.api_level + def isEnabled(self, manual, data): + return super(NZBVortex, self).isEnabled(manual, data) and self.getApiLevel() + class HTTPSConnection(httplib.HTTPSConnection): def __init__(self, *args, **kwargs): diff --git a/couchpotato/core/downloaders/pneumatic/main.py b/couchpotato/core/downloaders/pneumatic/main.py index 57e47e60..5e2b7854 100644 --- a/couchpotato/core/downloaders/pneumatic/main.py +++ b/couchpotato/core/downloaders/pneumatic/main.py @@ -11,9 +11,7 @@ class Pneumatic(Downloader): type = ['nzb'] strm_syntax = 'plugin://plugin.program.pneumatic/?mode=strm&type=add_file&nzb=%s&nzbname=%s' - def download(self, data = {}, movie = {}, manual = False, filedata = None): - if self.isDisabled(manual) or (not self.isCorrectType(data.get('type'))): - return + def download(self, data = {}, movie = {}, filedata = None): directory = self.conf('directory') if not directory or not os.path.isdir(directory): diff --git a/couchpotato/core/downloaders/sabnzbd/main.py b/couchpotato/core/downloaders/sabnzbd/main.py index e3848e40..91302780 100644 --- a/couchpotato/core/downloaders/sabnzbd/main.py +++ b/couchpotato/core/downloaders/sabnzbd/main.py @@ -12,10 +12,7 @@ class Sabnzbd(Downloader): type = ['nzb'] - def download(self, data = {}, movie = {}, manual = False, filedata = None): - - if self.isDisabled(manual) or not self.isCorrectType(data.get('type')): - return + def download(self, data = {}, movie = {}, filedata = None): log.info('Sending "%s" to SABnzbd.', data.get('name')) @@ -65,8 +62,6 @@ class Sabnzbd(Downloader): return False def getAllDownloadStatus(self): - if self.isDisabled(manual = True): - return False log.debug('Checking SABnzbd download status.') @@ -122,9 +117,6 @@ class Sabnzbd(Downloader): def removeFailed(self, item): - if not self.conf('delete_failed', default = True): - return False - log.info('%s failed downloading, deleting...', item['name']) try: diff --git a/couchpotato/core/downloaders/synology/main.py b/couchpotato/core/downloaders/synology/main.py index 02d91d56..6e405980 100644 --- a/couchpotato/core/downloaders/synology/main.py +++ b/couchpotato/core/downloaders/synology/main.py @@ -14,10 +14,7 @@ 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 + def download(self, data, movie, filedata = None): log.error('Sending "%s" (%s) to Synology.', (data.get('name'), data.get('type'))) diff --git a/couchpotato/core/downloaders/transmission/main.py b/couchpotato/core/downloaders/transmission/main.py index 22e01c2f..63c9de9d 100644 --- a/couchpotato/core/downloaders/transmission/main.py +++ b/couchpotato/core/downloaders/transmission/main.py @@ -16,10 +16,7 @@ class Transmission(Downloader): type = ['torrent', '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 + def download(self, data, movie, filedata = None): log.debug('Sending "%s" (%s) to Transmission.', (data.get('name'), data.get('type'))) diff --git a/couchpotato/core/downloaders/utorrent/main.py b/couchpotato/core/downloaders/utorrent/main.py index 7e703d0c..e1e67de1 100644 --- a/couchpotato/core/downloaders/utorrent/main.py +++ b/couchpotato/core/downloaders/utorrent/main.py @@ -20,10 +20,7 @@ class uTorrent(Downloader): type = ['torrent', 'torrent_magnet'] utorrent_api = None - def download(self, data, movie, manual = False, filedata = None): - - if self.isDisabled(manual) or not self.isCorrectType(data.get('type')): - return + def download(self, data, movie, filedata = None): log.debug('Sending "%s" (%s) to uTorrent.', (data.get('name'), data.get('type'))) diff --git a/couchpotato/core/event.py b/couchpotato/core/event.py index 8365ae57..aa05ce0f 100644 --- a/couchpotato/core/event.py +++ b/couchpotato/core/event.py @@ -115,7 +115,8 @@ def fireEvent(name, *args, **kwargs): elif isinstance(results[0], list): merged = [] for result in results: - merged += result + if result not in merged: + merged += result results = merged diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index d5e1f672..eb953cd1 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -91,31 +91,44 @@ class Searcher(Plugin): 'to_go': len(movies), } - for movie in movies: - movie_dict = movie.to_dict({ - 'profile': {'types': {'quality': {}}}, - 'releases': {'status': {}, 'quality': {}}, - 'library': {'titles': {}, 'files':{}}, - 'files': {} - }) + try: + search_types = self.getSearchTypes() - try: - self.single(movie_dict) - except IndexError: - log.error('Forcing library update for %s, if you see this often, please report: %s', (movie_dict['library']['identifier'], traceback.format_exc())) - fireEvent('library.update', movie_dict['library']['identifier'], force = True) - except: - log.error('Search failed for %s: %s', (movie_dict['library']['identifier'], traceback.format_exc())) + for movie in movies: + movie_dict = movie.to_dict({ + 'profile': {'types': {'quality': {}}}, + 'releases': {'status': {}, 'quality': {}}, + 'library': {'titles': {}, 'files':{}}, + 'files': {} + }) - self.in_progress['to_go'] -= 1 + try: + self.single(movie_dict, search_types) + except IndexError: + log.error('Forcing library update for %s, if you see this often, please report: %s', (movie_dict['library']['identifier'], traceback.format_exc())) + fireEvent('library.update', movie_dict['library']['identifier'], force = True) + except: + log.error('Search failed for %s: %s', (movie_dict['library']['identifier'], traceback.format_exc())) - # Break if CP wants to shut down - if self.shuttingDown(): - break + self.in_progress['to_go'] -= 1 + + # Break if CP wants to shut down + if self.shuttingDown(): + break + + except SearchSetupError: + pass self.in_progress = False - def single(self, movie): + def single(self, movie, search_types = None): + + # Find out search type + try: + if not search_types: + search_types = self.getSearchTypes() + except SearchSetupError: + return done_status = fireEvent('status.get', 'done', single = True) @@ -140,6 +153,7 @@ class Searcher(Plugin): fireEvent('notify.frontend', type = 'searcher.started.%s' % movie['id'], data = True, message = 'Searching for "%s"' % default_title) + ret = False for quality_type in movie['profile']['types']: if not self.couldBeReleased(quality_type['quality']['identifier'], release_dates, pre_releases): @@ -159,7 +173,11 @@ class Searcher(Plugin): log.info('Search for %s in %s', (default_title, quality_type['quality']['label'])) quality = fireEvent('quality.single', identifier = quality_type['quality']['identifier'], single = True) - results = fireEvent('yarr.search', movie, quality, merge = True) + results = [] + for search_type in search_types: + type_results = fireEvent('%s.search' % search_type, movie, quality, merge = True) + if type_results: + results += type_results sorted_results = sorted(results, key = lambda k: k['score'], reverse = True) if len(sorted_results) == 0: @@ -230,6 +248,12 @@ class Searcher(Plugin): break elif downloaded != 'try_next': break + + # Remove releases that aren't found anymore + for release in movie.get('releases', []): + if release.get('identifier') not in found_releases: + fireEvent('release.delete', release.get('id'), single = True) + else: log.info('Better quality (%s) already available or snatched for %s', (quality_type['quality']['label'], default_title)) fireEvent('movie.restatus', movie['id']) @@ -239,72 +263,93 @@ class Searcher(Plugin): if self.shuttingDown() or ret: break - # Remove releases that aren't found anymore - for release in movie.get('releases', []): - if release.get('identifier') not in found_releases: - fireEvent('release.delete', release.get('id'), single = True) - fireEvent('notify.frontend', type = 'searcher.ended.%s' % movie['id'], data = True) return ret def download(self, data, movie, manual = False): - snatched_status = fireEvent('status.get', 'snatched', single = True) + # Test to see if any downloaders are enabled for this type + downloader_enabled = fireEvent('download.enabled', manual, data, single = True) - # Download movie to temp - 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 == 'try_next': - return filedata + if downloader_enabled: - successful = fireEvent('download', data = data, movie = movie, manual = manual, filedata = filedata, single = True) + snatched_status = fireEvent('status.get', 'snatched', single = True) - if successful: + # Download movie to temp + 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 == 'try_next': + return filedata - try: - # Mark release as snatched - db = get_session() - rls = db.query(Release).filter_by(identifier = md5(data['url'])).first() - if rls: - rls.status_id = snatched_status.get('id') - db.commit() + successful = fireEvent('download', data = data, movie = movie, manual = manual, filedata = filedata, single = True) - log_movie = '%s (%s) in %s' % (getTitle(movie['library']), movie['library']['year'], rls.quality.label) - snatch_message = 'Snatched "%s": %s' % (data.get('name'), log_movie) - log.info(snatch_message) - fireEvent('movie.snatched', message = snatch_message, data = rls.to_dict()) + if successful: - # If renamer isn't used, mark movie done - if not Env.setting('enabled', 'renamer'): - 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 rls and profile_type['quality_id'] == rls.quality.id and profile_type['finish']: - log.info('Renamer disabled, marking movie as finished: %s', log_movie) + try: + # Mark release as snatched + db = get_session() + rls = db.query(Release).filter_by(identifier = md5(data['url'])).first() + if rls: + rls.status_id = snatched_status.get('id') + db.commit() - # Mark release done - rls.status_id = done_status.get('id') - db.commit() + log_movie = '%s (%s) in %s' % (getTitle(movie['library']), movie['library']['year'], rls.quality.label) + snatch_message = 'Snatched "%s": %s' % (data.get('name'), log_movie) + log.info(snatch_message) + fireEvent('movie.snatched', message = snatch_message, data = rls.to_dict()) - # Mark movie done - mvie = db.query(Movie).filter_by(id = movie['id']).first() - mvie.status_id = done_status.get('id') - db.commit() - except: - log.error('Failed marking movie finished, renamer disabled: %s', traceback.format_exc()) + # If renamer isn't used, mark movie done + if not Env.setting('enabled', 'renamer'): + 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 rls and profile_type['quality_id'] == rls.quality.id and profile_type['finish']: + log.info('Renamer disabled, marking movie as finished: %s', log_movie) - except: - log.error('Failed marking movie finished: %s', traceback.format_exc()) + # Mark release done + rls.status_id = done_status.get('id') + db.commit() - return True + # Mark movie done + mvie = db.query(Movie).filter_by(id = movie['id']).first() + mvie.status_id = done_status.get('id') + db.commit() + except: + log.error('Failed marking movie finished, renamer disabled: %s', traceback.format_exc()) + + except: + log.error('Failed marking movie finished: %s', traceback.format_exc()) + + return True + + log.info('Tried to download, but none of the "%s" downloaders are enabled', (data.get('type', ''))) - log.info('Tried to download, but none of the downloaders are enabled') return False + def getSearchTypes(self): + + download_types = fireEvent('download.enabled_types', merge = True) + provider_types = fireEvent('provider.enabled_types', merge = True) + + if download_types and len(list(set(provider_types) & set(download_types))) == 0: + log.error('There aren\'t any providers enabled for your downloader (%s). Check your settings.', ','.join(download_types)) + raise NoProviders + + for useless_provider in list(set(provider_types) - set(download_types)): + log.debug('Provider for "%s" enabled, but no downloader.', useless_provider) + + search_types = download_types + + if len(search_types) == 0: + log.error('There aren\'t any downloaders enabled. Please pick one in settings.') + raise NoDownloaders + + return search_types + def correctMovie(self, nzb = {}, movie = {}, quality = {}, **kwargs): imdb_results = kwargs.get('imdb_results', False) @@ -548,3 +593,12 @@ class Searcher(Plugin): except: log.error('Failed searching for next release: %s', traceback.format_exc()) return False + +class SearchSetupError(Exception): + pass + +class NoDownloaders(SearchSetupError): + pass + +class NoProviders(SearchSetupError): + pass diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py index 9c143d81..a07282af 100644 --- a/couchpotato/core/providers/base.py +++ b/couchpotato/core/providers/base.py @@ -84,8 +84,16 @@ class YarrProvider(Provider): login_opener = None def __init__(self): + addEvent('provider.enabled_types', self.getEnabledProviderType) addEvent('provider.belongs_to', self.belongsTo) addEvent('yarr.search', self.search) + addEvent('%s.search' % self.type, self.search) + + def getEnabledProviderType(self): + if self.isEnabled(): + return self.type + else: + return [] def login(self): diff --git a/couchpotato/core/providers/nzb/newznab/main.py b/couchpotato/core/providers/nzb/newznab/main.py index e6529733..f80e07cc 100644 --- a/couchpotato/core/providers/nzb/newznab/main.py +++ b/couchpotato/core/providers/nzb/newznab/main.py @@ -109,10 +109,18 @@ class Newznab(NZBProvider, RSS): return cleanHost(host) + 'api?t=' + type - def isDisabled(self, host): + def isDisabled(self, host = None): return not self.isEnabled(host) - def isEnabled(self, host): + def isEnabled(self, host = None): + + # Return true if at least one is enabled and no host is given + if host is None: + for host in self.getHosts(): + if self.isEnabled(host): + return True + return False + return NZBProvider.isEnabled(self) and host['host'] and host['api_key'] and int(host['use']) def getApiExt(self, host): From 4fe9f9e42f5971ae9a3548023bb0f5b9fb7fc014 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 13 Jan 2013 10:08:59 +0100 Subject: [PATCH 19/19] Log subtitle search --- couchpotato/core/plugins/subtitle/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/couchpotato/core/plugins/subtitle/main.py b/couchpotato/core/plugins/subtitle/main.py index cde1b929..73ead087 100644 --- a/couchpotato/core/plugins/subtitle/main.py +++ b/couchpotato/core/plugins/subtitle/main.py @@ -49,6 +49,7 @@ class Subtitle(Plugin): available_languages = sum(group['subtitle_language'].itervalues(), []) downloaded = [] files = [toUnicode(x) for x in group['files']['movie']] + log.debug('Searching for subtitles for: %s', files) for lang in self.getLanguages(): if lang not in available_languages: @@ -57,6 +58,7 @@ class Subtitle(Plugin): downloaded.extend(download[subtitle]) for d_sub in downloaded: + log.info('Found subtitle (%s): %s', (d_sub.language.alpha2, files)) group['files']['subtitle'].add(d_sub.path) group['subtitle_language'][d_sub.path] = [d_sub.language.alpha2]