cleanup imports and syntax warnings

This commit is contained in:
j 2011-01-01 17:14:42 +05:30
parent 7fdae917cf
commit 2d5f924891
46 changed files with 452 additions and 517 deletions

View file

@ -2,49 +2,32 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
from datetime import datetime
import os.path
import math
import random
import re
import subprocess
import unicodedata
from glob import glob
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.conf import settings
from ox.django import fields
import ox
from ox.utils import json
from ox import stripTags
from ox.normalize import canonicalTitle, canonicalName
import utils
class Layer(models.Model):
class Meta:
ordering = ('position', )
name = models.CharField(null=True, max_length=255, unique=True)
title = models.CharField(null=True, max_length=255)
#text, string, string from list(fixme), event, place, person
#text, string, string from list(fixme), event, place, person
type = models.CharField(null=True, max_length=255)
position = models.IntegerField(default=0)
overlapping = models.BooleanField(default=True)
enabled = models.BooleanField(default=True)
overlapping = models.BooleanField(default=True)
enabled = models.BooleanField(default=True)
enabled = models.BooleanField(default=True)
public = models.BooleanField(default=True) #false=users only see there own bins
subtitle = models.BooleanField(default=True) #bis can be displayed as subtitle, only one bin
enabled = models.BooleanField(default=True)
public = models.BooleanField(default=True) #false=users only see there own bins
subtitle = models.BooleanField(default=True) #bis can be displayed as subtitle, only one bin
find = models.BooleanField(default=True)
#words / item duration(wpm), total words, cuts per minute, cuts, number of annotations, number of annotations/duration
find = models.BooleanField(default=True)
#words / item duration(wpm), total words, cuts per minute, cuts, number of annotations, number of annotations/duration
sort = models.CharField(null=True, max_length=255)
def properties(self):
@ -61,7 +44,9 @@ class Layer(models.Model):
def __unicode__(self):
return self.title
class Annotation(models.Model):
#FIXME: here having a item,start index would be good
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@ -77,9 +62,9 @@ class Annotation(models.Model):
def editable(self, user):
if user.is_authenticated():
if obj.user == user.id or user.has_perm('0x.admin'):
if self.user == user or user.has_perm('0x.admin'):
return True
if user.groups.filter(id__in=obj.groups.all()).count() > 0:
if user.groups.filter(id__in=self.groups.all()).count() > 0:
return True
return False
@ -102,4 +87,3 @@ class Annotation(models.Model):
def __unicode__(self):
return "%s/%s-%s" %(self.item, self.start, self.stop)

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -1,12 +1,15 @@
# -*- coding: utf-8 -*-
# ci:si:et:sw=4:sts=4:ts=4
import re
import ox
def html_parser(text, nofollow=True):
text = text.replace('<i>', '__i__').replace('</i>', '__/i__')
text = text.replace('<b>', '__b__').replace('</b>', '__/b__')
#truns links into wiki links, make sure to only take http links
text = re.sub('<a .*?href="(http.*?)".*?>(.*?)</a>', '[\\1 \\2]', text)
text = escape(text)
text = ox.escape(text)
text = text.replace('__i__', '<i>').replace('__/i__', '</i>')
text = text.replace('__b__', '<b>').replace('__/b__', '</b>')
if nofollow:
@ -25,7 +28,7 @@ def html_parser(text, nofollow=True):
ll = '<a href="%s"%s>%s</a>' % (link, nofollow_rel, link)
text = text.replace(t, ll)
text = urlize(text, nofollow=nofollow)
text = ox.urlize(text, nofollow=nofollow)
#inpage links
text = re.sub('\[(/.+?) (.+?)\]', '<a href="\\1">\\2</a>', text)
@ -33,4 +36,3 @@ def html_parser(text, nofollow=True):
text = text.replace('__LINK__', 'http').replace('__DOT__', '.')
text = text.replace("\n", '<br />')
return text

View file

@ -1,27 +1,10 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
import ox
import models
from api.actions import actions
@ -48,6 +31,7 @@ def findAnnotation(request):
return render_to_json_response(response)
actions.register(findAnnotation)
@login_required_json
def addAnnotation(request):
'''
@ -67,7 +51,8 @@ def addAnnotation(request):
data = json.loads(request.POST['data'])
for key in ('item', 'layer', 'start', 'end', 'value'):
if key not in data:
return render_to_json_response(json_response(status=400, text='invalid data'))
return render_to_json_response(json_response(status=400,
text='invalid data'))
item = get_object_or_404_json(models.Item, itemId=data['item'])
layer = get_object_or_404_json(models.Layer, layerId=data['layer'])
@ -77,8 +62,7 @@ def addAnnotation(request):
layer=layer,
user=request.user,
start=float(data['start']), end=float(data['end']),
value=data['value']
)
value=data['value'])
annotation.save()
response = json_response()
response['data']['annotation'] = annotation.json()
@ -88,6 +72,7 @@ def addAnnotation(request):
return render_to_json_response(response)
actions.register(addAnnotation)
@login_required_json
def removeAnnotation(request):
'''
@ -103,6 +88,7 @@ def removeAnnotation(request):
return render_to_json_response(response)
actions.register(removeAnnotation)
@login_required_json
def editAnnotation(request):
'''
@ -129,4 +115,3 @@ def editAnnotation(request):
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(editAnnotation)

View file

@ -46,8 +46,11 @@ def trim(docstring):
# Return a single string:
return '\n'.join(trimmed)
class ApiActions(dict):
def __init__(self):
def api(request):
'''
returns list of all known api action
@ -56,7 +59,8 @@ class ApiActions(dict):
'''
actions = self.keys()
actions.sort()
return render_to_json_response(json_response({'actions': actions}))
response = json_response({'actions': actions})
return render_to_json_response(response)
self['api'] = api
def apidoc(request):

View file

@ -1,54 +1,32 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
import ox
import models
from ox.django.shortcuts import render_to_json_response, json_response
from pandora.user.models import get_user_json
from pandora.archive.models import File
from pandora.archive import extract
from actions import actions
def api(request):
if request.META['REQUEST_METHOD'] == "OPTIONS":
response = HttpResponse('')
response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}})
response = render_to_json_response({'status': {'code': 200,
'text': 'use POST'}})
response['Access-Control-Allow-Origin'] = '*'
return response
if not 'action' in request.POST:
methods = actions.keys()
api = []
for f in sorted(methods):
api.append({
'name': f,
'doc': actions.doc(f).replace('\n', '<br>\n')
})
api.append({'name': f,
'doc': actions.doc(f).replace('\n', '<br>\n')})
context = RequestContext(request, {'api': api,
'sitename': settings.SITENAME,})
'sitename': settings.SITENAME})
return render_to_response('api.html', context)
function = request.POST['action']
#FIXME: possible to do this in f
@ -63,6 +41,7 @@ def api(request):
response['Access-Control-Allow-Origin'] = '*'
return response
def hello(request):
'''
return {'status': {'code': int, 'text': string},
@ -73,15 +52,17 @@ def hello(request):
if request.user.is_authenticated():
response['data']['user'] = get_user_json(request.user)
else:
response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'preferences': {}}
response['data']['user'] = {'name': 'Guest',
'group': 'guest',
'preferences': {}}
return render_to_json_response(response)
actions.register(hello)
def error(request):
'''
this action is used to test api error codes, it should return a 503 error
this action is used to test api error codes, it should return a 503 error
'''
success = error_is_success
return render_to_json_response({})
actions.register(error)

View file

@ -5,6 +5,7 @@ from django.contrib import admin
import models
class PageAdmin(admin.ModelAdmin):
search_fields = ['name', 'body']
@ -15,4 +16,3 @@ class SiteSettingsAdmin(admin.ModelAdmin):
search_fields = ['key', 'value']
admin.site.register(models.SiteSettings, SiteSettingsAdmin)

View file

@ -2,6 +2,7 @@
# vi:si:et:sw=4:sts=4:ts=4
from django.db import models
class Page(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@ -11,10 +12,10 @@ class Page(models.Model):
def __unicode__(self):
return self.name
class SiteSettings(models.Model):
key = models.CharField(max_length=1024, unique=True)
value = models.TextField(blank=True)
def __unicode__(self):
return self.key

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -1,31 +1,32 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from ox.django.shortcuts import json_response, render_to_json_response, get_object_or_404_json
from ox.utils import json
import models
from item.models import siteJson
from api.actions import actions
def intro(request):
context = RequestContext(request, {'settings':settings})
context = RequestContext(request, {'settings': settings})
return render_to_response('intro.html', context)
def index(request):
context = RequestContext(request, {'settings':settings})
if request.GET.get('_escaped_fragment_', None):
return html_snapshot(request)
context = RequestContext(request, {'settings': settings})
return render_to_response('index.html', context)
def timeline(request):
context = RequestContext(request, {'settings':settings})
context = RequestContext(request, {'settings': settings})
return render_to_response('timeline.html', context)
def getPage(request):
data = json.loads(request.POST['data'])
name = data['page']
@ -34,6 +35,7 @@ def getPage(request):
return render_to_json_response(response)
actions.register(getPage)
def site_json(request):
'''
return render_to_json_response(siteJson())
@ -41,6 +43,7 @@ def site_json(request):
siteSettings = {}
for s in models.SiteSettings.objects.all():
siteSettings[s.key] = s.value
context = RequestContext(request, {'settings':settings, 'siteSettings': siteSettings})
return render_to_response('site.json', context, mimetype="application/javascript")
context = RequestContext(request, {'settings': settings,
'siteSettings': siteSettings})
return render_to_response('site.json', context,
mimetype="application/javascript")

View file

@ -6,6 +6,7 @@ from django.contrib import admin
from forms import FileAdminForm, InstanceAdminForm
import models
class FileAdmin(admin.ModelAdmin):
search_fields = ['name', 'video_codec']
list_display = ['available', 'is_main', '__unicode__', 'itemId']
@ -18,9 +19,9 @@ class FileAdmin(admin.ModelAdmin):
admin.site.register(models.File, FileAdmin)
class InstanceAdmin(admin.ModelAdmin):
search_fields = ['name', 'folder', 'volume__name']
form = InstanceAdminForm
admin.site.register(models.Instance, InstanceAdmin)

View file

@ -3,33 +3,31 @@
from __future__ import division, with_statement
import os
from os.path import abspath, join, dirname, exists
from os.path import exists
import fractions
import subprocess
import sys
import shutil
import tempfile
import time
import re
import math
from glob import glob
import numpy as np
import Image
import ox
from ox.utils import json
img_extension='jpg'
FFMPEG2THEORA = 'ffmpeg2theora'
class AspectRatio(fractions.Fraction):
def __new__(cls, numerator, denominator=None):
if not denominator:
ratio = map(int, numerator.split(':'))
if len(ratio) == 1: ratio.append(1)
if len(ratio) == 1:
ratio.append(1)
numerator = ratio[0]
denominator = ratio[1]
#if its close enough to the common aspect ratios rather use that
@ -45,6 +43,7 @@ class AspectRatio(fractions.Fraction):
def ratio(self):
return "%d:%d" % (self.numerator, self.denominator)
def stream(video, target, profile, info):
if not os.path.exists(target):
fdir = os.path.dirname(target)
@ -118,7 +117,7 @@ def stream(video, target, profile, info):
bpp = 0.17
fps = AspectRatio(info['video'][0]['framerate'])
width = int(dar * height)
width = int(dar * height)
width += width % 2
bitrate = height*width*fps*bpp/1000
@ -184,7 +183,7 @@ def stream(video, target, profile, info):
'-me_range', '16',
'-g', '250', #FIXME: should this be related to fps?
'-keyint_min', '25', #FIXME: should this be related to fps?
'-sc_threshold','40',
'-sc_threshold', '40',
'-i_qfactor', '0.71',
'-qmin', '10', '-qmax', '51',
'-qdiff', '4'
@ -200,19 +199,20 @@ def stream(video, target, profile, info):
if format == 'mp4':
cmd += ["%s.mp4"%target]
else:
cmd += ['-f','webm', target]
cmd += ['-f', 'webm', target]
print cmd
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
p.communicate()
if format == 'mp4':
cmd = ['qt-faststart', "%s.mp4"%target, target]
cmd = ['qt-faststart', "%s.mp4"%target, target]
print cmd
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
p.communicate()
os.unlink("%s.mp4"%target)
return True
def run_command(cmd, timeout=10):
#print cmd
p = subprocess.Popen(cmd, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
@ -226,6 +226,7 @@ def run_command(cmd, timeout=10):
killedpid, stat = os.waitpid(p.pid, os.WNOHANG)
return p.returncode
def frame(videoFile, frame, position, width=128, redo=False):
'''
params:
@ -243,6 +244,7 @@ def frame(videoFile, frame, position, width=128, redo=False):
cmd = ['oxframe', '-i', videoFile, '-o', frame, '-p', str(position), '-x', str(width)]
run_command(cmd)
def resize_image(image_source, image_output, width=None, size=None):
if exists(image_source):
source = Image.open(image_source).convert('RGB')
@ -269,12 +271,13 @@ def resize_image(image_source, image_output, width=None, size=None):
output = source.resize((width, height), resize_method)
output.save(image_output)
def timeline(video, prefix):
cmd = ['oxtimeline', '-i', video, '-o', prefix]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
#stats based on timeline images
def average_color(prefix):
height = 64
width = 1500
@ -294,10 +297,12 @@ def average_color(prefix):
color += p
return list(map(float, color))
def get_distance(rgb0, rgb1):
dst = math.sqrt(pow(rgb0[0] - rgb1[0], 2) + pow(rgb0[0] - rgb1[0], 2) + pow(rgb0[0] - rgb1[0], 2))
return dst / math.sqrt(3 * pow(255, 2))
def cuts(prefix):
cuts = []
fps = 25
@ -324,6 +329,7 @@ def cuts(prefix):
cuts.append(frame / fps)
return cuts
def divide(num, by):
# >>> divide(100, 3)
# [33, 33, 34]
@ -334,9 +340,10 @@ def divide(num, by):
arr.append(div + (i > by - 1 - mod))
return arr
def timeline_strip(item, cuts, info, prefix):
_debug = False
duration = info['duration']
duration = info['duration']
video_height = info['video'][0]['height']
video_width = info['video'][0]['width']
video_ratio = video_width / video_height
@ -392,6 +399,7 @@ def timeline_strip(item, cuts, info, prefix):
print 'writing', timeline_file
timeline_image.save(timeline_file)
def chop(video, start, end):
t = end - start
tmp = tempfile.mkdtemp()
@ -401,7 +409,7 @@ def chop(video, start, end):
'-y',
'-i', video,
'-ss', '%.3f'%start,
'-t','%.3f'%t,
'-t', '%.3f'%t,
'-vcodec', 'copy',
'-acodec', 'copy',
'-f', 'webm',

View file

@ -1,4 +1,4 @@
from ajax_filtered_fields.forms import AjaxManyToManyField, ForeignKeyByLetter
from ajax_filtered_fields.forms import ForeignKeyByLetter
from django.conf import settings
from django import forms
@ -10,6 +10,8 @@ ajax_filtered_js = (
settings.STATIC_URL + 'js/jquery/jquery.js',
settings.STATIC_URL + 'js/ajax_filtered_fields.js',
)
class FileAdminForm(forms.ModelForm):
item = ForeignKeyByLetter(models.Item, field_name='itemId')
@ -28,4 +30,3 @@ class InstanceAdminForm(forms.ModelForm):
class Media:
js = ajax_filtered_js

View file

@ -1,31 +1,23 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
from datetime import datetime
import os.path
import random
import re
import time
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.utils import simplejson as json
from django.conf import settings
from ox.django import fields
import ox
from ox import stripTags
from ox.normalize import canonicalTitle, canonicalName
from firefogg import Firefogg
from ox.normalize import canonicalTitle
import chardet
from item import utils
from item.models import Item
import extract
class File(models.Model):
created = models.DateTimeField(auto_now_add=True)
@ -37,7 +29,7 @@ class File(models.Model):
item = models.ForeignKey(Item, related_name='files')
name = models.CharField(max_length=2048, default="") # canoncial path/file
sort_name = models.CharField(max_length=2048, default="") # sort path/file name
sort_name = models.CharField(max_length=2048, default="") # sort name
part = models.CharField(default="", max_length=255)
version = models.CharField(default="", max_length=255) # sort path/file name
@ -146,13 +138,14 @@ class File(models.Model):
return None
def srt(self):
def _detectEncoding(fp):
bomDict={ # bytepattern : name
(0x00, 0x00, 0xFE, 0xFF) : "utf_32_be",
(0xFF, 0xFE, 0x00, 0x00) : "utf_32_le",
(0xFE, 0xFF, None, None) : "utf_16_be",
(0xFF, 0xFE, None, None) : "utf_16_le",
(0xEF, 0xBB, 0xBF, None) : "utf_8",
(0x00, 0x00, 0xFE, 0xFF): "utf_32_be",
(0xFF, 0xFE, 0x00, 0x00): "utf_32_le",
(0xFE, 0xFF, None, None): "utf_16_be",
(0xFF, 0xFE, None, None): "utf_16_le",
(0xEF, 0xBB, 0xBF, None): "utf_8",
}
# go to beginning of file and get the first 4 bytes
@ -162,15 +155,15 @@ class File(models.Model):
# try bom detection using 4 bytes, 3 bytes, or 2 bytes
bomDetection = bomDict.get((byte1, byte2, byte3, byte4))
if not bomDetection :
if not bomDetection:
bomDetection = bomDict.get((byte1, byte2, byte3, None))
if not bomDetection :
if not bomDetection:
bomDetection = bomDict.get((byte1, byte2, None, None))
## if BOM detected, we're done :-)
fp.seek(oldFP)
if bomDetection :
return bomDetection
if bomDetection:
return bomDetection
encoding = 'latin-1'
#more character detecting magick using http://chardet.feedparser.org/
@ -221,7 +214,9 @@ class File(models.Model):
return True
return False
class Volume(models.Model):
class Meta:
unique_together = ("user", "name")
@ -234,7 +229,9 @@ class Volume(models.Model):
def __unicode__(self):
return u"%s's %s"% (self.user, self.name)
class Instance(models.Model):
class Meta:
unique_together = ("name", "folder", "volume")
@ -258,12 +255,15 @@ class Instance(models.Model):
def itemId(self):
return File.objects.get(oshash=self.oshash).itemId
def frame_path(frame, name):
ext = os.path.splitext(name)[-1]
name = "%s%s" % (frame.position, ext)
return frame.file.path(name)
class Frame(models.Model):
class Meta:
unique_together = ("file", "position")
created = models.DateTimeField(auto_now_add=True)
@ -282,5 +282,3 @@ class Frame(models.Model):
def __unicode__(self):
return u'%s at %s' % (self.file, self.position)

View file

@ -1,17 +1,15 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from datetime import timedelta
import os
import re
from celery.decorators import task, periodic_task
from celery.decorators import task
from item.utils import oxid, parse_path
from item.utils import parse_path
from item.models import get_item
import item.tasks
import models
@task(ignore_resulsts=True, queue='default')
def update_files(user, volume, files):
user = models.User.objects.get(username=user)
@ -33,9 +31,9 @@ def update_files(user, volume, files):
same_folder = models.Instance.objects.filter(folder=folder, volume=volume)
if same_folder.count() > 0:
item = same_folder[0].file.item
i = same_folder[0].file.item
else:
item = None
i = None
path = os.path.join(folder, name)
@ -48,7 +46,7 @@ def update_files(user, volume, files):
setattr(instance, key, f[key])
updated=True
if updated:
instance.save()
instance.save()
else:
#look if oshash is known
file_objects = models.File.objects.filter(oshash=oshash)
@ -56,13 +54,13 @@ def update_files(user, volume, files):
file_object = file_objects[0]
#new oshash, add to database
else:
if not item:
if not i:
item_info = parse_path(folder)
item = get_item(item_info)
i = get_item(item_info)
file_object = models.File()
file_object.oshash = oshash
file_object.name = name
file_object.item = item
file_object.item = i
file_object.save()
instance = models.Instance()
instance.volume = volume
@ -74,4 +72,3 @@ def update_files(user, volume, files):
#remove deleted files
#FIXME: can this have any bad consequences? i.e. on the selction of used item files.
models.Instance.objects.filter(volume=volume).exclude(file__oshash__in=all_files).delete()

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -2,29 +2,18 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.shortcuts import get_object_or_404, redirect
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
from ox.django.views import task_status
import ox
from item.utils import oxid, parse_path
from item.utils import parse_path
from item.models import get_item
import item.tasks
from api.actions import actions
@ -47,6 +36,7 @@ def removeVolume(request):
return render_to_json_response(response)
actions.register(removeVolume)
@login_required_json
def update(request):
'''
@ -111,12 +101,14 @@ def update(request):
return render_to_json_response(response)
actions.register(update)
@login_required_json
def encodingProfile(request):
response = json_response({'profile': settings.VIDEO_PROFILE})
return render_to_json_response(response)
actions.register(encodingProfile)
@login_required_json
def upload(request):
'''
@ -157,11 +149,13 @@ def upload(request):
return render_to_json_response(response)
actions.register(upload)
class VideoChunkForm(forms.Form):
chunk = forms.FileField()
chunkId = forms.IntegerField(required=False)
done = forms.IntegerField(required=False)
@login_required_json
def firefogg_upload(request):
profile = request.GET['profile']
@ -189,7 +183,7 @@ def firefogg_upload(request):
#FIXME: this fails badly if rabbitmq goes down
try:
t = item.tasks.update_streams.delay((f.item.itemId))
data['resultUrl'] = t.task_id
response['resultUrl'] = t.task_id
except:
pass
response['result'] = 1
@ -213,6 +207,7 @@ def firefogg_upload(request):
response = json_response(status=400, text='this request requires POST')
return render_to_json_response(response)
@login_required_json
def taskStatus(request):
#FIXME: should check if user has permissions to get status
@ -223,6 +218,7 @@ def taskStatus(request):
return render_to_json_response(response)
actions.register(taskStatus)
@login_required_json
def editFile(request):
'''
@ -257,6 +253,7 @@ def editFile(request):
return render_to_json_response(response)
actions.register(editFile)
def lookup_file(request, oshash):
f = get_object_or_404(models.File, oshash=oshash)
return redirect(f.item.get_absolute_url())
@ -270,34 +267,34 @@ def fileInfo(request):
'data': {imdbId:string }}
'''
if 'data' in request.POST:
oshash = json.loads(request.POST['data'])
elif 'oshash' in request.GET:
oshash = request.GET['oshash']
oshash = json.loads(request.POST['data'])
elif 'oshash' in request.GET:
oshash = request.GET['oshash']
f = models.ItemFile.objects.get(oshash=oshash)
response = {'data': f.json()}
return render_to_json_response(response)
actions.register(fileInfo)
def subtitles(request):
'''
param data
oshash string
language string
subtitle string
return
if no language is provided:
{data: {languages: array}}
if language is set:
{data: {subtitle: string}}
if subtitle is set:
saves subtitle for given language
'''
'''
param data
oshash string
language string
subtitle string
return
if no language is provided:
{data: {languages: array}}
if language is set:
{data: {subtitle: string}}
if subtitle is set:
saves subtitle for given language
'''
if 'data' in request.POST:
data = json.loads(request.POST['data'])
oshash = data['oshash']
language = data.get('language', None)
srt = data.get('subtitle', None)
if srt:
data = json.loads(request.POST['data'])
oshash = data['oshash']
language = data.get('language', None)
srt = data.get('subtitle', None)
if srt:
user = request.user
sub = models.Subtitles.objects.get_or_create(user, oshash, language)
sub.srt = srt
@ -307,8 +304,8 @@ def subtitles(request):
if language:
q = models.Subtitles.objects.filter(item_file__oshash=oshash, language=language)
if q.count() > 0:
response['data']['subtitle'] = q[0].srt
return render_to_json_response(response)
response['data']['subtitle'] = q[0].srt
return render_to_json_response(response)
l = models.Subtitles.objects.filter(item_file__oshash=oshash).values('language')
response['data']['languages'] = [f['language'] for f in l]
return render_to_json_response(response)

View file

@ -9,4 +9,3 @@ import models
class DateAdmin(admin.ModelAdmin):
search_fields = ['name']
admin.site.register(models.Date, DateAdmin)

View file

@ -1,15 +1,11 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import re
from ox.utils import json
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Manager
import models
class DateManager(Manager):
def get_query_set(self):
return super(DateManager, self).get_query_set()

View file

@ -3,13 +3,12 @@
from __future__ import division, with_statement
from django.db import models
from django.db.models import Q
from django.conf import settings
from ox.django import fields
import managers
class Date(models.Model):
'''
Dates are dates in time that can be once or recurring,
@ -41,4 +40,3 @@ class Date(models.Model):
self.name_sort = self.name
self.name_find = self.name + '||'.join(self.aliases)
super(Date, self).save(*args, **kwargs)

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -1,32 +1,15 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
import ox
import models
from api.actions import actions
@login_required_json
def addDate(request):
data = json.loads(request.POST['data'])
@ -39,6 +22,7 @@ def addDate(request):
return render_to_json_response(response)
actions.register(addDate)
@login_required_json
def editDate(request):
'''
@ -69,12 +53,14 @@ def editDate(request):
return render_to_json_response(response)
actions.register(editDate)
@login_required_json
def removeDate(request):
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(removeDate)
def findDate(request):
'''
param data
@ -111,8 +97,7 @@ Positions
response = json_response(status=200, text='ok')
response['data']['places'] = []
#FIXME: add coordinates to limit search
for p in Dates.objects.find(data['query']):
for p in models.Date.objects.find(data['query']):
response['data']['dates'].append(p.json())
return render_to_json_response(response)
actions.register(findDate)

View file

@ -5,6 +5,7 @@ from django.contrib import admin
import models
class ItemAdmin(admin.ModelAdmin):
search_fields = ['itemId', 'data', 'external_data']
list_display = ['available', 'itemId', '__unicode__']
@ -12,8 +13,7 @@ class ItemAdmin(admin.ModelAdmin):
admin.site.register(models.Item, ItemAdmin)
class PropertyAdmin(admin.ModelAdmin):
search_fields = ['name', 'title']
admin.site.register(models.Property, PropertyAdmin)

View file

@ -1,8 +1,5 @@
from ajax_filtered_fields.forms import AjaxManyToManyField, ForeignKeyByLetter
from django.conf import settings
from django import forms
import models
ajax_filtered_js = (
settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js",

View file

@ -1,12 +1,7 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import re
from datetime import datetime
from urllib2 import unquote
from ox.utils import json
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Manager
import models
@ -21,6 +16,7 @@ def keyType(key):
return "float"
return "string"
def parseCondition(condition):
'''
condition: {
@ -33,13 +29,15 @@ def parseCondition(condition):
operator: "!="
}
...
'''
'''
k = condition.get('key', 'all')
k = {'id': 'itemId'}.get(k, k)
if not k: k = 'all'
if not k:
k = 'all'
v = condition['value']
op = condition.get('operator', None)
if not op: op = '~'
if not op:
op = '~'
if op.startswith('!'):
op = op[1:]
exclude = True
@ -66,16 +64,17 @@ def parseCondition(condition):
k = str(k)
if exclude:
if in_find and not k.startswith('itemId'):
q = ~Q(**{'find__key':k, value_key:v})
q = ~Q(**{'find__key': k, value_key: v})
else:
q = ~Q(**{k:v})
q = ~Q(**{k: v})
else:
if in_find and not k.startswith('itemId'):
q = Q(**{'find__key':k, value_key:v})
q = Q(**{'find__key': k, value_key: v})
else:
q = Q(**{k:v})
q = Q(**{k: v})
return q
else: #number or date
def parseDate(d):
while len(d) < 3:
d.append(1)
@ -90,11 +89,11 @@ def parseCondition(condition):
if exclude: #!1960-1970
k1 = 'value__lt'
k2 = 'value__gte'
return Q(**{'find__key': k, k1:v1})|Q(**{'find__key': k, k2:v2})
return Q(**{'find__key': k, k1: v1})|Q(**{'find__key': k, k2: v2})
else: #1960-1970
k1 = 'value__gte'
k2 = 'value__lt'
return Q(**{'find__key': k, k1:v1})&Q(**{'find__key': k, k2:v2})
return Q(**{'find__key': k, k1: v1})&Q(**{'find__key': k, k2: v2})
else:
if keyType(k) == "date":
v = parseDate(v.split('.'))
@ -113,9 +112,10 @@ def parseCondition(condition):
vk = str(vk)
if exclude: #!1960
return ~Q(**{'find__key': k, vk:v})
return ~Q(**{'find__key': k, vk: v})
else: #1960
return Q(**{'find__key': k, vk:v})
return Q(**{'find__key': k, vk: v})
def parseConditions(conditions, operator):
'''
@ -135,16 +135,18 @@ def parseConditions(conditions, operator):
}
],
operator: "&"
'''
'''
conn = []
for condition in conditions:
if 'conditions' in condition:
q = parseConditions(condition['conditions'],
condition.get('operator', '&'))
if q: conn.append(q)
if q:
conn.append(q)
pass
else:
if condition.get('value', '') != '' or condition.get('operator', '') == '=':
if condition.get('value', '') != '' or \
condition.get('operator', '') == '=':
conn.append(parseCondition(condition))
if conn:
q = conn[0]
@ -156,7 +158,9 @@ def parseConditions(conditions, operator):
return q
return None
class ItemManager(Manager):
def get_query_set(self):
return super(ItemManager, self).get_query_set()
@ -165,13 +169,14 @@ class ItemManager(Manager):
l = l.split(":")
only_public = True
if not user.is_anonymous():
if len(l) == 1: l = [request.user.username] + l
if request.user.username == l[0]:
if len(l) == 1:
l = [user.username] + l
if user.username == l[0]:
only_public = False
if len(l) == 2:
lqs = models.List.objects.filter(name=l[1], user__username=l[0])
if only_public:
lqs = qls.filter(public=True)
lqs = lqs.filter(public=True)
if lqs.count() == 1:
qs = qs.filter(listitem__list__id=lqs[0].id)
return qs
@ -196,7 +201,7 @@ class ItemManager(Manager):
],
operator: "&"
}
'''
'''
#join query with operator
qs = self.get_query_set()
@ -212,4 +217,3 @@ class ItemManager(Manager):
l = data.get('list', 'all')
qs = self.filter_list(qs, l, user)
return qs

View file

@ -4,26 +4,18 @@ from __future__ import division, with_statement
from datetime import datetime
import os.path
import math
import random
import re
import subprocess
import unicodedata
from glob import glob
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.utils import simplejson as json
from django.conf import settings
from ox.django import fields
import ox
from ox import stripTags
from ox.django import fields
from ox.normalize import canonicalTitle
import ox.web.imdb
from ox.normalize import canonicalTitle, canonicalName
from firefogg import Firefogg
import managers
import utils
@ -31,23 +23,23 @@ import tasks
from archive import extract
from annotaion.models import Annotation, Layer
from person.models import get_name_sort, Person
from person.models import get_name_sort
def siteJson():
r = {}
r['findKeys'] = [{"id": "all", "title": "All"}]
for p in Property.objects.all():
if p.find:
title = p.title
if not title:
title = p.name.capitalize()
f = {"id": p.name, "title": title}
f['autocomplete'] = p.autocomplete
r['findKeys'].append(f)
r = {}
r['findKeys'] = [{"id": "all", "title": "All"}]
for p in Property.objects.all():
if p.find:
title = p.title
if not title:
title = p.name.capitalize()
f = {"id": p.name, "title": title}
f['autocomplete'] = p.autocomplete
r['findKeys'].append(f)
r['groups'] = [p.name for p in Property.objects.filter(group=True)]
r['layers'] = [l.json() for l in Layer.objects.all()]
r['groups'] = [p.name for p in Property.objects.filter(group=True)]
r['layers'] = [l.json() for l in Layer.objects.all()]
r['itemViews'] = [
{"id": "info", "title": "Info"},
@ -81,28 +73,28 @@ def siteJson():
{"id": "public", "title": "Public Lists"},
{"id": "featured", "title": "Featured Lists"}
]
r['sortKeys'] = []
for p in Property.objects.exclude(sort=''):
title = p.title
if not title:
title = p.name.capitalize()
r['sortKeys'] = []
for p in Property.objects.exclude(sort=''):
title = p.title
if not title:
title = p.name.capitalize()
f = {
"id": p.name,
"title": title,
"operator": p.operator,
"align": p.align,
"width": p.width,
}
if not p.removable:
f['removable'] = False
r['sortKeys'].append(f)
r['sortKeys'].append([{"id": "id", "title": "ID", "operator": "", "align": "left", "width": 90}])
f = {
"id": p.name,
"title": title,
"operator": p.operator,
"align": p.align,
"width": p.width,
}
if not p.removable:
f['removable'] = False
r['sortKeys'].append(f)
r['sortKeys'].append([{"id": "id", "title": "ID", "operator": "", "align": "left", "width": 90}])
r['totals'] = [{"id": "items"}]
for p in Property.objects.filter(totals=True):
f = {'id': p.name, 'admin': p.admin}
r['totals'].append(f)
r['totals'] = [{"id": "items"}]
for p in Property.objects.filter(totals=True):
f = {'id': p.name, 'admin': p.admin}
r['totals'].append(f)
#FIXME: defaults should also be populated from properties
r["user"] = {
@ -127,7 +119,8 @@ def siteJson():
},
"username": ""
}
return r
return r
def get_item(info):
'''
@ -176,28 +169,30 @@ def get_item(info):
item.save()
return item
class Property(models.Model):
class Meta:
ordering = ('position', )
verbose_name_plural = "Properties"
name = models.CharField(null=True, max_length=255, unique=True)
title = models.CharField(null=True, max_length=255, blank=True)
#text, string, string from list(fixme), event, place, person
#text, string, string from list(fixme), event, place, person
type = models.CharField(null=True, max_length=255)
array = models.BooleanField(default=False)
position = models.IntegerField(default=0)
width = models.IntegerField(default=180)
align = models.CharField(null=True, max_length=255, default='left')
operator = models.CharField(null=True, max_length=5, default='', blank=True)
default = models.BooleanField('Enabled by default', default=False)
removable = models.BooleanField(default=True)
default = models.BooleanField('Enabled by default', default=False)
removable = models.BooleanField(default=True)
#sort values: title, string, integer, float, date
#sort values: title, string, integer, float, date
sort = models.CharField(null=True, max_length=255, blank=True)
find = models.BooleanField(default=False)
autocomplete = models.BooleanField(default=False)
group = models.BooleanField(default=False)
find = models.BooleanField(default=False)
autocomplete = models.BooleanField(default=False)
group = models.BooleanField(default=False)
totals = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
@ -207,19 +202,20 @@ class Property(models.Model):
return self.title
return self.name
def json(self):
j = {}
for key in ('type', 'sort', 'title', 'array', 'totals', 'admin'):
value = getattr(self, key)
if value:
j[key] = value
return j
def json(self):
j = {}
for key in ('type', 'sort', 'title', 'array', 'totals', 'admin'):
value = getattr(self, key)
if value:
j[key] = value
return j
def save(self, *args, **kwargs):
if not self.title:
self.title = self.name.capitalize()
super(Property, self).save(*args, **kwargs)
class Item(models.Model):
person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character')
facet_keys = person_keys + ('country', 'language', 'genre', 'keyword')
@ -258,9 +254,9 @@ class Item(models.Model):
def edit(self, data):
#FIXME: how to map the keys to the right place to write them to?
for key in data:
if key != 'id':
setattr(self.data, key, data[key])
for key in data:
if key != 'id':
setattr(self.data, key, data[key])
self.oxdb.save()
self.save()
@ -339,11 +335,11 @@ class Item(models.Model):
#FIXME: this should not be used
_public_fields = {
'itemId': 'id',
'title': 'title',
'year': 'year',
'title': 'title',
'year': 'year',
'runtime': 'runtime',
'release_date': 'release_date',
'runtime': 'runtime',
'release_date': 'release_date',
'countries': 'country',
'directors': 'director',
@ -468,7 +464,9 @@ class Item(models.Model):
'''
Search related functions
'''
def update_find(self):
def save(key, value):
f, created = ItemFind.objects.get_or_create(item=self, key=key)
if value not in ('', '||'):
@ -544,10 +542,10 @@ class Item(models.Model):
# data from related subtitles
s.scenes = 0 #FIXME
s.dialog = 0 #FIXME
s.words = 0 #FIXME
s.wpm = 0 #FIXME
s.risk = 0 #FIXME
s.dialog = 0 #FIXME
s.words = 0 #FIXME
s.wpm = 0 #FIXME
s.risk = 0 #FIXME
# data from related files
videos = self.main_videos()
if len(videos) > 0:
@ -585,8 +583,8 @@ class Item(models.Model):
if not getattr(s, key):
setattr(s, key, u'zzzzzzzzzzzzzzzzzzzzzzzzz')
if not s.year:
s.year_desc = '';
s.year = '9999';
s.year_desc = ''
s.year = '9999'
#FIXME: also deal with number based rows like genre, keywords etc
s.save()
@ -624,6 +622,7 @@ class Item(models.Model):
'''
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, self.path(), 'frames', "%d"%width, "%s.jpg"%position)
@ -693,6 +692,7 @@ class Item(models.Model):
'''
Poster related functions
'''
def update_poster_urls(self):
_current = {}
for s in settings.POSTER_SERVICES:
@ -781,12 +781,14 @@ class Item(models.Model):
p.wait()
return posters.keys()
class ItemFind(models.Model):
"""
used to find items,
item.update_find populates this table
its used in manager.ItemManager
"""
class Meta:
unique_together = ("item", "key")
@ -794,8 +796,9 @@ class ItemFind(models.Model):
key = models.CharField(max_length=200, db_index=True)
value = models.TextField(blank=True)
#FIXME: make sort based on site.json
class ItemSort(models.Model):
#FIXME: make sort based on site.json
"""
used to sort items, all sort values are in here
"""
@ -872,6 +875,7 @@ class ItemSort(models.Model):
return tuple(fields)
fields = classmethod(fields)
class Facet(models.Model):
item = models.ForeignKey('Item', related_name='facets')
key = models.CharField(max_length=200, db_index=True)
@ -883,7 +887,9 @@ class Facet(models.Model):
self.value_sort = self.value
super(Facet, self).save(*args, **kwargs)
class Stream(models.Model):
class Meta:
unique_together = ("item", "profile")
@ -945,7 +951,9 @@ class Stream(models.Model):
self.info = ox.avinfo(self.video.path)
super(Stream, self).save(*args, **kwargs)
class PosterUrl(models.Model):
class Meta:
unique_together = ("item", "service", "url")
ordering = ('-height', )
@ -958,4 +966,3 @@ class PosterUrl(models.Model):
def __unicode__(self):
return u'%s %s %dx%d' % (unicode(self.item), self.service, self.width, self.height)

View file

@ -11,16 +11,19 @@ import models
def cronjob(**kwargs):
print "do some cleanup stuff once a day"
@task(ignore_resulsts=True, queue='default')
def update_poster(itemId):
item = models.Item.objects.get(itemId=itemId)
item.make_poster(True)
@task(ignore_resulsts=True, queue='default')
def update_imdb(itemId):
item = models.Item.objects.get(itemId=itemId)
item.update_imdb()
@task(queue="encoding")
def update_streams(itemId):
'''

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -13,4 +13,3 @@ urlpatterns = patterns("item.views",
(r'^(?P<id>[A-Z0-9].*)/poster\.jpg$', 'poster'),
(r'^(?P<id>[A-Z0-9].*)/timelines/(?P<timeline>.+)\.(?P<size>\d+)\.(?P<position>\d+)\.png$', 'timeline'),
)

View file

@ -2,17 +2,15 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
#
import errno
from decimal import Decimal
import os
import sys
import re
import hashlib
import unicodedata
import ox
import ox.iso
from ox.normalize import normalizeName, normalizeTitle, canonicalTitle
from ox.normalize import normalizeName, normalizeTitle
def parse_decimal(string):
@ -22,11 +20,13 @@ def parse_decimal(string):
d = string.split('/')
return Decimal(d[0]) / Decimal(d[1])
def plural_key(term):
return {
'country': 'countries',
}.get(term, term + 's')
def oxid(title, directors, year='', seriesTitle='', episodeTitle='', season=0, episode=0):
director = ', '.join(directors)
oxid_value = u"\n".join([title, director, year])
@ -38,6 +38,7 @@ def oxid(title, directors, year='', seriesTitle='', episodeTitle='', season=0, e
oxid += hashlib.sha1(oxid_value.encode('utf-8')).hexdigest()[:20]
return u"0x" + oxid
def oxdb_id(title, directors=[], year='', season='', episode='', episode_title='', episode_directors=[], episode_year=''):
# new id function, will replace oxid()
def get_hash(string):
@ -51,11 +52,13 @@ def oxdb_id(title, directors=[], year='', season='', episode='', episode_title='
get_hash('\n'.join([str(episode), episode_director, episode_title, str(episode_year)]))[:8]
return u'0x' + oxdb_id
def oxdb_directors(director):
director = os.path.basename(os.path.dirname(director))
if director.endswith('_'):
director = "%s." % director[:-1]
directors = [normalizeName(d) for d in director.split('; ')]
def cleanup(director):
director = director.strip()
director = director.replace('Series', '')
@ -65,6 +68,7 @@ def oxdb_directors(director):
directors = filter(None, [cleanup(d) for d in directors])
return directors
def oxdb_title(_title, searchTitle = False):
'''
normalize filename to get item title
@ -98,9 +102,11 @@ def oxdb_title(_title, searchTitle = False):
title = normalizeTitle(title)
return title
def oxdb_year(data):
return ox.findRe(data, '\.(\d{4})\.')
def oxdb_series_title(path):
seriesTitle = u''
if path.startswith('Series'):
@ -111,6 +117,7 @@ def oxdb_series_title(path):
seriesTitle = t.split(" (S")[0]
return seriesTitle
def oxdb_episode_title(path):
episodeTitle = u''
ep = re.compile('.Episode \d+?\.(.*?)\.[a-zA-Z]').findall(path)
@ -118,6 +125,7 @@ def oxdb_episode_title(path):
episodeTitle = ep[0]
return episodeTitle
def oxdb_season_episode(path):
season = 0
episode = 0
@ -137,6 +145,7 @@ def oxdb_season_episode(path):
episode = int(se[0][1])
return (season, episode)
def oxdb_part(path):
part = 1
path = path.lower()
@ -149,6 +158,7 @@ def oxdb_part(path):
part = p[0]
return part
def parse_path(path):
'''
expects path in the form
@ -178,6 +188,7 @@ def parse_path(path):
episode_year='')
return r
def sort_title(title):
#title
title = re.sub(u'[\'!¿¡,\.;\-"\:\*\[\]]', '', title)
@ -185,9 +196,8 @@ def sort_title(title):
#title = title.replace(u'Æ', 'Ae')
if isinstance(title, str):
title = unicode(title)
title = unicodedata.normalize('NFKD',title)
title = unicodedata.normalize('NFKD', title)
#pad numbered titles
title = re.sub('(\d+)', lambda x: '%010d' % int(x.group(0)), title)
return title.strip()

View file

@ -2,19 +2,10 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.db.models import Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.shortcuts import get_object_or_404, redirect
from django.conf import settings
from ox.utils import json
@ -28,13 +19,13 @@ import models
import utils
import tasks
from user.models import get_user_json
from archive.models import File
from archive import extract
from api.actions import actions
def _order_query(qs, sort, prefix='sort__'):
order_by = []
if len(sort) == 1:
@ -44,7 +35,8 @@ def _order_query(qs, sort, prefix='sort__'):
sort.append({'operator': '+', 'key': 'director'})
for e in sort:
operator = e['operator']
if operator != '-': operator = ''
if operator != '-':
operator = ''
key = {'id': 'itemId'}.get(e['key'], e['key'])
#FIXME: this should be a property of models.ItemSort!!!
if operator=='-' and key in ('title', 'director', 'writer', 'producer', 'editor', 'cinematographer', 'language', 'country', 'year'):
@ -371,7 +363,8 @@ def getImdbId(request):
}
}
'''
imdbId = ox.web.imdb.guess(search_title, r['director'], timeout=-1)
data = json.loads(request.POST['data'])
imdbId = ox.web.imdb.getImdbId(data['title'], data['director'], timeout=-1)
if imdbId:
response = json_response({'imdbId': imdbId})
else:
@ -406,7 +399,8 @@ def poster(request, id, size=None):
else:
poster_path = item.poster.path
else:
if not size: size='large'
if not size:
size='large'
return redirect('http://0xdb.org/%s/poster.%s.jpg' % (item.itemId, size))
poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png')
return HttpFileResponse(poster_path, content_type='image/jpeg')

View file

@ -2,29 +2,12 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
from datetime import datetime
import os.path
import math
import random
import re
import subprocess
import unicodedata
from glob import glob
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.utils import simplejson as json
from django.conf import settings
from ox.django import fields
import ox
from ox import stripTags
from ox.normalize import canonicalTitle, canonicalName
class List(models.Model):
class Meta:
unique_together = ("user", "name")
@ -33,7 +16,8 @@ class List(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=255)
public = models.BooleanField(default=False)
items = models.ManyToManyField('item.Item', related_name='lists', through='ListItem')
items = models.ManyToManyField('item.Item', related_name='lists',
through='ListItem')
def add(self, item):
q = self.items.filter(id=item.id)
@ -55,6 +39,7 @@ class List(models.Model):
return True
return False
class ListItem(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@ -63,4 +48,3 @@ class ListItem(models.Model):
def __unicode__(self):
return u'%s in %s' % (self.item, self.list)

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -1,28 +1,12 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
import ox
import models
from api.actions import actions
@ -54,6 +38,7 @@ def addListItem(request):
return render_to_json_response(response)
actions.register(addListItem)
@login_required_json
def removeListItem(request):
'''
@ -82,6 +67,7 @@ def removeListItem(request):
return render_to_json_response(response)
actions.register(removeListItem)
@login_required_json
def addList(request):
'''
@ -97,12 +83,11 @@ def addList(request):
response = json_response(status=200, text='created')
else:
response = json_response(status=200, text='list already exists')
response['data']['errors'] = {
'name': 'List already exists'
}
response['data']['errors'] = {'name': 'List already exists'}
return render_to_json_response(response)
actions.register(addList)
@login_required_json
def editList(request):
'''
@ -124,6 +109,8 @@ def editList(request):
return render_to_json_response(response)
actions.register(editList)
@login_required_json
def removeList(request):
'''
param data
@ -139,4 +126,3 @@ def removeList(request):
response = json_response(status=403, text='not allowed')
return render_to_json_response(response)
actions.register(removeList)

View file

@ -2,26 +2,12 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
from datetime import datetime
import os.path
import math
import random
import re
import subprocess
import unicodedata
from glob import glob
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.utils import simplejson as json
from django.conf import settings
from ox.django import fields
import ox
from ox import stripTags
from ox.normalize import canonicalTitle, canonicalName
def get_name_sort(name):
@ -29,6 +15,7 @@ def get_name_sort(name):
name_sort = unicodedata.normalize('NFKD', person.name_sort)
return name_sort
class Person(models.Model):
name = models.CharField(max_length=200)
name_sort = models.CharField(max_length=200)
@ -67,4 +54,3 @@ class Person(models.Model):
def json(self):
return self.name

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -9,5 +9,3 @@ import models
class PlaceAdmin(admin.ModelAdmin):
search_fields = ['name']
admin.site.register(models.Place, PlaceAdmin)

View file

@ -1,15 +1,10 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import re
from ox.utils import json
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Manager
import models
class PlaceManager(Manager):
def get_query_set(self):
return super(PlaceManager, self).get_query_set()
@ -22,7 +17,7 @@ class PlaceManager(Manager):
Q(Q(ne_lat__gt=sw_lat)|Q(ne_lat__lt=ne_lat)|Q(ne_lng__gt=sw_lng)|Q(ne_lng__lt=ne_lng))
))
if q:
qs = qs.filter(name_find__icontains, q)
qs = qs.filter(name_find__icontains=q)
return qs
'''
#only return locations that have layers of videos visible to current user

View file

@ -3,13 +3,13 @@
from __future__ import division, with_statement
from django.db import models
from django.db.models import Q
from django.conf import settings
import ox
from ox.django import fields
import managers
class Place(models.Model):
'''
Places are named locations, they should have geographical information attached to them.
@ -60,7 +60,6 @@ class Place(models.Model):
self.lng_center = ox.location.center(self.lng_sw, self.lng_ne)
#update area
self.area = location.area(self.lat_sw, self.lng_sw, self.lat_ne, self.lng_ne)
self.area = ox.location.area(self.lat_sw, self.lng_sw, self.lat_ne, self.lng_ne)
super(Place, self).save(*args, **kwargs)

View file

@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View file

@ -1,37 +1,19 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
import os.path
import re
from datetime import datetime
from urllib2 import unquote
import mimetypes
from django import forms
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
import ox
import models
from api.actions import actions
'''
fixme, require admin
'''
@login_required_json
def addPlace(request):
#FIXME: require admin
'''
param data
{
@ -56,6 +38,7 @@ def addPlace(request):
return render_to_json_response(response)
actions.register(addPlace)
@login_required_json
def editPlace(request):
'''
@ -86,12 +69,14 @@ def editPlace(request):
return render_to_json_response(response)
actions.register(editPlace)
@login_required_json
def removePlace(request):
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(removePlace)
def findPlace(request):
'''
param data
@ -129,8 +114,7 @@ Positions
response = json_response(status=200, text='ok')
response['data']['places'] = []
#FIXME: add coordinates to limit search
for p in Places.objects.find(data['query']):
for p in models.Place.objects.find(data['query']):
response['data']['places'].append(p.json())
return render_to_json_response(response)
actions.register(findPlace)

View file

@ -5,11 +5,6 @@ from datetime import datetime
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
import ox
from ox.django import fields
from ox.utils import json
class News(models.Model):
@ -29,6 +24,7 @@ class News(models.Model):
def get_absolute_url(self):
return '/text/%s' % self.slug
class Text(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@ -46,6 +42,7 @@ class Text(models.Model):
def get_absolute_url(self):
return '/text/%s' % self.slug
class Image(models.Model):
image = models.ImageField(upload_to='text/image')
caption = models.CharField(max_length=255, default="")
@ -53,10 +50,10 @@ class Image(models.Model):
def get_absolute_url(self):
return self.image.url
class Attachment(models.Model):
file = models.FileField(upload_to='text/attachment')
caption = models.CharField(max_length=255, default="")
def get_absolute_url(self):
return self.file.url

View file

@ -2,23 +2,15 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q, Avg, Count, Sum
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
import ox
import models
from api.actions import actions
def getNews(request):
'''
param data
@ -33,6 +25,23 @@ def getNews(request):
return render_to_json_response(response)
actions.register(getNews)
@login_required_json
def editNews(request):
'''
param data
string id
return page
'''
response = json_response({})
itemId = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Text, pk=itemId)
response['data']['page'] = item.html()
return render_to_json_response(response)
actions.register(editNews)
def findNews(request):
'''
'''
@ -40,6 +49,7 @@ def findNews(request):
return render_to_json_response(response)
actions.register(findNews)
def getText(request):
'''
param data
@ -54,10 +64,26 @@ def getText(request):
return render_to_json_response(response)
actions.register(getText)
@login_required_json
def editText(request):
'''
param data
string id
return page
'''
response = json_response({})
itemId = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Text, pk=itemId)
response['data']['page'] = item.html()
return render_to_json_response(response)
actions.register(editText)
def findText(request):
'''
'''
response = json_response({})
return render_to_json_response(response)
actions.register(findText)

View file

@ -10,12 +10,14 @@ from django.conf import settings
import ox.torrent
import transmissionrpc
def connect():
return transmissionrpc.Client(settings.TRANSMISSON_HOST,
port=settings.TRANSMISSON_PORT,
user=settings.TRANSMISSON_USER,
password=settings.TRANSMISSON_PASSWORD)
def remove(info_hash):
if settings.DEBUG:
print 'remove', info_hash
@ -24,10 +26,11 @@ def remove(info_hash):
tc = connect()
tc.remove(info_hash.lower())
except:
if DEBUG:
if settings.DEBUG:
import traceback
traceback.print_exc()
def add(torrent_file):
download_dir = os.path.dirname(torrent_file)
with open(torrent_file) as f:
@ -42,6 +45,7 @@ def add(torrent_file):
import traceback
traceback.print_exc()
def is_seeding(info_hash):
info_hash = info_hash.lower()
try:
@ -56,6 +60,7 @@ def is_seeding(info_hash):
return True
return False
def start_daemon():
try:
tc = connect()
@ -71,4 +76,3 @@ def start_daemon():
'-w', settings.MEDIA_ROOT,
])
time.sleep(1)

View file

@ -5,12 +5,11 @@ from datetime import datetime
from django.contrib.auth.models import User
from django.db import models
from django.db.models import signals
from django.dispatch import dispatcher
from django.conf import settings
from ox.utils import json
class UserProfile(models.Model):
reset_token = models.TextField(blank=True, null=True, unique=True)
user = models.ForeignKey(User, unique=True)
@ -18,11 +17,13 @@ class UserProfile(models.Model):
files_updated = models.DateTimeField(default=datetime.now)
newsletter = models.BooleanField(default=True)
def user_post_save(sender, instance, **kwargs):
profile, new = UserProfile.objects.get_or_create(user=instance)
models.signals.post_save.connect(user_post_save, sender=User)
class Preference(models.Model):
user = models.ForeignKey(User, related_name='preferences')
created = models.DateTimeField(auto_now_add=True)
@ -33,18 +34,20 @@ class Preference(models.Model):
def __unicode__(self):
return u"%s/%s=%s" % (self.user, self.key, self.value)
def get_user_json(user):
json = {}
result = {}
for key in ('username', ):
json[key] = getattr(user, key)
json['group'] = 'user'
result[key] = getattr(user, key)
result['group'] = 'user'
if user.is_staff:
json['group'] = 'admin'
result['group'] = 'admin'
elif user.has_perm('0x.vip'): #FIXME: permissions
json['group'] = 'vip'
json['preferences'] = get_preferences(user)
json['ui'] = get_ui(user)
return json
result['group'] = 'vip'
result['preferences'] = get_preferences(user)
result['ui'] = get_ui(user)
return result
def get_ui(user):
with open(os.path.join(settings.PROJECT_ROOT, 'templates', 'site.json')) as f:
@ -70,6 +73,7 @@ def get_ui(user):
}
'''
def get_preferences(user):
prefs = {}
for p in Preference.objects.filter(user=user):
@ -77,6 +81,7 @@ def get_preferences(user):
prefs['email'] = user.email
return prefs
def get_preference(user, key, value=None):
if key in ('email', ):
value = getattr(user, key)
@ -86,6 +91,7 @@ def get_preference(user, key, value=None):
value = json.loads(q[0].value)
return value
def set_preference(user, key, value):
if key in ('email', ):
setattr(user, key, value)

View file

@ -7,8 +7,7 @@ random.seed()
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
from django.template import RequestContext, loader, Context
from django.template import RequestContext, loader
from django.utils import simplejson as json
from django.conf import settings
from django.core.mail import send_mail, BadHeaderError
@ -26,6 +25,7 @@ class LoginForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
def api_login(request):
'''
param data {
@ -81,6 +81,7 @@ def api_login(request):
return render_to_json_response(response)
actions.register(api_login, 'login')
def api_logout(request):
'''
param data {
@ -105,11 +106,13 @@ def api_logout(request):
return render_to_json_response(response)
actions.register(api_logout, 'logout')
class RegisterForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
email = forms.TextInput()
def register(request):
'''
param data {
@ -172,6 +175,7 @@ def register(request):
return render_to_json_response(response)
actions.register(register)
def resetPassword(request):
'''
param data {
@ -226,6 +230,7 @@ def resetPassword(request):
return render_to_json_response(response)
actions.register(resetPassword)
def requestToken(request):
'''
param data {
@ -291,6 +296,7 @@ def requestToken(request):
return render_to_json_response(response)
actions.register(requestToken)
def findUser(request):
'''
param data {
@ -315,11 +321,13 @@ def findUser(request):
return render_to_json_response(response)
actions.register(findUser)
class ContactForm(forms.Form):
email = forms.EmailField()
subject = forms.TextInput()
message = forms.TextInput()
def contact(request):
'''
param data {
@ -353,6 +361,7 @@ def contact(request):
return render_to_json_response(response)
actions.register(contact)
@login_required_json
def preferences(request):
'''
@ -391,4 +400,3 @@ def preferences(request):
models.set_preference(request.user, key, data[key])
return render_to_json_response(response)
actions.register(preferences)