re-add api route
This commit is contained in:
parent
3c3837b3f2
commit
64e18f16dd
@ -76,11 +76,13 @@ def create_app():
|
||||
from app.routes.threads import bp as threads_bp
|
||||
from app.routes.users import bp as users_bp
|
||||
from app.routes.mod import bp as mod_bp
|
||||
from app.routes.api import bp as api_bp
|
||||
app.register_blueprint(app_bp)
|
||||
app.register_blueprint(topics_bp)
|
||||
app.register_blueprint(threads_bp)
|
||||
app.register_blueprint(users_bp)
|
||||
app.register_blueprint(mod_bp)
|
||||
app.register_blueprint(api_bp)
|
||||
|
||||
app.config['SESSION_COOKIE_SECURE'] = True
|
||||
|
||||
@ -88,11 +90,12 @@ def create_app():
|
||||
def make_session_permanent():
|
||||
session.permanent = True
|
||||
|
||||
@app.context_processor
|
||||
def inject_constants():
|
||||
commit = ""
|
||||
with open('.git/refs/heads/main') as f:
|
||||
commit = f.read().strip()
|
||||
|
||||
@app.context_processor
|
||||
def inject_constants():
|
||||
return {
|
||||
"InfoboxIcons": InfoboxIcons,
|
||||
"InfoboxHTMLClass": InfoboxHTMLClass,
|
||||
|
@ -1,5 +1,6 @@
|
||||
from .db import Model, db
|
||||
from .constants import PermissionLevel
|
||||
import time
|
||||
|
||||
class Users(Model):
|
||||
table = "users"
|
||||
@ -219,3 +220,27 @@ class Avatars(Model):
|
||||
|
||||
class Subscriptions(Model):
|
||||
table = "subscriptions"
|
||||
|
||||
class APIRateLimits(Model):
|
||||
table = 'api_rate_limits'
|
||||
|
||||
@classmethod
|
||||
def is_allowed(cls, user_id, method, seconds):
|
||||
q = """
|
||||
SELECT logged_at FROM api_rate_limits
|
||||
WHERE user_id = ? AND method = ?
|
||||
ORDER BY logged_at DESC LIMIT 1"""
|
||||
last_call = db.fetch_one(q, user_id, method)
|
||||
if last_call is None or (int(time.time()) - int(last_call['logged_at']) >= seconds):
|
||||
with db.transaction():
|
||||
db.query(
|
||||
'DELETE FROM api_rate_limits WHERE user_id = ? AND method = ?',
|
||||
user_id, method
|
||||
)
|
||||
db.query(
|
||||
'INSERT INTO api_rate_limits (user_id, method) VALUES (?, ?)',
|
||||
user_id, method
|
||||
)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
43
app/routes/api.py
Normal file
43
app/routes/api.py
Normal file
@ -0,0 +1,43 @@
|
||||
from flask import Blueprint, request, url_for
|
||||
from ..lib.babycode import babycode_to_html
|
||||
from .users import is_logged_in, get_active_user
|
||||
from ..models import APIRateLimits, Threads
|
||||
from ..db import db
|
||||
|
||||
bp = Blueprint("api", __name__, url_prefix="/api/")
|
||||
|
||||
|
||||
@bp.post('/thread-updates/<thread_id>')
|
||||
def thread_updates(thread_id):
|
||||
thread = Threads.find({'id': thread_id})
|
||||
if not thread:
|
||||
return {'error': 'no such thread'}, 404
|
||||
target_time = request.json.get('since')
|
||||
if not target_time:
|
||||
return {'error': 'missing parameter "since"'}, 400
|
||||
try:
|
||||
target_time = int(target_time)
|
||||
except:
|
||||
return {'error': 'parameter "since" is not/cannot be converted to a number'}, 400
|
||||
|
||||
q = 'SELECT id FROM posts WHERE thread_id = ? AND posts.created_at > ? ORDER BY posts.created_at ASC LIMIT 1'
|
||||
new_post = db.fetch_one(q, thread_id, target_time)
|
||||
if not new_post:
|
||||
return {'status': 'none'}
|
||||
|
||||
url = url_for('threads.thread', slug=thread.slug, after=new_post['id'], _anchor=f'post-{new_post['id']}')
|
||||
return {'status': 'new_post', 'url': url}
|
||||
|
||||
|
||||
@bp.post('/babycode-preview')
|
||||
def babycode_preview():
|
||||
if not is_logged_in():
|
||||
return {'error': 'not authorized'}, 401
|
||||
user = get_active_user()
|
||||
if not APIRateLimits.is_allowed(user.id, 'babycode_preview', 5):
|
||||
return {'error': 'too many requests'}, 429
|
||||
markup = request.json.get('markup')
|
||||
if not markup or not isinstance(markup, str):
|
||||
return {'error': 'markup field missing or invalid type'}, 400
|
||||
rendered = babycode_to_html(markup)
|
||||
return {'html': rendered}
|
@ -72,5 +72,16 @@
|
||||
</span>
|
||||
</div>
|
||||
</dialog>
|
||||
<input type='hidden' id='thread-subscribe-endpoint' value='{{ url_for('api.thread_updates', thread_id=thread.id) }}'>
|
||||
<div id="new-post-notification" class="new-concept-notification hidden">
|
||||
<div class="new-notification-content">
|
||||
<p>New post in thread!</p>
|
||||
<span class="notification-buttons">
|
||||
<button id="dismiss-new-post-button">Dismiss</button>
|
||||
<a class="linkbutton" id="go-to-new-post-button">View post</a>
|
||||
<button id="unsub-new-post-button">Stop updates</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/thread.js?v=1"></script>
|
||||
{% endblock %}
|
||||
|
Loading…
Reference in New Issue
Block a user