From e7be5c7809ec1db9e0589e685741a1b83b74a938 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 25 Jul 2014 10:52:53 +1200 Subject: [PATCH 01/16] Added "library.related" event and "library.query", "library.related" API calls --- couchpotato/core/media/_base/library/main.py | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index a723de5..2eccfce 100644 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -1,10 +1,35 @@ +from couchpotato import get_db +from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent +from couchpotato.core.logger import CPLog from couchpotato.core.media._base.library.base import LibraryBase +log = CPLog(__name__) + class Library(LibraryBase): def __init__(self): addEvent('library.title', self.title) + addEvent('library.related', self.related) + + addApiView('library.query', self.queryView) + addApiView('library.related', self.relatedView) + + def queryView(self, media_id, **kwargs): + db = get_db() + media = db.get('id', media_id) + + return { + 'result': fireEvent('library.query', media, single = True) + } + + def relatedView(self, media_id, **kwargs): + db = get_db() + media = db.get('id', media_id) + + return { + 'result': fireEvent('library.related', media, single = True) + } def title(self, library): return fireEvent( @@ -16,3 +41,16 @@ class Library(LibraryBase): include_identifier = False, single = True ) + + def related(self, media): + result = {media['type']: media} + + db = get_db() + cur = media + + while cur and cur.get('parent_id'): + cur = db.get('id', cur['parent_id']) + + result[cur['type']] = cur + + return result From a1ce3e0d6ba5633992ad5f69f90c8b31ebfda8e0 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Wed, 20 Aug 2014 14:54:24 +1200 Subject: [PATCH 02/16] Added "library.root" event, fixes to "matcher", "release" and "score" to use "library.root" + handle missing "year" --- couchpotato/core/media/_base/library/main.py | 10 ++++++++++ couchpotato/core/media/_base/matcher/main.py | 6 +++--- couchpotato/core/plugins/release/main.py | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index 2eccfce..b90f4c3 100644 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -11,6 +11,7 @@ class Library(LibraryBase): def __init__(self): addEvent('library.title', self.title) addEvent('library.related', self.related) + addEvent('library.root', self.root) addApiView('library.query', self.queryView) addApiView('library.related', self.relatedView) @@ -54,3 +55,12 @@ class Library(LibraryBase): result[cur['type']] = cur return result + + def root(self, media): + db = get_db() + cur = media + + while cur and cur.get('parent_id'): + cur = db.get('id', cur['parent_id']) + + return cur diff --git a/couchpotato/core/media/_base/matcher/main.py b/couchpotato/core/media/_base/matcher/main.py index 2034249..64e13ae 100644 --- a/couchpotato/core/media/_base/matcher/main.py +++ b/couchpotato/core/media/_base/matcher/main.py @@ -40,7 +40,7 @@ class Matcher(MatcherBase): return False def correctTitle(self, chain, media): - root_library = media['library']['root_library'] + root = fireEvent('library.root', media, single = True) if 'show_name' not in chain.info or not len(chain.info['show_name']): log.info('Wrong: missing show name in parsed result') @@ -50,10 +50,10 @@ class Matcher(MatcherBase): chain_words = [x.lower() for x in chain.info['show_name']] # Build a list of possible titles of the media we are searching for - titles = root_library['info']['titles'] + titles = root['info']['titles'] # Add year suffix titles (will result in ['', ' ', '', ...]) - suffixes = [None, root_library['info']['year']] + suffixes = [None, root['info']['year']] titles = [ title + ((' %s' % suffix) if suffix else '') diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index b1ecafd..e4bfdc2 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -325,7 +325,7 @@ class Release(Plugin): rls['download_info'] = download_result db.update(rls) - log_movie = '%s (%s) in %s' % (getTitle(media), media['info']['year'], rls['quality']) + log_movie = '%s (%s) in %s' % (getTitle(media), media['info'].get('year'), rls['quality']) snatch_message = 'Snatched "%s": %s' % (data.get('name'), log_movie) log.info(snatch_message) fireEvent('%s.snatched' % data['type'], message = snatch_message, data = media) From a821d85bf2c80b3c30e0bfb75e29c6e2694e3e5f Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 25 Jul 2014 13:44:18 +1200 Subject: [PATCH 03/16] Fixed MediaBase.getPoster(), switched MovieBase to use this generic method --- couchpotato/core/media/__init__.py | 9 ++++++--- couchpotato/core/media/movie/_base/main.py | 32 +++--------------------------- 2 files changed, 9 insertions(+), 32 deletions(-) mode change 100644 => 100755 couchpotato/core/media/__init__.py mode change 100644 => 100755 couchpotato/core/media/movie/_base/main.py diff --git a/couchpotato/core/media/__init__.py b/couchpotato/core/media/__init__.py old mode 100644 new mode 100755 index 4a3eb68..4e319fc --- a/couchpotato/core/media/__init__.py +++ b/couchpotato/core/media/__init__.py @@ -65,10 +65,13 @@ class MediaBase(Plugin): return def_title or 'UNKNOWN' - def getPoster(self, image_urls, existing_files): - image_type = 'poster' + def getPoster(self, media, image_urls): + if 'files' not in media: + media['files'] = {} + + existing_files = media['files'] - # Remove non-existing files + image_type = 'poster' file_type = 'image_%s' % image_type # Make existing unique diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py old mode 100644 new mode 100755 index 336d803..3afe1e8 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -312,37 +312,11 @@ class MovieBase(MovieTypeBase): media['title'] = def_title # Files - images = info.get('images', []) - media['files'] = media.get('files', {}) - for image_type in ['poster']: - - # Remove non-existing files - file_type = 'image_%s' % image_type - existing_files = list(set(media['files'].get(file_type, []))) - for ef in media['files'].get(file_type, []): - if not os.path.isfile(ef): - existing_files.remove(ef) - - # Replace new files list - media['files'][file_type] = existing_files - if len(existing_files) == 0: - del media['files'][file_type] - - # Loop over type - for image in images.get(image_type, []): - if not isinstance(image, (str, unicode)): - continue - - if file_type not in media['files'] or len(media['files'].get(file_type, [])) == 0: - file_path = fireEvent('file.download', url = image, single = True) - if file_path: - media['files'][file_type] = [file_path] - break - else: - break + image_urls = info.get('images', []) - db.update(media) + self.getPoster(media, image_urls) + db.update(media) return media except: log.error('Failed update media: %s', traceback.format_exc()) From a366d57278c8dd6c95953a4d989011b16fffb2cb Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 25 Jul 2014 16:56:09 +1200 Subject: [PATCH 04/16] Added "library.tree" event/api call --- couchpotato/core/media/_base/library/main.py | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) mode change 100644 => 100755 couchpotato/core/media/_base/library/main.py diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py old mode 100644 new mode 100755 index b90f4c3..d20342f --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -11,10 +11,13 @@ class Library(LibraryBase): def __init__(self): addEvent('library.title', self.title) addEvent('library.related', self.related) + addEvent('library.tree', self.tree) + addEvent('library.root', self.root) addApiView('library.query', self.queryView) addApiView('library.related', self.relatedView) + addApiView('library.tree', self.treeView) def queryView(self, media_id, **kwargs): db = get_db() @@ -32,6 +35,14 @@ class Library(LibraryBase): 'result': fireEvent('library.related', media, single = True) } + def treeView(self, media_id, **kwargs): + db = get_db() + media = db.get('id', media_id) + + return { + 'result': fireEvent('library.tree', media, single = True) + } + def title(self, library): return fireEvent( 'library.query', @@ -64,3 +75,33 @@ class Library(LibraryBase): cur = db.get('id', cur['parent_id']) return cur + + def tree(self, media): + result = media + + db = get_db() + + # TODO this probably should be using an index? + items = [ + item['doc'] + for item in db.all('media', with_doc = True) + if item['doc'].get('parent_id') == media['_id'] + ] + + keys = [] + + for item in items: + key = item['type'] + 's' + + if key not in result: + result[key] = {} + + if key not in keys: + keys.append(key) + + result[key][item['_id']] = fireEvent('library.tree', item, single = True) + + for key in keys: + result[key] = result[key].values() + + return result From f2b0d3f80bcd41f062ee3a68e9de4b959c5ec719 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sat, 26 Jul 2014 13:54:55 +1200 Subject: [PATCH 05/16] Switched "library.tree" to use "media_children" index --- couchpotato/core/media/_base/library/main.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index d20342f..c0e4464 100755 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -80,18 +80,12 @@ class Library(LibraryBase): result = media db = get_db() - - # TODO this probably should be using an index? - items = [ - item['doc'] - for item in db.all('media', with_doc = True) - if item['doc'].get('parent_id') == media['_id'] - ] + items = db.get_many('media_children', media['_id'], with_doc = True) keys = [] for item in items: - key = item['type'] + 's' + key = item['doc']['type'] + 's' if key not in result: result[key] = {} @@ -99,7 +93,7 @@ class Library(LibraryBase): if key not in keys: keys.append(key) - result[key][item['_id']] = fireEvent('library.tree', item, single = True) + result[key][item['_id']] = fireEvent('library.tree', item['doc'], single = True) for key in keys: result[key] = result[key].values() From d75f58f5ecb5042e58ac6cd59af3877ea2be9c34 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sat, 26 Jul 2014 22:29:16 +1200 Subject: [PATCH 06/16] Fixed "library.related" and "libary.tree" to work with "show.episode", 'show.season" media types --- couchpotato/core/media/_base/library/main.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index c0e4464..b565d16 100755 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -63,7 +63,9 @@ class Library(LibraryBase): while cur and cur.get('parent_id'): cur = db.get('id', cur['parent_id']) - result[cur['type']] = cur + parts = cur['type'].split('.') + + result[parts[-1]] = cur return result @@ -85,7 +87,8 @@ class Library(LibraryBase): keys = [] for item in items: - key = item['doc']['type'] + 's' + parts = item['doc']['type'].split('.') + key = parts[-1] + 's' if key not in result: result[key] = {} From cd836f36606f0666de844ff430e41f8f904f930a Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sun, 27 Jul 2014 01:03:58 +1200 Subject: [PATCH 07/16] Include releases in "library.tree" --- couchpotato/core/media/_base/library/main.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index b565d16..2f5629d 100755 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -82,10 +82,12 @@ class Library(LibraryBase): result = media db = get_db() - items = db.get_many('media_children', media['_id'], with_doc = True) + # Find children + items = db.get_many('media_children', media['_id'], with_doc = True) keys = [] + # Build children arrays for item in items: parts = item['doc']['type'].split('.') key = parts[-1] + 's' @@ -98,7 +100,11 @@ class Library(LibraryBase): result[key][item['_id']] = fireEvent('library.tree', item['doc'], single = True) + # Unique children for key in keys: result[key] = result[key].values() + # Include releases + result['releases'] = fireEvent('release.for_media', media['_id'], single = True) + return result From 058846f54fabd42529c8172280c46a5189251d16 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Mon, 28 Jul 2014 16:06:05 +1200 Subject: [PATCH 08/16] Added "find" helper function --- couchpotato/core/helpers/variable.py | 8 ++++++++ 1 file changed, 8 insertions(+) mode change 100644 => 100755 couchpotato/core/helpers/variable.py diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py old mode 100644 new mode 100755 index fc844aa..db68da2 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -380,3 +380,11 @@ def getFreeSpace(directories): free_space[folder] = size return free_space + + +def find(func, iterable): + for item in iterable: + if func(item): + return item + + return None From 3869e350bf14735298eaafc9026fd5ef11276a7d Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Mon, 28 Jul 2014 16:06:51 +1200 Subject: [PATCH 09/16] Added "media_id" parameter to "library.tree" event --- couchpotato/core/media/_base/library/main.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index 2f5629d..da526ec 100755 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -78,13 +78,18 @@ class Library(LibraryBase): return cur - def tree(self, media): - result = media - + def tree(self, media = None, media_id = None): db = get_db() + if media: + result = media + elif media_id: + result = db.get('id', media_id, with_doc = True) + else: + return None + # Find children - items = db.get_many('media_children', media['_id'], with_doc = True) + items = db.get_many('media_children', result['_id'], with_doc = True) keys = [] # Build children arrays @@ -94,6 +99,8 @@ class Library(LibraryBase): if key not in result: result[key] = {} + elif type(result[key]) is not dict: + result[key] = {} if key not in keys: keys.append(key) @@ -105,6 +112,6 @@ class Library(LibraryBase): result[key] = result[key].values() # Include releases - result['releases'] = fireEvent('release.for_media', media['_id'], single = True) + result['releases'] = fireEvent('release.for_media', result['_id'], single = True) return result From 072b6d09fad404ddba9b97fbac5f78bd9afe9dcf Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Mon, 28 Jul 2014 19:54:06 +1200 Subject: [PATCH 10/16] Renamed "[media].update_info" event to "[media].update" --- couchpotato/core/media/_base/media/main.py | 2 +- couchpotato/core/media/movie/_base/main.py | 8 ++++---- couchpotato/core/media/movie/providers/metadata/base.py | 2 +- couchpotato/core/media/movie/searcher.py | 2 +- couchpotato/core/plugins/manage.py | 2 +- couchpotato/core/plugins/renamer.py | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) mode change 100644 => 100755 couchpotato/core/media/_base/media/main.py mode change 100644 => 100755 couchpotato/core/media/movie/providers/metadata/base.py mode change 100644 => 100755 couchpotato/core/media/movie/searcher.py mode change 100644 => 100755 couchpotato/core/plugins/manage.py mode change 100644 => 100755 couchpotato/core/plugins/renamer.py diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py old mode 100644 new mode 100755 index ee9e6cc..a5a1bbd --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -109,7 +109,7 @@ class MediaPlugin(MediaBase): try: media = get_db().get('id', media_id) - event = '%s.update_info' % media.get('type') + event = '%s.update' % media.get('type') def handler(): fireEvent(event, media_id = media_id, on_complete = self.createOnComplete(media_id)) diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 3afe1e8..8a04d0b 100755 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -46,7 +46,7 @@ class MovieBase(MovieTypeBase): }) addEvent('movie.add', self.add) - addEvent('movie.update_info', self.updateInfo) + addEvent('movie.update', self.update) addEvent('movie.update_release_dates', self.updateReleaseDate) def add(self, params = None, force_readd = True, search_after = True, update_after = True, notify_after = True, status = None): @@ -172,7 +172,7 @@ class MovieBase(MovieTypeBase): # Trigger update info if added and update_after: # Do full update to get images etc - fireEventAsync('movie.update_info', m['_id'], default_title = params.get('title'), on_complete = onComplete) + fireEventAsync('movie.update', m['_id'], default_title = params.get('title'), on_complete = onComplete) # Remove releases for rel in fireEvent('release.for_media', m['_id'], single = True): @@ -256,7 +256,7 @@ class MovieBase(MovieTypeBase): 'success': False, } - def updateInfo(self, media_id = None, identifier = None, default_title = None, extended = False): + def update(self, media_id = None, identifier = None, default_title = None, extended = False): """ Update movie information inside media['doc']['info'] @@ -337,7 +337,7 @@ class MovieBase(MovieTypeBase): media = db.get('id', media_id) if not media.get('info'): - media = self.updateInfo(media_id) + media = self.update(media_id) dates = media.get('info', {}).get('release_date') else: dates = media.get('info').get('release_date') diff --git a/couchpotato/core/media/movie/providers/metadata/base.py b/couchpotato/core/media/movie/providers/metadata/base.py old mode 100644 new mode 100755 index 7968000..cc914af --- a/couchpotato/core/media/movie/providers/metadata/base.py +++ b/couchpotato/core/media/movie/providers/metadata/base.py @@ -28,7 +28,7 @@ class MovieMetaData(MetaDataBase): # Update library to get latest info try: - group['media'] = fireEvent('movie.update_info', group['media'].get('_id'), identifier = getIdentifier(group['media']), extended = True, single = True) + group['media'] = fireEvent('movie.update', group['media'].get('_id'), identifier = getIdentifier(group['media']), extended = True, single = True) except: log.error('Failed to update movie, before creating metadata: %s', traceback.format_exc()) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py old mode 100644 new mode 100755 index 4bd8c8d..e943c21 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -94,7 +94,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): self.single(media, search_protocols, manual = manual) except IndexError: log.error('Forcing library update for %s, if you see this often, please report: %s', (getIdentifier(media), traceback.format_exc())) - fireEvent('movie.update_info', media_id) + fireEvent('movie.update', media_id) except: log.error('Search failed for %s: %s', (getIdentifier(media), traceback.format_exc())) diff --git a/couchpotato/core/plugins/manage.py b/couchpotato/core/plugins/manage.py old mode 100644 new mode 100755 index c8d53ea..d389e22 --- a/couchpotato/core/plugins/manage.py +++ b/couchpotato/core/plugins/manage.py @@ -219,7 +219,7 @@ class Manage(Plugin): # Add it to release and update the info fireEvent('release.add', group = group, update_info = False) - fireEvent('movie.update_info', identifier = group['identifier'], on_complete = self.createAfterUpdate(folder, group['identifier'])) + fireEvent('movie.update', identifier = group['identifier'], on_complete = self.createAfterUpdate(folder, group['identifier'])) return addToLibrary diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py old mode 100644 new mode 100755 index ad72086..d47d87f --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -247,7 +247,7 @@ class Renamer(Plugin): 'profile_id': None }, search_after = False, status = 'done', single = True) else: - group['media'] = fireEvent('movie.update_info', media_id = group['media'].get('_id'), single = True) + group['media'] = fireEvent('movie.update', media_id = group['media'].get('_id'), single = True) if not group['media'] or not group['media'].get('_id'): log.error('Could not rename, no library item to work with: %s', group_identifier) From 7df92f2882716b95f1fba4160439b4a6bb120e74 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Mon, 28 Jul 2014 20:33:50 +1200 Subject: [PATCH 11/16] Fix possible dashboard error, add "types" parameter to "media.with_status", limit suggestions to movies (for now) --- couchpotato/core/media/_base/media/main.py | 9 ++++++++- couchpotato/core/media/movie/suggestion/main.py | 2 +- couchpotato/core/plugins/dashboard.py | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) mode change 100644 => 100755 couchpotato/core/media/movie/suggestion/main.py diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index a5a1bbd..bcb8402 100755 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -160,10 +160,13 @@ class MediaPlugin(MediaBase): 'media': media, } - def withStatus(self, status, with_doc = True): + def withStatus(self, status, types = None, with_doc = True): db = get_db() + if types and not isinstance(types, (list, tuple)): + types = [types] + status = list(status if isinstance(status, (list, tuple)) else [status]) for s in status: @@ -171,6 +174,10 @@ class MediaPlugin(MediaBase): if with_doc: try: doc = db.get('id', ms['_id']) + + if types and doc.get('type') not in types: + continue + yield doc except RecordNotFound: log.debug('Record not found, skipping: %s', ms['_id']) diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py old mode 100644 new mode 100755 index 146a6a0..3df67ab --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -27,7 +27,7 @@ class Suggestion(Plugin): else: if not movies or len(movies) == 0: - active_movies = fireEvent('media.with_status', ['active', 'done'], single = True) + active_movies = fireEvent('media.with_status', ['active', 'done'], 'movie', single = True) movies = [getIdentifier(x) for x in active_movies] if not ignored or len(ignored) == 0: diff --git a/couchpotato/core/plugins/dashboard.py b/couchpotato/core/plugins/dashboard.py index 776f24e..d8ea4c9 100644 --- a/couchpotato/core/plugins/dashboard.py +++ b/couchpotato/core/plugins/dashboard.py @@ -62,7 +62,7 @@ class Dashboard(Plugin): for media_id in active_ids: media = db.get('id', media_id) - pp = profile_pre.get(media['profile_id']) + pp = profile_pre.get(media.get('profile_id')) if not pp: continue eta = media['info'].get('release_date', {}) or {} From e2df3a4dfd6fc8e39a93e07e232799962aff4e10 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sun, 3 Aug 2014 22:04:49 +1200 Subject: [PATCH 12/16] Added children to "library.related" --- couchpotato/core/media/_base/library/main.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/couchpotato/core/media/_base/library/main.py b/couchpotato/core/media/_base/library/main.py index da526ec..9e614fb 100755 --- a/couchpotato/core/media/_base/library/main.py +++ b/couchpotato/core/media/_base/library/main.py @@ -55,7 +55,7 @@ class Library(LibraryBase): ) def related(self, media): - result = {media['type']: media} + result = {self.key(media['type']): media} db = get_db() cur = media @@ -63,9 +63,17 @@ class Library(LibraryBase): while cur and cur.get('parent_id'): cur = db.get('id', cur['parent_id']) - parts = cur['type'].split('.') + result[self.key(cur['type'])] = cur - result[parts[-1]] = cur + children = db.get_many('media_children', media['_id'], with_doc = True) + + for item in children: + key = self.key(item['doc']['type']) + 's' + + if key not in result: + result[key] = [] + + result[key].append(item['doc']) return result @@ -94,8 +102,7 @@ class Library(LibraryBase): # Build children arrays for item in items: - parts = item['doc']['type'].split('.') - key = parts[-1] + 's' + key = self.key(item['doc']['type']) + 's' if key not in result: result[key] = {} @@ -115,3 +122,7 @@ class Library(LibraryBase): result['releases'] = fireEvent('release.for_media', result['_id'], single = True) return result + + def key(self, media_type): + parts = media_type.split('.') + return parts[-1] From 81d4d9a4e255de40bae424cb50eb428be0471227 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Thu, 7 Aug 2014 14:05:05 +1200 Subject: [PATCH 13/16] Changed "media.with_identifiers" to remove "No media found with..." messages --- couchpotato/core/media/_base/media/main.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index bcb8402..7021f82 100755 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -185,17 +185,15 @@ class MediaPlugin(MediaBase): yield ms def withIdentifiers(self, identifiers, with_doc = False): - db = get_db() for x in identifiers: try: - media = db.get('media', '%s-%s' % (x, identifiers[x]), with_doc = with_doc) - return media + return db.get('media', '%s-%s' % (x, identifiers[x]), with_doc = with_doc) except: pass - log.debug('No media found with identifiers: %s', identifiers) + return False def list(self, types = None, status = None, release_status = None, status_or = False, limit_offset = None, with_tags = None, starts_with = None, search = None): From c381b719b111ff41974d778014b5b2ecd673bd8d Mon Sep 17 00:00:00 2001 From: seedzero Date: Tue, 29 Jul 2014 18:13:02 +1000 Subject: [PATCH 14/16] Stop movie searcher searching for TV shows and hosing episodes --- couchpotato/core/media/movie/searcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index e943c21..a8d6fe5 100755 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -74,7 +74,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): self.in_progress = True fireEvent('notify.frontend', type = 'movie.searcher.started', data = True, message = 'Full search started') - medias = [x['_id'] for x in fireEvent('media.with_status', 'active', with_doc = False, single = True)] + medias = [x['_id'] for x in fireEvent('media.with_status', 'active', 'movie', single = True)] random.shuffle(medias) total = len(medias) From 436883a96d09bbe9007c4eea8baf711b1ed28537 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Wed, 20 Aug 2014 14:59:57 +1200 Subject: [PATCH 15/16] Fixed media.types & addSingleListView addSingleCharView, addSingleDeleteView Conflicts: couchpotato/core/media/show/_base/main.py --- couchpotato/core/media/_base/media/main.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 7021f82..8adc666 100755 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -312,8 +312,7 @@ class MediaPlugin(MediaBase): def addSingleListView(self): for media_type in fireEvent('media.types', merge = True): - def tempList(*args, **kwargs): - return self.listView(types = media_type, **kwargs) + tempList = lambda media_type = media_type, *args, **kwargs : self.listView(type = media_type, **kwargs) addApiView('%s.list' % media_type, tempList) def availableChars(self, types = None, status = None, release_status = None): @@ -381,8 +380,7 @@ class MediaPlugin(MediaBase): def addSingleCharView(self): for media_type in fireEvent('media.types', merge = True): - def tempChar(*args, **kwargs): - return self.charView(types = media_type, **kwargs) + tempChar = lambda media_type = media_type, *args, **kwargs : self.charView(type = media_type, **kwargs) addApiView('%s.available_chars' % media_type, tempChar) def delete(self, media_id, delete_from = None): @@ -451,8 +449,7 @@ class MediaPlugin(MediaBase): def addSingleDeleteView(self): for media_type in fireEvent('media.types', merge = True): - def tempDelete(*args, **kwargs): - return self.deleteView(types = media_type, *args, **kwargs) + tempDelete = lambda media_type = media_type, *args, **kwargs : self.deleteView(type = media_type, **kwargs) addApiView('%s.delete' % media_type, tempDelete) def restatus(self, media_id): From cfd92b826869791b46142bff956642d7fbd5c876 Mon Sep 17 00:00:00 2001 From: seedzero Date: Tue, 19 Aug 2014 01:36:12 +1000 Subject: [PATCH 16/16] Documentation added for media type .list & .delete APIs --- couchpotato/core/media/_base/media/main.py | 36 +++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 8adc666..26140f3 100755 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -44,15 +44,15 @@ class MediaPlugin(MediaBase): 'desc': 'List media', 'params': { 'type': {'type': 'string', 'desc': 'Media type to filter on.'}, - 'status': {'type': 'array or csv', 'desc': 'Filter movie by status. Example:"active,done"'}, - 'release_status': {'type': 'array or csv', 'desc': 'Filter movie by status of its releases. Example:"snatched,available"'}, - 'limit_offset': {'desc': 'Limit and offset the movie list. Examples: "50" or "50,30"'}, - 'starts_with': {'desc': 'Starts with these characters. Example: "a" returns all movies starting with the letter "a"'}, - 'search': {'desc': 'Search movie title'}, + 'status': {'type': 'array or csv', 'desc': 'Filter media by status. Example:"active,done"'}, + 'release_status': {'type': 'array or csv', 'desc': 'Filter media by status of its releases. Example:"snatched,available"'}, + 'limit_offset': {'desc': 'Limit and offset the media list. Examples: "50" or "50,30"'}, + 'starts_with': {'desc': 'Starts with these characters. Example: "a" returns all media starting with the letter "a"'}, + 'search': {'desc': 'Search media title'}, }, 'return': {'type': 'object', 'example': """{ 'success': True, - 'empty': bool, any movies returned or not, + 'empty': bool, any media returned or not, 'media': array, media found, }"""} }) @@ -313,7 +313,21 @@ class MediaPlugin(MediaBase): for media_type in fireEvent('media.types', merge = True): tempList = lambda media_type = media_type, *args, **kwargs : self.listView(type = media_type, **kwargs) - addApiView('%s.list' % media_type, tempList) + addApiView('%s.list' % media_type, tempList, docs = { + 'desc': 'List media', + 'params': { + 'status': {'type': 'array or csv', 'desc': 'Filter ' + media_type + ' by status. Example:"active,done"'}, + 'release_status': {'type': 'array or csv', 'desc': 'Filter ' + media_type + ' by status of its releases. Example:"snatched,available"'}, + 'limit_offset': {'desc': 'Limit and offset the ' + media_type + ' list. Examples: "50" or "50,30"'}, + 'starts_with': {'desc': 'Starts with these characters. Example: "a" returns all ' + media_type + 's starting with the letter "a"'}, + 'search': {'desc': 'Search ' + media_type + ' title'}, + }, + 'return': {'type': 'object', 'example': """{ + 'success': True, + 'empty': bool, any """ + media_type + """s returned or not, + 'media': array, media found, + }"""} + }) def availableChars(self, types = None, status = None, release_status = None): @@ -450,7 +464,13 @@ class MediaPlugin(MediaBase): for media_type in fireEvent('media.types', merge = True): tempDelete = lambda media_type = media_type, *args, **kwargs : self.deleteView(type = media_type, **kwargs) - addApiView('%s.delete' % media_type, tempDelete) + addApiView('%s.delete' % media_type, tempDelete, docs = { + 'desc': 'Delete a ' + media_type + ' from the wanted list', + 'params': { + 'id': {'desc': 'Media ID(s) you want to delete.', 'type': 'int (comma separated)'}, + 'delete_from': {'desc': 'Delete ' + media_type + ' from this page', 'type': 'string: all (default), wanted, manage'}, + } + }) def restatus(self, media_id):