0
0
Fork 0

Keyword/phrase filtering (#7905)

* Add keyword filtering

    GET|POST       /api/v1/filters
    GET|PUT|DELETE /api/v1/filters/:id

- Irreversible filters can drop toots from home or notifications
- Other filters can hide toots through the client app
- Filters use a phrase valid in particular contexts, expiration

* Make sure expired filters don't get applied client-side

* Add missing API methods

* Remove "regex filter" from column settings

* Add tests

* Add test for FeedManager

* Add CustomFilter test

* Add UI for managing filters

* Add streaming API event to allow syncing filters

* Fix tests
This commit is contained in:
Eugen Rochko 2018-06-29 15:34:36 +02:00 committed by GitHub
parent fbee9b5ac8
commit cdb101340a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 530 additions and 72 deletions

View file

@ -153,6 +153,7 @@ class FeedManager
def filter_from_home?(status, receiver_id)
return false if receiver_id == status.account_id
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 = status.mentions.pluck(:account_id)
check_for_blocks.concat([status.account_id])
@ -177,6 +178,7 @@ class FeedManager
def filter_from_mentions?(status, receiver_id)
return true if receiver_id == status.account_id
return true if phrase_filtered?(status, receiver_id, :notifications)
# This filter is called from NotifyService, but already after the sender of
# the notification has been checked for mute/block. Therefore, it's not
@ -190,6 +192,20 @@ class FeedManager
should_filter
end
def phrase_filtered?(status, receiver_id, context)
active_filters = Rails.cache.fetch("filters:#{receiver_id}") { CustomFilter.where(account_id: receiver_id).active_irreversible.to_a }.to_a
active_filters.select! { |filter| filter.context.include?(context.to_s) && !filter.expired? }
active_filters.map! { |filter| Regexp.new(Regexp.escape(filter.phrase), true) }
return false if active_filters.empty?
combined_regex = active_filters.reduce { |memo, obj| Regexp.union(memo, obj) }
!combined_regex.match(status.text).nil? ||
(status.spoiler_text.present? && !combined_regex.match(status.spoiler_text).nil?)
end
# Adds a status to an account's feed, returning true if a status was
# added, and false if it was not added to the feed. Note that this is
# an internal helper: callers must call trim or push updates if