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