This commit is contained in:
rolux 2011-10-22 14:51:12 +00:00
commit 140e85e9f6
13 changed files with 124 additions and 184 deletions

View file

@ -21,6 +21,7 @@
"canSeeDebugMenu": {"admin": true}, "canSeeDebugMenu": {"admin": true},
"canSeeFiles": {"staff": true, "admin": true}, "canSeeFiles": {"staff": true, "admin": true},
"canSeeItem": {"guest": 2, "member": 2, "friend": 3, "staff": 4, "admin": 4}, "canSeeItem": {"guest": 2, "member": 2, "friend": 3, "staff": 4, "admin": 4},
"canSeeNotes": {"staff": true, "admin": true},
"canSeeExtraItemViews": {"friend": true, "staff": true, "admin": true} "canSeeExtraItemViews": {"friend": true, "staff": true, "admin": true}
}, },
/* /*

View file

@ -25,7 +25,7 @@ def index(request):
return render_to_response('index.html', context) return render_to_response('index.html', context)
def embed(request): def embed(request, id):
context = RequestContext(request, {'settings': settings}) context = RequestContext(request, {'settings': settings})
return render_to_response('embed.html', context) return render_to_response('embed.html', context)

View file

@ -291,7 +291,7 @@ def average_color(prefix, start=0, end=0):
timelines = sorted(filter(lambda t: t!= '%s%sp.png'%(prefix,height), glob("%s%sp*.png"%(prefix, height)))) timelines = sorted(filter(lambda t: t!= '%s%sp.png'%(prefix,height), glob("%s%sp*.png"%(prefix, height))))
for image in timelines: for image in timelines:
start_offset = 0 start_offset = 0
timeline = Image.open(image) timeline = Image.open(image).convert('RGB')
frames += timeline.size[0] frames += timeline.size[0]
if start and frames < start: if start and frames < start:
continue continue

View file

@ -504,14 +504,9 @@ class Stream(models.Model):
self.file.save() self.file.save()
def json(self): def json(self):
if settings.XSENDFILE or settings.XACCELREDIRECT:
base_url = '/%s' % self.file.item.itemId
else:
base_url = os.path.dirname(self.video.url)
return { return {
'duration': self.duration, 'duration': self.duration,
'aspectRatio': self.aspect_ratio, 'aspectRatio': self.aspect_ratio,
'baseUrl': base_url
} }
def delete_stream(sender, **kwargs): def delete_stream(sender, **kwargs):

View file

@ -159,6 +159,8 @@ class Item(models.Model):
upload_to=lambda i, x: i.path('torrent.torrent')) upload_to=lambda i, x: i.path('torrent.torrent'))
stream_info = fields.DictField(default={}, editable=False) stream_info = fields.DictField(default={}, editable=False)
notes = models.TextField(default='')
#stream related fields #stream related fields
stream_aspect = models.FloatField(default=4/3) stream_aspect = models.FloatField(default=4/3)
@ -401,7 +403,8 @@ class Item(models.Model):
def get_json(self, keys=None): def get_json(self, keys=None):
i = { i = {
'id': self.itemId, 'id': self.itemId,
'rendered': self.rendered 'rendered': self.rendered,
'rightsLevel': self.level
} }
i.update(self.external_data) i.update(self.external_data)
i.update(self.data) i.update(self.data)

View file

@ -27,5 +27,4 @@ urlpatterns = patterns("item.views",
(r'^(?P<id>[A-Z0-9].+)/poster\.jpg$', 'siteposter'), (r'^(?P<id>[A-Z0-9].+)/poster\.jpg$', 'siteposter'),
(r'^(?P<id>[A-Z0-9].+)/frameposter(?P<position>\d+).jpg$', 'poster_frame'), (r'^(?P<id>[A-Z0-9].+)/frameposter(?P<position>\d+).jpg$', 'poster_frame'),
) )

View file

@ -395,6 +395,9 @@ def get(request):
info['layers'] = item.get_layers(request.user) info['layers'] = item.get_layers(request.user)
if data['keys'] and 'files' in data['keys']: if data['keys'] and 'files' in data['keys']:
info['files'] = item.get_files(request.user) info['files'] = item.get_files(request.user)
if not data['keys'] or 'notes' in data['keys'] \
and request.user.get_profile().capability('canSeeNotes'):
info['notes'] = item.notes
response['data'] = info response['data'] = info
else: else:
response = json_response(status=403, text='permission denied') response = json_response(status=403, text='permission denied')
@ -438,6 +441,10 @@ def editItem(request):
item = get_object_or_404_json(models.Item, itemId=data['id']) item = get_object_or_404_json(models.Item, itemId=data['id'])
if item.editable(request.user): if item.editable(request.user):
response = json_response(status=200, text='ok') response = json_response(status=200, text='ok')
if 'notes' in data:
if request.user.get_profile().capability('canSeeNotes'):
item.notes = data['notes']
del data['notes']
item.edit(data) item.edit(data)
else: else:
response = json_response(status=403, text='permissino denied') response = json_response(status=403, text='permissino denied')

View file

@ -3,15 +3,9 @@
<head> <head>
<title>{{settings.SITENAME}}</title> <title>{{settings.SITENAME}}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="shortcut icon" type="image/png" href="/static/png/icon16.png"/>
<script type='text/javascript'>
if(typeof(console)=='undefined') {
console = {};
console.log = function() {};
}
</script>
<script type="text/javascript" src="/static/oxjs/build/Ox.js"></script> <script type="text/javascript" src="/static/oxjs/build/Ox.js"></script>
<script type="text/javascript" src="/static/js/pandora.embed.js"></script> <script type="text/javascript" src="/static/js/pandoraEmbed.js"></script>
</head> </head>
<body></body> <body>
</body>
</html> </html>

View file

@ -27,6 +27,7 @@ urlpatterns = patterns('',
(r'^url=(?P<url>.*)$', 'app.views.redirect_url'), (r'^url=(?P<url>.*)$', 'app.views.redirect_url'),
(r'^file/(?P<oshash>.*)$', 'archive.views.lookup_file'), (r'^file/(?P<oshash>.*)$', 'archive.views.lookup_file'),
(r'^api/$', include('api.urls')), (r'^api/$', include('api.urls')),
(r'^resetUI$', 'user.views.reset_ui'),
(r'', include('item.urls')), (r'', include('item.urls')),
(r'^list/(?P<id>.*?)/icon(?P<size>\d*).jpg$', 'itemlist.views.icon'), (r'^list/(?P<id>.*?)/icon(?P<size>\d*).jpg$', 'itemlist.views.icon'),
(r'^robots.txt$', serve_static_file, {'location': os.path.join(settings.STATIC_ROOT, 'robots.txt'), 'content_type': 'text/plain'}), (r'^robots.txt$', serve_static_file, {'location': os.path.join(settings.STATIC_ROOT, 'robots.txt'), 'content_type': 'text/plain'}),
@ -47,7 +48,7 @@ urlpatterns += patterns('',
(r'^(V[a-z0-9]*/.*)$', 'urlalias.views.padma_video'), (r'^(V[a-z0-9]*/.*)$', 'urlalias.views.padma_video'),
) )
urlpatterns += patterns('', urlpatterns += patterns('',
(r'^.*?embed$', 'app.views.embed'), (r'^(?P<id>[A-Z0-9].+)/embed', 'app.views.embed'),
(r'^[A-Z0-9].*$', 'app.views.index'), (r'^[A-Z0-9].*$', 'app.views.index'),
(r'^[a-z0-9].+$', 'app.views.index'), (r'^[a-z0-9].+$', 'app.views.index'),
(r'^$', 'app.views.index'), (r'^$', 'app.views.index'),

View file

@ -42,6 +42,9 @@ class UserProfile(models.Model):
def get_level(self): def get_level(self):
return settings.CONFIG['userLevels'][self.level] return settings.CONFIG['userLevels'][self.level]
def capability(self, capability):
return settings.CONFIG['capabilities'][capability].get(self.get_level()) == True
def user_post_save(sender, instance, **kwargs): def user_post_save(sender, instance, **kwargs):
profile, new = UserProfile.objects.get_or_create(user=instance) profile, new = UserProfile.objects.get_or_create(user=instance)

View file

@ -4,7 +4,6 @@ import random
random.seed() random.seed()
import re import re
from django import forms
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.template import RequestContext, loader from django.template import RequestContext, loader
@ -12,6 +11,7 @@ from django.utils import simplejson as json
from django.conf import settings from django.conf import settings
from django.core.mail import send_mail, BadHeaderError from django.core.mail import send_mail, BadHeaderError
from django.db.models import Sum from django.db.models import Sum
from django.shortcuts import redirect
from ox.django.shortcuts import render_to_json_response, json_response, get_object_or_404_json from ox.django.shortcuts import render_to_json_response, json_response, get_object_or_404_json
from ox.django.decorators import admin_required_json, login_required_json from ox.django.decorators import admin_required_json, login_required_json
@ -26,11 +26,6 @@ import models
import managers import managers
class SigninForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
def signin(request): def signin(request):
''' '''
param data { param data {
@ -52,9 +47,10 @@ def signin(request):
} }
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
form = SigninForm(data, request.FILES) if 'username' in data and 'password' in data:
if form.is_valid(): data['username'] = data['username'].strip()
if models.User.objects.filter(username=form.data['username']).count() == 0: data['password'] = data['password'].strip()
if models.User.objects.filter(username=data['username']).count() == 0:
response = json_response({ response = json_response({
'errors': { 'errors': {
'username': 'Unknown Username' 'username': 'Unknown Username'
@ -112,12 +108,6 @@ def signout(request):
actions.register(signout, cache=False) actions.register(signout, cache=False)
class SignupForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
email = forms.TextInput()
def signup(request): def signup(request):
''' '''
param data { param data {
@ -140,21 +130,22 @@ def signup(request):
} }
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
form = SignupForm(data, request.FILES) if 'username' in data and 'password' in data:
if form.is_valid(): data['username'] = data['username'].strip()
if models.User.objects.filter(username=form.data['username']).count() > 0: data['password'] = data['password'].strip()
if models.User.objects.filter(username=data['username']).count() > 0:
response = json_response({ response = json_response({
'errors': { 'errors': {
'username': 'Username already exists' 'username': 'Username already exists'
} }
}) })
elif models.User.objects.filter(email=form.data['email']).count() > 0: elif models.User.objects.filter(email=data['email']).count() > 0:
response = json_response({ response = json_response({
'errors': { 'errors': {
'email': 'Email address already exits' 'email': 'Email address already exits'
} }
}) })
elif not form.data['password']: elif not data['password']:
response = json_response({ response = json_response({
'errors': { 'errors': {
'password': 'Password can not be empty' 'password': 'Password can not be empty'
@ -162,8 +153,8 @@ def signup(request):
}) })
else: else:
first_user = models.User.objects.count() == 0 first_user = models.User.objects.count() == 0
user = models.User(username=form.data['username'], email=form.data['email']) user = models.User(username=data['username'], email=data['email'])
user.set_password(form.data['password']) user.set_password(data['password'])
#make first user admin #make first user admin
user.is_superuser = first_user user.is_superuser = first_user
user.is_staff = first_user user.is_staff = first_user
@ -176,8 +167,8 @@ def signup(request):
setattr(list, key, l[key]) setattr(list, key, l[key])
list.save() list.save()
user = authenticate(username=form.data['username'], user = authenticate(username=data['username'],
password=form.data['password']) password=data['password'])
login(request, user) login(request, user)
user_json = models.init_user(user) user_json = models.init_user(user)
response = json_response({ response = json_response({
@ -375,7 +366,8 @@ def findUser(request):
''' '''
param data { param data {
key: "username", key: "username",
value: "foo", operator: "=" value: "foo",
operator: "=="
keys: [] keys: []
} }
@ -528,12 +520,6 @@ Positions
actions.register(findUsers) actions.register(findUsers)
class ContactForm(forms.Form):
email = forms.EmailField()
subject = forms.TextInput()
message = forms.TextInput()
def contact(request): def contact(request):
''' '''
param data { param data {
@ -547,8 +533,7 @@ def contact(request):
} }
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
form = ContactForm(data, request.FILES) if 'email' in data and 'message' in data:
if form.is_valid():
email = data['email'] email = data['email']
template = loader.get_template('contact_email.txt') template = loader.get_template('contact_email.txt')
context = RequestContext(request, { context = RequestContext(request, {
@ -607,6 +592,16 @@ def editPreferences(request):
actions.register(editPreferences, cache=False) actions.register(editPreferences, cache=False)
def reset_ui(request):
response = json_response()
if request.user.is_authenticated():
profile = request.user.get_profile()
profile.ui = {}
profile.save()
else:
request.session['ui'] = '{}'
return redirect('/')
def resetUI(request): def resetUI(request):
''' '''
reset user ui settings to defaults reset user ui settings to defaults

View file

@ -1,132 +0,0 @@
/***
Pandora embed
***/
Ox.load('UI', {
debug: true,
hideScreen: false,
loadImages: true,
showScreen: true,
theme: 'modern'
}, function() {
window.pandora = new Ox.App({url: '/api/'}).bindEvent({
apiURL: '/api/',
}).bindEvent('load', function(data) {
Ox.extend(pandora, {
ui: {},
info: function(item) {
var that = Ox.Element()
.append(
ui.infoTimeline = Ox.Element('<img>')
.css({
position: 'absolute',
left: 0,
bottom: 0,
height: '16px',
})
.attr('src', '/' + item + '/timeline16p.png')
)
.append(
ui.infoStill = new app.flipbook(item)
.css({
position: 'absolute',
left: 0,
width: '100%',
height: $(document).height()-16 + 'px',
})
)
return that;
},
clip: function(item, inPoint, outPoint) {
Ox.print('!@#!@#!@#', inPoint, outPoint);
var that = Ox.Element();
pandora.api.getItem(item, function(result) {
var video = result.data.stream,
format = $.support.video.supportedFormat(video.formats);
video.height = video.profiles[0];
video.width = parseInt(video.height * video.aspectRatio / 2) * 2;
video.url = video.baseUrl + '/' + video.height + 'p.' + format;
that.append(pandora.player = Ox.VideoPlayer({
controlsBottom: ['playInToOut', 'space', 'position'],
enableFind: false,
enableFullscreen: true,
enableVolume: true,
externalControls: false,
height: 192,
paused: true,
showMarkers: true,
showMilliseconds: 2,
width: 360,
'in': inPoint,
out: outPoint,
position: inPoint,
poster: '/' + item + '/' + '128p' + inPoint +'.jpg',
title: result.data.title,
video: video.url
})
.bindEvent({
position: function(data) {
if(data.position<inPoint || data.position>outPoint) {
if(!pandora.player.options('paused'))
pandora.player.togglePaused();
pandora.player.options({
position: inPoint,
});
}
}
})
);
Ox.UI.hideLoadingScreen();
});
return that;
},
flipbook: function(item) {
var that = Ox.Flipbook({
}).bindEvent('click', function(data) {
var item_url = document.location.origin + '/' + item;
window.top.location.href = item_url + '/timeline#t=' + data.position;
});
pandora.api.getItem(item, function(result) {
var duration = result.data.item.duration,
posterFrame = result.data.item.posterFrame || parseInt(duration/2),
steps = 24,
framePrefix = '/' + item + '/' + that.height() + 'p',
frames = {};
Ox.range(0, duration, duration/steps).forEach(function(position) {
position = parseInt(position);
frames[position] = framePrefix + position + '.jpg';
});
that.options({
frames: frames,
icon: framePrefix + posterFrame + '.jpg',
duration: duration
});
});
return that;
}
});
var item = document.location.pathname.split('/')[1];
function getArgument(key, result) {
var args = Ox.map(document.location.hash.substr(1).split('&'), function(a) {
a = a.split('=');
var key = a[0],
value = a[1];
return {
'key': key,
'value': value
}
});
args.forEach(function(a, i) {
Ox.print(i, a);
if (a.key == key) {
result = a.value;
return false;
}
});
return result;
}
var t = getArgument('t', '0,10').split(',')
pandora.ui.info = pandora.clip(item, parseInt(t[0]), parseInt(t[1]))
.appendTo(document.body);
});
});

74
static/js/pandoraEmbed.js Executable file
View file

@ -0,0 +1,74 @@
/***
Pandora embed
***/
Ox.load('UI', {
debug: false,
hideScreen: false,
loadImages: true,
showScreen: true,
theme: 'modern'
}, function() {
window.pandora = new Ox.App({url: '/api/'}).bindEvent({
load: function(data) {
Ox.extend(pandora, {
site: data.site,
user: data.user.level == 'guest' ? Ox.clone(data.site.user) : data.user,
ui: {},
clip: function(item, inPoint, outPoint) {
Ox.print('!@#!@#!@#', inPoint, outPoint);
var that = Ox.Element();
pandora.api.get({id: item, keys: []}, function(result) {
var video = {};
pandora.site.video.resolutions.forEach(function(resolution) {
video[resolution] = Ox.range(result.data.parts).map(function(i) {
return '/' + pandora.user.ui.item + '/'
+ resolution + 'p' + (i + 1) + '.' + pandora.user.videoFormat;
});
});
that.append(pandora.player = Ox.VideoPlayer({
controlsBottom: ['play', 'playInToOut', 'space', 'position'],
enableFind: false,
enableFullscreen: true,
enableVolume: true,
externalControls: false,
height: document.height,
'in': inPoint,
out: outPoint,
paused: true,
position: inPoint,
poster: '/' + item + '/' + '128p' + inPoint +'.jpg',
showMarkers: true,
showMilliseconds: 2,
title: result.data.title,
video: video,
width: document.width,
})
.bindEvent({
position: function(data) {
if(data.position<inPoint || data.position>outPoint) {
if(!pandora.player.options('paused'))
pandora.player.togglePaused();
pandora.player.options({
position: inPoint,
});
}
}
})
);
Ox.UI.hideLoadingScreen();
});
return that;
},
});
Ox.extend(pandora.user, {
videoFormat: Ox.UI.getVideoFormat(pandora.site.video.formats)
});
var item = document.location.pathname.split('/')[1],
inPoint = 10,
outPoint = 15;
pandora.ui.info = pandora.clip(item, inPoint, outPoint)
.css({width: '100%', height: '100%'})
.appendTo(document.body);
}
});
});