# frozen_string_literal: true require "use_case/base" require "errors" module UseCase module Question class Create < UseCase::Base option :source_user_id, type: Types::Coercible::Integer | Types::Nil, optional: true option :target_user_id, type: Types::Coercible::Integer option :content, type: Types::Coercible::String option :anonymous, type: Types::Params::Bool, default: proc { false } option :author_identifier, type: Types::Coercible::String | Types::Nil option :direct, type: Types::Params::Bool, default: proc { true } def call check_anonymous_rules check_blocks question = ::Question.create!( content: content, author_is_anonymous: anonymous, author_identifier: author_identifier, user: source_user_id.nil? ? nil : source_user, direct: direct ) return if filtered?(question) increment_asked_count inbox = ::Inbox.create!(user: target_user, question: question, new: true) { question: question, inbox: inbox } end private def check_anonymous_rules if !source_user_id && !anonymous # We can not create a non-anonymous question without a source user raise Errors::BadRequest.new("anonymous must be set to true") end # The target user does not want questions from strangers raise Errors::Forbidden.new("no anonymous questions allowed") if !target_user.privacy_allow_anonymous_questions && anonymous end def check_blocks return if source_user_id.blank? raise Errors::AskingOtherBlockedSelf if target_user.blocking?(source_user) raise Errors::AskingSelfBlockedOther if source_user.blocking?(target_user) end def increment_asked_count unless source_user_id && !anonymous && !direct # Only increment the asked count of the source user if the question # is not anonymous, and we actually have a source user return end source_user.increment(:asked_count) source_user.save end def filtered?(question) target_user.mute_rules.any? { |rule| rule.applies_to? question } || (anonymous && target_user.anonymous_blocks.where(identifier: question.author_identifier).any?) end def source_user @source_user ||= ::User.find(source_user_id) end def target_user @target_user ||= ::User.find(target_user_id) end end end end