mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
poll - federation #181
This commit is contained in:
parent
79798b28e3
commit
0d9d4f12cb
4 changed files with 111 additions and 8 deletions
|
@ -549,7 +549,7 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
user.last_seen = community.last_active = site.last_active = utcnow()
|
||||
|
||||
object_type = request_json['object']['type']
|
||||
new_content_types = ['Page', 'Article', 'Link', 'Note']
|
||||
new_content_types = ['Page', 'Article', 'Link', 'Note', 'Question']
|
||||
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:
|
||||
|
|
|
@ -13,7 +13,7 @@ from sqlalchemy import text, func
|
|||
from app import db, cache, constants, celery
|
||||
from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance, utcnow, \
|
||||
PostVote, PostReplyVote, ActivityPubLog, Notification, Site, CommunityMember, InstanceRole, Report, Conversation, \
|
||||
Language, Tag
|
||||
Language, Tag, Poll, PollChoice
|
||||
from app.activitypub.signature import signed_get_request
|
||||
import time
|
||||
import base64
|
||||
|
@ -179,7 +179,25 @@ def post_to_activity(post: Post, community: Community):
|
|||
if post.image_id is not None:
|
||||
activity_data["object"]["object"]["image"] = {"url": post.image.view_url(), "type": "Image"}
|
||||
if post.image.alt_text:
|
||||
activity_data["object"]["object"]["image"]['altText'] = post.image.alt_text
|
||||
activity_data["object"]["object"]["image"]['name'] = post.image.alt_text
|
||||
if post.type == POST_TYPE_POLL:
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
activity_data["object"]["object"]['type'] = 'Question'
|
||||
mode = 'oneOf' if poll.mode == 'single' else 'anyOf'
|
||||
choices = []
|
||||
for choice in PollChoice.query.filter_by(post_id=post.id).order_by(PollChoice.sort_order).all():
|
||||
choices.append({
|
||||
"type": "Note",
|
||||
"name": choice.choice_text,
|
||||
"replies": {
|
||||
"type": "Collection",
|
||||
"totalItems": choice.num_votes
|
||||
}
|
||||
})
|
||||
activity_data["object"]["object"][mode] = choices
|
||||
activity_data["object"]["object"]['endTime'] = ap_datetime(poll.end_poll)
|
||||
activity_data["object"]["object"]['votersCount'] = poll.total_votes()
|
||||
|
||||
return activity_data
|
||||
|
||||
|
||||
|
@ -1554,6 +1572,21 @@ def create_post(activity_log: ActivityPubLog, community: Community, request_json
|
|||
activity_log.result = 'success'
|
||||
db.session.commit()
|
||||
|
||||
# Polls need to be processed quite late because they need a post_id to refer to
|
||||
if request_json['object']['type'] == 'Question':
|
||||
post.type = POST_TYPE_POLL
|
||||
mode = 'single'
|
||||
if 'anyOf' in request_json['object']:
|
||||
mode = 'multiple'
|
||||
poll = Poll(post_id=post.id, end_poll=request_json['object']['endTime'], mode=mode, local_only=False)
|
||||
db.session.add(poll)
|
||||
i = 1
|
||||
for choice_ap in request_json['object']['oneOf' if mode == 'single' else 'anyOf']:
|
||||
new_choice = PollChoice(post_id=post.id, choice_text=choice_ap['name'], sort_order=i)
|
||||
db.session.add(new_choice)
|
||||
i += 1
|
||||
db.session.commit()
|
||||
|
||||
if post.image_id:
|
||||
make_image_sizes(post.image_id, 150, 512, 'posts') # the 512 sized image is for masonry view
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@ from app.community.util import search_for_community, actor_to_community, \
|
|||
delete_post_from_community, delete_post_reply_from_community, community_in_list
|
||||
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE, \
|
||||
SUBSCRIPTION_PENDING, SUBSCRIPTION_MODERATOR, REPORT_STATE_NEW, REPORT_STATE_ESCALATED, REPORT_STATE_RESOLVED, \
|
||||
REPORT_STATE_DISCARDED, POST_TYPE_VIDEO, NOTIF_COMMUNITY
|
||||
REPORT_STATE_DISCARDED, POST_TYPE_VIDEO, NOTIF_COMMUNITY, POST_TYPE_POLL
|
||||
from app.inoculation import inoculation
|
||||
from app.models import User, Community, CommunityMember, CommunityJoinRequest, CommunityBan, Post, \
|
||||
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog, Topic, Conversation, PostReply, \
|
||||
NotificationSubscription, UserFollower, Instance, Language
|
||||
NotificationSubscription, UserFollower, Instance, Language, Poll, PollChoice
|
||||
from app.community import bp
|
||||
from app.user.utils import search_for_user
|
||||
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
||||
|
@ -805,6 +805,7 @@ def add_poll_post(actor):
|
|||
abort(401)
|
||||
post = Post(user_id=current_user.id, community_id=form.communities.data, instance_id=1)
|
||||
save_post(form, post, 'poll')
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
community.post_count += 1
|
||||
community.last_active = g.site.last_active = utcnow()
|
||||
db.session.commit()
|
||||
|
@ -815,9 +816,9 @@ def add_poll_post(actor):
|
|||
|
||||
notify_about_post(post)
|
||||
|
||||
if not community.local_only:
|
||||
if not community.local_only and not poll.local_only:
|
||||
federate_post(community, post)
|
||||
federate_post_to_user_followers(post)
|
||||
federate_post_to_user_followers(post)
|
||||
|
||||
return redirect(f"/post/{post.id}")
|
||||
else:
|
||||
|
@ -897,6 +898,23 @@ def federate_post(community, post):
|
|||
if post.type == POST_TYPE_IMAGE:
|
||||
page['attachment'] = [{'type': 'Link',
|
||||
'href': post.image.source_url}] # source_url is always a https link, no need for .replace() as done above
|
||||
|
||||
if post.type == POST_TYPE_POLL:
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
page['type'] = 'Question'
|
||||
page['endTime'] = ap_datetime(poll.end_poll)
|
||||
page['votersCount'] = 0
|
||||
choices = []
|
||||
for choice in PollChoice.query.filter_by(post_id=post.id).all():
|
||||
choices.append({
|
||||
"type": "Note",
|
||||
"name": choice.choice_text,
|
||||
"replies": {
|
||||
"type": "Collection",
|
||||
"totalItems": 0
|
||||
}
|
||||
})
|
||||
page['oneOf' if poll.mode == 'single' else 'anyOf'] = choices
|
||||
if not community.is_local(): # this is a remote community - send the post to the instance that hosts it
|
||||
success = post_request(community.ap_inbox_url, create, current_user.private_key,
|
||||
current_user.ap_profile_id + '#main-key')
|
||||
|
@ -989,8 +1007,25 @@ def federate_post_to_user_followers(post):
|
|||
if post.body_html:
|
||||
note['content'] = note['content'] + '<p>' + post.body_html + '</p>'
|
||||
|
||||
if post.type == POST_TYPE_POLL:
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
note['type'] = 'Question'
|
||||
note['endTime'] = ap_datetime(poll.end_poll)
|
||||
note['votersCount'] = 0
|
||||
choices = []
|
||||
for choice in PollChoice.query.filter_by(post_id=post.id).all():
|
||||
choices.append({
|
||||
"type": "Note",
|
||||
"name": choice.choice_text,
|
||||
"replies": {
|
||||
"type": "Collection",
|
||||
"totalItems": 0
|
||||
}
|
||||
})
|
||||
note['oneOf' if poll.mode == 'single' else 'anyOf'] = choices
|
||||
|
||||
instances = Instance.query.join(User, User.instance_id == Instance.id).join(UserFollower, UserFollower.remote_user_id == User.id)
|
||||
instances = instances.filter(UserFollower.local_user_id == post.user_id)
|
||||
instances = instances.filter(UserFollower.local_user_id == post.user_id).filter(Instance.gone_forever == False)
|
||||
for i in instances:
|
||||
post_request(i.inbox, create, current_user.private_key, current_user.ap_profile_id + '#main-key')
|
||||
|
||||
|
|
|
@ -1233,6 +1233,8 @@ def post_edit_poll_post(post_id: int):
|
|||
)
|
||||
else:
|
||||
abort(401)
|
||||
|
||||
|
||||
def federate_post_update(post):
|
||||
page_json = {
|
||||
'type': 'Page',
|
||||
|
@ -1288,6 +1290,23 @@ def federate_post_update(post):
|
|||
if post.type == POST_TYPE_IMAGE:
|
||||
page_json['attachment'] = [{'type': 'Link',
|
||||
'href': post.image.source_url}] # source_url is always a https link, no need for .replace() as done above
|
||||
if post.type == POST_TYPE_POLL:
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
page_json['type'] = 'Question'
|
||||
page_json['endTime'] = ap_datetime(poll.end_poll)
|
||||
page_json['votersCount'] = 0
|
||||
choices = []
|
||||
for choice in PollChoice.query.filter_by(post_id=post.id).all():
|
||||
choices.append({
|
||||
"type": "Note",
|
||||
"name": choice.choice_text,
|
||||
"replies": {
|
||||
"type": "Collection",
|
||||
"totalItems": 0
|
||||
}
|
||||
})
|
||||
page_json['oneOf' if poll.mode == 'single' else 'anyOf'] = choices
|
||||
|
||||
if not post.community.is_local(): # this is a remote community, send it to the instance that hosts it
|
||||
success = post_request(post.community.ap_inbox_url, update_json, current_user.private_key,
|
||||
current_user.ap_profile_id + '#main-key')
|
||||
|
@ -1369,6 +1388,22 @@ def federate_post_edit_to_user_followers(post):
|
|||
note['attachment'] = [{'type': 'Document', 'url': post.image.source_url, 'name': post.image.alt_text}]
|
||||
else:
|
||||
note['attachment'] = [{'type': 'Document', 'url': post.image.source_url}]
|
||||
elif post.type == POST_TYPE_POLL:
|
||||
poll = Poll.query.filter_by(post_id=post.id).first()
|
||||
note['type'] = 'Question'
|
||||
note['endTime'] = ap_datetime(poll.end_poll)
|
||||
note['votersCount'] = 0
|
||||
choices = []
|
||||
for choice in PollChoice.query.filter_by(post_id=post.id).all():
|
||||
choices.append({
|
||||
"type": "Note",
|
||||
"name": choice.choice_text,
|
||||
"replies": {
|
||||
"type": "Collection",
|
||||
"totalItems": 0
|
||||
}
|
||||
})
|
||||
note['oneOf' if poll.mode == 'single' else 'anyOf'] = choices
|
||||
|
||||
if post.body_html:
|
||||
note['content'] = note['content'] + '<p>' + post.body_html + '</p>'
|
||||
|
|
Loading…
Add table
Reference in a new issue