From c3bc9c859157109042d9c8f75ec7e23811c2b69d Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 8 Feb 2014 17:58:45 +0100 Subject: [PATCH] Nosql --- couchpotato/core/helpers/request.py | 6 +- couchpotato/core/media/_base/media/index.py | 14 ---- couchpotato/core/media/_base/media/main.py | 44 +++++----- couchpotato/core/media/movie/_base/main.py | 10 +-- couchpotato/core/media/movie/_base/static/list.js | 10 +-- .../core/media/movie/_base/static/movie.actions.js | 93 ++++++---------------- couchpotato/core/media/movie/_base/static/movie.js | 22 ++--- .../core/media/movie/_base/static/search.js | 2 +- couchpotato/core/media/movie/searcher/main.py | 3 +- couchpotato/core/media/movie/suggestion/main.py | 25 ++---- .../core/notifications/core/static/notification.js | 4 +- couchpotato/core/plugins/category/index.py | 21 ++++- couchpotato/core/plugins/category/main.py | 62 ++++++--------- .../core/plugins/category/static/category.js | 12 +-- couchpotato/core/plugins/profile/main.py | 71 ++++++++--------- couchpotato/core/plugins/profile/static/profile.js | 34 ++++---- couchpotato/core/plugins/quality/main.py | 3 - couchpotato/core/plugins/quality/static/quality.js | 2 +- couchpotato/core/plugins/release/main.py | 36 --------- couchpotato/core/plugins/renamer/main.py | 5 +- couchpotato/core/plugins/scanner/main.py | 21 +---- couchpotato/core/plugins/subtitle/main.py | 27 +------ couchpotato/core/providers/info/_modifier/main.py | 2 +- couchpotato/core/providers/nzb/newznab/__init__.py | 2 +- couchpotato/core/settings/__init__.py | 2 +- couchpotato/runner.py | 2 - couchpotato/static/scripts/page/home.js | 2 +- 27 files changed, 185 insertions(+), 352 deletions(-) diff --git a/couchpotato/core/helpers/request.py b/couchpotato/core/helpers/request.py index 8a10f07..523e46e 100644 --- a/couchpotato/core/helpers/request.py +++ b/couchpotato/core/helpers/request.py @@ -9,6 +9,7 @@ def getParams(params): reg = re.compile('^[a-z0-9_\.]+$') temp = {} + for param, value in sorted(params.items()): nest = re.split("([\[\]]+)", param) @@ -44,7 +45,10 @@ def dictToList(params): new = {} for x, value in params.items(): try: - new_value = [dictToList(value[k]) for k in sorted(value.keys(), cmp = natcmp)] + convert = lambda text: int(text) if text.isdigit() else text.lower() + alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] + sorted_keys = sorted(value.keys(), key = alphanum_key) + new_value = [dictToList(value[k]) for k in sorted_keys] except: new_value = value diff --git a/couchpotato/core/media/_base/media/index.py b/couchpotato/core/media/_base/media/index.py index d83c347..68e6610 100644 --- a/couchpotato/core/media/_base/media/index.py +++ b/couchpotato/core/media/_base/media/index.py @@ -92,20 +92,6 @@ from couchpotato.core.helpers.encoding import simplifyString""" return key.rjust(32, '_').lower() -class YearIndex(TreeBasedIndex): - - def __init__(self, *args, **kwargs): - kwargs['key_format'] = 'i' - super(YearIndex, self).__init__(*args, **kwargs) - - def make_key(self, key): - return key - - def make_key_value(self, data): - if data.get('_t') == 'media' and data.get('year') is not None: - return data['year'], None - - class TitleIndex(TreeBasedIndex): custom_header = """from CodernityDB.tree_index import TreeBasedIndex diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 17e443b..480b571 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -1,13 +1,12 @@ import traceback -from couchpotato import get_session, tryInt, get_db +from couchpotato import tryInt, 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, getImdb, getTitle from couchpotato.core.logger import CPLog from couchpotato.core.media import MediaBase -from .index import MediaIMDBIndex, MediaStatusIndex, YearIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex -from couchpotato.core.settings.model import Media +from .index import MediaIMDBIndex, MediaStatusIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex from string import ascii_lowercase log = CPLog(__name__) @@ -102,12 +101,6 @@ class MediaPlugin(MediaBase): log.debug('Index already exists') db.edit_index(MediaTypeIndex(db.path, 'media_by_type')) - # Year index - try: db.add_index(YearIndex(db.path, 'media_year')) - except: - log.debug('Index already exists') - db.edit_index(YearIndex(db.path, 'media_year')) - # Title index try: db.add_index(TitleIndex(db.path, 'media_title')) except: @@ -377,46 +370,45 @@ class MediaPlugin(MediaBase): def delete(self, media_id, delete_from = None): try: - db = get_session() + db = get_db() - media = db.query(Media).filter_by(id = media_id).first() + media = db.get('id', media_id) if media: deleted = False if delete_from == 'all': db.delete(media) - db.commit() deleted = True else: - total_releases = len(media.releases) + media_releases = list(db.run('release', 'for_media', media['_id'])) + + total_releases = len(media_releases) total_deleted = 0 - new_movie_status = None - for release in media.releases: + new_media_status = None + + for release in media_releases: if delete_from in ['wanted', 'snatched', 'late']: if release.get('status') != 'done': db.delete(release) total_deleted += 1 - new_movie_status = 'done' + new_media_status = 'done' elif delete_from == 'manage': if release.get('status') == 'done': db.delete(release) total_deleted += 1 - new_movie_status = 'active' - db.commit() + new_media_status = 'active' if total_releases == total_deleted: db.delete(media) - db.commit() deleted = True - elif new_movie_status: - media.profile_id = None - media['status'] = new_status - db.commit() + elif new_media_status: + media['status'] = new_media_status + db.update(media) else: - fireEvent('media.restatus', media.id, single = True) + fireEvent('media.restatus', media.get('_id'), single = True) if deleted: - fireEvent('notify.frontend', type = 'movie.deleted', data = media.to_dict()) + fireEvent('notify.frontend', type = 'media.deleted', data = media) except: log.error('Failed deleting media: %s', traceback.format_exc()) @@ -453,7 +445,7 @@ class MediaPlugin(MediaBase): move_to_wanted = True profile = db.get('id', m['profile_id']) - media_releases = db.get_many('release', m['_id']) + media_releases = db.run('release', 'for_media', m['_id']) 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 bb04b39..79ab97e 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -94,7 +94,7 @@ class MovieBase(MovieTypeBase): 'identifier': params.get('identifier'), 'status': status if status else 'active', 'profile_id': params.get('profile_id', default_profile.get('_id')), - 'category_id': tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else None, + 'category_id': cat_id if cat_id is not None and len(cat_id) > 0 else None, } new = False @@ -135,7 +135,7 @@ class MovieBase(MovieTypeBase): fireEvent('release.delete', release['_id'], single = True) m['profile_id'] = params.get('profile_id', default_profile.get('id')) - m['category_id'] = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else (m.get('category_id') or None) + m['category_id'] = cat_id if cat_id is not None and len(cat_id) > 0 else (m.get('category_id') or None) else: log.debug('Movie already exists, not updating: %s', params) added = False @@ -198,7 +198,7 @@ class MovieBase(MovieTypeBase): cat_id = kwargs.get('category_id') if cat_id is not None: - m['category_id'] = tryInt(cat_id) if tryInt(cat_id) > 0 else None + m['category_id'] = cat_id if len(cat_id) > 0 else None # Remove releases for rel in db.run('release', 'for_media', m['_id']): @@ -209,12 +209,12 @@ class MovieBase(MovieTypeBase): if kwargs.get('default_title'): m['title'] = kwargs.get('default_title') - print m - db.update(m) fireEvent('media.restatus', m['_id']) + m = db.get('id', media_id) + movie_dict = db.run('media', 'to_dict', m['_id']) fireEventAsync('movie.searcher.single', movie_dict, on_complete = self.createNotifyFront(media_id)) diff --git a/couchpotato/core/media/movie/_base/static/list.js b/couchpotato/core/media/movie/_base/static/list.js index a193daf..ce40595 100644 --- a/couchpotato/core/media/movie/_base/static/list.js +++ b/couchpotato/core/media/movie/_base/static/list.js @@ -63,7 +63,7 @@ var MovieList = new Class({ self.movies.each(function(movie){ if(movie.get('_id') == notification.data._id){ movie.destroy(); - delete self.movies_added[notification.data.id]; + delete self.movies_added[notification.data._id]; self.setCounter(self.counter_count-1); self.total_movies--; } @@ -77,7 +77,7 @@ var MovieList = new Class({ var self = this; self.fireEvent('movieAdded', notification); - if(self.options.add_new && !self.movies_added[notification.data.id] && notification.data.status.identifier == self.options.status){ + if(self.options.add_new && !self.movies_added[notification.data._id] && notification.data.status == self.options.status){ window.scroll(0,0); self.createMovie(notification.data, 'top'); self.setCounter(self.counter_count+1); @@ -180,7 +180,7 @@ var MovieList = new Class({ m.fireEvent('injected'); self.movies.include(m) - self.movies_added[movie.id] = true; + self.movies_added[movie._id] = true; }, createNavigation: function(){ @@ -259,8 +259,8 @@ var MovieList = new Class({ self.mass_edit_select_class = new Form.Check(self.mass_edit_select); Quality.getActiveProfiles().each(function(profile){ new Element('option', { - 'value': profile.id ? profile.id : profile.data.id, - 'text': profile.label ? profile.label : profile.data.label + 'value': profile.get('_id'), + 'text': profile.get('label') }).inject(self.mass_edit_quality) }); diff --git a/couchpotato/core/media/movie/_base/static/movie.actions.js b/couchpotato/core/media/movie/_base/static/movie.actions.js index b52a592..50548cc 100644 --- a/couchpotato/core/media/movie/_base/static/movie.actions.js +++ b/couchpotato/core/media/movie/_base/static/movie.actions.js @@ -127,7 +127,7 @@ MA.Release = new Class({ self.showHelper(); App.on('movie.searcher.ended', function(notification){ - if(self.movie.data.id != notification.data.id) return; + if(self.movie.data._id != notification.data._id) return; self.releases = null; if(self.options_container){ @@ -143,30 +143,7 @@ MA.Release = new Class({ if(e) (e).preventDefault(); - if(self.releases) - self.createReleases(); - else { - - self.movie.busy(true); - - Api.request('release.for_movie', { - 'data': { - 'id': self.movie.data.id - }, - 'onComplete': function(json){ - self.movie.busy(false, 1); - - if(json && json.releases){ - self.releases = json.releases; - self.createReleases(); - } - else - alert('Something went wrong, check the logs.'); - } - }); - - } - + self.createReleases(); }, @@ -189,9 +166,9 @@ MA.Release = new Class({ new Element('span.provider', {'text': 'Provider'}) ).inject(self.release_container) - self.releases.each(function(release){ + self.movie.data.releases.each(function(release){ - var quality = Quality.getProfile(release.quality_id) || {}, + var quality = Quality.getQuality(release.quality) || {}, info = release.info, provider = self.get(release, 'provider') + (release.info['provider_extra'] ? self.get(release, 'provider_extra') : ''); @@ -209,12 +186,12 @@ MA.Release = new Class({ // Create release var item = new Element('div', { - 'class': 'item '+status.identifier, - 'id': 'release_'+release.id + 'class': 'item '+release.status, + 'id': 'release_'+release._id }).adopt( new Element('span.name', {'text': release_name, 'title': release_name}), - new Element('span.status', {'text': status.identifier, 'class': 'release_status '+release.status}), - new Element('span.quality', {'text': quality.get('label') || 'n/a'}), + new Element('span.status', {'text': release.status, 'class': 'release_status '+release.status}), + new Element('span.quality', {'text': quality.label || 'n/a'}), new Element('span.size', {'text': release.info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}), new Element('span.age', {'text': self.get(release, 'age')}), new Element('span.score', {'text': self.get(release, 'score')}), @@ -243,32 +220,32 @@ MA.Release = new Class({ ).inject(self.release_container); release['el'] = item; - if(status.identifier == 'ignored' || status.identifier == 'failed' || status.identifier == 'snatched'){ - if(!self.last_release || (self.last_release && self.last_release.status.identifier != 'snatched' && status.identifier == 'snatched')) + if(release.status == 'ignored' || release.status == 'failed' || release.status == 'snatched'){ + if(!self.last_release || (self.last_release && self.last_release.status != 'snatched' && release.status == 'snatched')) self.last_release = release; } - else if(!self.next_release && status.identifier == 'available'){ + else if(!self.next_release && release.status == 'available'){ self.next_release = release; } var update_handle = function(notification) { - if(notification.data.id != release.id) return; + if(notification.data._id != release._id) return; - var q = self.movie.quality.getElement('.q_id' + release.quality_id), + var q = self.movie.quality.getElement('.q_' + release.quality), new_status = notification.data.status; release.el.set('class', 'item ' + new_status); var status_el = release.el.getElement('.release_status'); status_el.set('class', 'release_status ' + new_status); - status_el.set('text', new_status.identifier); + status_el.set('text', new_status); if(!q && (new_status == 'snatched' || new_status == 'seeding' || new_status == 'done')) var q = self.addQuality(release.quality_id); if(q && !q.hasClass(new_status)) { q.removeClass(release.status).addClass(new_status); - q.set('title', q.get('title').replace(status, new_status)); + q.set('title', q.get('title').replace(release.status, new_status)); } } @@ -277,12 +254,12 @@ MA.Release = new Class({ }); if(self.last_release) - self.release_container.getElements('#release_'+self.last_release.id).addClass('last_release'); + self.release_container.getElements('#release_'+self.last_release._id).addClass('last_release'); if(self.next_release) - self.release_container.getElements('#release_'+self.next_release.id).addClass('next_release'); + self.release_container.getElements('#release_'+self.next_release._id).addClass('next_release'); - if(self.next_release || (self.last_release && ['ignored', 'failed'].indexOf(self.last_release.status.identifier) === false)){ + if(self.next_release || (self.last_release && ['ignored', 'failed'].indexOf(self.last_release.status) === false)){ self.trynext_container = new Element('div.buttons.try_container').inject(self.release_container, 'top'); @@ -385,7 +362,7 @@ MA.Release = new Class({ download: function(release){ var self = this; - var release_el = self.release_container.getElement('#release_'+release.id), + var release_el = self.release_container.getElement('#release_'+release._id), icon = release_el.getElement('.download.icon2'); if(icon) @@ -393,7 +370,7 @@ MA.Release = new Class({ Api.request('release.manual_download', { 'data': { - 'id': release.id + 'id': release._id }, 'onComplete': function(json){ if(icon) @@ -416,7 +393,7 @@ MA.Release = new Class({ Api.request('release.ignore', { 'data': { - 'id': release.id + 'id': release._id }, }) @@ -623,14 +600,14 @@ MA.Edit = new Class({ self.category_select.show(); categories.each(function(category){ - var category_id = category.data.id; + var category_id = category.data._id; new Element('option', { 'value': category_id, 'text': category.data.label }).inject(self.category_select); - if(self.movie.category && self.movie.category.data && self.movie.category.data.id == category_id) + if(self.movie.category && self.movie.category.data && self.movie.category.data._id == category_id) self.category_select.set('value', category_id); }); @@ -859,29 +836,7 @@ MA.Files = new Class({ var self = this; (e).preventDefault(); - if(self.releases) - self.showFiles(); - else { - - self.movie.busy(true); - - Api.request('release.for_movie', { - 'data': { - 'id': self.movie.data.id - }, - 'onComplete': function(json){ - self.movie.busy(false, 1); - - if(json && json.releases){ - self.releases = json.releases; - self.showFiles(); - } - else - alert('Something went wrong, check the logs.'); - } - }); - - } + self.showFiles(); }, diff --git a/couchpotato/core/media/movie/_base/static/movie.js b/couchpotato/core/media/movie/_base/static/movie.js index 7e07cd4..417f065 100644 --- a/couchpotato/core/media/movie/_base/static/movie.js +++ b/couchpotato/core/media/movie/_base/static/movie.js @@ -27,7 +27,7 @@ var Movie = new Class({ // Do refresh with new data self.global_events['movie.update'] = function(notification){ - if(self.data.id != notification.data.id) return; + if(self.data._id != notification.data._id) return; self.busy(false); self.removeView(); @@ -38,7 +38,7 @@ var Movie = new Class({ // Add spinner on load / search ['media.busy', 'movie.searcher.started'].each(function(listener){ self.global_events[listener] = function(notification){ - if(notification.data && (self.data.id == notification.data.id || (typeOf(notification.data.id) == 'array' && notification.data.id.indexOf(self.data.id) > -1))) + if(notification.data && (self.data._id == notification.data._id || (typeOf(notification.data._id) == 'array' && notification.data._id.indexOf(self.data._id) > -1))) self.busy(true); } App.on(listener, self.global_events[listener]); @@ -46,7 +46,7 @@ var Movie = new Class({ // Remove spinner self.global_events['movie.searcher.ended'] = function(notification){ - if(notification.data && self.data.id == notification.data.id) + if(notification.data && self.data._id == notification.data._id) self.busy(false) } App.on('movie.searcher.ended', self.global_events['movie.searcher.ended']); @@ -54,12 +54,12 @@ var Movie = new Class({ // Reload when releases have updated self.global_events['release.update_status'] = function(notification){ var data = notification.data - if(data && self.data.id == data.movie_id){ + if(data && self.data._id == data.movie_id){ if(!self.data.releases) self.data.releases = []; - self.data.releases.push({'quality_identifier': data.quality_identifier, 'status': data.status}); + self.data.releases.push({'quality': data.quality, 'status': data.status}); self.updateReleases(); } } @@ -197,7 +197,7 @@ var Movie = new Class({ if(self.profile.data) self.profile.getTypes().each(function(type){ - var q = self.addQuality(type.quality_identifier || type.get('quality_identifier')); + var q = self.addQuality(type.get('quality')); if((type.finish == true || type.get('finish')) && !q.hasClass('finish')){ q.addClass('finish'); q.set('title', q.get('title') + ' Will finish searching for this movie if this quality is found.') @@ -222,11 +222,11 @@ var Movie = new Class({ self.data.releases.each(function(release){ - var q = self.quality.getElement('.q_id'+ release.quality_id), + var q = self.quality.getElement('.q_'+ release.quality), status = release.status; if(!q && (status == 'snatched' || status == 'seeding' || status == 'done')) - var q = self.addQuality(release.quality_identifier) + var q = self.addQuality(release.quality) if (q && !q.hasClass(status)){ q.addClass(status); @@ -236,13 +236,13 @@ var Movie = new Class({ }); }, - addQuality: function(quality_identifier){ + addQuality: function(quality){ var self = this; - var q = Quality.getQuality(quality_identifier); + var q = Quality.getQuality(quality); return new Element('span', { 'text': q.label, - 'class': 'q_'+q.identifier + ' q_id' + q.id, + 'class': 'q_'+q.identifier, 'title': '' }).inject(self.quality); diff --git a/couchpotato/core/media/movie/_base/static/search.js b/couchpotato/core/media/movie/_base/static/search.js index 6184214..edd1d23 100644 --- a/couchpotato/core/media/movie/_base/static/search.js +++ b/couchpotato/core/media/movie/_base/static/search.js @@ -184,7 +184,7 @@ Block.Search.MovieItem = new Class({ self.category_select.show(); categories.each(function(category){ new Element('option', { - 'value': category.data.id, + 'value': category.data._id, 'text': category.data.label }).inject(self.category_select); }); diff --git a/couchpotato/core/media/movie/searcher/main.py b/couchpotato/core/media/movie/searcher/main.py index 69615a1..cecfd72 100644 --- a/couchpotato/core/media/movie/searcher/main.py +++ b/couchpotato/core/media/movie/searcher/main.py @@ -139,7 +139,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): profile = db.get('id', movie['profile_id']) quality_order = fireEvent('quality.order', single = True) - media_releases = db.get_many('release', movie['_id']) + media_releases = db.run('release', 'for_media', movie['_id']) ret = False @@ -202,7 +202,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): fireEvent('notify.frontend', type = 'movie.searcher.ended', data = {'id': movie['_id']}) - pass #db.close() return ret def correctRelease(self, nzb = None, media = None, quality = None, **kwargs): diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py index 55cf706..bc42e45 100644 --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -1,12 +1,9 @@ -from couchpotato import get_session +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.plugins.base import Plugin -from couchpotato.core.settings.model import Media, Library from couchpotato.environment import Env -from sqlalchemy.orm import joinedload_all -from sqlalchemy.sql.expression import or_ class Suggestion(Plugin): @@ -28,12 +25,9 @@ class Suggestion(Plugin): else: if not movies or len(movies) == 0: - db = get_session() - active_movies = db.query(Media) \ - .options(joinedload_all('library')) \ - .filter(or_(*[Media.status.has(identifier = s) for s in ['active', 'done']])).all() - movies = [x.library.identifier for x in active_movies] - pass #db.close() + db = get_db() + active_movies = db.run('media', 'with_status', ['active', 'done']) + movies = [x['identifier'] for x in active_movies] if not ignored or len(ignored) == 0: ignored = splitString(Env.prop('suggest_ignore', default = '')) @@ -88,15 +82,10 @@ class Suggestion(Plugin): # Get new results and add them if len(new_suggestions) - 1 < limit: - - db = get_session() - active_movies = db.query(Media) \ - .join(Library) \ - .with_entities(Library.identifier) \ - .filter(Media.status_id.in_([active_status.get('id'), done_status.get('id')])).all() - movies = [x[0] for x in active_movies] + db = get_db() + active_movies = db.run('media', 'with_status', ['active', 'done']) + movies = [x['identifier'] for x in active_movies] movies.extend(seen) - pass #db.close() ignored.extend([x.get('imdb') for x in cached_suggestion]) suggestions = fireEvent('movie.suggest', movies = movies, ignore = removeDuplicate(ignored), single = True) diff --git a/couchpotato/core/notifications/core/static/notification.js b/couchpotato/core/notifications/core/static/notification.js index f8d4664..756c41e 100644 --- a/couchpotato/core/notifications/core/static/notification.js +++ b/couchpotato/core/notifications/core/static/notification.js @@ -77,7 +77,7 @@ var NotificationBase = new Class({ var ids = [] rn.each(function(n){ - ids.include(n.id) + ids.include(n._id) }) } @@ -187,7 +187,7 @@ var NotificationBase = new Class({ new Element('a.close.icon2', { 'events': { 'click': function(){ - self.markAsRead([data.id]); + self.markAsRead([data._id]); hide_message(); } } diff --git a/couchpotato/core/plugins/category/index.py b/couchpotato/core/plugins/category/index.py index 1eb3651..107f927 100644 --- a/couchpotato/core/plugins/category/index.py +++ b/couchpotato/core/plugins/category/index.py @@ -1,16 +1,29 @@ -from hashlib import md5 from CodernityDB.tree_index import TreeBasedIndex class CategoryIndex(TreeBasedIndex): def __init__(self, *args, **kwargs): - kwargs['key_format'] = '32s' + kwargs['key_format'] = 'i' super(CategoryIndex, self).__init__(*args, **kwargs) def make_key(self, key): - return md5(key).hexdigest() + return key def make_key_value(self, data): if data.get('_t') == 'category': - return md5(data['media_id']).hexdigest(), None + return data.get('order', -99), None + + +class CategoryMediaIndex(TreeBasedIndex): + + def __init__(self, *args, **kwargs): + kwargs['key_format'] = '32s' + super(CategoryMediaIndex, self).__init__(*args, **kwargs) + + def make_key(self, key): + return str(key) + + def make_key_value(self, data): + if data.get('_t') == 'media' and data.get('category_id'): + return str(data.get('category_id')), None diff --git a/couchpotato/core/plugins/category/main.py b/couchpotato/core/plugins/category/main.py index 52161c6..4761c11 100644 --- a/couchpotato/core/plugins/category/main.py +++ b/couchpotato/core/plugins/category/main.py @@ -1,12 +1,11 @@ import traceback -from couchpotato import get_session, get_db +from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import addEvent from couchpotato.core.helpers.encoding import toUnicode from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin -from .index import CategoryIndex -from couchpotato.core.settings.model import Media, Category +from .index import CategoryIndex, CategoryMediaIndex log = CPLog(__name__) @@ -32,18 +31,25 @@ class CategoryPlugin(Plugin): db = get_db() - # Release media_id index + # Category index try: db.add_index(CategoryIndex(db.path, 'category')) except: log.debug('Index already exists') db.edit_index(CategoryIndex(db.path, 'category')) + # Category media_id index + try: + db.add_index(CategoryMediaIndex(db.path, 'category_media')) + except: + log.debug('Index already exists') + db.edit_index(CategoryMediaIndex(db.path, 'category_media')) + def allView(self, **kwargs): return { 'success': True, - 'list': self.all() + 'categories': self.all() } def all(self): @@ -51,11 +57,7 @@ class CategoryPlugin(Plugin): db = get_db() categories = db.all('category', with_doc = True) - temp = [] - for category in categories: - temp.append(category['doc']) - - return temp + return [x['doc'] for x in categories] def save(self, **kwargs): @@ -63,7 +65,8 @@ class CategoryPlugin(Plugin): db = get_db() category = { - 'order': kwargs.get('order', 0), + '_t': 'category', + 'order': kwargs.get('order', 999), 'label': toUnicode(kwargs.get('label', '')), 'ignored': toUnicode(kwargs.get('ignored', '')), 'preferred': toUnicode(kwargs.get('preferred', '')), @@ -96,26 +99,21 @@ class CategoryPlugin(Plugin): def saveOrder(self, **kwargs): try: - db = get_session() + db = get_db() order = 0 for category_id in kwargs.get('ids', []): - c = db.query(Category).filter_by(id = category_id).first() - c.order = order + c = db.get('id', category_id) + c['order'] = order + db.update(c) order += 1 - db.commit() - - pass #db.close() return { 'success': True } except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() return { 'success': False @@ -124,32 +122,27 @@ class CategoryPlugin(Plugin): def delete(self, id = None, **kwargs): try: - db = get_session() + db = get_db() success = False message = '' try: - c = db.query(Category).filter_by(id = id).first() + c = db.get('id', id) db.delete(c) - db.commit() # Force defaults on all empty category movies self.removeFromMovie(id) success = True - except Exception as e: - message = log.error('Failed deleting category: %s', e) + except: + message = log.error('Failed deleting category: %s', traceback.format_exc()) - pass #db.close() return { 'success': success, 'message': message } except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() return { 'success': False @@ -158,15 +151,12 @@ class CategoryPlugin(Plugin): def removeFromMovie(self, category_id): try: - db = get_session() - movies = db.query(Media).filter(Media.category_id == category_id).all() + db = get_db() + movies = [x['doc'] for x in db.get_many('category_media', category_id, with_doc = True)] if len(movies) > 0: for movie in movies: - movie.category_id = None - db.commit() + movie['category_id'] = None + db.update(movie) except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() diff --git a/couchpotato/core/plugins/category/static/category.js b/couchpotato/core/plugins/category/static/category.js index 168b70d..fedd284 100644 --- a/couchpotato/core/plugins/category/static/category.js +++ b/couchpotato/core/plugins/category/static/category.js @@ -86,7 +86,7 @@ var CategoryListBase = new Class({ getCategory: function(id){ return this.categories.filter(function(category){ - return category.data.id == id + return category.data._id == id }).pick() }, @@ -121,7 +121,7 @@ var CategoryListBase = new Class({ ).inject(self.content) Array.each(self.categories, function(category){ - new Element('li', {'data-id': category.data.id}).adopt( + new Element('li', {'data-id': category.data._id}).adopt( new Element('span.category_label', { 'text': category.data.label }), @@ -258,7 +258,7 @@ var Category = new Class({ var self = this; var data = { - 'id' : self.data.id, + 'id' : self.data._id, 'label' : self.el.getElement('.category_label input').get('value'), 'required' : self.el.getElement('.category_required input').get('value'), 'preferred' : self.el.getElement('.category_preferred input').get('value'), @@ -271,7 +271,7 @@ var Category = new Class({ del: function(){ var self = this; - + if(self.data.label == undefined){ self.el.destroy(); return; @@ -286,7 +286,7 @@ var Category = new Class({ (e).preventDefault(); Api.request('category.delete', { 'data': { - 'id': self.data.id + 'id': self.data._id }, 'useSpinner': true, 'spinnerOptions': { @@ -329,4 +329,4 @@ var Category = new Class({ return this.el } -}); \ No newline at end of file +}); diff --git a/couchpotato/core/plugins/profile/main.py b/couchpotato/core/plugins/profile/main.py index 9033595..1c3ec63 100644 --- a/couchpotato/core/plugins/profile/main.py +++ b/couchpotato/core/plugins/profile/main.py @@ -1,8 +1,9 @@ import traceback -from couchpotato import get_session, get_db +from couchpotato import get_session, get_db, tryInt from couchpotato.api import addApiView from couchpotato.core.event import addEvent from couchpotato.core.helpers.encoding import toUnicode +from couchpotato.core.helpers.variable import splitString from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from .index import ProfileIndex @@ -78,45 +79,41 @@ class ProfilePlugin(Plugin): def save(self, **kwargs): try: - db = get_session() - - p = db.query(Profile).filter_by(id = kwargs.get('id')).first() - if not p: - p = Profile() - db.add(p) - - p.label = toUnicode(kwargs.get('label')) - p.order = kwargs.get('order', p.order if p.order else 0) - p.core = kwargs.get('core', False) + db = get_db() - #delete old types - [db.delete(t) for t in p.types] + profile = { + 'label': toUnicode(kwargs.get('label')), + 'order': tryInt(kwargs.get('order', 999)), + 'core': kwargs.get('core', False), + 'qualities': [], + 'wait_for': [], + 'finish': [] + } + # Update types order = 0 for type in kwargs.get('types', []): - t = ProfileType( - order = order, - finish = type.get('finish') if order > 0 else 1, - wait_for = kwargs.get('wait_for'), - quality_id = type.get('quality_id') - ) - p.types.append(t) - + profile['qualities'].append(type.get('quality')) + profile['wait_for'].append(tryInt(type.get('wait_for'))) + profile['finish'].append((tryInt(type.get('finish')) == 1) if order > 0 else True) order += 1 - db.commit() + id = kwargs.get('id') + try: + p = db.get('id', id) + except: + p = db.insert(profile) + p.update(profile) - profile_dict = p.to_dict(self.to_dict) + p['order'] = tryInt(kwargs.get('order', p.get('order', 999))) + db.update(p) return { 'success': True, - 'profile': profile_dict + 'profile': p } except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() return { 'success': False @@ -129,26 +126,23 @@ class ProfilePlugin(Plugin): def saveOrder(self, **kwargs): try: - db = get_session() + db = get_db() order = 0 - for profile in kwargs.get('ids', []): - p = db.query(Profile).filter_by(id = profile).first() - p.hide = kwargs.get('hidden')[order] - p.order = order - order += 1 + for profile_id in kwargs.get('ids', []): + p = db.get('id', profile_id) + p['hide'] = tryInt(kwargs.get('hidden')[order]) == 1 + p['order'] = order + db.update(p) - db.commit() + order += 1 return { 'success': True } except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() return { 'success': False @@ -180,9 +174,6 @@ class ProfilePlugin(Plugin): } except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() return { 'success': False diff --git a/couchpotato/core/plugins/profile/static/profile.js b/couchpotato/core/plugins/profile/static/profile.js index 2789e98..1bd2edc 100644 --- a/couchpotato/core/plugins/profile/static/profile.js +++ b/couchpotato/core/plugins/profile/static/profile.js @@ -57,14 +57,16 @@ var Profile = new Class({ self.makeSortable(); // Combine qualities and properties into types - data.types = []; - data.qualities.each(function(quality, nr){ - data.types.include({ - 'quality_identifier': quality, - 'finish': data.finish[nr] || false, - 'wait_for': data.wait_for[nr] || 0 - }) - }); + if(data.qualities){ + data.types = []; + data.qualities.each(function(quality, nr){ + data.types.include({ + 'quality': quality, + 'finish': data.finish[nr] || false, + 'wait_for': data.wait_for[nr] || 0 + }) + }); + } if(data.types) data.types.each(self.addType.bind(self)); @@ -112,16 +114,16 @@ var Profile = new Class({ var self = this; var data = { - 'id' : self.data.id, + 'id' : self.data._id, 'label' : self.el.getElement('.quality_label input').get('value'), 'wait_for' : self.el.getElement('.wait_for input').get('value'), 'types': [] } Array.each(self.type_container.getElements('.type'), function(type){ - if(!type.hasClass('deleted') && type.getElement('select').get('value') > 0) + if(!type.hasClass('deleted') && type.getElement('select').get('value') != -1) data.types.include({ - 'quality_identifier': type.getElement('select').get('value'), + 'quality': type.getElement('select').get('value'), 'finish': +type.getElement('input[type=checkbox]').checked, 'wait_for': 0 }); @@ -156,7 +158,7 @@ var Profile = new Class({ var self = this; return self.types.filter(function(type){ - return type.get('quality_identifier') + return type.get('quality') }); }, @@ -173,7 +175,7 @@ var Profile = new Class({ (e).preventDefault(); Api.request('profile.delete', { 'data': { - 'id': self.data.id + 'id': self.data._id }, 'useSpinner': true, 'spinnerOptions': { @@ -275,7 +277,7 @@ Profile.Type = new Class({ new Element('span.handle') ); - self.el[self.data.quality_identifier ? 'removeClass' : 'addClass']('is_empty'); + self.el[self.data.quality ? 'removeClass' : 'addClass']('is_empty'); self.finish_class = new Form.Check(self.finish); @@ -302,7 +304,7 @@ Profile.Type = new Class({ }).inject(self.qualities) }); - self.qualities.set('value', self.data.quality_identifier); + self.qualities.set('value', self.data.quality); return self.qualities; @@ -312,7 +314,7 @@ Profile.Type = new Class({ var self = this; return { - 'quality_identifier': self.qualities.get('value'), + 'quality': self.qualities.get('value'), 'finish': +self.finish.checked, 'wait_for': 0 } diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index e75eb46..265cdf2 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -138,9 +138,6 @@ class QualityPlugin(Plugin): } except: log.error('Failed: %s', traceback.format_exc()) - db.rollback() - finally: - pass #db.close() return { 'success': False diff --git a/couchpotato/core/plugins/quality/static/quality.js b/couchpotato/core/plugins/quality/static/quality.js index af01775..613096f 100644 --- a/couchpotato/core/plugins/quality/static/quality.js +++ b/couchpotato/core/plugins/quality/static/quality.js @@ -117,7 +117,7 @@ var QualityBase = new Class({ Array.each(self.profiles, function(profile){ var check; - new Element('li', {'data-id': profile.data.id}).adopt( + new Element('li', {'data-id': profile.data._id}).adopt( check = new Element('input.inlay[type=checkbox]', { 'checked': !profile.data.hide, 'events': { diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 7cb634b..bd805fd 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -42,18 +42,11 @@ class Release(Plugin): 'id': {'type': 'id', 'desc': 'ID of the release object in release-table'} } }) - addApiView('release.for_movie', self.forMovieView, docs = { - 'desc': 'Returns all releases for a movie. Ordered by score(desc)', - 'params': { - 'id': {'type': 'id', 'desc': 'ID of the movie'} - } - }) addEvent('release.add', self.add) addEvent('release.download', self.download) addEvent('release.try_download_result', self.tryDownloadResult) addEvent('release.create_from_search', self.createFromSearch) - addEvent('release.for_movie', self.forMovie) addEvent('release.delete', self.delete) addEvent('release.clean', self.clean) addEvent('release.update_status', self.updateStatus) @@ -266,7 +259,6 @@ class Release(Plugin): if success: fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Successfully snatched "%s"' % item['name']) - pass #db.close() return { 'success': success == True } @@ -352,10 +344,7 @@ class Release(Plugin): except: log.error('Failed storing download status: %s', traceback.format_exc()) - db.rollback() return False - finally: - pass #db.close() return True @@ -431,31 +420,6 @@ class Release(Plugin): return [] - def forMovie(self, id = None): - - db = get_session() - - releases_raw = db.query(Relea) \ - .options(joinedload_all('info')) \ - .options(joinedload_all('files')) \ - .filter(Relea.movie_id == id) \ - .all() - - releases = [r.to_dict({'info': {}, 'files': {}}) for r in releases_raw] - releases = sorted(releases, key = lambda k: k['info'].get('score', 0), reverse = True) - - pass #db.close() - return releases - - def forMovieView(self, id = None, **kwargs): - - releases = self.forMovie(id) - - return { - 'releases': releases, - 'success': True - } - def updateStatus(self, release_id, status = None): if not status: return False diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 799b177..c26de9e 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -591,7 +591,6 @@ class Renamer(Plugin): break self.renaming_started = False - pass #db.close() def getRenameExtras(self, extra_type = '', replacements = None, folder_name = '', file_name = '', destination = '', group = None, current_file = '', remove_multiple = False): if not group: group = {} @@ -845,7 +844,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.get_many('release', 'with_status', ['snatched', 'seeding', 'missing'])) + rels = list(db.run('release', 'with_status', ['snatched', 'seeding', 'missing'])) if not rels: #No releases found that need status checking @@ -1058,8 +1057,6 @@ Remove it if you want it to be renamed (again, or at least let it try again) if not rls: log.error('Download ID %s from downloader %s not found in releases', (release_download.get('id'), release_download.get('downloader'))) - pass #db.close() - if rls: rls_dict = rls.to_dict({'info':{}}) diff --git a/couchpotato/core/plugins/scanner/main.py b/couchpotato/core/plugins/scanner/main.py index f9ccea7..744c7bd 100644 --- a/couchpotato/core/plugins/scanner/main.py +++ b/couchpotato/core/plugins/scanner/main.py @@ -1,11 +1,9 @@ -from couchpotato import get_session from couchpotato.core.event import fireEvent, addEvent -from couchpotato.core.helpers.encoding import toUnicode, simplifyString, ss, sp +from couchpotato.core.helpers.encoding import toUnicode, simplifyString, sp from couchpotato.core.helpers.variable import getExt, getImdb, tryInt, \ splitString from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin -from couchpotato.core.settings.model import File from enzyme.exceptions import NoParserError, ParseError from guessit import guess_movie_info from subliminal.videos import Video @@ -352,7 +350,6 @@ class Scanner(Plugin): release_download = None # Determine file types - db = get_session() processed_movies = {} while True and not self.shuttingDown(): try: @@ -439,7 +436,6 @@ class Scanner(Plugin): else: log.debug('Found no movies in the folder %s', folder) - pass #db.close() return processed_movies def getMetaData(self, group, folder = '', release_download = None): @@ -594,21 +590,6 @@ class Scanner(Plugin): except: pass - # Check if path is already in db - if not imdb_id: - - db = get_session() - for cf in files['movie']: - f = db.query(File).filter_by(path = toUnicode(cf)).first() - try: - imdb_id = f.library[0].identifier - log.debug('Found movie via database: %s', cf) - cur_file = cf - break - except: - pass - pass #db.close() - # Search based on identifiers if not imdb_id: for identifier in group['identifiers']: diff --git a/couchpotato/core/plugins/subtitle/main.py b/couchpotato/core/plugins/subtitle/main.py index a3b1d13..c00c757 100644 --- a/couchpotato/core/plugins/subtitle/main.py +++ b/couchpotato/core/plugins/subtitle/main.py @@ -1,10 +1,8 @@ -from couchpotato import get_session -from couchpotato.core.event import addEvent, fireEvent +from couchpotato.core.event import addEvent from couchpotato.core.helpers.encoding import toUnicode, sp from couchpotato.core.helpers.variable import splitString from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin -from couchpotato.core.settings.model import Library, FileType from couchpotato.environment import Env import subliminal import traceback @@ -19,29 +17,6 @@ class Subtitle(Plugin): def __init__(self): addEvent('renamer.before', self.searchSingle) - def searchLibrary(self): - - # Get all active and online movies - db = get_session() - - library = db.query(Library).all() - - for movie in library.movies: - - for release in movie.releases: - - # get releases and their movie files - if release.get('status') == 'done': - - files = [] - for file in release.files.filter(FileType.status.has(identifier = 'movie')).all(): - files.append(file.path) - - # get subtitles for those files - subliminal.list_subtitles(files, cache_dir = Env.get('cache_dir'), multi = True, languages = self.getLanguages(), services = self.services) - - pass #db.close() - def searchSingle(self, group): if self.isDisabled(): return diff --git a/couchpotato/core/providers/info/_modifier/main.py b/couchpotato/core/providers/info/_modifier/main.py index 09d1925..010f1f5 100644 --- a/couchpotato/core/providers/info/_modifier/main.py +++ b/couchpotato/core/providers/info/_modifier/main.py @@ -100,7 +100,7 @@ class MovieResultModifier(Plugin): if media.get('status') == 'active': temp['in_wanted'] = media - for release in db.get_many('release', media.get('_id'), with_doc = True): + for release in db.run('release', 'for_media', media.get('_id')): if release.get('status') == 'done': temp['in_library'] = media except: diff --git a/couchpotato/core/providers/nzb/newznab/__init__.py b/couchpotato/core/providers/nzb/newznab/__init__.py index 97f1cfa..86a25a4 100644 --- a/couchpotato/core/providers/nzb/newznab/__init__.py +++ b/couchpotato/core/providers/nzb/newznab/__init__.py @@ -29,7 +29,7 @@ config = [{ }, { 'name': 'host', - 'default': 'nzb.su,dognzb.cr,nzbs.org,https://index.nzbgeek.info, https://smackdownonyou.com, https://www.nzbfinder.ws', + 'default': 'api.nzb.su,dognzb.cr,nzbs.org,https://index.nzbgeek.info, https://smackdownonyou.com, https://www.nzbfinder.ws', 'description': 'The hostname of your newznab provider', }, { diff --git a/couchpotato/core/settings/__init__.py b/couchpotato/core/settings/__init__.py index fcea04f..23f48b1 100644 --- a/couchpotato/core/settings/__init__.py +++ b/couchpotato/core/settings/__init__.py @@ -228,7 +228,7 @@ class Settings(object): propert = db.get('property', identifier, with_doc = True) prop = propert['doc']['value'] except: - self.log.debug('Property doesn\'t exist: %s', traceback.format_exc(0)) + self.log.debug('Property "%s" doesn\'t exist: %s', (identifier, traceback.format_exc(0))) return prop diff --git a/couchpotato/runner.py b/couchpotato/runner.py index e3f0785..d6a967c 100644 --- a/couchpotato/runner.py +++ b/couchpotato/runner.py @@ -86,8 +86,6 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En db_path = toUnicode(os.path.join(data_dir, 'database')) # Check if database exists - print db_path - db = ThreadSafeDatabase(db_path) db_exists = db.exists() if db_exists: diff --git a/couchpotato/static/scripts/page/home.js b/couchpotato/static/scripts/page/home.js index 818ce0e..dbf8d7b 100644 --- a/couchpotato/static/scripts/page/home.js +++ b/couchpotato/static/scripts/page/home.js @@ -62,7 +62,7 @@ Page.Home = new Class({ // Track movie added var after_search = function(data){ - if(notification.data.id != data.data.id) return; + if(notification.data._id != data.data._id) return; // Force update after search self.available_list.update();