from flask import Blueprint, request from ..auth import is_logged_in, hard_login_required, get_active_user from ..lib.babycode import babycode_to_html from ..models import APIRateLimits, Posts, Threads, Reactions from ..constants import REACTION_EMOJI bp = Blueprint('api', __name__, url_prefix='/api/') @bp.before_request def ensure_json(): if request.method == 'POST': if not request.is_json: return {'error': 'unsupported media type'}, 415 elif not request.content_length: return {'error': 'body expected'}, 400 elif not isinstance(request.json, dict): return {'error': 'body must be an object'}, 400 @bp.post('/babycode-preview/') @hard_login_required def babycode_preview(): user = get_active_user() if not APIRateLimits.is_allowed(user.id, 'babycode_preview', 5): return {'error': 'too many requests'}, 429 markup = str(request.json.get('markup', '')) if not markup: return {'error': 'markup field missing or invalid type'}, 400 banned_tags = request.json.get('banned_tags', []) if not isinstance(banned_tags, list): return {'error': 'banned_tags field is invalid type'}, 400 rendered = babycode_to_html(markup, banned_tags).result return {'html': rendered} @bp.get('/whoami/') def whoami(): user = get_active_user() if not user: return {} return { 'id': user.id, 'username': user.username, 'display_name': user.display_name, } @bp.post('/toggle-reaction/') @hard_login_required def toggle_reaction(): user = get_active_user() emoji = request.json.get('reaction') if emoji not in REACTION_EMOJI: return {'error': f'invalid reaction string, given: {emoji}'}, 400 post_id = request.json.get('post', -1) post = Posts.find({'id': post_id}) if not post: return {'error': 'post not found'}, 404 thread = Threads.find({'id': post.thread_id}) if not user.can_post_to_thread_or_topic(thread): return {'error': 'thread is locked'}, 403 reaction_obj = { 'user_id': int(user.id), 'post_id': int(post_id), 'reaction_text': emoji, } r = Reactions.find(reaction_obj) if r: # remove r.delete() return {'status': 'ok', 'added': False} else: # add r = Reactions.create(reaction_obj) return {'status': 'ok', 'added': True} @bp.get('/thread-permission/') def thread_permission(thread_id): user = get_active_user() if not user: return {'can_post': False} thread = Threads.find({'id': thread_id}) if not thread: return {'can_post': False} return {'can_post': user.can_post_to_thread_or_topic(thread)}