Add exclude_direct flag to /api/v1/accounts/:id/statuses to exclude direct messages (#37763)

This commit is contained in:
Claire 2026-02-27 10:34:12 +01:00 committed by GitHub
parent fc1f57b5f1
commit 3b7c33e763
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 4 deletions

View File

@ -37,7 +37,7 @@ class AccountStatusesFilter
if anonymous?
account.statuses.distributable_visibility
elsif author?
account.statuses.all # NOTE: #merge! does not work without the #all
exclude_direct? ? account.statuses.where(visibility: %i(public unlisted private)) : account.statuses.all # NOTE: #merge! does not work without the #all
elsif blocked?
Status.none
else
@ -46,9 +46,15 @@ class AccountStatusesFilter
end
def filtered_scope
scope = account.statuses.left_outer_joins(:mentions)
scope = account.statuses
if exclude_direct?
scope = scope.where(visibility: follower? ? %i(public unlisted private) : %i(public unlisted))
else
scope = account.statuses.left_outer_joins(:mentions)
scope.merge!(scope.where(visibility: follower? ? %i(public unlisted private) : %i(public unlisted)).or(scope.where(mentions: { account_id: current_account.id })).group(Status.arel_table[:id]))
end
scope.merge!(scope.where(visibility: follower? ? %i(public unlisted private) : %i(public unlisted)).or(scope.where(mentions: { account_id: current_account.id })).group(Status.arel_table[:id]))
scope.merge!(filtered_reblogs_scope) if reblogs_may_occur?
scope
@ -123,6 +129,10 @@ class AccountStatusesFilter
truthy_param?(:only_media)
end
def exclude_direct?
truthy_param?(:exclude_direct)
end
def exclude_replies?
truthy_param?(:exclude_replies)
end

View File

@ -45,7 +45,7 @@ module Mastodon
def api_versions
{
mastodon: 7,
mastodon: 8,
}
end

View File

@ -64,6 +64,9 @@ RSpec.describe AccountStatusesFilter do
expect(results_for(exclude_reblogs: true))
.to all(satisfy { |status| !status.reblog? })
expect(results_for(exclude_direct: true))
.to all(satisfy { |status| !status.direct_visibility? })
end
def results_for(params)
@ -77,6 +80,18 @@ RSpec.describe AccountStatusesFilter do
let(:current_account) { nil }
let(:direct_status) { nil }
context 'when rejecting direct messages' do
let(:params) { { exclude_direct: true } }
it 'returns only public statuses, public replies, and public reblogs' do
expect(results_unique_visibilities).to match_array %w(unlisted public)
expect(results_in_reply_to_ids).to_not be_empty
expect(results_reblog_of_ids).to_not be_empty
end
end
it 'returns only public statuses, public replies, and public reblogs' do
expect(results_unique_visibilities).to match_array %w(unlisted public)
@ -95,6 +110,14 @@ RSpec.describe AccountStatusesFilter do
account.block!(current_account)
end
context 'when rejecting direct messages' do
let(:params) { { exclude_direct: true } }
it 'returns nothing' do
expect(subject.to_a).to be_empty
end
end
it 'returns nothing' do
expect(subject.to_a).to be_empty
end
@ -121,6 +144,18 @@ RSpec.describe AccountStatusesFilter do
current_account.follow!(account)
end
context 'when rejecting direct messages' do
let(:params) { { exclude_direct: true } }
it 'returns private statuses, replies, and reblogs' do
expect(results_unique_visibilities).to match_array %w(private unlisted public)
expect(results_in_reply_to_ids).to_not be_empty
expect(results_reblog_of_ids).to_not be_empty
end
end
it 'returns private statuses, replies, and reblogs' do
expect(results_unique_visibilities).to match_array %w(private unlisted public)
@ -135,6 +170,8 @@ RSpec.describe AccountStatusesFilter do
it 'returns the direct status' do
expect(results_ids).to include(direct_status.id)
end
it_behaves_like 'filter params'
end
it_behaves_like 'filter params'
@ -143,6 +180,18 @@ RSpec.describe AccountStatusesFilter do
context 'when accessed by a non-follower' do
let(:current_account) { Fabricate(:account) }
context 'when rejecting direct messages' do
let(:params) { { exclude_direct: true } }
it 'returns private statuses, replies, and reblogs' do
expect(results_unique_visibilities).to match_array %w(unlisted public)
expect(results_in_reply_to_ids).to_not be_empty
expect(results_reblog_of_ids).to_not be_empty
end
end
it 'returns only public statuses, replies, and reblogs' do
expect(results_unique_visibilities).to match_array %w(unlisted public)
@ -157,6 +206,8 @@ RSpec.describe AccountStatusesFilter do
it 'returns the private status' do
expect(results_ids).to include(private_status.id)
end
it_behaves_like 'filter params'
end
context 'when blocking a reblogged account' do