Skip to content
Snippets Groups Projects
Commit 6fd865c0 authored by Eugen Rochko's avatar Eugen Rochko
Browse files

Spawn FeedInsertWorker to deliver status into personal feed

parent 5f549818
No related branches found
No related tags found
No related merge requests found
......@@ -11,11 +11,11 @@ class FeedManager
"feed:#{type}:#{id}"
end
def filter?(timeline_type, status, receiver)
def filter?(timeline_type, status, receiver_id)
if timeline_type == :home
filter_from_home?(status, receiver)
filter_from_home?(status, receiver_id)
elsif timeline_type == :mentions
filter_from_mentions?(status, receiver)
filter_from_mentions?(status, receiver_id)
else
false
end
......@@ -91,39 +91,39 @@ class FeedManager
Redis.current
end
def filter_from_home?(status, receiver)
def filter_from_home?(status, receiver_id)
return true if status.reply? && status.in_reply_to_id.nil?
check_for_mutes = [status.account_id]
check_for_mutes.concat([status.reblog.account_id]) if status.reblog?
return true if receiver.muting?(check_for_mutes)
return true if Mute.where(account_id: receiver_id, target_account_id: check_for_mutes).any?
check_for_blocks = status.mentions.map(&:account_id)
check_for_blocks.concat([status.reblog.account_id]) if status.reblog?
return true if receiver.blocking?(check_for_blocks)
return true if Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any?
if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply
should_filter = !receiver.following?(status.in_reply_to_account) # and I'm not following the person it's a reply to
should_filter &&= !(receiver.id == status.in_reply_to_account_id) # and it's not a reply to me
should_filter &&= !(status.account_id == status.in_reply_to_account_id) # and it's not a self-reply
if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply
should_filter = !Follow.where(account_id: receiver_id, target_account_id: status.in_reply_to_account_id).exists? # and I'm not following the person it's a reply to
should_filter &&= !(receiver_id == status.in_reply_to_account_id) # and it's not a reply to me
should_filter &&= !(status.account_id == status.in_reply_to_account_id) # and it's not a self-reply
return should_filter
elsif status.reblog? # Filter out a reblog
return status.reblog.account.blocking?(receiver) # or if the author of the reblogged status is blocking me
elsif status.reblog? # Filter out a reblog
return Block.where(account_id: status.reblog.account_id, target_account_id: receiver_id).exists? # or if the author of the reblogged status is blocking me
end
false
end
def filter_from_mentions?(status, receiver)
def filter_from_mentions?(status, receiver_id)
check_for_blocks = [status.account_id]
check_for_blocks.concat(status.mentions.select('account_id').map(&:account_id))
check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil?
should_filter = receiver.id == status.account_id # Filter if I'm mentioning myself
should_filter ||= receiver.blocking?(check_for_blocks) # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked
should_filter ||= (status.account.silenced? && !receiver.following?(status.account)) # of if the account is silenced and I'm not following them
should_filter = receiver_id == status.account_id # Filter if I'm mentioning myself
should_filter ||= Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any? # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked
should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them
should_filter
end
......
......@@ -33,9 +33,8 @@ class FanOutOnWriteService < BaseService
def deliver_to_followers(status)
Rails.logger.debug "Delivering status #{status.id} to followers"
status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).find_each do |follower|
next if FeedManager.instance.filter?(:home, status, follower)
FeedManager.instance.push(:home, follower, status)
status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).select(:id).find_each do |follower|
FeedInsertWorker.perform_async(status.id, follower.id)
end
end
......@@ -44,7 +43,7 @@ class FanOutOnWriteService < BaseService
status.mentions.includes(:account).each do |mention|
mentioned_account = mention.account
next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mentioned_account)
next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id)
FeedManager.instance.push(:home, mentioned_account, status)
end
end
......@@ -54,9 +53,9 @@ class FanOutOnWriteService < BaseService
payload = FeedManager.instance.inline_render(nil, 'api/v1/statuses/show', status)
status.tags.find_each do |tag|
FeedManager.instance.broadcast("hashtag:#{tag.name}", event: 'update', payload: payload)
FeedManager.instance.broadcast("hashtag:#{tag.name}:local", event: 'update', payload: payload) if status.account.local?
status.tags.pluck(:name).each do |hashtag|
FeedManager.instance.broadcast("hashtag:#{hashtag}", event: 'update', payload: payload)
FeedManager.instance.broadcast("hashtag:#{hashtag}:local", event: 'update', payload: payload) if status.account.local?
end
end
......
......@@ -17,7 +17,7 @@ class NotifyService < BaseService
private
def blocked_mention?
FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient)
FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient.id)
end
def blocked_favourite?
......
......@@ -7,7 +7,7 @@ class PrecomputeFeedService < BaseService
def call(_, account)
redis.pipelined do
Status.as_home_timeline(account).limit(FeedManager::MAX_ITEMS / 4).each do |status|
next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account)
next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account.id)
redis.zadd(FeedManager.instance.key(:home, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
end
end
......
# frozen_string_literal: true
class FeedInsertWorker
include Sidekiq::Worker
def perform(status_id, follower_id)
status = Status.find(status_id)
follower = Account.find(follower_id)
return if FeedManager.instance.filter?(:home, status, follower.id)
FeedManager.instance.push(:home, follower, status)
rescue ActiveRecord::RecordNotFound
true
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment