##// END OF EJS Templates
Unify thread and post creation into one method inside post manager, that can be called from almost anywhere (one step closer to ajax thread creation)
neko259 -
r1997:be673d04 default
parent child Browse files
Show More
@@ -2,3 +2,4 b' import re'
2 2
3 3 FILE_DIRECTORY = 'files/'
4 4 REGEX_TAGS = re.compile(r'^[\w\s\d\']+$', re.UNICODE)
5 REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]') No newline at end of file
@@ -8,6 +8,7 b' from django.template.defaultfilters impo'
8 8 from django.template.loader import render_to_string
9 9 from django.urls import reverse
10 10
11 from boards.abstracts.constants import REGEX_REPLY
11 12 from boards.abstracts.tripcode import Tripcode
12 13 from boards.models import Attachment, KeyPair, GlobalId
13 14 from boards.models.attachment import FILE_TYPES_IMAGE
@@ -30,7 +31,6 b" BAN_REASON_AUTO = 'Auto'"
30 31
31 32 TITLE_MAX_LENGTH = 200
32 33
33 REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]')
34 34 REGEX_GLOBAL_REPLY = re.compile(r'\[post\](\w+)::([^:]+)::(\d+)\[/post\]')
35 35 REGEX_URL = re.compile(r'https?\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?')
36 36 REGEX_NOTIFICATION = re.compile(r'\[user\](\w+)\[/user\]')
@@ -1,16 +1,18 b''
1 1 import logging
2 import re
2 3 from datetime import datetime, timedelta, date
3 4 from datetime import time as dtime
4 5
5 6 from django.core.exceptions import PermissionDenied
6 7 from django.db import models, transaction
7 8 from django.dispatch import Signal
9 from django.shortcuts import redirect
8 10 from django.utils import timezone
9 11
10 12 import boards
11 13 from boards import utils
12 14 from boards.abstracts.exceptions import ArchiveException
13 from boards.abstracts.constants import REGEX_TAGS
15 from boards.abstracts.constants import REGEX_TAGS, REGEX_REPLY
14 16 from boards.mdx_neboard import Parser
15 17 from boards.models import Attachment
16 18 from boards.models.attachment import StickerPack, AttachmentSticker
@@ -24,6 +26,11 b" NO_IP = '0.0.0.0'"
24 26
25 27 post_import_deps = Signal()
26 28
29 FORM_TEXT = 'text'
30 FORM_TAGS = 'tags'
31
32 REFLINK_PREFIX = '>>'
33
27 34
28 35 class PostManager(models.Manager):
29 36 @transaction.atomic
@@ -190,6 +197,48 b' class PostManager(models.Manager):'
190 197 thread.tags.clear()
191 198 list(map(thread.tags.add, tags))
192 199
200 def create_from_form(self, request, form, opening_post, html_response=True):
201 ip = utils.get_client_ip(request)
202
203 data = form.cleaned_data
204
205 title = form.get_title()
206 text = data[FORM_TEXT]
207 files = form.get_files()
208 file_urls = form.get_file_urls()
209 images = form.get_images()
210
211 text = self._remove_invalid_links(text)
212
213 if opening_post:
214 post_thread = opening_post.get_thread()
215 monochrome = False
216 stickerpack = False
217 tags = []
218 else:
219 tags = data[FORM_TAGS]
220 monochrome = form.is_monochrome()
221 stickerpack = form.is_stickerpack()
222 post_thread = None
223
224 post = self.create_post(title=title, text=text, files=files,
225 thread=post_thread, ip=ip,
226 tripcode=form.get_tripcode(),
227 images=images, file_urls=file_urls,
228 monochrome=monochrome,
229 stickerpack=stickerpack, tags=tags)
230
231 if form.is_subscribe():
232 from boards.abstracts.settingsmanager import get_settings_manager
233 settings_manager = get_settings_manager(request)
234 settings_manager.add_or_read_fav_thread(
235 post_thread.get_opening_post())
236
237 if html_response:
238 return redirect(post.get_absolute_url())
239 else:
240 return post
241
193 242 def _add_file_to_post(self, file, post):
194 243 post.attachments.add(Attachment.objects.create_with_hash(file))
195 244
@@ -226,3 +275,17 b' class PostManager(models.Manager):'
226 275 name=post.get_title(), tripcode=post.tripcode)
227 276 if created:
228 277 logger.info('Created stickerpack {}'.format(stickerpack))
278
279 def _remove_invalid_links(self, text):
280 """
281 Replace invalid links in posts so that they won't be parsed.
282 Invalid links are links to non-existent posts
283 """
284
285 for reply_number in re.finditer(REGEX_REPLY, text):
286 post_id = reply_number.group(1)
287 post = self.filter(id=post_id)
288 if not post.exists():
289 text = text.replace(REFLINK_PREFIX + post_id, post_id)
290
291 return text
@@ -13,8 +13,8 b' from boards.mdx_neboard import get_parse'
13 13 from boards.models import Post, GlobalId, Attachment, Thread
14 14 from boards.models.attachment import StickerPack, AttachmentSticker
15 15 from boards.models.attachment.viewers import FILE_TYPES_IMAGE
16 from boards.models.post import REGEX_NOTIFICATION, REGEX_REPLY,\
17 REGEX_GLOBAL_REPLY
16 from boards.models.post import REGEX_NOTIFICATION, REGEX_GLOBAL_REPLY
17 from boards.abstracts.constants import REGEX_REPLY
18 18 from boards.models.post.manager import post_import_deps
19 19 from boards.models.user import Notification
20 20 from neboard.settings import MEDIA_ROOT
@@ -4,7 +4,7 b' from django.views.i18n import JavaScript'
4 4
5 5 from boards import views
6 6 from boards.rss import AllThreadsFeed, TagThreadsFeed, ThreadPostsFeed
7 from boards.views import api, tag_threads, all_threads, settings, feed, stickers
7 from boards.views import api, tag_threads, all_threads, settings, feed, stickers, thread, banned
8 8 from boards.views.authors import AuthorsView
9 9 from boards.views.landing import LandingView
10 10 from boards.views.notifications import NotificationView
@@ -1,22 +1,19 b''
1 1 from django.core.paginator import EmptyPage
2 from django.db import transaction
3 2 from django.http import Http404
4 3 from django.shortcuts import render, redirect
5 4 from django.urls import reverse
6 5 from django.utils.decorators import method_decorator
7 6 from django.views.decorators.csrf import csrf_protect
8 7
9 from boards import utils, settings
8 from boards import settings
10 9 from boards.abstracts.paginator import get_paginator
11 10 from boards.abstracts.settingsmanager import get_settings_manager, \
12 11 SETTING_ONLY_FAVORITES
13 12 from boards.forms import ThreadForm, PlainErrorList
14 from boards.models import Post, Thread, Ban
15 from boards.views.banned import BannedView
13 from boards.models import Post, Thread
16 14 from boards.views.base import BaseBoardView, CONTEXT_FORM
17 15 from boards.views.mixins import FileUploadMixin, PaginatedMixin, \
18 16 DispatcherMixin, PARAMETER_METHOD
19 from boards.views.posting_mixin import PostMixin
20 17
21 18 FORM_TAGS = 'tags'
22 19 FORM_TEXT = 'text'
@@ -37,10 +34,9 b" PARAMETER_MAX_FILES = 'max_files'"
37 34 TEMPLATE = 'boards/all_threads.html'
38 35 DEFAULT_PAGE = 1
39 36
40 FORM_TAGS = 'tags'
41 37
42
43 class AllThreadsView(PostMixin, FileUploadMixin, BaseBoardView, PaginatedMixin, DispatcherMixin):
38 class AllThreadsView(FileUploadMixin, BaseBoardView, PaginatedMixin,
39 DispatcherMixin):
44 40
45 41 tag_name = ''
46 42
@@ -103,7 +99,7 b' class AllThreadsView(PostMixin, FileUplo'
103 99 form.session = request.session
104 100
105 101 if form.is_valid():
106 return self.create_thread(request, form)
102 return Post.objects.create_from_form(request, form, None)
107 103 if form.need_to_ban:
108 104 # Ban user because he is suspected to be a bot
109 105 self._ban_current_user(request)
@@ -113,48 +109,6 b' class AllThreadsView(PostMixin, FileUplo'
113 109 def get_reverse_url(self):
114 110 return reverse('index')
115 111
116 @transaction.atomic
117 def create_thread(self, request, form: ThreadForm, html_response=True):
118 """
119 Creates a new thread with an opening post.
120 """
121
122 ip = utils.get_client_ip(request)
123 is_banned = Ban.objects.filter(ip=ip).exists()
124
125 if is_banned:
126 if html_response:
127 return redirect(BannedView().as_view())
128 else:
129 return
130
131 data = form.cleaned_data
132
133 title = form.get_title()
134 text = data[FORM_TEXT]
135 files = form.get_files()
136 file_urls = form.get_file_urls()
137 images = form.get_images()
138
139 text = self._remove_invalid_links(text)
140
141 tags = data[FORM_TAGS]
142 monochrome = form.is_monochrome()
143 stickerpack = form.is_stickerpack()
144
145 post = Post.objects.create_post(title=title, text=text, files=files,
146 ip=ip, tags=tags,
147 tripcode=form.get_tripcode(),
148 monochrome=monochrome, images=images,
149 file_urls=file_urls, stickerpack=stickerpack)
150
151 if form.is_subscribe():
152 settings_manager = get_settings_manager(request)
153 settings_manager.add_or_read_fav_thread(post)
154
155 if html_response:
156 return redirect(post.get_absolute_url())
157
158 112 def get_threads(self):
159 113 """
160 114 Gets list of threads that will be shown on a page.
@@ -16,7 +16,6 b' from boards.models.attachment import Att'
16 16 from boards.models.thread import STATUS_ARCHIVE
17 17 from boards.models.user import Notification
18 18 from boards.utils import datetime_to_epoch
19 from boards.views.thread import ThreadView
20 19
21 20 __author__ = 'neko259'
22 21
@@ -104,8 +103,8 b' def api_add_post(request, opening_post_i'
104 103 # _ban_current_user(request)
105 104 status = STATUS_ERROR
106 105 if form.is_valid():
107 post = ThreadView().new_post(request, form, opening_post,
108 html_response=False)
106 post = Post.objects.create_from_form(request, form, opening_post,
107 html_response=False)
109 108 if not post:
110 109 status = STATUS_ERROR
111 110 else:
@@ -6,7 +6,6 b' from boards.abstracts.paginator import g'
6 6 from boards.abstracts.settingsmanager import get_settings_manager
7 7 from boards.models import Post
8 8 from boards.views.base import BaseBoardView
9 from boards.views.posting_mixin import PostMixin
10 9 from boards.views.mixins import PaginatedMixin
11 10
12 11 POSTS_PER_PAGE = settings.get_int('View', 'PostsPerPage')
@@ -92,7 +91,7 b' class ImageFilter(FeedFilter):'
92 91 return 'File: {}'.format(image)
93 92
94 93
95 class FeedView(PostMixin, PaginatedMixin, BaseBoardView):
94 class FeedView(PaginatedMixin, BaseBoardView):
96 95 filters = (
97 96 TripcodeFilter,
98 97 FavoritesFilter,
@@ -1,6 +1,5 b''
1 1 import boards
2 2
3
4 3 PARAM_NEXT = 'next'
5 4 PARAMETER_METHOD = 'method'
6 5
@@ -10,6 +9,7 b" PARAMETER_PAGINATOR = 'paginator'"
10 9 PARAMETER_PREV_LINK = 'prev_page_link'
11 10 PARAMETER_NEXT_LINK = 'next_page_link'
12 11
12
13 13 class DispatcherMixin:
14 14 """
15 15 This class contains a dispather method that can run a method specified by
@@ -58,4 +58,3 b' class PaginatedMixin:'
58 58 current_page.next_page_number())
59 59
60 60 return params
61
@@ -3,7 +3,7 b' from django.urls import reverse'
3 3
4 4 from boards.abstracts.settingsmanager import get_settings_manager, \
5 5 SETTING_FAVORITE_TAGS, SETTING_HIDDEN_TAGS
6 from boards.models import Tag, TagAlias
6 from boards.models import Tag, TagAlias, Post
7 7 from boards.views.all_threads import AllThreadsView
8 8 from boards.views.mixins import DispatcherMixin, PARAMETER_METHOD
9 9 from boards.forms import ThreadForm, PlainErrorList
@@ -79,7 +79,7 b' class TagView(AllThreadsView, Dispatcher'
79 79 form.session = request.session
80 80
81 81 if form.is_valid():
82 return self.create_thread(request, form)
82 return Post.objects.create_from_form(request, form, opening_post=None)
83 83 if form.need_to_ban:
84 84 # Ban user because he is suspected to be a bot
85 85 self._ban_current_user(request)
@@ -6,13 +6,11 b' from django.utils.decorators import meth'
6 6 from django.views.decorators.csrf import csrf_protect
7 7 from django.views.generic.edit import FormMixin
8 8
9 from boards import utils
10 9 from boards.abstracts.settingsmanager import get_settings_manager
11 10 from boards.forms import PostForm, PlainErrorList
12 11 from boards.models import Post
13 12 from boards.views.base import BaseBoardView, CONTEXT_FORM
14 13 from boards.views.mixins import DispatcherMixin, PARAMETER_METHOD
15 from boards.views.posting_mixin import PostMixin
16 14
17 15 REQ_POST_ID = 'post_id'
18 16
@@ -23,13 +21,8 b" CONTEXT_OP = 'opening_post'"
23 21 CONTEXT_FAVORITE = 'is_favorite'
24 22 CONTEXT_RSS_URL = 'rss_url'
25 23
26 FORM_TITLE = 'title'
27 FORM_TEXT = 'text'
28 FORM_IMAGE = 'image'
29 FORM_THREADS = 'threads'
30 24
31
32 class ThreadView(BaseBoardView, PostMixin, FormMixin, DispatcherMixin):
25 class ThreadView(BaseBoardView, FormMixin, DispatcherMixin):
33 26
34 27 @method_decorator(csrf_protect)
35 28 def get(self, request, post_id, form: PostForm=None):
@@ -87,49 +80,13 b' class ThreadView(BaseBoardView, PostMixi'
87 80 form.session = request.session
88 81
89 82 if form.is_valid():
90 return self.new_post(request, form, opening_post)
83 return Post.objects.create_from_form(request, form, opening_post)
91 84 if form.need_to_ban:
92 85 # Ban user because he is suspected to be a bot
93 86 self._ban_current_user(request)
94 87
95 88 return self.get(request, post_id, form)
96 89
97 def new_post(self, request, form: PostForm, opening_post: Post=None,
98 html_response=True):
99 """
100 Adds a new post (in thread or as a reply).
101 """
102
103 ip = utils.get_client_ip(request)
104
105 data = form.cleaned_data
106
107 title = form.get_title()
108 text = data[FORM_TEXT]
109 files = form.get_files()
110 file_urls = form.get_file_urls()
111 images = form.get_images()
112
113 text = self._remove_invalid_links(text)
114
115 post_thread = opening_post.get_thread()
116
117 post = Post.objects.create_post(title=title, text=text, files=files,
118 thread=post_thread, ip=ip,
119 tripcode=form.get_tripcode(),
120 images=images, file_urls=file_urls)
121
122 if form.is_subscribe():
123 settings_manager = get_settings_manager(request)
124 settings_manager.add_or_read_fav_thread(
125 post_thread.get_opening_post())
126
127 if html_response:
128 if opening_post:
129 return redirect(post.get_absolute_url())
130 else:
131 return post
132
133 90 def get_data(self, thread) -> dict:
134 91 """
135 92 Returns context params for the view.
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now