forked from 0x2620/pandora
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.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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue