Files
MarietjeDjango/marietje/api/views.py

264 lines
7.9 KiB
Python

import time
from functools import wraps
import django.middleware.csrf as csrf
from django.contrib.auth import authenticate, login
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from django.http import JsonResponse, HttpResponseForbidden
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_http_methods
from mutagen import File
from marietje.utils import song_to_dict, playlist_song_to_dict, send_to_bertha
from queues.models import PlaylistSong, QueueCommand
from songs.models import Song
def api_auth_required(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
if request.user.is_authenticated and request.user.is_active:
return view_func(request, *args, **kwargs)
response = JsonResponse({
'error': 'User not authenticated or activated.'
})
response.status_code = 401
return response
return _wrapped_view
def login_user(request):
data = {'error': 'Method not allowed'}
status = 405
if request.method == "POST":
username = request.POST.get('username', '').strip()
password = request.POST.get('password', '').strip()
data = {'error': 'Please enter a correct username and password. '
'Note that both fields may be case-sensitive.'}
status = 401
if username and password:
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
data = {}
status = 200
else:
data = {'error': 'User is not active'}
status = 401
else:
csrf.get_token(request)
response = JsonResponse(data)
response.status_code = status
return response
@api_auth_required
def permissions(request):
return JsonResponse({
'can_move': request.user.has_perm('queues.can_move'),
'can_skip': request.user.has_perm('queues.can_skip'),
'can_cancel': request.user.has_perm('queues.can_cancel')
})
@api_auth_required
def songs(request):
try:
pagesize = int(request.POST.get('pagesize'))
except:
pagesize = 10
if not pagesize or pagesize < 10:
pagesize = 10
try:
page = int(request.POST.get('page'))
except:
page = 1
queries = [Q(deleted=False)]
queries.extend([Q(Q(artist__icontains=word) | Q(title__icontains=word)) for word in request.POST.get('all', '').split()])
queries.extend([Q(user__name__icontains=word) for word in request.POST.get('uploader', '').split()])
filter_query = queries.pop()
for query in queries:
filter_query &= query
songs_query = Song.objects.filter(filter_query).order_by('artist', 'title').select_related('user')
paginator = Paginator(songs_query, pagesize)
try:
songs = paginator.page(page)
except PageNotAnInteger:
songs = paginator.page(1)
except EmptyPage:
songs = paginator.page(paginator.num_pages)
songs_dict = [song_to_dict(song, user=True) for song in songs.object_list]
return JsonResponse({
'per_page': pagesize,
'current_page': page,
'last_page': paginator.num_pages,
'data': songs_dict
})
@api_auth_required
def managesongs(request):
try:
pagesize = int(request.POST.get('pagesize'))
except:
pagesize = 10
if not pagesize or pagesize < 10:
pagesize = 10
try:
page = int(request.POST.get('page'))
except:
page = 1
songs_query = Song.objects.filter(
user=request.user, deleted=False,
artist__icontains=request.POST.get('artist', ''),
title__icontains=request.POST.get('title', '')
).order_by('artist', 'title')
total = songs_query.count()
paginator = Paginator(songs_query, pagesize)
try:
songs = paginator.page(page)
except PageNotAnInteger:
songs = paginator.page(1)
except EmptyPage:
songs = paginator.page(paginator.num_pages)
songs_dict = [song_to_dict(song) for song in songs.object_list]
return JsonResponse({
'total': total,
'per_page': pagesize,
'current_page': page,
'last_page': paginator.num_pages,
'data': songs_dict
})
@api_auth_required
def queue(request):
queue = request.user.queue
return JsonResponse({
'current_song': playlist_song_to_dict(queue.current_song()),
'queue': [playlist_song_to_dict(playlist_song, user=request.user) for playlist_song in queue.queue()],
'started_at': 0 if queue.started_at is None else int(time.mktime(queue.started_at.timetuple())),
'current_time': int(time.time())
})
@api_auth_required
def skip(request):
playlist_song = request.user.queue.current_song()
if playlist_song.user != request.user and not request.user.has_perm('queues.can_skip'):
return HttpResponseForbidden()
playlist_song.state = 2
playlist_song.save()
return JsonResponse({})
@require_http_methods(["POST"])
@api_auth_required
def move_up(request):
if not request.user.has_perm('queues.can_move'):
return HttpResponseForbidden()
playlist_song = get_object_or_404(PlaylistSong, id=request.POST.get('id'))
playlist_song.move_up()
return JsonResponse({})
@require_http_methods(["POST"])
@api_auth_required
def move_down(request):
playlist_song = get_object_or_404(PlaylistSong, id=request.POST.get('id'))
if playlist_song.user != request.user and not request.user.has_perm('queues.can_move'):
return HttpResponseForbidden()
playlist_song.move_down()
return JsonResponse({})
@require_http_methods(["POST"])
@api_auth_required
def cancel(request):
playlist_song = get_object_or_404(PlaylistSong, id=request.POST.get('id'))
if playlist_song.user != request.user and not request.user.has_perm('queues.can_cancel'):
return HttpResponseForbidden()
playlist_song.state = 3
playlist_song.save()
return JsonResponse({})
@require_http_methods(["POST"])
@api_auth_required
def request(request):
queue = request.user.queue
song = get_object_or_404(Song, id=request.POST.get('id'), deleted=False)
queue.request(song, request.user)
return JsonResponse({
'success': True
})
@require_http_methods(["POST"])
@api_auth_required
def upload(request):
files = request.FILES.getlist('file[]')
artists = request.POST.getlist('artist[]')
titles = request.POST.getlist('title[]')
for artist in artists:
if not artist:
return JsonResponse({'success': False, 'errorMessage': 'Please enter artists which are not empty.'})
for title in titles:
if not title:
return JsonResponse({'success': False, 'errorMessage': 'Please enter titles which are not empty.'})
for i, file in enumerate(files):
duration = File(file).info.length
hash = send_to_bertha(file)
if not hash:
return JsonResponse({'success': False, 'errorMessage': 'Files not uploaded correctly.'})
song = Song(user=request.user, artist=artists[i], title=titles[i], hash=hash, duration=duration)
song.save()
return JsonResponse({'success': True})
@require_http_methods(["POST"])
@api_auth_required
def volume_down(request):
if not request.user.has_perm('queues.can_control_volume'):
return HttpResponseForbidden()
command = QueueCommand(queue=request.user.queue, command='volume_down')
command.save()
return JsonResponse({})
@require_http_methods(["POST"])
@api_auth_required
def volume_up(request):
if not request.user.has_perm('queues.can_control_volume'):
return HttpResponseForbidden()
command = QueueCommand(queue=request.user.queue, command='volume_up')
command.save()
return JsonResponse({})