From 5a0a5ad83b6016068eab4122144a7bf78103e86e Mon Sep 17 00:00:00 2001 From: clinton-hall Date: Wed, 19 Mar 2014 15:45:20 +1030 Subject: [PATCH 01/36] only compare filesize as int. --- couchpotato/core/media/movie/searcher.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 515f5f9..5887444 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -233,12 +233,12 @@ class MovieSearcher(SearcherBase, MovieTypeBase): # File to small - if nzb['size'] and preferred_quality['size_min'] > nzb['size']: + if nzb['size'] and int(preferred_quality['size_min']) > int(nzb['size']): log.info2('Wrong: "%s" is too small to be %s. %sMB instead of the minimal of %sMB.', (nzb['name'], preferred_quality['label'], nzb['size'], preferred_quality['size_min'])) return False # File to large - if nzb['size'] and preferred_quality.get('size_max') < nzb['size']: + if nzb['size'] and int(preferred_quality['size_max']) < int(nzb['size']): log.info2('Wrong: "%s" is too large to be %s. %sMB instead of the maximum of %sMB.', (nzb['name'], preferred_quality['label'], nzb['size'], preferred_quality['size_max'])) return False From 5b2dfffe0f858fb2eac4299842968732821b102c Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 19 Mar 2014 22:09:27 +0100 Subject: [PATCH 02/36] Use correct year key --- couchpotato/core/media/movie/providers/nzb/nzbindex.py | 2 +- couchpotato/core/media/movie/providers/torrent/bitsoup.py | 2 +- couchpotato/core/media/movie/providers/torrent/iptorrents.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/media/movie/providers/nzb/nzbindex.py b/couchpotato/core/media/movie/providers/nzb/nzbindex.py index 0b5b2b4..70e939d 100644 --- a/couchpotato/core/media/movie/providers/nzb/nzbindex.py +++ b/couchpotato/core/media/movie/providers/nzb/nzbindex.py @@ -14,7 +14,7 @@ class NzbIndex(MovieProvider, Base): def buildUrl(self, media, quality): title = fireEvent('library.query', media, include_year = False, single = True) - year = media['year'] + year = media['info']['year'] query = tryUrlencode({ 'q': '"%s %s" | "%s (%s)"' % (title, year, title, year), diff --git a/couchpotato/core/media/movie/providers/torrent/bitsoup.py b/couchpotato/core/media/movie/providers/torrent/bitsoup.py index 578de69..b3ecf2e 100644 --- a/couchpotato/core/media/movie/providers/torrent/bitsoup.py +++ b/couchpotato/core/media/movie/providers/torrent/bitsoup.py @@ -21,7 +21,7 @@ class Bitsoup(MovieProvider, Base): query = tryUrlencode({ 'search': '"%s" %s' % ( fireEvent('library.query', media, include_year = False, single = True), - media['year'] + media['info']['year'] ), 'cat': self.getCatId(quality['identifier'])[0], }) diff --git a/couchpotato/core/media/movie/providers/torrent/iptorrents.py b/couchpotato/core/media/movie/providers/torrent/iptorrents.py index a1ad4aa..4f9d651 100644 --- a/couchpotato/core/media/movie/providers/torrent/iptorrents.py +++ b/couchpotato/core/media/movie/providers/torrent/iptorrents.py @@ -17,6 +17,6 @@ class IPTorrents(MovieProvider, Base): ] def buildUrl(self, title, media, quality): - query = '%s %s' % (title.replace(':', ''), media['year']) + query = '%s %s' % (title.replace(':', ''), media['info']['year']) return self._buildUrl(query, quality['identifier']) From f4e373447eb07f167ae72c47085216a1ad8c6896 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 19 Mar 2014 22:37:44 +0100 Subject: [PATCH 03/36] File not properly send to Sabnzbd --- couchpotato/core/helpers/variable.py | 2 +- couchpotato/core/plugins/base.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index 5eab960..96faefc 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -293,7 +293,7 @@ def isSubFolder(sub_folder, base_folder): return base_folder and sub_folder and ss(os.path.normpath(base_folder).rstrip(os.path.sep) + os.path.sep) in ss(os.path.normpath(sub_folder).rstrip(os.path.sep) + os.path.sep) # From SABNZBD -re_password = [re.compile(r'([^/\\]+)[/\\](.+)'), re.compile(r'(.+){{([^{}]+)}}$'), re.compile(r'(.+)\s+password\s*=\s*(.+)$', re.I)] +re_password = [re.compile(r'(.+){{([^{}]+)}}$'), re.compile(r'(.+)\s+password\s*=\s*(.+)$', re.I)] def scanForPassword(name): m = None for reg in re_password: diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index 7d52e1e..08f8efd 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -7,7 +7,6 @@ import time import traceback import urllib2 -from couchpotato import get_db from couchpotato.core.event import fireEvent, addEvent from couchpotato.core.helpers.encoding import ss, toSafeString, \ toUnicode, sp @@ -332,7 +331,7 @@ class Plugin(object): return '%s%s' % (toSafeString(toUnicode(release_name)[:max_length]), tag) def createFileName(self, data, filedata, media): - name = sp(os.path.join(self.createNzbName(data, media))) + name = self.createNzbName(data, media) if data.get('protocol') == 'nzb' and 'DOCTYPE nzb' not in filedata and '' not in filedata: return '%s.%s' % (name, 'rar') return '%s.%s' % (name, data.get('protocol')) From a2d22b6feb87fa42937631d2ea1c4eda0874dbb0 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 19 Mar 2014 22:46:14 +0100 Subject: [PATCH 04/36] Set cleanup interval --- couchpotato/core/plugins/file.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/plugins/file.py b/couchpotato/core/plugins/file.py index 77b3ba8..b2533c0 100644 --- a/couchpotato/core/plugins/file.py +++ b/couchpotato/core/plugins/file.py @@ -4,7 +4,7 @@ import traceback from couchpotato import get_db from couchpotato.api import addApiView -from couchpotato.core.event import addEvent +from couchpotato.core.event import addEvent, fireEvent from couchpotato.core.helpers.encoding import toUnicode from couchpotato.core.helpers.variable import md5, getExt from couchpotato.core.logger import CPLog @@ -32,12 +32,11 @@ class FileManager(Plugin): 'return': {'type': 'file'} }) - addEvent('app.load', self.cleanup) + fireEvent('schedule.interval', 'file.cleanup', self.cleanup, hours = 24) def cleanup(self): # Wait a bit after starting before cleanup - time.sleep(2) log.debug('Cleaning up unused files') try: From be46ed12ac8ccedc885ff111fe30480e77f870e2 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 19 Mar 2014 23:06:27 +0100 Subject: [PATCH 05/36] get identifier helper --- couchpotato/core/helpers/variable.py | 8 ++++-- couchpotato/core/media/_base/media/main.py | 5 +--- .../_base/providers/torrent/kickasstorrents.py | 4 +-- .../_base/providers/torrent/passthepopcorn.py | 4 +-- couchpotato/core/media/movie/_base/main.py | 29 +++++++++++----------- .../core/media/movie/providers/nzb/binsearch.py | 3 ++- .../core/media/movie/providers/nzb/newznab.py | 3 ++- .../media/movie/providers/torrent/torrentpotato.py | 3 ++- couchpotato/core/media/movie/searcher.py | 8 +++--- couchpotato/core/plugins/base.py | 5 ++-- couchpotato/core/plugins/renamer.py | 4 +-- couchpotato/core/plugins/scanner.py | 4 +-- 12 files changed, 43 insertions(+), 37 deletions(-) diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index 96faefc..34e66e9 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -227,6 +227,10 @@ def toIterable(value): return [value] +def getIdentifier(media): + return media.get('identifier') or media.get('identifiers', {}).get('imdb') + + def getTitle(media_dict): try: try: @@ -241,10 +245,10 @@ def getTitle(media_dict): try: return media_dict['media']['info']['titles'][0] except: - log.error('Could not get title for %s', media_dict.get('identifier')) + log.error('Could not get title for %s', getIdentifier(media_dict)) return None - log.error('Could not get title for %s', media_dict['identifier']) + log.error('Could not get title for %s', getIdentifier(media_dict)) return None except: log.error('Could not get title for library item: %s', media_dict) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 85047e9..c09d416 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -99,13 +99,10 @@ class MediaPlugin(MediaBase): try: media = get_db().get('id', media_id) - - - default_title = getTitle(media) event = '%s.update_info' % media.get('type') def handler(): - fireEvent(event, identifier = media.get('identifier'), default_title = default_title, on_complete = self.createOnComplete(media_id)) + fireEvent(event, media_id = media_id, on_complete = self.createOnComplete(media_id)) if handler: return handler diff --git a/couchpotato/core/media/_base/providers/torrent/kickasstorrents.py b/couchpotato/core/media/_base/providers/torrent/kickasstorrents.py index 03f0a99..b347ccb 100644 --- a/couchpotato/core/media/_base/providers/torrent/kickasstorrents.py +++ b/couchpotato/core/media/_base/providers/torrent/kickasstorrents.py @@ -2,7 +2,7 @@ import re import traceback from bs4 import BeautifulSoup -from couchpotato.core.helpers.variable import tryInt +from couchpotato.core.helpers.variable import tryInt, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider @@ -38,7 +38,7 @@ class Base(TorrentMagnetProvider): def _search(self, media, quality, results): - data = self.getHTMLData(self.urls['search'] % (self.getDomain(), 'm', media['identifier'].replace('tt', ''))) + data = self.getHTMLData(self.urls['search'] % (self.getDomain(), 'm', getIdentifier(media).replace('tt', ''))) if data: diff --git a/couchpotato/core/media/_base/providers/torrent/passthepopcorn.py b/couchpotato/core/media/_base/providers/torrent/passthepopcorn.py index 56550d2..5368ad3 100644 --- a/couchpotato/core/media/_base/providers/torrent/passthepopcorn.py +++ b/couchpotato/core/media/_base/providers/torrent/passthepopcorn.py @@ -5,7 +5,7 @@ import time import traceback from couchpotato.core.helpers.encoding import tryUrlencode -from couchpotato.core.helpers.variable import getTitle, tryInt, mergeDicts +from couchpotato.core.helpers.variable import getTitle, tryInt, mergeDicts, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.base import TorrentProvider from dateutil.parser import parse @@ -36,7 +36,7 @@ class Base(TorrentProvider): params = mergeDicts(self.quality_search_params[quality_id].copy(), { 'order_by': 'relevance', 'order_way': 'descending', - 'searchstr': media['identifier'] + 'searchstr': getIdentifier(media) }) url = '%s?json=noredirect&%s' % (self.urls['torrent'], tryUrlencode(params)) diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index d8060d7..932c8b2 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -6,7 +6,7 @@ from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, fireEventAsync, addEvent from couchpotato.core.helpers.encoding import toUnicode -from couchpotato.core.helpers.variable import splitString, getTitle, getImdb +from couchpotato.core.helpers.variable import splitString, getTitle, getImdb, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media.movie import MovieTypeBase import six @@ -266,7 +266,7 @@ class MovieBase(MovieTypeBase): else: media = db.get('media', 'imdb-%s' % identifier, with_doc = True)['doc'] - info = fireEvent('movie.info', merge = True, extended = extended, identifier = media.get('identifier')) + info = fireEvent('movie.info', merge = True, extended = extended, identifier = getIdentifier(media)) # Don't need those here try: del info['in_wanted'] @@ -275,7 +275,7 @@ class MovieBase(MovieTypeBase): except: pass if not info or len(info) == 0: - log.error('Could not update, no movie info to work with: %s', media.get('identifier')) + log.error('Could not update, no movie info to work with: %s', identifier) return False # Update basic info @@ -285,19 +285,20 @@ class MovieBase(MovieTypeBase): log.debug('Adding titles: %s', titles) # Define default title - def_title = None if default_title: - counter = 0 - for title in titles: - if title.lower() == toUnicode(default_title.lower()) or (toUnicode(default_title) == six.u('') and toUnicode(titles[0]) == title): - def_title = toUnicode(title) - break - counter += 1 + def_title = None + if default_title: + counter = 0 + for title in titles: + if title.lower() == toUnicode(default_title.lower()) or (toUnicode(default_title) == six.u('') and toUnicode(titles[0]) == title): + def_title = toUnicode(title) + break + counter += 1 - if not def_title: - def_title = toUnicode(titles[0]) + if not def_title: + def_title = toUnicode(titles[0]) - media['title'] = def_title + media['title'] = def_title # Files images = info.get('images', []) @@ -357,7 +358,7 @@ class MovieBase(MovieTypeBase): dates = media.get('info').get('release_date') if dates and (dates.get('expires', 0) < time.time() or dates.get('expires', 0) > time.time() + (604800 * 4)) or not dates: - dates = fireEvent('movie.info.release_date', identifier = media['identifier'], merge = True) + dates = fireEvent('movie.info.release_date', identifier = getIdentifier(media), merge = True) media['info'].update({'release_date': dates}) db.update(media) diff --git a/couchpotato/core/media/movie/providers/nzb/binsearch.py b/couchpotato/core/media/movie/providers/nzb/binsearch.py index f4c16c4..d6f4852 100644 --- a/couchpotato/core/media/movie/providers/nzb/binsearch.py +++ b/couchpotato/core/media/movie/providers/nzb/binsearch.py @@ -1,4 +1,5 @@ from couchpotato.core.helpers.encoding import tryUrlencode +from couchpotato.core.helpers.variable import getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.nzb.binsearch import Base from couchpotato.core.media.movie.providers.base import MovieProvider @@ -13,7 +14,7 @@ class BinSearch(MovieProvider, Base): def buildUrl(self, media, quality): query = tryUrlencode({ - 'q': media['identifier'], + 'q': getIdentifier(media), 'm': 'n', 'max': 400, 'adv_age': Env.setting('retention', 'nzb'), diff --git a/couchpotato/core/media/movie/providers/nzb/newznab.py b/couchpotato/core/media/movie/providers/nzb/newznab.py index dd4d94c..9783f8d 100644 --- a/couchpotato/core/media/movie/providers/nzb/newznab.py +++ b/couchpotato/core/media/movie/providers/nzb/newznab.py @@ -1,4 +1,5 @@ from couchpotato.core.helpers.encoding import tryUrlencode +from couchpotato.core.helpers.variable import getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.nzb.newznab import Base from couchpotato.core.media.movie.providers.base import MovieProvider @@ -13,7 +14,7 @@ class Newznab(MovieProvider, Base): def buildUrl(self, media, api_key): query = tryUrlencode({ 't': 'movie', - 'imdbid': media['identifier'].replace('tt', ''), + 'imdbid': getIdentifier(media).replace('tt', ''), 'apikey': api_key, 'extended': 1 }) diff --git a/couchpotato/core/media/movie/providers/torrent/torrentpotato.py b/couchpotato/core/media/movie/providers/torrent/torrentpotato.py index 9c99207..6757353 100644 --- a/couchpotato/core/media/movie/providers/torrent/torrentpotato.py +++ b/couchpotato/core/media/movie/providers/torrent/torrentpotato.py @@ -1,4 +1,5 @@ from couchpotato.core.helpers.encoding import tryUrlencode +from couchpotato.core.helpers.variable import getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.torrentpotato import Base from couchpotato.core.media.movie.providers.base import MovieProvider @@ -14,6 +15,6 @@ class TorrentPotato(MovieProvider, Base): arguments = tryUrlencode({ 'user': host['name'], 'passkey': host['pass_key'], - 'imdbid': media['identifier'] + 'imdbid': getIdentifier(media), }) return '%s?%s' % (host['host'], arguments) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 515f5f9..d217c65 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -8,7 +8,7 @@ from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent, fireEventAsync from couchpotato.core.helpers.encoding import simplifyString -from couchpotato.core.helpers.variable import getTitle, possibleTitles, getImdb +from couchpotato.core.helpers.variable import getTitle, possibleTitles, getImdb, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.searcher.base import SearcherBase from couchpotato.core.media.movie import MovieTypeBase @@ -95,10 +95,10 @@ class MovieSearcher(SearcherBase, MovieTypeBase): try: self.single(media, search_protocols) except IndexError: - log.error('Forcing library update for %s, if you see this often, please report: %s', (media['identifier'], traceback.format_exc())) + log.error('Forcing library update for %s, if you see this often, please report: %s', (getIdentifier(media), traceback.format_exc())) fireEvent('movie.update_info', media_id) except: - log.error('Search failed for %s: %s', (media['identifier'], traceback.format_exc())) + log.error('Search failed for %s: %s', (getIdentifier(media), traceback.format_exc())) self.in_progress['to_go'] -= 1 @@ -257,7 +257,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): return True # Check if nzb contains imdb link - if getImdb(nzb.get('description', '')) == media['identifier']: + if getImdb(nzb.get('description', '')) == getIdentifier(media): return True for raw_title in media['info']['titles']: diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index 08f8efd..1e4bfeb 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -10,7 +10,7 @@ import urllib2 from couchpotato.core.event import fireEvent, addEvent from couchpotato.core.helpers.encoding import ss, toSafeString, \ toUnicode, sp -from couchpotato.core.helpers.variable import getExt, md5, isLocalIP, scanForPassword, tryInt +from couchpotato.core.helpers.variable import getExt, md5, isLocalIP, scanForPassword, tryInt, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.environment import Env import requests @@ -338,7 +338,8 @@ class Plugin(object): def cpTag(self, media): if Env.setting('enabled', 'renamer'): - return '.cp(' + media.get('identifier') + ')' if media.get('identifier') else '' + identifier = getIdentifier(media) + return '.cp(' + identifier + ')' if identifier else '' return '' diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 0f531bc..4cfc987 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -10,7 +10,7 @@ from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent, fireEventAsync from couchpotato.core.helpers.encoding import toUnicode, ss, sp from couchpotato.core.helpers.variable import getExt, mergeDicts, getTitle, \ - getImdb, link, symlink, tryInt, splitString, fnEscape, isSubFolder + getImdb, link, symlink, tryInt, splitString, fnEscape, isSubFolder, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from couchpotato.environment import Env @@ -1043,7 +1043,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) if rls: media = db.get('id', rls['media_id']) release_download.update({ - 'imdb_id': media['identifier'], + 'imdb_id': getIdentifier(media), 'quality': rls['quality'], 'protocol': rls.get('info', {}).get('protocol') or rls.get('info', {}).get('type'), 'release_id': rls['_id'], diff --git a/couchpotato/core/plugins/scanner.py b/couchpotato/core/plugins/scanner.py index 0066c36..65ae257 100644 --- a/couchpotato/core/plugins/scanner.py +++ b/couchpotato/core/plugins/scanner.py @@ -8,7 +8,7 @@ from couchpotato import get_db from couchpotato.core.event import fireEvent, addEvent from couchpotato.core.helpers.encoding import toUnicode, simplifyString, sp from couchpotato.core.helpers.variable import getExt, getImdb, tryInt, \ - splitString + splitString, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from enzyme.exceptions import NoParserError, ParseError @@ -403,7 +403,7 @@ class Scanner(Plugin): if not group['media']: log.error('Unable to determine media: %s', group['identifiers']) else: - group['identifier'] = group['media'].get('identifier') or group['media']['info'].get('imdb') + group['identifier'] = getIdentifier(group['media']) or group['media']['info'].get('imdb') processed_movies[identifier] = group From 8316b5cb29109c9d3c2ad892e743bc64cffe092d Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 19 Mar 2014 23:24:16 +0100 Subject: [PATCH 06/36] Key identifiers missing --- couchpotato/core/media/_base/media/index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/_base/media/index.py b/couchpotato/core/media/_base/media/index.py index 5065871..069cb63 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -6,7 +6,7 @@ from couchpotato.core.helpers.encoding import toUnicode, simplifyString class MediaIndex(MultiTreeBasedIndex): - _version = 2 + _version = 3 custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex""" @@ -26,7 +26,7 @@ class MediaIndex(MultiTreeBasedIndex): ids = [] for x in identifiers: - ids.append(md5('%s-%s' % (x, data['identifiers'][x])).hexdigest()) + ids.append(md5('%s-%s' % (x, identifiers[x])).hexdigest()) return ids, None From e314c605f117eb2c5eda0b8c8c8fe502221a67e6 Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 19 Mar 2014 23:28:12 +0100 Subject: [PATCH 07/36] Missing identifier key --- couchpotato/core/plugins/manage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/plugins/manage.py b/couchpotato/core/plugins/manage.py index e1e084f..990bc90 100644 --- a/couchpotato/core/plugins/manage.py +++ b/couchpotato/core/plugins/manage.py @@ -8,7 +8,7 @@ from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, addEvent, fireEventAsync from couchpotato.core.helpers.encoding import sp -from couchpotato.core.helpers.variable import splitString, getTitle, tryInt +from couchpotato.core.helpers.variable import splitString, getTitle, tryInt, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from couchpotato.environment import Env @@ -123,7 +123,7 @@ class Manage(Plugin): total_movies, done_movies = fireEvent('media.list', types = 'movie', status = 'done', single = True) for done_movie in done_movies: - if done_movie['identifier'] not in added_identifiers: + if getIdentifier(done_movie) not in added_identifiers: fireEvent('media.delete', media_id = done_movie['_id'], delete_from = 'all') else: From 21c9d7fcc39deee77ab62053287a9d67448f73d1 Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 20 Mar 2014 16:53:27 +0100 Subject: [PATCH 08/36] Use identifier helper --- couchpotato/core/media/_base/providers/torrent/hdbits.py | 4 ++-- couchpotato/core/media/_base/providers/torrent/yify.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/media/_base/providers/torrent/hdbits.py b/couchpotato/core/media/_base/providers/torrent/hdbits.py index 73bfc16..fa45b83 100644 --- a/couchpotato/core/media/_base/providers/torrent/hdbits.py +++ b/couchpotato/core/media/_base/providers/torrent/hdbits.py @@ -2,7 +2,7 @@ import re import json import traceback -from couchpotato.core.helpers.variable import tryInt +from couchpotato.core.helpers.variable import tryInt, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.base import TorrentProvider @@ -44,7 +44,7 @@ class Base(TorrentProvider): def _search(self, movie, quality, results): - match = re.match(r'tt(\d{7})', movie['identifier']) + match = re.match(r'tt(\d{7})', getIdentifier(movie)) data = self._post_query(imdb = {'id': match.group(1)}) diff --git a/couchpotato/core/media/_base/providers/torrent/yify.py b/couchpotato/core/media/_base/providers/torrent/yify.py index 9380e65..fe7a9b4 100644 --- a/couchpotato/core/media/_base/providers/torrent/yify.py +++ b/couchpotato/core/media/_base/providers/torrent/yify.py @@ -1,6 +1,6 @@ import traceback -from couchpotato.core.helpers.variable import tryInt +from couchpotato.core.helpers.variable import tryInt, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.base import TorrentProvider @@ -35,7 +35,7 @@ class Base(TorrentProvider): def _search(self, movie, quality, results): - search_url = self.urls['search'] % (self.getDomain(), movie['identifier'], quality['identifier']) + search_url = self.urls['search'] % (self.getDomain(), getIdentifier(movie), quality['identifier']) data = self.getJsonData(search_url) From 00419910b49056d5f2a0e8a21fcf034574f8f300 Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 20 Mar 2014 16:54:54 +0100 Subject: [PATCH 09/36] Use getIdentifier in suggestions --- couchpotato/core/media/movie/suggestion/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py index 62b9f57..e9b071d 100644 --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -1,7 +1,7 @@ from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import fireEvent -from couchpotato.core.helpers.variable import splitString, removeDuplicate +from couchpotato.core.helpers.variable import splitString, removeDuplicate, getIdentifier from couchpotato.core.plugins.base import Plugin from couchpotato.environment import Env @@ -87,7 +87,7 @@ class Suggestion(Plugin): if len(new_suggestions) - 1 < limit: db = get_db() active_movies = db.run('media', 'with_status', ['active', 'done']) - movies = [x['identifier'] for x in active_movies] + movies = [getIdentifier(x) for x in active_movies] movies.extend(seen) ignored.extend([x.get('imdb') for x in cached_suggestion]) From ff94bd6a9017dde07c043cc1498a68333612c3bc Mon Sep 17 00:00:00 2001 From: Friso Abcouwer Date: Thu, 20 Mar 2014 20:17:13 +0100 Subject: [PATCH 10/36] Rewrite contributing.md --- contributing.md | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/contributing.md b/contributing.md index d5db0b4..0d82d71 100644 --- a/contributing.md +++ b/contributing.md @@ -1,25 +1,36 @@ -## Got a issue/feature request or submitting a pull request? +# Contributing to CouchPotatoServer -Make sure you think of the following things: +1. [Contributing](#contributing) +2. [Submitting an Issue](#issues) +3. [Submitting a Pull Request](#pull-requests) -## Issue - * Search through the existing (and closed) issues first, see if you can get your answer there. - * Double check the result manually, because it could be an external issue. - * Post logs! Without seeing what is going on, I can't reproduce the error. - * Also check the logs before submitting, obvious errors like permission or http errors are often not related to CP. - * What is the movie + quality you are searching for? - * What are you're settings for the specific problem? - * What providers are you using? (While you're logs include these, scanning through hundred of lines of log isn't our hobby) - * Post the logs from config directory, please do not copy paste the UI. Use pastebin to store these logs! +## Contributing +Thank you for your interest in contributing to CouchPotato. There are several ways to help out, even if you've never worked on an open source project before. +If you've found a bug or want to request a feature, you can report it by [posting an issue](https://github.com/RuudBurger/CouchPotatoServer/issues/new) - be sure to read the [guidelines](#issues) first! +If you want to contribute your own work, please read the [guidelines](#pull-requests) for submitting a pull request. +Lastly, for anything related to CouchPotato, feel free to stop by the [forum](http://couchpota.to/forum/) or the [#couchpotato](http://webchat.freenode.net/?channels=couchpotato) IRC channel at irc.freenode.net. + +## Issues +Issues are intended for reporting bugs and weird behaviour or suggesting improvements to CouchPotatoServer. +Before you submit an issue, please go through the following checklist: + * Search through existing issues (*including closed issues!*) first: you might be able to get your answer there. + * Double check your issue manually, because it could be an external issue. + * Post logs with your issue: Without seeing what is going on, the developers can't reproduce the error. + * Check the logs yourself before submitting them. Obvious errors like permission or HTTP errors are often not related to CouchPotato. + * What movie and quality are you searching for? + * What are your settings for the specific problem? + * What providers are you using? (While your logs include these, scanning through hundreds of lines of logs isn't our hobby) + * Post the logs from the *config* directory, please do not copy paste the UI. Use pastebin to store these logs! * Give a short step by step of how to reproduce the error. - * What hardware / OS are you using and what are the limits? NAS can be slow and maybe have a different python installed then when you use CP on OSX or Windows for example. - * I will mark issues with the "can't reproduce" tag. Don't go asking "why closed" if it clearly says the issue in the tag ;) - * If you're running on a NAS (QNAP, Austor etc..) with pre-made packages, make sure these are setup to use our source repo (RuudBurger/CouchPotatoServer) and nothing else!! + * What hardware / OS are you using and what are its limitations? For example: NAS can be slow and maybe have a different version of python installed then when you use CP on OSX or Windows. + * Your issue might be marked with the "can't reproduce" tag. Don't ask why your issue was closed if it says so in the tag. + * If you're running on a NAS (QNAP, Austor etc..) with pre-made packages, make sure these are set up to use our source repository (RuudBurger/CouchPotatoServer) and nothing else!! + +The more relevant information you can provide, the more likely it is the issue will be resolved rather than closed. -## Pull Request - * Make sure you're pull request is made for develop branch (or relevant feature branch) +## Pull Requests +Pull requests are intended for contributing code or documentation to the project. Before you submit a pull request, consider the following: + * Make sure your pull request is made for the *develop* branch (or relevant feature branch). * Have you tested your PR? If not, why? - * Are there any limitations of your PR we should know of? - * Make sure to keep you're PR up-to-date with the branch you're trying to push into. - -**If we don't get enough info, the chance of the issue getting closed is a lot bigger ;)** + * Does your PR have any limitations we should know of? + * Is your PR up-to-date with the branch you're trying to push into? From 384a2e0e152dd06990e69909fed13a43db933b20 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 11:06:25 +0100 Subject: [PATCH 11/36] Suggestions not showing --- couchpotato/core/media/movie/suggestion/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py index e9b071d..1c6e95f 100644 --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -30,7 +30,7 @@ class Suggestion(Plugin): if not movies or len(movies) == 0: db = get_db() active_movies = db.run('media', 'with_status', ['active', 'done']) - movies = [x['identifier'] for x in active_movies] + movies = [getIdentifier(x) for x in active_movies] if not ignored or len(ignored) == 0: ignored = splitString(Env.prop('suggest_ignore', default = '')) From 41e94e1e22236a1a161c754b27f1ff087f5c846e Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 12:15:46 +0100 Subject: [PATCH 12/36] Make sure media dict has category key --- couchpotato/core/media/__init__.py | 2 +- couchpotato/core/media/_base/media/index.py | 5 ----- couchpotato/core/media/_base/media/main.py | 17 ++++++++++------- couchpotato/core/media/movie/_base/main.py | 4 ++-- couchpotato/core/media/movie/searcher.py | 4 ++-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/couchpotato/core/media/__init__.py b/couchpotato/core/media/__init__.py index f9b3b46..4799766 100644 --- a/couchpotato/core/media/__init__.py +++ b/couchpotato/core/media/__init__.py @@ -25,7 +25,7 @@ class MediaBase(Plugin): def onComplete(): try: db = get_db() - media = db.get('id', media_id) + media = fireEvent('media.get', media_id, single = True) event_name = '%s.searcher.single' % media.get('type') fireEventAsync(event_name, media, on_complete = self.createNotifyFront(media_id)) diff --git a/couchpotato/core/media/_base/media/index.py b/couchpotato/core/media/_base/media/index.py index 069cb63..808eb12 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -30,11 +30,6 @@ class MediaIndex(MultiTreeBasedIndex): return ids, None - def run_to_dict(self, db, media_id, dict_dept = None): - if not dict_dept: dict_dept = {} - - return db.get('id', media_id) - def run_identifiers(self, db, identifiers, with_doc = False): for x in identifiers: try: diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index c09d416..de8a703 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -121,16 +121,19 @@ class MediaPlugin(MediaBase): imdb_id = getImdb(str(media_id)) + media = None if imdb_id: - m = db.get('media', 'imdb-%s' % imdb_id, with_doc = True)['doc'] + media = db.get('media', 'imdb-%s' % imdb_id, with_doc = True)['doc'] else: - m = db.get('id', media_id) + media = db.get('id', media_id) + + if media: - results = None - if m: - results = db.run('media', 'to_dict', m['_id']) + # Attach category + if media.get('category_id'): + media['category'] = db.get('id', media.get('category_id')) - return results + return media def getView(self, id = None, **kwargs): @@ -217,7 +220,7 @@ class MediaPlugin(MediaBase): offset -= 1 continue - media = db.run('media', 'to_dict', media_id) + media = fireEvent('media.get', media_id, single = True) media['releases'] = list(db.run('release', 'for_media', media_id)) diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 932c8b2..499dba9 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -168,7 +168,7 @@ class MovieBase(MovieTypeBase): if rel['status'] is 'available': db.delete(rel) - movie_dict = db.run('media', 'to_dict', m['_id']) + movie_dict = fireEvent('media.get', m['_id'], single = True) if do_search and search_after: onComplete = self.createOnComplete(m['_id']) @@ -229,7 +229,7 @@ class MovieBase(MovieTypeBase): m = db.get('id', media_id) - movie_dict = db.run('media', 'to_dict', m['_id']) + movie_dict = fireEvent('media.get', m['_id'], single = True) fireEventAsync('movie.searcher.single', movie_dict, on_complete = self.createNotifyFront(media_id)) except: diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index d217c65..6a42631 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -90,7 +90,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): for media_id in medias: - media = db.run('media', 'to_dict', media_id) + media = fireEvent('media.get', media_id, single = True) try: self.single(media, search_protocols) @@ -335,7 +335,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): rel['status'] = 'ignored' db.update(rel) - movie_dict = db.run('media', 'to_dict', media_id) + movie_dict = fireEvent('media.get', media_id, single = True) log.info('Trying next release for: %s', getTitle(movie_dict)) self.single(movie_dict, manual = manual) From 6243ed3bd5746e3c8fa70cadeb5eb8994347cc4d Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 12:30:44 +0100 Subject: [PATCH 13/36] Add destination support to Synology downloader --- couchpotato/core/downloaders/synology.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/downloaders/synology.py b/couchpotato/core/downloaders/synology.py index 46d889f..f7145de 100644 --- a/couchpotato/core/downloaders/synology.py +++ b/couchpotato/core/downloaders/synology.py @@ -33,7 +33,7 @@ class Synology(Downloader): try: # Send request to Synology - srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password')) + srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password'), self.conf('destination')) if data['protocol'] == 'torrent_magnet': log.info('Adding torrent URL %s', data['url']) response = srpc.create_task(url = data['url']) @@ -84,7 +84,7 @@ class SynologyRPC(object): """SynologyRPC lite library""" - def __init__(self, host = 'localhost', port = 5000, username = None, password = None): + def __init__(self, host = 'localhost', port = 5000, username = None, password = None, destination = None): super(SynologyRPC, self).__init__() @@ -92,6 +92,7 @@ class SynologyRPC(object): self.auth_url = 'http://%s:%s/webapi/auth.cgi' % (host, port) self.username = username self.password = password + self.destination = destination self.session_name = 'DownloadStation' def _login(self): @@ -144,6 +145,10 @@ class SynologyRPC(object): 'version': '1', 'method': 'create', '_sid': self.sid} + + if self.destination and len(self.destination) > 0: + args['destination'] = self.destination + if url: log.info('Login success, adding torrent URI') args['uri'] = url @@ -196,6 +201,11 @@ config = [{ 'type': 'password', }, { + 'name': 'destination', + 'description': 'Specify existing destination share to where your files will be downloaded, usually Downloads', + 'advanced': True, + }, + { 'name': 'use_for', 'label': 'Use for', 'default': 'both', From 1224b98745711a0f95e2e88fe175f05291e52128 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 13:15:35 +0100 Subject: [PATCH 14/36] Add releases to media.get. re-use where possible --- couchpotato/core/media/_base/media/main.py | 4 ++-- couchpotato/core/media/movie/searcher.py | 5 ++--- couchpotato/core/plugins/manage.py | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index de8a703..06bbf67 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -133,6 +133,8 @@ class MediaPlugin(MediaBase): if media.get('category_id'): media['category'] = db.get('id', media.get('category_id')) + media['releases'] = list(db.run('release', 'for_media', media['_id'])) + return media def getView(self, id = None, **kwargs): @@ -222,8 +224,6 @@ class MediaPlugin(MediaBase): media = fireEvent('media.get', media_id, single = True) - media['releases'] = list(db.run('release', 'for_media', media_id)) - # Merge releases with movie dict medias.append(media) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 6a42631..84ef50e 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -142,7 +142,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): profile = db.get('id', movie['profile_id']) quality_order = fireEvent('quality.order', single = True) - media_releases = db.run('release', 'for_media', movie['_id']) ret = False @@ -161,7 +160,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): has_better_quality = 0 # See if better quality is available - for release in media_releases: + for release in movie.get('releases', []): if quality_order.index(release['quality']) <= quality_order.index(q_identifier) and release['status'] not in ['available', 'ignored', 'failed']: has_better_quality += 1 @@ -187,7 +186,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): ret = True # Remove releases that aren't found anymore - for release in db.run('release', 'for_media', movie['_id']): + for release in movie.get('releases', []): if release.get('status') == 'available' and release.get('identifier') not in found_releases: fireEvent('release.delete', release.get('_id'), single = True) diff --git a/couchpotato/core/plugins/manage.py b/couchpotato/core/plugins/manage.py index 990bc90..623ce6f 100644 --- a/couchpotato/core/plugins/manage.py +++ b/couchpotato/core/plugins/manage.py @@ -127,8 +127,7 @@ class Manage(Plugin): fireEvent('media.delete', media_id = done_movie['_id'], delete_from = 'all') else: - db = get_db() - releases = list(db.run('release', 'for_media', done_movie.get('_id'))) + releases = done_movie.get('releases', []) for release in releases: if release.get('files'): From f734e27d238feab7da218189a094caf9565508c4 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 13:22:16 +0100 Subject: [PATCH 15/36] Make sure to safe size as int --- couchpotato/core/media/movie/searcher.py | 6 +++--- couchpotato/core/plugins/quality/main.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 4205054..e479d2a 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -8,7 +8,7 @@ from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent, fireEventAsync from couchpotato.core.helpers.encoding import simplifyString -from couchpotato.core.helpers.variable import getTitle, possibleTitles, getImdb, getIdentifier +from couchpotato.core.helpers.variable import getTitle, possibleTitles, getImdb, getIdentifier, tryInt from couchpotato.core.logger import CPLog from couchpotato.core.media._base.searcher.base import SearcherBase from couchpotato.core.media.movie import MovieTypeBase @@ -232,12 +232,12 @@ class MovieSearcher(SearcherBase, MovieTypeBase): # File to small - if nzb['size'] and int(preferred_quality['size_min']) > int(nzb['size']): + if nzb['size'] and tryInt(preferred_quality['size_min']) > tryInt(nzb['size']): log.info2('Wrong: "%s" is too small to be %s. %sMB instead of the minimal of %sMB.', (nzb['name'], preferred_quality['label'], nzb['size'], preferred_quality['size_min'])) return False # File to large - if nzb['size'] and int(preferred_quality['size_max']) < int(nzb['size']): + if nzb['size'] and tryInt(preferred_quality['size_max']) < tryInt(nzb['size']): log.info2('Wrong: "%s" is too large to be %s. %sMB instead of the maximum of %sMB.', (nzb['name'], preferred_quality['label'], nzb['size'], preferred_quality['size_max'])) return False diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index ee06d4c..e64b503 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -5,7 +5,7 @@ from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import addEvent from couchpotato.core.helpers.encoding import toUnicode, ss -from couchpotato.core.helpers.variable import mergeDicts, getExt +from couchpotato.core.helpers.variable import mergeDicts, getExt, tryInt from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.quality.index import QualityIndex @@ -121,7 +121,7 @@ class QualityPlugin(Plugin): quality = db.get('quality', kwargs.get('identifier'), with_doc = True) if quality: - quality['doc'][kwargs.get('value_type')] = kwargs.get('value') + quality['doc'][kwargs.get('value_type')] = tryInt(kwargs.get('value')) db.update(quality['doc']) self.cached_qualities = None @@ -148,8 +148,8 @@ class QualityPlugin(Plugin): '_t': 'quality', 'order': order, 'identifier': q.get('identifier'), - 'size_min': q.get('size')[0], - 'size_max': q.get('size')[1] + 'size_min': tryInt(q.get('size')[0]), + 'size_max': tryInt(q.get('size')[1]), }) log.info('Creating profile: %s', q.get('label')) From a8159c9e55588c67c498a2d6edfd15852bd05830 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 13:23:52 +0100 Subject: [PATCH 16/36] Make sure quality sizes are int on migrate --- couchpotato/core/database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/database.py b/couchpotato/core/database.py index 3aa1bb7..19fde90 100644 --- a/couchpotato/core/database.py +++ b/couchpotato/core/database.py @@ -279,8 +279,8 @@ class Database(object): quality = db.get('id', q_id) quality['order'] = q.get('order') - quality['size_min'] = q.get('size_min') - quality['size_max'] = q.get('size_max') + quality['size_min'] = tryInt(q.get('size_min')) + quality['size_max'] = tryInt(q.get('size_max')) db.update(quality) quality_link[x] = quality From 6115f83a0982263b760c1c74211c1b5e44285a94 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 13:29:34 +0100 Subject: [PATCH 17/36] Update TPB proxies --- couchpotato/core/media/_base/providers/torrent/thepiratebay.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/_base/providers/torrent/thepiratebay.py b/couchpotato/core/media/_base/providers/torrent/thepiratebay.py index 42006d1..4d81961 100644 --- a/couchpotato/core/media/_base/providers/torrent/thepiratebay.py +++ b/couchpotato/core/media/_base/providers/torrent/thepiratebay.py @@ -29,9 +29,9 @@ class Base(TorrentMagnetProvider): 'http://pirateproxy.ca', 'http://tpb.al', 'http://www.tpb.gr', - 'http://nl.tpb.li', + 'http://bayproxy.me', 'http://proxybay.eu', - 'https://www.getpirate.com', + 'http://www.getpirate.com', 'http://piratebay.io', ] From 37bc54e01e91b4f6e7721fa9e1f9127f14e84792 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 13:32:36 +0100 Subject: [PATCH 18/36] Add title to boxcar2 message closes #2977 --- couchpotato/core/notifications/boxcar2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/notifications/boxcar2.py b/couchpotato/core/notifications/boxcar2.py index 3e19c19..04ce4f3 100644 --- a/couchpotato/core/notifications/boxcar2.py +++ b/couchpotato/core/notifications/boxcar2.py @@ -25,7 +25,7 @@ class Boxcar2(Notification): data = { 'user_credentials': self.conf('token'), - 'notification[title]': toUnicode(message), + 'notification[title]': toUnicode('%s - %s' % (self.default_title, message)), 'notification[long_message]': toUnicode(long_message), } From 27e4800ed222039e7f7c21bb2b8b298499af6384 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 14:31:49 +0100 Subject: [PATCH 19/36] try next release, use media_id --- couchpotato/core/media/movie/_base/static/movie.actions.js | 2 +- couchpotato/core/media/movie/searcher.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/movie/_base/static/movie.actions.js b/couchpotato/core/media/movie/_base/static/movie.actions.js index cb4be00..5dcaed7 100644 --- a/couchpotato/core/media/movie/_base/static/movie.actions.js +++ b/couchpotato/core/media/movie/_base/static/movie.actions.js @@ -428,7 +428,7 @@ MA.Release = new Class({ Api.request('movie.searcher.try_next', { 'data': { - 'id': self.movie.get('_id') + 'media_id': self.movie.get('_id') } }); diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index e479d2a..5a95629 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -38,7 +38,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): addApiView('movie.searcher.try_next', self.tryNextReleaseView, docs = { 'desc': 'Marks the snatched results as ignored and try the next best release', 'params': { - 'id': {'desc': 'The id of the movie'}, + 'media_id': {'desc': 'The id of the media'}, }, }) From 8bdbf8df2e60faf1bdbe398b2aa1d45772fe4115 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Tue, 11 Mar 2014 00:29:56 +1300 Subject: [PATCH 20/36] Updated rtorrent-python library - Fixed bug with basic auth on secure connections - Added 'test_connection' method to RTorrent class - Minor adjustment to authorization encoding --- libs/rtorrent/__init__.py | 7 +++++-- libs/rtorrent/lib/xmlrpc/basic_auth.py | 38 +++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/libs/rtorrent/__init__.py b/libs/rtorrent/__init__.py index d70e6e1..a3f1607 100755 --- a/libs/rtorrent/__init__.py +++ b/libs/rtorrent/__init__.py @@ -89,13 +89,16 @@ class RTorrent: def _get_conn(self): """Get ServerProxy instance""" - if self.username is not None and self.password is not None: + + if self.username and self.password: if self.scheme == 'scgi': raise NotImplementedError() + secure = self.scheme == 'https' + return self.sp( self.uri, - transport=BasicAuthTransport(self.username, self.password), + transport=BasicAuthTransport(secure, self.username, self.password), **self.sp_kwargs ) diff --git a/libs/rtorrent/lib/xmlrpc/basic_auth.py b/libs/rtorrent/lib/xmlrpc/basic_auth.py index 20c02d9..c5654a2 100644 --- a/libs/rtorrent/lib/xmlrpc/basic_auth.py +++ b/libs/rtorrent/lib/xmlrpc/basic_auth.py @@ -20,24 +20,46 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -from base64 import encodestring -import string +from base64 import b64encode +import httplib import xmlrpclib class BasicAuthTransport(xmlrpclib.Transport): - def __init__(self, username=None, password=None): + def __init__(self, secure=False, username=None, password=None): xmlrpclib.Transport.__init__(self) + self.secure = secure + self.username = username self.password = password def send_auth(self, h): - if self.username is not None and self.password is not None: - h.putheader('AUTHORIZATION', "Basic %s" % string.replace( - encodestring("%s:%s" % (self.username, self.password)), - "\012", "" - )) + if not self.username or not self.password: + return + + auth = b64encode("%s:%s" % (self.username, self.password)) + + h.putheader('Authorization', "Basic %s" % auth) + + def make_connection(self, host): + if self._connection and host == self._connection[0]: + return self._connection[1] + + chost, self._extra_headers, x509 = self.get_host_info(host) + + if self.secure: + try: + self._connection = host, httplib.HTTPSConnection(chost, None, **(x509 or {})) + except AttributeError: + raise NotImplementedError( + "your version of httplib doesn't support HTTPS" + ) + else: + self._connection = host, httplib.HTTPConnection(chost) + + return self._connection[1] + def single_request(self, host, handler, request_body, verbose=0): # issue XML-RPC request From 28062eacb66eed52c2697f685170f4e963f0bdf4 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Tue, 11 Mar 2014 15:13:49 +1300 Subject: [PATCH 21/36] [rtorrent] cleaned up connection, '+https' is now added to 'httprpc' protocol if SSL option is enabled --- couchpotato/core/downloaders/rtorrent_.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/couchpotato/core/downloaders/rtorrent_.py b/couchpotato/core/downloaders/rtorrent_.py index fb8948c..d5dbf7d 100644 --- a/couchpotato/core/downloaders/rtorrent_.py +++ b/couchpotato/core/downloaders/rtorrent_.py @@ -59,20 +59,24 @@ class rTorrent(Downloader): return self.rt url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl')) + + # Automatically add '+https' to 'httprpc' protocol if SSL is enabled + if self.conf('ssl') and url.startswith('httprpc://'): + url = url.replace('httprpc://', 'httprpc+https://') + parsed = urlparse(url) # rpc_url is only used on http/https scgi pass-through if parsed.scheme in ['http', 'https']: url += self.conf('rpc_url') - if self.conf('username') and self.conf('password'): - self.rt = RTorrent( - url, - self.conf('username'), - self.conf('password') - ) - else: - self.rt = RTorrent(url) + print url + + self.rt = RTorrent( + url, + self.conf('username'), + self.conf('password') + ) self.error_msg = '' try: From 61f1fdabd131a9c89bae2aec6cfa3c312ed16f63 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sat, 22 Mar 2014 02:46:05 +1300 Subject: [PATCH 22/36] Removed print statement from rtorrent downloader --- couchpotato/core/downloaders/rtorrent_.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/couchpotato/core/downloaders/rtorrent_.py b/couchpotato/core/downloaders/rtorrent_.py index d5dbf7d..6e5c4b6 100644 --- a/couchpotato/core/downloaders/rtorrent_.py +++ b/couchpotato/core/downloaders/rtorrent_.py @@ -70,8 +70,6 @@ class rTorrent(Downloader): if parsed.scheme in ['http', 'https']: url += self.conf('rpc_url') - print url - self.rt = RTorrent( url, self.conf('username'), From 89c83001ca992565e68e844c37cf9d8bbb345ead Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 14:49:44 +0100 Subject: [PATCH 23/36] Move status_get outside index --- couchpotato/core/media/_base/media/index.py | 8 -------- couchpotato/core/media/_base/media/main.py | 19 +++++++++++++++---- couchpotato/core/media/movie/searcher.py | 10 ++++------ couchpotato/core/media/movie/suggestion/main.py | 5 ++--- couchpotato/core/plugins/dashboard.py | 2 +- couchpotato/core/plugins/profile/main.py | 4 ++-- couchpotato/core/plugins/release/main.py | 2 +- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/couchpotato/core/media/_base/media/index.py b/couchpotato/core/media/_base/media/index.py index 808eb12..4733ffa 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -38,14 +38,6 @@ class MediaIndex(MultiTreeBasedIndex): except: pass - def run_with_status(self, db, status = [], with_doc = True): - - status = list(status if isinstance(status, (list, tuple)) else [status]) - - for s in status: - for ms in db.get_many('media_status', s, with_doc = with_doc): - yield ms['doc'] if with_doc else ms - class MediaStatusIndex(TreeBasedIndex): _version = 1 diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 06bbf67..d1f2914 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -74,6 +74,7 @@ class MediaPlugin(MediaBase): addEvent('app.load', self.addSingleDeleteView, priority = 100) addEvent('media.get', self.get) + addEvent('media.with_status', self.withStatus) addEvent('media.list', self.list) addEvent('media.delete', self.delete) addEvent('media.restatus', self.restatus) @@ -146,6 +147,16 @@ class MediaPlugin(MediaBase): 'media': media, } + def withStatus(self, status, with_doc = True): + + db = get_db() + + status = list(status if isinstance(status, (list, tuple)) else [status]) + + for s in status: + for ms in db.get_many('media_status', s, with_doc = with_doc): + yield ms['doc'] if with_doc else ms + def list(self, types = None, status = None, release_status = None, status_or = False, limit_offset = None, starts_with = None, search = None): db = get_db() @@ -172,13 +183,13 @@ class MediaPlugin(MediaBase): # Filter on movie status if status and len(status) > 0: filter_by['media_status'] = set() - for media_status in db.run('media', 'with_status', status, with_doc = False): + for media_status in fireEvent('media.with_status', status, with_doc = False, single = True): filter_by['media_status'].add(media_status.get('_id')) # Filter on release status if release_status and len(release_status) > 0: filter_by['release_status'] = set() - for release_status in db.run('release', 'with_status', release_status, with_doc = False): + for release_status in fireEvent('media.with_status', release_status, with_doc = False, single = True): filter_by['release_status'].add(release_status.get('media_id')) # Add search filters @@ -285,13 +296,13 @@ class MediaPlugin(MediaBase): # Filter on movie status if status and len(status) > 0: filter_by['media_status'] = set() - for media_status in db.run('media', 'with_status', status, with_doc = False): + for media_status in fireEvent('media.with_status', status, with_doc = False, single = True): filter_by['media_status'].add(media_status.get('_id')) # Filter on release status if release_status and len(release_status) > 0: filter_by['release_status'] = set() - for release_status in db.run('release', 'with_status', release_status, with_doc = False): + for release_status in fireEvent('media.with_status', release_status, with_doc = False, single = True): filter_by['release_status'].add(release_status.get('media_id')) # Filter by combining ids diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 5a95629..682fa69 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -74,9 +74,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): self.in_progress = True fireEvent('notify.frontend', type = 'movie.searcher.started', data = True, message = 'Full search started') - db = get_db() - - medias = [x['_id'] for x in db.run('media', 'with_status', 'active', with_doc = False)] + medias = [x['_id'] for x in fireEvent('media.with_status', 'active', with_doc = False, single = True)] random.shuffle(medias) total = len(medias) @@ -316,9 +314,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase): return False - def tryNextReleaseView(self, id = None, **kwargs): + def tryNextReleaseView(self, media_id = None, **kwargs): - trynext = self.tryNextRelease(id, manual = True) + trynext = self.tryNextRelease(media_id, manual = True) return { 'success': trynext @@ -328,7 +326,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): try: db = get_db() - rels = db.run('media', 'with_status', media_id, status = ['snatched', 'done']) + rels = fireEvent('media.with_status', ['snatched', 'done'], single = True) for rel in rels: rel['status'] = 'ignored' diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py index 1c6e95f..5db403f 100644 --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -28,8 +28,7 @@ class Suggestion(Plugin): else: if not movies or len(movies) == 0: - db = get_db() - active_movies = db.run('media', 'with_status', ['active', 'done']) + active_movies = fireEvent('media.with_status', ['active', 'done'], single = True) movies = [getIdentifier(x) for x in active_movies] if not ignored or len(ignored) == 0: @@ -86,7 +85,7 @@ class Suggestion(Plugin): # Get new results and add them if len(new_suggestions) - 1 < limit: db = get_db() - active_movies = db.run('media', 'with_status', ['active', 'done']) + active_movies = fireEvent('media.with_status', ['active', 'done'], single = True) movies = [getIdentifier(x) for x in active_movies] movies.extend(seen) diff --git a/couchpotato/core/plugins/dashboard.py b/couchpotato/core/plugins/dashboard.py index 57cd7af..fad68b0 100644 --- a/couchpotato/core/plugins/dashboard.py +++ b/couchpotato/core/plugins/dashboard.py @@ -45,7 +45,7 @@ class Dashboard(Plugin): limit = tryInt(splt[0]) # Get all active medias - active_ids = [x['_id'] for x in db.run('media', 'with_status', 'active', with_doc = False)] + active_ids = [x['_id'] for x in fireEvent('media.with_status', 'active', with_doc = False, single = True)] medias = [] now_year = date.today().year diff --git a/couchpotato/core/plugins/profile/main.py b/couchpotato/core/plugins/profile/main.py index 8f838f4..5d15c11 100644 --- a/couchpotato/core/plugins/profile/main.py +++ b/couchpotato/core/plugins/profile/main.py @@ -2,7 +2,7 @@ import traceback from couchpotato import get_db, tryInt from couchpotato.api import addApiView -from couchpotato.core.event import addEvent +from couchpotato.core.event import addEvent, fireEvent from couchpotato.core.helpers.encoding import toUnicode from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin @@ -41,7 +41,7 @@ class ProfilePlugin(Plugin): # Get all active movies without profile try: db = get_db() - medias = db.run('media', 'with_status', ['active']) + medias = fireEvent('media.with_status', 'active', single = True) profile_ids = [x.get('_id') for x in self.all()] default_id = profile_ids[0] diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 40475a4..5320908 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -67,7 +67,7 @@ class Release(Plugin): db = get_db() # get movies last_edit more than a week ago - medias = db.run('media', 'with_status', ['done']) + medias = fireEvent('media.with_status', 'done', single = True) for media in medias: if media.get('last_edit', 0) > (now - week): From b4a3ac8081b97177a7d72e7514f9f260dc7daf9b Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 16:20:25 +0100 Subject: [PATCH 24/36] Remove get_session --- couchpotato/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/couchpotato/__init__.py b/couchpotato/__init__.py index ce034db..1946963 100644 --- a/couchpotato/__init__.py +++ b/couchpotato/__init__.py @@ -48,10 +48,6 @@ def addView(route, func, static = False): views[route] = func -def get_session(): - return None - - def get_db(): return Env.get('db') From b63f7b7e5d7a2cd501eaf870f5b4075d2909076e Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 16:21:49 +0100 Subject: [PATCH 25/36] Move with_status out of releases --- couchpotato/core/media/_base/media/main.py | 4 ++-- couchpotato/core/plugins/release/index.py | 8 -------- couchpotato/core/plugins/release/main.py | 11 +++++++++++ couchpotato/core/plugins/renamer.py | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index d1f2914..5a6fc79 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -189,7 +189,7 @@ class MediaPlugin(MediaBase): # Filter on release status if release_status and len(release_status) > 0: filter_by['release_status'] = set() - for release_status in fireEvent('media.with_status', release_status, with_doc = False, single = True): + for release_status in fireEvent('release.with_status', release_status, with_doc = False, single = True): filter_by['release_status'].add(release_status.get('media_id')) # Add search filters @@ -302,7 +302,7 @@ class MediaPlugin(MediaBase): # Filter on release status if release_status and len(release_status) > 0: filter_by['release_status'] = set() - for release_status in fireEvent('media.with_status', release_status, with_doc = False, single = True): + for release_status in fireEvent('release.with_status', release_status, with_doc = False, single = True): filter_by['release_status'].add(release_status.get('media_id')) # Filter by combining ids diff --git a/couchpotato/core/plugins/release/index.py b/couchpotato/core/plugins/release/index.py index ee76253..23c1576 100644 --- a/couchpotato/core/plugins/release/index.py +++ b/couchpotato/core/plugins/release/index.py @@ -22,14 +22,6 @@ class ReleaseIndex(TreeBasedIndex): for release in db.get_many('release', media_id, with_doc = True): yield release['doc'] - def run_with_status(self, db, status = [], with_doc = True): - - status = list(status if isinstance(status, (list, tuple)) else [status]) - - for s in status: - for ms in db.get_many('release_status', s, with_doc = with_doc): - yield ms['doc'] if with_doc else ms - class ReleaseStatusIndex(TreeBasedIndex): _version = 1 diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 5320908..3ebb93b 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -53,6 +53,7 @@ class Release(Plugin): addEvent('release.delete', self.delete) addEvent('release.clean', self.clean) addEvent('release.update_status', self.updateStatus) + addEvent('release.with_status', self.withStatus) # Clean releases that didn't have activity in the last week addEvent('app.load', self.cleanDone) @@ -422,3 +423,13 @@ class Release(Plugin): log.error('Failed: %s', traceback.format_exc()) return False + + def withStatus(self, status, with_doc = True): + + db = get_db() + + status = list(status if isinstance(status, (list, tuple)) else [status]) + + for s in status: + for ms in db.get_many('release_status', s, with_doc = with_doc): + yield ms['doc'] if with_doc else ms diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 4cfc987..b452648 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -834,7 +834,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) try: db = get_db() - rels = list(db.run('release', 'with_status', ['snatched', 'seeding', 'missing'])) + rels = list(fireEvent('release.with_status', ['snatched', 'seeding', 'missing'], single = True)) if not rels: #No releases found that need status checking From 269d779df703772737691688268a680ae3b7bb46 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 16:28:40 +0100 Subject: [PATCH 26/36] Move for_media out of release index --- couchpotato/core/media/_base/media/main.py | 6 +++--- couchpotato/core/media/movie/_base/main.py | 6 +++--- couchpotato/core/media/movie/providers/info/_modifier.py | 4 ++-- couchpotato/core/plugins/release/index.py | 4 ---- couchpotato/core/plugins/release/main.py | 10 +++++++++- couchpotato/core/plugins/renamer.py | 2 +- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 5a6fc79..be3faf4 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -134,7 +134,7 @@ class MediaPlugin(MediaBase): if media.get('category_id'): media['category'] = db.get('id', media.get('category_id')) - media['releases'] = list(db.run('release', 'for_media', media['_id'])) + media['releases'] = list(fireEvent('release.for_media', media['_id'], single = True)) return media @@ -352,7 +352,7 @@ class MediaPlugin(MediaBase): deleted = True else: - media_releases = list(db.run('release', 'for_media', media['_id'])) + media_releases = list(fireEvent('release.for_media', media['_id'], single = True)) total_releases = len(media_releases) total_deleted = 0 @@ -418,7 +418,7 @@ class MediaPlugin(MediaBase): move_to_wanted = True profile = db.get('id', m['profile_id']) - media_releases = list(db.run('release', 'for_media', m['_id'])) + media_releases = list(fireEvent('release.for_media', m['_id'], single = True)) for q_identifier in profile['qualities']: index = profile['qualities'].index(q_identifier) diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 499dba9..a783cd1 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -138,7 +138,7 @@ class MovieBase(MovieTypeBase): elif force_readd: # Clean snatched history - for release in db.run('release', 'for_media', m['_id']): + for release in fireEvent('release.for_media', m['_id'], single = True): if release.get('status') in ['downloaded', 'snatched', 'done']: if params.get('ignore_previous', False): release['status'] = 'ignored' @@ -164,7 +164,7 @@ class MovieBase(MovieTypeBase): fireEventAsync('movie.update_info', m['_id'], default_title = params.get('title'), on_complete = onComplete) # Remove releases - for rel in db.run('release', 'for_media', m['_id']): + for rel in fireEvent('release.for_media', m['_id'], single = True): if rel['status'] is 'available': db.delete(rel) @@ -215,7 +215,7 @@ class MovieBase(MovieTypeBase): m['category_id'] = cat_id if len(cat_id) > 0 else None # Remove releases - for rel in db.run('release', 'for_media', m['_id']): + for rel in fireEvent('release.for_media', m['_id'], single = True): if rel['status'] is 'available': db.delete(rel) diff --git a/couchpotato/core/media/movie/providers/info/_modifier.py b/couchpotato/core/media/movie/providers/info/_modifier.py index 131cc05..cea0f49 100644 --- a/couchpotato/core/media/movie/providers/info/_modifier.py +++ b/couchpotato/core/media/movie/providers/info/_modifier.py @@ -3,7 +3,7 @@ import traceback from CodernityDB.database import RecordNotFound from couchpotato import get_db -from couchpotato.core.event import addEvent +from couchpotato.core.event import addEvent, fireEvent from couchpotato.core.helpers.variable import mergeDicts, randomString from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin @@ -104,7 +104,7 @@ class MovieResultModifier(Plugin): if media.get('status') == 'active': temp['in_wanted'] = media - for release in db.run('release', 'for_media', media.get('_id')): + for release in fireEvent('release.for_media', media['_id'], single = True): if release.get('status') == 'done': if not temp['in_library']: temp['in_library'] = media diff --git a/couchpotato/core/plugins/release/index.py b/couchpotato/core/plugins/release/index.py index 23c1576..f509f48 100644 --- a/couchpotato/core/plugins/release/index.py +++ b/couchpotato/core/plugins/release/index.py @@ -18,10 +18,6 @@ class ReleaseIndex(TreeBasedIndex): if data.get('_t') == 'release' and data.get('media_id'): return data['media_id'], None - def run_for_media(self, db, media_id): - for release in db.get_many('release', media_id, with_doc = True): - yield release['doc'] - class ReleaseStatusIndex(TreeBasedIndex): _version = 1 diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 3ebb93b..a80dfc0 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -54,6 +54,7 @@ class Release(Plugin): addEvent('release.clean', self.clean) addEvent('release.update_status', self.updateStatus) addEvent('release.with_status', self.withStatus) + addEvent('release.for_media', self.forMedia) # Clean releases that didn't have activity in the last week addEvent('app.load', self.cleanDone) @@ -74,7 +75,7 @@ class Release(Plugin): if media.get('last_edit', 0) > (now - week): continue - for rel in db.run('release', 'for_media', media['_id']): + for rel in fireEvent('release.for_media', media['_id'], single = True): # Remove all available releases if rel['status'] in ['available']: @@ -433,3 +434,10 @@ class Release(Plugin): for s in status: for ms in db.get_many('release_status', s, with_doc = with_doc): yield ms['doc'] if with_doc else ms + + def forMedia(self, media_id): + + db = get_db() + + for release in db.get_many('release', media_id, with_doc = True): + yield release['doc'] diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index b452648..a259802 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -446,7 +446,7 @@ class Renamer(Plugin): log.error('Failed marking movie finished: %s', (traceback.format_exc())) # Go over current movie releases - for release in db.run('release', 'for_media', media['_id']): + for release in fireEvent('release.for_media', media['_id'], single = True): # When a release already exists if release.get('status') == 'done': From a818276b6d507395a7af0e1c253bbb2f04f91860 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 16:32:31 +0100 Subject: [PATCH 27/36] Move multi-identifier search out of index --- couchpotato/core/media/_base/media/index.py | 8 -------- couchpotato/core/media/_base/media/main.py | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/couchpotato/core/media/_base/media/index.py b/couchpotato/core/media/_base/media/index.py index 4733ffa..42e6990 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -30,14 +30,6 @@ class MediaIndex(MultiTreeBasedIndex): return ids, None - def run_identifiers(self, db, identifiers, with_doc = False): - for x in identifiers: - try: - media = db.get('media', '%s-%s' % (x, identifiers[x]), with_doc = with_doc) - return media - except: - pass - class MediaStatusIndex(TreeBasedIndex): _version = 1 diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index be3faf4..f6bcd71 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -75,6 +75,7 @@ class MediaPlugin(MediaBase): addEvent('media.get', self.get) addEvent('media.with_status', self.withStatus) + addEvent('media.with_identifiers', self.withIdentifiers) addEvent('media.list', self.list) addEvent('media.delete', self.delete) addEvent('media.restatus', self.restatus) @@ -157,6 +158,19 @@ class MediaPlugin(MediaBase): for ms in db.get_many('media_status', s, with_doc = with_doc): yield ms['doc'] if with_doc else ms + def withIdentifiers(self, identifiers, with_doc = False): + + db = get_db() + + for x in identifiers: + try: + media = db.get('media', '%s-%s' % (x, identifiers[x]), with_doc = with_doc) + return media + except: + pass + + log.error('No media found with identifiers: %s', identifiers) + def list(self, types = None, status = None, release_status = None, status_or = False, limit_offset = None, starts_with = None, search = None): db = get_db() From e12dcc2fb8116c5afe5d603afd46e790a2b2ca36 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 16:37:35 +0100 Subject: [PATCH 28/36] Also return releases on notify frontend --- couchpotato/core/media/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/couchpotato/core/media/__init__.py b/couchpotato/core/media/__init__.py index 4799766..8e704de 100644 --- a/couchpotato/core/media/__init__.py +++ b/couchpotato/core/media/__init__.py @@ -38,8 +38,7 @@ class MediaBase(Plugin): def notifyFront(): try: - db = get_db() - media = db.get('id', media_id) + media = fireEvent('media.get', media_id, single = True) event_name = '%s.update' % media.get('type') fireEvent('notify.frontend', type = event_name, data = media) From b4610e5c23bfde12add9f9947fac900aa9501ef5 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 17:34:24 +0100 Subject: [PATCH 29/36] Make sure to make release download id lowercase --- couchpotato/core/plugins/release/index.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/plugins/release/index.py b/couchpotato/core/plugins/release/index.py index f509f48..8265fe3 100644 --- a/couchpotato/core/plugins/release/index.py +++ b/couchpotato/core/plugins/release/index.py @@ -50,15 +50,15 @@ class ReleaseIDIndex(HashIndex): class ReleaseDownloadIndex(HashIndex): - _version = 1 + _version = 2 def __init__(self, *args, **kwargs): kwargs['key_format'] = '32s' super(ReleaseDownloadIndex, self).__init__(*args, **kwargs) def make_key(self, key): - return md5(key).hexdigest() + return md5(key.lower()).hexdigest() def make_key_value(self, data): if data.get('_t') == 'release' and data.get('download_info') and data['download_info']['id'] and data['download_info']['downloader']: - return md5('%s-%s' % (data['download_info']['downloader'], data['download_info']['id'])).hexdigest(), None + return md5(('%s-%s' % (data['download_info']['downloader'], data['download_info']['id'])).lower()).hexdigest(), None From ad94cce283c43b20a16c3b88cdb20132406d15d7 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 17:35:26 +0100 Subject: [PATCH 30/36] Make release files normal list --- couchpotato/core/downloaders/deluge.py | 2 +- couchpotato/core/downloaders/qbittorrent_.py | 2 +- couchpotato/core/downloaders/rtorrent_.py | 2 +- couchpotato/core/downloaders/transmission.py | 2 +- couchpotato/core/downloaders/utorrent.py | 2 +- couchpotato/core/plugins/renamer.py | 39 ++++++++++++++++------------ 6 files changed, 28 insertions(+), 21 deletions(-) diff --git a/couchpotato/core/downloaders/deluge.py b/couchpotato/core/downloaders/deluge.py index 2a386ad..26592ca 100644 --- a/couchpotato/core/downloaders/deluge.py +++ b/couchpotato/core/downloaders/deluge.py @@ -147,7 +147,7 @@ class Deluge(Downloader): 'seed_ratio': torrent['ratio'], 'timeleft': str(timedelta(seconds = torrent['eta'])), 'folder': sp(download_dir if len(torrent_files) == 1 else os.path.join(download_dir, torrent['name'])), - 'files': '|'.join(torrent_files), + 'files': torrent_files, }) return release_downloads diff --git a/couchpotato/core/downloaders/qbittorrent_.py b/couchpotato/core/downloaders/qbittorrent_.py index 349af17..558222d 100644 --- a/couchpotato/core/downloaders/qbittorrent_.py +++ b/couchpotato/core/downloaders/qbittorrent_.py @@ -135,7 +135,7 @@ class qBittorrent(Downloader): 'original_status': torrent.state, 'timeleft': torrent.progress * 100 if torrent.progress else -1, # percentage 'folder': sp(torrent.save_path), - 'files': '|'.join(torrent_files) + 'files': torrent_files }) return release_downloads diff --git a/couchpotato/core/downloaders/rtorrent_.py b/couchpotato/core/downloaders/rtorrent_.py index 6e5c4b6..98946b2 100644 --- a/couchpotato/core/downloaders/rtorrent_.py +++ b/couchpotato/core/downloaders/rtorrent_.py @@ -245,7 +245,7 @@ class rTorrent(Downloader): 'original_status': torrent.state, 'timeleft': str(timedelta(seconds = float(torrent.left_bytes) / torrent.down_rate)) if torrent.down_rate > 0 else -1, 'folder': sp(torrent.directory), - 'files': '|'.join(torrent_files) + 'files': torrent_files }) return release_downloads diff --git a/couchpotato/core/downloaders/transmission.py b/couchpotato/core/downloaders/transmission.py index f49cb9d..dd11166 100644 --- a/couchpotato/core/downloaders/transmission.py +++ b/couchpotato/core/downloaders/transmission.py @@ -141,7 +141,7 @@ class Transmission(Downloader): 'seed_ratio': torrent['uploadRatio'], 'timeleft': str(timedelta(seconds = torrent['eta'])), 'folder': sp(torrent_folder if len(torrent_files) == 1 else os.path.join(torrent_folder, torrent['name'])), - 'files': '|'.join(torrent_files) + 'files': torrent_files }) return release_downloads diff --git a/couchpotato/core/downloaders/utorrent.py b/couchpotato/core/downloaders/utorrent.py index dae8950..671dd9e 100644 --- a/couchpotato/core/downloaders/utorrent.py +++ b/couchpotato/core/downloaders/utorrent.py @@ -184,7 +184,7 @@ class uTorrent(Downloader): 'original_status': torrent[1], 'timeleft': str(timedelta(seconds = torrent[10])), 'folder': sp(torrent[26]), - 'files': '|'.join(torrent_files) + 'files': torrent_files }) return release_downloads diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index a259802..4726734 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -79,16 +79,22 @@ class Renamer(Plugin): downloader = kwargs.get('downloader') download_id = kwargs.get('download_id') - files = '|'.join([sp(filename) for filename in splitString(kwargs.get('files'), '|')]) + files = [sp(filename) for filename in splitString(kwargs.get('files'), '|')] status = kwargs.get('status', 'completed') release_download = None if not base_folder and media_folder: release_download = {'folder': media_folder} - release_download.update({'id': download_id, 'downloader': downloader, 'status': status, 'files': files} if download_id else {}) - fire_handle = fireEvent if not async else fireEventAsync + if download_id: + release_download.update({ + 'id': download_id, + 'downloader': downloader, + 'status': status, + 'files': files + }) + fire_handle = fireEvent if not async else fireEventAsync fire_handle('renamer.scan', base_folder = base_folder, release_download = release_download) return { @@ -142,7 +148,7 @@ class Renamer(Plugin): log.debug('The provided media folder %s does not exist. Trying to find it in the \'from\' folder.', media_folder) # Update to the from folder - if len(splitString(release_download.get('files'), '|')) == 1: + if len(release_download.get('files'), []) == 1: new_media_folder = from_folder else: new_media_folder = os.path.join(from_folder, os.path.basename(media_folder)) @@ -152,7 +158,7 @@ class Renamer(Plugin): return # Update the files - new_files = [os.path.join(new_media_folder, os.path.relpath(filename, media_folder)) for filename in splitString(release_download.get('files'), '|')] + new_files = [os.path.join(new_media_folder, os.path.relpath(filename, media_folder)) for filename in release_download.get('files', [])] if new_files and not os.path.isfile(new_files[0]): log.error('The provided media folder %s does not exist and its files could also not be found in the \'from\' folder.', media_folder) return @@ -160,7 +166,7 @@ class Renamer(Plugin): # Update release_download info to the from folder log.debug('Release %s found in the \'from\' folder.', media_folder) release_download['folder'] = new_media_folder - release_download['files'] = '|'.join(new_files) + release_download['files'] = new_files media_folder = new_media_folder if media_folder: @@ -182,11 +188,10 @@ class Renamer(Plugin): log.info('Scanning media folder %s...', media_folder) folder = os.path.dirname(media_folder) - if release_download.get('files', ''): - files = splitString(release_download['files'], '|') - + release_files = release_download.get('files', []) + if release_files: # If there is only one file in the torrent, the downloader did not create a subfolder - if len(files) == 1: + if len(release_files) == 1: folder = media_folder else: # Get all files from the specified folder @@ -643,8 +648,8 @@ Remove it if you want it to be renamed (again, or at least let it try again) elif isinstance(release_download, dict): # Tag download_files if they are known - if release_download['files']: - tag_files = splitString(release_download['files'], '|') + if release_download.get('files', []): + tag_files = release_download.get('files', []) # Tag all files in release folder else: @@ -678,8 +683,8 @@ Remove it if you want it to be renamed (again, or at least let it try again) elif isinstance(release_download, dict): # Untag download_files if they are known - if release_download['files']: - tag_files = splitString(release_download['files'], '|') + if release_download.get('files'): + tag_files = release_download.get('files', []) # Untag all files in release folder else: @@ -719,8 +724,8 @@ Remove it if you want it to be renamed (again, or at least let it try again) ignore_files = [] # Find tag on download_files if they are known - if release_download['files']: - tag_files = splitString(release_download['files'], '|') + if release_download.get('files'): + tag_files = release_download.get('files', []) # Find tag on all files in release folder else: @@ -1040,6 +1045,8 @@ Remove it if you want it to be renamed (again, or at least let it try again) except: log.error('Download ID %s from downloader %s not found in releases', (release_download.get('id'), release_download.get('downloader'))) + print rls + if rls: media = db.get('id', rls['media_id']) release_download.update({ From 78e2ff4870b0a270b1488e51d5159c0277203b6c Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 18:01:52 +0100 Subject: [PATCH 31/36] Cleanup --- couchpotato/core/downloaders/base.py | 2 +- couchpotato/core/plugins/renamer.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/downloaders/base.py b/couchpotato/core/downloaders/base.py index 269bdc6..8042c4a 100644 --- a/couchpotato/core/downloaders/base.py +++ b/couchpotato/core/downloaders/base.py @@ -210,7 +210,7 @@ class ReleaseDownloadList(list): 'status': 'busy', 'downloader': self.provider.getName(), 'folder': '', - 'files': '', + 'files': [], } return mergeDicts(defaults, result) diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 4726734..f3b22c9 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -911,7 +911,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) found_release = True break else: - if release_download['name'] == nzbname or rel['info']['name'] in release_download['name'] or getImdb(release_download['name']) == movie_dict['identifier']: + if release_download['name'] == nzbname or rel['info']['name'] in release_download['name'] or getImdb(release_download['name']) == getIdentifier(movie_dict): log.debug('Found release by release name or imdb ID: %s', release_download['name']) found_release = True break @@ -1045,8 +1045,6 @@ Remove it if you want it to be renamed (again, or at least let it try again) except: log.error('Download ID %s from downloader %s not found in releases', (release_download.get('id'), release_download.get('downloader'))) - print rls - if rls: media = db.get('id', rls['media_id']) release_download.update({ From 25b1d86c5059cb82479b7452413a404e1d30beb8 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 18:10:32 +0100 Subject: [PATCH 32/36] get identifier in awesomehd --- couchpotato/core/media/_base/providers/torrent/awesomehd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/_base/providers/torrent/awesomehd.py b/couchpotato/core/media/_base/providers/torrent/awesomehd.py index bf10456..1372f6c 100644 --- a/couchpotato/core/media/_base/providers/torrent/awesomehd.py +++ b/couchpotato/core/media/_base/providers/torrent/awesomehd.py @@ -2,7 +2,7 @@ import re import traceback from bs4 import BeautifulSoup -from couchpotato.core.helpers.variable import tryInt +from couchpotato.core.helpers.variable import tryInt, getIdentifier from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.base import TorrentProvider @@ -22,7 +22,7 @@ class Base(TorrentProvider): def _search(self, movie, quality, results): - data = self.getHTMLData(self.urls['search'] % (self.conf('passkey'), movie['identifier'], self.conf('only_internal'))) + data = self.getHTMLData(self.urls['search'] % (self.conf('passkey'), getIdentifier(movie), self.conf('only_internal'))) if data: try: From 334078fc34cda83168a5ea6457b6c91f49873b11 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 18:25:36 +0100 Subject: [PATCH 33/36] Allow password tag in returned release dict --- couchpotato/core/plugins/base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index 1e4bfeb..c5892f5 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -326,6 +326,8 @@ class Plugin(object): if name_password: release_name, password = name_password tag += '{{%s}}' % password + elif data.get('password'): + tag += '{{%s}}' % data.get('password') max_length = 127 - len(tag) # Some filesystems don't support 128+ long filenames return '%s%s' % (toSafeString(toUnicode(release_name)[:max_length]), tag) From caf4eab104685baee155c8a62b32a4309ecda76e Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 18:34:58 +0100 Subject: [PATCH 34/36] Get correct size from HDBits api. fix #2997 --- couchpotato/core/media/_base/providers/torrent/hdbits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/media/_base/providers/torrent/hdbits.py b/couchpotato/core/media/_base/providers/torrent/hdbits.py index fa45b83..c2e85ac 100644 --- a/couchpotato/core/media/_base/providers/torrent/hdbits.py +++ b/couchpotato/core/media/_base/providers/torrent/hdbits.py @@ -56,7 +56,7 @@ class Base(TorrentProvider): 'name': result['name'], 'url': self.urls['download'] % (result['id'], self.conf('passkey')), 'detail_url': self.urls['detail'] % result['id'], - 'size': self.parseSize(result['size']), + 'size': tryInt(result['size'])/1024/1024, 'seeders': tryInt(result['seeders']), 'leechers': tryInt(result['leechers']) }) From 1f647b3cc79143898e23a3b83db22eb7a42d3711 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 18:46:01 +0100 Subject: [PATCH 35/36] Autoload missing for notifications. fix #2980 --- couchpotato/core/notifications/boxcar.py | 2 ++ couchpotato/core/notifications/email_.py | 2 ++ couchpotato/core/notifications/growl.py | 2 ++ couchpotato/core/notifications/nmj.py | 2 ++ couchpotato/core/notifications/notifymyandroid.py | 2 ++ couchpotato/core/notifications/notifymywp.py | 2 ++ couchpotato/core/notifications/prowl.py | 2 ++ couchpotato/core/notifications/pushalot.py | 2 ++ couchpotato/core/notifications/pushbullet.py | 2 ++ 9 files changed, 18 insertions(+) diff --git a/couchpotato/core/notifications/boxcar.py b/couchpotato/core/notifications/boxcar.py index 3777a42..a7acc88 100644 --- a/couchpotato/core/notifications/boxcar.py +++ b/couchpotato/core/notifications/boxcar.py @@ -7,6 +7,8 @@ from couchpotato.core.notifications.base import Notification log = CPLog(__name__) +autoload = 'Boxcar' + class Boxcar(Notification): diff --git a/couchpotato/core/notifications/email_.py b/couchpotato/core/notifications/email_.py index b42650b..938a361 100644 --- a/couchpotato/core/notifications/email_.py +++ b/couchpotato/core/notifications/email_.py @@ -12,6 +12,8 @@ from couchpotato.environment import Env log = CPLog(__name__) +autoload = 'Email' + class Email(Notification): diff --git a/couchpotato/core/notifications/growl.py b/couchpotato/core/notifications/growl.py index c7847da..160e383 100644 --- a/couchpotato/core/notifications/growl.py +++ b/couchpotato/core/notifications/growl.py @@ -9,6 +9,8 @@ from gntp import notifier log = CPLog(__name__) +autoload = 'Growl' + class Growl(Notification): diff --git a/couchpotato/core/notifications/nmj.py b/couchpotato/core/notifications/nmj.py index 6ef70d4..4b9b92b 100644 --- a/couchpotato/core/notifications/nmj.py +++ b/couchpotato/core/notifications/nmj.py @@ -15,6 +15,8 @@ except ImportError: log = CPLog(__name__) +autoload = 'NMJ' + class NMJ(Notification): diff --git a/couchpotato/core/notifications/notifymyandroid.py b/couchpotato/core/notifications/notifymyandroid.py index 8b08360..ed7a24c 100644 --- a/couchpotato/core/notifications/notifymyandroid.py +++ b/couchpotato/core/notifications/notifymyandroid.py @@ -6,6 +6,8 @@ import six log = CPLog(__name__) +autoload = 'NotifyMyAndroid' + class NotifyMyAndroid(Notification): diff --git a/couchpotato/core/notifications/notifymywp.py b/couchpotato/core/notifications/notifymywp.py index 914897f..262fd8d 100644 --- a/couchpotato/core/notifications/notifymywp.py +++ b/couchpotato/core/notifications/notifymywp.py @@ -6,6 +6,8 @@ import six log = CPLog(__name__) +autoload = 'NotifyMyWP' + class NotifyMyWP(Notification): diff --git a/couchpotato/core/notifications/prowl.py b/couchpotato/core/notifications/prowl.py index b276d7f..fdece32 100644 --- a/couchpotato/core/notifications/prowl.py +++ b/couchpotato/core/notifications/prowl.py @@ -7,6 +7,8 @@ from couchpotato.core.notifications.base import Notification log = CPLog(__name__) +autoload = 'Prowl' + class Prowl(Notification): diff --git a/couchpotato/core/notifications/pushalot.py b/couchpotato/core/notifications/pushalot.py index 0ce9027..f8fa187 100644 --- a/couchpotato/core/notifications/pushalot.py +++ b/couchpotato/core/notifications/pushalot.py @@ -7,6 +7,8 @@ from couchpotato.core.notifications.base import Notification log = CPLog(__name__) +autoload = 'Pushalot' + class Pushalot(Notification): diff --git a/couchpotato/core/notifications/pushbullet.py b/couchpotato/core/notifications/pushbullet.py index fd1a376..56cf228 100644 --- a/couchpotato/core/notifications/pushbullet.py +++ b/couchpotato/core/notifications/pushbullet.py @@ -9,6 +9,8 @@ from couchpotato.core.notifications.base import Notification log = CPLog(__name__) +autoload = 'Pushbullet' + class Pushbullet(Notification): From f50852fee03f65c1895115c3db60ffe495d86202 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 21 Mar 2014 18:52:11 +0100 Subject: [PATCH 36/36] Get proper iTunes namespace. fix #2978 --- couchpotato/core/media/movie/providers/automation/itunes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/media/movie/providers/automation/itunes.py b/couchpotato/core/media/movie/providers/automation/itunes.py index bb6eef2..fcb20b1 100644 --- a/couchpotato/core/media/movie/providers/automation/itunes.py +++ b/couchpotato/core/media/movie/providers/automation/itunes.py @@ -26,7 +26,7 @@ class ITunes(Automation, RSS): urls = splitString(self.conf('automation_urls')) namespace = 'http://www.w3.org/2005/Atom' - namespace_im = 'https://rss.itunes.apple.com' + namespace_im = 'http://itunes.apple.com/rss' index = -1 for url in urls: