Files
interchan/board/views.py
Alek Ratzloff 356196db26 Fix small bug with ban calculation
If a user had a permaban, there would be a comparison error between the
current time and the expiration time (none).

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
2022-06-26 20:27:42 -07:00

250 lines
7.8 KiB
Python

from typing import Any, Dict
from django.conf import settings
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ImproperlyConfigured
from django.db.models import Q
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.views.generic.base import TemplateView
from django.views.generic import edit
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from board.forms import BanForm, PostForm, ReplyForm, ReportForm
from board.models import Ban, BanTemplate, Board, Post, Report
from board.utils import *
__all__ = (
"BanCreateView",
"BanSuccessView",
"BannedView",
"BoardView",
"PostView",
"PostSuccessView",
"ReplyCreateView",
"ReportView",
"ReportSuccessView",
)
class BannedView(TemplateView):
template_name = "board/banned.html"
def get_context_data(self, **kwargs):
context = super(TemplateView, self).get_context_data(**kwargs)
ip = get_client_ip(self.request)
bans = get_ip_bans(ip)
now = timezone.now()
active_bans = [ban for ban in bans if not ban.expires or ban.expires > now]
context["bans"] = bans
context["active_bans"] = active_bans
context["ip"] = ip
return context
class CreateView(edit.CreateView):
"""
Helper class that sets a few variables for posts and check against bans.
This should not be used by itself.
This class sets the following variables on GET and POST:
* self.board
"""
def get_form_kwargs(self):
kwargs = super(CreateView, self).get_form_kwargs()
kwargs["board"] = self.board
kwargs["ip"] = get_client_ip(self.request)
return kwargs
def dispatch(self, request, *args, **kwargs):
# Set the board on this object
self.board = get_object_or_404(Board, url=kwargs["url"])
# Check for bans
ip = get_client_ip(request)
if request.method == "POST" and is_banned(ip, self.board):
return HttpResponseRedirect(reverse("board:banned"))
else:
return super(CreateView, self).dispatch(request, *args, **kwargs)
class BoardView(CreateView):
model = Post
form_class = PostForm
slug_field = "url"
slug_url_kwarg = "url"
template_name = "board/board_detail.html"
def get(self, request, *args, **kwargs):
# If the page isn't set, then redirect to the /page/1 url
if "page" not in kwargs:
return HttpResponseRedirect(
reverse("board:board_detail", kwargs={"url": kwargs["url"], "page": 1})
)
return super(BoardView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
page = self.kwargs["page"]
if page not in range(1, self.board.max_pages + 1):
raise Http404()
threads_per_page = self.board.threads_per_page
start = (page - 1) * threads_per_page
end = start + threads_per_page
thread_count = self.board.threads.count()
last_page = (thread_count // threads_per_page) + 1
kwargs["board"] = self.board
kwargs["threads"] = self.board.threads.order_by("-last_bump")[start:end]
kwargs["current_page"] = page
kwargs["pages"] = range(1, last_page + 1)
kwargs["last_page"] = last_page
kwargs["max_upload_size"] = settings.MAX_UPLOAD_SIZE
return super(BoardView, self).get_context_data(**kwargs)
class ReplyCreateView(CreateView):
model = Post
form_class = ReplyForm
slug_field = "url"
slug_url_kwarg = "url"
template_name = "board/reply_create_view.html"
success_url = reverse_lazy("board:post_success")
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["board"] = self.board
post_id = self.kwargs["id"]
context["post"] = get_object_or_404(Post, id=post_id)
context["max_upload_size"] = settings.MAX_UPLOAD_SIZE
print(context["board"])
return context
def get_form_kwargs(self):
kwargs = super(ReplyCreateView, self).get_form_kwargs()
post_id = self.kwargs["id"]
post = get_object_or_404(Post, id=post_id)
kwargs["op"] = post
kwargs["reply"] = post
return kwargs
class PostView(CreateView):
model = Post
form_class = ReplyForm
slug_field = "url"
slug_url_kwarg = "url"
template_name = "board/post_detail.html"
def get_context_data(self, **kwargs):
kwargs["board"] = self.board
post_id = self.kwargs["id"]
kwargs["post"] = get_object_or_404(Post, id=post_id)
kwargs["max_upload_size"] = settings.MAX_UPLOAD_SIZE
return super(PostView, self).get_context_data(**kwargs)
def get_form_kwargs(self):
kwargs = super(PostView, self).get_form_kwargs()
post_id = self.kwargs["id"]
post = get_object_or_404(Post, id=post_id)
kwargs["op"] = post
kwargs["reply"] = post
return kwargs
class PostSuccessView(TemplateView):
template_name = "board/post_success.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["window_timeout"] = settings.POST_WINDOW_CLOSE_TIMEOUT
return context
class ReportView(CreateView):
model = Report
form_class = ReportForm
success_url = reverse_lazy("board:report_success")
@property
def board_url(self) -> str:
return self.kwargs["url"]
@property
def post_id(self) -> int:
return self.kwargs["id"]
def get_form_kwargs(self):
kwargs = super(ReportView, self).get_form_kwargs()
post_id = self.kwargs["id"]
post = get_object_or_404(Post, id=post_id)
kwargs["op"] = post
return kwargs
class ReportSuccessView(TemplateView):
template_name = "board/report_success.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["window_timeout"] = settings.REPORT_WINDOW_CLOSE_TIMEOUT
return context
class BanCreateView(PermissionRequiredMixin, edit.CreateView):
model = Ban
form_class = BanForm
permission_required = "ban.create"
success_url = reverse_lazy("board:ban_success")
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
context = super().get_context_data(**kwargs)
context["board"] = self.board
context["post"] = self.post_obj
ip = self.post_obj.ip
now = timezone.now()
bans = [
ban
for ban in get_ip_bans(ip)
if ban.board == self.board or ban.board is None
]
context["previous_bans"] = [
ban for ban in bans if ban.expires and ban.expires < now
]
context["current_bans"] = [
ban for ban in bans if not ban.expires or ban.expires > now
]
context["templates"] = BanTemplate.objects.filter(
Q(board=self.board) | Q(board=None)
)
return context
def get_form_kwargs(self) -> Dict[str, Any]:
kwargs = super(edit.CreateView, self).get_form_kwargs()
post_id = self.kwargs["id"]
post = get_object_or_404(Post, id=post_id)
kwargs["op"] = post
return kwargs
def dispatch(self, request, *args, **kwargs):
self.board = get_object_or_404(Board, url=kwargs["url"])
self.post_obj = get_object_or_404(Post, pk=kwargs["id"])
return super().dispatch(request, *args, **kwargs)
class BanSuccessView(PermissionRequiredMixin, TemplateView):
permission_required = "ban.create"
template_name = "board/ban_success.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["window_timeout"] = settings.BAN_WINDOW_CLOSE_TIMEOUT
return context