mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
Merge pull request 'Allow reuploading images in image type posts' (#385) from xmatt/pyfedi:feature/image_post_editing into main
Reviewed-on: https://codeberg.org/rimu/pyfedi/pulls/385
This commit is contained in:
commit
8088aa1b3c
8 changed files with 111 additions and 70 deletions
|
@ -178,8 +178,9 @@ class CreateImageForm(CreatePostForm):
|
|||
|
||||
return True
|
||||
|
||||
class EditImageForm(CreatePostForm):
|
||||
image_alt_text = StringField(_l('Alt text'), validators=[Optional(), Length(min=3, max=1500)])
|
||||
class EditImageForm(CreateImageForm):
|
||||
image_file = FileField(_l('Replace Image'), validators=[DataRequired()], render_kw={'accept': 'image/*'})
|
||||
image_file = FileField(_l('Image'), validators=[Optional()], render_kw={'accept': 'image/*'})
|
||||
|
||||
def validate(self, extra_validators=None) -> bool:
|
||||
if self.communities:
|
||||
|
|
|
@ -690,8 +690,13 @@ def add_post(actor, type):
|
|||
img.thumbnail((2000, 2000))
|
||||
img.save(final_place)
|
||||
|
||||
request_json['object']['attachment'] = [{'type': 'Image', 'url': f'https://{current_app.config["SERVER_NAME"]}/{final_place.replace("app/", "")}',
|
||||
'name': form.image_alt_text.data}]
|
||||
request_json['object']['attachment'] = [{
|
||||
'type': 'Image',
|
||||
'url': f'https://{current_app.config["SERVER_NAME"]}/{final_place.replace("app/", "")}',
|
||||
'name': form.image_alt_text.data,
|
||||
'file_path': final_place
|
||||
}]
|
||||
|
||||
elif type == 'video':
|
||||
request_json['object']['attachment'] = [{'type': 'Document', 'url': form.video_url.data}]
|
||||
elif type == 'poll':
|
||||
|
|
|
@ -304,11 +304,16 @@ def save_post(form, post: Post, type: int):
|
|||
elif type == POST_TYPE_IMAGE:
|
||||
post.type = POST_TYPE_IMAGE
|
||||
alt_text = form.image_alt_text.data if form.image_alt_text.data else form.title.data
|
||||
if post.image_id is not None:
|
||||
# editing an existing image post, dont try an upload
|
||||
pass
|
||||
else:
|
||||
uploaded_file = request.files['image_file']
|
||||
# If we are uploading new file in the place of existing one just remove the old one
|
||||
if post.image_id is not None and uploaded_file:
|
||||
post.image.delete_from_disk()
|
||||
image_id = post.image_id
|
||||
post.image_id = None
|
||||
db.session.add(post)
|
||||
db.session.commit()
|
||||
File.query.filter_by(id=image_id).delete()
|
||||
|
||||
if uploaded_file and uploaded_file.filename != '':
|
||||
if post.image_id:
|
||||
remove_old_file(post.image_id)
|
||||
|
@ -364,6 +369,7 @@ def save_post(form, post: Post, type: int):
|
|||
db.session.add(file)
|
||||
db.session.commit()
|
||||
post.image_id = file.id
|
||||
|
||||
elif type == POST_TYPE_VIDEO:
|
||||
form.video_url.data = form.video_url.data.strip()
|
||||
url_changed = post.id is None or form.video_url.data != post.url
|
||||
|
|
|
@ -329,7 +329,6 @@ class File(db.Model):
|
|||
if purge_from_cache:
|
||||
flush_cdn_cache(purge_from_cache)
|
||||
|
||||
|
||||
def filesize(self):
|
||||
size = 0
|
||||
if self.file_path and os.path.exists(self.file_path):
|
||||
|
@ -1246,6 +1245,7 @@ class Post(db.Model):
|
|||
if blocked_phrase in post.body:
|
||||
return None
|
||||
|
||||
file_path = None
|
||||
if ('attachment' in request_json['object'] and
|
||||
isinstance(request_json['object']['attachment'], list) and
|
||||
len(request_json['object']['attachment']) > 0 and
|
||||
|
@ -1258,9 +1258,10 @@ class Post(db.Model):
|
|||
if 'name' in request_json['object']['attachment'][0]:
|
||||
alt_text = request_json['object']['attachment'][0]['name']
|
||||
if request_json['object']['attachment'][0]['type'] == 'Image':
|
||||
post.url = request_json['object']['attachment'][0]['url'] # PixelFed, PieFed, Lemmy >= 0.19.4
|
||||
if 'name' in request_json['object']['attachment'][0]:
|
||||
alt_text = request_json['object']['attachment'][0]['name']
|
||||
attachment = request_json['object']['attachment'][0]
|
||||
post.url = attachment['url'] # PixelFed, PieFed, Lemmy >= 0.19.4
|
||||
alt_text = attachment.get("name")
|
||||
file_path = attachment.get("file_path")
|
||||
|
||||
if 'attachment' in request_json['object'] and isinstance(request_json['object']['attachment'], dict): # a.gup.pe (Mastodon)
|
||||
alt_text = None
|
||||
|
@ -1272,6 +1273,8 @@ class Post(db.Model):
|
|||
image = File(source_url=post.url)
|
||||
if alt_text:
|
||||
image.alt_text = alt_text
|
||||
if file_path:
|
||||
image.file_path = file_path
|
||||
db.session.add(image)
|
||||
post.image = image
|
||||
elif is_video_url(post.url): # youtube is detected later
|
||||
|
|
|
@ -32,7 +32,7 @@ from app.utils import get_setting, render_template, allowlist_html, markdown_to_
|
|||
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, \
|
||||
languages_for_form, menu_topics, add_to_modlog, blocked_communities, piefed_markdown_to_lemmy_markdown, \
|
||||
permission_required, blocked_users, get_request
|
||||
permission_required, blocked_users, get_request, is_local_image_url, is_video_url
|
||||
|
||||
|
||||
def show_post(post_id: int):
|
||||
|
@ -730,14 +730,23 @@ def post_reply_options(post_id: int, comment_id: int):
|
|||
@login_required
|
||||
def post_edit(post_id: int):
|
||||
post = Post.query.get_or_404(post_id)
|
||||
post_type = post.type
|
||||
if post.type == POST_TYPE_ARTICLE:
|
||||
form = CreateDiscussionForm()
|
||||
elif post.type == POST_TYPE_LINK:
|
||||
form = CreateLinkForm()
|
||||
elif post.type == POST_TYPE_IMAGE:
|
||||
if post.image and post.image.source_url and is_local_image_url(post.image.source_url):
|
||||
form = EditImageForm()
|
||||
else:
|
||||
form = CreateLinkForm()
|
||||
post_type = POST_TYPE_LINK
|
||||
elif post.type == POST_TYPE_VIDEO:
|
||||
if is_video_url(post.url):
|
||||
form = CreateVideoForm()
|
||||
else:
|
||||
form = CreateLinkForm()
|
||||
post_type = POST_TYPE_LINK
|
||||
elif post.type == POST_TYPE_POLL:
|
||||
form = CreatePollForm()
|
||||
poll = Poll.query.filter_by(post_id=post_id).first()
|
||||
|
@ -769,7 +778,7 @@ def post_edit(post_id: int):
|
|||
form.language_id.choices = languages_for_form()
|
||||
|
||||
if form.validate_on_submit():
|
||||
save_post(form, post, post.type)
|
||||
save_post(form, post, post_type)
|
||||
post.community.last_active = utcnow()
|
||||
post.edited_at = utcnow()
|
||||
|
||||
|
@ -812,14 +821,23 @@ def post_edit(post_id: int):
|
|||
form.sticky.data = post.sticky
|
||||
form.language_id.data = post.language_id
|
||||
form.tags.data = tags_to_string(post)
|
||||
if post.type == POST_TYPE_LINK:
|
||||
if post_type == POST_TYPE_LINK:
|
||||
form.link_url.data = post.url
|
||||
elif post.type == POST_TYPE_IMAGE:
|
||||
elif post_type == POST_TYPE_IMAGE:
|
||||
# existing_image = True
|
||||
form.image_alt_text.data = post.image.alt_text
|
||||
elif post.type == POST_TYPE_VIDEO:
|
||||
path = post.image.file_path
|
||||
# This is fallback for existing entries
|
||||
if not path:
|
||||
path = "app/" + post.image.source_url.replace(
|
||||
f"https://{current_app.config['SERVER_NAME']}/", ""
|
||||
)
|
||||
with open(path, "rb")as file:
|
||||
form.image_file.data = file.read()
|
||||
|
||||
elif post_type == POST_TYPE_VIDEO:
|
||||
form.video_url.data = post.url
|
||||
elif post.type == POST_TYPE_POLL:
|
||||
elif post_type == POST_TYPE_POLL:
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
form.mode.data = poll.mode
|
||||
form.local_only.data = poll.local_only
|
||||
|
@ -832,7 +850,7 @@ def post_edit(post_id: int):
|
|||
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.html', title=_('Edit post'), form=form,
|
||||
post_type=post.type, community=post.community, post=post,
|
||||
post_type=post_type, community=post.community, post=post,
|
||||
markdown_editor=current_user.markdown_editor, mods=mod_list,
|
||||
moderating_communities=moderating_communities(current_user.get_id()),
|
||||
joined_communities=joined_communities(current_user.get_id()),
|
||||
|
|
|
@ -32,9 +32,8 @@
|
|||
</a>
|
||||
{% endif -%}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ render_field(form.image_file) }}
|
||||
{% endif %}
|
||||
{{ render_field(form.image_file) }}
|
||||
{{ render_field(form.image_alt_text) }}
|
||||
<small class="field_hint">{{ _('Describe the image, to help visually impaired people.') }}</small>
|
||||
{% elif post_type == POST_TYPE_VIDEO %}
|
||||
|
|
|
@ -22,6 +22,7 @@ import jwt
|
|||
|
||||
warnings.filterwarnings("ignore", category=MarkupResemblesLocatorWarning)
|
||||
import os
|
||||
from furl import furl
|
||||
from flask import current_app, json, redirect, url_for, request, make_response, Response, g, flash
|
||||
from flask_babel import _
|
||||
from flask_login import current_user, logout_user
|
||||
|
@ -195,6 +196,13 @@ def is_image_url(url):
|
|||
return any(path.endswith(extension) for extension in common_image_extensions)
|
||||
|
||||
|
||||
def is_local_image_url(url):
|
||||
if not is_image_url(url):
|
||||
return False
|
||||
f = furl(url)
|
||||
return f.host in ["127.0.0.1", current_app.config["SERVER_NAME"]]
|
||||
|
||||
|
||||
def is_video_url(url: str) -> bool:
|
||||
common_video_extensions = ['.mp4', '.webm']
|
||||
mime_type = mime_type_using_head(url)
|
||||
|
|
|
@ -32,3 +32,4 @@ Werkzeug==2.3.3
|
|||
pytesseract==0.3.10
|
||||
sentry-sdk==1.40.6
|
||||
python-slugify==8.0.4
|
||||
furl==2.1.3
|
||||
|
|
Loading…
Reference in a new issue