diff --git a/app/lib/account_statuses_filter.rb b/app/lib/account_statuses_filter.rb index 92196b6da40..5fa9a2ca419 100644 --- a/app/lib/account_statuses_filter.rb +++ b/app/lib/account_statuses_filter.rb @@ -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 diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index e83fa6b998f..76c849e8f6d 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -45,7 +45,7 @@ module Mastodon def api_versions { - mastodon: 7, + mastodon: 8, } end diff --git a/spec/lib/account_statuses_filter_spec.rb b/spec/lib/account_statuses_filter_spec.rb index 351d3dae574..ecb75d55d0d 100644 --- a/spec/lib/account_statuses_filter_spec.rb +++ b/spec/lib/account_statuses_filter_spec.rb @@ -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