takahe/users/views/admin/emoji.py
2023-11-09 12:07:21 -07:00

118 lines
3.7 KiB
Python

from django import forms
from django.conf import settings
from django.core.validators import RegexValidator
from django.db import models
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views.generic import FormView, ListView
from activities.models import Emoji
from users.decorators import moderator_required
from users.views.admin.generic import HTMXActionView
@method_decorator(moderator_required, name="dispatch")
class EmojiRoot(ListView):
template_name = "admin/emoji.html"
paginate_by = 50
def get(self, request, *args, **kwargs):
self.query = request.GET.get("query")
self.local_only = request.GET.get("local_only")
self.extra_context = {
"section": "emoji",
"query": self.query or "",
"local_only": self.local_only,
}
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = Emoji.objects.filter().order_by("shortcode", "domain_id")
if self.local_only:
queryset = queryset.filter(local=True)
if self.query:
query = self.query.lower().strip().lstrip("@")
queryset = queryset.filter(
models.Q(shortcode__icontains=query) | models.Q(domain_id=query)
)
return queryset
@method_decorator(moderator_required, name="dispatch")
class EmojiCreate(FormView):
template_name = "admin/emoji_create.html"
extra_context = {"section": "emoji"}
class form_class(forms.Form):
shortcode = forms.SlugField(
help_text="What users type to use the emoji :likethis:\nShould only contain 0-9, a-z and underscores",
validators=[
RegexValidator(r"^[a-z0-9_]+$", message="Invalid emoji shortcode")
],
)
image = forms.ImageField(
help_text=f"The emoji image\nShould be at least 40 x 40 pixels, and under {settings.SETUP.EMOJI_MAX_IMAGE_FILESIZE_KB}KB",
)
def clean_image(self):
data = self.cleaned_data["image"]
if data.size > settings.SETUP.EMOJI_MAX_IMAGE_FILESIZE_KB * 1024:
raise forms.ValidationError(
f"Image filesize is too large (actual: {data.size // 1024}KB)"
)
if data.image.width < 40 or data.image.height < 40:
raise forms.ValidationError(
f"Image should at least 40 x 40 pixels (actual: {data.image.width} x {data.image.height} pixels)"
)
return data
def form_valid(self, form):
Emoji.objects.create(
shortcode=form.cleaned_data["shortcode"],
file=form.cleaned_data["image"],
mimetype=form.cleaned_data["image"].image.get_format_mimetype(),
local=True,
public=True,
)
return redirect(Emoji.urls.admin)
@method_decorator(moderator_required, name="dispatch")
class EmojiDelete(HTMXActionView):
"""
Deletes an emoji
"""
model = Emoji
def action(self, emoji: Emoji):
emoji.delete()
@method_decorator(moderator_required, name="dispatch")
class EmojiEnable(HTMXActionView):
"""
Sets an emoji to be enabled (or not!)
"""
model = Emoji
enable = True
def action(self, emoji: Emoji):
emoji.public = self.enable
emoji.save()
@method_decorator(moderator_required, name="dispatch")
class EmojiCopyLocal(HTMXActionView):
"""
Duplicates a domain emoji to be local, as long as it is usable and the
shortcode is available.
"""
model = Emoji
def action(self, emoji: Emoji):
# Force reload locals cache to avoid potential for shortcode dupes
Emoji.locals = Emoji.load_locals()
emoji.copy_to_local()