You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

182 lines
6.7 KiB
Python

from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.db.models import F, Min
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import timezone
from re import match
from .forms import AddBreakContentForm, CreatePlaylistForm
from .models import BreakContent
from .spreadsheet import get_sheet_data
from ..core.models import Artist, Playlist, Session
def get_absolute_join_session_url(request, session):
return request.build_absolute_uri(reverse('join_session', args=(session.pk,)))
# Create your views here.
@login_required
@transaction.atomic
def create_playlist(request):
form = CreatePlaylistForm()
if request.method == 'POST':
form = CreatePlaylistForm(request.POST)
if not form.is_valid():
return render(request, 'host/create_playlist.html', {'error': None, 'form': form})
m = match(r'https://docs.google.com/spreadsheets/d/([-0-9A-Z_a-z]{44})', form.cleaned_data['spreadsheet_url'])
if m == None:
return render(request, 'host/create_playlist.html', {'error': 'Der eingegebene Link führt nicht zu einer Google Tabelle.', 'form': CreatePlaylistForm()})
spreadsheet_id = m[1]
if Playlist.objects.filter(pk=spreadsheet_id).exists():
return redirect('playlist', spreadsheet_id)
playlist = Playlist(spreadsheet_id=spreadsheet_id)
data = get_sheet_data(spreadsheet_id)
mapping = {}
artist_names = set()
artists = []
for row in data:
row = list(map(lambda s: s.strip(), row))
if not mapping:
if settings.REQUIRED_FIELDS[0] in row:
required_fields = set(settings.REQUIRED_FIELDS)
for index, heading in enumerate(row):
if heading in required_fields:
mapping[heading] = index
required_fields.remove(heading)
if len(required_fields) == 0:
break
if len(required_fields) != 0:
return render(request, 'host/create_playlist.html', {'error': 'Die Tabelle ist nicht im passenden Format.', 'form': CreatePlaylistForm()})
playlist.field_indices = mapping
playlist.save()
continue
values = {}
for field in settings.REQUIRED_FIELDS:
index = mapping[field]
model_field, blank = settings.SHEET_TO_MODEL[field]
if index >= len(row):
if not blank:
values = {}
break
continue
value = row[index]
if not (value or blank) or model_field == 'name' and value in artist_names:
values = {}
break
values[model_field] = value
if model_field == 'name':
artist_names.add(value)
if values:
artists.append(Artist(playlist=playlist, **values))
Artist.objects.bulk_create(artists)
return redirect('playlist', playlist=spreadsheet_id)
return render(request, 'host/create_playlist.html', {'error': None, 'form': form})
@login_required
def break_view(request):
if request.method == 'POST':
session = get_object_or_404(Session, pk=request.session.get('session'))
session.last_break = timezone.now()
session.save()
return redirect('view_artist', session.playlist.pk, session.offset)
min_use_count = BreakContent.objects.aggregate(Min('use_count'))['use_count__min']
content = BreakContent.objects.filter(use_count=min_use_count).order_by('?')[0]
content.use_count = F('use_count') + 1
content.save()
return render(request, 'host/break.html', {'video_id': content.video_id})
@login_required
def add_break_content(request):
form = AddBreakContentForm()
if request.method == 'POST':
form = AddBreakContentForm(request.POST)
if not form.is_valid():
return redirect('add_break_content')
m = match(settings.YOUTUBE_RE, form.cleaned_data['video_url'])
if m == None:
return redirect('add_break_content')
min_use_count = BreakContent.objects.aggregate(Min('use_count'))['use_count__min']
content = BreakContent(video_id=m[1], use_count=min_use_count or 0)
content.save()
return redirect('add_break_content')
return render(request, 'host/add_break_content.html', {'form': form})
@login_required
def session(request):
if 'session' in request.session:
try:
session = Session.objects.get(pk=request.session['session'])
return render(request, 'host/session.html', {'session': session, 'session_url': get_absolute_join_session_url(request, session)})
except Session.DoesNotExist:
del request.session['session']
return redirect('create_playlist')
@login_required
def playlist(request, playlist):
playlist = get_object_or_404(Playlist, pk=playlist)
return render(request, 'host/playlist.html', {'num_artists': playlist.artist_set.count()})
@login_required
def start_session(request, playlist):
playlist = get_object_or_404(Playlist, pk=playlist)
if request.method == 'POST':
if 'session' in request.session:
return redirect('session')
session = Session(playlist=playlist)
session.save()
request.session['session'] = session.token
return redirect('session')
return redirect('playlist', playlist=playlist.pk)
@login_required
def view_artist(request, playlist, offset):
artists = get_object_or_404(Playlist, pk=playlist).artist_set
artist = artists.order_by('id')[offset]
links = (('youtube', m[1]) if (m := match(settings.YOUTUBE_RE, link)) else ('other', link) for link in (artist.link_1, artist.link_2) if link)
session_url = None
if 'session' in request.session:
try:
session = Session.objects.get(pk=request.session['session'])
session_url = get_absolute_join_session_url(request, session)
if session.offset < offset:
session.offset = offset
session.save()
if (timezone.now()-session.last_break).total_seconds() >= settings.BREAK_INTERVAL*60:
return redirect('break')
except Session.DoesNotExist:
del request.session['session']
return render(request, 'host/view_artist.html', {'artist': artist, 'count': artists.count(), 'links': links, 'offset': offset, 'playlist': playlist, 'session_url': session_url})