# frozen_string_literal: true require "bandwidth" require "value_semantics/monkey_patched" require "uri" class CustomerFwd class InfiniteTimeout < StandardError attr_reader :fwd def initialize(fwd) super "Infinite timeout" @fwd = fwd end end def self.for(uri:, timeout: nil, voicemail_enabled: :default) timeout = Timeout.for(timeout, voicemail_enabled: voicemail_enabled) fwd = if uri if uri =~ /\Asip:(.*)@sip.cheogram.com\Z/ uri = "xmpp:#{$1.gsub(/%([0-9A-F]{2})/i) { $1.to_i(16).chr }}" end URIS.fetch(uri.split(":", 2).first&.to_sym) { raise "Unknown forward URI: #{uri}" }.new(uri: uri, timeout: timeout) end fwd && !timeout.zero? ? fwd : None.new(uri: uri, timeout: timeout) end class Timeout def self.for(s, voicemail_enabled: :default) return Infinite.new unless voicemail_enabled if s.nil? || s.is_a?(Infinite) || s.to_i.negative? return new(25) if voicemail_enabled == true # ~5s / ring, 5 rings return Infinite.new end return s if s.is_a?(self) new(s) end def initialize(s) @timeout = [s.to_i, 300].min end def zero? @timeout.zero? end def infinite? false end def to_i @timeout end def to_s to_i.to_s end class Infinite < Timeout def initialize; end def zero? false end def infinite? 1 end def to_i; end end end value_semantics do uri Either(/:/, NilClass) def_attr :timeout, Timeout, coerce: Timeout.method(:for) end def with(new_attrs) CustomerFwd.for(to_h.merge(new_attrs)) end def voicemail_enabled? !timeout.infinite? end def create_call(account) raise InfiniteTimeout, self if timeout.infinite? request = Bandwidth::ApiCreateCallRequest.new.tap { |cc| cc.to = to cc.call_timeout = timeout.to_i yield cc if block_given? } BANDWIDTH_VOICE.create_call(account, body: request).data.call_id end class Tel < CustomerFwd def initialize(values) super raise "Bad tel format: #{uri}" unless uri.match?(/\Atel:\+1\d{10}\Z/) end def to uri.sub(/^tel:/, "") end end class SIP < CustomerFwd def to uri end end class XMPP < CustomerFwd def to jid = uri.sub(/^xmpp:/, "") "sip:#{ERB::Util.url_encode(jid)}@sip.cheogram.com" end end class None < CustomerFwd def create_call(*); end def to; end end URIS = { tel: Tel, sip: SIP, xmpp: XMPP }.freeze end