##// END OF EJS Templates
Search aliases with term in any place, not only from the start
neko259 -
r1703:75e48094 default
parent child Browse files
Show More
@@ -1,315 +1,315 b''
1 import json
1 import json
2 import logging
2 import logging
3
3
4 from django.core import serializers
4 from django.core import serializers
5 from django.db import transaction
5 from django.db import transaction
6 from django.http import HttpResponse
6 from django.http import HttpResponse
7 from django.shortcuts import get_object_or_404
7 from django.shortcuts import get_object_or_404
8 from django.views.decorators.csrf import csrf_protect
8 from django.views.decorators.csrf import csrf_protect
9
9
10 from boards.abstracts.settingsmanager import get_settings_manager
10 from boards.abstracts.settingsmanager import get_settings_manager
11 from boards.forms import PostForm, PlainErrorList
11 from boards.forms import PostForm, PlainErrorList
12 from boards.mdx_neboard import Parser
12 from boards.mdx_neboard import Parser
13 from boards.models import Post, Thread, Tag, Attachment
13 from boards.models import Post, Thread, Tag, Attachment
14 from boards.models.thread import STATUS_ARCHIVE
14 from boards.models.thread import STATUS_ARCHIVE
15 from boards.models.user import Notification
15 from boards.models.user import Notification
16 from boards.utils import datetime_to_epoch
16 from boards.utils import datetime_to_epoch
17 from boards.views.thread import ThreadView
17 from boards.views.thread import ThreadView
18 from boards.models.attachment.viewers import FILE_TYPES_IMAGE
18 from boards.models.attachment.viewers import FILE_TYPES_IMAGE
19
19
20 __author__ = 'neko259'
20 __author__ = 'neko259'
21
21
22 PARAMETER_TRUNCATED = 'truncated'
22 PARAMETER_TRUNCATED = 'truncated'
23 PARAMETER_TAG = 'tag'
23 PARAMETER_TAG = 'tag'
24 PARAMETER_OFFSET = 'offset'
24 PARAMETER_OFFSET = 'offset'
25 PARAMETER_DIFF_TYPE = 'type'
25 PARAMETER_DIFF_TYPE = 'type'
26 PARAMETER_POST = 'post'
26 PARAMETER_POST = 'post'
27 PARAMETER_UPDATED = 'updated'
27 PARAMETER_UPDATED = 'updated'
28 PARAMETER_LAST_UPDATE = 'last_update'
28 PARAMETER_LAST_UPDATE = 'last_update'
29 PARAMETER_THREAD = 'thread'
29 PARAMETER_THREAD = 'thread'
30 PARAMETER_UIDS = 'uids'
30 PARAMETER_UIDS = 'uids'
31 PARAMETER_SUBSCRIBED = 'subscribed'
31 PARAMETER_SUBSCRIBED = 'subscribed'
32
32
33 DIFF_TYPE_HTML = 'html'
33 DIFF_TYPE_HTML = 'html'
34 DIFF_TYPE_JSON = 'json'
34 DIFF_TYPE_JSON = 'json'
35
35
36 STATUS_OK = 'ok'
36 STATUS_OK = 'ok'
37 STATUS_ERROR = 'error'
37 STATUS_ERROR = 'error'
38
38
39 logger = logging.getLogger(__name__)
39 logger = logging.getLogger(__name__)
40
40
41
41
42 @transaction.atomic
42 @transaction.atomic
43 def api_get_threaddiff(request):
43 def api_get_threaddiff(request):
44 """
44 """
45 Gets posts that were changed or added since time
45 Gets posts that were changed or added since time
46 """
46 """
47
47
48 thread_id = request.POST.get(PARAMETER_THREAD)
48 thread_id = request.POST.get(PARAMETER_THREAD)
49 uids_str = request.POST.get(PARAMETER_UIDS)
49 uids_str = request.POST.get(PARAMETER_UIDS)
50
50
51 if not thread_id or not uids_str:
51 if not thread_id or not uids_str:
52 return HttpResponse(content='Invalid request.')
52 return HttpResponse(content='Invalid request.')
53
53
54 uids = uids_str.strip().split(' ')
54 uids = uids_str.strip().split(' ')
55
55
56 opening_post = get_object_or_404(Post, id=thread_id)
56 opening_post = get_object_or_404(Post, id=thread_id)
57 thread = opening_post.get_thread()
57 thread = opening_post.get_thread()
58
58
59 json_data = {
59 json_data = {
60 PARAMETER_UPDATED: [],
60 PARAMETER_UPDATED: [],
61 PARAMETER_LAST_UPDATE: None, # TODO Maybe this can be removed already?
61 PARAMETER_LAST_UPDATE: None, # TODO Maybe this can be removed already?
62 }
62 }
63 posts = Post.objects.filter(threads__in=[thread]).exclude(uid__in=uids)
63 posts = Post.objects.filter(threads__in=[thread]).exclude(uid__in=uids)
64
64
65 diff_type = request.GET.get(PARAMETER_DIFF_TYPE, DIFF_TYPE_HTML)
65 diff_type = request.GET.get(PARAMETER_DIFF_TYPE, DIFF_TYPE_HTML)
66
66
67 for post in posts:
67 for post in posts:
68 json_data[PARAMETER_UPDATED].append(post.get_post_data(
68 json_data[PARAMETER_UPDATED].append(post.get_post_data(
69 format_type=diff_type, request=request))
69 format_type=diff_type, request=request))
70 json_data[PARAMETER_LAST_UPDATE] = str(thread.last_edit_time)
70 json_data[PARAMETER_LAST_UPDATE] = str(thread.last_edit_time)
71
71
72 settings_manager = get_settings_manager(request)
72 settings_manager = get_settings_manager(request)
73 json_data[PARAMETER_SUBSCRIBED] = str(settings_manager.thread_is_fav(opening_post))
73 json_data[PARAMETER_SUBSCRIBED] = str(settings_manager.thread_is_fav(opening_post))
74
74
75 # If the tag is favorite, update the counter
75 # If the tag is favorite, update the counter
76 settings_manager = get_settings_manager(request)
76 settings_manager = get_settings_manager(request)
77 favorite = settings_manager.thread_is_fav(opening_post)
77 favorite = settings_manager.thread_is_fav(opening_post)
78 if favorite:
78 if favorite:
79 settings_manager.add_or_read_fav_thread(opening_post)
79 settings_manager.add_or_read_fav_thread(opening_post)
80
80
81 return HttpResponse(content=json.dumps(json_data))
81 return HttpResponse(content=json.dumps(json_data))
82
82
83
83
84 @csrf_protect
84 @csrf_protect
85 def api_add_post(request, opening_post_id):
85 def api_add_post(request, opening_post_id):
86 """
86 """
87 Adds a post and return the JSON response for it
87 Adds a post and return the JSON response for it
88 """
88 """
89
89
90 opening_post = get_object_or_404(Post, id=opening_post_id)
90 opening_post = get_object_or_404(Post, id=opening_post_id)
91
91
92 logger.info('Adding post via api...')
92 logger.info('Adding post via api...')
93
93
94 status = STATUS_OK
94 status = STATUS_OK
95 errors = []
95 errors = []
96
96
97 if request.method == 'POST':
97 if request.method == 'POST':
98 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
98 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
99 form.session = request.session
99 form.session = request.session
100
100
101 if form.need_to_ban:
101 if form.need_to_ban:
102 # Ban user because he is suspected to be a bot
102 # Ban user because he is suspected to be a bot
103 # _ban_current_user(request)
103 # _ban_current_user(request)
104 status = STATUS_ERROR
104 status = STATUS_ERROR
105 if form.is_valid():
105 if form.is_valid():
106 post = ThreadView().new_post(request, form, opening_post,
106 post = ThreadView().new_post(request, form, opening_post,
107 html_response=False)
107 html_response=False)
108 if not post:
108 if not post:
109 status = STATUS_ERROR
109 status = STATUS_ERROR
110 else:
110 else:
111 logger.info('Added post #%d via api.' % post.id)
111 logger.info('Added post #%d via api.' % post.id)
112 else:
112 else:
113 status = STATUS_ERROR
113 status = STATUS_ERROR
114 errors = form.as_json_errors()
114 errors = form.as_json_errors()
115
115
116 response = {
116 response = {
117 'status': status,
117 'status': status,
118 'errors': errors,
118 'errors': errors,
119 }
119 }
120
120
121 return HttpResponse(content=json.dumps(response))
121 return HttpResponse(content=json.dumps(response))
122
122
123
123
124 def get_post(request, post_id):
124 def get_post(request, post_id):
125 """
125 """
126 Gets the html of a post. Used for popups. Post can be truncated if used
126 Gets the html of a post. Used for popups. Post can be truncated if used
127 in threads list with 'truncated' get parameter.
127 in threads list with 'truncated' get parameter.
128 """
128 """
129
129
130 post = get_object_or_404(Post, id=post_id)
130 post = get_object_or_404(Post, id=post_id)
131 truncated = PARAMETER_TRUNCATED in request.GET
131 truncated = PARAMETER_TRUNCATED in request.GET
132
132
133 return HttpResponse(content=post.get_view(truncated=truncated, need_op_data=True))
133 return HttpResponse(content=post.get_view(truncated=truncated, need_op_data=True))
134
134
135
135
136 def api_get_threads(request, count):
136 def api_get_threads(request, count):
137 """
137 """
138 Gets the JSON thread opening posts list.
138 Gets the JSON thread opening posts list.
139 Parameters that can be used for filtering:
139 Parameters that can be used for filtering:
140 tag, offset (from which thread to get results)
140 tag, offset (from which thread to get results)
141 """
141 """
142
142
143 if PARAMETER_TAG in request.GET:
143 if PARAMETER_TAG in request.GET:
144 tag_name = request.GET[PARAMETER_TAG]
144 tag_name = request.GET[PARAMETER_TAG]
145 if tag_name is not None:
145 if tag_name is not None:
146 tag = get_object_or_404(Tag, name=tag_name)
146 tag = get_object_or_404(Tag, name=tag_name)
147 threads = tag.get_threads().exclude(status=STATUS_ARCHIVE)
147 threads = tag.get_threads().exclude(status=STATUS_ARCHIVE)
148 else:
148 else:
149 threads = Thread.objects.exclude(status=STATUS_ARCHIVE)
149 threads = Thread.objects.exclude(status=STATUS_ARCHIVE)
150
150
151 if PARAMETER_OFFSET in request.GET:
151 if PARAMETER_OFFSET in request.GET:
152 offset = request.GET[PARAMETER_OFFSET]
152 offset = request.GET[PARAMETER_OFFSET]
153 offset = int(offset) if offset is not None else 0
153 offset = int(offset) if offset is not None else 0
154 else:
154 else:
155 offset = 0
155 offset = 0
156
156
157 threads = threads.order_by('-bump_time')
157 threads = threads.order_by('-bump_time')
158 threads = threads[offset:offset + int(count)]
158 threads = threads[offset:offset + int(count)]
159
159
160 opening_posts = []
160 opening_posts = []
161 for thread in threads:
161 for thread in threads:
162 opening_post = thread.get_opening_post()
162 opening_post = thread.get_opening_post()
163
163
164 # TODO Add tags, replies and images count
164 # TODO Add tags, replies and images count
165 post_data = opening_post.get_post_data(include_last_update=True)
165 post_data = opening_post.get_post_data(include_last_update=True)
166 post_data['status'] = thread.get_status()
166 post_data['status'] = thread.get_status()
167
167
168 opening_posts.append(post_data)
168 opening_posts.append(post_data)
169
169
170 return HttpResponse(content=json.dumps(opening_posts))
170 return HttpResponse(content=json.dumps(opening_posts))
171
171
172
172
173 # TODO Test this
173 # TODO Test this
174 def api_get_tags(request):
174 def api_get_tags(request):
175 """
175 """
176 Gets all tags or user tags.
176 Gets all tags or user tags.
177 """
177 """
178
178
179 # TODO Get favorite tags for the given user ID
179 # TODO Get favorite tags for the given user ID
180
180
181 tags = Tag.objects.get_not_empty_tags()
181 tags = Tag.objects.get_not_empty_tags()
182
182
183 term = request.GET.get('term')
183 term = request.GET.get('term')
184 if term is not None:
184 if term is not None:
185 tags = tags.filter(name__contains=term)
185 tags = tags.filter(name__contains=term)
186
186
187 tag_names = [tag.name for tag in tags]
187 tag_names = [tag.name for tag in tags]
188
188
189 return HttpResponse(content=json.dumps(tag_names))
189 return HttpResponse(content=json.dumps(tag_names))
190
190
191
191
192 def api_get_stickers(request):
192 def api_get_stickers(request):
193 attachments = Attachment.objects.filter(mimetype__in=FILE_TYPES_IMAGE)\
193 attachments = Attachment.objects.filter(mimetype__in=FILE_TYPES_IMAGE)\
194 .exclude(alias='').exclude(alias=None)
194 .exclude(alias='').exclude(alias=None)
195
195
196 term = request.GET.get('term')
196 term = request.GET.get('term')
197 if term:
197 if term:
198 attachments = attachments.filter(alias__startswith=term)
198 attachments = attachments.filter(alias__contains=term)
199
199
200 image_dict = [{'thumb': attachment.get_thumb_url(),
200 image_dict = [{'thumb': attachment.get_thumb_url(),
201 'alias': attachment.alias}
201 'alias': attachment.alias}
202 for attachment in attachments]
202 for attachment in attachments]
203
203
204 return HttpResponse(content=json.dumps(image_dict))
204 return HttpResponse(content=json.dumps(image_dict))
205
205
206
206
207 # TODO The result can be cached by the thread last update time
207 # TODO The result can be cached by the thread last update time
208 # TODO Test this
208 # TODO Test this
209 def api_get_thread_posts(request, opening_post_id):
209 def api_get_thread_posts(request, opening_post_id):
210 """
210 """
211 Gets the JSON array of thread posts
211 Gets the JSON array of thread posts
212 """
212 """
213
213
214 opening_post = get_object_or_404(Post, id=opening_post_id)
214 opening_post = get_object_or_404(Post, id=opening_post_id)
215 thread = opening_post.get_thread()
215 thread = opening_post.get_thread()
216 posts = thread.get_replies()
216 posts = thread.get_replies()
217
217
218 json_data = {
218 json_data = {
219 'posts': [],
219 'posts': [],
220 'last_update': None,
220 'last_update': None,
221 }
221 }
222 json_post_list = []
222 json_post_list = []
223
223
224 for post in posts:
224 for post in posts:
225 json_post_list.append(post.get_post_data())
225 json_post_list.append(post.get_post_data())
226 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
226 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
227 json_data['posts'] = json_post_list
227 json_data['posts'] = json_post_list
228
228
229 return HttpResponse(content=json.dumps(json_data))
229 return HttpResponse(content=json.dumps(json_data))
230
230
231
231
232 def api_get_notifications(request, username):
232 def api_get_notifications(request, username):
233 last_notification_id_str = request.GET.get('last', None)
233 last_notification_id_str = request.GET.get('last', None)
234 last_id = int(last_notification_id_str) if last_notification_id_str is not None else None
234 last_id = int(last_notification_id_str) if last_notification_id_str is not None else None
235
235
236 posts = Notification.objects.get_notification_posts(usernames=[username],
236 posts = Notification.objects.get_notification_posts(usernames=[username],
237 last=last_id)
237 last=last_id)
238
238
239 json_post_list = []
239 json_post_list = []
240 for post in posts:
240 for post in posts:
241 json_post_list.append(post.get_post_data())
241 json_post_list.append(post.get_post_data())
242 return HttpResponse(content=json.dumps(json_post_list))
242 return HttpResponse(content=json.dumps(json_post_list))
243
243
244
244
245 def api_get_post(request, post_id):
245 def api_get_post(request, post_id):
246 """
246 """
247 Gets the JSON of a post. This can be
247 Gets the JSON of a post. This can be
248 used as and API for external clients.
248 used as and API for external clients.
249 """
249 """
250
250
251 post = get_object_or_404(Post, id=post_id)
251 post = get_object_or_404(Post, id=post_id)
252
252
253 json = serializers.serialize("json", [post], fields=(
253 json = serializers.serialize("json", [post], fields=(
254 "pub_time", "_text_rendered", "title", "text", "image",
254 "pub_time", "_text_rendered", "title", "text", "image",
255 "image_width", "image_height", "replies", "tags"
255 "image_width", "image_height", "replies", "tags"
256 ))
256 ))
257
257
258 return HttpResponse(content=json)
258 return HttpResponse(content=json)
259
259
260
260
261 def api_get_preview(request):
261 def api_get_preview(request):
262 raw_text = request.POST['raw_text']
262 raw_text = request.POST['raw_text']
263
263
264 parser = Parser()
264 parser = Parser()
265 return HttpResponse(content=parser.parse(parser.preparse(raw_text)))
265 return HttpResponse(content=parser.parse(parser.preparse(raw_text)))
266
266
267
267
268 def api_get_new_posts(request):
268 def api_get_new_posts(request):
269 """
269 """
270 Gets favorite threads and unread posts count.
270 Gets favorite threads and unread posts count.
271 """
271 """
272 posts = list()
272 posts = list()
273
273
274 include_posts = 'include_posts' in request.GET
274 include_posts = 'include_posts' in request.GET
275
275
276 settings_manager = get_settings_manager(request)
276 settings_manager = get_settings_manager(request)
277 fav_threads = settings_manager.get_fav_threads()
277 fav_threads = settings_manager.get_fav_threads()
278 fav_thread_ops = Post.objects.filter(id__in=fav_threads.keys())\
278 fav_thread_ops = Post.objects.filter(id__in=fav_threads.keys())\
279 .order_by('-pub_time').prefetch_related('thread')
279 .order_by('-pub_time').prefetch_related('thread')
280
280
281 ops = [{'op': op, 'last_id': fav_threads[str(op.id)]} for op in fav_thread_ops]
281 ops = [{'op': op, 'last_id': fav_threads[str(op.id)]} for op in fav_thread_ops]
282 if include_posts:
282 if include_posts:
283 new_post_threads = Thread.objects.get_new_posts(ops)
283 new_post_threads = Thread.objects.get_new_posts(ops)
284 if new_post_threads:
284 if new_post_threads:
285 thread_ids = {thread.id: thread for thread in new_post_threads}
285 thread_ids = {thread.id: thread for thread in new_post_threads}
286 else:
286 else:
287 thread_ids = dict()
287 thread_ids = dict()
288
288
289 for op in fav_thread_ops:
289 for op in fav_thread_ops:
290 fav_thread_dict = dict()
290 fav_thread_dict = dict()
291
291
292 op_thread = op.get_thread()
292 op_thread = op.get_thread()
293 if op_thread.id in thread_ids:
293 if op_thread.id in thread_ids:
294 thread = thread_ids[op_thread.id]
294 thread = thread_ids[op_thread.id]
295 new_post_count = thread.new_post_count
295 new_post_count = thread.new_post_count
296 fav_thread_dict['newest_post_link'] = thread.get_replies()\
296 fav_thread_dict['newest_post_link'] = thread.get_replies()\
297 .filter(id__gt=fav_threads[str(op.id)])\
297 .filter(id__gt=fav_threads[str(op.id)])\
298 .first().get_absolute_url(thread=thread)
298 .first().get_absolute_url(thread=thread)
299 else:
299 else:
300 new_post_count = 0
300 new_post_count = 0
301 fav_thread_dict['new_post_count'] = new_post_count
301 fav_thread_dict['new_post_count'] = new_post_count
302
302
303 fav_thread_dict['id'] = op.id
303 fav_thread_dict['id'] = op.id
304
304
305 fav_thread_dict['post_url'] = op.get_link_view()
305 fav_thread_dict['post_url'] = op.get_link_view()
306 fav_thread_dict['title'] = op.title
306 fav_thread_dict['title'] = op.title
307
307
308 posts.append(fav_thread_dict)
308 posts.append(fav_thread_dict)
309 else:
309 else:
310 fav_thread_dict = dict()
310 fav_thread_dict = dict()
311 fav_thread_dict['new_post_count'] = \
311 fav_thread_dict['new_post_count'] = \
312 Thread.objects.get_new_post_count(ops)
312 Thread.objects.get_new_post_count(ops)
313 posts.append(fav_thread_dict)
313 posts.append(fav_thread_dict)
314
314
315 return HttpResponse(content=json.dumps(posts))
315 return HttpResponse(content=json.dumps(posts))
General Comments 0
You need to be logged in to leave comments. Login now