~singpolyma/sgx-jmp

sgx-jmp/lib/customer_fwd.rb -rw-r--r-- 2.4 KiB
94298f5dStephen Paul Weber Refactor alt top up to use FormTemplate 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# frozen_string_literal: true

require "bandwidth"
require "value_semantics/monkey_patched"
require "uri"

class CustomerFwd
	class InfiniteTimeout < StandardError
		attr_reader :fwd

		def initialize(fwd)
			super "Infinite timeout"
			@fwd = fwd
		end
	end

	def self.for(uri:, timeout: nil, voicemail_enabled: :default)
		timeout = Timeout.for(timeout, voicemail_enabled: voicemail_enabled)

		fwd = if uri
			if uri =~ /\Asip:(.*)@sip.cheogram.com\Z/
				uri = "xmpp:#{$1.gsub(/%([0-9A-F]{2})/i) { $1.to_i(16).chr }}"
			end

			URIS.fetch(uri.split(":", 2).first&.to_sym) {
				raise "Unknown forward URI: #{uri}"
			}.new(uri: uri, timeout: timeout)
		end

		fwd && !timeout.zero? ? fwd : None.new(uri: uri, timeout: timeout)
	end

	class Timeout
		def self.for(s, voicemail_enabled: :default)
			return Infinite.new unless voicemail_enabled

			if s.nil? || s.is_a?(Infinite) || s.to_i.negative?
				return new(25) if voicemail_enabled == true # ~5s / ring, 5 rings

				return Infinite.new
			end

			return s if s.is_a?(self)

			new(s)
		end

		def initialize(s)
			@timeout = [s.to_i, 300].min
		end

		def zero?
			@timeout.zero?
		end

		def infinite?
			false
		end

		def to_i
			@timeout
		end

		def to_s
			to_i.to_s
		end

		class Infinite < Timeout
			def initialize; end

			def zero?
				false
			end

			def infinite?
				1
			end

			def to_i; end
		end
	end

	value_semantics do
		uri Either(/:/, NilClass)
		def_attr :timeout, Timeout, coerce: Timeout.method(:for)
	end

	def with(new_attrs)
		CustomerFwd.for(to_h.merge(new_attrs))
	end

	def voicemail_enabled?
		!timeout.infinite?
	end

	def create_call(account)
		raise InfiniteTimeout, self if timeout.infinite?

		request = Bandwidth::ApiCreateCallRequest.new.tap { |cc|
			cc.to = to
			cc.call_timeout = timeout.to_i
			yield cc if block_given?
		}
		BANDWIDTH_VOICE.create_call(account, body: request).data.call_id
	end

	class Tel < CustomerFwd
		def initialize(values)
			super
			raise "Bad tel format: #{uri}" unless uri.match?(/\Atel:\+1\d{10}\Z/)
		end

		def to
			uri.sub(/^tel:/, "")
		end
	end

	class SIP < CustomerFwd
		def to
			uri
		end
	end

	class XMPP < CustomerFwd
		def to
			jid = uri.sub(/^xmpp:/, "")
			"sip:#{ERB::Util.url_encode(jid)}@sip.cheogram.com"
		end
	end

	class None < CustomerFwd
		def create_call(*); end

		def to; end
	end

	URIS = {
		tel: Tel,
		sip: SIP,
		xmpp: XMPP
	}.freeze
end