more poster

This commit is contained in:
j 2010-09-10 17:12:22 +02:00
parent be116ef7a5
commit 966c5d435a
4 changed files with 147 additions and 105 deletions

View file

@ -160,6 +160,9 @@ class Movie(models.Model):
self.updateSort() self.updateSort()
self.updateFacets() self.updateFacets()
'''
JSON cache related functions
'''
_public_fields = { _public_fields = {
'movieId': 'id', 'movieId': 'id',
'title': 'title', 'title': 'title',
@ -188,8 +191,6 @@ class Movie(models.Model):
'votes': 'votes', 'votes': 'votes',
'alternative_titles': 'alternative_titles', 'alternative_titles': 'alternative_titles',
'connections_json': 'connections', 'connections_json': 'connections',
'poster_width': 'posterWidth',
'poster_height': 'posterHeight'
} }
def get_poster(self): def get_poster(self):
poster = {} poster = {}
@ -204,6 +205,35 @@ class Movie(models.Model):
''' '''
return poster return poster
def get_posters(self):
posters = {}
for p in self.poster_urls.all():
if p.service not in posters:
posters[p.service] = []
posters[p.service].append({'url': p.url, 'width': p.width, 'height': p.height})
local_posters = self.local_posters().keys()
if local_posters:
posters['local'] = []
for p in local_posters:
url = p.replace(settings.MEDIA_ROOT, settings.MEDIA_URL)
width = 640
height = 1024
posters['local'].append({'url': url, 'width': width, 'height': height})
return posters
def get_stream(self):
stream = {}
if self.streams.all().count():
s = self.streams.all()[0]
if s.video and s.info:
stream['duration'] = s.info['duration']
if 'video' in s.info and s.info['video']:
stream['aspectRatio'] = s.info['video'][0]['width'] / s.info['video'][0]['height']
stream['baseUrl'] = os.path.dirname(s.video.url)
stream['profiles'] = list(set(map(lambda s: int(os.path.splitext(s['profile'])[0][:-1]), self.streams.all().values('profile'))))
return stream
def get_json(self, fields=None): def get_json(self, fields=None):
movie = {} movie = {}
for key in self._public_fields: for key in self._public_fields:
@ -220,25 +250,13 @@ class Movie(models.Model):
if not fields: if not fields:
movie['stream'] = self.get_stream() movie['stream'] = self.get_stream()
movie['poster'] = self.get_poster() movie['poster'] = self.get_poster()
movie['posters'] = self.get_posters()
if fields: if fields:
for f in fields: for f in fields:
if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'): if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'):
movie[f] = getattr(self.sort, f[:-7]) movie[f] = getattr(self.sort, f[:-7])
return movie return movie
def get_stream(self):
stream = {}
if self.streams.all().count():
s = self.streams.all()[0]
if s.video and s.info:
stream['duration'] = s.info['duration']
if 'video' in s.info and s.info['video']:
stream['aspectRatio'] = s.info['video'][0]['width'] / s.info['video'][0]['height']
stream['baseUrl'] = os.path.dirname(s.video.url)
stream['profiles'] = list(set(map(lambda s: int(os.path.splitext(s['profile'])[0][:-1]), self.streams.all().values('profile'))))
return stream
def fields(self): def fields(self):
fields = {} fields = {}
for f in self._meta.fields: for f in self._meta.fields:
@ -254,13 +272,10 @@ class Movie(models.Model):
self.get('series title', ''), self.get('episode title', ''), self.get('series title', ''), self.get('episode title', ''),
self.get('season', ''), self.get('episode', '')) self.get('season', ''), self.get('episode', ''))
def frame(self, position, width=128):
stream = self.streams.filter(profile=settings.VIDEO_PROFILE+'.webm')[0]
path = os.path.join(settings.MEDIA_ROOT, movieid_path(self.movieId), 'frame', "%d"%width, "%s.jpg"%position)
if not os.path.exists(path):
extract.frame(stream.video.path, path, position, width)
return path
'''
Search related functions
'''
def updateFind(self): def updateFind(self):
try: try:
f = self.find f = self.find
@ -387,79 +402,15 @@ class Movie(models.Model):
else: else:
Facet.objects.filter(movie=self, key='year').delete() Facet.objects.filter(movie=self, key='year').delete()
def updatePosterUrls(self): '''
_current = {} Video related functions
for s in settings.POSTER_SERVICES: '''
url = s + '?movieId=' + self.movieId def frame(self, position, width=128):
try: stream = self.streams.filter(profile=settings.VIDEO_PROFILE+'.webm')[0]
data = json.loads(ox.net.readUrlUnicode(url)) path = os.path.join(settings.MEDIA_ROOT, movieid_path(self.movieId), 'frame', "%d"%width, "%s.jpg"%position)
except: if not os.path.exists(path):
continue extract.frame(stream.video.path, path, position, width)
for service in data: return path
if service not in _current:
_current[service] = []
for poster in data[service]:
_current[service].append(poster)
#FIXME: remove urls that are no longer listed
for service in _current:
for poster in _current[service]:
p, created = PosterUrl.objects.get_or_create(movie=self, url=poster['url'], service=service)
if created:
p.width = poster['width']
p.height = poster['height']
p.save()
def poster_delete(self):
path = self.poster.path
self.poster.delete()
for f in glob(path.replace('.jpg', '*.jpg')):
os.unlink(f)
def poster_download(self):
if not self.poster:
url = self.poster_url
if not url:
self.updatePosterUrls()
if self.poster_urls.count() > 0:
url = self.poster_urls.all().order_by('-height')[0].url
if url:
print url
data = ox.net.readUrl(url)
self.poster.save('poster.jpg', ContentFile(data))
self.save()
else:
local_posters = self.make_local_posters()
if local_posters:
with open(local_posters[0]) as f:
self.poster.save('poster.jpg', ContentFile(f.read()))
def local_posters(self):
part = 1
posters = {}
for f in self.files.filter(is_main=True, available=True):
for frame in f.frames.all():
path = os.path.join(movieid_path(self.movieId), 'poster.pandora.%s.%s.jpg'%(part, frame.position))
path = os.path.abspath(os.path.join(settings.MEDIA_ROOT, path))
posters[path] = frame.frame.path
part += 1
return posters
def make_local_posters(self):
posters = self.local_posters()
for poster in posters:
frame = posters[poster]
cmd = ['oxposter',
'-t', self.get('title'),
'-d', ', '.join(self.get('directors', ['Unknown Director'])),
'-f', frame,
'-p', poster
]
if len(self.movieId) == 7:
cmd += ['-i', self.movieId]
cmd += ['-o', self.oxdbId]
p = subprocess.Popen(cmd)
p.wait()
return posters.keys()
@property @property
def timeline_prefix(self): def timeline_prefix(self):
@ -498,6 +449,87 @@ class Movie(models.Model):
self.available = True self.available = True
self.save() self.save()
'''
Poster related functions
'''
def update_poster_urls(self):
_current = {}
for s in settings.POSTER_SERVICES:
url = s + '?movieId=' + self.movieId
try:
data = json.loads(ox.net.readUrlUnicode(url))
except:
continue
for service in data:
if service not in _current:
_current[service] = []
for poster in data[service]:
_current[service].append(poster)
#FIXME: remove urls that are no longer listed
for service in _current:
for poster in _current[service]:
p, created = PosterUrl.objects.get_or_create(movie=self, url=poster['url'], service=service)
if created:
p.width = poster['width']
p.height = poster['height']
p.save()
def delete_poster(self):
path = self.poster.path
self.poster.delete()
for f in glob(path.replace('.jpg', '*.jpg')):
os.unlink(f)
def download_poster(self, force=True):
if not self.poster or force:
url = self.poster_url
if not url:
self.update_poster_urls()
if self.poster_urls.count() > 0:
url = self.poster_urls.all().order_by('-height')[0].url
if url:
data = ox.net.readUrl(url)
if force:
self.delete_poster()
self.poster.save('poster.jpg', ContentFile(data))
self.save()
else:
if force:
self.delete_poster()
local_posters = self.make_local_posters()
if local_posters:
with open(local_posters[0]) as f:
self.poster.save('poster.jpg', ContentFile(f.read()))
def local_posters(self):
part = 1
posters = {}
for f in self.files.filter(is_main=True, available=True):
for frame in f.frames.all():
path = os.path.join(movieid_path(self.movieId), 'poster.pandora.%s.%s.jpg'%(part, frame.position))
path = os.path.abspath(os.path.join(settings.MEDIA_ROOT, path))
posters[path] = frame.frame.path
part += 1
return posters
def make_local_posters(self):
posters = self.local_posters()
for poster in posters:
frame = posters[poster]
cmd = ['oxposter',
'-t', self.get('title'),
'-d', ', '.join(self.get('directors', ['Unknown Director'])),
'-f', frame,
'-p', poster
]
if len(self.movieId) == 7:
cmd += ['-i', self.movieId]
cmd += ['-o', self.oxdbId]
p = subprocess.Popen(cmd)
p.wait()
return posters.keys()
class MovieFind(models.Model): class MovieFind(models.Model):
""" """
used to search movies, all search values are in here used to search movies, all search values are in here

View file

@ -12,6 +12,11 @@ import models
def cronjob(**kwargs): def cronjob(**kwargs):
print "do some cleanup stuff once a day" print "do some cleanup stuff once a day"
@task(ignore_resulsts=True, queue='default')
def updatePoster(movieId):
movie = models.Movie.objects.get(movieId=movieId)
movie.download_poster(True)
@task(ignore_resulsts=True, queue='default') @task(ignore_resulsts=True, queue='default')
def updateImdb(imdbId): def updateImdb(imdbId):
movie = models.Movie.objects.get(movieId=imdbId) movie = models.Movie.objects.get(movieId=imdbId)

View file

@ -78,6 +78,7 @@ def api_hello(request):
return {'status': {'code': int, 'text': string}, return {'status': {'code': int, 'text': string},
'data': {user: object}} 'data': {user: object}}
''' '''
#data = json.loads(request.POST['data'])
response = json_response({}) response = json_response({})
if request.user.is_authenticated(): if request.user.is_authenticated():
response['data']['user'] = getUserJSON(request.user) response['data']['user'] = getUserJSON(request.user)
@ -278,7 +279,7 @@ def api_getItem(request):
itemId = json.loads(request.POST['data']) itemId = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=itemId) item = get_object_or_404_json(models.Movie, movieId=itemId)
#FIXME: check permissions #FIXME: check permissions
response['data'] = {'item': item.json} response['data'] = {'item': item.get_json()}
return render_to_json_response(response) return render_to_json_response(response)
@login_required_json @login_required_json
@ -464,20 +465,24 @@ def api_setPoster(request): #parse path and return info
param data param data
{id: movieId, url: string} {id: movieId, url: string}
return {'status': {'code': int, 'text': string}, return {'status': {'code': int, 'text': string},
data: {poster: url}} data: {poster: {url,width,height}}}
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=data['id']) item = get_object_or_404_json(models.Movie, movieId=data['id'])
if item.editable(request.user): if item.editable(request.user):
#FIXME: check that poster is from allowed url valid_urls = [p.url for p in item.poster_urls.all()]
item.poster_url = data['url'] if data['url'] in valid_urls:
if item.poster: item.poster_url = data['url']
item.poster.delete() if item.poster:
item.save() item.poster.delete()
response = json_response(status=200, text='ok') item.save()
response['data']['poster'] = item.get_poster() tasks.updatePoster.delay(item.movieId)
response = json_response(status=200, text='ok')
response['data']['poster'] = item.get_poster()
else:
response = json_response(status=403, text='invalid poster url')
else: else:
response = json_response(status=403, text='permissino denied') response = json_response(status=403, text='permission denied')
return render_to_json_response(response) return render_to_json_response(response)
def api_getImdbId(request): def api_getImdbId(request):

View file

@ -34,7 +34,7 @@ $(function() {
position = duration/2; position = duration/2;
videoWidth += videoWidth%2; videoWidth += videoWidth%2;
videoUrl = video.baseUrl + "/96p." + ($.support.video.webm ? "webm": "mp4"); videoUrl = video.baseUrl + "/" + video.profiles[0] + "p." + ($.support.video.webm ? "webm": "mp4");
//resizeVideoPlayers(pageWidth); //resizeVideoPlayers(pageWidth);