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