mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
add language choices to UI #51
This commit is contained in:
parent
29c2a05d38
commit
af4dee7ea3
24 changed files with 287 additions and 59 deletions
|
@ -21,11 +21,11 @@ from app.activitypub.util import public_key, users_total, active_half_year, acti
|
|||
upvote_post, delete_post_or_comment, community_members, \
|
||||
user_removed_from_remote_server, create_post, create_post_reply, update_post_reply_from_activity, \
|
||||
update_post_from_activity, undo_vote, undo_downvote, post_to_page, get_redis_connection, find_reported_object, \
|
||||
process_report, ensure_domains_match
|
||||
process_report, ensure_domains_match, can_edit, can_delete
|
||||
from app.utils import gibberish, get_setting, is_image_url, allowlist_html, render_template, \
|
||||
domain_from_url, markdown_to_html, community_membership, ap_datetime, ip_address, can_downvote, \
|
||||
can_upvote, can_create_post, awaken_dormant_instance, shorten_string, can_create_post_reply, sha256_digest, \
|
||||
community_moderators, blocked_users
|
||||
community_moderators
|
||||
import werkzeug.exceptions
|
||||
|
||||
|
||||
|
@ -933,17 +933,23 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
if request_json['object']['type'] == 'Page': # Editing a post
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if post:
|
||||
update_post_from_activity(post, request_json)
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
activity_log.result = 'success'
|
||||
if can_edit(request_json['actor'], post):
|
||||
update_post_from_activity(post, request_json)
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Edit attempt denied'
|
||||
else:
|
||||
activity_log.exception_message = 'Post not found'
|
||||
elif request_json['object']['type'] == 'Note': # Editing a reply
|
||||
reply = PostReply.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if reply:
|
||||
update_post_reply_from_activity(reply, request_json)
|
||||
announce_activity_to_followers(reply.community, reply.author, request_json)
|
||||
activity_log.result = 'success'
|
||||
if can_edit(request_json['actor'], reply):
|
||||
update_post_reply_from_activity(reply, request_json)
|
||||
announce_activity_to_followers(reply.community, reply.author, request_json)
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Edit attempt denied'
|
||||
else:
|
||||
activity_log.exception_message = 'PostReply not found'
|
||||
elif request_json['type'] == 'Delete':
|
||||
|
@ -954,28 +960,34 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
post = Post.query.filter_by(ap_id=ap_id).first()
|
||||
# Delete post
|
||||
if post:
|
||||
if post.url and post.cross_posts is not None:
|
||||
old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all()
|
||||
post.cross_posts.clear()
|
||||
for ocp in old_cross_posts:
|
||||
if ocp.cross_posts is not None:
|
||||
ocp.cross_posts.remove(post.id)
|
||||
post.delete_dependencies()
|
||||
post.community.post_count -= 1
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
db.session.delete(post)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
if can_delete(request_json['actor'], post):
|
||||
if post.url and post.cross_posts is not None:
|
||||
old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all()
|
||||
post.cross_posts.clear()
|
||||
for ocp in old_cross_posts:
|
||||
if ocp.cross_posts is not None:
|
||||
ocp.cross_posts.remove(post.id)
|
||||
post.delete_dependencies()
|
||||
post.community.post_count -= 1
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
db.session.delete(post)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Delete attempt denied'
|
||||
else:
|
||||
# Delete PostReply
|
||||
reply = PostReply.query.filter_by(ap_id=ap_id).first()
|
||||
if reply:
|
||||
reply.body_html = '<p><em>deleted</em></p>'
|
||||
reply.body = 'deleted'
|
||||
reply.post.reply_count -= 1
|
||||
announce_activity_to_followers(reply.community, reply.author, request_json)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
if can_delete(request_json['actor'], reply):
|
||||
reply.body_html = '<p><em>deleted</em></p>'
|
||||
reply.body = 'deleted'
|
||||
reply.post.reply_count -= 1
|
||||
announce_activity_to_followers(reply.community, reply.author, request_json)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Delete attempt denied'
|
||||
else:
|
||||
# Delete User
|
||||
user = find_actor_or_create(ap_id, create_if_not_found=False)
|
||||
|
@ -1399,7 +1411,11 @@ def comment_ap(comment_id):
|
|||
'mediaType': 'text/html',
|
||||
'published': ap_datetime(reply.created_at),
|
||||
'distinguished': False,
|
||||
'audience': reply.community.profile_id()
|
||||
'audience': reply.community.profile_id(),
|
||||
'language': {
|
||||
'identifier': reply.language_code(),
|
||||
'name': reply.language_name()
|
||||
}
|
||||
}
|
||||
if reply.edited_at:
|
||||
reply_data['updated'] = ap_datetime(reply.edited_at)
|
||||
|
|
|
@ -156,7 +156,11 @@ def post_to_activity(post: Post, community: Community):
|
|||
"sensitive": post.nsfw or post.nsfl,
|
||||
"published": ap_datetime(post.created_at),
|
||||
"stickied": post.sticky,
|
||||
"audience": f"https://{current_app.config['SERVER_NAME']}/c/{community.name}"
|
||||
"audience": f"https://{current_app.config['SERVER_NAME']}/c/{community.name}",
|
||||
'language': {
|
||||
'identifier': post.language_code(),
|
||||
'name': post.language_name()
|
||||
}
|
||||
},
|
||||
"cc": [
|
||||
f"https://{current_app.config['SERVER_NAME']}/c/{community.name}"
|
||||
|
@ -756,6 +760,11 @@ def post_json_to_model(activity_log, post_json, user, community) -> Post:
|
|||
domain.post_count += 1
|
||||
post.domain = domain
|
||||
|
||||
if 'language' in post_json:
|
||||
language = find_language_or_create(post_json['language']['identifier'], post_json['language']['name'])
|
||||
if language:
|
||||
post.language_id = language.id
|
||||
|
||||
if post is not None:
|
||||
if 'image' in post_json and post.image is None:
|
||||
image = File(source_url=post_json['image']['url'])
|
||||
|
@ -1312,6 +1321,11 @@ def create_post_reply(activity_log: ActivityPubLog, community: Community, in_rep
|
|||
elif 'content' in request_json['object']: # Kbin
|
||||
post_reply.body_html = allowlist_html(request_json['object']['content'])
|
||||
post_reply.body = ''
|
||||
if 'language' in request_json['object'] and isinstance(request_json['object']['language'], dict):
|
||||
language = find_language_or_create(request_json['object']['language']['identifier'],
|
||||
request_json['object']['language']['name'])
|
||||
post_reply.language_id = language.id
|
||||
|
||||
if post_id is not None:
|
||||
# Discard post_reply if it contains certain phrases. Good for stopping spam floods.
|
||||
if post_reply.body:
|
||||
|
@ -1579,6 +1593,10 @@ def update_post_reply_from_activity(reply: PostReply, request_json: dict):
|
|||
elif 'content' in request_json['object']:
|
||||
reply.body_html = allowlist_html(request_json['object']['content'])
|
||||
reply.body = ''
|
||||
# Language
|
||||
if 'language' in request_json['object'] and isinstance(request_json['object']['language'], dict):
|
||||
language = find_language_or_create(request_json['object']['language']['identifier'], request_json['object']['language']['name'])
|
||||
reply.language_id = language.id
|
||||
reply.edited_at = utcnow()
|
||||
db.session.commit()
|
||||
|
||||
|
@ -1636,7 +1654,7 @@ def update_post_from_activity(post: Post, request_json: dict):
|
|||
db.session.add(image)
|
||||
post.image = image
|
||||
elif is_video_url(post.url):
|
||||
post.type == POST_TYPE_VIDEO
|
||||
post.type = POST_TYPE_VIDEO
|
||||
image = File(source_url=post.url)
|
||||
db.session.add(image)
|
||||
post.image = image
|
||||
|
@ -2049,3 +2067,16 @@ def ensure_domains_match(activity: dict) -> bool:
|
|||
|
||||
return False
|
||||
|
||||
|
||||
def can_edit(user_ap_id, post):
|
||||
user = find_actor_or_create(user_ap_id, create_if_not_found=False)
|
||||
if user:
|
||||
if post.user_id == user.id:
|
||||
return True
|
||||
if post.community.is_moderator(user) or post.community.is_owner(user) or post.community.is_instance_admin(user):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def can_delete(user_ap_id, post):
|
||||
return can_edit(user_ap_id, post)
|
||||
|
|
|
@ -87,6 +87,7 @@ def register(app):
|
|||
db.session.add(Settings(name='allow_remote_image_posts', value=json.dumps(True)))
|
||||
db.session.add(Settings(name='federation', value=json.dumps(True)))
|
||||
db.session.add(Language(name='Undetermined', code='und'))
|
||||
db.session.add(Language(name='English', code='en'))
|
||||
banned_instances = ['anonib.al','lemmygrad.ml', 'gab.com', 'rqd2.net', 'exploding-heads.com', 'hexbear.net',
|
||||
'threads.net', 'noauthority.social', 'pieville.net', 'links.hackliberty.org',
|
||||
'poa.st', 'freespeechextremist.com', 'bae.st', 'nicecrew.digital', 'detroitriotcity.com',
|
||||
|
|
|
@ -100,6 +100,7 @@ class CreateDiscussionForm(FlaskForm):
|
|||
nsfw = BooleanField(_l('NSFW'))
|
||||
nsfl = BooleanField(_l('Gore/gross'))
|
||||
notify_author = BooleanField(_l('Notify about replies'))
|
||||
language_id = SelectField(_l('Language'), validators=[DataRequired()], coerce=int, render_kw={'class': 'form-select'})
|
||||
submit = SubmitField(_l('Save'))
|
||||
|
||||
|
||||
|
@ -113,6 +114,7 @@ class CreateLinkForm(FlaskForm):
|
|||
nsfw = BooleanField(_l('NSFW'))
|
||||
nsfl = BooleanField(_l('Gore/gross'))
|
||||
notify_author = BooleanField(_l('Notify about replies'))
|
||||
language_id = SelectField(_l('Language'), validators=[DataRequired()], coerce=int, render_kw={'class': 'form-select'})
|
||||
submit = SubmitField(_l('Save'))
|
||||
|
||||
def validate(self, extra_validators=None) -> bool:
|
||||
|
@ -133,6 +135,7 @@ class CreateVideoForm(FlaskForm):
|
|||
nsfw = BooleanField(_l('NSFW'))
|
||||
nsfl = BooleanField(_l('Gore/gross'))
|
||||
notify_author = BooleanField(_l('Notify about replies'))
|
||||
language_id = SelectField(_l('Language'), validators=[DataRequired()], coerce=int, render_kw={'class': 'form-select'})
|
||||
submit = SubmitField(_l('Save'))
|
||||
|
||||
def validate(self, extra_validators=None) -> bool:
|
||||
|
@ -153,6 +156,7 @@ class CreateImageForm(FlaskForm):
|
|||
nsfw = BooleanField(_l('NSFW'))
|
||||
nsfl = BooleanField(_l('Gore/gross'))
|
||||
notify_author = BooleanField(_l('Notify about replies'))
|
||||
language_id = SelectField(_l('Language'), validators=[DataRequired()], coerce=int, render_kw={'class': 'form-select'})
|
||||
submit = SubmitField(_l('Save'))
|
||||
|
||||
def validate(self, extra_validators=None) -> bool:
|
||||
|
|
|
@ -33,7 +33,7 @@ from app.utils import get_setting, render_template, allowlist_html, markdown_to_
|
|||
request_etag_matches, return_304, instance_banned, can_create_post, can_upvote, can_downvote, user_filters_posts, \
|
||||
joined_communities, moderating_communities, blocked_domains, mimetype_from_url, blocked_instances, \
|
||||
community_moderators, communities_banned_from, show_ban_message, recently_upvoted_posts, recently_downvoted_posts, \
|
||||
blocked_users, post_ranking, languages_for_form
|
||||
blocked_users, post_ranking, languages_for_form, english_language_id
|
||||
from feedgen.feed import FeedGenerator
|
||||
from datetime import timezone, timedelta
|
||||
|
||||
|
@ -488,6 +488,8 @@ def add_discussion_post(actor):
|
|||
if not community_in_list(community.id, form.communities.choices):
|
||||
form.communities.choices.append((community.id, community.display_name()))
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if not can_create_post(current_user, community):
|
||||
abort(401)
|
||||
|
||||
|
@ -515,6 +517,7 @@ def add_discussion_post(actor):
|
|||
else:
|
||||
form.communities.data = community.id
|
||||
form.notify_author.data = True
|
||||
form.language_id.data = current_user.language_id if current_user.language_id else english_language_id()
|
||||
if community.posting_warning:
|
||||
flash(community.posting_warning)
|
||||
|
||||
|
@ -551,6 +554,8 @@ def add_image_post(actor):
|
|||
if not community_in_list(community.id, form.communities.choices):
|
||||
form.communities.choices.append((community.id, community.display_name()))
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if not can_create_post(current_user, community):
|
||||
abort(401)
|
||||
|
||||
|
@ -594,6 +599,7 @@ def add_image_post(actor):
|
|||
else:
|
||||
form.communities.data = community.id
|
||||
form.notify_author.data = True
|
||||
form.language_id.data = current_user.language_id if current_user.language_id else english_language_id()
|
||||
|
||||
return render_template('community/add_image_post.html', title=_('Add post to community'), form=form, community=community,
|
||||
markdown_editor=current_user.markdown_editor, low_bandwidth=False, actor=actor,
|
||||
|
@ -628,6 +634,8 @@ def add_link_post(actor):
|
|||
if not community_in_list(community.id, form.communities.choices):
|
||||
form.communities.choices.append((community.id, community.display_name()))
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if not can_create_post(current_user, community):
|
||||
abort(401)
|
||||
|
||||
|
@ -671,6 +679,7 @@ def add_link_post(actor):
|
|||
else:
|
||||
form.communities.data = community.id
|
||||
form.notify_author.data = True
|
||||
form.language_id.data = current_user.language_id if current_user.language_id else english_language_id()
|
||||
|
||||
return render_template('community/add_link_post.html', title=_('Add post to community'), form=form, community=community,
|
||||
markdown_editor=current_user.markdown_editor, low_bandwidth=False, actor=actor,
|
||||
|
@ -705,6 +714,8 @@ def add_video_post(actor):
|
|||
if not community_in_list(community.id, form.communities.choices):
|
||||
form.communities.choices.append((community.id, community.display_name()))
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if not can_create_post(current_user, community):
|
||||
abort(401)
|
||||
|
||||
|
@ -748,6 +759,7 @@ def add_video_post(actor):
|
|||
else:
|
||||
form.communities.data = community.id
|
||||
form.notify_author.data = True
|
||||
form.language_id.data = current_user.language_id if current_user.language_id else english_language_id()
|
||||
|
||||
return render_template('community/add_video_post.html', title=_('Add post to community'), form=form, community=community,
|
||||
markdown_editor=current_user.markdown_editor, low_bandwidth=False, actor=actor,
|
||||
|
@ -780,7 +792,11 @@ def federate_post(community, post):
|
|||
'nsfl': post.nsfl,
|
||||
'stickied': post.sticky,
|
||||
'published': ap_datetime(utcnow()),
|
||||
'audience': community.ap_profile_id
|
||||
'audience': community.ap_profile_id,
|
||||
'language': {
|
||||
'identifier': post.language_code(),
|
||||
'name': post.language_name()
|
||||
}
|
||||
}
|
||||
create = {
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/create/{gibberish(15)}",
|
||||
|
@ -870,7 +886,11 @@ def federate_post_to_user_followers(post):
|
|||
'sensitive': post.nsfw,
|
||||
'nsfl': post.nsfl,
|
||||
'stickied': post.sticky,
|
||||
'published': ap_datetime(utcnow())
|
||||
'published': ap_datetime(utcnow()),
|
||||
'language': {
|
||||
'identifier': post.language_code(),
|
||||
'name': post.language_name()
|
||||
}
|
||||
}
|
||||
create = {
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/create/{gibberish(15)}",
|
||||
|
|
|
@ -216,6 +216,8 @@ def save_post(form, post: Post, type: str):
|
|||
post.nsfw = form.nsfw.data
|
||||
post.nsfl = form.nsfl.data
|
||||
post.notify_author = form.notify_author.data
|
||||
post.language_id = form.language_id.data
|
||||
current_user.language_id = form.language_id.data
|
||||
if type == '' or type == 'discussion':
|
||||
post.title = form.discussion_title.data
|
||||
post.body = form.discussion_body.data
|
||||
|
|
|
@ -944,10 +944,9 @@ class Post(db.Model):
|
|||
up_votes = db.Column(db.Integer, default=0)
|
||||
down_votes = db.Column(db.Integer, default=0)
|
||||
ranking = db.Column(db.Integer, default=0, index=True) # used for 'hot' ranking
|
||||
language = db.Column(db.String(10))
|
||||
edited_at = db.Column(db.DateTime)
|
||||
reports = db.Column(db.Integer, default=0) # how many times this post has been reported. Set to -1 to ignore reports
|
||||
language_id = db.Column(db.Integer, index=True)
|
||||
language_id = db.Column(db.Integer, db.ForeignKey('language.id'), index=True)
|
||||
cross_posts = db.Column(MutableList.as_mutable(ARRAY(db.Integer)))
|
||||
tags = db.relationship('Tag', lazy='dynamic', secondary=post_tag, backref=db.backref('posts', lazy='dynamic'))
|
||||
|
||||
|
@ -962,6 +961,7 @@ class Post(db.Model):
|
|||
author = db.relationship('User', lazy='joined', overlaps='posts', foreign_keys=[user_id])
|
||||
community = db.relationship('Community', lazy='joined', overlaps='posts', foreign_keys=[community_id])
|
||||
replies = db.relationship('PostReply', lazy='dynamic', backref='post')
|
||||
language = db.relationship('Language', foreign_keys=[language_id])
|
||||
|
||||
def is_local(self):
|
||||
return self.ap_id is None or self.ap_id.startswith('https://' + current_app.config['SERVER_NAME'])
|
||||
|
@ -1006,6 +1006,18 @@ class Post(db.Model):
|
|||
NotificationSubscription.type == NOTIF_POST).first()
|
||||
return existing_notification is not None
|
||||
|
||||
def language_code(self):
|
||||
if self.language_id:
|
||||
return self.language.code
|
||||
else:
|
||||
return 'en'
|
||||
|
||||
def language_name(self):
|
||||
if self.language_id:
|
||||
return self.language.name
|
||||
else:
|
||||
return 'English'
|
||||
|
||||
|
||||
class PostReply(db.Model):
|
||||
query_class = FullTextSearchQuery
|
||||
|
@ -1033,7 +1045,7 @@ class PostReply(db.Model):
|
|||
up_votes = db.Column(db.Integer, default=0)
|
||||
down_votes = db.Column(db.Integer, default=0)
|
||||
ranking = db.Column(db.Float, default=0.0, index=True) # used for 'hot' sorting
|
||||
language = db.Column(db.String(10))
|
||||
language_id = db.Column(db.Integer, db.ForeignKey('language.id'), index=True)
|
||||
edited_at = db.Column(db.DateTime)
|
||||
reports = db.Column(db.Integer, default=0) # how many times this post has been reported. Set to -1 to ignore reports
|
||||
|
||||
|
@ -1045,6 +1057,19 @@ class PostReply(db.Model):
|
|||
|
||||
author = db.relationship('User', lazy='joined', foreign_keys=[user_id], single_parent=True, overlaps="post_replies")
|
||||
community = db.relationship('Community', lazy='joined', overlaps='replies', foreign_keys=[community_id])
|
||||
language = db.relationship('Language', foreign_keys=[language_id])
|
||||
|
||||
def language_code(self):
|
||||
if self.language_id:
|
||||
return self.language.code
|
||||
else:
|
||||
return 'en'
|
||||
|
||||
def language_name(self):
|
||||
if self.language_id:
|
||||
return self.language.name
|
||||
else:
|
||||
return 'English'
|
||||
|
||||
def is_local(self):
|
||||
return self.ap_id is None or self.ap_id.startswith('https://' + current_app.config['SERVER_NAME'])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from flask_wtf import FlaskForm
|
||||
from wtforms import TextAreaField, SubmitField, BooleanField, StringField
|
||||
from wtforms.fields.choices import SelectField
|
||||
from wtforms.validators import DataRequired, Length, ValidationError
|
||||
from flask_babel import _, lazy_gettext as _l
|
||||
|
||||
|
@ -9,6 +10,7 @@ from app.utils import MultiCheckboxField
|
|||
class NewReplyForm(FlaskForm):
|
||||
body = TextAreaField(_l('Body'), render_kw={'placeholder': 'What are your thoughts?', 'rows': 5}, validators={DataRequired(), Length(min=1, max=5000)})
|
||||
notify_author = BooleanField(_l('Notify about replies'))
|
||||
language_id = SelectField(_l('Language'), validators=[DataRequired()], coerce=int, render_kw={'class': 'form-select language-float-right'})
|
||||
submit = SubmitField(_l('Comment'))
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@ from app.utils import get_setting, render_template, allowlist_html, markdown_to_
|
|||
request_etag_matches, ip_address, user_ip_banned, instance_banned, can_downvote, can_upvote, post_ranking, \
|
||||
reply_already_exists, reply_is_just_link_to_gif_reaction, confidence, moderating_communities, joined_communities, \
|
||||
blocked_instances, blocked_domains, community_moderators, blocked_phrases, show_ban_message, recently_upvoted_posts, \
|
||||
recently_downvoted_posts, recently_upvoted_post_replies, recently_downvoted_post_replies, reply_is_stupid
|
||||
recently_downvoted_posts, recently_upvoted_post_replies, recently_downvoted_post_replies, reply_is_stupid, \
|
||||
languages_for_form, english_language_id
|
||||
|
||||
|
||||
def show_post(post_id: int):
|
||||
|
@ -58,6 +59,7 @@ def show_post(post_id: int):
|
|||
|
||||
# handle top-level comments/replies
|
||||
form = NewReplyForm()
|
||||
form.language_id.choices = languages_for_form()
|
||||
if current_user.is_authenticated and current_user.verified and form.validate_on_submit():
|
||||
|
||||
if not post.comments_enabled:
|
||||
|
@ -98,11 +100,12 @@ def show_post(post_id: int):
|
|||
reply = PostReply(user_id=current_user.id, post_id=post.id, community_id=community.id, body=form.body.data,
|
||||
body_html=markdown_to_html(form.body.data), body_html_safe=True,
|
||||
from_bot=current_user.bot, nsfw=post.nsfw, nsfl=post.nsfl,
|
||||
notify_author=form.notify_author.data, instance_id=1)
|
||||
notify_author=form.notify_author.data, language_id=form.language_id.data, instance_id=1)
|
||||
|
||||
post.last_active = community.last_active = utcnow()
|
||||
post.reply_count += 1
|
||||
community.post_reply_count += 1
|
||||
current_user.language_id = form.language_id.data
|
||||
|
||||
db.session.add(reply)
|
||||
db.session.commit()
|
||||
|
@ -163,7 +166,11 @@ def show_post(post_id: int):
|
|||
'href': post.author.public_url(),
|
||||
'name': post.author.mention_tag(),
|
||||
'type': 'Mention'
|
||||
}]
|
||||
}],
|
||||
'language': {
|
||||
'identifier': reply.language_code(),
|
||||
'name': reply.language_name()
|
||||
}
|
||||
}
|
||||
create_json = {
|
||||
'type': 'Create',
|
||||
|
@ -222,6 +229,7 @@ def show_post(post_id: int):
|
|||
else:
|
||||
replies = post_replies(post.id, sort)
|
||||
form.notify_author.data = True
|
||||
form.language_id.data = current_user.language_id if current_user.language_id else english_language_id()
|
||||
|
||||
og_image = post.image.source_url if post.image_id else None
|
||||
description = shorten_string(markdown_to_text(post.body), 150) if post.body else None
|
||||
|
@ -588,6 +596,7 @@ def add_reply(post_id: int, comment_id: int):
|
|||
return redirect(url_for('activitypub.post_ap', post_id=post_id))
|
||||
|
||||
form = NewReplyForm()
|
||||
form.language_id.choices = languages_for_form()
|
||||
if form.validate_on_submit():
|
||||
if reply_already_exists(user_id=current_user.id, post_id=post.id, parent_id=in_reply_to.id, body=form.body.data):
|
||||
if in_reply_to.depth <= constants.THREAD_CUTOFF_DEPTH:
|
||||
|
@ -617,11 +626,12 @@ def add_reply(post_id: int, comment_id: int):
|
|||
|
||||
current_user.last_seen = utcnow()
|
||||
current_user.ip_address = ip_address()
|
||||
current_user.language_id = form.language_id.data
|
||||
reply = PostReply(user_id=current_user.id, post_id=post.id, parent_id=in_reply_to.id, depth=in_reply_to.depth + 1,
|
||||
community_id=post.community.id, body=form.body.data,
|
||||
body_html=markdown_to_html(form.body.data), body_html_safe=True,
|
||||
from_bot=current_user.bot, nsfw=post.nsfw, nsfl=post.nsfl,
|
||||
notify_author=form.notify_author.data, instance_id=1)
|
||||
notify_author=form.notify_author.data, instance_id=1, language_id=form.language_id.data)
|
||||
if reply.body:
|
||||
for blocked_phrase in blocked_phrases():
|
||||
if blocked_phrase in reply.body:
|
||||
|
@ -761,6 +771,7 @@ def add_reply(post_id: int, comment_id: int):
|
|||
return redirect(url_for('post.continue_discussion', post_id=post_id, comment_id=reply.parent_id))
|
||||
else:
|
||||
form.notify_author.data = True
|
||||
form.language_id.data = current_user.language_id if current_user.language_id else english_language_id()
|
||||
|
||||
return render_template('post/add_reply.html', title=_('Discussing %(title)s', title=post.title), post=post,
|
||||
is_moderator=is_moderator, form=form, comment=in_reply_to, markdown_editor=current_user.is_authenticated and current_user.markdown_editor,
|
||||
|
@ -828,6 +839,8 @@ def post_edit_discussion_post(post_id: int):
|
|||
form.nsfl.data = True
|
||||
form.nsfw.render_kw = {'disabled': True}
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if form.validate_on_submit():
|
||||
save_post(form, post, 'discussion')
|
||||
post.community.last_active = utcnow()
|
||||
|
@ -848,6 +861,7 @@ def post_edit_discussion_post(post_id: int):
|
|||
form.nsfw.data = post.nsfw
|
||||
form.nsfl.data = post.nsfl
|
||||
form.sticky.data = post.sticky
|
||||
form.language_id.data = post.language_id
|
||||
if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()):
|
||||
form.sticky.render_kw = {'disabled': True}
|
||||
return render_template('post/post_edit_discussion.html', title=_('Edit post'), form=form, post=post,
|
||||
|
@ -886,6 +900,8 @@ def post_edit_image_post(post_id: int):
|
|||
|
||||
old_url = post.url
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if form.validate_on_submit():
|
||||
save_post(form, post, 'image')
|
||||
post.community.last_active = utcnow()
|
||||
|
@ -929,6 +945,7 @@ def post_edit_image_post(post_id: int):
|
|||
form.nsfw.data = post.nsfw
|
||||
form.nsfl.data = post.nsfl
|
||||
form.sticky.data = post.sticky
|
||||
form.language_id.data = post.language_id
|
||||
if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()):
|
||||
form.sticky.render_kw = {'disabled': True}
|
||||
return render_template('post/post_edit_image.html', title=_('Edit post'), form=form, post=post,
|
||||
|
@ -967,6 +984,8 @@ def post_edit_link_post(post_id: int):
|
|||
|
||||
old_url = post.url
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if form.validate_on_submit():
|
||||
save_post(form, post, 'link')
|
||||
post.community.last_active = utcnow()
|
||||
|
@ -1010,6 +1029,7 @@ def post_edit_link_post(post_id: int):
|
|||
form.nsfw.data = post.nsfw
|
||||
form.nsfl.data = post.nsfl
|
||||
form.sticky.data = post.sticky
|
||||
form.language_id.data = post.language_id
|
||||
if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()):
|
||||
form.sticky.render_kw = {'disabled': True}
|
||||
return render_template('post/post_edit_link.html', title=_('Edit post'), form=form, post=post,
|
||||
|
@ -1048,6 +1068,8 @@ def post_edit_video_post(post_id: int):
|
|||
|
||||
old_url = post.url
|
||||
|
||||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if form.validate_on_submit():
|
||||
save_post(form, post, 'video')
|
||||
post.community.last_active = utcnow()
|
||||
|
@ -1091,6 +1113,7 @@ def post_edit_video_post(post_id: int):
|
|||
form.nsfw.data = post.nsfw
|
||||
form.nsfl.data = post.nsfl
|
||||
form.sticky.data = post.sticky
|
||||
form.language_id.data = post.language_id
|
||||
if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()):
|
||||
form.sticky.render_kw = {'disabled': True}
|
||||
return render_template('post/post_edit_video.html', title=_('Edit post'), form=form, post=post,
|
||||
|
@ -1126,7 +1149,11 @@ def federate_post_update(post):
|
|||
'stickied': post.sticky,
|
||||
'published': ap_datetime(post.posted_at),
|
||||
'updated': ap_datetime(post.edited_at),
|
||||
'audience': post.community.ap_profile_id
|
||||
'audience': post.community.ap_profile_id,
|
||||
'language': {
|
||||
'identifier': post.language_code(),
|
||||
'name': post.language_name()
|
||||
}
|
||||
}
|
||||
update_json = {
|
||||
'id': f"https://{current_app.config['SERVER_NAME']}/activities/update/{gibberish(15)}",
|
||||
|
@ -1487,6 +1514,7 @@ def post_reply_edit(post_id: int, comment_id: int):
|
|||
else:
|
||||
comment = None
|
||||
form = NewReplyForm()
|
||||
form.language_id.choices = languages_for_form()
|
||||
if post_reply.user_id == current_user.id or post.community.is_moderator():
|
||||
if form.validate_on_submit():
|
||||
post_reply.body = form.body.data
|
||||
|
@ -1494,6 +1522,7 @@ def post_reply_edit(post_id: int, comment_id: int):
|
|||
post_reply.notify_author = form.notify_author.data
|
||||
post.community.last_active = utcnow()
|
||||
post_reply.edited_at = utcnow()
|
||||
post_reply.language_id = form.language_id.data
|
||||
db.session.commit()
|
||||
flash(_('Your changes have been saved.'), 'success')
|
||||
|
||||
|
@ -1528,6 +1557,10 @@ def post_reply_edit(post_id: int, comment_id: int):
|
|||
'audience': post.community.public_url(),
|
||||
'contentMap': {
|
||||
'en': post_reply.body_html
|
||||
},
|
||||
'language': {
|
||||
'identifier': post_reply.language_code(),
|
||||
'name': post_reply.language_name()
|
||||
}
|
||||
}
|
||||
update_json = {
|
||||
|
@ -1599,6 +1632,7 @@ def post_reply_edit(post_id: int, comment_id: int):
|
|||
else:
|
||||
form.body.data = post_reply.body
|
||||
form.notify_author.data = post_reply.notify_author
|
||||
form.language_id.data = post_reply.language_id
|
||||
return render_template('post/post_reply_edit.html', title=_('Edit comment'), form=form, post=post, post_reply=post_reply,
|
||||
comment=comment, markdown_editor=current_user.markdown_editor, moderating_communities=moderating_communities(current_user.get_id()),
|
||||
joined_communities=joined_communities(current_user.get_id()), community=post.community,
|
||||
|
|
|
@ -1376,4 +1376,22 @@ h1 .warning_badge {
|
|||
max-height: 90vh;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.post_language_chooser label {
|
||||
display: none;
|
||||
}
|
||||
.post_language_chooser select {
|
||||
max-width: 150px;
|
||||
float: right;
|
||||
margin-top: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.language-float-right {
|
||||
max-width: 150px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=structure.css.map */
|
||||
|
|
|
@ -1051,3 +1051,23 @@ h1 .warning_badge {
|
|||
max-width: 100%;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.post_language_chooser {
|
||||
@include breakpoint(phablet) {
|
||||
label {
|
||||
display: none;
|
||||
}
|
||||
select {
|
||||
max-width: 150px;
|
||||
float: right;
|
||||
margin-top: -5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.language-float-right {
|
||||
@include breakpoint(phablet) {
|
||||
max-width: 150px;
|
||||
float: right;
|
||||
}
|
||||
}
|
|
@ -58,8 +58,8 @@
|
|||
<div class="col-md-1">
|
||||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@
|
|||
<div class="col-md-1">
|
||||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -59,8 +59,8 @@
|
|||
<div class="col-md-1">
|
||||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@
|
|||
<div class="col-md-1">
|
||||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
});
|
||||
</script>
|
||||
{% else %}
|
||||
<a href="#" aria-hidden="true" id="post_reply_markdown_editor_enabler" class="markdown_editor_enabler" data-id="body">{{ _('Enable markdown editor') }}</a>
|
||||
<!-- <a href="#" aria-hidden="true" id="post_reply_markdown_editor_enabler" class="markdown_editor_enabler" data-id="body">{{ _('Enable markdown editor') }}</a> -->
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@
|
|||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
{{ render_field(form.nsfl) }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
|
||||
<div class="col post_language_chooser">
|
||||
{{ render_field(form.language_id) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
<div class="card-title">{{ _('Options for "%(post_title)s"', post_title=post.title) }}</div>
|
||||
<ul class="option_list">
|
||||
{% if current_user.is_authenticated %}
|
||||
{% if post.user_id == current_user.id or post.community.is_moderator() or current_user.is_admin() %}
|
||||
{% if post.user_id == current_user.id %}
|
||||
<li><a href="{{ url_for('post.post_edit', post_id=post.id) }}" class="no-underline" rel="nofollow"><span class="fe fe-edit"></span>
|
||||
{{ _('Edit') }}</a></li>
|
||||
{% endif %}
|
||||
{% if post.user_id == current_user.id or post.community.is_moderator() or post.community.is_owner() or current_user.is_admin() %}
|
||||
<li><a href="{{ url_for('post.post_delete', post_id=post.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-delete"></span>
|
||||
{{ _('Delete') }}</a></li>
|
||||
{% endif %}
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
<div class="card-title">{{ _('Options for comment on "%(post_title)s"', post_title=post.title) }}</div>
|
||||
<ul class="option_list">
|
||||
{% if current_user.is_authenticated %}
|
||||
{% if post_reply.user_id == current_user.id or post.community.is_moderator() or current_user.is_admin() %}
|
||||
{% if post_reply.user_id == current_user.id %}
|
||||
<li><a href="{{ url_for('post.post_reply_edit', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline" rel="nofollow"><span class="fe fe-edit"></span>
|
||||
{{ _('Edit') }}</a></li>
|
||||
{% endif %}
|
||||
{% if post_reply.user_id == current_user.id or post.community.is_moderator() or post.community.is_owner() or current_user.is_admin() %}
|
||||
<li><a href="{{ url_for('post.post_reply_delete', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-delete"></span>
|
||||
{{ _('Delete') }}</a></li>
|
||||
{% endif %}
|
||||
|
|
|
@ -984,3 +984,8 @@ def languages_for_form():
|
|||
if language.code != 'und':
|
||||
result.append((language.id, language.name))
|
||||
return result
|
||||
|
||||
|
||||
def english_language_id():
|
||||
english = Language.query.filter(Language.code == 'en').first()
|
||||
return english.id if english else None
|
||||
|
|
46
migrations/versions/9ad372b72d7c_post_reply_language.py
Normal file
46
migrations/versions/9ad372b72d7c_post_reply_language.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
"""post_reply language
|
||||
|
||||
Revision ID: 9ad372b72d7c
|
||||
Revises: e73996747d7e
|
||||
Create Date: 2024-05-09 14:26:48.888908
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '9ad372b72d7c'
|
||||
down_revision = 'e73996747d7e'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('post', schema=None) as batch_op:
|
||||
batch_op.create_foreign_key(None, 'language', ['language_id'], ['id'])
|
||||
batch_op.drop_column('language')
|
||||
|
||||
with op.batch_alter_table('post_reply', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('language_id', sa.Integer(), nullable=True))
|
||||
batch_op.create_index(batch_op.f('ix_post_reply_language_id'), ['language_id'], unique=False)
|
||||
batch_op.create_foreign_key(None, 'language', ['language_id'], ['id'])
|
||||
batch_op.drop_column('language')
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('post_reply', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('language', sa.VARCHAR(length=10), autoincrement=False, nullable=True))
|
||||
batch_op.drop_constraint(None, type_='foreignkey')
|
||||
batch_op.drop_index(batch_op.f('ix_post_reply_language_id'))
|
||||
batch_op.drop_column('language_id')
|
||||
|
||||
with op.batch_alter_table('post', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('language', sa.VARCHAR(length=10), autoincrement=False, nullable=True))
|
||||
batch_op.drop_constraint(None, type_='foreignkey')
|
||||
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in a new issue