Change: #648 センシティブワードの入力フォーム (#653)

* Change: #648 センシティブワードの入力フォーム

* Wip: 行の追加削除

* Wip: 設定の保存、マイグレーション

* 不要な処理を削除

* マイグレーションコード調整
This commit is contained in:
KMY(雪あすか) 2024-03-19 08:18:34 +09:00 committed by GitHub
parent f509bd4fc3
commit ed246f0d03
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 377 additions and 61 deletions

View file

@ -5,12 +5,12 @@ class Admin::SensitiveWord
def sensitive?(text, spoiler_text, local: true)
exposure_text = spoiler_text.presence || text
sensitive = (spoiler_text.blank? && sensitive_words_all.any? { |word| include?(text, word) }) ||
sensitive_words_all_for_full.any? { |word| include?(exposure_text, word) }
return sensitive if sensitive || !local
sensitive_words = ::SensitiveWord.caches
sensitive_words.select!(&:remote) unless local
(spoiler_text.blank? && sensitive_words.any? { |word| include?(text, word) }) ||
sensitive_words_for_full.any? { |word| include?(exposure_text, word) }
return sensitive_words.filter(&:spoiler).any? { |word| include?(spoiler_text, word) } if spoiler_text.present?
sensitive_words.any? { |word| include?(exposure_text, word) }
end
def modified_text(text, spoiler_text)
@ -24,27 +24,11 @@ class Admin::SensitiveWord
private
def include?(text, word)
if word.start_with?('?') && word.size >= 2
text =~ /#{word[1..]}/i
if word.regexp
text =~ /#{word.keyword}/
else
text.include?(word)
text.include?(word.keyword)
end
end
def sensitive_words
Setting.sensitive_words || []
end
def sensitive_words_for_full
Setting.sensitive_words_for_full || []
end
def sensitive_words_all
Setting.sensitive_words_all || []
end
def sensitive_words_all_for_full
Setting.sensitive_words_all_for_full || []
end
end
end

View file

@ -51,10 +51,6 @@ class Form::AdminSettings
post_hash_tags_max
post_mentions_max
post_stranger_mentions_max
sensitive_words
sensitive_words_for_full
sensitive_words_all
sensitive_words_all_for_full
auto_warning_text
authorized_fetch
receive_other_servers_emoji_reaction
@ -128,10 +124,6 @@ class Form::AdminSettings
STRING_ARRAY_KEYS = %i(
ng_words
ng_words_for_stranger_mention
sensitive_words
sensitive_words_for_full
sensitive_words_all
sensitive_words_all_for_full
emoji_reaction_disallow_domains
permit_new_account_domains
).freeze

View file

@ -0,0 +1,81 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: sensitive_words
#
# id :bigint(8) not null, primary key
# keyword :string not null
# regexp :boolean default(FALSE), not null
# remote :boolean default(FALSE), not null
# spoiler :boolean default(TRUE), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class SensitiveWord < ApplicationRecord
attr_accessor :keywords, :regexps, :remotes, :spoilers
class << self
def caches
Rails.cache.fetch('sensitive_words') { SensitiveWord.where.not(id: 0).order(:keyword).to_a }
end
def save_from_hashes(rows)
unmatched = caches
matched = []
SensitiveWord.transaction do
rows.filter { |item| item[:keyword].present? }.each do |item|
exists = unmatched.find { |i| i.keyword == item[:keyword] }
if exists.present?
unmatched.delete(exists)
matched << exists
next if exists.regexp == item[:regexp] && exists.remote == item[:remote] && exists.spoiler == item[:spoiler]
exists.update!(regexp: item[:regexp], remote: item[:remote], spoiler: item[:spoiler])
elsif matched.none? { |i| i.keyword == item[:keyword] }
SensitiveWord.create!(
keyword: item[:keyword],
regexp: item[:regexp],
remote: item[:remote],
spoiler: item[:spoiler]
)
end
end
SensitiveWord.destroy(unmatched.map(&:id))
end
true
# rescue
# false
end
def save_from_raws(rows)
regexps = rows['regexps'] || []
remotes = rows['remotes'] || []
spoilers = rows['spoilers'] || []
hashes = (rows['keywords'] || []).zip(rows['temporary_ids'] || []).map do |item|
temp_id = item[1]
{
keyword: item[0],
regexp: regexps.include?(temp_id),
remote: remotes.include?(temp_id),
spoiler: spoilers.include?(temp_id),
}
end
save_from_hashes(hashes)
end
end
private
def invalidate_cache!
Rails.cache.delete('sensitive_words')
end
end