EOD commit (WIP). So close to writing tv objects to database but too tired to finish. Currently storing a show as a movie using imdb metadata. Added another search button beside movie button
This commit is contained in:
@@ -346,7 +346,6 @@ class MovieBase(MovieTypeBase):
|
||||
}
|
||||
|
||||
def add(self, params = {}, force_readd = True, search_after = True, update_library = False, status_id = None):
|
||||
|
||||
if not params.get('identifier'):
|
||||
msg = 'Can\'t add movie without imdb identifier.'
|
||||
log.error(msg)
|
||||
|
||||
@@ -11,7 +11,7 @@ Block.Search = new Class({
|
||||
self.el = new Element('div.search_form').adopt(
|
||||
new Element('div.input').adopt(
|
||||
self.input = new Element('input', {
|
||||
'placeholder': 'Search & add a new show',
|
||||
'placeholder': 'Search & add a new movie',
|
||||
'events': {
|
||||
'keyup': self.keyup.bind(self),
|
||||
'focus': function(){
|
||||
@@ -66,7 +66,7 @@ Block.Search = new Class({
|
||||
self.input.set('value', '');
|
||||
self.input.focus()
|
||||
|
||||
self.shows = []
|
||||
self.movies = []
|
||||
self.results.empty()
|
||||
self.el.removeClass('filled')
|
||||
|
||||
@@ -131,7 +131,7 @@ Block.Search = new Class({
|
||||
if(!self.spinner)
|
||||
self.spinner = createSpinner(self.mask);
|
||||
|
||||
self.api_request = Api.request('show.search', {
|
||||
self.api_request = Api.request('movie.search', {
|
||||
'data': {
|
||||
'q': q
|
||||
},
|
||||
@@ -150,17 +150,17 @@ Block.Search = new Class({
|
||||
|
||||
self.cache[q] = json
|
||||
|
||||
self.shows = {}
|
||||
self.movies = {}
|
||||
self.results.empty()
|
||||
|
||||
Object.each(json.shows, function(show){
|
||||
Object.each(json.movies, function(movie){
|
||||
|
||||
var m = new Block.Search.Item(show);
|
||||
var m = new Block.Search.Item(movie);
|
||||
$(m).inject(self.results)
|
||||
self.shows[show.imdb || 'r-'+Math.floor(Math.random()*10000)] = m
|
||||
self.movies[movie.imdb || 'r-'+Math.floor(Math.random()*10000)] = m
|
||||
|
||||
if(q == show.imdb)
|
||||
m.showOptions()
|
||||
if(q == movie.imdb)
|
||||
m.movieOptions()
|
||||
|
||||
});
|
||||
|
||||
@@ -201,7 +201,7 @@ Block.Search.Item = new Class({
|
||||
var self = this,
|
||||
info = self.info;
|
||||
|
||||
self.el = new Element('div.show_result', {
|
||||
self.el = new Element('div.movie_result', {
|
||||
'id': info.imdb
|
||||
}).adopt(
|
||||
self.thumbnail = info.images && info.images.poster.length > 0 ? new Element('img.thumbnail', {
|
||||
@@ -212,7 +212,7 @@ Block.Search.Item = new Class({
|
||||
self.options_el = new Element('div.options.inlay'),
|
||||
self.data_container = new Element('div.data', {
|
||||
'events': {
|
||||
'click': self.showOptions.bind(self)
|
||||
'click': self.movieOptions.bind(self)
|
||||
}
|
||||
}).adopt(
|
||||
self.info_container = new Element('div.info').adopt(
|
||||
@@ -256,7 +256,7 @@ Block.Search.Item = new Class({
|
||||
return this.info[key]
|
||||
},
|
||||
|
||||
showOptions: function(){
|
||||
movieOptions: function(){
|
||||
var self = this;
|
||||
|
||||
self.createOptions();
|
||||
@@ -281,7 +281,7 @@ Block.Search.Item = new Class({
|
||||
|
||||
self.loadingMask();
|
||||
|
||||
Api.request('show.add', {
|
||||
Api.request('movie.add', {
|
||||
'data': {
|
||||
'identifier': self.info.imdb,
|
||||
'title': self.title_select.get('value'),
|
||||
@@ -366,7 +366,7 @@ Block.Search.Item = new Class({
|
||||
if(categories.length == 0)
|
||||
self.category_select.hide();
|
||||
else {
|
||||
self.category_select.show();
|
||||
self.category_select.movie();
|
||||
categories.each(function(category){
|
||||
new Element('option', {
|
||||
'value': category.data.id,
|
||||
|
||||
@@ -55,6 +55,16 @@ class ShowBase(MediaBase):
|
||||
'shows': array, shows found,
|
||||
}"""}
|
||||
})
|
||||
addApiView('show.add', self.addView, docs = {
|
||||
'desc': 'Add new movie to the wanted list',
|
||||
'params': {
|
||||
'identifier': {'desc': 'IMDB id of the movie your want to add.'},
|
||||
'profile_id': {'desc': 'ID of quality profile you want the add the movie in. If empty will use the default profile.'},
|
||||
'title': {'desc': 'Movie title to use for searches. Has to be one of the titles returned by movie.search.'},
|
||||
}
|
||||
})
|
||||
|
||||
addEvent('show.add', self.add)
|
||||
|
||||
def search(self, q = '', **kwargs):
|
||||
|
||||
@@ -75,3 +85,148 @@ class ShowBase(MediaBase):
|
||||
'shows': shows,
|
||||
}
|
||||
|
||||
def addView(self, **kwargs):
|
||||
|
||||
movie_dict = fireEvent('show.add', params=kwargs) # XXX: Temp added so we can catch a breakpoint
|
||||
#movie_dict = self.add(params = kwargs)
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'added': True if movie_dict else False,
|
||||
'movie': movie_dict,
|
||||
}
|
||||
|
||||
def add(self, params = {}, force_readd = True, search_after = True, update_library = False, status_id = None):
|
||||
"""
|
||||
1. Add Show
|
||||
1. Add All Episodes
|
||||
2. Add All Seasons
|
||||
|
||||
Notes, not to forget:
|
||||
- relate parent and children, possible grandparent to grandchild so episodes know it belong to show, etc
|
||||
- looks like we dont send info to library; it comes later
|
||||
- change references to plot to description
|
||||
- change Model to Media
|
||||
"""
|
||||
log.debug("show.add")
|
||||
|
||||
|
||||
identifier = params.get('thetvdb_id')
|
||||
episodes = fireEvent('show.episodes', identifier = identifier)
|
||||
|
||||
# XXX: Fix so we dont have a nested list
|
||||
for episode in episodes[0]:
|
||||
self.add2(params=episode)
|
||||
|
||||
return self.add2(params = params)
|
||||
|
||||
def add2(self, params = {}, force_readd = True, search_after = True, update_library = False, status_id = None):
|
||||
log.debug("show.add2")
|
||||
|
||||
if not params.get('identifier'):
|
||||
msg = 'Can\'t add show without imdb identifier.'
|
||||
log.error(msg)
|
||||
fireEvent('notify.frontend', type = 'show.is_tvshow', message = msg)
|
||||
return False
|
||||
#else:
|
||||
#try:
|
||||
#is_show = fireEvent('movie.is_show', identifier = params.get('identifier'), single = True)
|
||||
#if not is_show:
|
||||
#msg = 'Can\'t add show, seems to be a TV show.'
|
||||
#log.error(msg)
|
||||
#fireEvent('notify.frontend', type = 'show.is_tvshow', message = msg)
|
||||
#return False
|
||||
#except:
|
||||
#pass
|
||||
|
||||
|
||||
library = fireEvent('library.add', single = True, attrs = params, update_after = update_library)
|
||||
|
||||
# Status
|
||||
status_active, snatched_status, ignored_status, done_status, downloaded_status = \
|
||||
fireEvent('status.get', ['active', 'snatched', 'ignored', 'done', 'downloaded'], single = True)
|
||||
|
||||
default_profile = fireEvent('profile.default', single = True)
|
||||
cat_id = params.get('category_id', None)
|
||||
|
||||
db = get_session()
|
||||
m = db.query(Movie).filter_by(library_id = library.get('id')).first()
|
||||
added = True
|
||||
do_search = False
|
||||
if not m:
|
||||
m = Movie(
|
||||
library_id = library.get('id'),
|
||||
profile_id = params.get('profile_id', default_profile.get('id')),
|
||||
status_id = status_id if status_id else status_active.get('id'),
|
||||
category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else None,
|
||||
)
|
||||
db.add(m)
|
||||
db.commit()
|
||||
|
||||
onComplete = None
|
||||
if search_after:
|
||||
onComplete = self.createOnComplete(m.id)
|
||||
|
||||
fireEventAsync('library.update', params.get('identifier'), default_title = params.get('title', ''), on_complete = onComplete)
|
||||
search_after = False
|
||||
elif force_readd:
|
||||
|
||||
# Clean snatched history
|
||||
for release in m.releases:
|
||||
if release.status_id in [downloaded_status.get('id'), snatched_status.get('id'), done_status.get('id')]:
|
||||
if params.get('ignore_previous', False):
|
||||
release.status_id = ignored_status.get('id')
|
||||
else:
|
||||
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 None
|
||||
else:
|
||||
log.debug('Movie already exists, not updating: %s', params)
|
||||
added = False
|
||||
|
||||
if force_readd:
|
||||
m.status_id = status_id if status_id else status_active.get('id')
|
||||
m.last_edit = int(time.time())
|
||||
do_search = True
|
||||
|
||||
db.commit()
|
||||
|
||||
# Remove releases
|
||||
available_status = fireEvent('status.get', 'available', single = True)
|
||||
for rel in m.releases:
|
||||
if rel.status_id is available_status.get('id'):
|
||||
db.delete(rel)
|
||||
db.commit()
|
||||
|
||||
show_dict = m.to_dict(self.default_dict)
|
||||
|
||||
if do_search and search_after:
|
||||
onComplete = self.createOnComplete(m.id)
|
||||
onComplete()
|
||||
|
||||
if added:
|
||||
fireEvent('notify.frontend', type = 'show.added', data = show_dict, message = 'Successfully added "%s" to your wanted list.' % params.get('title', ''))
|
||||
|
||||
db.expire_all()
|
||||
return show_dict
|
||||
|
||||
def createOnComplete(self, movie_id):
|
||||
|
||||
def onComplete():
|
||||
db = get_session()
|
||||
movie = db.query(Movie).filter_by(id = movie_id).first()
|
||||
fireEventAsync('movie.searcher.single', movie.to_dict(self.default_dict), on_complete = self.createNotifyFront(movie_id))
|
||||
db.expire_all()
|
||||
|
||||
return onComplete
|
||||
|
||||
def createNotifyFront(self, movie_id):
|
||||
|
||||
def notifyFront():
|
||||
db = get_session()
|
||||
movie = db.query(Movie).filter_by(id = movie_id).first()
|
||||
fireEvent('notify.frontend', type = 'show.update.%s' % movie.id, data = movie.to_dict(self.default_dict))
|
||||
db.expire_all()
|
||||
|
||||
return notifyFront
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
right: 205px;
|
||||
right: 135px;
|
||||
top: 0;
|
||||
text-align: right;
|
||||
text-align: left;
|
||||
height: 100%;
|
||||
border-bottom: 4px solid transparent;
|
||||
transition: all .4s cubic-bezier(0.9,0,0.1,1);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Block.Search = new Class({
|
||||
Block.ShowSearch = new Class({
|
||||
|
||||
Extends: BlockBase,
|
||||
|
||||
@@ -11,7 +11,7 @@ Block.Search = new Class({
|
||||
self.el = new Element('div.show_search_form').adopt(
|
||||
new Element('div.input').adopt(
|
||||
self.input = new Element('input', {
|
||||
'placeholder': 'Search & add a new show,
|
||||
'placeholder': 'Search & add a new *show*',
|
||||
'events': {
|
||||
'keyup': self.keyup.bind(self),
|
||||
'focus': function(){
|
||||
@@ -155,7 +155,7 @@ Block.Search = new Class({
|
||||
|
||||
Object.each(json.shows, function(show){
|
||||
|
||||
var m = new Block.Search.Item(show);
|
||||
var m = new Block.ShowSearch.Item(show);
|
||||
$(m).inject(self.results)
|
||||
self.shows[show.imdb || 'r-'+Math.floor(Math.random()*10000)] = m
|
||||
|
||||
@@ -183,7 +183,7 @@ Block.Search = new Class({
|
||||
|
||||
});
|
||||
|
||||
Block.Search.Item = new Class({
|
||||
Block.ShowSearch.Item = new Class({
|
||||
|
||||
Implements: [Options, Events],
|
||||
|
||||
@@ -284,6 +284,7 @@ Block.Search.Item = new Class({
|
||||
Api.request('show.add', {
|
||||
'data': {
|
||||
'identifier': self.info.imdb,
|
||||
'thetvdb_id': self.info.thetvdb_id,
|
||||
'title': self.title_select.get('value'),
|
||||
'profile_id': self.profile_select.get('value'),
|
||||
'category_id': self.category_select.get('value')
|
||||
|
||||
@@ -20,7 +20,7 @@ class LibraryPlugin(Plugin):
|
||||
addEvent('library.update', self.update)
|
||||
addEvent('library.update_release_date', self.updateReleaseDate)
|
||||
|
||||
def add(self, attrs = {}, update_after = True):
|
||||
def add(self, attrs = {}, update_after = True, type='movie'):
|
||||
|
||||
db = get_session()
|
||||
|
||||
@@ -28,6 +28,7 @@ class LibraryPlugin(Plugin):
|
||||
if not l:
|
||||
status = fireEvent('status.get', 'needs_update', single = True)
|
||||
l = Library(
|
||||
type = type,
|
||||
year = attrs.get('year'),
|
||||
identifier = attrs.get('identifier'),
|
||||
plot = toUnicode(attrs.get('plot')),
|
||||
|
||||
@@ -14,6 +14,7 @@ class TheTVDb(ShowProvider):
|
||||
#addEvent('show.by_hash', self.byHash)
|
||||
addEvent('show.search', self.search, priority = 1)
|
||||
addEvent('show.info', self.getInfo, priority = 1)
|
||||
addEvent('show.episodes', self.getEpisodes, priority = 1)
|
||||
#addEvent('show.info_by_thetvdb', self.getInfoByTheTVDBId)
|
||||
|
||||
# Use base wrapper
|
||||
@@ -100,11 +101,24 @@ class TheTVDb(ShowProvider):
|
||||
|
||||
return results
|
||||
|
||||
def getInfo(self, identifier = None):
|
||||
|
||||
def getEpisodes(self, identifier=None):
|
||||
if not identifier:
|
||||
return {}
|
||||
|
||||
return []
|
||||
|
||||
try:
|
||||
show = self.tvdb[int(identifier)]
|
||||
except:
|
||||
return []
|
||||
|
||||
result = []
|
||||
for season in show.values():
|
||||
for episode in season.values():
|
||||
# Consider cache
|
||||
result.append(self.parseEpisode(episode))
|
||||
|
||||
return result
|
||||
|
||||
def getInfo(self, identifier = None):
|
||||
cache_key = 'thetvdb.cache.%s' % identifier
|
||||
result = self.getCache(cache_key)
|
||||
|
||||
@@ -217,6 +231,85 @@ class TheTVDb(ShowProvider):
|
||||
#show_data['titles'].append(alt_name)
|
||||
|
||||
return show_data
|
||||
|
||||
def parseEpisode(self, episode):
|
||||
"""
|
||||
('episodenumber', u'1'),
|
||||
('thumb_added', None),
|
||||
('rating', u'7.7'),
|
||||
('overview',
|
||||
u'Experienced waitress Max Black meets her new co-worker, former rich-girl Caroline Channing, and puts her skills to the test at an old but re-emerging Brooklyn diner. Despite her initial distaste for Caroline, Max eventually softens and the two team up for a new business venture.'),
|
||||
('dvd_episodenumber', None),
|
||||
('dvd_discid', None),
|
||||
('combined_episodenumber', u'1'),
|
||||
('epimgflag', u'7'),
|
||||
('id', u'4099506'),
|
||||
('seasonid', u'465948'),
|
||||
('thumb_height', u'225'),
|
||||
('tms_export', u'1374789754'),
|
||||
('seasonnumber', u'1'),
|
||||
('writer', u'|Michael Patrick King|Whitney Cummings|'),
|
||||
('lastupdated', u'1371420338'),
|
||||
('filename', u'http://thetvdb.com/banners/episodes/248741/4099506.jpg'),
|
||||
('absolute_number', u'1'),
|
||||
('ratingcount', u'102'),
|
||||
('combined_season', u'1'),
|
||||
('thumb_width', u'400'),
|
||||
('imdb_id', u'tt1980319'),
|
||||
('director', u'James Burrows'),
|
||||
('dvd_chapter', None),
|
||||
('dvd_season', None),
|
||||
('gueststars',
|
||||
u'|Brooke Lyons|Noah Mills|Shoshana Bush|Cale Hartmann|Adam Korson|Alex Enriquez|Matt Cook|Bill Parks|Eugene Shaw|Sergey Brusilovsky|Greg Lewis|Cocoa Brown|Nick Jameson|'),
|
||||
('seriesid', u'248741'),
|
||||
('language', u'en'),
|
||||
('productioncode', u'296793'),
|
||||
('firstaired', u'2011-09-19'),
|
||||
('episodename', u'Pilot')]
|
||||
"""
|
||||
|
||||
## Images
|
||||
#poster = self.getImage(episode, type = 'poster', size = 'cover')
|
||||
#backdrop = self.getImage(episode, type = 'fanart', size = 'w1280')
|
||||
##poster_original = self.getImage(episode, type = 'poster', size = 'original')
|
||||
##backdrop_original = self.getImage(episode, type = 'backdrop', size = 'original')
|
||||
poster = []
|
||||
backdrop = []
|
||||
|
||||
## Genres
|
||||
genres = []
|
||||
|
||||
## Year (not really needed for episode)
|
||||
year = None
|
||||
|
||||
episode_data = {
|
||||
'via_thetvdb': True,
|
||||
'thetvdb_id': int(episode['id']),
|
||||
'titles': [episode['episodename'], ],
|
||||
'original_title': episode['episodename'],
|
||||
'images': {
|
||||
'poster': [poster] if poster else [],
|
||||
'backdrop': [backdrop] if backdrop else [],
|
||||
'poster_original': [],
|
||||
'backdrop_original': [],
|
||||
},
|
||||
'imdb': episode['imdb_id'],
|
||||
'runtime': None,
|
||||
'released': episode['firstaired'],
|
||||
'year': year,
|
||||
'plot': episode['overview'],
|
||||
'genres': genres,
|
||||
}
|
||||
|
||||
episode_data = dict((k, v) for k, v in episode_data.iteritems() if v)
|
||||
|
||||
## Add alternative names
|
||||
#for alt in ['original_name', 'alternative_name']:
|
||||
#alt_name = toUnicode(episode.get(alt))
|
||||
#if alt_name and not alt_name in episode_data['titles'] and alt_name.lower() != 'none' and alt_name != None:
|
||||
#episode_data['titles'].append(alt_name)
|
||||
|
||||
return episode_data
|
||||
|
||||
def getImage(self, show, type = 'poster', size = 'cover'):
|
||||
""""""
|
||||
|
||||
@@ -91,6 +91,7 @@ class Library(Entity):
|
||||
""""""
|
||||
|
||||
# For Movies, CPS uses three: omdbapi (no prio !?), tmdb (prio 2) and couchpotatoapi (prio 1)
|
||||
type = Field(String(10), default="movie", index=True)
|
||||
provider = Field(String(10), default="imdb", index=True)
|
||||
year = Field(Integer)
|
||||
identifier = Field(String(20), index = True)
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
new Element('div').adopt(
|
||||
self.block.navigation = new Block.Navigation(self, {}),
|
||||
self.block.search = new Block.Search(self, {}),
|
||||
self.block.search = new Block.ShowSearch(self, {}),
|
||||
self.block.more = new Block.Menu(self, {'button_class': 'icon2.cog'})
|
||||
)
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user