mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
apf part 33: Log unmatched activity, and delete old code
This commit is contained in:
parent
175094496a
commit
3d4ea6637c
1 changed files with 1 additions and 801 deletions
|
@ -1103,807 +1103,7 @@ def process_inbox_request(request_json, store_ap_json):
|
|||
|
||||
return
|
||||
|
||||
|
||||
# -- below this point is code that will be incrementally replaced to use log_incoming_ap() instead --
|
||||
|
||||
# save all incoming data to aid in debugging and development. Set result to 'success' if things go well
|
||||
activity_log = ActivityPubLog(direction='in', result='failure')
|
||||
|
||||
if 'id' in request_json:
|
||||
activity_log.activity_id = request_json['id']
|
||||
if site.log_activitypub_json:
|
||||
activity_log.activity_json = json.dumps(request_json)
|
||||
activity_log.result = 'processing'
|
||||
db.session.add(activity_log)
|
||||
db.session.commit()
|
||||
|
||||
if 'type' in request_json:
|
||||
activity_log.activity_type = request_json['type']
|
||||
if not instance_blocked(request_json['id']):
|
||||
# Create is new content. Update is often an edit, but Updates from Lemmy can also be new content
|
||||
if request_json['type'] == 'Create' or request_json['type'] == 'Update':
|
||||
activity_log.activity_type = 'Create'
|
||||
user_ap_id = request_json['object']['attributedTo'] if 'attributedTo' in request_json['object'] and isinstance(request_json['object']['attributedTo'], str) else None
|
||||
if user_ap_id is None: # if there is no attributedTo, fall back to the actor on the parent object
|
||||
user_ap_id = request_json['actor'] if 'actor' in request_json and isinstance(request_json['actor'], str) else None
|
||||
if request_json['object']['type'] == 'ChatMessage':
|
||||
activity_log.activity_type = 'Create ChatMessage'
|
||||
sender = find_actor_or_create(user_ap_id)
|
||||
recipient_ap_id = request_json['object']['to'][0]
|
||||
recipient = find_actor_or_create(recipient_ap_id)
|
||||
if sender and recipient and recipient.is_local():
|
||||
if sender.created_recently() or sender.reputation <= -10:
|
||||
activity_log.exception_message = "Sender not eligible to send"
|
||||
elif recipient.has_blocked_user(sender.id) or recipient.has_blocked_instance(sender.instance_id):
|
||||
activity_log.exception_message = "Sender blocked by recipient"
|
||||
else:
|
||||
# Find existing conversation to add to
|
||||
existing_conversation = Conversation.find_existing_conversation(recipient=recipient, sender=sender)
|
||||
if not existing_conversation:
|
||||
existing_conversation = Conversation(user_id=sender.id)
|
||||
existing_conversation.members.append(recipient)
|
||||
existing_conversation.members.append(sender)
|
||||
db.session.add(existing_conversation)
|
||||
db.session.commit()
|
||||
# Save ChatMessage to DB
|
||||
encrypted = request_json['object']['encrypted'] if 'encrypted' in request_json['object'] else None
|
||||
new_message = ChatMessage(sender_id=sender.id, recipient_id=recipient.id, conversation_id=existing_conversation.id,
|
||||
body=request_json['object']['source']['content'],
|
||||
body_html=markdown_to_html(request_json['object']['source']['content']),
|
||||
encrypted=encrypted)
|
||||
db.session.add(new_message)
|
||||
existing_conversation.updated_at = utcnow()
|
||||
db.session.commit()
|
||||
|
||||
# Notify recipient
|
||||
notify = Notification(title=shorten_string('New message from ' + sender.display_name()),
|
||||
url=f'/chat/{existing_conversation.id}#message_{new_message}', user_id=recipient.id,
|
||||
author_id=sender.id)
|
||||
db.session.add(notify)
|
||||
recipient.unread_notifications += 1
|
||||
existing_conversation.read = False
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
try:
|
||||
community_ap_id = ''
|
||||
locations = ['audience', 'cc', 'to']
|
||||
if 'object' in request_json:
|
||||
rjs = [request_json, request_json['object']]
|
||||
else:
|
||||
rjs = [request_json]
|
||||
followers_suffix = '/followers'
|
||||
for rj in rjs:
|
||||
for location in locations:
|
||||
if location in rj:
|
||||
potential_id = rj[location]
|
||||
if isinstance(potential_id, str):
|
||||
if not potential_id.startswith('https://www.w3.org') and not potential_id.endswith(followers_suffix):
|
||||
community_ap_id = potential_id
|
||||
if isinstance(potential_id, list):
|
||||
for c in potential_id:
|
||||
if not c.startswith('https://www.w3.org') and not c.endswith(followers_suffix):
|
||||
community_ap_id = c
|
||||
break
|
||||
if community_ap_id:
|
||||
break
|
||||
if community_ap_id:
|
||||
break
|
||||
if not community_ap_id and 'object' in request_json and \
|
||||
'inReplyTo' in request_json['object'] and request_json['object']['inReplyTo'] is not None:
|
||||
post_being_replied_to = Post.query.filter_by(ap_id=request_json['object']['inReplyTo']).first()
|
||||
if post_being_replied_to:
|
||||
community_ap_id = post_being_replied_to.community.ap_profile_id
|
||||
else:
|
||||
comment_being_replied_to = PostReply.query.filter_by(ap_id=request_json['object']['inReplyTo']).first()
|
||||
if comment_being_replied_to:
|
||||
community_ap_id = comment_being_replied_to.community.ap_profile_id
|
||||
if not community_ap_id and 'object' in request_json and request_json['object']['type'] == 'Video': # PeerTube
|
||||
if 'attributedTo' in request_json['object'] and isinstance(request_json['object']['attributedTo'], list):
|
||||
for a in request_json['object']['attributedTo']:
|
||||
if a['type'] == 'Group':
|
||||
community_ap_id = a['id']
|
||||
if a['type'] == 'Person':
|
||||
user_ap_id = a['id']
|
||||
if not community_ap_id:
|
||||
activity_log.result = 'failure'
|
||||
activity_log.exception_message = 'Unable to extract community'
|
||||
db.session.commit()
|
||||
return
|
||||
except:
|
||||
activity_log.activity_type = 'exception'
|
||||
db.session.commit()
|
||||
return
|
||||
if 'object' in request_json:
|
||||
if not ensure_domains_match(request_json['object']):
|
||||
activity_log.result = 'failure'
|
||||
activity_log.exception_message = 'Domains do not match'
|
||||
db.session.commit()
|
||||
return
|
||||
community = find_actor_or_create(community_ap_id, community_only=True)
|
||||
if community and community.local_only:
|
||||
activity_log.exception_message = 'Remote Create in local_only community'
|
||||
activity_log.result = 'ignored'
|
||||
db.session.commit()
|
||||
return
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
if user and not user.is_local():
|
||||
if community:
|
||||
user.last_seen = community.last_active = site.last_active = utcnow()
|
||||
else:
|
||||
user.last_seen = site.last_active = utcnow()
|
||||
object_type = request_json['object']['type']
|
||||
new_content_types = ['Page', 'Article', 'Link', 'Note', 'Question']
|
||||
if object_type in new_content_types: # create or update a post
|
||||
in_reply_to = request_json['object']['inReplyTo'] if 'inReplyTo' in request_json['object'] else None
|
||||
if not in_reply_to: # Creating a new post
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if post:
|
||||
if request_json['type'] == 'Create':
|
||||
activity_log.result = 'ignored'
|
||||
activity_log.exception_message = 'Create received for already known object'
|
||||
db.session.commit()
|
||||
return
|
||||
else:
|
||||
activity_log.activity_type = 'Update'
|
||||
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:
|
||||
if can_create_post(user, community):
|
||||
try:
|
||||
post = create_post(activity_log, community, request_json, user)
|
||||
if post:
|
||||
announce_activity_to_followers(community, user, request_json)
|
||||
activity_log.result = 'success'
|
||||
except TypeError as e:
|
||||
activity_log.exception_message = 'TypeError. See log file.'
|
||||
current_app.logger.error('TypeError: ' + str(request_json))
|
||||
post = None
|
||||
else:
|
||||
post = None
|
||||
else: # Creating a reply / comment
|
||||
reply = PostReply.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
if reply:
|
||||
if request_json['type'] == 'Create':
|
||||
activity_log.result = 'ignored'
|
||||
activity_log.exception_message = 'Create received for already known object'
|
||||
db.session.commit()
|
||||
return
|
||||
else:
|
||||
activity_log.activity_type = 'Update'
|
||||
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:
|
||||
if community is None: # Mastodon: replies do not specify the community they're in. Attempt to find out the community by looking at the parent object
|
||||
parent_post_id, parent_comment_id, _ = find_reply_parent(in_reply_to)
|
||||
if parent_comment_id:
|
||||
community = PostReply.query.get(parent_comment_id).community
|
||||
elif parent_post_id:
|
||||
community = Post.query.get(parent_post_id).community
|
||||
if can_create_post_reply(user, community):
|
||||
try:
|
||||
post_reply = create_post_reply(activity_log, community, in_reply_to, request_json, user)
|
||||
if post_reply:
|
||||
announce_activity_to_followers(community, user, request_json)
|
||||
except TypeError as e:
|
||||
activity_log.exception_message = 'TypeError. See log file.'
|
||||
current_app.logger.error('TypeError: ' + str(request_json))
|
||||
post = None
|
||||
else:
|
||||
post = None
|
||||
elif object_type == 'Video': # PeerTube: editing a video (PT doesn't seem to Announce these)
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['id']).first()
|
||||
activity_log.activity_type = 'Update'
|
||||
if post:
|
||||
if can_edit(request_json['actor'], post):
|
||||
update_post_from_activity(post, request_json)
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Edit attempt denied'
|
||||
else:
|
||||
activity_log.exception_message = 'Post not found'
|
||||
else:
|
||||
activity_log.exception_message = 'Unacceptable type (create): ' + object_type
|
||||
else:
|
||||
if user is None or community is None:
|
||||
activity_log.exception_message = 'Blocked or unfound user or community'
|
||||
if user and user.is_local():
|
||||
activity_log.exception_message = 'Activity about local content which is already present'
|
||||
activity_log.result = 'ignored'
|
||||
|
||||
# Announce is new content and votes that happened on a remote server.
|
||||
if request_json['type'] == 'Announce':
|
||||
if isinstance(request_json['object'], str): # Mastodon, PeerTube, A.gup.pe
|
||||
activity_log.activity_json = json.dumps(request_json)
|
||||
activity_log.exception_message = 'invalid json?'
|
||||
if 'actor' in request_json:
|
||||
community = find_actor_or_create(request_json['actor'], community_only=True, create_if_not_found=False)
|
||||
if community:
|
||||
post = resolve_remote_post(request_json['object'], community.id, request_json['actor'])
|
||||
elif request_json['object']['type'] == 'Create' or request_json['object']['type'] == 'Update':
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
if 'object' in request_json and 'object' in request_json['object']:
|
||||
if not ensure_domains_match(request_json['object']['object']):
|
||||
activity_log.exception_message = 'Domains do not match'
|
||||
activity_log.result = 'failure'
|
||||
db.session.commit()
|
||||
return
|
||||
user_ap_id = request_json['object']['object']['attributedTo']
|
||||
try:
|
||||
community_ap_id = request_json['object']['audience'] if 'audience' in request_json['object'] else request_json['actor']
|
||||
except KeyError:
|
||||
activity_log.activity_type = 'exception'
|
||||
db.session.commit()
|
||||
return
|
||||
community = find_actor_or_create(community_ap_id, community_only=True)
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
if (user and not user.is_local()) and community:
|
||||
user.last_seen = community.last_active = site.last_active = utcnow()
|
||||
object_type = request_json['object']['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']['object']['inReplyTo'] if 'inReplyTo' in \
|
||||
request_json['object']['object'] else None
|
||||
if not in_reply_to:
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['object']['id']).first()
|
||||
if post:
|
||||
if request_json['object']['type'] == 'Create':
|
||||
activity_log.result = 'ignored'
|
||||
activity_log.exception_message = 'Create received for already known object'
|
||||
db.session.commit()
|
||||
return
|
||||
else:
|
||||
try:
|
||||
update_post_from_activity(post, request_json['object'])
|
||||
except KeyError:
|
||||
activity_log.result = 'exception'
|
||||
db.session.commit()
|
||||
return
|
||||
activity_log.result = 'success'
|
||||
else: # activity was a Create, or an Update sent instead of a Create
|
||||
if can_create_post(user, community):
|
||||
post = create_post(activity_log, community, request_json['object'], user, announce_id=request_json['id'])
|
||||
else:
|
||||
post = None
|
||||
else:
|
||||
reply = PostReply.query.filter_by(ap_id=request_json['object']['object']['id']).first()
|
||||
if reply:
|
||||
if request_json['object']['type'] == 'Create':
|
||||
activity_log.result = 'ignored'
|
||||
activity_log.exception_message = 'Create received for already known object'
|
||||
db.session.commit()
|
||||
return
|
||||
else:
|
||||
try:
|
||||
update_post_reply_from_activity(reply, request_json['object'])
|
||||
except KeyError:
|
||||
activity_log.result = 'exception'
|
||||
db.session.commit()
|
||||
return
|
||||
activity_log.result = 'success'
|
||||
else: # activity was a Create, or an Update sent instead of a Create
|
||||
if can_create_post_reply(user, community):
|
||||
post = create_post_reply(activity_log, community, in_reply_to, request_json['object'], user, announce_id=request_json['id'])
|
||||
else:
|
||||
post = None
|
||||
else:
|
||||
activity_log.exception_message = 'Unacceptable type: ' + object_type
|
||||
else:
|
||||
if user is None or community is None:
|
||||
activity_log.exception_message = 'Blocked or unfound user or community'
|
||||
if user and user.is_local():
|
||||
activity_log.exception_message = 'Activity about local content which is already present'
|
||||
activity_log.result = 'ignored'
|
||||
|
||||
elif request_json['object']['type'] == 'Like' or request_json['object']['type'] == 'EmojiReact':
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
user_ap_id = request_json['object']['actor']
|
||||
liked_ap_id = request_json['object']['object']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
liked = find_liked_object(liked_ap_id)
|
||||
|
||||
if user is None:
|
||||
activity_log.exception_message = 'Blocked or unfound user'
|
||||
elif liked is None:
|
||||
activity_log.exception_message = 'Unfound object ' + liked_ap_id
|
||||
elif user.is_local():
|
||||
activity_log.exception_message = 'Activity about local content which is already present'
|
||||
activity_log.result = 'ignored'
|
||||
elif can_upvote(user, liked.community):
|
||||
# insert into voted table
|
||||
if liked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif liked is not None and isinstance(liked, (Post, PostReply)):
|
||||
liked.vote(user, 'upvote')
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
else:
|
||||
activity_log.exception_message = 'Cannot upvote this'
|
||||
activity_log.result = 'ignored'
|
||||
|
||||
elif request_json['object']['type'] == 'Dislike':
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
if site.enable_downvotes is False:
|
||||
activity_log.exception_message = 'Dislike ignored because of allow_dislike setting'
|
||||
else:
|
||||
user_ap_id = request_json['object']['actor']
|
||||
liked_ap_id = request_json['object']['object']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
disliked = find_liked_object(liked_ap_id)
|
||||
if user is None:
|
||||
activity_log.exception_message = 'Blocked or unfound user'
|
||||
elif disliked is None:
|
||||
activity_log.exception_message = 'Unfound object ' + liked_ap_id
|
||||
elif user.is_local():
|
||||
activity_log.exception_message = 'Activity about local content which is already present'
|
||||
activity_log.result = 'ignored'
|
||||
elif can_downvote(user, disliked.community, site):
|
||||
# insert into voted table
|
||||
if disliked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif isinstance(disliked, (Post, PostReply)):
|
||||
disliked.vote(user, 'downvote')
|
||||
activity_log.result = 'success'
|
||||
# todo: recalculate 'hotness' of liked post/reply
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
else:
|
||||
activity_log.exception_message = 'Cannot downvote this'
|
||||
activity_log.result = 'ignored'
|
||||
elif request_json['object']['type'] == 'Delete':
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
user_ap_id = request_json['object']['actor']
|
||||
to_be_deleted_ap_id = request_json['object']['object']
|
||||
if isinstance(to_be_deleted_ap_id, dict):
|
||||
activity_log.result = 'failure'
|
||||
activity_log.exception_message = 'dict instead of string ' + str(to_be_deleted_ap_id)
|
||||
else:
|
||||
delete_post_or_comment(user_ap_id, to_be_deleted_ap_id, activity_log.id)
|
||||
elif request_json['object']['type'] == 'Page': # Sent for Mastodon's benefit
|
||||
activity_log.result = 'ignored'
|
||||
activity_log.exception_message = 'Intended for Mastodon'
|
||||
elif request_json['object']['type'] == 'Note': # Never sent?
|
||||
activity_log.result = 'ignored'
|
||||
activity_log.exception_message = 'Intended for Mastodon'
|
||||
elif request_json['object']['type'] == 'Undo':
|
||||
if request_json['object']['object']['type'] == 'Like' or request_json['object']['object']['type'] == 'Dislike':
|
||||
activity_log.activity_type = request_json['object']['object']['type']
|
||||
user_ap_id = request_json['object']['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
post = None
|
||||
comment = None
|
||||
target_ap_id = request_json['object']['object']['object'] # object object object!
|
||||
post = undo_vote(activity_log, comment, post, target_ap_id, user)
|
||||
elif request_json['object']['object']['type'] == 'Delete':
|
||||
if 'object' in request_json and 'object' in request_json['object']:
|
||||
restore_post_or_comment(request_json['object']['object'], activity_log.id)
|
||||
elif request_json['object']['object']['type'] == 'Block':
|
||||
activity_log.activity_type = 'Undo User Ban'
|
||||
deletor_ap_id = request_json['object']['object']['actor']
|
||||
user_ap_id = request_json['object']['object']['object']
|
||||
target = request_json['object']['object']['target']
|
||||
if target == request_json['actor'] and user_ap_id.startswith('https://' + current_app.config['SERVER_NAME']):
|
||||
unban_local_user(deletor_ap_id, user_ap_id, target)
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['object']['type'] == 'Lock' and 'object' in request_json['object']['object']:
|
||||
activity_log.activity_type = 'Post Unlock'
|
||||
mod_ap_id = request_json['object']['object']['actor']
|
||||
post_id = request_json['object']['object']['object']
|
||||
lock_post(mod_ap_id, post_id, True)
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Add' and 'target' in request_json['object']:
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
target = request_json['object']['target']
|
||||
community = Community.query.filter_by(ap_public_url=request_json['actor']).first()
|
||||
if community:
|
||||
featured_url = community.ap_featured_url
|
||||
moderators_url = community.ap_moderators_url
|
||||
if target == featured_url:
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['object']).first()
|
||||
if post:
|
||||
post.sticky = True
|
||||
activity_log.result = 'success'
|
||||
if target == moderators_url:
|
||||
user = find_actor_or_create(request_json['object']['object'])
|
||||
if user:
|
||||
existing_membership = CommunityMember.query.filter_by(community_id=community.id, user_id=user.id).first()
|
||||
if existing_membership:
|
||||
existing_membership.is_moderator = True
|
||||
else:
|
||||
new_membership = CommunityMember(community_id=community.id, user_id=user.id, is_moderator=True)
|
||||
db.session.add(new_membership)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Remove' and 'target' in request_json['object']:
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
target = request_json['object']['target']
|
||||
community = Community.query.filter_by(ap_public_url=request_json['actor']).first()
|
||||
if community:
|
||||
featured_url = community.ap_featured_url
|
||||
moderators_url = community.ap_moderators_url
|
||||
if target == featured_url:
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['object']).first()
|
||||
if post:
|
||||
post.sticky = False
|
||||
activity_log.result = 'success'
|
||||
if target == moderators_url:
|
||||
user = find_actor_or_create(request_json['object']['object'], create_if_not_found=False)
|
||||
if user:
|
||||
existing_membership = CommunityMember.query.filter_by(community_id=community.id, user_id=user.id).first()
|
||||
if existing_membership:
|
||||
existing_membership.is_moderator = False
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Block' and 'target' in request_json['object']:
|
||||
activity_log.activity_type = 'User Ban'
|
||||
deletor_ap_id = request_json['object']['actor']
|
||||
user_ap_id = request_json['object']['object']
|
||||
target = request_json['object']['target']
|
||||
remove_data = request_json['object']['removeData']
|
||||
if target == request_json['actor']:
|
||||
if remove_data == True:
|
||||
remove_data_from_banned_user(deletor_ap_id, user_ap_id, target)
|
||||
if user_ap_id.startswith('https://' + current_app.config['SERVER_NAME']):
|
||||
ban_local_user(deletor_ap_id, user_ap_id, target, request_json['object'])
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Lock' and 'object' in request_json['object']:
|
||||
activity_log.activity_type = 'Post Lock'
|
||||
mod_ap_id = request_json['object']['actor']
|
||||
post_id = request_json['object']['object']
|
||||
lock_post(mod_ap_id, post_id, False)
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Invalid type for Announce'
|
||||
|
||||
# Follow: remote user wants to join/follow one of our communities
|
||||
elif request_json['type'] == 'Follow': # Follow is when someone wants to join a community
|
||||
user_ap_id = request_json['actor']
|
||||
community_ap_id = request_json['object']
|
||||
follow_id = request_json['id']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
community = find_actor_or_create(community_ap_id, community_only=True)
|
||||
if isinstance(community, Community):
|
||||
if community and community.local_only and user:
|
||||
activity_log.exception_message = 'Local only cannot be followed by remote users'
|
||||
|
||||
# send reject message to deny the follow
|
||||
reject = {
|
||||
"@context": default_context(),
|
||||
"actor": community.public_url(),
|
||||
"to": [
|
||||
user.public_url()
|
||||
],
|
||||
"object": {
|
||||
"actor": user.public_url(),
|
||||
"to": None,
|
||||
"object": community.public_url(),
|
||||
"type": "Follow",
|
||||
"id": follow_id
|
||||
},
|
||||
"type": "Reject",
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/reject/" + gibberish(32)
|
||||
}
|
||||
# Lemmy doesn't yet understand Reject/Follow, so send without worrying about response for now.
|
||||
post_request(user.ap_inbox_url, reject, community.private_key, f"{community.public_url()}#main-key")
|
||||
else:
|
||||
if user is not None and community is not None:
|
||||
# check if user is banned from this community
|
||||
banned = CommunityBan.query.filter_by(user_id=user.id, community_id=community.id).first()
|
||||
if banned is None:
|
||||
user.last_seen = utcnow()
|
||||
if community_membership(user, community) != SUBSCRIPTION_MEMBER:
|
||||
member = CommunityMember(user_id=user.id, community_id=community.id)
|
||||
db.session.add(member)
|
||||
db.session.commit()
|
||||
cache.delete_memoized(community_membership, user, community)
|
||||
# send accept message to acknowledge the follow
|
||||
accept = {
|
||||
"@context": default_context(),
|
||||
"actor": community.public_url(),
|
||||
"to": [
|
||||
user.public_url()
|
||||
],
|
||||
"object": {
|
||||
"actor": user.public_url(),
|
||||
"to": None,
|
||||
"object": community.public_url(),
|
||||
"type": "Follow",
|
||||
"id": follow_id
|
||||
},
|
||||
"type": "Accept",
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/accept/" + gibberish(32)
|
||||
}
|
||||
if post_request(user.ap_inbox_url, accept, community.private_key, f"{community.public_url()}#main-key") is True:
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Error sending Accept'
|
||||
else:
|
||||
activity_log.exception_message = 'user is banned from this community'
|
||||
elif isinstance(community, User): # Pixelfed sends follow requests to the shared inbox, not the user inbox...
|
||||
if current_app.debug:
|
||||
process_user_follow_request(request_json, activity_log.id, user.id)
|
||||
else:
|
||||
process_user_follow_request.delay(request_json, activity_log.id, user.id)
|
||||
# Accept: remote server is accepting our previous follow request
|
||||
elif request_json['type'] == 'Accept':
|
||||
if isinstance(request_json['object'], str): # a.gup.pe accepts using a string with the ID of the follow request
|
||||
join_request_parts = request_json['object'].split('/')
|
||||
join_request = CommunityJoinRequest.query.get(join_request_parts[-1])
|
||||
existing_membership = CommunityMember.query.filter_by(user_id=join_request.user_id,
|
||||
community_id=join_request.community_id).first()
|
||||
if not existing_membership:
|
||||
member = CommunityMember(user_id=join_request.user_id, community_id=join_request.community_id)
|
||||
db.session.add(member)
|
||||
community.subscriptions_count += 1
|
||||
db.session.commit()
|
||||
cache.delete_memoized(community_membership, User.query.get(join_request.user_id), Community.query.get(join_request.community_id))
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Follow':
|
||||
community_ap_id = request_json['actor']
|
||||
user_ap_id = request_json['object']['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
community = find_actor_or_create(community_ap_id, community_only=True)
|
||||
if user and community:
|
||||
join_request = CommunityJoinRequest.query.filter_by(user_id=user.id, community_id=community.id).first()
|
||||
if join_request:
|
||||
existing_membership = CommunityMember.query.filter_by(user_id=user.id, community_id=community.id).first()
|
||||
if not existing_membership:
|
||||
member = CommunityMember(user_id=user.id, community_id=community.id)
|
||||
db.session.add(member)
|
||||
community.subscriptions_count += 1
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
cache.delete_memoized(community_membership, user, community)
|
||||
|
||||
elif request_json['type'] == 'Undo':
|
||||
if request_json['object']['type'] == 'Follow': # Unsubscribe from a community
|
||||
community_ap_id = request_json['object']['object']
|
||||
user_ap_id = request_json['object']['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
community = find_actor_or_create(community_ap_id, community_only=True)
|
||||
if user and community:
|
||||
user.last_seen = utcnow()
|
||||
member = CommunityMember.query.filter_by(user_id=user.id, community_id=community.id).first()
|
||||
join_request = CommunityJoinRequest.query.filter_by(user_id=user.id, community_id=community.id).first()
|
||||
if member:
|
||||
db.session.delete(member)
|
||||
community.subscriptions_count -= 1
|
||||
if join_request:
|
||||
db.session.delete(join_request)
|
||||
db.session.commit()
|
||||
cache.delete_memoized(community_membership, user, community)
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Like': # Undoing an upvote or downvote
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
user_ap_id = request_json['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
post = None
|
||||
comment = None
|
||||
target_ap_id = request_json['object']['object']
|
||||
post_or_comment = undo_vote(activity_log, comment, post, target_ap_id, user)
|
||||
if post_or_comment:
|
||||
announce_activity_to_followers(post_or_comment.community, user, request_json)
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Dislike': # Undoing a downvote - probably unused
|
||||
activity_log.activity_type = request_json['object']['type']
|
||||
user_ap_id = request_json['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
post = None
|
||||
comment = None
|
||||
target_ap_id = request_json['object']['object']
|
||||
post_or_comment = undo_downvote(activity_log, comment, post, target_ap_id, user)
|
||||
if post_or_comment:
|
||||
announce_activity_to_followers(post_or_comment.community, user, request_json)
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Block': # Undoing a ban
|
||||
activity_log.activity_type = 'Undo User Ban'
|
||||
deletor_ap_id = request_json['object']['actor']
|
||||
user_ap_id = request_json['object']['object']
|
||||
target = request_json['object']['target']
|
||||
if user_ap_id.startswith('https://' + current_app.config['SERVER_NAME']):
|
||||
unban_local_user(deletor_ap_id, user_ap_id, target)
|
||||
activity_log.result = 'success'
|
||||
elif request_json['object']['type'] == 'Delete': # undoing a delete
|
||||
activity_log.activity_type = 'Restore'
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['object']).first()
|
||||
if post:
|
||||
deletor = find_actor_or_create(request_json['object']['actor'], create_if_not_found=False)
|
||||
if deletor:
|
||||
if post.author.id == deletor.id or post.community.is_moderator(deletor) or post.community.is_instance_admin(deletor):
|
||||
post.deleted = False
|
||||
post.deleted_by = None
|
||||
post.author.post_count += 1
|
||||
post.community.post_count += 1
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Restore attempt denied'
|
||||
else:
|
||||
activity_log.exception_message = 'Restorer did not already exist'
|
||||
else:
|
||||
reply = PostReply.query.filter_by(ap_id=request_json['object']['object']).first()
|
||||
if reply:
|
||||
deletor = find_actor_or_create(request_json['object']['actor'], create_if_not_found=False)
|
||||
if deletor:
|
||||
if reply.author.id == deletor.id or reply.community.is_moderator(deletor) or reply.community.is_instance_admin(deletor):
|
||||
reply.deleted = False
|
||||
reply.deleted_by = None
|
||||
if not reply.author.bot:
|
||||
reply.post.reply_count += 1
|
||||
reply.author.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 = 'Restore attempt denied'
|
||||
else:
|
||||
activity_log.exception_message = 'Restorer did not already exist'
|
||||
else:
|
||||
activity_log.exception_message = 'Object not found, or object was not a post or a reply'
|
||||
elif request_json['type'] == 'Delete':
|
||||
if isinstance(request_json['object'], str):
|
||||
ap_id = request_json['object'] # lemmy
|
||||
else:
|
||||
ap_id = request_json['object']['id'] # kbin
|
||||
post = Post.query.filter_by(ap_id=ap_id).first()
|
||||
# Delete post
|
||||
if post:
|
||||
deletor = find_actor_or_create(request_json['actor'], create_if_not_found=False)
|
||||
if deletor:
|
||||
if post.author.id == deletor.id or post.community.is_moderator(deletor) or post.community.is_instance_admin(deletor):
|
||||
post.deleted = True
|
||||
post.delted_by = deletor.id
|
||||
post.author.post_count -= 1
|
||||
post.community.post_count -= 1
|
||||
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)
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Delete attempt denied'
|
||||
else:
|
||||
activity_log.exception_message = 'Deletor did not already exist'
|
||||
else:
|
||||
# Delete PostReply
|
||||
reply = PostReply.query.filter_by(ap_id=ap_id).first()
|
||||
if reply:
|
||||
deletor = find_actor_or_create(request_json['actor'], create_if_not_found=False)
|
||||
if deletor:
|
||||
if reply.author.id == deletor.id or reply.community.is_moderator(deletor) or reply.community.is_instance_admin(deletor):
|
||||
reply.deleted = True
|
||||
reply.deleted_by = deletor.id
|
||||
if not reply.author.bot:
|
||||
reply.post.reply_count -= 1
|
||||
reply.author.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:
|
||||
activity_log.exception_message = 'Deletor did not already exist'
|
||||
else:
|
||||
# Delete User
|
||||
user = find_actor_or_create(ap_id, create_if_not_found=False)
|
||||
if user:
|
||||
user.deleted = True
|
||||
user.delete_dependencies()
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Delete: cannot find ' + ap_id
|
||||
|
||||
elif request_json['type'] == 'Like' or request_json['type'] == 'EmojiReact': # Upvote
|
||||
activity_log.activity_type = request_json['type']
|
||||
user_ap_id = request_json['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
liked = find_liked_object(request_json['object'])
|
||||
if user is None:
|
||||
activity_log.exception_message = 'Blocked or unfound user'
|
||||
elif liked is None:
|
||||
activity_log.exception_message = 'Unfound object ' + request_json['object']
|
||||
elif user.is_local():
|
||||
activity_log.exception_message = 'Activity about local content which is already present'
|
||||
activity_log.result = 'ignored'
|
||||
elif can_upvote(user, liked.community):
|
||||
# insert into voted table
|
||||
if liked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif liked is not None and isinstance(liked, (Post, PostReply)):
|
||||
liked.vote(user, 'upvote')
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
if activity_log.result == 'success':
|
||||
announce_activity_to_followers(liked.community, user, request_json)
|
||||
else:
|
||||
activity_log.exception_message = 'Cannot upvote this'
|
||||
activity_log.result = 'ignored'
|
||||
elif request_json['type'] == 'Dislike': # Downvote
|
||||
if get_setting('allow_dislike', True) is False:
|
||||
activity_log.exception_message = 'Dislike ignored because of allow_dislike setting'
|
||||
else:
|
||||
activity_log.activity_type = request_json['type']
|
||||
user_ap_id = request_json['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
target_ap_id = request_json['object']
|
||||
disliked = find_liked_object(target_ap_id)
|
||||
if user is None:
|
||||
activity_log.exception_message = 'Blocked or unfound user'
|
||||
elif disliked is None:
|
||||
activity_log.exception_message = 'Unfound object' + target_ap_id
|
||||
elif user.is_local():
|
||||
activity_log.exception_message = 'Activity about local content which is already present'
|
||||
activity_log.result = 'ignored'
|
||||
elif can_downvote(user, disliked.community, site):
|
||||
# insert into voted table
|
||||
if disliked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif isinstance(disliked, (Post, PostReply)):
|
||||
disliked.vote(user, 'downvote')
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
if activity_log.result == 'success':
|
||||
announce_activity_to_followers(disliked.community, user, request_json)
|
||||
else:
|
||||
activity_log.exception_message = 'Cannot downvote this'
|
||||
activity_log.result = 'ignored'
|
||||
elif request_json['type'] == 'Flag': # Reported content
|
||||
activity_log.activity_type = 'Report'
|
||||
user_ap_id = request_json['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
target_ap_id = request_json['object']
|
||||
reported = find_reported_object(target_ap_id)
|
||||
if user and reported:
|
||||
process_report(user, reported, request_json, activity_log)
|
||||
announce_activity_to_followers(reported.community, user, request_json)
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Report ignored due to missing user or content'
|
||||
elif request_json['type'] == 'Block':
|
||||
activity_log.activity_type = 'User Ban'
|
||||
deletor_ap_id = request_json['actor']
|
||||
user_ap_id = request_json['object']
|
||||
target = request_json['target']
|
||||
remove_data = request_json['removeData']
|
||||
if remove_data == True:
|
||||
remove_data_from_banned_user(deletor_ap_id, user_ap_id, target)
|
||||
if user_ap_id.startswith('https://' + current_app.config['SERVER_NAME']):
|
||||
ban_local_user(deletor_ap_id, user_ap_id, target, request_json)
|
||||
activity_log.result = 'success'
|
||||
|
||||
# Flush the caches of any major object that was created. To be sure.
|
||||
if 'user' in vars() and user is not None:
|
||||
if user.instance_id and user.instance_id != 1:
|
||||
user.instance.last_seen = utcnow()
|
||||
# user.instance.ip_address = ip_address
|
||||
user.instance.dormant = False
|
||||
user.instance.gone_forever = False
|
||||
user.instance.failures = 0
|
||||
else:
|
||||
activity_log.exception_message = 'Instance blocked'
|
||||
|
||||
if activity_log.exception_message is not None and activity_log.result == 'processing':
|
||||
activity_log.result = 'failure'
|
||||
# Don't log successful json - save space
|
||||
if site.log_activitypub_json and activity_log.result == 'success' and not current_app.debug:
|
||||
activity_log.activity_json = ''
|
||||
db.session.commit()
|
||||
log_incoming_ap(request_json['id'], APLOG_MONITOR, APLOG_PROCESSING, request_json if store_ap_json else None, 'Unmatched activity')
|
||||
|
||||
|
||||
@celery.task
|
||||
|
|
Loading…
Add table
Reference in a new issue