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 def v2_safe?
61 false
62 end
63
64 class Tel < CustomerFwd
65 def v2_safe?
66 true
67 end
68
69 def initialize(values)
70 super
71 raise "Bad tel format: #{uri}" unless uri.match?(/\Atel:\+1\d{10}\Z/)
72 end
73
74 def to
75 uri.sub(/^tel:/, "")
76 end
77 end
78
79 class SIP < CustomerFwd
80 def v2_safe?
81 uri.end_with?(CONFIG[:sip][:realm])
82 end
83
84 def to
85 uri
86 end
87 end
88
89 class XMPP < CustomerFwd
90 def v2_safe?
91 true
92 end
93
94 def to
95 jid = uri.sub(/^xmpp:/, "")
96 "sip:#{ERB::Util.url_encode(jid)}@sip.cheogram.com"
97 end
98 end
99
100 class None < CustomerFwd
101 def create_call(*); end
102
103 def to; end
104 end
105
106 URIS = {
107 tel: Tel,
108 sip: SIP,
109 xmpp: XMPP
110 }.freeze
111end