mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-24 03:43:42 -08:00
various small bugfixes
This commit is contained in:
parent
686ac36ac7
commit
41f6a29e33
10 changed files with 133 additions and 94 deletions
|
@ -408,7 +408,10 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
||||||
|
|
||||||
# Announce is new content and votes that happened on a remote server.
|
# Announce is new content and votes that happened on a remote server.
|
||||||
if request_json['type'] == 'Announce':
|
if request_json['type'] == 'Announce':
|
||||||
if request_json['object']['type'] == 'Create':
|
if isinstance(request_json['object'], str):
|
||||||
|
activity_log.activity_json = json.dumps(request_json)
|
||||||
|
activity_log.exception_message = 'invalid json?'
|
||||||
|
elif request_json['object']['type'] == 'Create':
|
||||||
activity_log.activity_type = request_json['object']['type']
|
activity_log.activity_type = request_json['object']['type']
|
||||||
user_ap_id = request_json['object']['object']['attributedTo']
|
user_ap_id = request_json['object']['object']['attributedTo']
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -536,6 +536,7 @@ def make_image_sizes_async(file_id, thumbnail_width, medium_width, directory):
|
||||||
final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp')
|
final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp')
|
||||||
|
|
||||||
# Load image data into Pillow
|
# Load image data into Pillow
|
||||||
|
Image.MAX_IMAGE_PIXELS = 89478485
|
||||||
image = Image.open(BytesIO(source_image))
|
image = Image.open(BytesIO(source_image))
|
||||||
image = ImageOps.exif_transpose(image)
|
image = ImageOps.exif_transpose(image)
|
||||||
img_width = image.width
|
img_width = image.width
|
||||||
|
@ -563,11 +564,11 @@ def make_image_sizes_async(file_id, thumbnail_width, medium_width, directory):
|
||||||
|
|
||||||
# Alert regarding fascist meme content
|
# Alert regarding fascist meme content
|
||||||
try:
|
try:
|
||||||
image_text = pytesseract.image_to_string(Image.open(BytesIO(source_image)).convert('L'))
|
image_text = pytesseract.image_to_string(Image.open(BytesIO(source_image)).convert('L'), timeout=30)
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
image_text = ''
|
image_text = ''
|
||||||
if 'Anonymous' in image_text and ('No.' in image_text or ' N0' in image_text): # chan posts usually contain the text 'Anonymous' and ' No.12345'
|
if 'Anonymous' in image_text and ('No.' in image_text or ' N0' in image_text): # chan posts usually contain the text 'Anonymous' and ' No.12345'
|
||||||
post = Post.query.filter(image_id=file.id).first()
|
post = Post.query.filter_by(image_id=file.id).first()
|
||||||
notification = Notification(title='Review this',
|
notification = Notification(title='Review this',
|
||||||
user_id=1,
|
user_id=1,
|
||||||
author_id=post.user_id,
|
author_id=post.user_id,
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
from flask import request
|
||||||
|
from flask_login import current_user
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import StringField, SubmitField, TextAreaField, BooleanField, HiddenField, SelectField, FileField
|
from wtforms import StringField, SubmitField, TextAreaField, BooleanField, HiddenField, SelectField, FileField
|
||||||
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
|
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
|
||||||
from flask_babel import _, lazy_gettext as _l
|
from flask_babel import _, lazy_gettext as _l
|
||||||
|
|
||||||
|
from app import db
|
||||||
from app.utils import domain_from_url, MultiCheckboxField
|
from app.utils import domain_from_url, MultiCheckboxField
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
from io import BytesIO
|
||||||
|
import pytesseract
|
||||||
|
|
||||||
|
|
||||||
class AddLocalCommunity(FlaskForm):
|
class AddLocalCommunity(FlaskForm):
|
||||||
|
@ -36,7 +42,7 @@ class SearchRemoteCommunity(FlaskForm):
|
||||||
|
|
||||||
class CreatePostForm(FlaskForm):
|
class CreatePostForm(FlaskForm):
|
||||||
communities = SelectField(_l('Community'), validators=[DataRequired()], coerce=int)
|
communities = SelectField(_l('Community'), validators=[DataRequired()], coerce=int)
|
||||||
type = HiddenField() # https://getbootstrap.com/docs/4.6/components/navs/#tabs
|
post_type = HiddenField() # https://getbootstrap.com/docs/4.6/components/navs/#tabs
|
||||||
discussion_title = StringField(_l('Title'), validators={Optional(), Length(min=3, max=255)})
|
discussion_title = StringField(_l('Title'), validators={Optional(), Length(min=3, max=255)})
|
||||||
discussion_body = TextAreaField(_l('Body'), validators={Optional(), Length(min=3, max=5000)}, render_kw={'placeholder': 'Text (optional)'})
|
discussion_body = TextAreaField(_l('Body'), validators={Optional(), Length(min=3, max=5000)}, render_kw={'placeholder': 'Text (optional)'})
|
||||||
link_title = StringField(_l('Title'), validators={Optional(), Length(min=3, max=255)})
|
link_title = StringField(_l('Title'), validators={Optional(), Length(min=3, max=255)})
|
||||||
|
@ -56,14 +62,14 @@ class CreatePostForm(FlaskForm):
|
||||||
def validate(self, extra_validators=None) -> bool:
|
def validate(self, extra_validators=None) -> bool:
|
||||||
if not super().validate():
|
if not super().validate():
|
||||||
return False
|
return False
|
||||||
if self.type.data is None or self.type.data == '':
|
if self.post_type.data is None or self.post_type.data == '':
|
||||||
self.type.data = 'discussion'
|
self.post_type.data = 'discussion'
|
||||||
|
|
||||||
if self.type.data == 'discussion':
|
if self.post_type.data == 'discussion':
|
||||||
if self.discussion_title.data == '':
|
if self.discussion_title.data == '':
|
||||||
self.discussion_title.errors.append(_('Title is required.'))
|
self.discussion_title.errors.append(_('Title is required.'))
|
||||||
return False
|
return False
|
||||||
elif self.type.data == 'link':
|
elif self.post_type.data == 'link':
|
||||||
if self.link_title.data == '':
|
if self.link_title.data == '':
|
||||||
self.link_title.errors.append(_('Title is required.'))
|
self.link_title.errors.append(_('Title is required.'))
|
||||||
return False
|
return False
|
||||||
|
@ -74,14 +80,27 @@ class CreatePostForm(FlaskForm):
|
||||||
if domain and domain.banned:
|
if domain and domain.banned:
|
||||||
self.link_url.errors.append(_(f"Links to %s are not allowed.".format(domain.name)))
|
self.link_url.errors.append(_(f"Links to %s are not allowed.".format(domain.name)))
|
||||||
return False
|
return False
|
||||||
elif self.type.data == 'image':
|
elif self.post_type.data == 'image':
|
||||||
if self.image_title.data == '':
|
if self.image_title.data == '':
|
||||||
self.image_title.errors.append(_('Title is required.'))
|
self.image_title.errors.append(_('Title is required.'))
|
||||||
return False
|
return False
|
||||||
if self.image_file.data == '':
|
if self.image_file.data == '':
|
||||||
self.image_file.errors.append(_('File is required.'))
|
self.image_file.errors.append(_('File is required.'))
|
||||||
return False
|
return False
|
||||||
elif self.type.data == 'poll':
|
uploaded_file = request.files['image_file']
|
||||||
|
if uploaded_file and uploaded_file.filename != '':
|
||||||
|
Image.MAX_IMAGE_PIXELS = 89478485
|
||||||
|
# Do not allow fascist meme content
|
||||||
|
try:
|
||||||
|
image_text = pytesseract.image_to_string(Image.open(BytesIO(uploaded_file.read())).convert('L'))
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
image_text = ''
|
||||||
|
if 'Anonymous' in image_text and ('No.' in image_text or ' N0' in image_text): # chan posts usually contain the text 'Anonymous' and ' No.12345'
|
||||||
|
self.image_file.errors.append(f"This image is an invalid file type.") # deliberately misleading error message
|
||||||
|
current_user.reputation -= 1
|
||||||
|
db.session.commit()
|
||||||
|
return False
|
||||||
|
elif self.post_type.data == 'poll':
|
||||||
self.discussion_title.errors.append(_('Poll not implemented yet.'))
|
self.discussion_title.errors.append(_('Poll not implemented yet.'))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from io import BytesIO
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, g, json
|
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, g, json
|
||||||
|
@ -19,7 +20,7 @@ from app.models import User, Community, CommunityMember, CommunityJoinRequest, C
|
||||||
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog
|
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog
|
||||||
from app.community import bp
|
from app.community import bp
|
||||||
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
||||||
shorten_string, markdown_to_text, domain_from_url, validate_image, gibberish, community_membership, ap_datetime, \
|
shorten_string, gibberish, community_membership, ap_datetime, \
|
||||||
request_etag_matches, return_304, instance_banned, can_create, can_upvote, can_downvote, user_filters_posts, \
|
request_etag_matches, return_304, instance_banned, can_create, can_upvote, can_downvote, user_filters_posts, \
|
||||||
joined_communities, moderating_communities
|
joined_communities, moderating_communities
|
||||||
from feedgen.feed import FeedGenerator
|
from feedgen.feed import FeedGenerator
|
||||||
|
@ -459,6 +460,9 @@ def add_post(actor):
|
||||||
|
|
||||||
return redirect(f"/c/{community.link()}")
|
return redirect(f"/c/{community.link()}")
|
||||||
else:
|
else:
|
||||||
|
# when request.form has some data in it, it means form validation failed. Set the post_type so the correct tab is shown. See setupPostTypeTabs() in scripts.js
|
||||||
|
if request.form.get('post_type', None):
|
||||||
|
form.post_type.data = request.form.get('post_type')
|
||||||
form.communities.data = community.id
|
form.communities.data = community.id
|
||||||
form.notify_author.data = True
|
form.notify_author.data = True
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ from app.activitypub.util import find_actor_or_create, actor_json_to_model, post
|
||||||
from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE
|
from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE
|
||||||
from app.models import Community, File, BannedInstances, PostReply, PostVote, Post, utcnow, CommunityMember, Site, \
|
from app.models import Community, File, BannedInstances, PostReply, PostVote, Post, utcnow, CommunityMember, Site, \
|
||||||
Instance, Notification, User
|
Instance, Notification, User
|
||||||
from app.utils import get_request, gibberish, markdown_to_html, domain_from_url, validate_image, allowlist_html, \
|
from app.utils import get_request, gibberish, markdown_to_html, domain_from_url, allowlist_html, \
|
||||||
html_to_markdown, is_image_url, ensure_directory_exists, inbox_domain, post_ranking, shorten_string
|
html_to_markdown, is_image_url, ensure_directory_exists, inbox_domain, post_ranking, shorten_string
|
||||||
from sqlalchemy import desc, text
|
from sqlalchemy import desc, text
|
||||||
import os
|
import os
|
||||||
|
@ -152,6 +152,7 @@ def url_to_thumbnail_file(filename) -> File:
|
||||||
with open(final_place, 'wb') as f:
|
with open(final_place, 'wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
response.close()
|
response.close()
|
||||||
|
Image.MAX_IMAGE_PIXELS = 89478485
|
||||||
with Image.open(final_place) as img:
|
with Image.open(final_place) as img:
|
||||||
img = ImageOps.exif_transpose(img)
|
img = ImageOps.exif_transpose(img)
|
||||||
img.thumbnail((150, 150))
|
img.thumbnail((150, 150))
|
||||||
|
@ -167,12 +168,12 @@ def save_post(form, post: Post):
|
||||||
post.nsfw = form.nsfw.data
|
post.nsfw = form.nsfw.data
|
||||||
post.nsfl = form.nsfl.data
|
post.nsfl = form.nsfl.data
|
||||||
post.notify_author = form.notify_author.data
|
post.notify_author = form.notify_author.data
|
||||||
if form.type.data == '' or form.type.data == 'discussion':
|
if form.post_type.data == '' or form.post_type.data == 'discussion':
|
||||||
post.title = form.discussion_title.data
|
post.title = form.discussion_title.data
|
||||||
post.body = form.discussion_body.data
|
post.body = form.discussion_body.data
|
||||||
post.body_html = markdown_to_html(post.body)
|
post.body_html = markdown_to_html(post.body)
|
||||||
post.type = POST_TYPE_ARTICLE
|
post.type = POST_TYPE_ARTICLE
|
||||||
elif form.type.data == 'link':
|
elif form.post_type.data == 'link':
|
||||||
post.title = form.link_title.data
|
post.title = form.link_title.data
|
||||||
post.body = form.link_body.data
|
post.body = form.link_body.data
|
||||||
post.body_html = markdown_to_html(post.body)
|
post.body_html = markdown_to_html(post.body)
|
||||||
|
@ -187,10 +188,10 @@ def save_post(form, post: Post):
|
||||||
if post.image_id:
|
if post.image_id:
|
||||||
remove_old_file(post.image_id)
|
remove_old_file(post.image_id)
|
||||||
post.image_id = None
|
post.image_id = None
|
||||||
valid_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.webp'}
|
|
||||||
unused, file_extension = os.path.splitext(form.link_url.data) # do not use _ here instead of 'unused'
|
unused, file_extension = os.path.splitext(form.link_url.data) # do not use _ here instead of 'unused'
|
||||||
# this url is a link to an image - generate a thumbnail of it
|
# this url is a link to an image - generate a thumbnail of it
|
||||||
if file_extension.lower() in valid_extensions:
|
if file_extension.lower() in allowed_extensions:
|
||||||
file = url_to_thumbnail_file(form.link_url.data)
|
file = url_to_thumbnail_file(form.link_url.data)
|
||||||
if file:
|
if file:
|
||||||
post.image = file
|
post.image = file
|
||||||
|
@ -200,16 +201,15 @@ def save_post(form, post: Post):
|
||||||
opengraph = opengraph_parse(form.link_url.data)
|
opengraph = opengraph_parse(form.link_url.data)
|
||||||
if opengraph and opengraph.get('og:image', '') != '':
|
if opengraph and opengraph.get('og:image', '') != '':
|
||||||
filename = opengraph.get('og:image')
|
filename = opengraph.get('og:image')
|
||||||
valid_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.webp'}
|
|
||||||
unused, file_extension = os.path.splitext(filename)
|
unused, file_extension = os.path.splitext(filename)
|
||||||
if file_extension.lower() in valid_extensions:
|
if file_extension.lower() in allowed_extensions:
|
||||||
file = url_to_thumbnail_file(filename)
|
file = url_to_thumbnail_file(filename)
|
||||||
if file:
|
if file:
|
||||||
file.alt_text = opengraph.get('og:title')
|
file.alt_text = opengraph.get('og:title')
|
||||||
post.image = file
|
post.image = file
|
||||||
db.session.add(file)
|
db.session.add(file)
|
||||||
|
|
||||||
elif form.type.data == 'image':
|
elif form.post_type.data == 'image':
|
||||||
post.title = form.image_title.data
|
post.title = form.image_title.data
|
||||||
post.body = form.image_body.data
|
post.body = form.image_body.data
|
||||||
post.body_html = markdown_to_html(post.body)
|
post.body_html = markdown_to_html(post.body)
|
||||||
|
@ -222,7 +222,7 @@ def save_post(form, post: Post):
|
||||||
|
|
||||||
# check if this is an allowed type of file
|
# check if this is an allowed type of file
|
||||||
file_ext = os.path.splitext(uploaded_file.filename)[1]
|
file_ext = os.path.splitext(uploaded_file.filename)[1]
|
||||||
if file_ext.lower() not in allowed_extensions or file_ext.lower() != validate_image(uploaded_file.stream):
|
if file_ext.lower() not in allowed_extensions:
|
||||||
abort(400)
|
abort(400)
|
||||||
new_filename = gibberish(15)
|
new_filename = gibberish(15)
|
||||||
|
|
||||||
|
@ -233,13 +233,17 @@ def save_post(form, post: Post):
|
||||||
# save the file
|
# save the file
|
||||||
final_place = os.path.join(directory, new_filename + file_ext)
|
final_place = os.path.join(directory, new_filename + file_ext)
|
||||||
final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp')
|
final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp')
|
||||||
|
uploaded_file.seek(0)
|
||||||
uploaded_file.save(final_place)
|
uploaded_file.save(final_place)
|
||||||
|
|
||||||
if file_ext.lower() == '.heic':
|
if file_ext.lower() == '.heic':
|
||||||
register_heif_opener()
|
register_heif_opener()
|
||||||
|
|
||||||
|
#Image.MAX_IMAGE_PIXELS = 89478485
|
||||||
|
|
||||||
# resize if necessary
|
# resize if necessary
|
||||||
img = Image.open(final_place)
|
img = Image.open(final_place)
|
||||||
|
if '.' + img.format.lower() in allowed_extensions:
|
||||||
img = ImageOps.exif_transpose(img)
|
img = ImageOps.exif_transpose(img)
|
||||||
img_width = img.width
|
img_width = img.width
|
||||||
img_height = img.height
|
img_height = img.height
|
||||||
|
@ -261,7 +265,7 @@ def save_post(form, post: Post):
|
||||||
post.image = file
|
post.image = file
|
||||||
db.session.add(file)
|
db.session.add(file)
|
||||||
|
|
||||||
elif form.type.data == 'poll':
|
elif form.post_type.data == 'poll':
|
||||||
...
|
...
|
||||||
else:
|
else:
|
||||||
raise Exception('invalid post type')
|
raise Exception('invalid post type')
|
||||||
|
@ -285,7 +289,7 @@ def remove_old_file(file_id):
|
||||||
def save_icon_file(icon_file, directory='communities') -> File:
|
def save_icon_file(icon_file, directory='communities') -> File:
|
||||||
# check if this is an allowed type of file
|
# check if this is an allowed type of file
|
||||||
file_ext = os.path.splitext(icon_file.filename)[1]
|
file_ext = os.path.splitext(icon_file.filename)[1]
|
||||||
if file_ext.lower() not in allowed_extensions or file_ext.lower() != validate_image(icon_file.stream):
|
if file_ext.lower() not in allowed_extensions:
|
||||||
abort(400)
|
abort(400)
|
||||||
new_filename = gibberish(15)
|
new_filename = gibberish(15)
|
||||||
|
|
||||||
|
@ -302,7 +306,9 @@ def save_icon_file(icon_file, directory='communities') -> File:
|
||||||
register_heif_opener()
|
register_heif_opener()
|
||||||
|
|
||||||
# resize if necessary
|
# resize if necessary
|
||||||
|
Image.MAX_IMAGE_PIXELS = 89478485
|
||||||
img = Image.open(final_place)
|
img = Image.open(final_place)
|
||||||
|
if '.' + img.format.lower() in allowed_extensions:
|
||||||
img = ImageOps.exif_transpose(img)
|
img = ImageOps.exif_transpose(img)
|
||||||
img_width = img.width
|
img_width = img.width
|
||||||
img_height = img.height
|
img_height = img.height
|
||||||
|
@ -322,13 +328,14 @@ def save_icon_file(icon_file, directory='communities') -> File:
|
||||||
thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail)
|
thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail)
|
||||||
db.session.add(file)
|
db.session.add(file)
|
||||||
return file
|
return file
|
||||||
|
else:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
|
||||||
def save_banner_file(banner_file, directory='communities') -> File:
|
def save_banner_file(banner_file, directory='communities') -> File:
|
||||||
# check if this is an allowed type of file
|
# check if this is an allowed type of file
|
||||||
file_ext = os.path.splitext(banner_file.filename)[1]
|
file_ext = os.path.splitext(banner_file.filename)[1]
|
||||||
if file_ext.lower() not in allowed_extensions or file_ext.lower() != validate_image(
|
if file_ext.lower() not in allowed_extensions:
|
||||||
banner_file.stream):
|
|
||||||
abort(400)
|
abort(400)
|
||||||
new_filename = gibberish(15)
|
new_filename = gibberish(15)
|
||||||
|
|
||||||
|
@ -345,7 +352,9 @@ def save_banner_file(banner_file, directory='communities') -> File:
|
||||||
register_heif_opener()
|
register_heif_opener()
|
||||||
|
|
||||||
# resize if necessary
|
# resize if necessary
|
||||||
|
Image.MAX_IMAGE_PIXELS = 89478485
|
||||||
img = Image.open(final_place)
|
img = Image.open(final_place)
|
||||||
|
if '.' + img.format.lower() in allowed_extensions:
|
||||||
img = ImageOps.exif_transpose(img)
|
img = ImageOps.exif_transpose(img)
|
||||||
img_width = img.width
|
img_width = img.width
|
||||||
img_height = img.height
|
img_height = img.height
|
||||||
|
@ -365,6 +374,8 @@ def save_banner_file(banner_file, directory='communities') -> File:
|
||||||
width=img_width, height=img_height, thumbnail_width=thumbnail_width, thumbnail_height=thumbnail_height)
|
width=img_width, height=img_height, thumbnail_width=thumbnail_width, thumbnail_height=thumbnail_height)
|
||||||
db.session.add(file)
|
db.session.add(file)
|
||||||
return file
|
return file
|
||||||
|
else:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
|
||||||
# NB this always signs POSTs as the community so is only suitable for Announce activities
|
# NB this always signs POSTs as the community so is only suitable for Announce activities
|
||||||
|
|
|
@ -19,7 +19,7 @@ from app.models import Post, PostReply, \
|
||||||
PostReplyVote, PostVote, Notification, utcnow, UserBlock, DomainBlock, InstanceBlock, Report, Site, Community
|
PostReplyVote, PostVote, Notification, utcnow, UserBlock, DomainBlock, InstanceBlock, Report, Site, Community
|
||||||
from app.post import bp
|
from app.post import bp
|
||||||
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
||||||
shorten_string, markdown_to_text, domain_from_url, validate_image, gibberish, ap_datetime, return_304, \
|
shorten_string, markdown_to_text, gibberish, ap_datetime, return_304, \
|
||||||
request_etag_matches, ip_address, user_ip_banned, instance_banned, can_downvote, can_upvote, post_ranking, \
|
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
|
reply_already_exists, reply_is_just_link_to_gif_reaction, confidence, moderating_communities, joined_communities
|
||||||
|
|
||||||
|
@ -643,16 +643,16 @@ def post_edit(post_id: int):
|
||||||
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||||
else:
|
else:
|
||||||
if post.type == constants.POST_TYPE_ARTICLE:
|
if post.type == constants.POST_TYPE_ARTICLE:
|
||||||
form.type.data = 'discussion'
|
form.post_type.data = 'discussion'
|
||||||
form.discussion_title.data = post.title
|
form.discussion_title.data = post.title
|
||||||
form.discussion_body.data = post.body
|
form.discussion_body.data = post.body
|
||||||
elif post.type == constants.POST_TYPE_LINK:
|
elif post.type == constants.POST_TYPE_LINK:
|
||||||
form.type.data = 'link'
|
form.post_type.data = 'link'
|
||||||
form.link_title.data = post.title
|
form.link_title.data = post.title
|
||||||
form.link_body.data = post.body
|
form.link_body.data = post.body
|
||||||
form.link_url.data = post.url
|
form.link_url.data = post.url
|
||||||
elif post.type == constants.POST_TYPE_IMAGE:
|
elif post.type == constants.POST_TYPE_IMAGE:
|
||||||
form.type.data = 'image'
|
form.post_type.data = 'image'
|
||||||
form.image_title.data = post.title
|
form.image_title.data = post.title
|
||||||
form.image_body.data = post.body
|
form.image_body.data = post.body
|
||||||
form.notify_author.data = post.notify_author
|
form.notify_author.data = post.notify_author
|
||||||
|
|
|
@ -234,27 +234,37 @@ function setupPostTypeTabs() {
|
||||||
const tabEl = document.querySelector('#discussion-tab')
|
const tabEl = document.querySelector('#discussion-tab')
|
||||||
if(tabEl) {
|
if(tabEl) {
|
||||||
tabEl.addEventListener('show.bs.tab', event => {
|
tabEl.addEventListener('show.bs.tab', event => {
|
||||||
document.getElementById('type').value = 'discussion';
|
document.getElementById('post_type ').value = 'discussion';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const tabE2 = document.querySelector('#link-tab')
|
const tabE2 = document.querySelector('#link-tab')
|
||||||
if(tabE2) {
|
if(tabE2) {
|
||||||
tabE2.addEventListener('show.bs.tab', event => {
|
tabE2.addEventListener('show.bs.tab', event => {
|
||||||
document.getElementById('type').value = 'link';
|
document.getElementById('post_type').value = 'link';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const tabE3 = document.querySelector('#image-tab')
|
const tabE3 = document.querySelector('#image-tab')
|
||||||
if(tabE3) {
|
if(tabE3) {
|
||||||
tabE3.addEventListener('show.bs.tab', event => {
|
tabE3.addEventListener('show.bs.tab', event => {
|
||||||
document.getElementById('type').value = 'image';
|
document.getElementById('post_type').value = 'image';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const tabE4 = document.querySelector('#poll-tab')
|
const tabE4 = document.querySelector('#poll-tab')
|
||||||
if(tabE4) {
|
if(tabE4) {
|
||||||
tabE4.addEventListener('show.bs.tab', event => {
|
tabE4.addEventListener('show.bs.tab', event => {
|
||||||
document.getElementById('type').value = 'poll';
|
document.getElementById('post_type').value = 'poll';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Check if there is a hidden field with the name 'type'. This is set if server-side validation of the form fails
|
||||||
|
var typeField = document.getElementById('post_type');
|
||||||
|
if (typeField && typeField.tagName === 'INPUT' && typeField.type === 'hidden') {
|
||||||
|
var typeVal = typeField.value;
|
||||||
|
if(typeVal) {
|
||||||
|
const tab = document.getElementById(typeVal + '-tab');
|
||||||
|
if(tab)
|
||||||
|
tab.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
Poll
|
Poll
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ render_field(form.type) }}
|
{{ render_field(form.post_type) }}
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
{{ render_field(form.notify_author) }}
|
{{ render_field(form.notify_author) }}
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
Poll
|
Poll
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ render_field(form.type) }}
|
{{ render_field(form.post_type) }}
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
{{ render_field(form.notify_author) }}
|
{{ render_field(form.notify_author) }}
|
||||||
|
|
13
app/utils.py
13
app/utils.py
|
@ -312,15 +312,6 @@ def ensure_directory_exists(directory):
|
||||||
rebuild_directory += '/'
|
rebuild_directory += '/'
|
||||||
|
|
||||||
|
|
||||||
def validate_image(stream):
|
|
||||||
header = stream.read(512)
|
|
||||||
stream.seek(0)
|
|
||||||
format = imghdr.what(None, header)
|
|
||||||
if not format:
|
|
||||||
return None
|
|
||||||
return '.' + (format if format != 'jpeg' else 'jpg')
|
|
||||||
|
|
||||||
|
|
||||||
def validation_required(func):
|
def validation_required(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def decorated_view(*args, **kwargs):
|
def decorated_view(*args, **kwargs):
|
||||||
|
@ -609,9 +600,9 @@ def _confidence(ups, downs):
|
||||||
|
|
||||||
|
|
||||||
def confidence(ups, downs) -> float:
|
def confidence(ups, downs) -> float:
|
||||||
if ups is None:
|
if ups is None or ups < 0:
|
||||||
ups = 0
|
ups = 0
|
||||||
if downs is None:
|
if downs is None or downs < 0:
|
||||||
downs = 0
|
downs = 0
|
||||||
if ups + downs == 0:
|
if ups + downs == 0:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
Loading…
Add table
Reference in a new issue