Skip to content

Commit

Permalink
Add: #43 フォローしていないアカウントからのリプライのNGワード (#148)
Browse files Browse the repository at this point in the history
* Add: フォローしていないアカウントからのリプライのNGワード

* Test: ハッシュタグ使用量
  • Loading branch information
kmycode authored Oct 19, 2023
1 parent da662d2 commit 3a2030d
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 5 deletions.
2 changes: 1 addition & 1 deletion app/controllers/admin/ng_words_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def create
private

def test_words
ng_words = settings_params['ng_words'].split(/\r\n|\r|\n/)
ng_words = "#{settings_params['ng_words']}\n#{settings_params['ng_words_for_stranger_mention']}".split(/\r\n|\r|\n/).filter(&:present?)
Admin::NgWord.reject_with_custom_words?('Sample text', ng_words)
end

Expand Down
16 changes: 12 additions & 4 deletions app/lib/activitypub/activity/create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def process_status

return nil unless valid_status?
return nil if (reply_to_local? || reply_to_local_account? || reply_to_local_from_tags?) && reject_reply_to_local?
return nil if (!reply_to_local_account_following? || !reply_to_local_status_following? || !reply_to_local_from_tags_following?) && reject_reply_exclude_followers?
return nil if mention_to_local_but_not_followed? && reject_reply_exclude_followers?

ApplicationRecord.transaction do
@status = Status.create!(@params)
Expand Down Expand Up @@ -139,7 +139,11 @@ def process_status_params
end

def valid_status?
!Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") && !Admin::NgWord.hashtag_reject?(@tags.size)
valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") && !Admin::NgWord.hashtag_reject?(@tags.size)

valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") if valid && mention_to_local_but_not_followed?

valid
end

def accounts_in_audience
Expand Down Expand Up @@ -418,11 +422,11 @@ def reply_to_local_account_following?
end

def reply_to_local_from_tags?
(@mentions.present? && @mentions.any? { |m| m.account.local? })
@mentions.present? && @mentions.any? { |m| m.account.local? }
end

def reply_to_local_from_tags_following?
(@mentions.present? && @mentions.none? { |m| m.account.local? && !m.account.following?(@account) })
@mentions.nil? || @mentions.none? { |m| m.account.local? && !m.account.following?(@account) }
end

def reply_to_local?
Expand All @@ -433,6 +437,10 @@ def reply_to_local_status_following?
!reply_to_local? || replied_to_status.account.following?(@account)
end

def mention_to_local_but_not_followed?
!reply_to_local_account_following? || !reply_to_local_status_following? || !reply_to_local_from_tags_following?
end

def reject_reply_to_local?
@reject_reply_to_local ||= DomainBlock.reject_reply?(@account.domain)
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/admin/ng_word.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def hashtag_reject_with_extractor?(text)
hashtag_reject?(Extractor.extract_hashtags(text)&.size || 0)
end

def stranger_mention_reject?(text)
ng_words_for_stranger_mention.any? { |word| include?(text, word) }
end

private

def include?(text, word)
Expand All @@ -32,6 +36,10 @@ def ng_words
Setting.ng_words || []
end

def ng_words_for_stranger_mention
Setting.ng_words_for_stranger_mention || []
end

def post_hash_tags_max
value = Setting.post_hash_tags_max
value.is_a?(Integer) && value.positive? ? value : 0
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 @@ -38,6 +38,7 @@ class Form::AdminSettings
status_page_url
captcha_enabled
ng_words
ng_words_for_stranger_mention
hide_local_users_for_anonymous
post_hash_tags_max
sensitive_words
Expand Down Expand Up @@ -91,6 +92,7 @@ class Form::AdminSettings

STRING_ARRAY_KEYS = %i(
ng_words
ng_words_for_stranger_mention
sensitive_words
sensitive_words_for_full
).freeze
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 @@ -7,6 +7,9 @@
= simple_form_for @admin_settings, url: admin_ng_words_path, html: { method: :post } do |f|
= render 'shared/error_messages', object: @admin_settings

.fields-group
= f.input :ng_words_for_stranger_mention, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords_for_stranger_mention'), hint: t('admin.ng_words.keywords_for_stranger_mention_hint')

.fields-group
= f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint')

Expand Down
2 changes: 2 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ en:
ng_words:
hide_local_users_for_anonymous: Hide timeline local user posts from anonymous
keywords: Reject keywords
keywords_for_stranger_mention: Reject keywords when mention/reply from strangers
keywords_for_stranger_mention_hint: Currently this words are checked posts from other servers only.
keywords_hint: The first character of the line is "?". to use regular expressions
post_hash_tags_max: Hash tags max for posts
test_error: Testing is returned any errors
Expand Down
2 changes: 2 additions & 0 deletions config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ ja:
ng_words:
hide_local_users_for_anonymous: ログインしていない状態でローカルユーザーの投稿をタイムラインから取得できないようにする
keywords: 投稿できないキーワード
keywords_for_stranger_mention: フォローしていないアカウントへのメンションで利用できないキーワード
keywords_for_stranger_mention_hint: フォローしていないアカウントへのメンションにのみ適用されます。現状は外部サーバーから来た投稿のみに適用されます
keywords_hint: 行を「?」で始めると、正規表現が使えます
post_hash_tags_max: 投稿に設定可能なハッシュタグの最大数
test_error: NGワードのテストに失敗しました。正規表現のミスが含まれているかもしれません
Expand Down
193 changes: 193 additions & 0 deletions spec/lib/activitypub/activity/create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,199 @@
expect(status.language).to eq 'en-US'
end
end

context 'when ng word is set' do
let(:custom_before) { true }
let(:custom_before_sub) { false }
let(:content) { 'Lorem ipsum' }
let(:ng_words) { 'hello' }
let(:ng_words_for_stranger_mention) { 'ohagi' }
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: content,
to: 'https://www.w3.org/ns/activitystreams#Public',
}
end

before do
Form::AdminSettings.new(ng_words: ng_words, ng_words_for_stranger_mention: ng_words_for_stranger_mention).save
subject.perform unless custom_before_sub
end

context 'when not contains ng words' do
let(:content) { 'ohagi, world!' }

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

context 'when hit ng words' do
let(:content) { 'hello, world!' }

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

context 'when mention from tags' do
let(:recipient) { Fabricate(:user).account }

let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: content,
tag: [
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(recipient),
},
],
}
end

context 'with not using ng words for stranger' do
let(:content) { 'among us' }

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

context 'with using ng words for stranger' do
let(:content) { 'oh, ohagi!' }

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

context 'with using ng words for stranger but receiver is following him' do
let(:content) { 'oh, ohagi!' }
let(:custom_before_sub) { true }

before do
recipient.follow!(sender)
subject.perform
end

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

context 'with using ng words for stranger but multiple receivers are partically following him' do
let(:content) { 'oh, ohagi' }
let(:custom_before_sub) { true }

let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: content,
tag: [
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(recipient),
},
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(Fabricate(:user).account),
},
],
}
end

before do
recipient.follow!(sender)
subject.perform
end

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

context 'when a reply' do
let(:recipient) { Fabricate(:user).account }
let(:original_status) { Fabricate(:status, account: recipient) }

let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: 'ohagi peers',
inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
}
end

context 'with a simple case' do
it 'creates status' do
expect(sender.statuses.first).to be_nil
end
end

context 'with following' do
let(:custom_before_sub) { true }

before do
recipient.follow!(sender)
subject.perform
end

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

context 'when hashtags limit is set' do
let(:post_hash_tags_max) { 2 }
let(:custom_before) { true }
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: 'Lorem ipsum',
tag: [
{
type: 'Hashtag',
href: 'http://example.com/blah',
name: '#test',
},
{
type: 'Hashtag',
href: 'http://example.com/blah2',
name: '#test2',
},
],
}
end

before do
Form::AdminSettings.new(post_hash_tags_max: post_hash_tags_max).save
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_hash_tags_max) { 1 }

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

context 'with an encrypted message' do
Expand Down

0 comments on commit 3a2030d

Please sign in to comment.