diff --git a/oxdb/backend/models.py b/oxdb/backend/models.py index 4465659e1..caf3f28a6 100644 --- a/oxdb/backend/models.py +++ b/oxdb/backend/models.py @@ -123,6 +123,10 @@ def newMovie(title, director, year): movie.oxdbId = "__init__%s" % random.randint(0, 100000) movie.save() movie.oxdbId = movie.oxid() + print title, director, year + print movie.oxdbId + print movie.movieId + movie.save() return movie diff --git a/oxdb/backend/urls.py b/oxdb/backend/urls.py deleted file mode 100644 index ea0b31e6a..000000000 --- a/oxdb/backend/urls.py +++ /dev/null @@ -1,45 +0,0 @@ -from django.conf.urls.defaults import * - -# Uncomment the next two lines to enable the admin: -# from django.contrib import admin -# admin.autodiscover() - -''' -files/find -files/info -files/add -files/remove - -movies/find -movies/get -movies/edit?movie_id... - -subtitles/list?oshash -subtitles/get?oshash&language -subtitles/add?oshash&language -subtitles/remove?oshash&language -''' - -urlpatterns = patterns("backend.views", - (r'^find', 'find'), - (r'^files/find', 'find_files'), - (r'^files/info', 'file_info'), - (r'^archive/(?P.+)/update', 'update_archive'), - (r'^file/parse', 'file_parse'), - (r'^subtitle/get', 'subtitles'), - - # Example: - # (r'^oxdata/', include('oxdata.foo.urls')), - - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' - # to INSTALLED_APPS to enable admin documentation: - # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - # (r'^admin/(.*)', admin.site.root), -) - -#add user urls. login, logout, preferences etc -import user_management.urls -urlpatterns += user_management.urls.urlpatterns - diff --git a/oxdb/backend/utils.py b/oxdb/backend/utils.py index b0543ec7b..496e1c23a 100644 --- a/oxdb/backend/utils.py +++ b/oxdb/backend/utils.py @@ -122,6 +122,6 @@ def parsePath(path): r['season'], r['episode'] = oxdb_season_episode(path) r['series'] = oxdb_series_title(path) r['part'] = oxdb_part(path) - r['imdbId'] = oxweb.imdb.guess(search_title, r['director']) + r['imdbId'] = oxweb.imdb.guess(search_title, r['director'], timeout=-1) return r diff --git a/oxdb/backend/views.py b/oxdb/backend/views.py index 205b1897d..70be73de6 100644 --- a/oxdb/backend/views.py +++ b/oxdb/backend/views.py @@ -21,11 +21,35 @@ except ImportError: from oxdjango.shortcuts import render_to_json_response from oxdjango.decorators import login_required_json - import models import utils from daemon import send_bg_message - + +from oxuser.views import api_login, api_logout, api_register, api_recover, api_preferences + + +def api(request): + function = request.POST['function'] + #FIXME: possible to do this in f + #data = json.loads(request.POST['data']) + + #FIXME: security considerations, web facing api should not call anything in globals!!! + f = globals().get('api_'+function, None) + if f: + response = f(request) + else: + response = {'status': 404, 'statusText': 'Unknown function %s' % function} + return render_to_json_response(response) + +def api_hello(request): + ''' + function: helo + ''' + response = {'status': 200, 'statusText': 'ok'} + response.user = request.user.json() + return render_to_json_response(response) + + ''' field.length -> movie.sort.all()[0].field o=0&n=100 @@ -123,7 +147,7 @@ Examples: #auto compleat in find box ''' -def order_query(qs, s, prefix='sort__'): +def _order_query(qs, s, prefix='sort__'): order_by = [] for e in s.split(','): o = e.split(':') @@ -137,7 +161,7 @@ def order_query(qs, s, prefix='sort__'): qs = qs.order_by(*order_by) return qs -def parse_query(request): +def _parse_query(request): get = request.GET query = {} query['i'] = 0 @@ -167,12 +191,21 @@ def parse_query(request): #group by only allows sorting by name or number of itmes return query -def find(request): - query = parse_query(request) +def api_find(request): + ''' + function: find + data: {'q': query, 's': sort, 'r': range} + + query: query string, can contain field:search more on query syntax at + http://wiki.0xdb.org/wiki/QuerySyntax + sort: comma seperated list of field:order, default: director:asc,year:desc + range: result ragne, from:to or from + ''' + query = _parse_query(request) response = {} if 'p' in query: response['items'] = [] - qs = order_query(query['q'], query['s']) + qs = _order_query(query['q'], query['s']) if 'n' in query: response = {'items': qs.count()} else: @@ -218,7 +251,7 @@ def find(request): order_by = "%s:%s" % (name, order_by[1]) else: order_by = "%s:%s" % (items, order_by[1]) - qs = order_query(qs, order_by, '') + qs = _order_query(qs, order_by, '') qs = qs[query['i']:query['o']] response['items'] = [{'title': i[name], 'items': i[items]} for i in qs] @@ -235,6 +268,129 @@ def find(request): response['duration'] = r['duration__count'] return render_to_json_response(response) +def api_getItem(request): + ''' + function: getItem + + api('getItem', id) + return item with id + ''' + response = {'status': 200, 'statusText': 'ok'} + itemId = json.loads(request.POST['data']) + item = models.Movie.objects.get(movieId=itemId) + response['item'] = item.json() + return render_to_json_response(response) + +def api_editItem(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_removeItem(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_addLayer(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_removeLayer(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_editLayer(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_addListItem(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_removeListItem(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_addList(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_editList(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) +def api_removeList(request): + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) + +''' +POST update + > files: { + oshash: { 'path': .., ..}, + oshash: { 'path': .., ..}, + } +''' +#@login_required_json +def api_update(request, archive): + print "update request" + data = json.loads(request.POST['data']) + archive = data['archive'] + files = data['files'] + archive = models.Archive.objects.get(name=archive) + print "update request for", archive.name + needs_data = [] + rename = {} + for oshash in files: + print 'checking', oshash + data = files[oshash] + q = models.ArchiveFile.objects.filter(archive=archive, file__oshash=oshash) + if q.count() == 0: + print "adding file", oshash, data['path'] + f = models.ArchiveFile.get_or_create(archive, oshash) + f.update(data) + if not f.file.movie: + send_bg_message({'findMovie': f.file.id}) + #FIXME: only add if it was not in File + else: + f = q[0] + if data['path'] != f.path: + f.path = data['path'] + f.save() + if f.file.needs_data: + needs_data.append(oshash) + if f.path != f.file.path: + rename[oshash] = f.file.path + print "processed files for", archive.name + #remove all files not in files.keys() from ArchiveFile + response = {'status': 200, 'statusText': 'ok'} + response['info'] = needs_data + response['rename'] = rename + return render_to_json_response(response) + + +def api_upload(request): #video, timeline, frame + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) + +def api_file(request): #FIXME: should this be file.files. or part of update + ''' + change file / imdb link + ''' + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) + +def api_parse(request): #parse path and return info + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) + +def api_guess(request): #guess imdb based on title, director, year + response = {'status': 500, 'statusText': 'not implemented'} + return render_to_json_response(response) + + + + + + + + + + + + + + + +#FIXME: old stuff below... ''' GET info?oshash=a41cde31c581e11d > { @@ -306,7 +462,7 @@ def list_files(request): def find_files(request): response = {} - query = parse_query(request) + query = _parse_query(request) response['files'] = {} qs = models.UserFile.filter(user=request.user).filter(movie_file__movie__id__in=query['q']) p = Paginator(qs, 1000) @@ -405,47 +561,6 @@ def add_video(request, oshash): response['url'] = f.stream128.url() return render_to_json_response(response) -''' -POST update - > files: { - oshash: { 'path': .., ..}, - oshash: { 'path': .., ..}, - } -''' -#@login_required_json -def update_archive(request, archive): - print "update request" - archive = models.Archive.objects.get(name=archive) - files = json.loads(request.POST['files']) - print "update request for", archive.name - needs_data = [] - rename = {} - for oshash in files: - print 'checking', oshash - data = files[oshash] - q = models.ArchiveFile.objects.filter(archive=archive, file__oshash=oshash) - if q.count() == 0: - print "adding file", oshash, data['path'] - f = models.ArchiveFile.get_or_create(archive, oshash) - f.update(data) - if not f.file.movie: - send_bg_message({'findMovie': f.file.id}) - #FIXME: only add if it was not in File - else: - f = q[0] - if data['path'] != f.path: - f.path = data['path'] - f.save() - if f.file.needs_data: - needs_data.append(oshash) - if f.path != f.file.path: - rename[oshash] = f.file.path - print "processed files for", archive.name - #remove all files not in files.keys() from ArchiveFile - response = {} - response['info'] = needs_data - response['rename'] = rename - return render_to_json_response(response) def file_parse(request): response = utils.parsePath(request.POST['path']) diff --git a/oxdb/user_management/__init__.py b/oxdb/oxuser/__init__.py similarity index 100% rename from oxdb/user_management/__init__.py rename to oxdb/oxuser/__init__.py diff --git a/oxdb/user_management/models.py b/oxdb/oxuser/models.py similarity index 61% rename from oxdb/user_management/models.py rename to oxdb/oxuser/models.py index 369a26162..66bb3c156 100644 --- a/oxdb/user_management/models.py +++ b/oxdb/oxuser/models.py @@ -11,9 +11,6 @@ class Group(models.Model): name = models.CharField(blank=True, max_length=255, unique=True) users = models.ManyToManyField(User, related_name='groups') -class Profile(models.Model): - user = models.ForeignKey(User, unique=True) - class Preference(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) @@ -21,3 +18,18 @@ class Preference(models.Model): key = models.CharField(blank=True, max_length=255) value = models.TextField(blank=True) +def getPreference(user, key, value=None): + q = Preference.objects.filter(user=user, key=key) + if q.count() > 0: + value = json.loads(q[0].value) + return value + +def setPreference(user, key, value): + value = json.dumps(value) + q = Preference.objects.filter(user=user, key=key) + if q.count() > 0: + q[0].value = value + else: + p = Preference(user=user, key=key, value=value) + p.save() + diff --git a/oxdb/user_management/tests.py b/oxdb/oxuser/tests.py similarity index 100% rename from oxdb/user_management/tests.py rename to oxdb/oxuser/tests.py diff --git a/oxdb/oxuser/urls.py b/oxdb/oxuser/urls.py new file mode 100644 index 000000000..b6da4102c --- /dev/null +++ b/oxdb/oxuser/urls.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from django.conf.urls.defaults import * + + +urlpatterns = patterns("oxdb.oxuser.views", + (r'^preferences', 'api_preferences'), + (r'^login', 'api_login'), + (r'^logout', 'api_logout'), + (r'^register', 'api_register'), + (r'^recover', 'api_recover'), +) + diff --git a/oxdb/oxuser/views.py b/oxdb/oxuser/views.py new file mode 100644 index 000000000..35679612a --- /dev/null +++ b/oxdb/oxuser/views.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from django.contrib.auth.models import User +from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404 +from django.template import RequestContext +from django.utils import simplejson as json + +from oxdjango.shortcuts import render_to_json_response +from oxdjango.decorators import login_required_json + +import models + + +def api_login(request): + ''' + function: login + data: {'username': username, 'password': password} + + username/password to login + ''' + response = {'status': 403, 'statusText': 'login failed'} + data = json.loads(request.POST['data']) + + from django.contrib.auth import authenticate, login + user = authenticate(username=data['username'], password=data['password']) + if user is not None: + if user.is_active: + user_json = {} #FIXME: preferences etc should be in here + login(request, user) + response = {'status': 200, 'message': 'You are logged in.', 'user': user_json} + else: + response = {'status': 403, 'statusText': 'Your account is disabled.'} + print "Your account has been disabled!" + else: + response = {'status': 403, 'statusText': 'Your username and password were incorrect.'} + return render_to_json_response(response) + +def api_logout(request): + ''' + function: logout + ''' + response = {'status': 200, 'statusText': 'logged out'} + if request.user.is_authenticated(): + request.user.logout() + return render_to_json_response(response) + +def api_register(request): + ''' + function: register + data: {'username': username, 'password': password, 'email': email} + + username + password + email + ''' + data = json.loads(request.POST['data']) + response = {'status': 422, 'statusText': 'username exists'} + return render_to_json_response(response) + +def api_recover(request): + data = json.loads(request.POST['data']) + + username = data['username'] + user = None + q = models.User.objects.filter(username=username) + if q.count() > 0: + user = q[0] + else: + q = models.User.objects.filter(email=username) + if q.count() > 0: + user = q[0] + if user: + #user.sendmail(...) #FIXME: send recovery mail + response = {'status': 200, 'statusText': 'recover email sent.'} + else: + response = {'status': 404, 'statusText': 'user or email not found.'} + return render_to_json_response(response) + +@login_required_json +def api_preferences(request): + ''' + function: preferences + + api('preferences') + return all preferences + api('preferences', 'key1') + return preference key1 + api('preferences', [key1, key2]) + return preference key1, key2 + api('preferences', {key: value}) + set preference key to value + ''' + response = {'status': 200, 'statusText': 'ok'} + if 'data' not in request.POST: + response['preferences'] = request.user.preferences + else: + data = json.loads(request.POST['data']) + if isinstance(data, basestring): + response = {'status': 500, 'statusText': 'fixme: get preferences not implemented'} + response['preferences'][data] = models.getPreference(user, data) + elif isinstance(data, list): + response = {'status': 500, 'statusText': 'fixme: get preferences not implemented'} + response['preferences'] = {} + for preference in data: + response['preferences'][preference] = models.getPreference(user, preference) + elif isinstance(data, dict): + response = {'status': 500, 'statusText': 'fixme: set preferences not implemented'} + for key in data: + models.setPreference(user, key, data[key]) + return render_to_json_response(response) + diff --git a/oxdb/urls.py b/oxdb/urls.py index d9685075e..37056b068 100644 --- a/oxdb/urls.py +++ b/oxdb/urls.py @@ -10,7 +10,7 @@ admin.autodiscover() urlpatterns = patterns('', # Example: (r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')), - (r'^json/', include('backend.urls')), + (r'^api/', include('backend.views.api')), (r'^$', 'app.views.index'), # Uncomment the admin/doc line below and add 'django.contrib.admindocs' diff --git a/oxdb/user_management/urls.py b/oxdb/user_management/urls.py deleted file mode 100644 index b8e3dc284..000000000 --- a/oxdb/user_management/urls.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -from django.conf.urls.defaults import * - - -urlpatterns = patterns("oxdb.user_management.views", - (r'^preferences', 'preferences'), - (r'^login', 'login'), - (r'^logout', 'logout'), - (r'^register', 'register'), - (r'^recover', 'recover'), -) - diff --git a/oxdb/user_management/views.py b/oxdb/user_management/views.py deleted file mode 100644 index 3482d60e2..000000000 --- a/oxdb/user_management/views.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -from django.contrib.auth.models import User -from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404 -from django.template import RequestContext -from django.utils import simplejson as json - -from oxdjango.shortcuts import render_to_json_response -from oxdjango.decorators import login_required_json - -import models - - -def login(request): - from django.contrib.auth import authenticate, login - response = {'status': 403, 'message': 'login required'} - username = request.POST['username'] - password = request.POST['password'] - user = authenticate(username=username, password=password) - if user is not None: - if user.is_active: - user_json = {} #FIXME: preferences etc should be in here - login(request, user) - response = {'status': 200, 'message': 'You are logged in.', 'user': user_json} - else: - response = {'status': 403, 'message': 'Your account is disabled.'} - print "Your account has been disabled!" - else: - response = {'status': 403, 'message': 'Your username and password were incorrect.'} - return render_to_json_response(response) - -def logout(request): - response = {'status': 200} - if request.user.is_authenticated(): - request.user.logout() - return render_to_json_response(response) - -def register(request): - response = {'status': 500, 'message': 'registration failed'} - return render_to_json_response(response) - -def recover(request): - username = request.POST.get('username', None) - user = None - q = User.objects.filter(username=username) - if q.count() > 0: - user = q[0] - else: - q = User.objects.filter(email=email) - if q.count() > 0: - user = q[0] - if user: - #user.sendmail(...) #FIXME: send recovery mail - response = {'status': 200, 'message': 'recovert email sent.'} - else: - response = {'status': 500, 'message': 'user or email not found.'} - return render_to_json_response(response) - -''' -GET preferences/ //get all keys -GET preferences/?key= //get key -GEt preferences/?key=&value= //set key -''' -@login_required_json -def preferences(request): - response = {'status': 200} - key = request.GET.get('key', None) - value = request.GET.get('value', None) - user = request.user - response['preferences'] = {} - if not key: # return all preferences for current user - for p in models.Preference.objects.filter(user=user): - response['preferences'][p.key] = p.value - response['preferences']['email'] = user.email - elif value == None: #return one preference - p, created = models.Preference.objects.get_or_create(user=user, key=key) - response['preferences'][key] = p.value - else: # set preference - del response['preferences'] - response['message'] = '%s saved.' % key - if key == 'password': - user.set_password(value) - user.save() - elif key == 'email': - user.email = vaule - user.save() - else: - p, created = models.Preference.objects.get_or_create(user=user, key=key) - p.value = value - p.save() - return render_to_json_response(response) -