from django.core.files import File from django.core.files.temp import NamedTemporaryFile from django.core.paginator import EmptyPage from django.db import transaction from django.http import Http404 from django.shortcuts import render, redirect import requests from boards import utils, settings from boards.abstracts.paginator import get_paginator from boards.abstracts.settingsmanager import get_settings_manager from boards.forms import ThreadForm, PlainErrorList from boards.models import Post, Thread, Ban, Tag, PostImage from boards.views.banned import BannedView from boards.views.base import BaseBoardView, CONTEXT_FORM from boards.views.posting_mixin import PostMixin FORM_TAGS = 'tags' FORM_TEXT = 'text' FORM_TITLE = 'title' FORM_IMAGE = 'image' TAG_DELIMITER = ' ' PARAMETER_CURRENT_PAGE = 'current_page' PARAMETER_PAGINATOR = 'paginator' PARAMETER_THREADS = 'threads' TEMPLATE = 'boards/posting_general.html' DEFAULT_PAGE = 1 class AllThreadsView(PostMixin, BaseBoardView): def __init__(self): self.settings_manager = None super(AllThreadsView, self).__init__() def get(self, request, page=DEFAULT_PAGE, form: ThreadForm=None): params = self.get_context_data(request=request) if not form: form = ThreadForm(error_class=PlainErrorList) self.settings_manager = get_settings_manager(request) paginator = get_paginator(self.get_threads(), settings.THREADS_PER_PAGE) paginator.current_page = int(page) try: threads = paginator.page(page).object_list except EmptyPage: raise Http404() params[PARAMETER_THREADS] = threads params[CONTEXT_FORM] = form self._get_page_context(paginator, params, page) return render(request, TEMPLATE, params) def post(self, request, page=DEFAULT_PAGE): form = ThreadForm(request.POST, request.FILES, error_class=PlainErrorList) form.session = request.session if form.is_valid(): return self.create_thread(request, form) if form.need_to_ban: # Ban user because he is suspected to be a bot self._ban_current_user(request) return self.get(request, page, form) def _get_page_context(self, paginator, params, page): """ Get pagination context variables """ params[PARAMETER_PAGINATOR] = paginator params[PARAMETER_CURRENT_PAGE] = paginator.page(int(page)) @staticmethod def parse_tags_string(tag_strings): """ Parses tag list string and returns tag object list. """ tags = [] if tag_strings: tag_strings = tag_strings.split(TAG_DELIMITER) for tag_name in tag_strings: tag_name = tag_name.strip().lower() if len(tag_name) > 0: tag, created = Tag.objects.get_or_create(name=tag_name) tags.append(tag) return tags @transaction.atomic def create_thread(self, request, form: ThreadForm, html_response=True): """ Creates a new thread with an opening post. """ ip = utils.get_client_ip(request) is_banned = Ban.objects.filter(ip=ip).exists() if is_banned: if html_response: return redirect(BannedView().as_view()) else: return data = form.cleaned_data title = data[FORM_TITLE] text = data[FORM_TEXT] image = form.get_image() text = self._remove_invalid_links(text) tag_strings = data[FORM_TAGS] tags = self.parse_tags_string(tag_strings) post = Post.objects.create_post(title=title, text=text, image=image, ip=ip, tags=tags) # This is required to update the threads to which posts we have replied # when creating this one post.send_to_websocket(request) if html_response: return redirect(post.get_url()) def get_threads(self): """ Gets list of threads that will be shown on a page. """ return Thread.objects.order_by('-bump_time')\ .exclude(tags__in=self.settings_manager.get_hidden_tags())