customer_fwd.rb

 1# frozen_string_literal: true
 2
 3require "bandwidth"
 4require "value_semantics/monkey_patched"
 5require "uri"
 6
 7class CustomerFwd
 8	def self.for(uri:, timeout:)
 9		timeout = Timeout.new(timeout)
10
11		fwd = if uri
12			if uri =~ /\Asip:(.*)@sip.cheogram.com\Z/
13				uri = "xmpp:#{$1.gsub(/%([0-9A-F]{2})/i) { $1.to_i(16).chr }}"
14			end
15
16			URIS.fetch(uri.split(":", 2).first.to_sym) {
17				raise "Unknown forward URI: #{uri}"
18			}.new(uri: uri, timeout: timeout)
19		end
20
21		fwd && !timeout.zero? ? fwd : None.new(uri: uri, timeout: timeout)
22	end
23
24	class Timeout
25		def self.new(s)
26			s.is_a?(self) ? s : super
27		end
28
29		def initialize(s)
30			@timeout = s.nil? || s.to_i.negative? || s.to_i > 300 ? 300 : s.to_i
31		end
32
33		def zero?
34			@timeout.zero?
35		end
36
37		def to_i
38			@timeout
39		end
40
41		def to_s
42			to_i.to_s
43		end
44	end
45
46	value_semantics do
47		uri Either(/:/, NilClass)
48		def_attr :timeout, Timeout, coerce: Timeout.method(:new)
49	end
50
51	def with(new_attrs)
52		CustomerFwd.for(to_h.merge(new_attrs))
53	end
54
55	def create_call(account)
56		request = Bandwidth::ApiCreateCallRequest.new.tap { |cc|
57			cc.to = to
58			cc.call_timeout = timeout.to_i
59			yield cc if block_given?
60		}
61		BANDWIDTH_VOICE.create_call(account, body: request).data.call_id
62	end
63
64	class Tel < CustomerFwd
65		def initialize(values)
66			super
67			raise "Bad tel format: #{uri}" unless uri.match?(/\Atel:\+1\d{10}\Z/)
68		end
69
70		def to
71			uri.sub(/^tel:/, "")
72		end
73	end
74
75	class SIP < CustomerFwd
76		def to
77			uri
78		end
79	end
80
81	class XMPP < CustomerFwd
82		def to
83			jid = uri.sub(/^xmpp:/, "")
84			"sip:#{ERB::Util.url_encode(jid)}@sip.cheogram.com"
85		end
86	end
87
88	class None < CustomerFwd
89		def create_call(*); end
90
91		def to; end
92	end
93
94	URIS = {
95		tel: Tel,
96		sip: SIP,
97		xmpp: XMPP
98	}.freeze
99end