##// END OF EJS Templates
Corrected mistakes
neko259 -
r1497:d75e94e0 default
parent child Browse files
Show More
@@ -1,145 +1,145 b''
1 1 """
2 2 This module contains helper functions and helper classes.
3 3 """
4 4 import hashlib
5 5 from random import random
6 6 import time
7 7 import hmac
8 8
9 9 from django.core.cache import cache
10 10 from django.db.models import Model
11 11 from django import forms
12 12 from django.template.defaultfilters import filesizeformat
13 13 from django.utils import timezone
14 14 from django.utils.translation import ugettext_lazy as _
15 15 import magic
16 from portage import os
16 import os
17 17
18 18 import boards
19 19 from boards.settings import get_bool
20 20 from neboard import settings
21 21
22 22 CACHE_KEY_DELIMITER = '_'
23 23
24 24 HTTP_FORWARDED = 'HTTP_X_FORWARDED_FOR'
25 25 META_REMOTE_ADDR = 'REMOTE_ADDR'
26 26
27 27 SETTING_MESSAGES = 'Messages'
28 28 SETTING_ANON_MODE = 'AnonymousMode'
29 29
30 30 ANON_IP = '127.0.0.1'
31 31
32 32 UPLOAD_DIRS ={
33 33 'PostImage': 'images/',
34 34 'Attachment': 'files/',
35 35 }
36 36 FILE_EXTENSION_DELIMITER = '.'
37 37
38 38
39 39 def is_anonymous_mode():
40 40 return get_bool(SETTING_MESSAGES, SETTING_ANON_MODE)
41 41
42 42
43 43 def get_client_ip(request):
44 44 if is_anonymous_mode():
45 45 ip = ANON_IP
46 46 else:
47 47 x_forwarded_for = request.META.get(HTTP_FORWARDED)
48 48 if x_forwarded_for:
49 49 ip = x_forwarded_for.split(',')[-1].strip()
50 50 else:
51 51 ip = request.META.get(META_REMOTE_ADDR)
52 52 return ip
53 53
54 54
55 55 # TODO The output format is not epoch because it includes microseconds
56 56 def datetime_to_epoch(datetime):
57 57 return int(time.mktime(timezone.localtime(
58 58 datetime,timezone.get_current_timezone()).timetuple())
59 59 * 1000000 + datetime.microsecond)
60 60
61 61
62 62 def get_websocket_token(user_id='', timestamp=''):
63 63 """
64 64 Create token to validate information provided by new connection.
65 65 """
66 66
67 67 sign = hmac.new(settings.CENTRIFUGE_PROJECT_SECRET.encode())
68 68 sign.update(settings.CENTRIFUGE_PROJECT_ID.encode())
69 69 sign.update(user_id.encode())
70 70 sign.update(timestamp.encode())
71 71 token = sign.hexdigest()
72 72
73 73 return token
74 74
75 75
76 76 # TODO Test this carefully
77 77 def cached_result(key_method=None):
78 78 """
79 79 Caches method result in the Django's cache system, persisted by object name,
80 80 object name, model id if object is a Django model, args and kwargs if any.
81 81 """
82 82 def _cached_result(function):
83 83 def inner_func(obj, *args, **kwargs):
84 84 cache_key_params = [obj.__class__.__name__, function.__name__]
85 85
86 86 cache_key_params += args
87 87 for key, value in kwargs:
88 88 cache_key_params.append(key + ':' + value)
89 89
90 90 if isinstance(obj, Model):
91 91 cache_key_params.append(str(obj.id))
92 92
93 93 if key_method is not None:
94 94 cache_key_params += [str(arg) for arg in key_method(obj)]
95 95
96 96 cache_key = CACHE_KEY_DELIMITER.join(cache_key_params)
97 97
98 98 persisted_result = cache.get(cache_key)
99 99 if persisted_result is not None:
100 100 result = persisted_result
101 101 else:
102 102 result = function(obj, *args, **kwargs)
103 103 if result is not None:
104 104 cache.set(cache_key, result)
105 105
106 106 return result
107 107
108 108 return inner_func
109 109 return _cached_result
110 110
111 111
112 112 def get_file_hash(file) -> str:
113 113 md5 = hashlib.md5()
114 114 for chunk in file.chunks():
115 115 md5.update(chunk)
116 116 return md5.hexdigest()
117 117
118 118
119 119 def validate_file_size(size: int):
120 120 max_size = boards.settings.get_int('Forms', 'MaxFileSize')
121 121 if size > max_size:
122 122 raise forms.ValidationError(
123 123 _('File must be less than %s but is %s.')
124 124 % (filesizeformat(max_size), filesizeformat(size)))
125 125
126 126
127 127 def get_extension(filename):
128 128 return filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
129 129
130 130
131 131 def get_upload_filename(model_instance, old_filename):
132 132 # TODO Use something other than random number in file name
133 133 extension = get_extension(old_filename)
134 134 new_name = '{}{}.{}'.format(
135 135 str(int(time.mktime(time.gmtime()))),
136 136 str(int(random() * 1000)),
137 137 extension)
138 138
139 139 directory = UPLOAD_DIRS[type(model_instance).__name__]
140 140
141 141 return os.path.join(directory, new_name)
142 142
143 143
144 144 def get_file_mimetype(file) -> str:
145 145 return magic.from_buffer(file.chunks().__next__(), mime=True).decode()
@@ -1,169 +1,168 b''
1 from dbus.decorators import method
2 1 from django.core.urlresolvers import reverse
3 2 from django.core.files import File
4 3 from django.core.files.temp import NamedTemporaryFile
5 4 from django.core.paginator import EmptyPage
6 5 from django.db import transaction
7 6 from django.http import Http404
8 7 from django.shortcuts import render, redirect
9 8 import requests
10 9 from django.utils.decorators import method_decorator
11 10 from django.views.decorators.csrf import csrf_protect
12 11
13 12 from boards import utils, settings
14 13 from boards.abstracts.paginator import get_paginator
15 14 from boards.abstracts.settingsmanager import get_settings_manager
16 15 from boards.forms import ThreadForm, PlainErrorList
17 16 from boards.models import Post, Thread, Ban, Tag, PostImage, Banner
18 17 from boards.views.banned import BannedView
19 18 from boards.views.base import BaseBoardView, CONTEXT_FORM
20 19 from boards.views.posting_mixin import PostMixin
21 20 from boards.views.mixins import FileUploadMixin, PaginatedMixin
22 21
23 22 FORM_TAGS = 'tags'
24 23 FORM_TEXT = 'text'
25 24 FORM_TITLE = 'title'
26 25 FORM_IMAGE = 'image'
27 26 FORM_THREADS = 'threads'
28 27
29 28 TAG_DELIMITER = ' '
30 29
31 30 PARAMETER_CURRENT_PAGE = 'current_page'
32 31 PARAMETER_PAGINATOR = 'paginator'
33 32 PARAMETER_THREADS = 'threads'
34 33 PARAMETER_BANNERS = 'banners'
35 34 PARAMETER_ADDITIONAL = 'additional_params'
36 35 PARAMETER_MAX_FILE_SIZE = 'max_file_size'
37 36 PARAMETER_RSS_URL = 'rss_url'
38 37
39 38 TEMPLATE = 'boards/all_threads.html'
40 39 DEFAULT_PAGE = 1
41 40
42 41
43 42 class AllThreadsView(PostMixin, FileUploadMixin, BaseBoardView, PaginatedMixin):
44 43
45 44 def __init__(self):
46 45 self.settings_manager = None
47 46 super(AllThreadsView, self).__init__()
48 47
49 48 @method_decorator(csrf_protect)
50 49 def get(self, request, form: ThreadForm=None):
51 50 page = request.GET.get('page', DEFAULT_PAGE)
52 51
53 52 params = self.get_context_data(request=request)
54 53
55 54 if not form:
56 55 form = ThreadForm(error_class=PlainErrorList)
57 56
58 57 self.settings_manager = get_settings_manager(request)
59 58
60 59 threads = self.get_threads()
61 60
62 61 order = request.GET.get('order', 'bump')
63 62 if order == 'bump':
64 63 threads = threads.order_by('-bump_time')
65 64 else:
66 65 threads = threads.filter(multi_replies__opening=True).order_by('-multi_replies__pub_time')
67 66 filter = request.GET.get('filter')
68 67 if filter == 'fav_tags':
69 68 fav_tags = self.settings_manager.get_fav_tags()
70 69 if len(fav_tags) > 0:
71 70 threads = threads.filter(tags__in=fav_tags)
72 71 threads = threads.distinct()
73 72
74 73 paginator = get_paginator(threads,
75 74 settings.get_int('View', 'ThreadsPerPage'))
76 75 paginator.current_page = int(page)
77 76
78 77 try:
79 78 threads = paginator.page(page).object_list
80 79 except EmptyPage:
81 80 raise Http404()
82 81
83 82 params[PARAMETER_THREADS] = threads
84 83 params[CONTEXT_FORM] = form
85 84 params[PARAMETER_BANNERS] = Banner.objects.order_by('-id').all()
86 85 params[PARAMETER_MAX_FILE_SIZE] = self.get_max_upload_size()
87 86 params[PARAMETER_RSS_URL] = self.get_rss_url()
88 87
89 88 paginator.set_url(self.get_reverse_url(), request.GET.dict())
90 89 self.get_page_context(paginator, params, page)
91 90
92 91 return render(request, TEMPLATE, params)
93 92
94 93 @method_decorator(csrf_protect)
95 94 def post(self, request):
96 95 form = ThreadForm(request.POST, request.FILES,
97 96 error_class=PlainErrorList)
98 97 form.session = request.session
99 98
100 99 if form.is_valid():
101 100 return self.create_thread(request, form)
102 101 if form.need_to_ban:
103 102 # Ban user because he is suspected to be a bot
104 103 self._ban_current_user(request)
105 104
106 105 return self.get(request, form)
107 106
108 107 def get_page_context(self, paginator, params, page):
109 108 """
110 109 Get pagination context variables
111 110 """
112 111
113 112 params[PARAMETER_PAGINATOR] = paginator
114 113 current_page = paginator.page(int(page))
115 114 params[PARAMETER_CURRENT_PAGE] = current_page
116 115 self.set_page_urls(paginator, params)
117 116
118 117 def get_reverse_url(self):
119 118 return reverse('index')
120 119
121 120 @transaction.atomic
122 121 def create_thread(self, request, form: ThreadForm, html_response=True):
123 122 """
124 123 Creates a new thread with an opening post.
125 124 """
126 125
127 126 ip = utils.get_client_ip(request)
128 127 is_banned = Ban.objects.filter(ip=ip).exists()
129 128
130 129 if is_banned:
131 130 if html_response:
132 131 return redirect(BannedView().as_view())
133 132 else:
134 133 return
135 134
136 135 data = form.cleaned_data
137 136
138 137 title = form.get_title()
139 138 text = data[FORM_TEXT]
140 139 file = form.get_file()
141 140 threads = data[FORM_THREADS]
142 141
143 142 text = self._remove_invalid_links(text)
144 143
145 144 tags = data[FORM_TAGS]
146 145 monochrome = form.is_monochrome()
147 146
148 147 post = Post.objects.create_post(title=title, text=text, file=file,
149 148 ip=ip, tags=tags, opening_posts=threads,
150 149 tripcode=form.get_tripcode(),
151 150 monochrome=monochrome)
152 151
153 152 # This is required to update the threads to which posts we have replied
154 153 # when creating this one
155 154 post.notify_clients()
156 155
157 156 if html_response:
158 157 return redirect(post.get_absolute_url())
159 158
160 159 def get_threads(self):
161 160 """
162 161 Gets list of threads that will be shown on a page.
163 162 """
164 163
165 164 return Thread.objects\
166 165 .exclude(tags__in=self.settings_manager.get_hidden_tags())
167 166
168 167 def get_rss_url(self):
169 168 return self.get_reverse_url() + 'rss/'
General Comments 0
You need to be logged in to leave comments. Login now