takahe/users/views/admin/emoji.py

119 lines
3.7 KiB
Python
Raw Normal View History

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()