from django.contrib.admin.views.decorators import staff_member_required from django.shortcuts import redirect, render, get_object_or_404 from django.db.models.functions import TruncDate from django.db.models import Count from django.views import generic from django.conf import settings from django.urls import reverse from django.http import Http404 from nsfw import views as nsfw from .models import LogSource, LogEntry from .forms import SearchForm from utils import is_link_legit import datetime def chat_view(request): ctx = { "debug": settings.DEBUG, "bosh_url": settings.KHAGANAT_XMPP_BOSH_URL, "jid": settings.KHAGANAT_XMPP_JID, "rooms": settings.KHAGANAT_XMPP_ROOMS, "websocket_url": settings.KHAGANAT_XMPP_WEBSOCKET_URL, } return render(request, "chat/chat_conversejs.html", ctx) def _get_dates(): now = datetime.date.today() start_date = now - datetime.timedelta(days=settings.KHAGANAT_LOGS_MAX_DAYS) end_date = now - datetime.timedelta(days=settings.KHAGANAT_LOGS_MIN_DAYS - 1) return (now, start_date, end_date) def _switch_hidden(request, obj, pk): e = get_object_or_404(obj, pk=pk) e.hidden = not e.hidden e.save() next_page = request.GET.get("next", "/") if not is_link_legit(next_page): next_page = reverse("log_index") return redirect(next_page) @staff_member_required(login_url="login") def switch_log_source(request, pk): return _switch_hidden(request, LogSource, pk) @staff_member_required(login_url="login") def switch_log_entry(request, pk): return _switch_hidden(request, LogEntry, pk) def log_search_view(request): if request.method == "POST": form = SearchForm(request.POST) if form.is_valid(): date = form.cleaned_data["date"] return redirect( reverse( "log_day", kwargs={ "source": form.cleaned_data["source"], "year": date.year, "month": date.month, "day": date.day, }, ) ) raise Http404("No search parameters.") class LogEntriesView(generic.ListView): template_name = "chat/entries.html" context_object_name = "entries" filter_nsfw = False def is_nsfw(self): for e in self.get_queryset(): for tag in settings.KHAGANAT_NSFW_TAGS: if tag.lower() in e.content.lower(): return True return False def dispatch(self, request, *args, **kwargs): if self.is_nsfw(): if not nsfw.is_nsfw_allowed(request): self.filter_nsfw = True else: nsfw.alert(request, request.get_full_path()) return super().dispatch(request, *args, **kwargs) def get_date(self): """Return the date object corresponding to the URL parameters or None if missing. """ has_date = all( [ self.kwargs.get("year") is not None, self.kwargs.get("month") is not None, self.kwargs.get("day") is not None, ] ) if not has_date: return None return datetime.date( self.kwargs["year"], self.kwargs["month"], self.kwargs["day"] ) def get_dates(self, source): """Return a list if available dates for the current source.""" _, start_date, end_date = _get_dates() if source is None: return [] nb_max = settings.KHAGANAT_LOGS_MAX_DAYS nb_max -= settings.KHAGANAT_LOGS_MIN_DAYS lst = LogEntry.objects.filter(source=source) if not self.request.user.is_staff: lst = lst.filter(hidden=False, created__range=(start_date, end_date)) lst = ( lst.annotate(date=TruncDate("created")) .values("date") .annotate(nb=Count("date")) .order_by("-date")[:nb_max] ) return [o["date"] for o in lst] def get_source(self): """Return the current source.""" if self.kwargs.get("source") is None: return None return LogSource.objects.get(slug=self.kwargs["source"]) def get_sources(self): """Return available sources.""" now, start_date, end_date = _get_dates() qs = LogEntry.objects.all() if not self.request.user.is_staff: qs = qs.filter( hidden=False, source__hidden=False, created__range=(start_date, end_date), ) qs = qs.values( "source", "source__name", "source__slug", "source__id", "source__hidden" ).annotate(nb=Count("id")) out = [] for src in qs: dts = self.get_dates(src["source"]) src["first_date"] = dts[0] if dts else None out.append(src) return out def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["form"] = SearchForm() context["sources"] = self.get_sources() context["current_source"] = self.get_source() context["dates"] = self.get_dates(context["current_source"]) context["current_date"] = self.get_date() context["filter_nsfw"] = self.filter_nsfw context["current_url"] = self.request.get_full_path() return context def get_queryset(self): """Return the entries to be displayed.""" dt = self.get_date() if dt is None: return [] is_staff = self.request.user.is_staff now = datetime.date.today() out_of_bounds = any( ( (now - dt).days > settings.KHAGANAT_LOGS_MAX_DAYS, (now - dt).days < settings.KHAGANAT_LOGS_MIN_DAYS, ) ) if out_of_bounds and not is_staff: return LogEntry.objects.none() src = self.get_source() if src is None: return LogEntry.objects.none() if src.hidden and not is_staff: return LogEntry.objects.none() qs = ( LogEntry.objects.filter(source=src, created__year=dt.year) .filter(created__month=dt.month) .filter(created__day=dt.day) ) if not is_staff: qs = qs.filter(hidden=False) return qs.order_by("created")