From cbecb7430783501b446af94e0cab7496581e7104 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 14 Jun 2014 18:57:27 +0200 Subject: [PATCH 01/20] Show ETA on soon list. fix #2702 --- .../core/media/movie/_base/static/movie.css | 26 +++++++++++++++++++ .../core/media/movie/_base/static/movie.js | 19 ++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/couchpotato/core/media/movie/_base/static/movie.css b/couchpotato/core/media/movie/_base/static/movie.css index 52f503c3..311b111d 100644 --- a/couchpotato/core/media/movie/_base/static/movie.css +++ b/couchpotato/core/media/movie/_base/static/movie.css @@ -365,6 +365,32 @@ display: none; } + .movies .data .eta { + display: none; + } + + .movies.details_list .data .eta { + position: absolute; + bottom: 0; + right: 0; + display: block; + min-height: 20px; + text-align: right; + font-style: italic; + opacity: .8; + font-size: 11px; + } + + .movies.details_list .movie:hover .data .eta { + display: none; + } + + .movies.thumbs_list .data .eta { + display: block; + position: absolute; + bottom: 40px; + } + .movies .data .quality { position: absolute; bottom: 2px; diff --git a/couchpotato/core/media/movie/_base/static/movie.js b/couchpotato/core/media/movie/_base/static/movie.js index 679bbc2c..47880089 100644 --- a/couchpotato/core/media/movie/_base/static/movie.js +++ b/couchpotato/core/media/movie/_base/static/movie.js @@ -136,6 +136,21 @@ var Movie = new Class({ self.el.addClass('status_'+self.get('status')); + var eta = null, + eta_date = null, + now = Math.round(+new Date()/1000); + + if(self.data.info.release_date) + [self.data.info.release_date.dvd, self.data.info.release_date.theater].each(function(timestamp){ + if (timestamp > 0 && (eta == null || Math.abs(timestamp - now) < Math.abs(eta - now))) + eta = timestamp; + }); + + if(eta){ + eta_date = new Date(eta * 1000); + eta_date = eta_date.toLocaleString('en-us', { month: "long" }) + ' ' + eta_date.getFullYear(); + } + self.el.adopt( self.select_checkbox = new Element('input[type=checkbox].inlay', { 'events': { @@ -161,6 +176,10 @@ var Movie = new Class({ self.description = new Element('div.description.tiny_scroll', { 'text': self.data.info.plot }), + self.eta = eta_date && (now+8035200 > eta) ? new Element('div.eta', { + 'text': eta_date, + 'title': 'ETA' + }) : null, self.quality = new Element('div.quality', { 'events': { 'click': function(e){ From 9dd9f850c6a27498e3c18a48107bf28584cd3bc4 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 14 Jun 2014 18:59:52 +0200 Subject: [PATCH 02/20] Treat seeding as "done" --- couchpotato/static/scripts/page/home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/static/scripts/page/home.js b/couchpotato/static/scripts/page/home.js index 7cde7d2a..aff8fbb3 100644 --- a/couchpotato/static/scripts/page/home.js +++ b/couchpotato/static/scripts/page/home.js @@ -54,7 +54,7 @@ Page.Home = new Class({ }) ), 'filter': { - 'release_status': 'snatched,seeding,missing,available,downloaded' + 'release_status': 'snatched,missing,available,downloaded' }, 'limit': null, 'onLoaded': function(){ From 58bd9cd7a1af2ff01d3657618d92a7f32e2a98ec Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 15 Jun 2014 14:59:02 +0200 Subject: [PATCH 03/20] Unable to hide & reorder profiles. fix #3437 --- couchpotato/core/plugins/quality/static/quality.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/couchpotato/core/plugins/quality/static/quality.js b/couchpotato/core/plugins/quality/static/quality.js index 29324c22..d233b1ce 100644 --- a/couchpotato/core/plugins/quality/static/quality.js +++ b/couchpotato/core/plugins/quality/static/quality.js @@ -8,6 +8,7 @@ var QualityBase = new Class({ self.qualities = data.qualities; + self.profiles_list = null; self.profiles = []; Array.each(data.profiles, self.createProfilesClass.bind(self)); @@ -35,7 +36,7 @@ var QualityBase = new Class({ }).pick(); } catch(e){} - + return {} }, @@ -106,14 +107,13 @@ var QualityBase = new Class({ createProfileOrdering: function(){ var self = this; - var profile_list; self.settings.createGroup({ 'label': 'Profile Defaults', 'description': '(Needs refresh \'' +(App.isMac() ? 'CMD+R' : 'F5')+ '\' after editing)' }).adopt( new Element('.ctrlHolder#profile_ordering').adopt( new Element('label[text=Order]'), - profile_list = new Element('ul'), + self.profiles_list = new Element('ul'), new Element('p.formHint', { 'html': 'Change the order the profiles are in the dropdown list. Uncheck to hide it completely.
First one will be default.' }) @@ -133,7 +133,7 @@ var QualityBase = new Class({ 'text': profile.data.label }), new Element('span.handle') - ).inject(profile_list); + ).inject(self.profiles_list); new Form.Check(check); @@ -141,7 +141,7 @@ var QualityBase = new Class({ // Sortable var sorted_changed = false; - self.profile_sortable = new Sortables(profile_list, { + self.profile_sortable = new Sortables(self.profiles_list, { 'revert': true, 'handle': '.handle', 'opacity': 0.5, @@ -163,7 +163,7 @@ var QualityBase = new Class({ ids = [], hidden = []; - self.profile_sortable.list.getElements('li').each(function(el, nr){ + self.profiles_list.getElements('li').each(function(el, nr){ ids.include(el.get('data-id')); hidden[nr] = +!el.getElement('input[type=checkbox]').get('checked'); }); From a196a499ae0ec48fe22fdba81bb54af46a13d09e Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 15 Jun 2014 22:13:01 +0200 Subject: [PATCH 04/20] Only cache qualities if list length is correct --- couchpotato/core/plugins/quality/main.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index 63049243..677ee48f 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -95,15 +95,14 @@ class QualityPlugin(Plugin): db = get_db() - qualities = db.all('quality', with_doc = True) - temp = [] - for quality in qualities: - quality = quality['doc'] - q = mergeDicts(self.getQuality(quality.get('identifier')), quality) + for quality in self.qualities: + quality_doc = db.get('quality', quality.get('identifier'), with_doc = True)['doc'] + q = mergeDicts(quality, quality_doc) temp.append(q) - self.cached_qualities = temp + if len(temp) == len(self.qualities): + self.cached_qualities = temp return temp From e659aba176bc2c2cb53bdde41503e2b4420c09e5 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 15 Jun 2014 22:22:34 +0200 Subject: [PATCH 05/20] Clean .pyc files before starting --- CouchPotato.py | 7 +++++- couchpotato/core/_base/updater/main.py | 29 +++---------------------- couchpotato/core/helpers/variable.py | 30 +++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/CouchPotato.py b/CouchPotato.py index f21b9393..f5b9c046 100755 --- a/CouchPotato.py +++ b/CouchPotato.py @@ -19,7 +19,12 @@ base_path = dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.join(base_path, 'libs')) from couchpotato.environment import Env -from couchpotato.core.helpers.variable import getDataDir +from couchpotato.core.helpers.variable import getDataDir, removePyc + + +# Remove pyc files before dynamic load (sees .pyc files regular .py modules) +removePyc(base_path) + class Loader(object): diff --git a/couchpotato/core/_base/updater/main.py b/couchpotato/core/_base/updater/main.py index 27f9917a..093977da 100644 --- a/couchpotato/core/_base/updater/main.py +++ b/couchpotato/core/_base/updater/main.py @@ -11,6 +11,7 @@ from threading import RLock from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent, fireEventAsync from couchpotato.core.helpers.encoding import sp +from couchpotato.core.helpers.variable import removePyc from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from couchpotato.environment import Env @@ -143,7 +144,7 @@ class Updater(Plugin): def doShutdown(self): if not Env.get('dev'): - self.updater.deletePyc(show_logs = False) + removePyc(Env.get('app_dir'), show_logs = False) return super(Updater, self).doShutdown() @@ -181,30 +182,6 @@ class BaseUpdater(Plugin): def check(self): pass - def deletePyc(self, only_excess = True, show_logs = True): - - for root, dirs, files in os.walk(Env.get('app_dir')): - - pyc_files = filter(lambda filename: filename.endswith('.pyc'), files) - py_files = set(filter(lambda filename: filename.endswith('.py'), files)) - excess_pyc_files = filter(lambda pyc_filename: pyc_filename[:-1] not in py_files, pyc_files) if only_excess else pyc_files - - for excess_pyc_file in excess_pyc_files: - full_path = os.path.join(root, excess_pyc_file) - if show_logs: log.debug('Removing old PYC file: %s', full_path) - try: - os.remove(full_path) - except: - log.error('Couldn\'t remove %s: %s', (full_path, traceback.format_exc())) - - for dir_name in dirs: - full_path = os.path.join(root, dir_name) - if len(os.listdir(full_path)) == 0: - try: - os.rmdir(full_path) - except: - log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc())) - class GitUpdater(BaseUpdater): @@ -328,7 +305,7 @@ class SourceUpdater(BaseUpdater): data_dir = Env.get('data_dir') # Get list of files we want to overwrite - self.deletePyc() + removePyc(app_dir) existing_files = [] for root, subfiles, filenames in os.walk(app_dir): for filename in filenames: diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index 16207a64..66e01f55 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -6,8 +6,9 @@ import random import re import string import sys +import traceback -from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss +from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss, sp from couchpotato.core.logger import CPLog import six from six.moves import map, zip, filter @@ -313,3 +314,30 @@ under_pat = re.compile(r'_([a-z])') def underscoreToCamel(name): return under_pat.sub(lambda x: x.group(1).upper(), name) + + +def removePyc(folder, only_excess = True, show_logs = True): + + folder = sp(folder) + + for root, dirs, files in os.walk(folder): + + pyc_files = filter(lambda filename: filename.endswith('.pyc'), files) + py_files = set(filter(lambda filename: filename.endswith('.py'), files)) + excess_pyc_files = filter(lambda pyc_filename: pyc_filename[:-1] not in py_files, pyc_files) if only_excess else pyc_files + + for excess_pyc_file in excess_pyc_files: + full_path = os.path.join(root, excess_pyc_file) + if show_logs: log.debug('Removing old PYC file: %s', full_path) + try: + os.remove(full_path) + except: + log.error('Couldn\'t remove %s: %s', (full_path, traceback.format_exc())) + + for dir_name in dirs: + full_path = os.path.join(root, dir_name) + if len(os.listdir(full_path)) == 0: + try: + os.rmdir(full_path) + except: + log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc())) From 530d3cd91ecc79c384da922e5e2d2655242ee377 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 15 Jun 2014 22:37:18 +0200 Subject: [PATCH 06/20] Update rentals URL --- couchpotato/core/media/movie/providers/automation/imdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/movie/providers/automation/imdb.py b/couchpotato/core/media/movie/providers/automation/imdb.py index 9b4c1171..783e8f50 100644 --- a/couchpotato/core/media/movie/providers/automation/imdb.py +++ b/couchpotato/core/media/movie/providers/automation/imdb.py @@ -263,7 +263,7 @@ config = [{ 'name': 'automation_charts_rentals', 'type': 'bool', 'label': 'DVD Rentals', - 'description': 'Top DVD rentals chart', + 'description': 'Top DVD rentals chart', 'default': True, }, { @@ -312,7 +312,7 @@ config = [{ 'name': 'chart_display_rentals', 'type': 'bool', 'label': 'DVD Rentals', - 'description': 'Top DVD rentals chart', + 'description': 'Top DVD rentals chart', 'default': True, }, { From 3faece0b4cdac07c7efb4c47a2c6445c9ce58b08 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 16 Jun 2014 21:21:55 +0200 Subject: [PATCH 07/20] Don't log already deleted releases. --- couchpotato/core/plugins/manage.py | 12 ++++++------ couchpotato/core/plugins/release/main.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/couchpotato/core/plugins/manage.py b/couchpotato/core/plugins/manage.py index 97f66a78..f0e0faf4 100644 --- a/couchpotato/core/plugins/manage.py +++ b/couchpotato/core/plugins/manage.py @@ -136,6 +136,7 @@ class Manage(Plugin): # Get movies with done status total_movies, done_movies = fireEvent('media.list', types = 'movie', status = 'done', release_status = 'done', status_or = True, single = True) + deleted_releases = [] for done_movie in done_movies: if getIdentifier(done_movie) not in added_identifiers: fireEvent('media.delete', media_id = done_movie['_id'], delete_from = 'all') @@ -165,12 +166,11 @@ class Manage(Plugin): already_used = used_files.get(release_file) if already_used: - # delete current one - if already_used.get('last_edit', 0) < release.get('last_edit', 0): - fireEvent('release.delete', release['_id'], single = True) - # delete previous one - else: - fireEvent('release.delete', already_used['_id'], single = True) + if release_id not in deleted_releases: + release_id = release['_id'] if already_used.get('last_edit', 0) < release.get('last_edit', 0) else already_used['_id'] + fireEvent('release.delete', release_id, single = True) + + deleted_releases.append(release_id) break else: used_files[release_file] = release diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 08f02480..db2b0c89 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -149,7 +149,7 @@ class Release(Plugin): r = db.get('release_identifier', release_identifier, with_doc = True)['doc'] r['media_id'] = media['_id'] except: - log.error('Failed updating release by identifier: %s', traceback.format_exc()) + log.debug('Failed updating release by identifier "%s". Inserting new.', release_identifier) r = db.insert(release) # Update with ref and _id @@ -184,7 +184,7 @@ class Release(Plugin): db.delete(rel) return True except RecordDeleted: - log.error('Already deleted: %s', release_id) + log.debug('Already deleted: %s', release_id) return True except: log.error('Failed: %s', traceback.format_exc()) From 76126271fc743ff26a306c016e7287a7dc50b53e Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 16 Jun 2014 22:06:39 +0200 Subject: [PATCH 08/20] Don't add default profile if status is done --- couchpotato/core/media/movie/_base/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 4c5c2f29..2740e0dc 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -90,7 +90,7 @@ class MovieBase(MovieTypeBase): # Default profile and category default_profile = {} - if not params.get('profile_id'): + if not params.get('profile_id') and status != 'done': default_profile = fireEvent('profile.default', single = True) cat_id = params.get('category_id') From f65ddbbb9e35a3fccc521787cee8cd7d377f2292 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 16 Jun 2014 22:39:02 +0200 Subject: [PATCH 09/20] Encode environments args in html --- couchpotato/environment.py | 8 ++++++-- couchpotato/templates/index.html | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/couchpotato/environment.py b/couchpotato/environment.py index 658b744d..1000d489 100644 --- a/couchpotato/environment.py +++ b/couchpotato/environment.py @@ -2,6 +2,7 @@ import os from couchpotato.core.database import Database from couchpotato.core.event import fireEvent, addEvent +from couchpotato.core.helpers.encoding import toUnicode from couchpotato.core.loader import Loader from couchpotato.core.settings import Settings @@ -38,8 +39,11 @@ class Env(object): return Env._debug @staticmethod - def get(attr): - return getattr(Env, '_' + attr) + def get(attr, unicode = False): + if unicode: + return toUnicode(getattr(Env, '_' + attr)) + else: + return getattr(Env, '_' + attr) @staticmethod def all(): diff --git a/couchpotato/templates/index.html b/couchpotato/templates/index.html index b4328001..0d8acbc1 100644 --- a/couchpotato/templates/index.html +++ b/couchpotato/templates/index.html @@ -73,10 +73,10 @@ App.setup({ 'base_url': {{ json_encode(Env.get('web_base')) }}, - 'args': {{ json_encode(Env.get('args')) }}, + 'args': {{ json_encode(Env.get('args', unicode = True)) }}, 'options': {{ json_encode(('%s' % Env.get('options'))) }}, - 'app_dir': {{ json_encode(Env.get('app_dir')) }}, - 'data_dir': {{ json_encode(Env.get('data_dir')) }}, + 'app_dir': {{ json_encode(Env.get('app_dir', unicode = True)) }}, + 'data_dir': {{ json_encode(Env.get('data_dir', unicode = True)) }}, 'pid': {{ json_encode(Env.getPid()) }}, 'userscript_version': {{ json_encode(fireEvent('userscript.get_version', single = True)) }} }); From cfb77a1076c9dc5a66b3809f2b530d84e9aed8e6 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 14:22:42 +0200 Subject: [PATCH 10/20] Don't use extension to test for quality tags. fix #3457 --- couchpotato/core/plugins/quality/main.py | 28 +++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index 677ee48f..ef18647b 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -22,12 +22,12 @@ class QualityPlugin(Plugin): } qualities = [ - {'identifier': 'bd50', 'hd': True, 'allow_3d': True, 'size': (20000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25'], 'allow': ['1080p'], 'ext':['iso', 'img'], 'tags': ['bdmv', 'certificate', ('complete', 'bluray'), 'avc', 'mvc']}, - {'identifier': '1080p', 'hd': True, 'allow_3d': True, 'size': (4000, 20000), 'label': '1080p', 'width': 1920, 'height': 1080, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts'], 'tags': ['m2ts', 'x264', 'h264']}, + {'identifier': 'bd50', 'hd': True, 'allow_3d': True, 'size': (20000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25', ('br', 'disk')], 'allow': ['1080p'], 'ext':['iso', 'img'], 'tags': ['bdmv', 'certificate', ('complete', 'bluray'), 'avc', 'mvc']}, + {'identifier': '1080p', 'hd': True, 'allow_3d': True, 'size': (4000, 20000), 'label': '1080p', 'width': 1920, 'height': 1080, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts', 'ts'], 'tags': ['m2ts', 'x264', 'h264']}, {'identifier': '720p', 'hd': True, 'allow_3d': True, 'size': (3000, 10000), 'label': '720p', 'width': 1280, 'height': 720, 'alternative': [], 'allow': [], 'ext':['mkv', 'ts'], 'tags': ['x264', 'h264']}, - {'identifier': 'brrip', 'hd': True, 'allow_3d': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p', '1080p'], 'ext':[], 'tags': ['hdtv', 'hdrip', 'webdl', ('web', 'dl')]}, - {'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': ['br2dvd'], 'allow': [], 'ext':['iso', 'img', 'vob'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts', ('dvd', 'r'), 'dvd9']}, - {'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'width': 720, 'alternative': [], 'allow': [], 'ext':[], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]}, + {'identifier': 'brrip', 'hd': True, 'allow_3d': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip', ('br', 'rip')], 'allow': ['720p', '1080p'], 'ext':[], 'tags': ['hdtv', 'hdrip', 'webdl', ('web', 'dl')]}, + {'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': ['br2dvd', ('dvd', 'r')], 'allow': [], 'ext':['iso', 'img', 'vob'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts', ('dvd', 'r'), 'dvd9']}, + {'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'width': 720, 'alternative': [('dvd', 'rip')], 'allow': [], 'ext':[], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]}, {'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip', 'dvdscreener', 'hdscr'], 'allow': ['dvdr', 'dvdrip', '720p', '1080p'], 'ext':[], 'tags': ['webrip', ('web', 'rip')]}, {'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': ['r6'], 'allow': ['dvdr'], 'ext':[]}, {'identifier': 'tc', 'size': (600, 1000), 'label': 'TeleCine', 'alternative': ['telecine'], 'allow': [], 'ext':[]}, @@ -256,6 +256,9 @@ class QualityPlugin(Plugin): cur_file = ss(cur_file) score = 0 + extension = words[-1] + words = words[:-1] + points = { 'identifier': 10, 'label': 10, @@ -275,7 +278,7 @@ class QualityPlugin(Plugin): log.debug('Found %s via %s %s in %s', (quality['identifier'], tag_type, quality.get(tag_type), cur_file)) score += points.get(tag_type) - if isinstance(alt, (str, unicode)) and ss(alt.lower()) in cur_file.lower(): + if isinstance(alt, (str, unicode)) and ss(alt.lower()) in words: log.debug('Found %s via %s %s in %s', (quality['identifier'], tag_type, quality.get(tag_type), cur_file)) score += points.get(tag_type) / 2 @@ -285,8 +288,8 @@ class QualityPlugin(Plugin): # Check extention for ext in quality.get('ext', []): - if ext == words[-1]: - log.debug('Found %s extension in %s', (ext, cur_file)) + if ext == extension: + log.debug('Found %s with .%s extension in %s', (quality['identifier'], ext, cur_file)) score += points['ext'] return score @@ -432,7 +435,9 @@ class QualityPlugin(Plugin): 'Movie Monuments 2013 BrRip 720p': {'size': 1300, 'quality': 'brrip'}, 'The.Movie.2014.3D.1080p.BluRay.AVC.DTS-HD.MA.5.1-GroupName': {'size': 30000, 'quality': 'bd50', 'is_3d': True}, '/home/namehou/Movie Monuments (2013)/Movie Monuments.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': False}, - '/home/namehou/Movie Monuments (2013)/Movie Monuments Full-OU.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': True} + '/home/namehou/Movie Monuments (2013)/Movie Monuments Full-OU.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': True}, + '/volume1/Public/3D/Moviename/Moviename (2009).3D.SBS.ts': {'size': 7500, 'quality': '1080p', 'is_3d': True}, + '/volume1/Public/Moviename/Moviename (2009).ts': {'size': 5500, 'quality': '1080p'}, } correct = 0 @@ -440,7 +445,10 @@ class QualityPlugin(Plugin): test_quality = self.guess(files = [name], extra = tests[name].get('extra', None), size = tests[name].get('size', None)) or {} success = test_quality.get('identifier') == tests[name]['quality'] and test_quality.get('is_3d') == tests[name].get('is_3d', False) if not success: - log.error('%s failed check, thinks it\'s %s', (name, test_quality.get('identifier'))) + log.error('%s failed check, thinks it\'s "%s" expecting "%s"', (name, + test_quality.get('identifier') + (' 3D' if test_quality.get('is_3d') else ''), + tests[name]['quality'] + (' 3D' if tests[name].get('is_3d') else '') + )) correct += success From 664ce6421fd03ead21f03a99fef712d975b3a4de Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 15:21:08 +0200 Subject: [PATCH 11/20] Try only parse filename for release name --- couchpotato/core/plugins/scanner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/couchpotato/core/plugins/scanner.py b/couchpotato/core/plugins/scanner.py index 0b461862..ce7facd7 100644 --- a/couchpotato/core/plugins/scanner.py +++ b/couchpotato/core/plugins/scanner.py @@ -903,6 +903,7 @@ class Scanner(Plugin): log.debug('Could not detect via guessit "%s": %s', (file_name, traceback.format_exc())) # Backup to simple + release_name = os.path.basename(release_name.replace('\\', '/')) cleaned = ' '.join(re.split('\W+', simplifyString(release_name))) cleaned = re.sub(self.clean, ' ', cleaned) From 648ac7793ffc43cb7f450d05cbd11ef23586e546 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 15:21:30 +0200 Subject: [PATCH 12/20] Add multiple 3d tags to clean regex --- couchpotato/core/plugins/scanner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/scanner.py b/couchpotato/core/plugins/scanner.py index ce7facd7..d5937eae 100644 --- a/couchpotato/core/plugins/scanner.py +++ b/couchpotato/core/plugins/scanner.py @@ -105,7 +105,7 @@ class Scanner(Plugin): 'HDTV': ['hdtv'] } - clean = '([ _\,\.\(\)\[\]\-]|^)(3d|hsbs|sbs|ou|extended.cut|directors.cut|french|fr|swedisch|sw|danish|dutch|nl|swesub|subs|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip' \ + clean = '([ _\,\.\(\)\[\]\-]|^)(3d|hsbs|sbs|half.sbs|full.sbs|ou|half.ou|full.ou|extended.cut|directors.cut|french|fr|swedisch|sw|danish|dutch|nl|swesub|subs|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip' \ '|hdtvrip|webdl|web.dl|webrip|web.rip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|video_ts|audio_ts|480p|480i|576p|576i|720p|720i|1080p|1080i|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|hc|\[.*\])(?=[ _\,\.\(\)\[\]\-]|$)' multipart_regex = [ '[ _\.-]+cd[ _\.-]*([0-9a-d]+)', #*cd1 From 1857e047b0e4e4a1dfddf92dc144571c0a00a554 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 15:22:20 +0200 Subject: [PATCH 13/20] Remove moviename words when scanning for 3d tags. fix #3395 --- couchpotato/core/plugins/quality/main.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index ef18647b..ef885340 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -1,12 +1,12 @@ import traceback import re -from CodernityDB.database import RecordNotFound +from CodernityDB.database import RecordNotFound 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, ss -from couchpotato.core.helpers.variable import mergeDicts, getExt, tryInt +from couchpotato.core.helpers.variable import mergeDicts, getExt, tryInt, splitString from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.quality.index import QualityIndex @@ -192,7 +192,7 @@ class QualityPlugin(Plugin): # Create hash for cache cache_key = str([f.replace('.' + getExt(f), '') if len(getExt(f)) < 4 else f for f in files]) - cached = self.getCache(cache_key) + cached = None #self.getCache(cache_key) if cached and len(extra) == 0: return cached @@ -208,6 +208,10 @@ class QualityPlugin(Plugin): for cur_file in files: words = re.split('\W+', cur_file.lower()) + name_year = fireEvent('scanner.name_year', cur_file, file_name = cur_file, single = True) + if name_year and name_year.get('name'): + split_name = splitString(name_year.get('name'), ' ') + words = [x for x in words if x not in split_name] for quality in qualities: contains_score = self.containsTagScore(quality, words, cur_file) @@ -438,6 +442,9 @@ class QualityPlugin(Plugin): '/home/namehou/Movie Monuments (2013)/Movie Monuments Full-OU.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': True}, '/volume1/Public/3D/Moviename/Moviename (2009).3D.SBS.ts': {'size': 7500, 'quality': '1080p', 'is_3d': True}, '/volume1/Public/Moviename/Moviename (2009).ts': {'size': 5500, 'quality': '1080p'}, + '/movies/BluRay HDDVD H.264 MKV 720p EngSub/QuiQui le fou (criterion collection #123, 1915)/QuiQui le fou (1915) 720p x264 BluRay.mkv': {'size': 5500, 'quality': '720p'}, + 'C:\\movies\QuiQui le fou (collection #123, 1915)\QuiQui le fou (1915) 720p x264 BluRay.mkv': {'size': 5500, 'quality': '720p'}, + 'C:\\movies\QuiQui le fou (collection #123, 1915)\QuiQui le fou (1915) half-sbs 720p x264 BluRay.mkv': {'size': 5500, 'quality': '720p', 'is_3d': True}, } correct = 0 From 3786b5435f05847e94cdf1786e9dda4509a59126 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 15:36:18 +0200 Subject: [PATCH 14/20] Only remove movie title from 3d words check --- couchpotato/core/plugins/quality/main.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index ef885340..dd820cf0 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -192,7 +192,7 @@ class QualityPlugin(Plugin): # Create hash for cache cache_key = str([f.replace('.' + getExt(f), '') if len(getExt(f)) < 4 else f for f in files]) - cached = None #self.getCache(cache_key) + cached = self.getCache(cache_key) if cached and len(extra) == 0: return cached @@ -209,13 +209,14 @@ class QualityPlugin(Plugin): for cur_file in files: words = re.split('\W+', cur_file.lower()) name_year = fireEvent('scanner.name_year', cur_file, file_name = cur_file, single = True) + threed_words = words if name_year and name_year.get('name'): split_name = splitString(name_year.get('name'), ' ') - words = [x for x in words if x not in split_name] + threed_words = [x for x in words if x not in split_name] for quality in qualities: contains_score = self.containsTagScore(quality, words, cur_file) - threedscore = self.contains3D(quality, words, cur_file) if quality.get('allow_3d') else (0, None) + threedscore = self.contains3D(quality, threed_words, cur_file) if quality.get('allow_3d') else (0, None) self.calcScore(score, quality, contains_score, threedscore) From dd61c7dc211852d910c627d5ad3cc8eda1faf953 Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 16:27:22 +0200 Subject: [PATCH 15/20] Compact DB every 7 days if needed --- couchpotato/core/database.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/couchpotato/core/database.py b/couchpotato/core/database.py index 1b9501c2..d753d87f 100644 --- a/couchpotato/core/database.py +++ b/couchpotato/core/database.py @@ -26,7 +26,9 @@ class Database(object): addApiView('database.document.update', self.updateDocument) addApiView('database.document.delete', self.deleteDocument) + addEvent('database.setup.after', self.startup_compact) addEvent('database.setup_index', self.setupIndex) + addEvent('app.migrate', self.migrate) addEvent('app.after_shutdown', self.close) @@ -140,8 +142,14 @@ class Database(object): success = True try: + start = time.time() db = self.getDB() + size = float(db.get_db_details().get('size', 0)) + log.debug('Compacting database, current size: %sMB', round(size/1048576, 2)) + db.compact() + new_size = float(db.get_db_details().get('size', 0)) + log.debug('Done compacting database in %ss, new size: %sMB, saved: %sMB', (round(time.time()-start, 2), round(new_size/1048576, 2), round((size-new_size)/1048576, 2))) except: log.error('Failed compact: %s', traceback.format_exc()) success = False @@ -150,6 +158,18 @@ class Database(object): 'success': success } + # Compact on start + def startup_compact(self): + from couchpotato import Env + + db = self.getDB() + size = db.get_db_details().get('size') + prop_name = 'last_db_compact' + last_check = int(Env.prop(prop_name, default = 0)) + if size > 26214400 and last_check < time.time()-604800: # 25MB / 7 days + self.compact() + Env.prop(prop_name, value = int(time.time())) + def migrate(self): from couchpotato import Env From 67fbcc8238b951378ea4614aa318480f29f5c66a Mon Sep 17 00:00:00 2001 From: Ruud Date: Tue, 17 Jun 2014 23:32:27 +0200 Subject: [PATCH 16/20] Tag filter index --- couchpotato/core/media/_base/media/index.py | 21 +++++++++++++++++++++ couchpotato/core/media/_base/media/main.py | 18 ++++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/media/_base/media/index.py b/couchpotato/core/media/_base/media/index.py index 1b77b706..2166c0ac 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -176,3 +176,24 @@ class MediaChildrenIndex(TreeBasedIndex): if data.get('_t') == 'media' and data.get('parent_id'): return data.get('parent_id'), None + +class MediaTagIndex(MultiTreeBasedIndex): + _version = 1 + + custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex""" + + def __init__(self, *args, **kwargs): + kwargs['key_format'] = '32s' + super(MediaTagIndex, self).__init__(*args, **kwargs) + + def make_key_value(self, data): + if data.get('_t') == 'media' and len(data.get('tags', [])) > 0: + + tags = set() + for tag in data.get('tags', []): + tags.add(self.make_key(tag)) + + return list(tags), None + + def make_key(self, key): + return md5(key).hexdigest() diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 3c1bf694..bd0d53c5 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -9,7 +9,7 @@ from couchpotato.core.helpers.encoding import toUnicode from couchpotato.core.helpers.variable import splitString, getImdb, getTitle from couchpotato.core.logger import CPLog from couchpotato.core.media import MediaBase -from .index import MediaIndex, MediaStatusIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex, MediaChildrenIndex +from .index import MediaIndex, MediaStatusIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex, MediaChildrenIndex, MediaTagIndex log = CPLog(__name__) @@ -21,6 +21,7 @@ class MediaPlugin(MediaBase): 'media': MediaIndex, 'media_search_title': TitleSearchIndex, 'media_status': MediaStatusIndex, + 'media_tag': MediaTagIndex, 'media_by_type': MediaTypeIndex, 'media_title': TitleIndex, 'media_startswith': StartsWithIndex, @@ -177,7 +178,7 @@ class MediaPlugin(MediaBase): log.debug('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): + def list(self, types = None, status = None, release_status = None, status_or = False, limit_offset = None, with_tags = None, starts_with = None, search = None): db = get_db() @@ -188,6 +189,8 @@ class MediaPlugin(MediaBase): release_status = [release_status] if types and not isinstance(types, (list, tuple)): types = [types] + if with_tags and not isinstance(with_tags, (list, tuple)): + with_tags = [with_tags] # query media ids if types: @@ -214,11 +217,17 @@ class MediaPlugin(MediaBase): # Add search filters if starts_with: - filter_by['starts_with'] = set() starts_with = toUnicode(starts_with.lower())[0] starts_with = starts_with if starts_with in ascii_lowercase else '#' filter_by['starts_with'] = [x['_id'] for x in db.get_many('media_startswith', starts_with)] + # Add tag filter + if with_tags: + filter_by['with_tags'] = set() + for tag in with_tags: + for x in db.get_many('media_tag', tag): + filter_by['with_tags'].add(x['_id']) + # Filter with search query if search: filter_by['search'] = [x['_id'] for x in db.get_many('media_search_title', search)] @@ -271,7 +280,8 @@ class MediaPlugin(MediaBase): release_status = splitString(kwargs.get('release_status')), status_or = kwargs.get('status_or') is not None, limit_offset = kwargs.get('limit_offset'), - starts_with = kwargs.get('starts_with'), + with_tags = kwargs.get('with_tags'), + starts_with = splitString(kwargs.get('starts_with')), search = kwargs.get('search') ) From 0b5dfe826abaeaeec521d824ed5f0ebfc0b4f73b Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 19 Jun 2014 14:15:42 +0200 Subject: [PATCH 17/20] Fix BitSoup parsing. close #3465 --- couchpotato/core/media/_base/providers/torrent/bitsoup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/_base/providers/torrent/bitsoup.py b/couchpotato/core/media/_base/providers/torrent/bitsoup.py index f32e79e7..d70579e0 100644 --- a/couchpotato/core/media/_base/providers/torrent/bitsoup.py +++ b/couchpotato/core/media/_base/providers/torrent/bitsoup.py @@ -1,6 +1,6 @@ import traceback -from bs4 import BeautifulSoup +from bs4 import BeautifulSoup, SoupStrainer from couchpotato.core.helpers.variable import tryInt from couchpotato.core.logger import CPLog from couchpotato.core.media._base.providers.torrent.base import TorrentProvider @@ -20,6 +20,7 @@ class Base(TorrentProvider): } http_time_between_calls = 1 # Seconds + only_tables_tags = SoupStrainer('table') def _searchOnTitle(self, title, movie, quality, results): @@ -27,7 +28,7 @@ class Base(TorrentProvider): data = self.getHTMLData(url) if data: - html = BeautifulSoup(data) + html = BeautifulSoup(data, 'html.parser', parse_only = self.only_tables_tags) try: result_table = html.find('table', attrs = {'class': 'koptekst'}) From 57ca5067ffd5b7f42db1cdf7f634e558f13c3861 Mon Sep 17 00:00:00 2001 From: Ruud Date: Thu, 19 Jun 2014 16:48:30 +0200 Subject: [PATCH 18/20] Insert themoviedb original_title in by default. --- couchpotato/core/media/movie/providers/info/themoviedb.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/media/movie/providers/info/themoviedb.py b/couchpotato/core/media/movie/providers/info/themoviedb.py index 16299f2e..4a397edd 100644 --- a/couchpotato/core/media/movie/providers/info/themoviedb.py +++ b/couchpotato/core/media/movie/providers/info/themoviedb.py @@ -153,8 +153,10 @@ class TheMovieDb(MovieProvider): movie_data = dict((k, v) for k, v in movie_data.items() if v) # Add alternative names + if movie_data['original_title'] and movie_data['original_title'] not in movie_data['titles']: + movie_data['titles'].insert(0, movie_data['original_title']) + if extended: - movie_data['titles'].append(movie.originaltitle) for alt in movie.alternate_titles: alt_name = alt.title if alt_name and alt_name not in movie_data['titles'] and alt_name.lower() != 'none' and alt_name is not None: From 5797348bb379a92bd43864aa91eed703f0a3bcd1 Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 20 Jun 2014 12:10:40 +0200 Subject: [PATCH 19/20] Update tag index --- 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 2166c0ac..b40e162b 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -178,7 +178,7 @@ class MediaChildrenIndex(TreeBasedIndex): class MediaTagIndex(MultiTreeBasedIndex): - _version = 1 + _version = 2 custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex""" @@ -187,7 +187,7 @@ class MediaTagIndex(MultiTreeBasedIndex): super(MediaTagIndex, self).__init__(*args, **kwargs) def make_key_value(self, data): - if data.get('_t') == 'media' and len(data.get('tags', [])) > 0: + if data.get('_t') == 'media' and data.get('tags') and len(data.get('tags', [])) > 0: tags = set() for tag in data.get('tags', []): From 6f766aae8c424208614eddd255d032044e3a7e9d Mon Sep 17 00:00:00 2001 From: Ruud Date: Fri, 20 Jun 2014 12:13:54 +0200 Subject: [PATCH 20/20] Tag and untag dashboard media --- couchpotato/core/media/_base/media/main.py | 40 ++++++++++++++++++++++ couchpotato/core/media/movie/_base/main.py | 1 + couchpotato/core/media/movie/searcher.py | 5 +++ couchpotato/core/plugins/release/main.py | 4 +++ couchpotato/core/plugins/renamer.py | 13 +++++++ couchpotato/static/scripts/page/home.js | 3 +- 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index bd0d53c5..b4c8ced0 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -82,6 +82,8 @@ class MediaPlugin(MediaBase): addEvent('media.list', self.list) addEvent('media.delete', self.delete) addEvent('media.restatus', self.restatus) + addEvent('media.tag', self.tag) + addEvent('media.untag', self.unTag) def refresh(self, id = '', **kwargs): handlers = [] @@ -469,3 +471,41 @@ class MediaPlugin(MediaBase): return True except: log.error('Failed restatus: %s', traceback.format_exc()) + + def tag(self, media_id, tag): + + try: + db = get_db() + m = db.get('id', media_id) + + tags = m.get('tags') or [] + if tag not in tags: + tags.append(tag) + m['tags'] = tags + db.update(m) + + return True + except: + log.error('Failed tagging: %s', traceback.format_exc()) + + return False + + def unTag(self, media_id, tag): + + try: + db = get_db() + m = db.get('id', media_id) + + tags = m.get('tags') or [] + if tag in tags: + new_tags = list(set(tags)) + new_tags.remove(tag) + + m['tags'] = new_tags + db.update(m) + + return True + except: + log.error('Failed untagging: %s', traceback.format_exc()) + + return False diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 2740e0dc..9475ec09 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -149,6 +149,7 @@ class MovieBase(MovieTypeBase): m['profile_id'] = params.get('profile_id', default_profile.get('id')) m['category_id'] = cat_id if cat_id is not None and len(cat_id) > 0 else (m.get('category_id') or None) m['last_edit'] = int(time.time()) + m['tags'] = [] do_search = True db.update(m) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 81d62004..0f4b4179 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -131,6 +131,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): outside_eta_results = 0 alway_search = self.conf('always_search') ignore_eta = manual + total_result_count = 0 default_title = getTitle(movie) if not default_title: @@ -199,6 +200,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or [] results_count = len(results) + total_result_count += results_count if results_count == 0: log.debug('Nothing found for %s in %s', (default_title, quality['label'])) @@ -235,6 +237,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase): if self.shuttingDown() or ret: break + if total_result_count > 0: + fireEvent('media.tag', movie['_id'], 'recent', single = True) + if len(too_early_to_search) > 0: log.info2('Too early to search for %s, %s', (too_early_to_search, default_title)) diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index db2b0c89..e3c93b42 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -104,6 +104,8 @@ class Release(Plugin): elif rel['status'] in ['snatched', 'downloaded']: self.updateStatus(rel['_id'], status = 'ignore') + fireEvent('media.untag', media.get('_id'), 'recent', single = True) + def add(self, group, update_info = True, update_id = None): try: @@ -346,6 +348,8 @@ class Release(Plugin): mdia['last_edit'] = int(time.time()) db.update(mdia) + fireEvent('media.tag', media['_id'], 'recent', single = True) + return True # Assume release downloaded diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 11585802..8b57103e 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -457,9 +457,15 @@ class Renamer(Plugin): mdia['last_edit'] = int(time.time()) db.update(mdia) + # List movie on dashboard + fireEvent('media.tag', media['_id'], 'recent', single = True) + except: log.error('Failed marking movie finished: %s', (traceback.format_exc())) + # Mark media for dashboard + mark_as_recent = False + # Go over current movie releases for release in fireEvent('release.for_media', media['_id'], single = True): @@ -506,14 +512,21 @@ class Renamer(Plugin): # Set the release to downloaded fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True) group['release_download'] = release_download + mark_as_recent = True elif release_download['status'] == 'seeding': # Set the release to seeding fireEvent('release.update_status', release['_id'], status = 'seeding', single = True) + mark_as_recent = True elif release.get('identifier') == group['meta_data']['quality']['identifier']: # Set the release to downloaded fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True) group['release_download'] = release_download + mark_as_recent = True + + # Mark media for dashboard + if mark_as_recent: + fireEvent('media.tag', group['media'].get('_id'), 'recent', single = True) # Remove leftover files if not remove_leftovers: # Don't remove anything diff --git a/couchpotato/static/scripts/page/home.js b/couchpotato/static/scripts/page/home.js index aff8fbb3..792b4a07 100644 --- a/couchpotato/static/scripts/page/home.js +++ b/couchpotato/static/scripts/page/home.js @@ -54,7 +54,8 @@ Page.Home = new Class({ }) ), 'filter': { - 'release_status': 'snatched,missing,available,downloaded' + 'release_status': 'snatched,missing,available,downloaded,done,seeding', + 'with_tags': 'recent' }, 'limit': null, 'onLoaded': function(){