Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: #577 メンション数上限設定を、メンションされた全てのローカルアカウントが相手をフォローしている場合、そうでない場合で分けられるように #578

Merged
merged 1 commit into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/lib/activitypub/activity/create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ def valid_status?
valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}", uri: @params[:uri], target_type: :status, public: @status_parser.distributable_visibility?)
valid = !Admin::NgWord.hashtag_reject?(@tags.size) if valid
valid = !Admin::NgWord.mention_reject?(@mentions.count { |m| !m.silent }) if valid
valid = !Admin::NgWord.stranger_mention_reject_with_count?(@mentions.count { |m| !m.silent }) if valid && (mention_to_local_stranger? || reference_to_local_stranger?)
valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}", uri: @params[:uri], target_type: :status, public: @status_parser.distributable_visibility?) if valid && (mention_to_local_stranger? || reference_to_local_stranger?)

valid
Expand Down
13 changes: 13 additions & 0 deletions app/models/admin/ng_word.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ def mention_reject_with_extractor?(text)
mention_reject?(text.gsub(Account::MENTION_RE)&.count || 0)
end

def stranger_mention_reject_with_count?(mention_count)
post_stranger_mentions_max.positive? && post_stranger_mentions_max < mention_count
end

def stranger_mention_reject_with_extractor?(text)
stranger_mention_reject_with_count?(text.gsub(Account::MENTION_RE)&.count || 0)
end

private

def include?(text, word)
Expand Down Expand Up @@ -62,6 +70,11 @@ def post_mentions_max
value.is_a?(Integer) && value.positive? ? value : 0
end

def post_stranger_mentions_max
value = Setting.post_stranger_mentions_max
value.is_a?(Integer) && value.positive? ? value : 0
end

def record!(type, text, keyword, options)
return unless options[:uri] && options[:target_type]
return if options.key?(:public) && !options.delete(:public)
Expand Down
2 changes: 2 additions & 0 deletions app/models/form/admin_settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class Form::AdminSettings
hide_local_users_for_anonymous
post_hash_tags_max
post_mentions_max
post_stranger_mentions_max
sensitive_words
sensitive_words_for_full
authorized_fetch
Expand All @@ -71,6 +72,7 @@ class Form::AdminSettings
backups_retention_period
post_hash_tags_max
post_mentions_max
post_stranger_mentions_max
registrations_limit
registrations_limit_per_day
registrations_start_hour
Expand Down
7 changes: 6 additions & 1 deletion app/services/activitypub/process_status_update_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,16 @@ def update_poll!(allow_significant_changes: true)
end

def valid_status?
!Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}", uri: @status.uri, target_type: :status) && !Admin::NgWord.hashtag_reject?(@raw_tags.size) && !Admin::NgWord.mention_reject?(@raw_mentions.size)
valid = !Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}", uri: @status.uri, target_type: :status)
valid = !Admin::NgWord.hashtag_reject?(@raw_tags.size) if valid

valid
end

def validate_status_mentions!
raise AbortError if (mention_to_stranger? || reference_to_stranger?) && Admin::NgWord.stranger_mention_reject?("#{@status.spoiler_text}\n#{@status.text}", uri: @status.uri, target_type: :status)
raise AbortError if Admin::NgWord.mention_reject?(@raw_mentions.size)
raise AbortError if (mention_to_stranger? || reference_to_stranger?) && Admin::NgWord.stranger_mention_reject_with_count?(@raw_mentions.size)
end

def mention_to_stranger?
Expand Down
3 changes: 2 additions & 1 deletion app/services/post_status_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,11 @@ def postprocess_status!
def validate_status!
raise Mastodon::ValidationError, I18n.t('statuses.contains_ng_words') if Admin::NgWord.reject?("#{@options[:spoiler_text]}\n#{@options[:text]}")
raise Mastodon::ValidationError, I18n.t('statuses.too_many_hashtags') if Admin::NgWord.hashtag_reject_with_extractor?(@text)
raise Mastodon::ValidationError, I18n.t('statuses.too_many_mentions') if Admin::NgWord.mention_reject_with_extractor?(@text)
end

def validate_status_mentions!
raise Mastodon::ValidationError, I18n.t('statuses.too_many_mentions') if Admin::NgWord.mention_reject_with_extractor?(@text)
raise Mastodon::ValidationError, I18n.t('statuses.too_many_mentions') if (mention_to_stranger? || reference_to_stranger?) && Admin::NgWord.stranger_mention_reject_with_extractor?(@text)
raise Mastodon::ValidationError, I18n.t('statuses.contains_ng_words') if (mention_to_stranger? || reference_to_stranger?) && Setting.stranger_mention_from_local_ng && Admin::NgWord.stranger_mention_reject?("#{@options[:spoiler_text]}\n#{@options[:text]}")
end

Expand Down
1 change: 1 addition & 0 deletions app/services/update_status_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def validate_status!
raise Mastodon::ValidationError, I18n.t('statuses.contains_ng_words') if Admin::NgWord.reject?("#{@options[:spoiler_text]}\n#{@options[:text]}")
raise Mastodon::ValidationError, I18n.t('statuses.too_many_hashtags') if Admin::NgWord.hashtag_reject_with_extractor?(@options[:text] || '')
raise Mastodon::ValidationError, I18n.t('statuses.too_many_mentions') if Admin::NgWord.mention_reject_with_extractor?(@options[:text] || '')
raise Mastodon::ValidationError, I18n.t('statuses.too_many_mentions') if (mention_to_stranger? || reference_to_stranger?) && Admin::NgWord.stranger_mention_reject_with_extractor?(@options[:text] || '')
end

def validate_status_mentions!
Expand Down
3 changes: 3 additions & 0 deletions app/views/admin/ng_words/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
.fields-group
= f.input :post_hash_tags_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_hash_tags_max')

.fields-group
= f.input :post_stranger_mentions_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_stranger_mentions_max')

.fields-group
= f.input :post_mentions_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_mentions_max')

Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ en:
keywords_hint: The first character of the line is "?". to use regular expressions
post_hash_tags_max: Hash tags max for posts
post_mentions_max: Mentions max for posts
post_stranger_mentions_max: 投稿に設定可能なメンションの最大数 (If the mentions include at least one person who is not a follower of yours)
stranger_mention_from_local_ng: フォローしていないアカウントへのメンションのNGワードを、ローカルユーザーによる投稿にも適用する
stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります
test_error: Testing is returned any errors
Expand Down
1 change: 1 addition & 0 deletions config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ ja:
keywords_hint: 行を「?」で始めると、正規表現が使えます
post_hash_tags_max: 投稿に設定可能なハッシュタグの最大数
post_mentions_max: 投稿に設定可能なメンションの最大数
post_stranger_mentions_max: 投稿に設定可能なメンションの最大数 (メンション先にフォロワー以外を1人でも含む場合)
stranger_mention_from_local_ng: フォローしていないアカウントへのメンションのNGワードを、ローカルユーザーによる投稿にも適用する
stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります
test_error: NGワードのテストに失敗しました。正規表現のミスが含まれているかもしれません
Expand Down
78 changes: 75 additions & 3 deletions spec/lib/activitypub/activity/create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2068,7 +2068,79 @@ def activity_for_object(json)
end

context 'when mentions limit is set' do
let(:post_mentions_max) { 2 }
let(:post_mentions_max) { 3 }
let(:post_stranger_mentions_max) { 0 }
let(:custom_before) { true }
let(:mention_recipient_alice) { Fabricate(:account) }
let(:mention_recipient_bob) { Fabricate(:account) }
let(:mention_recipient_ohagi) { Fabricate(:account) }
let(:mention_recipient_ohagi_follow) { true }
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: 'Lorem ipsum',
tag: [
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(mention_recipient_alice),
},
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(mention_recipient_bob),
},
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(mention_recipient_ohagi),
},
],
}
end

before do
Form::AdminSettings.new(post_mentions_max: post_mentions_max, post_stranger_mentions_max: post_stranger_mentions_max).save

mention_recipient_alice.follow!(sender)
mention_recipient_bob.follow!(sender)
mention_recipient_ohagi.follow!(sender) if mention_recipient_ohagi_follow

subject.perform
end

context 'when limit is enough' do
it 'creates status' do
expect(sender.statuses.first).to_not be_nil
end
end

context 'when limit is over' do
let(:post_mentions_max) { 1 }

it 'creates status' do
expect(sender.statuses.first).to be_nil
end
end

context 'when limit for stranger is over but normal limit is not reach' do
let(:post_stranger_mentions_max) { 1 }

it 'creates status' do
expect(sender.statuses.first).to_not be_nil
end
end

context 'when limit for stranger is over and following partically' do
let(:post_stranger_mentions_max) { 1 }
let(:mention_recipient_ohagi_follow) { false }

it 'creates status' do
expect(sender.statuses.first).to be_nil
end
end
end

context 'when mentions limit for stranger is set' do
let(:post_stranger_mentions_max) { 2 }
let(:custom_before) { true }
let(:object_json) do
{
Expand All @@ -2089,7 +2161,7 @@ def activity_for_object(json)
end

before do
Form::AdminSettings.new(post_mentions_max: post_mentions_max).save
Form::AdminSettings.new(post_stranger_mentions_max: post_stranger_mentions_max).save
subject.perform
end

Expand All @@ -2100,7 +2172,7 @@ def activity_for_object(json)
end

context 'when limit is over' do
let(:post_mentions_max) { 1 }
let(:post_stranger_mentions_max) { 1 }

it 'creates status' do
expect(sender.statuses.first).to be_nil
Expand Down
61 changes: 58 additions & 3 deletions spec/services/post_status_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -742,9 +742,11 @@
end

it 'using mentions under limit' do
Fabricate(:account, username: 'a')
Fabricate(:account, username: 'b')
a = Fabricate(:account, username: 'a')
b = Fabricate(:account, username: 'b')
account = Fabricate(:account)
a.follow!(account)
b.follow!(account)
text = '@a @b'
Form::AdminSettings.new(post_mentions_max: 2).save

Expand All @@ -755,11 +757,64 @@
end

it 'using mentions over limit' do
a = Fabricate(:account, username: 'a')
b = Fabricate(:account, username: 'b')
account = Fabricate(:account)
a.follow!(account)
b.follow!(account)
text = '@a @b'
Form::AdminSettings.new(post_mentions_max: 1).save

expect { subject.call(account, text: text) }.to raise_error Mastodon::ValidationError
end

it 'using mentions for stranger under limit' do
Fabricate(:account, username: 'a')
Fabricate(:account, username: 'b')
account = Fabricate(:account)
text = '@a @b'
Form::AdminSettings.new(post_mentions_max: 1).save
Form::AdminSettings.new(post_stranger_mentions_max: 2).save

status = subject.call(account, text: text)

expect(status).to be_persisted
expect(status.text).to eq text
end

it 'using mentions for stranger over limit' do
Fabricate(:account, username: 'a')
Fabricate(:account, username: 'b')
account = Fabricate(:account)
text = '@a @b'
Form::AdminSettings.new(post_stranger_mentions_max: 1).save

expect { subject.call(account, text: text) }.to raise_error Mastodon::ValidationError
end

it 'using mentions for stranger over limit but normal setting is under limit' do
a = Fabricate(:account, username: 'a')
b = Fabricate(:account, username: 'b')
account = Fabricate(:account)
a.follow!(account)
b.follow!(account)
text = '@a @b'
Form::AdminSettings.new(post_mentions_max: 2, post_stranger_mentions_max: 1).save

status = subject.call(account, text: text)

expect(status).to be_persisted
expect(status.text).to eq text
end

it 'using mentions for stranger over limit but normal setting is under limit when following one only' do
a = Fabricate(:account, username: 'a')
b = Fabricate(:account, username: 'b')
Fabricate(:account, username: 'c')
account = Fabricate(:account)
a.follow!(account)
b.follow!(account)
text = '@a @b @c'
Form::AdminSettings.new(post_mentions_max: 3, post_stranger_mentions_max: 2).save

expect { subject.call(account, text: text) }.to raise_error Mastodon::ValidationError
end
Expand Down
Loading