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