##// END OF EJS Templates
Added bumpable and archived attributes to the thread API output
neko259 -
r976:af7d403c default
parent child Browse files
Show More
@@ -1,223 +1,226 b''
1 from datetime import datetime
1 from datetime import datetime
2 import json
2 import json
3 import logging
3 import logging
4 from django.db import transaction
4 from django.db import transaction
5 from django.http import HttpResponse
5 from django.http import HttpResponse
6 from django.shortcuts import get_object_or_404, render
6 from django.shortcuts import get_object_or_404, render
7 from django.template import RequestContext
7 from django.template import RequestContext
8 from django.utils import timezone
8 from django.utils import timezone
9 from django.core import serializers
9 from django.core import serializers
10
10
11 from boards.forms import PostForm, PlainErrorList
11 from boards.forms import PostForm, PlainErrorList
12 from boards.models import Post, Thread, Tag
12 from boards.models import Post, Thread, Tag
13 from boards.utils import datetime_to_epoch
13 from boards.utils import datetime_to_epoch
14 from boards.views.thread import ThreadView
14 from boards.views.thread import ThreadView
15
15
16 __author__ = 'neko259'
16 __author__ = 'neko259'
17
17
18 PARAMETER_TRUNCATED = 'truncated'
18 PARAMETER_TRUNCATED = 'truncated'
19 PARAMETER_TAG = 'tag'
19 PARAMETER_TAG = 'tag'
20 PARAMETER_OFFSET = 'offset'
20 PARAMETER_OFFSET = 'offset'
21 PARAMETER_DIFF_TYPE = 'type'
21 PARAMETER_DIFF_TYPE = 'type'
22
22
23 DIFF_TYPE_HTML = 'html'
23 DIFF_TYPE_HTML = 'html'
24 DIFF_TYPE_JSON = 'json'
24 DIFF_TYPE_JSON = 'json'
25
25
26 STATUS_OK = 'ok'
26 STATUS_OK = 'ok'
27 STATUS_ERROR = 'error'
27 STATUS_ERROR = 'error'
28
28
29 logger = logging.getLogger(__name__)
29 logger = logging.getLogger(__name__)
30
30
31
31
32 @transaction.atomic
32 @transaction.atomic
33 def api_get_threaddiff(request, thread_id, last_update_time):
33 def api_get_threaddiff(request, thread_id, last_update_time):
34 """
34 """
35 Gets posts that were changed or added since time
35 Gets posts that were changed or added since time
36 """
36 """
37
37
38 thread = get_object_or_404(Post, id=thread_id).get_thread()
38 thread = get_object_or_404(Post, id=thread_id).get_thread()
39
39
40 # Add 1 to ensure we don't load the same post over and over
40 # Add 1 to ensure we don't load the same post over and over
41 last_update_timestamp = float(last_update_time) + 1
41 last_update_timestamp = float(last_update_time) + 1
42
42
43 filter_time = datetime.fromtimestamp(last_update_timestamp / 1000000,
43 filter_time = datetime.fromtimestamp(last_update_timestamp / 1000000,
44 timezone.get_current_timezone())
44 timezone.get_current_timezone())
45
45
46 json_data = {
46 json_data = {
47 'added': [],
47 'added': [],
48 'updated': [],
48 'updated': [],
49 'last_update': None,
49 'last_update': None,
50 }
50 }
51 added_posts = Post.objects.filter(thread_new=thread,
51 added_posts = Post.objects.filter(thread_new=thread,
52 pub_time__gt=filter_time) \
52 pub_time__gt=filter_time) \
53 .order_by('pub_time')
53 .order_by('pub_time')
54 updated_posts = Post.objects.filter(thread_new=thread,
54 updated_posts = Post.objects.filter(thread_new=thread,
55 pub_time__lte=filter_time,
55 pub_time__lte=filter_time,
56 last_edit_time__gt=filter_time)
56 last_edit_time__gt=filter_time)
57
57
58 diff_type = request.GET.get(PARAMETER_DIFF_TYPE, DIFF_TYPE_HTML)
58 diff_type = request.GET.get(PARAMETER_DIFF_TYPE, DIFF_TYPE_HTML)
59
59
60 for post in added_posts:
60 for post in added_posts:
61 json_data['added'].append(get_post_data(post.id, diff_type, request))
61 json_data['added'].append(get_post_data(post.id, diff_type, request))
62 for post in updated_posts:
62 for post in updated_posts:
63 json_data['updated'].append(get_post_data(post.id, diff_type, request))
63 json_data['updated'].append(get_post_data(post.id, diff_type, request))
64 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
64 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
65
65
66 return HttpResponse(content=json.dumps(json_data))
66 return HttpResponse(content=json.dumps(json_data))
67
67
68
68
69 def api_add_post(request, opening_post_id):
69 def api_add_post(request, opening_post_id):
70 """
70 """
71 Adds a post and return the JSON response for it
71 Adds a post and return the JSON response for it
72 """
72 """
73
73
74 opening_post = get_object_or_404(Post, id=opening_post_id)
74 opening_post = get_object_or_404(Post, id=opening_post_id)
75
75
76 logger.info('Adding post via api...')
76 logger.info('Adding post via api...')
77
77
78 status = STATUS_OK
78 status = STATUS_OK
79 errors = []
79 errors = []
80
80
81 if request.method == 'POST':
81 if request.method == 'POST':
82 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
82 form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
83 form.session = request.session
83 form.session = request.session
84
84
85 if form.need_to_ban:
85 if form.need_to_ban:
86 # Ban user because he is suspected to be a bot
86 # Ban user because he is suspected to be a bot
87 # _ban_current_user(request)
87 # _ban_current_user(request)
88 status = STATUS_ERROR
88 status = STATUS_ERROR
89 if form.is_valid():
89 if form.is_valid():
90 post = ThreadView().new_post(request, form, opening_post,
90 post = ThreadView().new_post(request, form, opening_post,
91 html_response=False)
91 html_response=False)
92 if not post:
92 if not post:
93 status = STATUS_ERROR
93 status = STATUS_ERROR
94 else:
94 else:
95 logger.info('Added post #%d via api.' % post.id)
95 logger.info('Added post #%d via api.' % post.id)
96 else:
96 else:
97 status = STATUS_ERROR
97 status = STATUS_ERROR
98 errors = form.as_json_errors()
98 errors = form.as_json_errors()
99
99
100 response = {
100 response = {
101 'status': status,
101 'status': status,
102 'errors': errors,
102 'errors': errors,
103 }
103 }
104
104
105 return HttpResponse(content=json.dumps(response))
105 return HttpResponse(content=json.dumps(response))
106
106
107
107
108 def get_post(request, post_id):
108 def get_post(request, post_id):
109 """
109 """
110 Gets the html of a post. Used for popups. Post can be truncated if used
110 Gets the html of a post. Used for popups. Post can be truncated if used
111 in threads list with 'truncated' get parameter.
111 in threads list with 'truncated' get parameter.
112 """
112 """
113
113
114 post = get_object_or_404(Post, id=post_id)
114 post = get_object_or_404(Post, id=post_id)
115
115
116 context = RequestContext(request)
116 context = RequestContext(request)
117 context['post'] = post
117 context['post'] = post
118 if PARAMETER_TRUNCATED in request.GET:
118 if PARAMETER_TRUNCATED in request.GET:
119 context[PARAMETER_TRUNCATED] = True
119 context[PARAMETER_TRUNCATED] = True
120
120
121 # TODO Use dict here
121 # TODO Use dict here
122 return render(request, 'boards/api_post.html', context_instance=context)
122 return render(request, 'boards/api_post.html', context_instance=context)
123
123
124
124
125 # TODO Test this
125 # TODO Test this
126 def api_get_threads(request, count):
126 def api_get_threads(request, count):
127 """
127 """
128 Gets the JSON thread opening posts list.
128 Gets the JSON thread opening posts list.
129 Parameters that can be used for filtering:
129 Parameters that can be used for filtering:
130 tag, offset (from which thread to get results)
130 tag, offset (from which thread to get results)
131 """
131 """
132
132
133 if PARAMETER_TAG in request.GET:
133 if PARAMETER_TAG in request.GET:
134 tag_name = request.GET[PARAMETER_TAG]
134 tag_name = request.GET[PARAMETER_TAG]
135 if tag_name is not None:
135 if tag_name is not None:
136 tag = get_object_or_404(Tag, name=tag_name)
136 tag = get_object_or_404(Tag, name=tag_name)
137 threads = tag.get_threads().filter(archived=False)
137 threads = tag.get_threads().filter(archived=False)
138 else:
138 else:
139 threads = Thread.objects.filter(archived=False)
139 threads = Thread.objects.filter(archived=False)
140
140
141 if PARAMETER_OFFSET in request.GET:
141 if PARAMETER_OFFSET in request.GET:
142 offset = request.GET[PARAMETER_OFFSET]
142 offset = request.GET[PARAMETER_OFFSET]
143 offset = int(offset) if offset is not None else 0
143 offset = int(offset) if offset is not None else 0
144 else:
144 else:
145 offset = 0
145 offset = 0
146
146
147 threads = threads.order_by('-bump_time')
147 threads = threads.order_by('-bump_time')
148 threads = threads[offset:offset + int(count)]
148 threads = threads[offset:offset + int(count)]
149
149
150 opening_posts = []
150 opening_posts = []
151 for thread in threads:
151 for thread in threads:
152 opening_post = thread.get_opening_post()
152 opening_post = thread.get_opening_post()
153
153
154 # TODO Add tags, replies and images count
154 # TODO Add tags, replies and images count
155 opening_posts.append(get_post_data(opening_post.id,
155 post_data = get_post_data(opening_post.id, include_last_update=True)
156 include_last_update=True))
156 post_data['bumpable'] = thread.can_bump()
157 post_data['archived'] = thread.archived
158
159 opening_posts.append(post_data)
157
160
158 return HttpResponse(content=json.dumps(opening_posts))
161 return HttpResponse(content=json.dumps(opening_posts))
159
162
160
163
161 # TODO Test this
164 # TODO Test this
162 def api_get_tags(request):
165 def api_get_tags(request):
163 """
166 """
164 Gets all tags or user tags.
167 Gets all tags or user tags.
165 """
168 """
166
169
167 # TODO Get favorite tags for the given user ID
170 # TODO Get favorite tags for the given user ID
168
171
169 tags = Tag.objects.get_not_empty_tags()
172 tags = Tag.objects.get_not_empty_tags()
170 tag_names = []
173 tag_names = []
171 for tag in tags:
174 for tag in tags:
172 tag_names.append(tag.name)
175 tag_names.append(tag.name)
173
176
174 return HttpResponse(content=json.dumps(tag_names))
177 return HttpResponse(content=json.dumps(tag_names))
175
178
176
179
177 # TODO The result can be cached by the thread last update time
180 # TODO The result can be cached by the thread last update time
178 # TODO Test this
181 # TODO Test this
179 def api_get_thread_posts(request, opening_post_id):
182 def api_get_thread_posts(request, opening_post_id):
180 """
183 """
181 Gets the JSON array of thread posts
184 Gets the JSON array of thread posts
182 """
185 """
183
186
184 opening_post = get_object_or_404(Post, id=opening_post_id)
187 opening_post = get_object_or_404(Post, id=opening_post_id)
185 thread = opening_post.get_thread()
188 thread = opening_post.get_thread()
186 posts = thread.get_replies()
189 posts = thread.get_replies()
187
190
188 json_data = {
191 json_data = {
189 'posts': [],
192 'posts': [],
190 'last_update': None,
193 'last_update': None,
191 }
194 }
192 json_post_list = []
195 json_post_list = []
193
196
194 for post in posts:
197 for post in posts:
195 json_post_list.append(get_post_data(post.id))
198 json_post_list.append(get_post_data(post.id))
196 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
199 json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
197 json_data['posts'] = json_post_list
200 json_data['posts'] = json_post_list
198
201
199 return HttpResponse(content=json.dumps(json_data))
202 return HttpResponse(content=json.dumps(json_data))
200
203
201
204
202 def api_get_post(request, post_id):
205 def api_get_post(request, post_id):
203 """
206 """
204 Gets the JSON of a post. This can be
207 Gets the JSON of a post. This can be
205 used as and API for external clients.
208 used as and API for external clients.
206 """
209 """
207
210
208 post = get_object_or_404(Post, id=post_id)
211 post = get_object_or_404(Post, id=post_id)
209
212
210 json = serializers.serialize("json", [post], fields=(
213 json = serializers.serialize("json", [post], fields=(
211 "pub_time", "_text_rendered", "title", "text", "image",
214 "pub_time", "_text_rendered", "title", "text", "image",
212 "image_width", "image_height", "replies", "tags"
215 "image_width", "image_height", "replies", "tags"
213 ))
216 ))
214
217
215 return HttpResponse(content=json)
218 return HttpResponse(content=json)
216
219
217
220
218 # TODO Remove this method and use post method directly
221 # TODO Remove this method and use post method directly
219 def get_post_data(post_id, format_type=DIFF_TYPE_JSON, request=None,
222 def get_post_data(post_id, format_type=DIFF_TYPE_JSON, request=None,
220 include_last_update=False):
223 include_last_update=False):
221 post = get_object_or_404(Post, id=post_id)
224 post = get_object_or_404(Post, id=post_id)
222 return post.get_post_data(format_type=format_type, request=request,
225 return post.get_post_data(format_type=format_type, request=request,
223 include_last_update=include_last_update)
226 include_last_update=include_last_update)
General Comments 0
You need to be logged in to leave comments. Login now