forked from 0x2620/pandora
more moving around
This commit is contained in:
parent
75f6e3b2dc
commit
bdb0365fb1
36 changed files with 200 additions and 120 deletions
5
pandora/api/models.py
Normal file
5
pandora/api/models.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vi:si:et:sw=4:sts=4:ts=4
|
||||||
|
|
||||||
|
from item.models import *
|
||||||
|
|
10
pandora/api/urls.py
Normal file
10
pandora/api/urls.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vi:si:et:sw=4:sts=4:ts=4
|
||||||
|
|
||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = patterns("api.views",
|
||||||
|
(r'^$', 'api'),
|
||||||
|
)
|
||||||
|
|
148
pandora/api/views.py
Normal file
148
pandora/api/views.py
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
# -*- 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
|
||||||
|
|
||||||
|
try:
|
||||||
|
import simplejson as json
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import simplejson as json
|
||||||
|
|
||||||
|
from oxdjango.decorators import login_required_json
|
||||||
|
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
|
||||||
|
from oxdjango.http import HttpFileResponse
|
||||||
|
import ox
|
||||||
|
|
||||||
|
import models
|
||||||
|
import utils
|
||||||
|
import tasks
|
||||||
|
|
||||||
|
from user.models import getUserJSON
|
||||||
|
from user.views import api_login, api_logout, api_register, api_contact, api_recover, api_preferences, api_findUser
|
||||||
|
|
||||||
|
from archive.views import api_update, api_upload, api_editFile
|
||||||
|
|
||||||
|
from archive.models import File
|
||||||
|
from archive import extract
|
||||||
|
|
||||||
|
from item.views import *
|
||||||
|
|
||||||
|
def api(request):
|
||||||
|
if request.META['REQUEST_METHOD'] == "OPTIONS":
|
||||||
|
response = HttpResponse('')
|
||||||
|
response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}})
|
||||||
|
response['Access-Control-Allow-Origin'] = '*'
|
||||||
|
return response
|
||||||
|
if not 'action' in request.POST:
|
||||||
|
return apidoc(request)
|
||||||
|
function = request.POST['action']
|
||||||
|
#FIXME: possible to do this in f
|
||||||
|
#data = json.loads(request.POST['data'])
|
||||||
|
|
||||||
|
f = globals().get('api_'+function, None)
|
||||||
|
if f:
|
||||||
|
response = f(request)
|
||||||
|
else:
|
||||||
|
response = render_to_json_response(json_response(status=400,
|
||||||
|
text='Unknown function %s' % function))
|
||||||
|
response['Access-Control-Allow-Origin'] = '*'
|
||||||
|
return response
|
||||||
|
|
||||||
|
def api_api(request):
|
||||||
|
'''
|
||||||
|
returns list of all known api action
|
||||||
|
return {'status': {'code': int, 'text': string},
|
||||||
|
'data': {actions: ['api', 'hello', ...]}}
|
||||||
|
'''
|
||||||
|
actions = globals().keys()
|
||||||
|
actions = map(lambda a: a[4:], filter(lambda a: a.startswith('api_'), actions))
|
||||||
|
actions.sort()
|
||||||
|
return render_to_json_response(json_response({'actions': actions}))
|
||||||
|
|
||||||
|
def api_hello(request):
|
||||||
|
'''
|
||||||
|
return {'status': {'code': int, 'text': string},
|
||||||
|
'data': {user: object}}
|
||||||
|
'''
|
||||||
|
#data = json.loads(request.POST['data'])
|
||||||
|
response = json_response({})
|
||||||
|
if request.user.is_authenticated():
|
||||||
|
response['data']['user'] = getUserJSON(request.user)
|
||||||
|
else:
|
||||||
|
response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'preferences': {}}
|
||||||
|
return render_to_json_response(response)
|
||||||
|
|
||||||
|
def api_error(request):
|
||||||
|
'''
|
||||||
|
trows 503 error
|
||||||
|
'''
|
||||||
|
success = error_is_success
|
||||||
|
return render_to_json_response({})
|
||||||
|
|
||||||
|
def apidoc(request):
|
||||||
|
'''
|
||||||
|
this is used for online documentation at http://127.0.0.1:8000/api/
|
||||||
|
'''
|
||||||
|
import sys
|
||||||
|
def trim(docstring):
|
||||||
|
if not docstring:
|
||||||
|
return ''
|
||||||
|
# Convert tabs to spaces (following the normal Python rules)
|
||||||
|
# and split into a list of lines:
|
||||||
|
lines = docstring.expandtabs().splitlines()
|
||||||
|
# Determine minimum indentation (first line doesn't count):
|
||||||
|
indent = sys.maxint
|
||||||
|
for line in lines[1:]:
|
||||||
|
stripped = line.lstrip()
|
||||||
|
if stripped:
|
||||||
|
indent = min(indent, len(line) - len(stripped))
|
||||||
|
# Remove indentation (first line is special):
|
||||||
|
trimmed = [lines[0].strip()]
|
||||||
|
if indent < sys.maxint:
|
||||||
|
for line in lines[1:]:
|
||||||
|
trimmed.append(line[indent:].rstrip())
|
||||||
|
# Strip off trailing and leading blank lines:
|
||||||
|
while trimmed and not trimmed[-1]:
|
||||||
|
trimmed.pop()
|
||||||
|
while trimmed and not trimmed[0]:
|
||||||
|
trimmed.pop(0)
|
||||||
|
# Return a single string:
|
||||||
|
return '\n'.join(trimmed)
|
||||||
|
|
||||||
|
functions = filter(lambda x: x.startswith('api_'), globals().keys())
|
||||||
|
api = []
|
||||||
|
for f in sorted(functions):
|
||||||
|
api.append({
|
||||||
|
'name': f[4:],
|
||||||
|
'doc': trim(globals()[f].__doc__).replace('\n', '<br>\n')
|
||||||
|
})
|
||||||
|
context = RequestContext(request, {'api': api,
|
||||||
|
'sitename': settings.SITENAME,})
|
||||||
|
return render_to_response('api.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
ajax html snapshots
|
||||||
|
http://code.google.com/web/ajaxcrawling/docs/html-snapshot.html
|
||||||
|
'''
|
||||||
|
def html_snapshot(request):
|
||||||
|
fragment = unquote(request.GET['_escaped_fragment_'])
|
||||||
|
url = request.build_absolute_uri('/ra')
|
||||||
|
url = 'http://'+settings.URL
|
||||||
|
response = HttpResponse('sorry, server side rendering for %s!#%s not yet implemented'%(url, fragment))
|
||||||
|
return response
|
|
@ -8,7 +8,7 @@ from oxdjango.shortcuts import json_response, render_to_json_response, get_objec
|
||||||
|
|
||||||
import models
|
import models
|
||||||
|
|
||||||
from backend.views import html_snapshot
|
from api.views import html_snapshot
|
||||||
|
|
||||||
def intro(request):
|
def intro(request):
|
||||||
context = RequestContext(request, {'settings':settings})
|
context = RequestContext(request, {'settings':settings})
|
||||||
|
|
|
@ -22,8 +22,8 @@ from ox.normalize import canonicalTitle, canonicalName
|
||||||
from firefogg import Firefogg
|
from firefogg import Firefogg
|
||||||
import chardet
|
import chardet
|
||||||
|
|
||||||
from backend import utils
|
from item import utils
|
||||||
from pandora.backend.models import Item
|
from item.models import Item
|
||||||
|
|
||||||
import extract
|
import extract
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ class File(models.Model):
|
||||||
|
|
||||||
#upload and data handling
|
#upload and data handling
|
||||||
video = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, '%s.webm'%settings.VIDEO_PROFILE))
|
video = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, '%s.webm'%settings.VIDEO_PROFILE))
|
||||||
data = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, 'data.raw'))
|
data = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, 'data.bin'))
|
||||||
|
|
||||||
def contents(self):
|
def contents(self):
|
||||||
if self.data != None:
|
if self.data != None:
|
||||||
|
|
|
@ -29,9 +29,9 @@ import ox
|
||||||
|
|
||||||
import models
|
import models
|
||||||
|
|
||||||
from backend.utils import oxid, parse_path
|
from item.utils import oxid, parse_path
|
||||||
import backend.models
|
import item.models
|
||||||
import backend.tasks
|
import item.tasks
|
||||||
|
|
||||||
@login_required_json
|
@login_required_json
|
||||||
def api_removeVolume(request):
|
def api_removeVolume(request):
|
||||||
|
@ -114,7 +114,7 @@ def api_update(request):
|
||||||
else:
|
else:
|
||||||
if not item:
|
if not item:
|
||||||
item_info = parse_path(folder)
|
item_info = parse_path(folder)
|
||||||
item = backend.models.getItem(item_info)
|
item = item.models.getItem(item_info)
|
||||||
file_object = models.File()
|
file_object = models.File()
|
||||||
file_object.oshash = oshash
|
file_object.oshash = oshash
|
||||||
file_object.name = name
|
file_object.name = name
|
||||||
|
@ -223,7 +223,7 @@ def firefogg_upload(request):
|
||||||
elif form.cleaned_data['done']:
|
elif form.cleaned_data['done']:
|
||||||
f.available = True
|
f.available = True
|
||||||
f.save()
|
f.save()
|
||||||
backend.tasks.updateStreams.delay(f.item.itemId)
|
item.tasks.updateStreams.delay(f.item.itemId)
|
||||||
response['result'] = 1
|
response['result'] = 1
|
||||||
response['done'] = 1
|
response['done'] = 1
|
||||||
return render_to_json_response(response)
|
return render_to_json_response(response)
|
||||||
|
|
0
pandora/item/__init__.py
Normal file
0
pandora/item/__init__.py
Normal file
23
pandora/item/tests.py
Normal file
23
pandora/item/tests.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
"""
|
||||||
|
This file demonstrates two different styles of tests (one doctest and one
|
||||||
|
unittest). These will both pass when you run "manage.py test".
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
self.failUnlessEqual(1 + 1, 2)
|
||||||
|
|
||||||
|
__test__ = {"doctest": """
|
||||||
|
Another way to test that 1 + 1 is equal to 2.
|
||||||
|
|
||||||
|
>>> 1 + 1 == 2
|
||||||
|
True
|
||||||
|
"""}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns("backend.views",
|
urlpatterns = patterns("item.views",
|
||||||
(r'^(?P<id>.*)/frame/(?P<size>\d+)/(?P<position>[0-9\.,]+).jpg$', 'frame'),
|
(r'^(?P<id>.*)/frame/(?P<size>\d+)/(?P<position>[0-9\.,]+).jpg$', 'frame'),
|
||||||
(r'^(?P<id>.*)/(?P<profile>.*.webm)$', 'video'),
|
(r'^(?P<id>.*)/(?P<profile>.*.webm)$', 'video'),
|
||||||
(r'^(?P<id>.*)/(?P<profile>.*.mp4)$', 'video'),
|
(r'^(?P<id>.*)/(?P<profile>.*.mp4)$', 'video'),
|
||||||
|
@ -12,6 +12,5 @@ urlpatterns = patterns("backend.views",
|
||||||
(r'^(?P<id>.*)/poster\.(?P<size>large)\.jpg$', 'poster'),
|
(r'^(?P<id>.*)/poster\.(?P<size>large)\.jpg$', 'poster'),
|
||||||
(r'^(?P<id>.*)/poster\.jpg$', 'poster'),
|
(r'^(?P<id>.*)/poster\.jpg$', 'poster'),
|
||||||
(r'^(?P<id>.*)/timelines/(?P<timeline>.+)\.(?P<size>\d+)\.(?P<position>\d+)\.png$', 'timeline'),
|
(r'^(?P<id>.*)/timelines/(?P<timeline>.+)\.(?P<size>\d+)\.(?P<position>\d+)\.png$', 'timeline'),
|
||||||
(r'^api/$', 'api'),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,66 +32,10 @@ import utils
|
||||||
import tasks
|
import tasks
|
||||||
|
|
||||||
from user.models import getUserJSON
|
from user.models import getUserJSON
|
||||||
from user.views import api_login, api_logout, api_register, api_contact, api_recover, api_preferences, api_findUser
|
|
||||||
|
|
||||||
from archive.views import api_update, api_upload, api_editFile
|
|
||||||
|
|
||||||
from archive.models import File
|
from archive.models import File
|
||||||
from archive import extract
|
from archive import extract
|
||||||
|
|
||||||
|
|
||||||
def api(request):
|
|
||||||
if request.META['REQUEST_METHOD'] == "OPTIONS":
|
|
||||||
response = HttpResponse('')
|
|
||||||
response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}})
|
|
||||||
response['Access-Control-Allow-Origin'] = '*'
|
|
||||||
return response
|
|
||||||
if not 'action' in request.POST:
|
|
||||||
return apidoc(request)
|
|
||||||
function = request.POST['action']
|
|
||||||
#FIXME: possible to do this in f
|
|
||||||
#data = json.loads(request.POST['data'])
|
|
||||||
|
|
||||||
f = globals().get('api_'+function, None)
|
|
||||||
if f:
|
|
||||||
response = f(request)
|
|
||||||
else:
|
|
||||||
response = render_to_json_response(json_response(status=400,
|
|
||||||
text='Unknown function %s' % function))
|
|
||||||
response['Access-Control-Allow-Origin'] = '*'
|
|
||||||
return response
|
|
||||||
|
|
||||||
def api_api(request):
|
|
||||||
'''
|
|
||||||
returns list of all known api action
|
|
||||||
return {'status': {'code': int, 'text': string},
|
|
||||||
'data': {actions: ['api', 'hello', ...]}}
|
|
||||||
'''
|
|
||||||
actions = globals().keys()
|
|
||||||
actions = map(lambda a: a[4:], filter(lambda a: a.startswith('api_'), actions))
|
|
||||||
actions.sort()
|
|
||||||
return render_to_json_response(json_response({'actions': actions}))
|
|
||||||
|
|
||||||
def api_hello(request):
|
|
||||||
'''
|
|
||||||
return {'status': {'code': int, 'text': string},
|
|
||||||
'data': {user: object}}
|
|
||||||
'''
|
|
||||||
#data = json.loads(request.POST['data'])
|
|
||||||
response = json_response({})
|
|
||||||
if request.user.is_authenticated():
|
|
||||||
response['data']['user'] = getUserJSON(request.user)
|
|
||||||
else:
|
|
||||||
response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'preferences': {}}
|
|
||||||
return render_to_json_response(response)
|
|
||||||
|
|
||||||
def api_error(request):
|
|
||||||
'''
|
|
||||||
trows 503 error
|
|
||||||
'''
|
|
||||||
success = error_is_success
|
|
||||||
return render_to_json_response({})
|
|
||||||
|
|
||||||
def _order_query(qs, sort, prefix='sort__'):
|
def _order_query(qs, sort, prefix='sort__'):
|
||||||
order_by = []
|
order_by = []
|
||||||
if len(sort) == 1:
|
if len(sort) == 1:
|
||||||
|
@ -489,46 +433,6 @@ def api_getImdbId(request):
|
||||||
response = json_response(status=404, text='not found')
|
response = json_response(status=404, text='not found')
|
||||||
return render_to_json_response(response)
|
return render_to_json_response(response)
|
||||||
|
|
||||||
def apidoc(request):
|
|
||||||
'''
|
|
||||||
this is used for online documentation at http://127.0.0.1:8000/api/
|
|
||||||
'''
|
|
||||||
import sys
|
|
||||||
def trim(docstring):
|
|
||||||
if not docstring:
|
|
||||||
return ''
|
|
||||||
# Convert tabs to spaces (following the normal Python rules)
|
|
||||||
# and split into a list of lines:
|
|
||||||
lines = docstring.expandtabs().splitlines()
|
|
||||||
# Determine minimum indentation (first line doesn't count):
|
|
||||||
indent = sys.maxint
|
|
||||||
for line in lines[1:]:
|
|
||||||
stripped = line.lstrip()
|
|
||||||
if stripped:
|
|
||||||
indent = min(indent, len(line) - len(stripped))
|
|
||||||
# Remove indentation (first line is special):
|
|
||||||
trimmed = [lines[0].strip()]
|
|
||||||
if indent < sys.maxint:
|
|
||||||
for line in lines[1:]:
|
|
||||||
trimmed.append(line[indent:].rstrip())
|
|
||||||
# Strip off trailing and leading blank lines:
|
|
||||||
while trimmed and not trimmed[-1]:
|
|
||||||
trimmed.pop()
|
|
||||||
while trimmed and not trimmed[0]:
|
|
||||||
trimmed.pop(0)
|
|
||||||
# Return a single string:
|
|
||||||
return '\n'.join(trimmed)
|
|
||||||
|
|
||||||
functions = filter(lambda x: x.startswith('api_'), globals().keys())
|
|
||||||
api = []
|
|
||||||
for f in sorted(functions):
|
|
||||||
api.append({
|
|
||||||
'name': f[4:],
|
|
||||||
'doc': trim(globals()[f].__doc__).replace('\n', '<br>\n')
|
|
||||||
})
|
|
||||||
context = RequestContext(request, {'api': api,
|
|
||||||
'sitename': settings.SITENAME,})
|
|
||||||
return render_to_response('api.html', context)
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
media delivery
|
media delivery
|
||||||
|
@ -577,14 +481,3 @@ def video(request, id, profile):
|
||||||
content_type = path.endswith('.mp4') and 'video/mp4' or 'video/webm'
|
content_type = path.endswith('.mp4') and 'video/mp4' or 'video/webm'
|
||||||
return HttpFileResponse(path, content_type=content_type)
|
return HttpFileResponse(path, content_type=content_type)
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
ajax html snapshots
|
|
||||||
http://code.google.com/web/ajaxcrawling/docs/html-snapshot.html
|
|
||||||
'''
|
|
||||||
def html_snapshot(request):
|
|
||||||
fragment = unquote(request.GET['_escaped_fragment_'])
|
|
||||||
url = request.build_absolute_uri('/ra')
|
|
||||||
url = 'http://'+settings.URL
|
|
||||||
response = HttpResponse('sorry, server side rendering for %s!#%s not yet implemented'%(url, fragment))
|
|
||||||
return response
|
|
|
@ -117,7 +117,8 @@ INSTALLED_APPS = (
|
||||||
'djcelery',
|
'djcelery',
|
||||||
|
|
||||||
'app',
|
'app',
|
||||||
'backend',
|
'api',
|
||||||
|
'item',
|
||||||
'archive',
|
'archive',
|
||||||
'user',
|
'user',
|
||||||
'torrent',
|
'torrent',
|
||||||
|
|
|
@ -24,7 +24,8 @@ urlpatterns = patterns('',
|
||||||
(r'^file/(?P<oshash>.*)$', 'archive.views.lookup_file'),
|
(r'^file/(?P<oshash>.*)$', 'archive.views.lookup_file'),
|
||||||
|
|
||||||
(r'^r/(?P<key>.*)$', 'user.views.recover'),
|
(r'^r/(?P<key>.*)$', 'user.views.recover'),
|
||||||
(r'', include('backend.urls')),
|
(r'^api/$', include('api.urls')),
|
||||||
|
(r'', include('item.urls')),
|
||||||
|
|
||||||
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
||||||
# to INSTALLED_APPS to enable admin documentation:
|
# to INSTALLED_APPS to enable admin documentation:
|
||||||
|
|
Loading…
Reference in a new issue