about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/lib/feed_manager.rb70
-rw-r--r--app/policies/status_policy.rb6
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)