Compare commits
No commits in common. "3da30545872b1002339e71389b73ab1578467314" and "57a6810b03e1b5493bb2a69d4bb53319ca2f503f" have entirely different histories.
3da3054587
...
57a6810b03
@ -53,6 +53,7 @@ $ deactivate
|
|||||||
|
|
||||||
when you want to run the server again, make sure to activate the venv first:
|
when you want to run the server again, make sure to activate the venv first:
|
||||||
```bash
|
```bash
|
||||||
|
$ python -m venv .venv
|
||||||
$ source .venv/bin/activate
|
$ source .venv/bin/activate
|
||||||
$ python -m app.run
|
$ python -m app.run
|
||||||
```
|
```
|
||||||
|
@ -76,13 +76,11 @@ def create_app():
|
|||||||
from app.routes.threads import bp as threads_bp
|
from app.routes.threads import bp as threads_bp
|
||||||
from app.routes.users import bp as users_bp
|
from app.routes.users import bp as users_bp
|
||||||
from app.routes.mod import bp as mod_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(app_bp)
|
||||||
app.register_blueprint(topics_bp)
|
app.register_blueprint(topics_bp)
|
||||||
app.register_blueprint(threads_bp)
|
app.register_blueprint(threads_bp)
|
||||||
app.register_blueprint(users_bp)
|
app.register_blueprint(users_bp)
|
||||||
app.register_blueprint(mod_bp)
|
app.register_blueprint(mod_bp)
|
||||||
app.register_blueprint(api_bp)
|
|
||||||
|
|
||||||
app.config['SESSION_COOKIE_SECURE'] = True
|
app.config['SESSION_COOKIE_SECURE'] = True
|
||||||
|
|
||||||
@ -90,12 +88,11 @@ def create_app():
|
|||||||
def make_session_permanent():
|
def make_session_permanent():
|
||||||
session.permanent = True
|
session.permanent = True
|
||||||
|
|
||||||
commit = ""
|
|
||||||
with open('.git/refs/heads/main') as f:
|
|
||||||
commit = f.read().strip()
|
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_constants():
|
def inject_constants():
|
||||||
|
commit = ""
|
||||||
|
with open('.git/refs/heads/main') as f:
|
||||||
|
commit = f.read().strip()
|
||||||
return {
|
return {
|
||||||
"InfoboxIcons": InfoboxIcons,
|
"InfoboxIcons": InfoboxIcons,
|
||||||
"InfoboxHTMLClass": InfoboxHTMLClass,
|
"InfoboxHTMLClass": InfoboxHTMLClass,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from .db import Model, db
|
from .db import Model, db
|
||||||
from .constants import PermissionLevel
|
from .constants import PermissionLevel
|
||||||
import time
|
|
||||||
|
|
||||||
class Users(Model):
|
class Users(Model):
|
||||||
table = "users"
|
table = "users"
|
||||||
@ -220,27 +219,3 @@ class Avatars(Model):
|
|||||||
|
|
||||||
class Subscriptions(Model):
|
class Subscriptions(Model):
|
||||||
table = "subscriptions"
|
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
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
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}
|
|
@ -31,6 +31,7 @@ def thread(slug):
|
|||||||
("thread_id", "=", thread.id),
|
("thread_id", "=", thread.id),
|
||||||
("id", "<=", after_id),
|
("id", "<=", after_id),
|
||||||
])
|
])
|
||||||
|
print(post_position)
|
||||||
page = math.ceil((post_position) / POSTS_PER_PAGE)
|
page = math.ceil((post_position) / POSTS_PER_PAGE)
|
||||||
else:
|
else:
|
||||||
page = max(1, min(page_count, int(request.args.get("page", default = 1))))
|
page = max(1, min(page_count, int(request.args.get("page", default = 1))))
|
||||||
|
@ -72,16 +72,5 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</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>
|
<script src="/static/js/thread.js?v=1"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
function tryFetchUpdate() {
|
function tryFetchUpdate() {
|
||||||
if (!threadEndpoint) return;
|
if (!threadEndpoint) return;
|
||||||
const body = JSON.stringify({'since': now});
|
const body = JSON.stringify({since: now});
|
||||||
fetch(threadEndpoint, {method: "POST", headers: {"Content-Type": "application/json"}, body: body})
|
fetch(threadEndpoint, {method: "POST", headers: {"Content-Type": "application/json"}, body: body})
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(json => {
|
.then(json => {
|
||||||
|
Loading…
Reference in New Issue
Block a user