# frozen_string_literal: true class Chat::DuplicateMessageValidator attr_reader :chat_message def initialize(chat_message) @chat_message = chat_message end def validate return if SiteSetting.chat_duplicate_message_sensitivity.zero? matrix = Chat::DuplicateMessageValidator.sensitivity_matrix( SiteSetting.chat_duplicate_message_sensitivity, ) # Check if the length of the message is too short to check for a duplicate message return if chat_message.message.length < matrix[:min_message_length] # Check if there are enough users in the channel to check for a duplicate message return if (chat_message.chat_channel.user_count || 0) < matrix[:min_user_count] # Check if the same duplicate message has been posted in the last N seconds by any user if !chat_message .chat_channel .chat_messages .where("created_at > ?", matrix[:min_past_seconds].seconds.ago) .where(message: chat_message.message) .exists? return end chat_message.errors.add(:base, I18n.t("chat.errors.duplicate_message")) end def self.sensitivity_matrix(sensitivity) { # 0.1 sensitivity = 100 users and 1.0 sensitivity = 5 users. min_user_count: (-1.0 * 105.5 * sensitivity + 110.55).to_i, # 0.1 sensitivity = 30 chars and 1.0 sensitivity = 10 chars. min_message_length: (-1.0 * 22.2 * sensitivity + 32.22).to_i, # 0.1 sensitivity = 10 seconds and 1.0 sensitivity = 60 seconds. min_past_seconds: (55.55 * sensitivity + 4.5).to_i, } end end