Titivillus/quest/views.py

198 lines
5.9 KiB
Python

#!/usr/bin/env python3
"""
Quest and quest accessory views.
"""
from datetime import timedelta, datetime, timezone
import bleach
from user_messages import api
from django.views.decorators.http import require_POST
from django.contrib import messages
from django.shortcuts import render, redirect
from django.db.models import F
from django.conf import settings
from django.urls import reverse
from django.http import HttpResponse
from .models import Quest, DiceRoll, PollOption, PollVote, Page, Post
from .forms import EditQuestForm, QuestForm, PostForm
from user.models import User
from .tools import download_img, send_to_websocket
def index(request):
"""The quest page index."""
search_terms = request.GET.get('search_terms')
search_type = request.GET.get('search_type')
tags = request.GET.get('tags')
order_by = request.GET.get('order_by')
order_way = request.GET.get('order_way', 'desc')
order_keys = {
'ceation_date': 'id',
'last_post': 'latest_post_date',
'next_live': 'live_time',
}
order_by = order_keys.get(order_by, 'id')
results = Quest.objects.all()
if search_terms:
if search_type == 'title':
results = results.filter(title__unaccent__icontains=search_terms)
elif search_type == 'author':
results = results.filter(
owner__username__unaccent__icontains=search_terms)
if tags:
results = results.filter(tags__name__in=tags.split()).distinct()
if order_way == 'asc':
results = results.order_by(F(order_by).asc(nulls_last=True))
elif order_way == 'desc':
results = results.order_by(F(order_by).desc(nulls_last=True))
context = locals()
return render(request, 'quest/index.html', context)
def quest(request, quest_id, page_num='0'):
"""
Arbituary quest page view.
"""
# TODO: 404 quest not found
quest = Quest.objects.get(id=quest_id)
pages = Page.objects.filter(
quest=quest, appendix=False).order_by('page_num')
appendices = Page.objects.filter(
quest=quest, appendix=True).order_by('title')
chat_messages = reversed(quest.message_set.all().order_by('-id')[:50])
try:
page = Page.objects.get(quest=quest, page_num=page_num)
except Page.DoesNotExist:
messages.error(request, "Page not found, redirecting you.")
return redirect('quest:quest', quest_id=quest.id, page_num='0')
posts = quest.post_set.filter(page=page)
# TODO: filter by page_num as well
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest=quest)
poll_options = PollOption.objects.filter(poll__post__quest=quest)
poll_votes = PollVote.objects.filter(option__poll__post__quest=quest)
ip_address = request.META['REMOTE_ADDR']
server_user_id = settings.SERVER_USER_ID
context = locals()
if page_num == '0':
return render(request, 'quest/quest_homepage.html', context)
else:
return render(request, 'quest/quest.html', context)
def edit_quest(request, quest_id, page_num='0'):
"""
Edit quest page. Only available to the QM.
"""
quest = Quest.objects.get(id=quest_id)
prev_live = quest.live
if quest.owner != request.user:
return redirect('quest:quest', quest_id=quest_id, page_num=page_num)
if request.method == 'POST':
form = EditQuestForm(request.POST)
if form.is_valid():
quest.title = form.cleaned_data['quest_title']
quest.anon_name = form.cleaned_data['anon_name']
quest.live = form.cleaned_data['live']
quest.description = form.cleaned_data['description']
quest.banner_url = download_img(form.cleaned_data['banner_url'])
if not quest.banner_url.startswith('http'):
quest.banner_url = None
live_date = form.cleaned_data['live_date']
live_time = form.cleaned_data['live_time']
if live_date and live_time:
live_datetime = datetime.combine(
live_date,
live_time,
timezone.utc
)
tz_delta = timedelta(minutes=form.cleaned_data['timezone'])
live_datetime = live_datetime + tz_delta
quest.live_time = live_datetime
else:
quest.live_time = None
quest.save()
data = {
'live': quest.live,
'live_time': quest.live_time,
}
if data['live_time']:
data['live_time'] =data['live_time'].strftime('%Y-%m-%d %H:%M')
send_to_websocket('live', quest_id, data)
if prev_live == False and quest.live == True:
subscribers = quest.user_set.all()
for subscriber in subscribers:
api.info(
subscriber,
f"{quest.title} has gone live!",
extra_tags='subscription',
meta={
'url': reverse(
'quest:quest',
args=(quest.id, 0),
),
},
deliver_once=False,
)
return redirect('quest:quest',quest_id=quest.id, page_num=page_num)
else:
messages.error(request, "Error")
else:
pass
context = locals()
return render(request, 'quest/edit_quest.html', context)
def new_quest(request):
"""
The page for creating new quests.
"""
if not request.user.is_authenticated:
return redirect('login:index')
if request.method == 'POST':
# TODO: clean the post body
quest_form = QuestForm(request.POST)
if quest_form.is_valid():
quest = quest_form.save(commit=False)
quest.owner = request.user
quest.banner_url = download_img(quest.banner_url)
if not quest.banner_url.startswith('http'):
quest.banner_url = None
quest.save()
quest_form.save_m2m()
print(quest.tags.names())
page = Page(
quest=quest,
page_num=0,
title="Homepage",
appendix=False,
)
page.save()
return redirect('quest:quest', quest_id=quest.id)
else:
quest_form = QuestForm()
context = locals()
return render(request, 'quest/new_quest.html', context)
@require_POST
def new_tag(request, quest_id):
"""Endpoint for adding new tags to a quest."""
if not request.user.is_authenticated:
return redirect('login:index')
tag = request.POST.get('tag', '').strip()
if not tag:
return redirect('quest:quest', quest_id=quest_id, page_num='0')
quest = Quest.objects.get(id=quest_id)
tag = bleach.clean(tag)
if tag in quest.tags.names():
return redirect('quest:quest', quest_id=quest_id, page_num='0')
quest.tags.add(tag)
return redirect('quest:quest', quest_id=quest_id, page_num='0')