about summary refs log tree commit diff
diff options
context:
space:
mode:
authormultiple creatures <dev@multiple-creature.party>2019-12-03 17:04:32 -0600
committermultiple creatures <dev@multiple-creature.party>2019-12-03 17:06:47 -0600
commitbc81d32c2caa5a53b3326421bd8ffdb2fd4a3491 (patch)
treebec4792b77eefd1133b48149d4b5f4ac9b7756d6
parentbcb45d2cbe7abd2095c5e7657f2b62db1211fd9f (diff)
when someone adds/changes a filter retroactively apply it to their home & list timelines
-rw-r--r--app/models/custom_filter.rb15
-rw-r--r--app/workers/filter_feeds_worker.rb46
2 files changed, 61 insertions, 0 deletions
diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb
index a90b99c48..67d1a0bea 100644
--- a/app/models/custom_filter.rb
+++ b/app/models/custom_filter.rb
@@ -18,4 +18,19 @@ class CustomFilter < ApplicationRecord
   belongs_to :account
 
   validates :phrase, presence: true
+
+  after_save :update_feeds
+  after_save :remove_cache
+
+  private
+
+  def update_feeds
+    FilterFeedsWorker.perform_async(account_id)
+  end
+
+  private
+
+  def remove_cache
+    redis.del("filtered_statuses:#{account_id}")
+  end
 end
diff --git a/app/workers/filter_feeds_worker.rb b/app/workers/filter_feeds_worker.rb
new file mode 100644
index 000000000..ced9e707b
--- /dev/null
+++ b/app/workers/filter_feeds_worker.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+class FilterFeedsWorker
+  include Sidekiq::Worker
+  include FilterHelper
+
+  def perform(account_id)
+    @account = Account.find(account_id)
+
+    statuses = HomeFeed.new(@account).all
+    filtered_statuses(statuses).each do |status|
+      FeedManager.instance.unpush_from_home(@account, status)
+    end
+
+    @account.lists.find_each do |list|
+      statuses = ListFeed.new(list).all
+      filtered_statuses(statuses).each do |status|
+        FeedManager.instance.unpush_from_list(list, status)
+      end
+    end
+  rescue ActiveRecord::RecordNotFound
+    true
+  end
+
+  private
+
+  def filtered_statuses(statuses)
+    account_ids = statuses.map(&:account_id).uniq
+    domains     = statuses.map(&:account_domain).compact.uniq
+    relations   = relations_map_for_account(@account, account_ids, domains)
+
+    statuses.select { |status| StatusFilter.new(status, @account, relations).filtered? }
+  end
+
+  def relations_map_for_account(account, account_ids, domains)
+    return {} if account.nil?
+
+    {
+      blocking: Account.blocking_map(account_ids, account.id),
+      blocked_by: Account.blocked_by_map(account_ids, account.id),
+      muting: Account.muting_map(account_ids, account.id),
+      following: Account.following_map(account_ids, account.id),
+      domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id),
+    }
+  end
+end