2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-07 09:09:31 +08:00
|
|
|
class TextSentinel
|
|
|
|
attr_accessor :text
|
|
|
|
|
2024-10-16 10:09:07 +08:00
|
|
|
ENTROPY_SCALE = 0.7
|
2013-08-28 23:04:28 +08:00
|
|
|
|
2013-04-10 17:00:50 +08:00
|
|
|
def initialize(text, opts = nil)
|
|
|
|
@opts = opts || {}
|
2013-05-23 12:52:12 +08:00
|
|
|
@text = text.to_s.encode("UTF-8", invalid: :replace, undef: :replace, replace: "")
|
2013-04-10 17:00:50 +08:00
|
|
|
end
|
|
|
|
|
2013-06-13 16:18:17 +08:00
|
|
|
def self.body_sentinel(text, opts = {})
|
|
|
|
entropy = SiteSetting.body_min_entropy
|
|
|
|
if opts[:private_message]
|
2018-01-31 13:56:00 +08:00
|
|
|
scale_entropy =
|
|
|
|
SiteSetting.min_personal_message_post_length.to_f / SiteSetting.min_post_length.to_f
|
2013-06-13 16:18:17 +08:00
|
|
|
entropy = (entropy * scale_entropy).to_i
|
2018-01-31 13:56:00 +08:00
|
|
|
entropy =
|
|
|
|
(SiteSetting.min_personal_message_post_length.to_f * ENTROPY_SCALE).to_i if entropy >
|
|
|
|
SiteSetting.min_personal_message_post_length
|
2013-08-28 23:04:28 +08:00
|
|
|
else
|
|
|
|
entropy = (SiteSetting.min_post_length.to_f * ENTROPY_SCALE).to_i if entropy >
|
|
|
|
SiteSetting.min_post_length
|
2013-06-13 16:18:17 +08:00
|
|
|
end
|
|
|
|
TextSentinel.new(text, min_entropy: entropy)
|
2013-02-07 09:09:31 +08:00
|
|
|
end
|
|
|
|
|
2013-02-09 05:55:40 +08:00
|
|
|
def self.title_sentinel(text)
|
2013-08-28 23:04:28 +08:00
|
|
|
entropy =
|
|
|
|
if SiteSetting.min_topic_title_length > SiteSetting.title_min_entropy
|
|
|
|
SiteSetting.title_min_entropy
|
|
|
|
else
|
|
|
|
(SiteSetting.min_topic_title_length.to_f * ENTROPY_SCALE).to_i
|
|
|
|
end
|
2015-04-02 13:46:53 +08:00
|
|
|
TextSentinel.new(text, min_entropy: entropy, max_word_length: SiteSetting.title_max_word_length)
|
2013-02-09 05:55:40 +08:00
|
|
|
end
|
|
|
|
|
2024-07-22 23:35:52 +08:00
|
|
|
# Number of unique bytes
|
2013-02-07 09:09:31 +08:00
|
|
|
def entropy
|
2024-07-22 23:35:52 +08:00
|
|
|
@entropy ||= @text.strip.bytes.uniq.size
|
2013-02-07 09:09:31 +08:00
|
|
|
end
|
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
def valid?
|
2013-05-24 01:48:37 +08:00
|
|
|
@text.present? && seems_meaningful? && seems_pronounceable? && seems_unpretentious? &&
|
2013-06-18 13:49:10 +08:00
|
|
|
seems_quiet?
|
2013-05-24 01:48:37 +08:00
|
|
|
end
|
|
|
|
|
2024-07-22 23:35:52 +08:00
|
|
|
# Ensure minumum entropy
|
2013-05-24 01:48:37 +08:00
|
|
|
def seems_meaningful?
|
2024-07-22 23:35:52 +08:00
|
|
|
@opts[:min_entropy].nil? || entropy >= @opts[:min_entropy]
|
2013-05-24 01:48:37 +08:00
|
|
|
end
|
2013-02-07 09:09:31 +08:00
|
|
|
|
2024-07-22 23:35:52 +08:00
|
|
|
# At least one non-symbol character
|
2013-05-24 01:48:37 +08:00
|
|
|
def seems_pronounceable?
|
2024-07-22 23:35:52 +08:00
|
|
|
@text.match?(/\p{Alnum}/)
|
2013-05-24 01:48:37 +08:00
|
|
|
end
|
2013-02-07 09:09:31 +08:00
|
|
|
|
2024-07-22 23:35:52 +08:00
|
|
|
# Ensure maximum word length
|
2013-05-24 01:48:37 +08:00
|
|
|
def seems_unpretentious?
|
2024-07-22 23:35:52 +08:00
|
|
|
skipped_locales.include?(SiteSetting.default_locale) || @opts[:max_word_length].nil? ||
|
2024-07-23 23:12:29 +08:00
|
|
|
!@text.match?(/\p{Alnum}{#{@opts[:max_word_length] + 1},}/)
|
2013-05-24 01:48:37 +08:00
|
|
|
end
|
2013-02-07 09:09:31 +08:00
|
|
|
|
2024-07-22 23:35:52 +08:00
|
|
|
# Ensure at least one lowercase letter
|
2013-05-24 01:48:37 +08:00
|
|
|
def seems_quiet?
|
2024-07-22 23:35:52 +08:00
|
|
|
SiteSetting.allow_uppercase_posts || @text.match?(/\p{Lowercase_Letter}|\p{Other_Letter}/) ||
|
|
|
|
!@text.match?(/\p{Letter}/)
|
2013-02-07 09:09:31 +08:00
|
|
|
end
|
|
|
|
|
2020-11-11 21:11:36 +08:00
|
|
|
private
|
|
|
|
|
2024-07-22 23:35:52 +08:00
|
|
|
# Hard to tell "word length" for CJK languages
|
|
|
|
def skipped_locales
|
|
|
|
@skipped_locales ||= %w[ja ko zh_CN zh_TW].freeze
|
2020-11-11 21:11:36 +08:00
|
|
|
end
|
2013-02-07 09:09:31 +08:00
|
|
|
end
|