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 | from django.db import transaction |
|
2 | from django.db import transaction | |
3 |
|
3 | |||
4 | from boards.models import Post |
|
4 | from boards.models import Post | |
5 | from boards.models.post import NO_IP |
|
5 | from boards.models.post.manager import NO_IP | |
6 |
|
||||
7 |
|
6 | |||
8 | __author__ = 'neko259' |
|
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 | import logging | |
4 | import re |
|
2 | import re | |
5 | import uuid |
|
3 | import uuid | |
6 |
|
4 | |||
7 | from django.core.exceptions import ObjectDoesNotExist |
|
5 | from django.core.exceptions import ObjectDoesNotExist | |
8 | from django.core.urlresolvers import reverse |
|
6 | from django.core.urlresolvers import reverse | |
9 |
from django.db import models |
|
7 | from django.db import models | |
10 | from django.db.models import TextField, QuerySet |
|
8 | from django.db.models import TextField, QuerySet | |
|
9 | ||||
11 | from django.template.loader import render_to_string |
|
10 | from django.template.loader import render_to_string | |
|
11 | ||||
12 | from django.utils import timezone |
|
12 | from django.utils import timezone | |
13 |
|
13 | |||
14 | from boards.mdx_neboard import Parser |
|
14 | from boards.mdx_neboard import Parser | |
@@ -16,10 +16,9 b' from boards.models import KeyPair, Globa' | |||||
16 | from boards import settings |
|
16 | from boards import settings | |
17 | from boards.models import PostImage |
|
17 | from boards.models import PostImage | |
18 | from boards.models.base import Viewable |
|
18 | from boards.models.base import Viewable | |
19 | from boards import utils |
|
|||
20 | from boards.models.post.export import get_exporter, DIFF_TYPE_JSON |
|
19 | from boards.models.post.export import get_exporter, DIFF_TYPE_JSON | |
21 |
from boards.models. |
|
20 | from boards.models.post.manager import PostManager | |
22 | import boards.models.thread |
|
21 | from boards.models.user import Notification | |
23 |
|
22 | |||
24 | WS_NOTIFICATION_TYPE_NEW_POST = 'new_post' |
|
23 | WS_NOTIFICATION_TYPE_NEW_POST = 'new_post' | |
25 | WS_NOTIFICATION_TYPE = 'notification_type' |
|
24 | WS_NOTIFICATION_TYPE = 'notification_type' | |
@@ -28,16 +27,12 b' WS_CHANNEL_THREAD = "thread:"' | |||||
28 |
|
27 | |||
29 | APP_LABEL_BOARDS = 'boards' |
|
28 | APP_LABEL_BOARDS = 'boards' | |
30 |
|
29 | |||
31 | POSTS_PER_DAY_RANGE = 7 |
|
|||
32 |
|
||||
33 | BAN_REASON_AUTO = 'Auto' |
|
30 | BAN_REASON_AUTO = 'Auto' | |
34 |
|
31 | |||
35 | IMAGE_THUMB_SIZE = (200, 150) |
|
32 | IMAGE_THUMB_SIZE = (200, 150) | |
36 |
|
33 | |||
37 | TITLE_MAX_LENGTH = 200 |
|
34 | TITLE_MAX_LENGTH = 200 | |
38 |
|
35 | |||
39 | NO_IP = '0.0.0.0' |
|
|||
40 |
|
||||
41 | REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]') |
|
36 | REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]') | |
42 | REGEX_GLOBAL_REPLY = re.compile(r'\[post\](\w+)::([^:]+)::(\d+)\[/post\]') |
|
37 | REGEX_GLOBAL_REPLY = re.compile(r'\[post\](\w+)::([^:]+)::(\d+)\[/post\]') | |
43 | REGEX_URL = re.compile(r'https?\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?') |
|
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 | REFMAP_STR = '<a href="{}">>>{}</a>' |
|
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 | class Post(models.Model, Viewable): |
|
67 | class Post(models.Model, Viewable): | |
183 | """A post is a message.""" |
|
68 | """A post is a message.""" | |
184 |
|
69 |
General Comments 0
You need to be logged in to leave comments.
Login now