basic posting

This commit is contained in:
2026-04-16 00:01:18 +03:00
parent d0daaf4494
commit d6b44da6c2
6 changed files with 64 additions and 8 deletions

View File

@@ -1,6 +1,7 @@
from flask import session, flash from flask import session, flash, redirect, url_for
from .models import Sessions, Users from .models import Sessions, Users
from argon2 import PasswordHasher from argon2 import PasswordHasher
from functools import wraps
import secrets import secrets
import time import time
@@ -15,7 +16,7 @@ def verify(expected, given):
except: except:
return False return False
def is_logged_in(): def is_logged_in() -> bool:
if 'pyrom_session_key' not in session: if 'pyrom_session_key' not in session:
return False return False
sess = Sessions.find({'key': session['pyrom_session_key']}) sess = Sessions.find({'key': session['pyrom_session_key']})
@@ -28,7 +29,7 @@ def is_logged_in():
return False return False
return True return True
def get_active_user(): def get_active_user() -> Users | None:
if not is_logged_in(): if not is_logged_in():
return None return None
@@ -41,3 +42,12 @@ def create_session(user_id):
'user_id': user_id, 'user_id': user_id,
'expires_at': int(time.time()) + (31 * 24 * 60 * 60), 'expires_at': int(time.time()) + (31 * 24 * 60 * 60),
}) })
# annotations
def login_required(view_func):
@wraps(view_func)
def wrapper(*args, **kwargs):
if not is_logged_in():
return redirect(url_for('users.log_in_page'))
return view_func(*args, **kwargs)
return wrapper

View File

@@ -267,6 +267,39 @@ class Posts(Model):
q = f'{self.FULL_POSTS_QUERY} WHERE posts.id = ?' q = f'{self.FULL_POSTS_QUERY} WHERE posts.id = ?'
return db.fetch_one(q, self.id) return db.fetch_one(q, self.id)
@classmethod
def new(cls, user_id: int, thread_id: int, content: str, language: str = 'babycode') -> Posts:
from .lib.babycode import babycode_to_html, babycode_to_rssxml, BABYCODE_VERSION
html_content = babycode_to_html(content)
rssxml_content = babycode_to_rssxml(content)
with db.transaction():
post = Posts.create({
'thread_id': thread_id,
'user_id': user_id,
'current_revision_id': None,
})
revision = PostHistory.create({
'post_id': post.id,
'content': html_content.result,
'content_rss': rssxml_content,
'is_initial_revision': True,
'original_markup': content,
'markup_language': language,
'format_version': BABYCODE_VERSION,
})
for mention in html_content.mentions:
Mentions.create({
'revision_id': revision.id,
'mentioned_iser_id': mention['mentioned_iser_id'],
'start_index': mention['start'],
'end_index': mention['end'],
})
post.update({'current_revision_id': revision.id})
return post
class PostHistory(Model): class PostHistory(Model):
table = 'post_history' table = 'post_history'

View File

@@ -1,5 +1,5 @@
from flask import Blueprint, redirect, url_for, render_template, request, abort from flask import Blueprint, redirect, url_for, render_template, request, abort
from ..auth import login_required, get_active_user
from ..models import Threads, Posts, Topics, Users, Reactions from ..models import Threads, Posts, Topics, Users, Reactions
import math import math
@@ -35,8 +35,17 @@ def thread(slug):
return render_template('threads/thread.html', thread=thread, posts=thread.get_posts(PER_PAGE, page), page=page, page_count=page_count, topic=topic, started_by=started_by, topics=Topics.get_list(), Reactions=Reactions) return render_template('threads/thread.html', thread=thread, posts=thread.get_posts(PER_PAGE, page), page=page, page_count=page_count, topic=topic, started_by=started_by, topics=Topics.get_list(), Reactions=Reactions)
@bp.post('/<slug>/reply') @bp.post('/<slug>/reply')
@login_required
def reply(slug): def reply(slug):
return 'stub' user = get_active_user()
thread = Threads.find({'slug': slug})
if not thread:
abort(404)
if thread.locked() and not user.is_mod():
# TODO: flash
return redirect(url_for('.thread', slug=slug))
post = Posts.new(user.id, thread.id, request.form.get('babycode_content'))
return redirect(url_for('.thread', slug=slug, after=post.id, _anchor=f'post-{post.id}'))
@bp.get('/<slug>/feed.atom') @bp.get('/<slug>/feed.atom')
def feed(slug): def feed(slug):

View File

@@ -5,8 +5,12 @@ from ..models import Users
bp = Blueprint('users', __name__, url_prefix='/users/') bp = Blueprint('users', __name__, url_prefix='/users/')
@bp.get('/log-in')
def log_in_page():
return 'stub/please log in'
@bp.post('/log-in') @bp.post('/log-in')
def log_in(): def log_in_post():
user = Users.find({'username': request.form['username']}) user = Users.find({'username': request.form['username']})
if not user: if not user:
return "no user" return "no user"

View File

@@ -101,7 +101,7 @@
</span> </span>
<a href="##">babycode help</a> <a href="##">babycode help</a>
</span> </span>
<textarea name="babycode-content" class="babycode-editor" placeholder="{{placeholder}}" required>{{ prefill }}</textarea> <textarea name="babycode_content" class="babycode-editor" placeholder="{{placeholder}}" required>{{ prefill }}</textarea>
{%- endif -%} {%- endif -%}
{%- endcall -%} {%- endcall -%}
{%- endmacro %} {%- endmacro %}

View File

@@ -14,7 +14,7 @@
</ul> </ul>
{%- endwith -%} {%- endwith -%}
{%- else -%} {%- else -%}
<form class="horizontal wrap" method="POST" action="{{url_for('users.log_in')}}"> <form class="horizontal wrap" method="POST" action="{{url_for('users.log_in_post')}}">
<input type="hidden" name="return_to" value="{{request.path}}"> <input type="hidden" name="return_to" value="{{request.path}}">
<input type="text" placeholder="Username" name="username" autocomplete="username" required> <input type="text" placeholder="Username" name="username" autocomplete="username" required>
<input type="password" placeholder="Password" name="password" autocomplete="current-password" required> <input type="password" placeholder="Password" name="password" autocomplete="current-password" required>