Browse Source

Merge branch 'tv_xem' into tv

pull/3730/merge
Dean Gardiner 11 years ago
parent
commit
a06bfcb3bf
  1. 8
      couchpotato/core/helpers/variable.py
  2. 17
      couchpotato/core/media/_base/library/main.py
  3. 11
      couchpotato/core/media/_base/media/main.py
  4. 8
      couchpotato/core/media/movie/_base/main.py
  5. 2
      couchpotato/core/media/movie/providers/metadata/base.py
  6. 2
      couchpotato/core/media/movie/searcher.py
  7. 2
      couchpotato/core/media/movie/suggestion/main.py
  8. 328
      couchpotato/core/media/show/_base/main.py
  9. 45
      couchpotato/core/media/show/episode.py
  10. 48
      couchpotato/core/media/show/providers/info/thetvdb.py
  11. 122
      couchpotato/core/media/show/providers/info/xem.py
  12. 41
      couchpotato/core/media/show/season.py
  13. 2
      couchpotato/core/plugins/dashboard.py
  14. 2
      couchpotato/core/plugins/manage.py
  15. 2
      couchpotato/core/plugins/renamer.py
  16. 2
      libs/tvdb_api/tvdb_api.py

8
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

17
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

11
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))
@ -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'])

8
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')

2
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())

2
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()))

2
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:

328
couchpotato/core/media/show/_base/main.py

@ -5,7 +5,7 @@ from couchpotato import get_db
from couchpotato.api import addApiView
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
from couchpotato.core.helpers.encoding import simplifyString
from couchpotato.core.helpers.variable import getTitle
from couchpotato.core.helpers.variable import getTitle, find
from couchpotato.core.logger import CPLog
from couchpotato.core.media import MediaBase
from qcond import QueryCondenser
@ -32,7 +32,8 @@ class ShowBase(MediaBase):
})
addEvent('show.add', self.add)
addEvent('show.update_info', self.updateInfo)
addEvent('show.update', self.update)
addEvent('show.update_extras', self.updateExtras)
def addView(self, **kwargs):
add_dict = self.add(params = kwargs)
@ -45,8 +46,6 @@ class ShowBase(MediaBase):
def add(self, params = None, force_readd = True, search_after = True, update_after = True, notify_after = True, status = None):
if not params: params = {}
db = get_db()
# Identifiers
if not params.get('identifiers'):
msg = 'Can\'t add show without at least 1 identifier.'
@ -58,6 +57,31 @@ class ShowBase(MediaBase):
if not info or (info and len(info.get('titles', [])) == 0):
info = fireEvent('show.info', merge = True, identifiers = params.get('identifiers'))
# Add Show
try:
m, added = self.create(info, params, force_readd, search_after, update_after)
result = fireEvent('media.get', m['_id'], single = True)
if added and notify_after:
if params.get('title'):
message = 'Successfully added "%s" to your wanted list.' % params.get('title', '')
else:
title = getTitle(m)
if title:
message = 'Successfully added "%s" to your wanted list.' % title
else:
message = 'Successfully added to your wanted list.'
fireEvent('notify.frontend', type = 'show.added', data = result, message = message)
return result
except:
log.error('Failed adding media: %s', traceback.format_exc())
def create(self, info, params = None, force_readd = True, search_after = True, update_after = True, notify_after = True, status = None):
db = get_db()
# Set default title
def_title = self.getDefaultTitle(info)
@ -65,136 +89,101 @@ class ShowBase(MediaBase):
default_profile = {}
if not params.get('profile_id'):
default_profile = fireEvent('profile.default', single = True)
cat_id = params.get('category_id')
# Add Show
media = {
'_t': 'media',
'type': 'show',
'title': def_title,
'identifiers': info.get('identifiers'),
'status': status if status else 'active',
'profile_id': params.get('profile_id', default_profile.get('_id')),
'category_id': cat_id if cat_id is not None and len(cat_id) > 0 and cat_id != '-1' else None
}
identifiers = info.pop('identifiers', {})
seasons = info.pop('seasons', {})
# Update media with info
self.updateInfo(media, info)
new = False
try:
media = {
'_t': 'media',
'type': 'show',
'title': def_title,
'identifiers': info.get('identifiers'),
'status': status if status else 'active',
'profile_id': params.get('profile_id', default_profile.get('_id')),
'category_id': cat_id if cat_id is not None and len(cat_id) > 0 and cat_id != '-1' else None
}
m = fireEvent('media.with_identifiers', params.get('identifiers'), with_doc = True, single = True)['doc']
except:
new = True
m = db.insert(media)
# TODO: stuff below is mostly a copy of what is done in movie
# Can we make a base function to do this stuff?
# Remove season info for later use (save separately)
seasons_info = info.get('seasons', {})
identifiers = info.get('identifiers', {})
# Make sure we don't nest in_wanted data
del info['identifiers']
try: del info['in_wanted']
except: pass
try: del info['in_library']
except: pass
try: del info['identifiers']
except: pass
try: del info['seasons']
except: pass
media['info'] = info
new = False
try:
m = fireEvent('media.with_identifiers', params.get('identifiers'), with_doc = True, single = True)['doc']
except:
new = True
m = db.insert(media)
# Update dict to be usable
m.update(media)
added = True
do_search = False
search_after = search_after and self.conf('search_on_add', section = 'showsearcher')
onComplete = None
if new:
if search_after:
onComplete = self.createOnComplete(m['_id'])
search_after = False
elif force_readd:
# Clean snatched history
for release in fireEvent('release.for_media', m['_id'], single = True):
if release.get('status') in ['downloaded', 'snatched', 'done']:
if params.get('ignore_previous', False):
release['status'] = 'ignored'
db.update(release)
else:
fireEvent('release.delete', release['_id'], single = True)
m['profile_id'] = params.get('profile_id', default_profile.get('id'))
m['category_id'] = media.get('category_id')
m['last_edit'] = int(time.time())
do_search = True
db.update(m)
else:
try: del params['info']
except: pass
log.debug('Show already exists, not updating: %s', params)
added = False
# Trigger update info
if added and update_after:
# Do full update to get images etc
fireEventAsync('show.update_info', m['_id'], info = info, on_complete = onComplete)
# Remove releases
for rel in fireEvent('release.for_media', m['_id'], single = True):
if rel['status'] is 'available':
db.delete(rel)
movie_dict = fireEvent('media.get', m['_id'], single = True)
if do_search and search_after:
# Update dict to be usable
m.update(media)
added = True
do_search = False
search_after = search_after and self.conf('search_on_add', section = 'showsearcher')
onComplete = None
if new:
if search_after:
onComplete = self.createOnComplete(m['_id'])
onComplete()
# Add Seasons
for season_nr in seasons_info:
search_after = False
elif force_readd:
# Clean snatched history
for release in fireEvent('release.for_media', m['_id'], single = True):
if release.get('status') in ['downloaded', 'snatched', 'done']:
if params.get('ignore_previous', False):
release['status'] = 'ignored'
db.update(release)
else:
fireEvent('release.delete', release['_id'], single = True)
season_info = seasons_info[season_nr]
episodes = season_info.get('episodes', {})
m['profile_id'] = params.get('profile_id', default_profile.get('id'))
m['category_id'] = media.get('category_id')
m['last_edit'] = int(time.time())
season = fireEvent('show.season.add', m.get('_id'), season_info, single = True)
do_search = True
db.update(m)
else:
params.pop('info', None)
log.debug('Show already exists, not updating: %s', params)
added = False
# Add Episodes
for episode_nr in episodes:
# Create episodes
self.createEpisodes(m, seasons)
episode_info = episodes[episode_nr]
episode_info['season_number'] = season_nr
fireEvent('show.episode.add', season.get('_id'), episode_info, single = True)
# Trigger update info
if added and update_after:
# Do full update to get images etc
fireEventAsync('show.update_extras', m, info, store = True, on_complete = onComplete)
# Remove releases
for rel in fireEvent('release.for_media', m['_id'], single = True):
if rel['status'] is 'available':
db.delete(rel)
if added and notify_after:
if do_search and search_after:
onComplete = self.createOnComplete(m['_id'])
onComplete()
if params.get('title'):
message = 'Successfully added "%s" to your wanted list.' % params.get('title', '')
else:
title = getTitle(m)
if title:
message = 'Successfully added "%s" to your wanted list.' % title
else:
message = 'Successfully added to your wanted list.'
fireEvent('notify.frontend', type = 'show.added', data = movie_dict, message = message)
return m, added
def createEpisodes(self, m, seasons_info):
# Add Seasons
for season_nr in seasons_info:
season_info = seasons_info[season_nr]
episodes = season_info.get('episodes', {})
return movie_dict
except:
log.error('Failed adding media: %s', traceback.format_exc())
season = fireEvent('show.season.add', m.get('_id'), season_info, update_after = False, single = True)
def updateInfo(self, media_id = None, identifiers = None, info = None):
if not info: info = {}
if not identifiers: identifiers = {}
# Add Episodes
for episode_nr in episodes:
episode_info = episodes[episode_nr]
episode_info['season_number'] = season_nr
fireEvent('show.episode.add', season.get('_id'), episode_info, update_after = False, single = True)
def update(self, media_id = None, media = None, identifiers = None, info = None):
"""
Update movie information inside media['doc']['info']
@ -209,41 +198,30 @@ class ShowBase(MediaBase):
@return: dict, with media
"""
if self.shuttingDown():
return
try:
db = get_db()
if media_id:
media = db.get('id', media_id)
else:
media = db.get('media', identifiers, with_doc = True)['doc']
if not info: info = {}
if not identifiers: identifiers = {}
if not info:
info = fireEvent('show.info', identifiers = media.get('identifiers'), merge = True)
db = get_db()
# Don't need those here
try: del info['seasons']
except: pass
try: del info['identifiers']
except: pass
try: del info['in_wanted']
except: pass
try: del info['in_library']
except: pass
if self.shuttingDown():
return
if not info or len(info) == 0:
log.error('Could not update, no show info to work with: %s', media.get('identifier'))
return False
if media is None and media_id:
media = db.get('id', media_id)
else:
log.error('missing "media" and "media_id" parameters, unable to update')
return
# Update basic info
media['info'] = info
if not info:
info = fireEvent('show.info', identifiers = media.get('identifiers'), merge = True)
# Update image file
image_urls = info.get('images', [])
try:
identifiers = info.pop('identifiers', {})
seasons = info.pop('seasons', {})
self.getPoster(media, image_urls)
self.updateInfo(media, info)
self.updateEpisodes(media, seasons)
self.updateExtras(media, info)
db.update(media)
return media
@ -251,3 +229,61 @@ class ShowBase(MediaBase):
log.error('Failed update media: %s', traceback.format_exc())
return {}
def updateInfo(self, media, info):
db = get_db()
# Remove season info for later use (save separately)
info.pop('in_wanted', None)
info.pop('in_library', None)
if not info or len(info) == 0:
log.error('Could not update, no show info to work with: %s', media.get('identifier'))
return False
# Update basic info
media['info'] = info
def updateEpisodes(self, media, seasons):
# Fetch current season/episode tree
show_tree = fireEvent('library.tree', media_id = media['_id'], single = True)
# Update seasons
for season_num in seasons:
season_info = seasons[season_num]
episodes = season_info.get('episodes', {})
# Find season that matches number
season = find(lambda s: s.get('info', {}).get('number', 0) == season_num, show_tree.get('seasons', []))
if not season:
log.warning('Unable to find season "%s"', season_num)
continue
# Update season
fireEvent('show.season.update', season['_id'], info = season_info, single = True)
# Update episodes
for episode_num in episodes:
episode_info = episodes[episode_num]
episode_info['season_number'] = season_num
# Find episode that matches number
episode = find(lambda s: s.get('info', {}).get('number', 0) == episode_num, season.get('episodes', []))
if not episode:
log.debug('Creating new episode %s in season %s', (episode_num, season_num))
fireEvent('show.episode.add', season.get('_id'), episode_info, update_after = False, single = True)
continue
fireEvent('show.episode.update', episode['_id'], info = episode_info, single = True)
def updateExtras(self, media, info, store=False):
db = get_db()
# Update image file
image_urls = info.get('images', [])
self.getPoster(media, image_urls)
if store:
db.update(media)

45
couchpotato/core/media/show/episode.py

@ -14,14 +14,17 @@ class Episode(MediaBase):
def __init__(self):
addEvent('show.episode.add', self.add)
addEvent('show.episode.update_info', self.updateInfo)
addEvent('show.episode.update', self.update)
addEvent('show.episode.update_extras', self.updateExtras)
def add(self, parent_id, info = None, update_after = True, status = None):
if not info: info = {}
identifiers = info.get('identifiers')
try: del info['identifiers']
except: pass
identifiers = info.pop('identifiers', None)
if not identifiers:
log.warning('Unable to add episode, missing identifiers (info provider mismatch?)')
return
# Add Season
episode_info = {
@ -41,6 +44,7 @@ class Episode(MediaBase):
if existing_episode:
s = existing_episode['doc']
s.update(episode_info)
episode = db.update(s)
else:
episode = db.insert(episode_info)
@ -48,11 +52,11 @@ class Episode(MediaBase):
# Update library info
if update_after is not False:
handle = fireEventAsync if update_after is 'async' else fireEvent
handle('show.season.update_info', episode.get('_id'), info = info, single = True)
handle('show.episode.update_extras', episode, info, store = True, single = True)
return episode
def updateInfo(self, media_id = None, info = None, force = False):
def update(self, media_id = None, identifiers = None, info = None):
if not info: info = {}
if self.shuttingDown():
@ -69,26 +73,35 @@ class Episode(MediaBase):
info = fireEvent(
'episode.info', show.get('identifiers'), {
'season_identifier': season.get('info', {}).get('number'),
'episode_identifier': episode.get('identifiers')
'season_identifiers': season.get('identifiers'),
'season_number': season.get('info', {}).get('number'),
'episode_identifiers': episode.get('identifiers'),
'episode_number': episode.get('info', {}).get('number'),
'absolute_number': episode.get('info', {}).get('absolute_number')
},
merge = True
)
identifiers = info.pop('identifiers', None) or identifiers
# Update/create media
if force:
episode['identifiers'].update(identifiers)
episode.update({'info': info})
episode['identifiers'].update(info['identifiers'])
if 'identifiers' in info:
del info['identifiers']
self.updateExtras(episode, info)
episode.update({'info': info})
e = db.update(episode)
episode.update(e)
db.update(episode)
return episode
def updateExtras(self, episode, info, store=False):
db = get_db()
# Get images
image_urls = info.get('images', [])
existing_files = episode.get('files', {})
self.getPoster(image_urls, existing_files)
return episode
if store:
db.update(episode)

48
couchpotato/core/media/show/providers/info/thetvdb.py

@ -60,8 +60,9 @@ class TheTVDb(ShowProvider):
self.tvdb_api_parms['language'] = language
self._setup()
search_string = simplifyString(q)
cache_key = 'thetvdb.cache.search.%s.%s' % (search_string, limit)
query = q
#query = simplifyString(query)
cache_key = 'thetvdb.cache.search.%s.%s' % (query, limit)
results = self.getCache(cache_key)
if not results:
@ -69,9 +70,9 @@ class TheTVDb(ShowProvider):
raw = None
try:
raw = self.tvdb.search(search_string)
raw = self.tvdb.search(query)
except (tvdb_exceptions.tvdb_error, IOError), e:
log.error('Failed searching TheTVDB for "%s": %s', (search_string, traceback.format_exc()))
log.error('Failed searching TheTVDB for "%s": %s', (query, traceback.format_exc()))
return False
results = []
@ -129,22 +130,17 @@ class TheTVDb(ShowProvider):
return result or {}
def getSeasonInfo(self, identifier = None, params = {}):
def getSeasonInfo(self, identifiers = None, params = {}):
"""Either return a list of all seasons or a single season by number.
identifier is the show 'id'
"""
if not identifier:
return False
season_identifier = params.get('season_identifier', None)
if not identifiers or not identifiers.get('thetvdb'):
return None
# season_identifier must contain the 'show id : season number' since there is no tvdb id
# for season and we need a reference to both the show id and season number
if season_identifier:
try: season_identifier = int(season_identifier.split(':')[1])
except: return False
season_number = params.get('season_number', None)
identifier = tryInt(identifiers.get('thetvdb'))
cache_key = 'thetvdb.cache.%s.%s' % (identifier, season_identifier)
cache_key = 'thetvdb.cache.%s.%s' % (identifier, season_number)
log.debug('Getting SeasonInfo: %s', cache_key)
result = self.getCache(cache_key) or {}
if result:
@ -158,12 +154,12 @@ class TheTVDb(ShowProvider):
result = []
for number, season in show.items():
if season_identifier is not None and number == season_identifier:
result = self._parseSeason(show, (number, season))
if season_number is not None and number == season_number:
result = self._parseSeason(show, number, season)
self.setCache(cache_key, result)
return result
else:
result.append(self._parseSeason(show, (number, season)))
result.append(self._parseSeason(show, number, season))
self.setCache(cache_key, result)
return result
@ -172,22 +168,22 @@ class TheTVDb(ShowProvider):
"""Either return a list of all episodes or a single episode.
If episode_identifer contains an episode number to search for
"""
season_identifier = self.getIdentifier(params.get('season_identifier', None))
episode_identifier = self.getIdentifier(params.get('episode_identifier', None))
season_number = self.getIdentifier(params.get('season_number', None))
episode_identifier = self.getIdentifier(params.get('episode_identifiers', None))
identifier = self.getIdentifier(identifier)
if not identifier and season_identifier is None:
if not identifier and season_number is None:
return False
# season_identifier must contain the 'show id : season number' since there is no tvdb id
# for season and we need a reference to both the show id and season number
if not identifier and season_identifier:
if not identifier and season_number:
try:
identifier, season_identifier = season_identifier.split(':')
season_identifier = int(season_identifier)
identifier, season_number = season_number.split(':')
season_number = int(season_number)
except: return None
cache_key = 'thetvdb.cache.%s.%s.%s' % (identifier, episode_identifier, season_identifier)
cache_key = 'thetvdb.cache.%s.%s.%s' % (identifier, episode_identifier, season_number)
log.debug('Getting EpisodeInfo: %s', cache_key)
result = self.getCache(cache_key) or {}
if result:
@ -201,7 +197,7 @@ class TheTVDb(ShowProvider):
result = []
for number, season in show.items():
if season_identifier is not None and number != season_identifier:
if season_number is not None and number != season_number:
continue
for episode in season.values():

122
couchpotato/core/media/show/providers/info/xem.py

@ -5,6 +5,8 @@ from couchpotato.core.media.show.providers.base import ShowProvider
log = CPLog(__name__)
autoload = 'Xem'
class Xem(ShowProvider):
'''
@ -75,76 +77,69 @@ class Xem(ShowProvider):
self.config['url_names'] = u"%(base_url)s/map/names?" % self.config
self.config['url_all_names'] = u"%(base_url)s/map/allNames?" % self.config
# TODO: Also get show aliases (store as titles)
def getShowInfo(self, identifier = None):
def getShowInfo(self, identifiers = None):
if self.isDisabled():
return {}
identifier = identifiers.get('thetvdb')
if not identifier:
return {}
cache_key = 'xem.cache.%s' % identifier
log.debug('Getting showInfo: %s', cache_key)
result = self.getCache(cache_key) or {}
if result:
return result
result['seasons'] = {}
# Create season/episode and absolute mappings
url = self.config['url_all'] + "id=%s&origin=tvdb" % tryUrlencode(identifier)
url = self.config['url_all'] + "id=%s&origin=tvdb" % tryUrlencode(identifier)
response = self.getJsonData(url)
if response:
if response.get('result') == 'success':
data = response.get('data', None)
result = self._parse(data)
if response and response.get('result') == 'success':
data = response.get('data', None)
self.parseMaps(result, data)
# Create name alias mappings
url = self.config['url_names'] + "id=%s&origin=tvdb" % tryUrlencode(identifier)
url = self.config['url_names'] + "id=%s&origin=tvdb" % tryUrlencode(identifier)
response = self.getJsonData(url)
if response:
if response.get('result') == 'success':
data = response.get('data', None)
result.update({'map_names': data})
if response and response.get('result') == 'success':
data = response.get('data', None)
self.parseNames(result, data)
self.setCache(cache_key, result)
return result
def getEpisodeInfo(self, identifier = None, params = {}):
episode = params.get('episode', None)
if episode is None:
def getEpisodeInfo(self, identifiers = None, params = {}):
episode_num = params.get('episode_number', None)
if episode_num is None:
return False
season_identifier = params.get('season_identifier', None)
if season_identifier is None:
season_num = params.get('season_number', None)
if season_num is None:
return False
episode_identifier = params.get('episode_identifier', None)
absolute = params.get('absolute', None)
# season_identifier must contain the 'show id : season number' since there is no tvdb id
# for season and we need a reference to both the show id and season number
if season_identifier:
try:
identifier, season_identifier = season_identifier.split(':')
season = int(season_identifier)
except: return False
result = self.getShowInfo(identifiers)
result = self.getShowInfo(identifier)
map = {}
if result:
map_episode = result.get('map_episode', {}).get(season, {}).get(episode, {})
if map_episode:
map.update({'map_episode': map_episode})
if not result:
return False
if absolute:
map_absolute = result.get('map_absolute', {}).get(absolute, {})
if map_absolute:
map.update({'map_absolute': map_absolute})
# Find season
if season_num not in result['seasons']:
return False
map_names = result.get('map_names', {}).get(toUnicode(season), {})
if map_names:
map.update({'map_names': map_names})
season = result['seasons'][season_num]
return map
# Find episode
if episode_num not in season['episodes']:
return False
return season['episodes'][episode_num]
def _parse(self, data, master = 'tvdb'):
def parseMaps(self, result, data, master = 'tvdb'):
'''parses xem map and returns a custom formatted dict map
To retreive map for scene:
@ -152,17 +147,44 @@ class Xem(ShowProvider):
print map['map_episode'][1][1]['scene']['season']
'''
if not isinstance(data, list):
return {}
return
map = {'map_episode': {}, 'map_absolute': {}}
for maps in data:
origin = maps.pop(master, None)
for episode_map in data:
origin = episode_map.pop(master, None)
if origin is None:
continue # No master origin to map to
map.get('map_episode').setdefault(origin['season'], {}).setdefault(origin['episode'], maps.copy())
map.get('map_absolute').setdefault(origin['absolute'], maps.copy())
continue # No master origin to map to
o_season = origin['season']
o_episode = origin['episode']
# Create season info
if o_season not in result['seasons']:
result['seasons'][o_season] = {}
season = result['seasons'][o_season]
if 'episodes' not in season:
season['episodes'] = {}
# Create episode info
if o_episode not in season['episodes']:
season['episodes'][o_episode] = {}
episode = season['episodes'][o_episode]
episode['episode_map'] = episode_map
def parseNames(self, result, data):
result['title_map'] = data.pop('all', None)
for season, title_map in data.items():
season = int(season)
# Create season info
if season not in result['seasons']:
result['seasons'][season] = {}
return map
season = result['seasons'][season]
season['title_map'] = title_map
def isDisabled(self):
if __name__ == '__main__':

41
couchpotato/core/media/show/season.py

@ -14,16 +14,14 @@ class Season(MediaBase):
def __init__(self):
addEvent('show.season.add', self.add)
addEvent('show.season.update_info', self.updateInfo)
addEvent('show.season.update', self.update)
addEvent('show.season.update_extras', self.updateExtras)
def add(self, parent_id, info = None, update_after = True, status = None):
if not info: info = {}
identifiers = info.get('identifiers')
try: del info['identifiers']
except: pass
try: del info['episodes']
except: pass
identifiers = info.pop('identifiers', None)
info.pop('episodes', None)
# Add Season
season_info = {
@ -43,6 +41,7 @@ class Season(MediaBase):
if existing_season:
s = existing_season['doc']
s.update(season_info)
season = db.update(s)
else:
season = db.insert(season_info)
@ -50,11 +49,11 @@ class Season(MediaBase):
# Update library info
if update_after is not False:
handle = fireEventAsync if update_after is 'async' else fireEvent
handle('show.season.update_info', season.get('_id'), info = info, single = True)
handle('show.season.update_extras', season, info, store = True, single = True)
return season
def updateInfo(self, media_id = None, info = None, force = False):
def update(self, media_id = None, identifiers = None, info = None):
if not info: info = {}
if self.shuttingDown():
@ -63,25 +62,33 @@ class Season(MediaBase):
db = get_db()
season = db.get('id', media_id)
show = db.get('id', season['parent_id'])
# Get new info
if not info:
info = fireEvent('season.info', season.get('identifiers'), merge = True)
info = fireEvent('season.info', show.get('identifiers'), {
'season_number': season.get('info', {}).get('number', 0)
}, merge = True)
identifiers = info.pop('identifiers', None) or identifiers
info.pop('episodes', None)
# Update/create media
if force:
season['identifiers'].update(identifiers)
season.update({'info': info})
self.updateExtras(season, info)
season['identifiers'].update(info['identifiers'])
if 'identifiers' in info:
del info['identifiers']
db.update(season)
return season
season.update({'info': info})
s = db.update(season)
season.update(s)
def updateExtras(self, season, info, store=False):
db = get_db()
# Get images
image_urls = info.get('images', [])
existing_files = season.get('files', {})
self.getPoster(image_urls, existing_files)
return season
if store:
db.update(season)

2
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 {}

2
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

2
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)

2
libs/tvdb_api/tvdb_api.py

@ -705,7 +705,7 @@ class Tvdb:
for k, v in banners[btype][btype2][bid].items():
if k.endswith("path"):
new_key = "_%s" % (k)
log().debug("Transforming %s to %s" % (k, new_key))
#log().debug("Transforming %s to %s" % (k, new_key))
new_url = self.config['url_artworkPrefix'] % (v)
banners[btype][btype2][bid][new_key] = new_url

Loading…
Cancel
Save