pyfedi/app/shared/tasks/likes.py
2024-11-02 23:56:56 +00:00

108 lines
3.8 KiB
Python

from app import cache, celery
from app.activitypub.signature import default_context, post_request
from app.models import CommunityBan, Post, PostReply, User
from app.utils import gibberish, instance_banned, recently_upvoted_posts, recently_downvoted_posts, recently_upvoted_post_replies, recently_downvoted_post_replies
from flask import current_app
""" JSON format
{
'id':
'type':
'actor':
'object':
'@context': (outer object only)
'audience': (inner object only)
'to': [] (announce only)
'cc': [] (announce only)
}
"""
@celery.task
def vote_for_post(send_async, user_id, post_id, vote_to_undo, vote_direction):
post = Post.query.filter_by(id=post_id).one()
cache.delete_memoized(recently_upvoted_posts, user_id)
cache.delete_memoized(recently_downvoted_posts, user_id)
send_vote(user_id, post, vote_to_undo, vote_direction)
@celery.task
def vote_for_reply(send_async, user_id, reply_id, vote_to_undo, vote_direction):
reply = PostReply.query.filter_by(id=reply_id).one()
cache.delete_memoized(recently_upvoted_post_replies, user_id)
cache.delete_memoized(recently_downvoted_post_replies, user_id)
send_vote(user_id, reply, vote_to_undo, vote_direction)
def send_vote(user_id, object, vote_to_undo, vote_direction):
user = User.query.filter_by(id=user_id).one()
community = object.community
if community.local_only or not community.instance.online():
return
banned = CommunityBan.query.filter_by(user_id=user_id, community_id=community.id).first()
if banned:
return
if not community.is_local():
if user.has_blocked_instance(community.instance.id) or instance_banned(community.instance.domain):
return
if vote_to_undo:
type=vote_to_undo
else:
type = 'Like' if vote_direction == 'upvote' else 'Dislike'
vote_id = f"https://{current_app.config['SERVER_NAME']}/activities/{type.lower()}/{gibberish(15)}"
actor = user.public_url(not(community.instance.votes_are_public() and user.vote_privately()))
vote = {
'id': vote_id,
'type': type,
'actor': actor,
'object': object.public_url(),
'@context': default_context(),
'audience': community.public_url()
}
if vote_to_undo:
del vote['@context']
undo_id = f"https://{current_app.config['SERVER_NAME']}/activities/undo/{gibberish(15)}"
undo = {
'id': undo_id,
'type': 'Undo',
'actor': actor,
'object': vote,
'@context': default_context(),
'audience': community.public_url()
}
if community.is_local():
if vote_to_undo:
del undo['@context']
object=undo
else:
del vote['@context']
object=vote
announce_id = f"https://{current_app.config['SERVER_NAME']}/activities/announce/{gibberish(15)}"
actor = community.public_url()
to = ["https://www.w3.org/ns/activitystreams#Public"]
cc = [community.ap_followers_url]
announce = {
'id': announce_id,
'type': 'Announce',
'actor': actor,
'object': object,
'@context': default_context(),
'to': to,
'cc': cc
}
for instance in community.following_instances():
if instance.inbox and instance.online() and not user.has_blocked_instance(instance.id) and not instance_banned(instance.domain):
post_request(instance.inbox, announce, community.private_key, community.public_url() + '#main-key')
else:
payload = undo if vote_to_undo else vote
post_request(community.ap_inbox_url, payload, user.private_key,
user.public_url(not(community.instance.votes_are_public() and user.vote_privately())) + '#main-key')