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
|
return
|
||||||
|
|
||||||
|
log_incoming_ap(request_json['id'], APLOG_MONITOR, APLOG_PROCESSING, request_json if store_ap_json else None, 'Unmatched activity')
|
||||||
# -- 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()
|
|
||||||
|
|
||||||
|
|
||||||
@celery.task
|
@celery.task
|
||||||
|
|
Loading…
Add table
Reference in a new issue