more poster
This commit is contained in:
parent
be116ef7a5
commit
966c5d435a
4 changed files with 147 additions and 105 deletions
|
@ -160,6 +160,9 @@ class Movie(models.Model):
|
|||
self.updateSort()
|
||||
self.updateFacets()
|
||||
|
||||
'''
|
||||
JSON cache related functions
|
||||
'''
|
||||
_public_fields = {
|
||||
'movieId': 'id',
|
||||
'title': 'title',
|
||||
|
@ -188,8 +191,6 @@ class Movie(models.Model):
|
|||
'votes': 'votes',
|
||||
'alternative_titles': 'alternative_titles',
|
||||
'connections_json': 'connections',
|
||||
'poster_width': 'posterWidth',
|
||||
'poster_height': 'posterHeight'
|
||||
}
|
||||
def get_poster(self):
|
||||
poster = {}
|
||||
|
@ -204,6 +205,35 @@ class Movie(models.Model):
|
|||
'''
|
||||
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):
|
||||
movie = {}
|
||||
for key in self._public_fields:
|
||||
|
@ -220,25 +250,13 @@ class Movie(models.Model):
|
|||
if not fields:
|
||||
movie['stream'] = self.get_stream()
|
||||
movie['poster'] = self.get_poster()
|
||||
movie['posters'] = self.get_posters()
|
||||
if fields:
|
||||
for f in fields:
|
||||
if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'):
|
||||
movie[f] = getattr(self.sort, f[:-7])
|
||||
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):
|
||||
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('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):
|
||||
try:
|
||||
f = self.find
|
||||
|
@ -387,79 +402,15 @@ class Movie(models.Model):
|
|||
else:
|
||||
Facet.objects.filter(movie=self, key='year').delete()
|
||||
|
||||
def updatePosterUrls(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 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()
|
||||
'''
|
||||
Video related functions
|
||||
'''
|
||||
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
|
||||
|
||||
@property
|
||||
def timeline_prefix(self):
|
||||
|
@ -498,6 +449,87 @@ class Movie(models.Model):
|
|||
self.available = True
|
||||
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):
|
||||
"""
|
||||
used to search movies, all search values are in here
|
||||
|
|
|
@ -12,6 +12,11 @@ import models
|
|||
def cronjob(**kwargs):
|
||||
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')
|
||||
def updateImdb(imdbId):
|
||||
movie = models.Movie.objects.get(movieId=imdbId)
|
||||
|
|
|
@ -78,6 +78,7 @@ def api_hello(request):
|
|||
return {'status': {'code': int, 'text': string},
|
||||
'data': {user: object}}
|
||||
'''
|
||||
#data = json.loads(request.POST['data'])
|
||||
response = json_response({})
|
||||
if request.user.is_authenticated():
|
||||
response['data']['user'] = getUserJSON(request.user)
|
||||
|
@ -278,7 +279,7 @@ def api_getItem(request):
|
|||
itemId = json.loads(request.POST['data'])
|
||||
item = get_object_or_404_json(models.Movie, movieId=itemId)
|
||||
#FIXME: check permissions
|
||||
response['data'] = {'item': item.json}
|
||||
response['data'] = {'item': item.get_json()}
|
||||
return render_to_json_response(response)
|
||||
|
||||
@login_required_json
|
||||
|
@ -464,20 +465,24 @@ def api_setPoster(request): #parse path and return info
|
|||
param data
|
||||
{id: movieId, url: string}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
data: {poster: url}}
|
||||
data: {poster: {url,width,height}}}
|
||||
'''
|
||||
data = json.loads(request.POST['data'])
|
||||
item = get_object_or_404_json(models.Movie, movieId=data['id'])
|
||||
if item.editable(request.user):
|
||||
#FIXME: check that poster is from allowed url
|
||||
valid_urls = [p.url for p in item.poster_urls.all()]
|
||||
if data['url'] in valid_urls:
|
||||
item.poster_url = data['url']
|
||||
if item.poster:
|
||||
item.poster.delete()
|
||||
item.save()
|
||||
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='permissino denied')
|
||||
response = json_response(status=403, text='invalid poster url')
|
||||
else:
|
||||
response = json_response(status=403, text='permission denied')
|
||||
return render_to_json_response(response)
|
||||
|
||||
def api_getImdbId(request):
|
||||
|
|
|
@ -34,7 +34,7 @@ $(function() {
|
|||
position = duration/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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue