about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2016-11-10 00:03:33 +0100
committerEugen Rochko <eugen@zeonfederated.com>2016-11-10 00:03:33 +0100
commit17903c6dae9eb38ac221fb7cf86e5e3cafe465d0 (patch)
tree4f1d32a1ec9b770407a919bcc46794fcc09f339b /app/models
parentc5e03a2e0d7eac132a5d62d1d7d523a6969697cc (diff)
Improve filtering of public/hashtag timelines, both in backlog and real-time
Diffstat (limited to 'app/models')
-rw-r--r--app/models/status.rb22
1 files changed, 16 insertions, 6 deletions
diff --git a/app/models/status.rb b/app/models/status.rb
index 9db7a0a3a..41c3b0a92 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -88,12 +88,10 @@ class Status < ApplicationRecord
     end
 
     def as_public_timeline(account = nil)
-      query = joins('LEFT OUTER JOIN statuses AS reblogs ON statuses.reblog_of_id = reblogs.id')
-        .joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
-        .where('accounts.silenced = FALSE')
+      query = joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id').where('accounts.silenced = FALSE')
 
       unless account.nil?
-        query = query.where('(reblogs.account_id IS NULL OR reblogs.account_id NOT IN (SELECT target_account_id FROM blocks WHERE account_id = ?)) AND statuses.account_id NOT IN (SELECT target_account_id FROM blocks WHERE account_id = ?)', account.id, account.id)
+        query = filter_timeline(query, account)
       end
 
       query.with_includes.with_counters
@@ -101,12 +99,11 @@ class Status < ApplicationRecord
 
     def as_tag_timeline(tag, account = nil)
       query = tag.statuses
-        .joins('LEFT OUTER JOIN statuses AS reblogs ON statuses.reblog_of_id = reblogs.id')
         .joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
         .where('accounts.silenced = FALSE')
 
       unless account.nil?
-        query = query.where('(reblogs.account_id IS NULL OR reblogs.account_id NOT IN (SELECT target_account_id FROM blocks WHERE account_id = ?)) AND statuses.account_id NOT IN (SELECT target_account_id FROM blocks WHERE account_id = ?)', account.id, account.id)
+        query = filter_timeline(query, account)
       end
 
       query.with_includes.with_counters
@@ -119,6 +116,19 @@ class Status < ApplicationRecord
     def reblogs_map(status_ids, account_id)
       select('reblog_of_id').where(reblog_of_id: status_ids).where(account_id: account_id).map { |s| [s.reblog_of_id, true] }.to_h
     end
+
+    private
+
+    def filter_timeline(query, account)
+      blocked = Block.where(account: account).pluck(:target_account_id)
+
+      query
+        .joins('LEFT OUTER JOIN statuses AS parents ON statuses.in_reply_to_id = parents.id')
+        .joins('LEFT OUTER JOIN statuses AS reblogs ON statuses.reblog_of_id = reblogs.id')
+        .where('parents.account_id NOT IN (?)', blocked)
+        .where('statuses.account_id NOT IN (?)', blocked)
+        .where('(reblogs.id IS NULL OR reblogs.account_id NOT IN (?))', blocked)
+    end
   end
 
   before_validation do