##// END OF EJS Templates
Continue merge
Continue merge

File last commit:

r1144:a82e4e4d decentral
r1158:05c160e3 decentral
Show More
api.py
246 lines | 6.9 KiB | text/x-python | PythonLexer
import json
import logging
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.core import serializers
from boards.forms import PostForm, PlainErrorList
from boards.models import Post, Thread, Tag
from boards.utils import datetime_to_epoch
from boards.views.thread import ThreadView
from boards.models.user import Notification
__author__ = 'neko259'
PARAMETER_TRUNCATED = 'truncated'
PARAMETER_TAG = 'tag'
PARAMETER_OFFSET = 'offset'
PARAMETER_DIFF_TYPE = 'type'
PARAMETER_POST = 'post'
PARAMETER_UPDATED = 'updated'
PARAMETER_LAST_UPDATE = 'last_update'
PARAMETER_THREAD = 'thread'
PARAMETER_UIDS = 'uids'
DIFF_TYPE_HTML = 'html'
DIFF_TYPE_JSON = 'json'
STATUS_OK = 'ok'
STATUS_ERROR = 'error'
logger = logging.getLogger(__name__)
@transaction.atomic
def api_get_threaddiff(request):
"""
Gets posts that were changed or added since time
"""
thread_id = request.GET.get(PARAMETER_THREAD)
uids_str = request.POST.get(PARAMETER_UIDS).strip()
uids = uids_str.split(' ')
thread = get_object_or_404(Post, id=thread_id).get_thread()
json_data = {
PARAMETER_UPDATED: [],
PARAMETER_LAST_UPDATE: None, # TODO Maybe this can be removed already?
}
posts = Post.objects.filter(threads__in=[thread]).exclude(uid__in=uids)
diff_type = request.GET.get(PARAMETER_DIFF_TYPE, DIFF_TYPE_HTML)
for post in posts:
json_data[PARAMETER_UPDATED].append(get_post_data(post.id, diff_type, request))
json_data[PARAMETER_LAST_UPDATE] = str(thread.last_edit_time)
return HttpResponse(content=json.dumps(json_data))
def api_add_post(request, opening_post_id):
"""
Adds a post and return the JSON response for it
"""
opening_post = get_object_or_404(Post, id=opening_post_id)
logger.info('Adding post via api...')
status = STATUS_OK
errors = []
if request.method == 'POST':
form = PostForm(request.POST, request.FILES, error_class=PlainErrorList)
form.session = request.session
if form.need_to_ban:
# Ban user because he is suspected to be a bot
# _ban_current_user(request)
status = STATUS_ERROR
if form.is_valid():
post = ThreadView().new_post(request, form, opening_post,
html_response=False)
if not post:
status = STATUS_ERROR
else:
logger.info('Added post #%d via api.' % post.id)
else:
status = STATUS_ERROR
errors = form.as_json_errors()
response = {
'status': status,
'errors': errors,
}
return HttpResponse(content=json.dumps(response))
def get_post(request, post_id):
"""
Gets the html of a post. Used for popups. Post can be truncated if used
in threads list with 'truncated' get parameter.
"""
post = get_object_or_404(Post, id=post_id)
truncated = PARAMETER_TRUNCATED in request.GET
return HttpResponse(content=post.get_view(truncated=truncated))
def api_get_threads(request, count):
"""
Gets the JSON thread opening posts list.
Parameters that can be used for filtering:
tag, offset (from which thread to get results)
"""
if PARAMETER_TAG in request.GET:
tag_name = request.GET[PARAMETER_TAG]
if tag_name is not None:
tag = get_object_or_404(Tag, name=tag_name)
threads = tag.get_threads().filter(archived=False)
else:
threads = Thread.objects.filter(archived=False)
if PARAMETER_OFFSET in request.GET:
offset = request.GET[PARAMETER_OFFSET]
offset = int(offset) if offset is not None else 0
else:
offset = 0
threads = threads.order_by('-bump_time')
threads = threads[offset:offset + int(count)]
opening_posts = []
for thread in threads:
opening_post = thread.get_opening_post()
# TODO Add tags, replies and images count
post_data = get_post_data(opening_post.id, include_last_update=True)
post_data['bumpable'] = thread.can_bump()
post_data['archived'] = thread.archived
opening_posts.append(post_data)
return HttpResponse(content=json.dumps(opening_posts))
# TODO Test this
def api_get_tags(request):
"""
Gets all tags or user tags.
"""
# TODO Get favorite tags for the given user ID
tags = Tag.objects.get_not_empty_tags()
term = request.GET.get('term')
if term is not None:
tags = tags.filter(name__contains=term)
tag_names = [tag.name for tag in tags]
return HttpResponse(content=json.dumps(tag_names))
# TODO The result can be cached by the thread last update time
# TODO Test this
def api_get_thread_posts(request, opening_post_id):
"""
Gets the JSON array of thread posts
"""
opening_post = get_object_or_404(Post, id=opening_post_id)
thread = opening_post.get_thread()
posts = thread.get_replies()
json_data = {
'posts': [],
'last_update': None,
}
json_post_list = []
for post in posts:
json_post_list.append(get_post_data(post.id))
json_data['last_update'] = datetime_to_epoch(thread.last_edit_time)
json_data['posts'] = json_post_list
return HttpResponse(content=json.dumps(json_data))
def api_get_notifications(request, username):
last_notification_id_str = request.GET.get('last', None)
last_id = int(last_notification_id_str) if last_notification_id_str is not None else None
posts = Notification.objects.get_notification_posts(username=username,
last=last_id)
json_post_list = []
for post in posts:
json_post_list.append(get_post_data(post.id))
return HttpResponse(content=json.dumps(json_post_list))
def api_get_post(request, post_id):
"""
Gets the JSON of a post. This can be
used as and API for external clients.
"""
post = get_object_or_404(Post, id=post_id)
json = serializers.serialize("json", [post], fields=(
"pub_time", "_text_rendered", "title", "text", "image",
"image_width", "image_height", "replies", "tags"
))
return HttpResponse(content=json)
# TODO Remove this method and use post method directly
def get_post_data(post_id, format_type=DIFF_TYPE_JSON, request=None,
include_last_update=False):
post = get_object_or_404(Post, id=post_id)
return post.get_post_data(format_type=format_type, request=request,
include_last_update=include_last_update)
# TODO Make a separate module for sync API methods
def sync_pull(request):
"""
Return 'get' request response for all posts.
"""
request_xml = request.get('xml')
if request_xml is None:
posts = Post.objects.all()
else:
pass # TODO Parse the XML and get filters from it
xml = Post.objects.generate_response_get(posts)
return HttpResponse(content=xml)