You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
docuseal/lib/sms.rb

64 lines
2.2 KiB

# frozen_string_literal: true
module Sms
class Error < StandardError; end
class NotConfiguredError < Error; end
class ProviderError < Error; end
class InvalidNumberError < Error; end
SUPPORTED_PROVIDERS = %w[bulkvs].freeze
module_function
# Returns the SMS configuration hash for an account, with the same keys the
# form posts: { provider, enabled, basic_auth_token, from_number,
# delivery_webhook_url }. Returns nil if no record exists.
def configuration_for(account)
return nil if account.nil?
record = EncryptedConfig.find_by(account_id: account.id, key: EncryptedConfig::SMS_CONFIGS_KEY)
record&.value
end
def enabled_for?(account)
config = configuration_for(account)
config.is_a?(Hash) &&
config['enabled'] &&
SUPPORTED_PROVIDERS.include?(config['provider'].to_s) &&
config['basic_auth_token'].to_s.present? &&
config['from_number'].to_s.present?
end
# Send an SMS via the account's configured provider.
#
# account: a WaboSign Account record
# to: the recipient phone number (E.164 string, leading + tolerated)
# text: the message body (already variable-substituted)
# webhook: optional override of the per-message delivery_status_webhook_url
#
# Returns the provider's parsed JSON response on success. Raises
# NotConfiguredError or ProviderError on failure.
def send_message(account:, to:, text:, webhook: nil)
config = configuration_for(account)
raise NotConfiguredError, 'SMS provider is not configured' unless enabled_for?(account)
provider = config['provider'].to_s
case provider
when 'bulkvs'
Sms::Providers::Bulkvs.new(config).deliver(to: to, text: text, webhook: webhook)
else
raise NotConfiguredError, "Unsupported SMS provider: #{provider.inspect}"
end
end
# Normalize a phone number to E.164 (digits-only, no '+'). BulkVS expects
# eleven-digit US numbers like 15551234567; international numbers are passed
# through as-is once stripped of formatting characters.
def normalize_phone(raw)
digits = raw.to_s.gsub(/[^\d]/, '')
raise InvalidNumberError, "Invalid phone number: #{raw.inspect}" if digits.length < 8
digits
end
end