Show More
@@ -0,0 +1,125 b'' | |||
|
1 | from datetime import datetime, timedelta, date | |
|
2 | from datetime import time as dtime | |
|
3 | import logging | |
|
4 | from django.db import models, transaction | |
|
5 | from django.utils import timezone | |
|
6 | from boards import utils | |
|
7 | from boards.mdx_neboard import Parser | |
|
8 | from boards.models import PostImage | |
|
9 | import boards.models | |
|
10 | ||
|
11 | __author__ = 'vurdalak' | |
|
12 | ||
|
13 | ||
|
14 | NO_IP = '0.0.0.0' | |
|
15 | POSTS_PER_DAY_RANGE = 7 | |
|
16 | ||
|
17 | ||
|
18 | class PostManager(models.Manager): | |
|
19 | @transaction.atomic | |
|
20 | def create_post(self, title: str, text: str, image=None, thread=None, | |
|
21 | ip=NO_IP, tags: list=None, opening_posts: list=None): | |
|
22 | """ | |
|
23 | Creates new post | |
|
24 | """ | |
|
25 | ||
|
26 | is_banned = boards.models.Ban.objects.filter(ip=ip).exists() | |
|
27 | ||
|
28 | # TODO Raise specific exception and catch it in the views | |
|
29 | if is_banned: | |
|
30 | raise Exception("This user is banned") | |
|
31 | ||
|
32 | if not tags: | |
|
33 | tags = [] | |
|
34 | if not opening_posts: | |
|
35 | opening_posts = [] | |
|
36 | ||
|
37 | posting_time = timezone.now() | |
|
38 | if not thread: | |
|
39 | thread = boards.models.thread.Thread.objects.create( | |
|
40 | bump_time=posting_time, last_edit_time=posting_time) | |
|
41 | list(map(thread.tags.add, tags)) | |
|
42 | boards.models.thread.Thread.objects.process_oldest_threads() | |
|
43 | else: | |
|
44 | thread.last_edit_time = posting_time | |
|
45 | thread.bump() | |
|
46 | thread.save() | |
|
47 | ||
|
48 | pre_text = Parser().preparse(text) | |
|
49 | ||
|
50 | post = self.create(title=title, | |
|
51 | text=pre_text, | |
|
52 | pub_time=posting_time, | |
|
53 | poster_ip=ip, | |
|
54 | thread=thread, | |
|
55 | last_edit_time=posting_time) | |
|
56 | post.threads.add(thread) | |
|
57 | ||
|
58 | post.set_global_id() | |
|
59 | ||
|
60 | logger = logging.getLogger('boards.post.create') | |
|
61 | ||
|
62 | logger.info('Created post {} by {}'.format(post, post.poster_ip)) | |
|
63 | ||
|
64 | if image: | |
|
65 | post.images.add(PostImage.objects.create_with_hash(image)) | |
|
66 | ||
|
67 | post.build_url() | |
|
68 | post.connect_replies() | |
|
69 | post.connect_threads(opening_posts) | |
|
70 | post.connect_notifications() | |
|
71 | ||
|
72 | return post | |
|
73 | ||
|
74 | @transaction.atomic | |
|
75 | def import_post(self, title: str, text: str, pub_time: str, | |
|
76 | opening_post=None, tags=list()): | |
|
77 | if opening_post is None: | |
|
78 | thread = boards.models.thread.Thread.objects.create( | |
|
79 | bump_time=pub_time, last_edit_time=pub_time) | |
|
80 | list(map(thread.tags.add, tags)) | |
|
81 | else: | |
|
82 | thread = opening_post.get_thread() | |
|
83 | ||
|
84 | post = self.create(title=title, text=text, | |
|
85 | pub_time=pub_time, | |
|
86 | poster_ip=NO_IP, | |
|
87 | last_edit_time=pub_time, | |
|
88 | thread_id=thread.id) | |
|
89 | ||
|
90 | post.build_url() | |
|
91 | post.connect_replies() | |
|
92 | post.connect_notifications() | |
|
93 | ||
|
94 | return post | |
|
95 | ||
|
96 | def delete_posts_by_ip(self, ip): | |
|
97 | """ | |
|
98 | Deletes all posts of the author with same IP | |
|
99 | """ | |
|
100 | ||
|
101 | posts = self.filter(poster_ip=ip) | |
|
102 | for post in posts: | |
|
103 | post.delete() | |
|
104 | ||
|
105 | @utils.cached_result() | |
|
106 | def get_posts_per_day(self) -> float: | |
|
107 | """ | |
|
108 | Gets average count of posts per day for the last 7 days | |
|
109 | """ | |
|
110 | ||
|
111 | day_end = date.today() | |
|
112 | day_start = day_end - timedelta(POSTS_PER_DAY_RANGE) | |
|
113 | ||
|
114 | day_time_start = timezone.make_aware(datetime.combine( | |
|
115 | day_start, dtime()), timezone.get_current_timezone()) | |
|
116 | day_time_end = timezone.make_aware(datetime.combine( | |
|
117 | day_end, dtime()), timezone.get_current_timezone()) | |
|
118 | ||
|
119 | posts_per_period = float(self.filter( | |
|
120 | pub_time__lte=day_time_end, | |
|
121 | pub_time__gte=day_time_start).count()) | |
|
122 | ||
|
123 | ppd = posts_per_period / POSTS_PER_DAY_RANGE | |
|
124 | ||
|
125 | return ppd |
@@ -2,8 +2,7 b' from django.core.management import BaseC' | |||
|
2 | 2 | from django.db import transaction |
|
3 | 3 | |
|
4 | 4 | from boards.models import Post |
|
5 | from boards.models.post import NO_IP | |
|
6 | ||
|
5 | from boards.models.post.manager import NO_IP | |
|
7 | 6 | |
|
8 | 7 | __author__ = 'neko259' |
|
9 | 8 |
@@ -1,14 +1,14 b'' | |||
|
1 | from datetime import datetime, timedelta, date | |
|
2 | from datetime import time as dtime | |
|
3 | 1 |
|
|
4 | 2 | import re |
|
5 | 3 | import uuid |
|
6 | 4 | |
|
7 | 5 | from django.core.exceptions import ObjectDoesNotExist |
|
8 | 6 | from django.core.urlresolvers import reverse |
|
9 |
from django.db import models |
|
|
7 | from django.db import models | |
|
10 | 8 | from django.db.models import TextField, QuerySet |
|
9 | ||
|
11 | 10 | from django.template.loader import render_to_string |
|
11 | ||
|
12 | 12 | from django.utils import timezone |
|
13 | 13 | |
|
14 | 14 | from boards.mdx_neboard import Parser |
@@ -16,10 +16,9 b' from boards.models import KeyPair, Globa' | |||
|
16 | 16 | from boards import settings |
|
17 | 17 | from boards.models import PostImage |
|
18 | 18 | from boards.models.base import Viewable |
|
19 | from boards import utils | |
|
20 | 19 | from boards.models.post.export import get_exporter, DIFF_TYPE_JSON |
|
21 |
from boards.models. |
|
|
22 | import boards.models.thread | |
|
20 | from boards.models.post.manager import PostManager | |
|
21 | from boards.models.user import Notification | |
|
23 | 22 | |
|
24 | 23 | WS_NOTIFICATION_TYPE_NEW_POST = 'new_post' |
|
25 | 24 | WS_NOTIFICATION_TYPE = 'notification_type' |
@@ -28,16 +27,12 b' WS_CHANNEL_THREAD = "thread:"' | |||
|
28 | 27 | |
|
29 | 28 | APP_LABEL_BOARDS = 'boards' |
|
30 | 29 | |
|
31 | POSTS_PER_DAY_RANGE = 7 | |
|
32 | ||
|
33 | 30 | BAN_REASON_AUTO = 'Auto' |
|
34 | 31 | |
|
35 | 32 | IMAGE_THUMB_SIZE = (200, 150) |
|
36 | 33 | |
|
37 | 34 | TITLE_MAX_LENGTH = 200 |
|
38 | 35 | |
|
39 | NO_IP = '0.0.0.0' | |
|
40 | ||
|
41 | 36 | REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]') |
|
42 | 37 | REGEX_GLOBAL_REPLY = re.compile(r'\[post\](\w+)::([^:]+)::(\d+)\[/post\]') |
|
43 | 38 | REGEX_URL = re.compile(r'https?\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?') |
@@ -69,116 +64,6 b' POST_VIEW_PARAMS = (' | |||
|
69 | 64 | REFMAP_STR = '<a href="{}">>>{}</a>' |
|
70 | 65 | |
|
71 | 66 | |
|
72 | class PostManager(models.Manager): | |
|
73 | @transaction.atomic | |
|
74 | def create_post(self, title: str, text: str, image=None, thread=None, | |
|
75 | ip=NO_IP, tags: list=None, opening_posts: list=None): | |
|
76 | """ | |
|
77 | Creates new post | |
|
78 | """ | |
|
79 | ||
|
80 | is_banned = Ban.objects.filter(ip=ip).exists() | |
|
81 | ||
|
82 | # TODO Raise specific exception and catch it in the views | |
|
83 | if is_banned: | |
|
84 | raise Exception("This user is banned") | |
|
85 | ||
|
86 | if not tags: | |
|
87 | tags = [] | |
|
88 | if not opening_posts: | |
|
89 | opening_posts = [] | |
|
90 | ||
|
91 | posting_time = timezone.now() | |
|
92 | if not thread: | |
|
93 | thread = boards.models.thread.Thread.objects.create( | |
|
94 | bump_time=posting_time, last_edit_time=posting_time) | |
|
95 | list(map(thread.tags.add, tags)) | |
|
96 | boards.models.thread.Thread.objects.process_oldest_threads() | |
|
97 | else: | |
|
98 | thread.last_edit_time = posting_time | |
|
99 | thread.bump() | |
|
100 | thread.save() | |
|
101 | ||
|
102 | pre_text = Parser().preparse(text) | |
|
103 | ||
|
104 | post = self.create(title=title, | |
|
105 | text=pre_text, | |
|
106 | pub_time=posting_time, | |
|
107 | poster_ip=ip, | |
|
108 | thread=thread, | |
|
109 | last_edit_time=posting_time) | |
|
110 | post.threads.add(thread) | |
|
111 | ||
|
112 | post.set_global_id() | |
|
113 | ||
|
114 | logger = logging.getLogger('boards.post.create') | |
|
115 | ||
|
116 | logger.info('Created post {} by {}'.format(post, post.poster_ip)) | |
|
117 | ||
|
118 | if image: | |
|
119 | post.images.add(PostImage.objects.create_with_hash(image)) | |
|
120 | ||
|
121 | post.build_url() | |
|
122 | post.connect_replies() | |
|
123 | post.connect_threads(opening_posts) | |
|
124 | post.connect_notifications() | |
|
125 | ||
|
126 | return post | |
|
127 | ||
|
128 | @transaction.atomic | |
|
129 | def import_post(self, title: str, text:str, pub_time: str, | |
|
130 | opening_post=None, tags=list()): | |
|
131 | if opening_post is None: | |
|
132 | thread = boards.models.thread.Thread.objects.create( | |
|
133 | bump_time=pub_time, last_edit_time=pub_time) | |
|
134 | list(map(thread.tags.add, tags)) | |
|
135 | else: | |
|
136 | thread = opening_post.get_thread() | |
|
137 | ||
|
138 | post = Post.objects.create(title=title, text=text, | |
|
139 | pub_time=pub_time, | |
|
140 | poster_ip=NO_IP, | |
|
141 | last_edit_time=pub_time, | |
|
142 | thread_id=thread.id) | |
|
143 | ||
|
144 | post.build_url() | |
|
145 | post.connect_replies() | |
|
146 | post.connect_notifications() | |
|
147 | ||
|
148 | return post | |
|
149 | ||
|
150 | def delete_posts_by_ip(self, ip): | |
|
151 | """ | |
|
152 | Deletes all posts of the author with same IP | |
|
153 | """ | |
|
154 | ||
|
155 | posts = self.filter(poster_ip=ip) | |
|
156 | for post in posts: | |
|
157 | post.delete() | |
|
158 | ||
|
159 | @utils.cached_result() | |
|
160 | def get_posts_per_day(self) -> float: | |
|
161 | """ | |
|
162 | Gets average count of posts per day for the last 7 days | |
|
163 | """ | |
|
164 | ||
|
165 | day_end = date.today() | |
|
166 | day_start = day_end - timedelta(POSTS_PER_DAY_RANGE) | |
|
167 | ||
|
168 | day_time_start = timezone.make_aware(datetime.combine( | |
|
169 | day_start, dtime()), timezone.get_current_timezone()) | |
|
170 | day_time_end = timezone.make_aware(datetime.combine( | |
|
171 | day_end, dtime()), timezone.get_current_timezone()) | |
|
172 | ||
|
173 | posts_per_period = float(self.filter( | |
|
174 | pub_time__lte=day_time_end, | |
|
175 | pub_time__gte=day_time_start).count()) | |
|
176 | ||
|
177 | ppd = posts_per_period / POSTS_PER_DAY_RANGE | |
|
178 | ||
|
179 | return ppd | |
|
180 | ||
|
181 | ||
|
182 | 67 | class Post(models.Model, Viewable): |
|
183 | 68 | """A post is a message.""" |
|
184 | 69 |
General Comments 0
You need to be logged in to leave comments.
Login now