Merge remote-tracking branch 'tootsuite/master' into glitchsoc/master

This commit is contained in:
Jenkins
2017-11-30 03:17:12 +00:00
13 changed files with 139 additions and 43 deletions

View File

@@ -9,6 +9,24 @@ module JsonLdHelper
value.is_a?(Array) ? value.first : value
end
# The url attribute can be a string, an array of strings, or an array of objects.
# The objects could include a mimeType. Not-included mimeType means it's text/html.
def url_to_href(value, preferred_type = nil)
single_value = if value.is_a?(Array) && !value.first.is_a?(String)
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
elsif value.is_a?(Array)
value.first
else
value
end
if single_value.nil? || single_value.is_a?(String)
single_value
else
single_value['href']
end
end
def as_array(value)
value.is_a?(Array) ? value : [value]
end

View File

@@ -1,6 +1,9 @@
# frozen_string_literal: true
class ActivityPub::Activity::Create < ActivityPub::Activity
SUPPORTED_TYPES = %w(Article Note).freeze
CONVERTED_TYPES = %w(Image Video).freeze
def perform
return if delete_arrived_first?(object_uri) || unsupported_object_type?
@@ -41,7 +44,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
url: object_url || @object['id'],
account: @account,
text: text_from_content || '',
language: language_from_content,
language: detected_language,
spoiler_text: @object['summary'] || '',
created_at: @options[:override_timestamps] ? nil : @object['published'],
reply: @object['inReplyTo'].present?,
@@ -165,40 +168,62 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end
def text_from_content
return Formatter.instance.linkify([text_from_name, object_url || @object['id']].join(' ')) if converted_object_type?
if @object['content'].present?
@object['content']
elsif language_map?
elsif content_language_map?
@object['contentMap'].values.first
end
end
def language_from_content
return LanguageDetector.instance.detect(text_from_content, @account) unless language_map?
@object['contentMap'].keys.first
def text_from_name
if @object['name'].present?
@object['name']
elsif name_language_map?
@object['nameMap'].values.first
end
end
def detected_language
if content_language_map?
@object['contentMap'].keys.first
elsif name_language_map?
@object['nameMap'].keys.first
elsif supported_object_type?
LanguageDetector.instance.detect(text_from_content, @account)
end
end
def object_url
return if @object['url'].blank?
value = first_of_value(@object['url'])
return value if value.is_a?(String)
value['href']
url_to_href(@object['url'], 'text/html')
end
def language_map?
def content_language_map?
@object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
end
def name_language_map?
@object['nameMap'].is_a?(Hash) && !@object['nameMap'].empty?
end
def unsupported_object_type?
@object.is_a?(String) || !%w(Article Note).include?(@object['type'])
@object.is_a?(String) || !(supported_object_type? || converted_object_type?)
end
def unsupported_media_type?(mime_type)
mime_type.present? && !(MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES).include?(mime_type)
end
def supported_object_type?
SUPPORTED_TYPES.include?(@object['type'])
end
def converted_object_type?
CONVERTED_TYPES.include?(@object['type'])
end
def skip_download?
return @skip_download if defined?(@skip_download)
@skip_download ||= DomainBlock.find_by(domain: @account.domain)&.reject_media?
@@ -210,7 +235,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def forward_for_reply
return unless @json['signature'].present? && reply_to_local?
ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id)
ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
end
def lock_options

View File

@@ -30,8 +30,11 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
def forward_for_reblogs(status)
return if @json['signature'].blank?
ActivityPub::RawDistributionWorker.push_bulk(status.reblogs.includes(:account).references(:account).merge(Account.local).pluck(:account_id)) do |account_id|
[payload, account_id]
rebloggers_ids = status.reblogs.includes(:account).references(:account).merge(Account.local).pluck(:account_id)
inboxes = Account.where(id: ::Follow.where(target_account_id: rebloggers_ids).select(:account_id)).inboxes - [@account.preferred_inbox_url]
ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
[payload, rebloggers_ids.first, inbox_url]
end
end

View File

@@ -51,12 +51,7 @@ class Formatter
def simplified_format(account)
return reformat(account.note).html_safe unless account.local? # rubocop:disable Rails/OutputSafety
html = encode_and_link_urls(account.note)
html = simple_format(html, {}, sanitize: false)
html = html.delete("\n")
html.html_safe # rubocop:disable Rails/OutputSafety
linkify(account.note)
end
def sanitize(html, config)
@@ -69,6 +64,14 @@ class Formatter
html.html_safe # rubocop:disable Rails/OutputSafety
end
def linkify(text)
html = encode_and_link_urls(text)
html = simple_format(html, {}, sanitize: false)
html = html.delete("\n")
html.html_safe # rubocop:disable Rails/OutputSafety
end
private
def encode(html)

View File

@@ -216,6 +216,10 @@ class Account < ApplicationRecord
Rails.cache.fetch("exclude_domains_for:#{id}") { domain_blocks.pluck(:domain) }
end
def preferred_inbox_url
shared_inbox_url.presence || inbox_url
end
class << self
def readonly_attributes
super - %w(statuses_count following_count followers_count)

View File

@@ -42,7 +42,7 @@ class ActivityPub::FetchRemoteStatusService < BaseService
end
def expected_type?
%w(Note Article).include? @json['type']
(ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES).include? @json['type']
end
def needs_update(actor)

View File

@@ -107,12 +107,7 @@ class ActivityPub::ProcessAccountService < BaseService
def url
return if @json['url'].blank?
value = first_of_value(@json['url'])
return value if value.is_a?(String)
value['href']
url_to_href(@json['url'], 'text/html')
end
def outbox_total_items

View File

@@ -3,7 +3,7 @@
class RemoveStatusService < BaseService
include StreamEntryRenderer
def call(status)
def call(status, options = {})
@payload = Oj.dump(event: :delete, payload: status.id.to_s)
@status = status
@account = status.account
@@ -11,6 +11,7 @@ class RemoveStatusService < BaseService
@mentions = status.mentions.includes(:account).to_a
@reblogs = status.reblogs.to_a
@stream_entry = status.stream_entry
@options = options
remove_from_self if status.account.local?
remove_from_followers
@@ -23,7 +24,12 @@ class RemoveStatusService < BaseService
@status.destroy!
return unless @account.local?
# There is no reason to send out Undo activities when the
# cause is that the original object has been removed, since
# original object being removed implicitly removes reblogs
# of it. The Delete activity of the original is forwarded
# separately.
return if !@account.local? || @options[:original_removed]
remove_from_remote_followers
remove_from_remote_affected
@@ -105,7 +111,7 @@ class RemoveStatusService < BaseService
# without us being able to do all the fancy stuff
@reblogs.each do |reblog|
RemoveStatusService.new.call(reblog)
RemoveStatusService.new.call(reblog, original_removed: true)
end
end

View File

@@ -5,10 +5,10 @@ class ActivityPub::RawDistributionWorker
sidekiq_options queue: 'push'
def perform(json, source_account_id)
def perform(json, source_account_id, exclude_inboxes = [])
@account = Account.find(source_account_id)
ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
ActivityPub::DeliveryWorker.push_bulk(inboxes - exclude_inboxes) do |inbox_url|
[json, @account.id, inbox_url]
end
rescue ActiveRecord::RecordNotFound