#!/usr/bin/env python3 """ Quest and quest accessory views. """ from datetime import timedelta, datetime, timezone import bleach 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 .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) 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) 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')