module Contacts class SubmitInquiry TOPICS = %w[commercial support privacy].freeze LIMIT = 5 WINDOW = 1.hour NAME_MAX = 120 CLUB_MAX = 160 MESSAGE_MIN = 10 MESSAGE_MAX = 4_000 Result = Struct.new(:ok, :error, keyword_init: true) def self.call(params:, ip:) new(params: params, ip: ip).call end def initialize(params:, ip:) @params = params @ip = ip.to_s.presence || "unknown" end def call if honeypot_filled? record_attempt return Result.new(ok: true, error: nil) end return Result.new(ok: false, error: :throttled) if throttled? error = validate return Result.new(ok: false, error: error) if error record_attempt deliver Result.new(ok: true, error: nil) end private def honeypot_filled? @params[:website].to_s.strip.present? end def throttled? current_count >= LIMIT end def validate return :privacy_required unless @params[:accept_privacy].to_s == "1" return :invalid if name.blank? || name.length > NAME_MAX return :invalid_email if email.blank? || email !~ URI::MailTo::EMAIL_REGEXP return :invalid if club_name.length > CLUB_MAX return :invalid unless TOPICS.include?(topic) return :invalid_message if message.length < MESSAGE_MIN || message.length > MESSAGE_MAX nil end def deliver mail = ContactMailer.inquiry( name: name, email: email, club_name: club_name, topic: topic, message: message ) MatchLiveTv.deliver_mail(mail) end def record_attempt Rails.cache.write(cache_key, current_count + 1, expires_in: WINDOW, raw: true) end def current_count Rails.cache.read(cache_key, raw: true).to_i end def cache_key "contacts:inquiry:#{@ip}" end def name @params[:name].to_s.strip end def email @params[:email].to_s.strip.downcase end def club_name @params[:club_name].to_s.strip end def topic @params[:topic].to_s.strip end def message @params[:message].to_s.strip end end end