From 4f3e491ad07a6468243c92aca520309b53ac8e70 Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Thu, 20 Aug 2020 19:52:43 -0500 Subject: [Bug, Filters, Cleanup] Fix the timeline filters (hopefully once and for all!) --- app/lib/feed_manager.rb | 70 ++++++++++++++++++++++++++----------------- app/policies/status_policy.rb | 6 +++- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 0ae15db9a..98d5105f2 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -250,57 +250,70 @@ class FeedManager def filter_from_home?(status, receiver_id, crutches, filter_options) conversation = status.conversation reblog_conversation = status.reblog&.conversation + return false if receiver_id == status.account_id - return true unless status.published? && conversation&.account_id.present? - return true unless conversation.public? || receiver_id == conversation.account_id || crutches[:following][conversation.account_id] + return true unless status.published? + return true if crutches[:hiding_thread][status.conversation_id] if conversation.present? return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?) return true if phrase_filtered?(status, receiver_id, :home) check_for_blocks = crutches[:active_mentions][status.id] || [] - check_for_blocks.concat([status.account_id]) - check_for_blocks.concat([conversation.account_id]) + check_for_blocks.concat([status.account_id, conversation&.account_id]) check_for_blocks.concat([status.in_reply_to_account_id]) if status.reply? if status.reblog? - return true if reblog_conversation&.account_id.blank? - - check_for_blocks.concat([status.reblog.account_id]) + check_for_blocks.concat([status.reblog.account_id, reblog_conversation&.account_id]) check_for_blocks.concat(crutches[:active_mentions][status.reblog_of_id] || []) - check_for_blocks.concat([reblog_conversation.account_id]) check_for_blocks.concat([status.reblog.in_reply_to_account_id]) if status.reblog.reply? end + check_for_blocks.uniq! + check_for_blocks.compact! return true if check_for_blocks.any? { |target_account_id| crutches[:blocking][target_account_id] || crutches[:muting][target_account_id] } - if status.reply? && !status.in_reply_to_account_id.nil? - should_filter = receiver_id != status.in_reply_to_account_id - should_filter &&= receiver_id != conversation.account_id - should_filter &&= status.account_id != status.in_reply_to_account_id - should_filter &&= if filter_options[:to_unknown] - !(crutches[:following][status.in_reply_to_account_id] && crutches[:following][conversation.account_id]) - else - !crutches[:following][status.in_reply_to_account_id] - end + # Filter if... + if status.reply? # ...it's a reply and... + # ...you're not following the author... + should_filter = !crutches[:following][status.in_reply_to_account_id] + # (optional) ...or the owner(s) of the thread... + should_filter ||= !crutches[:following][conversation.account_id] if filter_options[:to_unknown] && conversation&.account_id.present? + # ...and the author isn't replying to a post you wrote... + should_filter &&= receiver_id != status.in_reply_to_account_id + # ...and the author isn't mentioning you. + should_filter &&= !crutches[:active_mentions][receiver_id] return !!should_filter - elsif status.reblog? - should_filter = status.reblog.reply? - should_filter &&= status.reblog.account_id != status.reblog.in_reply_to_account_id - should_filter &&= if filter_options[:to_unknown] - !(crutches[:following][status.reblog.in_reply_to_account_id] && crutches[:following][reblog_conversation.account_id]) - else - !crutches[:following][status.reblog.in_reply_to_account_id] - end - - should_filter ||= !crutches[:following][status.reblog.account_id] if filter_options[:from_account] || status.reblog.account.silenced? + elsif status.reblog? # ...it's a boost and... + should_filter = false + + # ...it's a reply... + if status.reblog.reply? && !status.reblog.in_reply_to_account_id.nil? + # ...and you don't follow the author if: + # - you're filtering replies to parent authors you don't follow + # - they're silenced on this server + should_filter ||= !crutches[:following][status.reblog.in_reply_to_account_id] if filter_options[:to_unknown] || status.reblog.in_reply_to_account.silenced? + # - you're filtering replies to threads whose owners you don't follow + should_filter ||= !crutches[:following][reblog_conversation.account_id] if filter_options[:to_unknown] && reblog_conversation&.account_id.present? + # ...or you're blocking their domain... + should_filter ||= crutches[:domain_blocking][status.reblog.thread.account.domain] if status.reblog.thread.present? + end + + # ...or it's a post from a thread's trunk and you don't follow the author if: + # - you're filtering boosts of authors you don't follow + # - they're silenced on this server + should_filter ||= !crutches[:following][status.reblog.account_id] if filter_options[:from_unknown] || status.reblog.account.silenced? + + # ..or you're hiding boosts from them... should_filter ||= crutches[:hiding_reblogs][status.account_id] + # ...or they're blocking you... should_filter ||= crutches[:blocked_by][status.reblog.account_id] + # ...or you're blocking their domain... should_filter ||= crutches[:domain_blocking][status.reblog.account.domain] return !!should_filter end - false + crutches[:following][status.account_id] end def filter_from_mentions?(status, receiver_id) @@ -481,6 +494,7 @@ class FeedManager crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true } crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).each_with_object({}) { |domain, mapping| mapping[domain] = true } crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).each_with_object({}) { |id, mapping| mapping[id] = true } + crutches[:hiding_thread] = ConversationMute.where(account_id: receiver_id, conversation_id: statuses.map(&:conversation_id).compact, hidden: true).pluck(:conversation_id).each_with_object({}) { |id, mapping| mapping[id] = true } crutches end diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 6d1584ee8..b92494103 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -53,7 +53,7 @@ class StatusPolicy < ApplicationPolicy end def private? - visibility_for_remote_domain == 'private' || !public_conversation? + visibility_for_remote_domain == 'private' || reply? && !public_conversation? end def mention_exists? @@ -138,6 +138,10 @@ class StatusPolicy < ApplicationPolicy record.published? end + def reply? + record.reply? && record.in_reply_to_account_id != author.id + end + def public_conversation? return @public_conversation if defined?(@public_conversation) -- cgit