__init__.py
356 lines
| 9.5 KiB
| text/x-python
|
PythonLexer
neko259
|
r486 | from datetime import datetime, timedelta | ||
neko259
|
r491 | |||
neko259
|
r486 | from django.db.models import Count | ||
neko259
|
r443 | __author__ = 'neko259' | ||
import hashlib | ||||
import string | ||||
import re | ||||
from django.core import serializers | ||||
from django.core.urlresolvers import reverse | ||||
neko259
|
r542 | from django.http import HttpResponseRedirect | ||
neko259
|
r443 | from django.http.response import HttpResponse | ||
from django.template import RequestContext | ||||
from django.shortcuts import render, redirect, get_object_or_404 | ||||
from django.utils import timezone | ||||
from django.db import transaction | ||||
from django.views.decorators.cache import cache_page | ||||
from django.views.i18n import javascript_catalog | ||||
import boards | ||||
from boards import utils | ||||
neko259
|
r542 | from boards.forms import SettingsForm, PlainErrorList, \ | ||
LoginForm, ModeratorSettingsForm | ||||
from boards.models import Post, Tag, Ban, User | ||||
neko259
|
r443 | from boards.models.post import SETTING_MODERATE, REGEX_REPLY | ||
from boards.models.user import RANK_USER | ||||
from boards import authors | ||||
import neboard | ||||
neko259
|
r542 | import all_threads | ||
neko259
|
r443 | |||
BAN_REASON_SPAM = 'Autoban: spam bot' | ||||
neko259
|
r493 | DEFAULT_PAGE = 1 | ||
neko259
|
r443 | |||
neko259
|
r493 | |||
neko259
|
r443 | def login(request): | ||
"""Log in with user id""" | ||||
context = _init_default_context(request) | ||||
if request.method == 'POST': | ||||
form = LoginForm(request.POST, request.FILES, | ||||
error_class=PlainErrorList) | ||||
form.session = request.session | ||||
if form.is_valid(): | ||||
user = User.objects.get(user_id=form.cleaned_data['user_id']) | ||||
request.session['user_id'] = user.id | ||||
neko259
|
r542 | return redirect('index') | ||
neko259
|
r443 | |||
else: | ||||
form = LoginForm() | ||||
context['form'] = form | ||||
return render(request, 'boards/login.html', context) | ||||
def settings(request): | ||||
"""User's settings""" | ||||
context = _init_default_context(request) | ||||
user = _get_user(request) | ||||
is_moderator = user.is_moderator() | ||||
if request.method == 'POST': | ||||
with transaction.atomic(): | ||||
if is_moderator: | ||||
form = ModeratorSettingsForm(request.POST, | ||||
error_class=PlainErrorList) | ||||
else: | ||||
form = SettingsForm(request.POST, error_class=PlainErrorList) | ||||
if form.is_valid(): | ||||
selected_theme = form.cleaned_data['theme'] | ||||
user.save_setting('theme', selected_theme) | ||||
if is_moderator: | ||||
moderate = form.cleaned_data['moderate'] | ||||
user.save_setting(SETTING_MODERATE, moderate) | ||||
return redirect(settings) | ||||
else: | ||||
selected_theme = _get_theme(request) | ||||
if is_moderator: | ||||
form = ModeratorSettingsForm(initial={'theme': selected_theme, | ||||
'moderate': context['moderator']}, | ||||
error_class=PlainErrorList) | ||||
else: | ||||
form = SettingsForm(initial={'theme': selected_theme}, | ||||
error_class=PlainErrorList) | ||||
context['form'] = form | ||||
return render(request, 'boards/settings.html', context) | ||||
def all_tags(request): | ||||
"""All tags list""" | ||||
context = _init_default_context(request) | ||||
context['all_tags'] = Tag.objects.get_not_empty_tags() | ||||
return render(request, 'boards/tags.html', context) | ||||
def jump_to_post(request, post_id): | ||||
"""Determine thread in which the requested post is and open it's page""" | ||||
post = get_object_or_404(Post, id=post_id) | ||||
if not post.thread: | ||||
neko259
|
r542 | return redirect('thread', post_id=post.id) | ||
neko259
|
r443 | else: | ||
neko259
|
r542 | return redirect(reverse('thread', kwargs={'post_id': post.thread.id}) | ||
neko259
|
r443 | + '#' + str(post.id)) | ||
def authors(request): | ||||
"""Show authors list""" | ||||
context = _init_default_context(request) | ||||
context['authors'] = boards.authors.authors | ||||
return render(request, 'boards/authors.html', context) | ||||
@transaction.atomic | ||||
def delete(request, post_id): | ||||
"""Delete post""" | ||||
user = _get_user(request) | ||||
post = get_object_or_404(Post, id=post_id) | ||||
if user.is_moderator(): | ||||
# TODO Show confirmation page before deletion | ||||
Post.objects.delete_post(post) | ||||
if not post.thread: | ||||
return _redirect_to_next(request) | ||||
else: | ||||
neko259
|
r542 | return redirect('thread', post_id=post.thread.id) | ||
neko259
|
r443 | |||
@transaction.atomic | ||||
def ban(request, post_id): | ||||
"""Ban user""" | ||||
user = _get_user(request) | ||||
post = get_object_or_404(Post, id=post_id) | ||||
if user.is_moderator(): | ||||
# TODO Show confirmation page before ban | ||||
ban, created = Ban.objects.get_or_create(ip=post.poster_ip) | ||||
if created: | ||||
ban.reason = 'Banned for post ' + str(post_id) | ||||
ban.save() | ||||
return _redirect_to_next(request) | ||||
def page_404(request): | ||||
"""Show page 404 (not found error)""" | ||||
context = _init_default_context(request) | ||||
return render(request, 'boards/404.html', context) | ||||
@transaction.atomic | ||||
def tag_subscribe(request, tag_name): | ||||
"""Add tag to favorites""" | ||||
user = _get_user(request) | ||||
tag = get_object_or_404(Tag, name=tag_name) | ||||
if not tag in user.fav_tags.all(): | ||||
user.add_tag(tag) | ||||
return _redirect_to_next(request) | ||||
@transaction.atomic | ||||
def tag_unsubscribe(request, tag_name): | ||||
"""Remove tag from favorites""" | ||||
user = _get_user(request) | ||||
tag = get_object_or_404(Tag, name=tag_name) | ||||
if tag in user.fav_tags.all(): | ||||
user.remove_tag(tag) | ||||
return _redirect_to_next(request) | ||||
def static_page(request, name): | ||||
"""Show a static page that needs only tags list and a CSS""" | ||||
context = _init_default_context(request) | ||||
return render(request, 'boards/staticpages/' + name + '.html', context) | ||||
def api_get_post(request, post_id): | ||||
""" | ||||
Get the JSON of a post. This can be | ||||
used as and API for external clients. | ||||
""" | ||||
post = get_object_or_404(Post, id=post_id) | ||||
json = serializers.serialize("json", [post], fields=( | ||||
"pub_time", "_text_rendered", "title", "text", "image", | ||||
"image_width", "image_height", "replies", "tags" | ||||
)) | ||||
return HttpResponse(content=json) | ||||
@cache_page(86400) | ||||
def cached_js_catalog(request, domain='djangojs', packages=None): | ||||
return javascript_catalog(request, domain, packages) | ||||
neko259
|
r542 | # TODO This method is deprecated and should be removed after switching to | ||
# class-based view | ||||
neko259
|
r443 | def _get_theme(request, user=None): | ||
"""Get user's CSS theme""" | ||||
if not user: | ||||
user = _get_user(request) | ||||
theme = user.get_setting('theme') | ||||
if not theme: | ||||
theme = neboard.settings.DEFAULT_THEME | ||||
return theme | ||||
neko259
|
r542 | # TODO This method is deprecated and should be removed after switching to | ||
# class-based view | ||||
neko259
|
r443 | def _init_default_context(request): | ||
"""Create context with default values that are used in most views""" | ||||
context = RequestContext(request) | ||||
user = _get_user(request) | ||||
context['user'] = user | ||||
context['tags'] = user.get_sorted_fav_tags() | ||||
context['posts_per_day'] = float(Post.objects.get_posts_per_day()) | ||||
theme = _get_theme(request, user) | ||||
context['theme'] = theme | ||||
context['theme_css'] = 'css/' + theme + '/base_page.css' | ||||
# This shows the moderator panel | ||||
moderate = user.get_setting(SETTING_MODERATE) | ||||
if moderate == 'True': | ||||
context['moderator'] = user.is_moderator() | ||||
else: | ||||
context['moderator'] = False | ||||
return context | ||||
neko259
|
r542 | # TODO This method is deprecated and should be removed after switching to | ||
# class-based view | ||||
neko259
|
r443 | def _get_user(request): | ||
""" | ||||
Get current user from the session. If the user does not exist, create | ||||
a new one. | ||||
""" | ||||
session = request.session | ||||
if not 'user_id' in session: | ||||
request.session.save() | ||||
md5 = hashlib.md5() | ||||
md5.update(session.session_key) | ||||
new_id = md5.hexdigest() | ||||
neko259
|
r485 | while User.objects.filter(user_id=new_id).exists(): | ||
md5.update(str(timezone.now())) | ||||
new_id = md5.hexdigest() | ||||
neko259
|
r443 | time_now = timezone.now() | ||
user = User.objects.create(user_id=new_id, rank=RANK_USER, | ||||
registration_time=time_now) | ||||
neko259
|
r542 | # TODO This is just a test. This method should be removed | ||
# _delete_old_users() | ||||
neko259
|
r486 | |||
neko259
|
r443 | session['user_id'] = user.id | ||
else: | ||||
user = User.objects.get(id=session['user_id']) | ||||
return user | ||||
def _redirect_to_next(request): | ||||
""" | ||||
If a 'next' parameter was specified, redirect to the next page. This is | ||||
used when the user is required to return to some page after the current | ||||
view has finished its work. | ||||
""" | ||||
if 'next' in request.GET: | ||||
next_page = request.GET['next'] | ||||
return HttpResponseRedirect(next_page) | ||||
else: | ||||
neko259
|
r542 | return redirect('index') | ||
neko259
|
r443 | |||
@transaction.atomic | ||||
def _ban_current_user(request): | ||||
"""Add current user to the IP ban list""" | ||||
ip = utils.get_client_ip(request) | ||||
ban, created = Ban.objects.get_or_create(ip=ip) | ||||
if created: | ||||
ban.can_read = False | ||||
ban.reason = BAN_REASON_SPAM | ||||
ban.save() | ||||
def _remove_invalid_links(text): | ||||
""" | ||||
Replace invalid links in posts so that they won't be parsed. | ||||
Invalid links are links to non-existent posts | ||||
""" | ||||
for reply_number in re.finditer(REGEX_REPLY, text): | ||||
post_id = reply_number.group(1) | ||||
post = Post.objects.filter(id=post_id) | ||||
if not post.exists(): | ||||
text = string.replace(text, '>>' + post_id, post_id) | ||||
return text | ||||
def _get_template_thread(thread_to_show): | ||||
"""Get template values for thread""" | ||||
last_replies = thread_to_show.get_last_replies() | ||||
skipped_replies_count = thread_to_show.get_replies().count() \ | ||||
- len(last_replies) - 1 | ||||
return { | ||||
'thread': thread_to_show, | ||||
'op': thread_to_show.get_replies()[0], | ||||
'bumpable': thread_to_show.can_bump(), | ||||
'last_replies': last_replies, | ||||
'skipped_replies': skipped_replies_count, | ||||
} | ||||