diff --git a/couchpotato/api.py b/couchpotato/api.py index 029ebce2..7020fd93 100644 --- a/couchpotato/api.py +++ b/couchpotato/api.py @@ -12,27 +12,28 @@ api_docs_missing = [] # NonBlock API handler class NonBlockHandler(RequestHandler): - stoppers = [] + stopper = None @asynchronous def get(self, route, *args, **kwargs): route = route.strip('/') start, stop = api_nonblock[route] - self.stoppers.append(stop) + self.stopper = stop - start(self.onNewMessage, last_id = self.get_argument("last_id", None)) + start(self.onNewMessage, last_id = self.get_argument('last_id', None)) def onNewMessage(self, response): if self.request.connection.stream.closed(): return + self.finish(response) def on_connection_close(self): - for stop in self.stoppers: - stop(self.onNewMessage) + if self.stopper: + self.stopper(self.onNewMessage) - self.stoppers = [] + self.stopper = None def addNonBlockApiView(route, func_tuple, docs = None, **kwargs): api_nonblock[route] = func_tuple diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index c90cd2db..ef9d4efa 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -33,7 +33,7 @@ class NZBGet(Downloader): rpc = xmlrpclib.ServerProxy(url) try: if rpc.writelog('INFO', 'CouchPotato connected to drop off %s.' % nzb_name): - log.info('Successfully connected to NZBGet') + log.debug('Successfully connected to NZBGet') else: log.info('Successfully connected to NZBGet, but unable to send a message') except socket.error: @@ -74,7 +74,7 @@ class NZBGet(Downloader): rpc = xmlrpclib.ServerProxy(url) try: if rpc.writelog('INFO', 'CouchPotato connected to check status'): - log.info('Successfully connected to NZBGet') + log.debug('Successfully connected to NZBGet') else: log.info('Successfully connected to NZBGet, but unable to send a message') except socket.error: @@ -152,12 +152,12 @@ class NZBGet(Downloader): log.info('%s failed downloading, deleting...', item['name']) - url = self.url % {'host': self.conf('host'), 'password': self.conf('password')} + url = self.url % {'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')} rpc = xmlrpclib.ServerProxy(url) try: if rpc.writelog('INFO', 'CouchPotato connected to delete some history'): - log.info('Successfully connected to NZBGet') + log.debug('Successfully connected to NZBGet') else: log.info('Successfully connected to NZBGet, but unable to send a message') except socket.error: diff --git a/couchpotato/core/helpers/encoding.py b/couchpotato/core/helpers/encoding.py index a11dd88b..9b753db6 100644 --- a/couchpotato/core/helpers/encoding.py +++ b/couchpotato/core/helpers/encoding.py @@ -11,7 +11,8 @@ log = CPLog(__name__) def toSafeString(original): valid_chars = "-_.() %s%s" % (ascii_letters, digits) cleanedFilename = unicodedata.normalize('NFKD', toUnicode(original)).encode('ASCII', 'ignore') - return ''.join(c for c in cleanedFilename if c in valid_chars) + valid_string = ''.join(c for c in cleanedFilename if c in valid_chars) + return ' '.join(valid_string.split()) def simplifyString(original): string = stripAccents(original.lower()) diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index fa8a8b51..381889c0 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -176,6 +176,10 @@ def possibleTitles(raw_title): titles.append(raw_title.lower()) titles.append(simplifyString(raw_title)) + # replace some chars + new_title = raw_title.replace('&', 'and') + titles.append(simplifyString(new_title)) + return list(set(titles)) def randomString(size = 8, chars = string.ascii_uppercase + string.digits): diff --git a/couchpotato/core/loader.py b/couchpotato/core/loader.py index a97437a2..0f49700a 100644 --- a/couchpotato/core/loader.py +++ b/couchpotato/core/loader.py @@ -28,7 +28,7 @@ class Loader(object): provider_dir = os.path.join(root, 'couchpotato', 'core', 'providers') for provider in os.listdir(provider_dir): path = os.path.join(provider_dir, provider) - if os.path.isdir(path): + if os.path.isdir(path) and provider[:2] != '__': self.paths[provider + '_provider'] = (25, 'couchpotato.core.providers.' + provider, path) @@ -43,6 +43,9 @@ class Loader(object): for module_name, plugin in sorted(self.modules[priority].iteritems()): # Load module try: + if plugin.get('name')[:2] == '__': + continue + m = getattr(self.loadModule(module_name), plugin.get('name')) log.info('Loading %s: %s', (plugin['type'], plugin['name'])) diff --git a/couchpotato/core/notifications/core/main.py b/couchpotato/core/notifications/core/main.py index b6c07f58..a6ce2a63 100644 --- a/couchpotato/core/notifications/core/main.py +++ b/couchpotato/core/notifications/core/main.py @@ -7,6 +7,7 @@ from couchpotato.core.logger import CPLog from couchpotato.core.notifications.base import Notification from couchpotato.core.settings.model import Notification as Notif from couchpotato.environment import Env +from operator import itemgetter from sqlalchemy.sql.expression import or_ import threading import time @@ -19,8 +20,6 @@ log = CPLog(__name__) class CoreNotifier(Notification): m_lock = threading.Lock() - messages = [] - listeners = [] def __init__(self): super(CoreNotifier, self).__init__() @@ -51,10 +50,14 @@ class CoreNotifier(Notification): addApiView('notification.listener', self.listener) fireEvent('schedule.interval', 'core.check_messages', self.checkMessages, hours = 12, single = True) + fireEvent('schedule.interval', 'core.clean_messages', self.cleanMessages, seconds = 15, single = True) addEvent('app.load', self.clean) addEvent('app.load', self.checkMessages) + self.messages = [] + self.listeners = [] + def clean(self): db = get_session() @@ -169,8 +172,8 @@ class CoreNotifier(Notification): except: log.debug('Failed sending to listener: %s', traceback.format_exc()) + self.listeners = [] self.m_lock.release() - self.cleanMessages() log.debug('Done notifying frontend') @@ -199,12 +202,14 @@ class CoreNotifier(Notification): def cleanMessages(self): + if len(self.messages) == 0: + return + log.debug('Cleaning messages') self.m_lock.acquire() - for message in self.messages: - if message['time'] < (time.time() - 15): - self.messages.remove(message) + time_ago = (time.time() - 15) + self.messages[:] = [m for m in self.messages if (m['time'] > time_ago)] self.m_lock.release() log.debug('Done cleaning messages') @@ -215,16 +220,16 @@ class CoreNotifier(Notification): self.m_lock.acquire() recent = [] - index = 0 - for i in xrange(len(self.messages)): - index = len(self.messages) - i - 1 - if self.messages[index]["message_id"] == last_id: break - recent = self.messages[index:] + try: + index = map(itemgetter('message_id'), self.messages).index(last_id) + recent = self.messages[index+1:] + except: + pass self.m_lock.release() - log.debug('Returning for %s %s messages', (last_id, len(recent or []))) + log.debug('Returning for %s %s messages', (last_id, len(recent))) - return recent or [] + return recent def listener(self, init = False, **kwargs): @@ -237,6 +242,7 @@ class CoreNotifier(Notification): notifications = db.query(Notif) \ .filter(or_(Notif.read == False, Notif.added > (time.time() - 259200))) \ .all() + for n in notifications: ndict = n.to_dict() ndict['type'] = 'notification' diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index b1034a53..67c7f00d 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -22,7 +22,7 @@ class QualityPlugin(Plugin): {'identifier': 'brrip', 'hd': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p', '1080p'], 'ext':['avi'], 'tags': ['hdtv', 'hdrip', 'webdl', ('web', 'dl')]}, {'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': [], 'allow': [], 'ext':['iso', 'img'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts']}, {'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'width': 720, 'alternative': [], 'allow': [], 'ext':['avi', 'mpg', 'mpeg'], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]}, - {'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip', 'dvdscreener'], 'allow': ['dvdr', 'dvd'], 'ext':['avi', 'mpg', 'mpeg'], 'tags': ['webrip', ('web', 'rip')]}, + {'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip', 'dvdscreener', 'hdscr'], 'allow': ['dvdr', 'dvd'], 'ext':['avi', 'mpg', 'mpeg'], 'tags': ['webrip', ('web', 'rip')]}, {'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': ['r6'], 'allow': ['dvdr'], 'ext':['avi', 'mpg', 'mpeg']}, {'identifier': 'tc', 'size': (600, 1000), 'label': 'TeleCine', 'alternative': ['telecine'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}, {'identifier': 'ts', 'size': (600, 1000), 'label': 'TeleSync', 'alternative': ['telesync', 'hdts'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}, diff --git a/couchpotato/core/plugins/score/scores.py b/couchpotato/core/plugins/score/scores.py index 4d966eb2..a95b0a42 100644 --- a/couchpotato/core/plugins/score/scores.py +++ b/couchpotato/core/plugins/score/scores.py @@ -68,9 +68,12 @@ def namePositionScore(nzb_name, movie_name): name_year = fireEvent('scanner.name_year', nzb_name, single = True) # Give points for movies beginning with the correct name - name_split = simplifyString(nzb_name).split(simplifyString(movie_name)) - if name_split[0].strip() == '': - score += 10 + split_by = simplifyString(movie_name) + name_split = [] + if len(split_by) > 0: + name_split = simplifyString(nzb_name).split(split_by) + if name_split[0].strip() == '': + score += 10 # If year is second in line, give more points if len(name_split) > 1 and name_year: diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index dfb6ccba..b55e7201 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -195,7 +195,7 @@ class Searcher(Plugin): download_preference = self.conf('preferred_method') if download_preference != 'both': - sorted_results = sorted(sorted_results, key = lambda k: k['type'], reverse = (download_preference == 'torrent')) + sorted_results = sorted(sorted_results, key = lambda k: k['type'][:3], reverse = (download_preference == 'torrent')) # Check if movie isn't deleted while searching if not db.query(Movie).filter_by(id = movie.get('id')).first(): diff --git a/couchpotato/core/providers/automation/itunes/main.py b/couchpotato/core/providers/automation/itunes/main.py index 14ca2a82..8e352370 100644 --- a/couchpotato/core/providers/automation/itunes/main.py +++ b/couchpotato/core/providers/automation/itunes/main.py @@ -31,7 +31,7 @@ class ITunes(Automation, RSS): for url in urls: index += 1 - if not enablers[index]: + if len(enablers) == 0 or len(enablers) < index or not enablers[index]: continue try: