switch to Quart framework

This commit is contained in:
Yusur 2025-08-23 19:04:28 +02:00
parent b97355bb89
commit 73b5b7993f
38 changed files with 1259 additions and 938 deletions

View file

@ -1,29 +1,35 @@
'''
AJAX hooks for the website.
AJAX hooks for the OLD frontend.
2025 DEPRECATED in favor of /v1/ (REST)
DEPRECATED in 0.5 in favor of /v1/ (REST)
'''
from __future__ import annotations
import re
from flask import Blueprint, abort, flash, redirect, request
from quart import Blueprint, abort, flash, redirect, request
from sqlalchemy import delete, insert, select
from .models import Guild, Member, UserBlock, db, User, Post, PostUpvote, username_is_legal
from flask_login import current_user, login_required
current_user: User
from freak import UserLoader
from freak.utils import get_request_form
from .models import Guild, Member, UserBlock, db, User, Post, PostUpvote, username_is_legal
from quart_auth import current_user, login_required
current_user: UserLoader
bp = Blueprint('ajax', __name__)
@bp.route('/username_availability/<username>')
@bp.route('/ajax/username_availability/<username>')
def username_availability(username: str):
async def username_availability(username: str):
is_valid = username_is_legal(username)
if is_valid:
user = db.session.execute(select(User).where(User.username == username)).scalar()
async with db as session:
user = (await session.execute(select(User).where(User.username == username))).scalar()
is_available = user is None or user == current_user
is_available = user is None or user == current_user.user
else:
is_available = False
@ -34,13 +40,14 @@ def username_availability(username: str):
}
@bp.route('/guild_name_availability/<name>')
def guild_name_availability(name: str):
async def guild_name_availability(name: str):
is_valid = username_is_legal(name)
if is_valid:
gd = db.session.execute(select(Guild).where(Guild.name == name)).scalar()
async with db as session:
gd = (await session.execute(select(Guild).where(Guild.name == name))).scalar()
is_available = gd is None
is_available = gd is None
else:
is_available = False
@ -52,101 +59,112 @@ def guild_name_availability(name: str):
@bp.route('/comments/<b32l:id>/upvote', methods=['POST'])
@login_required
def post_upvote(id):
o = request.form['o']
p: Post | None = db.session.execute(select(Post).where(Post.id == id)).scalar()
async def post_upvote(id):
form = await get_request_form()
o = form['o']
async with db as session:
p: Post | None = (await session.execute(select(Post).where(Post.id == id))).scalar()
if p is None:
return { 'status': 'fail', 'message': 'Post not found' }, 404
if o == '1':
db.session.execute(delete(PostUpvote).where(PostUpvote.c.post_id == p.id, PostUpvote.c.voter_id == current_user.id, PostUpvote.c.is_downvote == True))
db.session.execute(insert(PostUpvote).values(post_id = p.id, voter_id = current_user.id, is_downvote = False))
elif o == '0':
db.session.execute(delete(PostUpvote).where(PostUpvote.c.post_id == p.id, PostUpvote.c.voter_id == current_user.id))
elif o == '-1':
db.session.execute(delete(PostUpvote).where(PostUpvote.c.post_id == p.id, PostUpvote.c.voter_id == current_user.id, PostUpvote.c.is_downvote == False))
db.session.execute(insert(PostUpvote).values(post_id = p.id, voter_id = current_user.id, is_downvote = True))
else:
return { 'status': 'fail', 'message': 'Invalid score' }, 400
if p is None:
return { 'status': 'fail', 'message': 'Post not found' }, 404
cur_score = await p.upvoted_by(current_user.user)
db.session.commit()
return { 'status': 'ok', 'count': p.upvotes() }
match (o, cur_score):
case ('1', 0) | ('1', -1):
await session.execute(delete(PostUpvote).where(PostUpvote.c.post_id == p.id, PostUpvote.c.voter_id == current_user.id, PostUpvote.c.is_downvote == True))
await session.execute(insert(PostUpvote).values(post_id = p.id, voter_id = current_user.id, is_downvote = False))
case ('0', _):
await session.execute(delete(PostUpvote).where(PostUpvote.c.post_id == p.id, PostUpvote.c.voter_id == current_user.id))
case ('-1', 1) | ('-1', 0):
await session.execute(delete(PostUpvote).where(PostUpvote.c.post_id == p.id, PostUpvote.c.voter_id == current_user.id, PostUpvote.c.is_downvote == False))
await session.execute(insert(PostUpvote).values(post_id = p.id, voter_id = current_user.id, is_downvote = True))
case ('1', 1) | ('-1', -1):
pass
case _:
await session.rollback()
return { 'status': 'fail', 'message': 'Invalid score' }, 400
await session.commit()
return { 'status': 'ok', 'count': await p.upvotes() }
@bp.route('/@<username>/block', methods=['POST'])
@login_required
def block_user(username):
u = db.session.execute(select(User).where(User.username == username)).scalar()
if u is None:
abort(404)
is_block = 'reverse' not in request.form
is_unblock = request.form.get('reverse') == '1'
async def block_user(username):
form = await get_request_form()
if is_block:
if current_user.has_blocked(u):
flash(f'{u.handle()} is already blocked')
else:
db.session.execute(insert(UserBlock).values(
actor_id = current_user.id,
target_id = u.id
))
db.session.commit()
flash(f'{u.handle()} is now blocked')
if is_unblock:
if not current_user.has_blocked(u):
flash('You didn\'t block this user')
else:
db.session.execute(delete(UserBlock).where(
UserBlock.c.actor_id == current_user.id,
UserBlock.c.target_id == u.id
))
db.session.commit()
flash(f'Removed block on {u.handle()}')
async with db as session:
u = (await session.execute(select(User).where(User.username == username))).scalar()
if u is None:
abort(404)
is_block = 'reverse' not in form
is_unblock = form.get('reverse') == '1'
if is_block:
if current_user.has_blocked(u):
await flash(f'{u.handle()} is already blocked')
else:
await session.execute(insert(UserBlock).values(
actor_id = current_user.id,
target_id = u.id
))
await flash(f'{u.handle()} is now blocked')
if is_unblock:
if not current_user.has_blocked(u):
await flash('You didn\'t block this user')
else:
await session.execute(delete(UserBlock).where(
UserBlock.c.actor_id == current_user.id,
UserBlock.c.target_id == u.id
))
await flash(f'Removed block on {u.handle()}')
return redirect(request.args.get('next', u.url())), 303
@bp.route('/+<name>/subscribe', methods=['POST'])
@login_required
def subscribe_guild(name):
gu = db.session.execute(select(Guild).where(Guild.name == name)).scalar()
async def subscribe_guild(name):
form = await get_request_form()
if gu is None:
abort(404)
is_join = 'reverse' not in request.form
is_leave = request.form.get('reverse') == '1'
async with db as session:
gu = (await session.execute(select(Guild).where(Guild.name == name))).scalar()
membership = db.session.execute(select(Member).where(Member.guild == gu, Member.user_id == current_user.id)).scalar()
if gu is None:
abort(404)
is_join = 'reverse' not in form
is_leave = form.get('reverse') == '1'
if is_join:
if membership is None:
membership = db.session.execute(insert(Member).values(
guild_id = gu.id,
user_id = current_user.id,
is_subscribed = True
).returning(Member)).scalar()
elif membership.is_subscribed == False:
membership.is_subscribed = True
db.session.add(membership)
else:
return redirect(gu.url()), 303
db.session.commit()
flash(f"You are now subscribed to {gu.handle()}")
membership = (await session.execute(select(Member).where(Member.guild == gu, Member.user_id == current_user.id))).scalar()
if is_leave:
if membership is None:
return redirect(gu.url()), 303
elif membership.is_subscribed == True:
membership.is_subscribed = False
db.session.add(membership)
else:
return redirect(gu.url()), 303
if is_join:
if membership is None:
membership = (await session.execute(insert(Member).values(
guild_id = gu.id,
user_id = current_user.id,
is_subscribed = True
).returning(Member))).scalar()
elif membership.is_subscribed == False:
membership.is_subscribed = True
await session.add(membership)
else:
return redirect(gu.url()), 303
await flash(f"You are now subscribed to {gu.handle()}")
db.session.commit()
flash(f"Unsubscribed from {gu.handle()}.")
if is_leave:
if membership is None:
return redirect(gu.url()), 303
elif membership.is_subscribed == True:
membership.is_subscribed = False
await session.add(membership)
else:
return redirect(gu.url()), 303
await session.commit()
await flash(f"Unsubscribed from {gu.handle()}.")
return redirect(gu.url()), 303