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