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 if uri =~ /\Asip:(.*)@sip.cheogram.com\Z/
11 uri = "xmpp:#{$1.gsub(/%([0-9A-F]{2})/i) { $1.to_i(16).chr }}"
12 end
13 URIS.fetch(uri.split(":", 2).first.to_sym) {
14 raise "Unknown forward URI: #{uri}"
15 }.new(uri: uri, timeout: timeout)
16 end
17
18 class Timeout
19 def self.new(s)
20 s.is_a?(self) ? s : super
21 end
22
23 def initialize(s)
24 @timeout = s.nil? || s.to_i.negative? ? 300 : s.to_i
25 end
26
27 def zero?
28 @timeout.zero?
29 end
30
31 def to_i
32 @timeout
33 end
34 end
35
36 value_semantics do
37 uri Either(String, NilClass)
38 # rubocop:disable Style/RedundantSelf
39 self.timeout Timeout, coerce: Timeout.method(:new)
40 # rubocop:enable Style/RedundantSelf
41 end
42
43 def with(new_attrs)
44 CustomerFwd.for(to_h.merge(new_attrs))
45 end
46
47 def create_call(account)
48 request = Bandwidth::ApiCreateCallRequest.new.tap do |cc|
49 cc.to = to
50 cc.call_timeout = timeout.to_i
51 yield cc if block_given?
52 end
53 BANDWIDTH_VOICE.create_call(account, body: request).data.call_id
54 end
55
56 class Tel < CustomerFwd
57 def to
58 uri.sub(/^tel:/, "")
59 end
60 end
61
62 class SIP < CustomerFwd
63 def to
64 uri
65 end
66 end
67
68 class XMPP < CustomerFwd
69 def to
70 jid = uri.sub(/^xmpp:/, "")
71 "sip:#{ERB::Util.url_encode(jid)}@sip.cheogram.com"
72 end
73 end
74
75 class None < CustomerFwd
76 def create_call; end
77
78 def to; end
79 end
80
81 URIS = {
82 tel: Tel,
83 sip: SIP,
84 xmpp: XMPP
85 }.freeze
86end