From af0b6f445c597b41e861da9e77f39b4caed3e753 Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Sun, 16 Aug 2020 21:48:42 -0500 Subject: [Filters, Timelines] Add options to toggle filters for replies to and boosts of unfollowed accounts --- app/lib/feed_manager.rb | 39 +++++++++++++++++++++++++++++--------- app/lib/user_settings_decorator.rb | 10 ++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) (limited to 'app/lib') diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 0ec341e3f..88fa592a7 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -2,6 +2,7 @@ require 'singleton' +# rubocop:disable Metrics/ClassLength class FeedManager include Singleton include Redisable @@ -23,7 +24,7 @@ class FeedManager def filter?(timeline_type, status, receiver_id) if [:home, :list].include?(timeline_type) - filter_from_home?(status, receiver_id, build_crutches(receiver_id, [status])) + filter_from_home?(status, receiver_id, build_crutches(receiver_id, [status]), filter_options_for(receiver_id)) elsif timeline_type == :mentions filter_from_mentions?(status, receiver_id) elsif timeline_type == :direct @@ -142,9 +143,10 @@ class FeedManager statuses = query.to_a crutches = build_crutches(into_account.id, statuses) + filter_options = filter_options_for(receiver_id) statuses.each do |status| - next if filter_from_home?(status, into_account.id, crutches) + next if filter_from_home?(status, into_account.id, crutches, filter_options) add_to_feed(:home, into_account.id, status, aggregate) end @@ -242,9 +244,9 @@ class FeedManager (context == :home ? Mute.where(account_id: receiver_id, target_account_id: account_ids).any? : Mute.where(account_id: receiver_id, target_account_id: account_ids, hide_notifications: true).any?) end - def filter_from_home?(status, receiver_id, crutches) + def filter_from_home?(status, receiver_id, crutches, filter_options) return false if receiver_id == status.account_id - return true unless status.published? && (status.conversation&.public? || crutches[:following][status.conversation&.account_id]) + return true unless status.published? && (status.conversation&.public? || status.conversation&.account_id == receiver_id || crutches[:following][status.conversation&.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) @@ -264,18 +266,25 @@ class FeedManager if status.reply? && !status.in_reply_to_account_id.nil? should_filter = receiver_id != status.in_reply_to_account_id + should_filter &&= receiver_id != status.conversation&.account_id should_filter &&= status.account_id != status.in_reply_to_account_id - should_filter &&= !(crutches[:following][status.in_reply_to_account_id] && crutches[:following][status.conversation&.account_id]) + should_filter &&= if filter_options[:to_unknown] + !(crutches[:following][status.in_reply_to_account_id] && crutches[:following][status.conversation&.account_id]) + else + !crutches[:following][status.in_reply_to_account_id] + end 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 &&= !(crutches[:following][status.reblog.in_reply_to_account_id] && crutches[:following][status.reblog.conversation&.account_id]) - - should_filter ||= !crutches[:following][status.reblog.account_id] if status.reblog.account.silenced? - should_filter ||= !crutches[:following][status.reblog.conversation&.account_id] if status.reblog.conversation&.account&.silenced? + should_filter &&= if filter_options[:to_unknown] + !(crutches[:following][status.reblog.in_reply_to_account_id] && crutches[:following][status.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? should_filter ||= crutches[:hiding_reblogs][status.account_id] should_filter ||= crutches[:blocked_by][status.reblog.account_id] should_filter ||= crutches[:domain_blocking][status.reblog.account.domain] @@ -423,6 +432,17 @@ class FeedManager redis.zrem(timeline_key, status.id) end + def filter_options_for(receiver_id) + Rails.cache.fetch("filter_settings:#{receiver_id}", expires_in: 1.month) do + return {} if (settings = User.find_by(account_id: receiver_id)&.settings).blank? + + { + to_unknown: settings.filter_to_unknown, + from_unknown: settings.filter_from_unknown, + } + end + end + def build_crutches(receiver_id, statuses) crutches = {} @@ -450,3 +470,4 @@ class FeedManager crutches end end +# rubocop:enable Metrics/ClassLength diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 28f40dc73..7b67a5a58 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -60,6 +60,8 @@ class UserSettingsDecorator user.settings['boost_every'] = boost_every_preference if change?('setting_boost_every') user.settings['boost_jitter'] = boost_jitter_preference if change?('setting_boost_jitter') user.settings['boost_random'] = boost_random_preference if change?('setting_boost_random') + user.settings['filter_to_unknown'] = filter_to_unknown_preference if change?('setting_filter_to_unknown') + user.settings['filter_from_unknown'] = filter_from_unknown_preference if change?('setting_filter_from_unknown') end def merged_notification_emails @@ -226,6 +228,14 @@ class UserSettingsDecorator boolean_cast_setting 'setting_boost_random' end + def filter_to_unknown_preference + boolean_cast_setting 'setting_filter_to_unknown' + end + + def filter_from_unknown_preference + boolean_cast_setting 'setting_filter_from_unknown' + end + def boolean_cast_setting(key) ActiveModel::Type::Boolean.new.cast(settings[key]) end -- cgit