mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-02-02 16:21:32 -08:00
federation - receive remote posts, including edits and deletions
This commit is contained in:
parent
58ebdadc44
commit
6ec660005c
4 changed files with 134 additions and 7 deletions
|
@ -1,4 +1,6 @@
|
|||
from app import db
|
||||
from datetime import datetime
|
||||
|
||||
from app import db, constants
|
||||
from app.activitypub import bp
|
||||
from flask import request, Response, current_app, abort, jsonify, json
|
||||
|
||||
|
@ -221,7 +223,97 @@ def shared_inbox():
|
|||
if 'type' in request_json:
|
||||
activity_log.activity_type = request_json['type']
|
||||
if not instance_blocked(request_json['id']):
|
||||
# Announce is new content and votes
|
||||
# Create is new content and votes, kbin style
|
||||
if request_json['type'] == 'Create':
|
||||
activity_log.activity_type = request_json['type'] == 'Create (kbin)'
|
||||
user_ap_id = request_json['object']['attributedTo']
|
||||
community_ap_id = request_json['to'][0]
|
||||
community = find_actor_or_create(community_ap_id)
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
if user and community:
|
||||
object_type = request_json['object']['type']
|
||||
new_content_types = ['Page', 'Article', 'Link', 'Note']
|
||||
if object_type in new_content_types: # create a new post
|
||||
in_reply_to = request_json['object']['inReplyTo'] if 'inReplyTo' in \
|
||||
request_json[
|
||||
'object'] else None
|
||||
if not in_reply_to:
|
||||
post = Post(user_id=user.id, community_id=community.id,
|
||||
title=request_json['object']['name'],
|
||||
comments_enabled=request_json['object'][
|
||||
'commentsEnabled'],
|
||||
sticky=request_json['object']['stickied'] if 'stickied' in
|
||||
request_json[
|
||||
'object'] else False,
|
||||
nsfw=request_json['object']['sensitive'],
|
||||
nsfl=request_json['object']['nsfl'] if 'nsfl' in request_json[
|
||||
'object'] else False,
|
||||
ap_id=request_json['object']['id'],
|
||||
ap_create_id=request_json['id'],
|
||||
ap_announce_id=None,
|
||||
type=constants.POST_TYPE_ARTICLE
|
||||
)
|
||||
if 'source' in request_json['object'] and \
|
||||
request_json['object']['source'][
|
||||
'mediaType'] == 'text/markdown':
|
||||
post.body = request_json['object']['source']['content']
|
||||
post.body_html = markdown_to_html(post.body)
|
||||
elif 'content' in request_json['object']:
|
||||
post.body_html = allowlist_html(request_json['object']['content'])
|
||||
post.body = html_to_markdown(post.body_html)
|
||||
if 'attachment' in request_json['object'] and \
|
||||
len(request_json['object']['attachment']) > 0 and \
|
||||
'type' in request_json['object']['attachment'][0]:
|
||||
if request_json['object']['attachment'][0]['type'] == 'Link':
|
||||
post.url = request_json['object']['attachment'][0]['href']
|
||||
if is_image_url(post.url):
|
||||
post.type = POST_TYPE_IMAGE
|
||||
else:
|
||||
post.type = POST_TYPE_LINK
|
||||
domain = domain_from_url(post.url)
|
||||
if not domain.banned:
|
||||
post.domain_id = domain.id
|
||||
else:
|
||||
post = None
|
||||
activity_log.exception_message = domain.name + ' is blocked by admin'
|
||||
activity_log.result = 'failure'
|
||||
if 'image' in request_json['object']:
|
||||
image = File(source_url=request_json['object']['image']['url'])
|
||||
db.session.add(image)
|
||||
post.image = image
|
||||
|
||||
if post is not None:
|
||||
db.session.add(post)
|
||||
community.post_count += 1
|
||||
db.session.commit()
|
||||
else:
|
||||
post_id, parent_comment_id, root_id = find_reply_parent(in_reply_to)
|
||||
post_reply = PostReply(user_id=user.id, community_id=community.id,
|
||||
post_id=post_id, parent_id=parent_comment_id,
|
||||
root_id=root_id,
|
||||
nsfw=community.nsfw,
|
||||
nsfl=community.nsfl,
|
||||
ap_id=request_json['object']['id'],
|
||||
ap_create_id=request_json['id'],
|
||||
ap_announce_id=None)
|
||||
if 'source' in request_json['object'] and \
|
||||
request_json['object']['source'][
|
||||
'mediaType'] == 'text/markdown':
|
||||
post_reply.body = request_json['object']['source']['content']
|
||||
post_reply.body_html = markdown_to_html(post_reply.body)
|
||||
elif 'content' in request_json['object']:
|
||||
post_reply.body_html = allowlist_html(
|
||||
request_json['object']['content'])
|
||||
post_reply.body = html_to_markdown(post_reply.body_html)
|
||||
|
||||
if post_reply is not None:
|
||||
db.session.add(post_reply)
|
||||
community.post_reply_count += 1
|
||||
db.session.commit()
|
||||
else:
|
||||
activity_log.exception_message = 'Unacceptable type (kbin): ' + object_type
|
||||
|
||||
# Announce is new content and votes, lemmy style
|
||||
if request_json['type'] == 'Announce':
|
||||
if request_json['object']['type'] == 'Create':
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
|
@ -246,6 +338,7 @@ def shared_inbox():
|
|||
ap_id=request_json['object']['object']['id'],
|
||||
ap_create_id=request_json['object']['id'],
|
||||
ap_announce_id=request_json['id'],
|
||||
type=constants.POST_TYPE_ARTICLE
|
||||
)
|
||||
if 'source' in request_json['object']['object'] and \
|
||||
request_json['object']['object']['source']['mediaType'] == 'text/markdown':
|
||||
|
@ -431,7 +524,32 @@ def shared_inbox():
|
|||
...
|
||||
elif request_json['object']['type'] == 'Dislike': # Undoing a downvote
|
||||
...
|
||||
|
||||
elif request_json['type'] == 'Update':
|
||||
if request_json['object']['type'] == 'Page': # Editing a post
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if post:
|
||||
if 'source' in request_json['object'] and \
|
||||
request_json['object']['source']['mediaType'] == 'text/markdown':
|
||||
post.body = request_json['object']['source']['content']
|
||||
post.body_html = markdown_to_html(post.body)
|
||||
elif 'content' in request_json['object']:
|
||||
post.body_html = allowlist_html(request_json['object']['content'])
|
||||
post.body = html_to_markdown(post.body_html)
|
||||
post.edited_at = datetime.utcnow()
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
elif request_json['type'] == 'Delete':
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if post:
|
||||
post.delete_dependencies()
|
||||
db.session.delete(post)
|
||||
else:
|
||||
reply = PostReply.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if reply:
|
||||
reply.body_html = '<p><em>deleted</em></p>'
|
||||
reply.body = 'deleted'
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Instance banned'
|
||||
else:
|
||||
|
|
|
@ -3,7 +3,7 @@ from datetime import date, datetime, timedelta
|
|||
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort
|
||||
from flask_login import login_user, logout_user, current_user, login_required
|
||||
from flask_babel import _
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy import or_, desc
|
||||
|
||||
from app import db, constants
|
||||
from app.activitypub.signature import RsaKeys, HttpSignature
|
||||
|
@ -86,9 +86,9 @@ def show_community(community: Community):
|
|||
mod_list = User.query.filter(User.id.in_(mod_user_ids)).all()
|
||||
|
||||
if current_user.is_anonymous or current_user.ignore_bots:
|
||||
posts = community.posts.filter(Post.from_bot == False).all()
|
||||
posts = community.posts.filter(Post.from_bot == False).order_by(desc(Post.last_active)).all()
|
||||
else:
|
||||
posts = community.posts
|
||||
posts = community.posts.order_by(desc(Post.last_active))
|
||||
|
||||
description = shorten_string(community.description, 150) if community.description else None
|
||||
og_image = community.image.source_url if community.image_id else None
|
||||
|
|
|
@ -353,6 +353,12 @@ class Post(db.Model):
|
|||
def get_by_ap_id(cls, ap_id):
|
||||
return cls.query.filter_by(ap_id=ap_id).first()
|
||||
|
||||
def delete_dependencies(self):
|
||||
db.session.execute(text('DELETE FROM post_reply_vote WHERE post_reply_id IN (SELECT id FROM post_reply WHERE post_id = :post_id)'),
|
||||
{'post_id': self.id})
|
||||
db.session.execute(text('DELETE FROM post_reply WHERE post_id = :post_id'), {'post_id': self.id})
|
||||
db.session.execute(text('DELETE FROM post_vote WHERE post_id = :post_id'), {'post_id': self.id})
|
||||
|
||||
|
||||
class PostReply(db.Model):
|
||||
query_class = FullTextSearchQuery
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
<img src="/static/images/external_link_black.svg" class="external_link_icon" alt="External link" />
|
||||
</a></small></p>
|
||||
{% endif %}
|
||||
<p><small>submitted {{ moment(post.posted_at).fromNow() }} by {{ render_username(post.author) }}</small></p>
|
||||
<p><small>submitted {{ moment(post.posted_at).fromNow() }} by {{ render_username(post.author) }}
|
||||
{% if post.edited_at %} edited {{ moment(post.edited_at).fromNow() }}{% endif %}
|
||||
</small></p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
{% if post.url %}
|
||||
|
@ -50,6 +52,7 @@
|
|||
{% endif %}
|
||||
<p class="small">submitted {{ moment(post.posted_at).fromNow() }} by
|
||||
{{ render_username(post.author) }}
|
||||
{% if post.edited_at %} edited {{ moment(post.edited_at).fromNow() }}{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Reference in a new issue