diff options
Diffstat (limited to 'app/services')
-rw-r--r-- | app/services/activitypub/fetch_remote_status_service.rb | 6 | ||||
-rw-r--r-- | app/services/batched_remove_status_service.rb | 13 | ||||
-rw-r--r-- | app/services/fan_out_on_write_service.rb | 17 | ||||
-rw-r--r-- | app/services/notify_service.rb | 57 | ||||
-rw-r--r-- | app/services/post_status_service.rb | 4 | ||||
-rw-r--r-- | app/services/process_mentions_service.rb | 29 | ||||
-rw-r--r-- | app/services/remove_status_service.rb | 15 | ||||
-rw-r--r-- | app/services/resolve_remote_account_service.rb | 4 | ||||
-rw-r--r-- | app/services/suspend_account_service.rb | 25 |
9 files changed, 123 insertions, 47 deletions
diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb index e2a89a87c..8d7b7a17c 100644 --- a/app/services/activitypub/fetch_remote_status_service.rb +++ b/app/services/activitypub/fetch_remote_status_service.rb @@ -16,7 +16,7 @@ class ActivityPub::FetchRemoteStatusService < BaseService return if actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id) actor = ActivityPub::TagManager.instance.uri_to_resource(actor_id, Account) - actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? + actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? || needs_update(actor) return if actor.suspended? @@ -44,4 +44,8 @@ class ActivityPub::FetchRemoteStatusService < BaseService def expected_type? %w(Note Article).include? @json['type'] end + + def needs_update(actor) + actor.possibly_stale? + end end diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index aa2229f13..21c775208 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -26,10 +26,11 @@ class BatchedRemoveStatusService < BaseService statuses.each(&:destroy) # Batch by source account - statuses.group_by(&:account_id).each do |_, account_statuses| + statuses.group_by(&:account_id).each_value do |account_statuses| account = account_statuses.first.account unpush_from_home_timelines(account, account_statuses) + unpush_from_list_timelines(account, account_statuses) if account.local? batch_stream_entries(account, account_statuses) @@ -80,7 +81,15 @@ class BatchedRemoveStatusService < BaseService recipients.each do |follower| statuses.each do |status| - FeedManager.instance.unpush(:home, follower, status) + FeedManager.instance.unpush_from_home(follower, status) + end + end + end + + def unpush_from_list_timelines(account, statuses) + account.lists.select(:id, :account_id).each do |list| + statuses.each do |status| + FeedManager.instance.unpush_from_list(list, status) end end end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 2214d73dd..0f77556dc 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -17,6 +17,7 @@ class FanOutOnWriteService < BaseService deliver_to_direct_timelines(status) else deliver_to_followers(status) + deliver_to_lists(status) end return if status.account.silenced? || !status.public_visibility? || status.reblog? @@ -32,7 +33,7 @@ class FanOutOnWriteService < BaseService def deliver_to_self(status) Rails.logger.debug "Delivering status #{status.id} to author" - FeedManager.instance.push(:home, status.account, status) + FeedManager.instance.push_to_home(status.account, status) end def deliver_to_followers(status) @@ -40,7 +41,17 @@ class FanOutOnWriteService < BaseService status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).select(:id).reorder(nil).find_in_batches do |followers| FeedInsertWorker.push_bulk(followers) do |follower| - [status.id, follower.id] + [status.id, follower.id, :home] + end + end + end + + def deliver_to_lists(status) + Rails.logger.debug "Delivering status #{status.id} to lists" + + status.account.lists.joins(account: :user).where('users.current_sign_in_at > ?', 14.days.ago).select(:id).reorder(nil).find_in_batches do |lists| + FeedInsertWorker.push_bulk(lists) do |list| + [status.id, list.id, :list] end end end @@ -51,7 +62,7 @@ class FanOutOnWriteService < BaseService status.mentions.includes(:account).each do |mention| mentioned_account = mention.account next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id) - FeedManager.instance.push(:home, mentioned_account, status) + FeedManager.instance.push_to_home(mentioned_account, status) end end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 3fa3f152c..d5960c3ad 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -36,17 +36,58 @@ class NotifyService < BaseService false end + def following_sender? + return @following_sender if defined?(@following_sender) + @following_sender = @recipient.following?(@notification.from_account) || @recipient.requested?(@notification.from_account) + end + + def optional_non_follower? + @recipient.user.settings.interactions['must_be_follower'] && !@notification.from_account.following?(@recipient) + end + + def optional_non_following? + @recipient.user.settings.interactions['must_be_following'] && !following_sender? + end + + def direct_message? + @notification.type == :mention && @notification.target_status.direct_visibility? + end + + def response_to_recipient? + @notification.target_status.in_reply_to_account_id == @recipient.id + end + + def optional_non_following_and_direct? + direct_message? && + @recipient.user.settings.interactions['must_be_following_dm'] && + !following_sender? && + !response_to_recipient? + end + + def hellbanned? + @notification.from_account.silenced? && !following_sender? + end + + def from_self? + @recipient.id == @notification.from_account.id + end + + def domain_blocking? + @recipient.domain_blocking?(@notification.from_account.domain) && !following_sender? + end + def blocked? - blocked = @recipient.suspended? # Skip if the recipient account is suspended anyway - blocked ||= @recipient.id == @notification.from_account.id # Skip for interactions with self - blocked ||= @recipient.domain_blocking?(@notification.from_account.domain) && !@recipient.following?(@notification.from_account) # Skip for domain blocked accounts - blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts + blocked = @recipient.suspended? # Skip if the recipient account is suspended anyway + blocked ||= from_self? # Skip for interactions with self + blocked ||= domain_blocking? # Skip for domain blocked accounts + blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts blocked ||= @recipient.muting_notifications?(@notification.from_account) - blocked ||= (@notification.from_account.silenced? && !@recipient.following?(@notification.from_account)) # Hellban - blocked ||= (@recipient.user.settings.interactions['must_be_follower'] && !@notification.from_account.following?(@recipient)) # Options - blocked ||= (@recipient.user.settings.interactions['must_be_following'] && !@recipient.following?(@notification.from_account)) # Options + blocked ||= hellbanned? # Hellban + blocked ||= optional_non_follower? # Options + blocked ||= optional_non_following? # Options + blocked ||= optional_non_following_and_direct? # Options blocked ||= conversation_muted? - blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters + blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters blocked end diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index d1b8f42c7..974c586f2 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -74,11 +74,11 @@ class PostStatusService < BaseService end def process_mentions_service - @process_mentions_service ||= ProcessMentionsService.new + ProcessMentionsService.new end def process_hashtags_service - @process_hashtags_service ||= ProcessHashtagsService.new + ProcessHashtagsService.new end def redis diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index 1c3eea369..a229d4ff8 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -10,23 +10,26 @@ class ProcessMentionsService < BaseService def call(status) return unless status.local? - status.text.scan(Account::MENTION_RE).each do |match| - username, domain = match.first.split('@') - mentioned_account = Account.find_remote(username, domain) - - if mentioned_account.nil? && !domain.nil? - begin - mentioned_account = follow_remote_account_service.call(match.first.to_s) - rescue Goldfinger::Error, HTTP::Error - mentioned_account = nil - end + status.text = status.text.gsub(Account::MENTION_RE) do |match| + begin + mentioned_account = resolve_remote_account_service.call($1) + rescue Goldfinger::Error, HTTP::Error + mentioned_account = nil end - next if mentioned_account.nil? + if mentioned_account.nil? + username, domain = match.first.split('@') + mentioned_account = Account.find_remote(username, domain) + end + + next match if mentioned_account.nil? || (!mentioned_account.local? && mentioned_account.ostatus? && status.stream_entry.hidden?) mentioned_account.mentions.where(status: status).first_or_create(status: status) + "@#{mentioned_account.acct}" end + status.save! + status.mentions.includes(:account).each do |mention| create_notification(status, mention) end @@ -54,7 +57,7 @@ class ProcessMentionsService < BaseService ).as_json).sign!(status.account)) end - def follow_remote_account_service - @follow_remote_account_service ||= ResolveRemoteAccountService.new + def resolve_remote_account_service + ResolveRemoteAccountService.new end end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 8eef3e57e..9617081fd 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -14,6 +14,7 @@ class RemoveStatusService < BaseService remove_from_self if status.account.local? remove_from_followers + remove_from_lists remove_from_affected remove_reblogs remove_from_hashtags @@ -31,12 +32,18 @@ class RemoveStatusService < BaseService private def remove_from_self - unpush(:home, @account, @status) + FeedManager.instance.unpush_from_home(@account, @status) end def remove_from_followers @account.followers.local.find_each do |follower| - unpush(:home, follower, @status) + FeedManager.instance.unpush_from_home(follower, @status) + end + end + + def remove_from_lists + @account.lists.select(:id, :account_id).find_each do |list| + FeedManager.instance.unpush_from_list(list, @status) end end @@ -102,10 +109,6 @@ class RemoveStatusService < BaseService end end - def unpush(type, receiver, status) - FeedManager.instance.unpush(type, receiver, status) - end - def remove_from_hashtags return unless @status.public_visibility? diff --git a/app/services/resolve_remote_account_service.rb b/app/services/resolve_remote_account_service.rb index 3d0a36f6c..3293fe40f 100644 --- a/app/services/resolve_remote_account_service.rb +++ b/app/services/resolve_remote_account_service.rb @@ -124,11 +124,11 @@ class ResolveRemoteAccountService < BaseService end def auto_suspend? - domain_block && domain_block.suspend? + domain_block&.suspend? end def auto_silence? - domain_block && domain_block.silence? + domain_block&.silence? end def domain_block diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb index 983c5495b..5b37ba9ba 100644 --- a/app/services/suspend_account_service.rb +++ b/app/services/suspend_account_service.rb @@ -1,22 +1,27 @@ # frozen_string_literal: true class SuspendAccountService < BaseService - def call(account, remove_user = false) + def call(account, options = {}) @account = account + @options = options - purge_user if remove_user - purge_profile - purge_content - unsubscribe_push_subscribers + purge_user! + purge_profile! + purge_content! + unsubscribe_push_subscribers! end private - def purge_user - @account.user.destroy + def purge_user! + if @options[:remove_user] + @account.user&.destroy + else + @account.user&.disable! + end end - def purge_content + def purge_content! @account.statuses.reorder(nil).find_in_batches do |statuses| BatchedRemoveStatusService.new.call(statuses) end @@ -33,7 +38,7 @@ class SuspendAccountService < BaseService end end - def purge_profile + def purge_profile! @account.suspended = true @account.display_name = '' @account.note = '' @@ -42,7 +47,7 @@ class SuspendAccountService < BaseService @account.save! end - def unsubscribe_push_subscribers + def unsubscribe_push_subscribers! destroy_all(@account.subscriptions) end |