diff options
Diffstat (limited to 'app/lib')
-rw-r--r-- | app/lib/activitypub/activity/create.rb | 53 | ||||
-rw-r--r-- | app/lib/activitypub/activity/delete.rb | 7 | ||||
-rw-r--r-- | app/lib/activitypub/adapter.rb | 1 | ||||
-rw-r--r-- | app/lib/feed_manager.rb | 40 | ||||
-rw-r--r-- | app/lib/formatter.rb | 15 |
5 files changed, 77 insertions, 39 deletions
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 66e4f7c5e..31e0abe39 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -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 diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb index 4c6afb090..d0fb49342 100644 --- a/app/lib/activitypub/activity/delete.rb +++ b/app/lib/activitypub/activity/delete.rb @@ -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 diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 790d2025c..90d589d90 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -9,6 +9,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive', + 'movedTo' => 'as:movedTo', 'Hashtag' => 'as:Hashtag', 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri', diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 76365c7d3..fe5ebfc36 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -149,7 +149,7 @@ class FeedManager return false if receiver_id == status.account_id return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?) - return true if keyword_filter?(status, Glitch::KeywordMute.matcher_for(receiver_id)) + return true if keyword_filter?(status, receiver_id) check_for_mutes = [status.account_id] check_for_mutes.concat(status.mentions.pluck(:account_id)) @@ -162,32 +162,38 @@ class FeedManager return true if Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any? - if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply - should_filter = !Follow.where(account_id: receiver_id, target_account_id: status.in_reply_to_account_id).exists? # and I'm not following the person it's a reply to - should_filter &&= receiver_id != status.in_reply_to_account_id # and it's not a reply to me - should_filter &&= status.account_id != status.in_reply_to_account_id # and it's not a self-reply + if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply + should_filter = !Follow.where(account_id: receiver_id, target_account_id: status.in_reply_to_account_id).exists? # and I'm not following the person it's a reply to + should_filter &&= receiver_id != status.in_reply_to_account_id # and it's not a reply to me + should_filter &&= status.account_id != status.in_reply_to_account_id # and it's not a self-reply return should_filter - elsif status.reblog? # Filter out a reblog - src_id = status.account_id - should_filter = Follow.where(account_id: receiver_id, target_account_id: src_id, show_reblogs: false).exists? # if the reblogger's reblogs are suppressed - should_filter ||= Block.where(account_id: status.reblog.account_id, target_account_id: receiver_id).exists? # or if the author of the reblogged status is blocking me - should_filter ||= AccountDomainBlock.where(account_id: receiver_id, domain: status.reblog.account.domain).exists? # or the author's domain is blocked + elsif status.reblog? # Filter out a reblog + should_filter = Follow.where(account_id: receiver_id, target_account_id: status.account_id, show_reblogs: false).exists? # if the reblogger's reblogs are suppressed + should_filter ||= Block.where(account_id: status.reblog.account_id, target_account_id: receiver_id).exists? # or if the author of the reblogged status is blocking me + should_filter ||= AccountDomainBlock.where(account_id: receiver_id, domain: status.reblog.account.domain).exists? # or the author's domain is blocked return should_filter end false end - def keyword_filter?(status, matcher) - should_filter = matcher =~ status.text - should_filter ||= matcher =~ status.spoiler_text + def keyword_filter?(status, receiver_id) + text_matcher = Glitch::KeywordMute.text_matcher_for(receiver_id) + tag_matcher = Glitch::KeywordMute.tag_matcher_for(receiver_id) + + should_filter = text_matcher.matches?(status.text) + should_filter ||= text_matcher.matches?(status.spoiler_text) + should_filter ||= tag_matcher.matches?(status.tags) if status.reblog? - should_filter ||= matcher =~ status.reblog.text - should_filter ||= matcher =~ status.reblog.spoiler_text + reblog = status.reblog + + should_filter ||= text_matcher.matches?(reblog.text) + should_filter ||= text_matcher.matches?(reblog.spoiler_text) + should_filter ||= tag_matcher.matches?(status.tags) end - !!should_filter + should_filter end def filter_from_mentions?(status, receiver_id) @@ -199,7 +205,7 @@ class FeedManager should_filter = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any? # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them - should_filter ||= keyword_filter?(status, Glitch::KeywordMute.matcher_for(receiver_id)) # or if the mention contains a muted keyword + should_filter ||= keyword_filter?(status, receiver_id) # or if the mention contains a muted keyword should_filter end diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 733a1c4b7..9d8bc52db 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -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) |