Source code for nkdsu.apps.vote.forms
import re
from random import choice
from typing import Any, Optional, Sequence
from uuid import uuid4
from django import forms
from django.utils.safestring import mark_safe
from .models import Note, Track, Vote
from ..vote import trivia
_disable_autocorrect = {
"autocomplete": "off",
"autocorrect": "off",
"spellcheck": "false",
}
_proper_noun_textinput = forms.TextInput(
attrs=dict(_disable_autocorrect, autocapitalize="words")
)
[docs]
class ClearableFileInput(forms.widgets.ClearableFileInput):
"""
The stock clearable file widget generates HTML that cannot be easily laid
out in a reasonable way with CSS. In particular, the way the 'clear'
checkbox is not put in any kind of elements makes intentional layout
basically impossible. Here, we aim to fix that.
"""
template_name = 'widgets/clearable_file_input.html'
[docs]
class PronounsInput(forms.TextInput):
template_name = 'widgets/pronouns_input.html'
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
attrs = {} if attrs is None else attrs
attrs.update(
autocomplete="off",
list=str(uuid4()),
placeholder='we will use they/them for you if you leave this blank',
)
super().__init__(attrs)
[docs]
class TriviaForm(forms.Form):
"""
A form protected by a trivia question.
"""
trivia_question = forms.CharField(widget=forms.HiddenInput)
trivia = forms.CharField(required=False)
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.order_fields([k for k in self.fields.keys() if k != 'trivia'] + ['trivia'])
self.fields['trivia_question'].initial = self.new_question()
[docs]
def new_question(self) -> str:
question = choice(list(trivia.questions.keys()))
self.fields['trivia'].label = 'Captcha: %s' % question
return question
[docs]
def clean_trivia(self):
human = True
if 'trivia' in self.cleaned_data:
human = re.match(
trivia.questions[self.cleaned_data['trivia_question']] + '$',
self.cleaned_data['trivia'],
re.I,
)
if not human:
hint = (
"That's not right, sorry. There are hints <a href='"
"https://codeberg.org/very-scary-scenario/nkdsu/src/branch/main/nkdsu/apps/vote/trivia.py"
"'>here</a>."
)
mutable = self.data._mutable
self.data._mutable = True
self.data['trivia_question'] = self.new_question()
self.data._mutable = mutable
raise forms.ValidationError([mark_safe(hint)])
return self.cleaned_data['trivia']
[docs]
class BadMetadataForm(forms.Form):
details = forms.CharField(
widget=forms.Textarea, label="What needs fixing?", required=False
)
track: Track
def __init__(self, *args, track: Track, **kwargs) -> None:
self.track = track
super().__init__(*args, **kwargs)
[docs]
class RequestForm(forms.Form):
"""
A form for requesting that a track be added to the library.
"""
title = forms.CharField(widget=_proper_noun_textinput, required=False)
artist = forms.CharField(widget=_proper_noun_textinput, required=False)
show = forms.CharField(
label="Source Anime", required=False, widget=_proper_noun_textinput
)
role = forms.CharField(label="Role (OP/ED/Insert/Character/etc.)", required=False)
details = forms.CharField(
widget=forms.Textarea(attrs=_disable_autocorrect),
label="Additional Details",
required=False,
)
[docs]
def clean(self) -> Optional[dict[str, Any]]:
cleaned_data = super().clean()
if cleaned_data is None:
return None
filled = [cleaned_data[f] for f in cleaned_data if cleaned_data[f]]
if len(filled) < 1:
raise forms.ValidationError(
'please provide at least some information to work with'
)
return cleaned_data
[docs]
class VoteForm(forms.ModelForm):
"""
A form for creating a :class:`.models.Vote`.
"""
tracks: Sequence[Track]
def __init__(self, *args, tracks: Sequence[Track], **kwargs):
self.tracks = tracks
super().__init__(*args, **kwargs)
[docs]
def clean(self) -> None:
super().clean()
if len(self.tracks) == 0:
raise forms.ValidationError('No tracks were selected')
[docs]
class CheckMetadataForm(forms.Form):
id3_title = forms.CharField(required=False, widget=forms.Textarea())
id3_artist = forms.CharField(required=False, widget=forms.Textarea())
composer = forms.CharField(required=False, widget=forms.Textarea())
year = forms.IntegerField(required=False)
[docs]
class LibraryUploadForm(forms.Form):
library_xml = forms.FileField(label='Library XML')
inudesu = forms.BooleanField(label='Inu Desu', required=False)
[docs]
class MyriadExportUploadForm(forms.Form):
myriad_csv = forms.FileField(label='Myriad library export CSV')
[docs]
class DarkModeForm(forms.Form):
mode = forms.ChoiceField(
choices=[
('light', 'light'),
('dark', 'dark'),
('system', 'system'),
]
)