Remove unfollowed hashtag posts from home feed (#26028)
parent
f18618d7f9
commit
943f27f437
|
@ -19,6 +19,7 @@ class Api::V1::TagsController < Api::BaseController
|
||||||
|
|
||||||
def unfollow
|
def unfollow
|
||||||
TagFollow.find_by(account: current_account, tag: @tag)&.destroy!
|
TagFollow.find_by(account: current_account, tag: @tag)&.destroy!
|
||||||
|
TagUnmergeWorker.perform_async(@tag.id, current_account.id)
|
||||||
render json: @tag, serializer: REST::TagSerializer
|
render json: @tag, serializer: REST::TagSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,26 @@ class FeedManager
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Remove a tag's statuses from a home feed
|
||||||
|
# @param [Tag] from_tag
|
||||||
|
# @param [Account] into_account
|
||||||
|
# @return [void]
|
||||||
|
def unmerge_tag_from_home(from_tag, into_account)
|
||||||
|
timeline_key = key(:home, into_account.id)
|
||||||
|
timeline_status_ids = redis.zrange(timeline_key, 0, -1)
|
||||||
|
|
||||||
|
# This is a bit tricky because we need posts tagged with this hashtag that are not
|
||||||
|
# also tagged with another followed hashtag or from a followed user
|
||||||
|
scope = from_tag.statuses
|
||||||
|
.where(id: timeline_status_ids)
|
||||||
|
.where.not(account: into_account.following)
|
||||||
|
.tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id))
|
||||||
|
|
||||||
|
scope.select('id, reblog_of_id').reorder(nil).find_each do |status|
|
||||||
|
remove_from_feed(:home, into_account.id, status, aggregate_reblogs: into_account.user&.aggregates_reblogs?)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Clear all statuses from or mentioning target_account from a home feed
|
# Clear all statuses from or mentioning target_account from a home feed
|
||||||
# @param [Account] account
|
# @param [Account] account
|
||||||
# @param [Account] target_account
|
# @param [Account] target_account
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TagUnmergeWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
include DatabaseHelper
|
||||||
|
|
||||||
|
sidekiq_options queue: 'pull'
|
||||||
|
|
||||||
|
def perform(from_tag_id, into_account_id)
|
||||||
|
with_primary do
|
||||||
|
@from_tag = Tag.find(from_tag_id)
|
||||||
|
@into_account = Account.find(into_account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
with_read_replica do
|
||||||
|
FeedManager.instance.unmerge_tag_from_home(@from_tag, @into_account)
|
||||||
|
end
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,39 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe TagUnmergeWorker do
|
||||||
|
subject { described_class.new }
|
||||||
|
|
||||||
|
describe 'perform' do
|
||||||
|
let(:follower) { Fabricate(:account) }
|
||||||
|
let(:followed) { Fabricate(:account) }
|
||||||
|
let(:followed_tag) { Fabricate(:tag) }
|
||||||
|
let(:unchanged_followed_tag) { Fabricate(:tag) }
|
||||||
|
let(:status_from_followed) { Fabricate(:status, created_at: 2.hours.ago, account: followed) }
|
||||||
|
let(:tagged_status) { Fabricate(:status, created_at: 1.hour.ago) }
|
||||||
|
let(:unchanged_tagged_status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
tagged_status.tags << followed_tag
|
||||||
|
unchanged_tagged_status.tags << followed_tag
|
||||||
|
unchanged_tagged_status.tags << unchanged_followed_tag
|
||||||
|
|
||||||
|
tag_follow = TagFollow.create_with(rate_limit: false).find_or_create_by!(tag: followed_tag, account: follower)
|
||||||
|
TagFollow.create_with(rate_limit: false).find_or_create_by!(tag: unchanged_followed_tag, account: follower)
|
||||||
|
|
||||||
|
FeedManager.instance.push_to_home(follower, status_from_followed, update: false)
|
||||||
|
FeedManager.instance.push_to_home(follower, tagged_status, update: false)
|
||||||
|
FeedManager.instance.push_to_home(follower, unchanged_tagged_status, update: false)
|
||||||
|
|
||||||
|
tag_follow.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'removes the expected status from the feed' do
|
||||||
|
expect { subject.perform(followed_tag.id, follower.id) }
|
||||||
|
.to change { HomeFeed.new(follower).get(10).pluck(:id) }
|
||||||
|
.from([unchanged_tagged_status.id, tagged_status.id, status_from_followed.id])
|
||||||
|
.to([unchanged_tagged_status.id, status_from_followed.id])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue