Add conversation-based forwarding for limited visibility statuses through bearcaps

This commit is contained in:
Eugen Rochko 2020-08-26 03:16:47 +02:00
parent 52157fdcba
commit 7cd4ed7d42
26 changed files with 430 additions and 78 deletions

View file

@ -90,6 +90,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
fetch_replies(@status)
check_for_spam
distribute(@status)
forward_for_conversation
forward_for_reply
end
@ -114,7 +115,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
sensitive: @object['sensitive'] || false,
visibility: visibility_from_audience,
thread: replied_to_status,
conversation: conversation_from_uri(@object['conversation']),
conversation: conversation_from_context,
media_attachment_ids: process_attachments.take(4).map(&:id),
poll: process_poll,
}
@ -122,8 +123,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end
def process_audience
conversation_uri = value_or_id(@object['context'])
(audience_to + audience_cc).uniq.each do |audience|
next if audience == ActivityPub::TagManager::COLLECTIONS[:public]
next if audience == ActivityPub::TagManager::COLLECTIONS[:public] || audience == conversation_uri
# Unlike with tags, there is no point in resolving accounts we don't already
# know here, because silent mentions would only be used for local access
@ -340,15 +343,45 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
ActivityPub::FetchRepliesWorker.perform_async(status.id, uri) unless uri.nil?
end
def conversation_from_uri(uri)
return nil if uri.nil?
return Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) if OStatus::TagManager.instance.local_id?(uri)
def conversation_from_context
atom_uri = @object['conversation']
begin
Conversation.find_or_create_by!(uri: uri)
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
retry
conversation = begin
if atom_uri.present? && OStatus::TagManager.instance.local_id?(atom_uri)
Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(atom_uri, 'Conversation'))
elsif atom_uri.present? && @object['context'].present?
Conversation.find_by(uri: atom_uri)
elsif atom_uri.present?
begin
Conversation.find_or_create_by!(uri: atom_uri)
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
retry
end
end
end
return conversation if @object['context'].nil?
uri = value_or_id(@object['context'])
conversation ||= ActivityPub::TagManager.instance.uri_to_resource(uri, Conversation)
return conversation if (conversation.present? && conversation.uri == uri) || !uri.start_with?('https://')
conversation_json = begin
if @object['context'].is_a?(Hash) && !invalid_origin?(uri)
@object['context']
else
fetch_resource(uri, true)
end
end
return conversation if conversation_json.blank?
conversation ||= Conversation.new
conversation.uri = uri
conversation.inbox_url = conversation_json['inbox']
conversation.save! if conversation.changed?
conversation
end
def visibility_from_audience
@ -492,6 +525,12 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
SpamCheck.perform(@status)
end
def forward_for_conversation
return unless audience_to.include?(value_or_id(@object['context'])) && @json['signature'].present? && @status.conversation.local?
ActivityPub::ForwardDistributionWorker.perform_async(@status.conversation_id, Oj.dump(@json))
end
def forward_for_reply
return unless @status.distributable? && @json['signature'].present? && reply_to_local?