1# frozen_string_literal: true
2
3require "em_promise"
4require "ruby-bandwidth-iris"
5Faraday.default_adapter = :em_synchrony
6
7class BandwidthTNOptions
8 def self.tn_eligible_for_port_out_pin?(creds)
9 user_id, token, secret, tel = creds
10 tel_local = tel.sub(/^\+1/, '')
11 client = BandwidthIris::Client.new(
12 account_id: user_id,
13 username: token,
14 password: secret
15 )
16 EMPromise.resolve(nil).then do
17 begin
18 tn = BandwidthIris::Tn.get(client, tel_local)
19 rescue BandwidthIris::Errors::GenericError => e
20 raise e unless e.http_status == 404
21
22 next false
23 end
24 details = tn.get_details()
25 details[:tier] == 0.0 && details[:on_net_vendor] == true
26 end
27 end
28
29 def self.set_port_out_pin(creds, pin)
30 tn_eligible_for_port_out_pin?(creds).then do |eligible|
31 unless eligible
32 raise "TN not eligible for port-out PIN"
33 end
34
35 user_id, token, secret, tel = creds
36 tel_local = tel.sub(/^\+1/, '')
37
38 client = BandwidthIris::Client.new(
39 account_id: user_id,
40 username: token,
41 password: secret
42 )
43
44
45 data = {
46 tn_option_groups: {
47 tn_option_group: [
48 {
49 port_out_passcode: pin,
50 telephone_numbers: {
51 telephone_number: [tel]
52 }
53 }
54 ]
55 }
56 }
57
58 order = BandwidthIris::TnOptions.create_tn_option_order(client, data)
59 order_id = order[:order_id]
60
61 unless order_id
62 raise "Missing OrderId in create response"
63 end
64
65 poll_order(order_id, client)
66 end
67 end
68
69 def self.poll_order(order_id, client, attempt=1, max_attempts=30)
70 if attempt > max_attempts
71 return EMPromise.reject(RuntimeError.new(
72 "TnOptions polling timeout after #{max_attempts} attempts"
73 ))
74 end
75
76 EMPromise.resolve(nil).then do
77 order = BandwidthIris::TnOptions.get_tn_option_order(client, order_id)
78
79 error_list = order[:error_list]
80 if error_list&.any?
81 errors = [error_list].flatten
82 msgs = errors.map { |e| e.to_s }.reject(&:empty?).join('; ')
83 raise "Dashboard tnOptions errors: #{msgs}"
84 end
85
86 warnings = order[:warnings]
87 if warnings&.any?
88 warns = [warnings].flatten
89 descs = warns.map { |w| w.to_s }.reject(&:empty?).join('; ')
90 raise "Dashboard tnOptions warnings: #{descs}"
91 end
92
93 status = order[:order_status] || order[:processing_status]
94
95 case status&.to_s&.upcase
96 when 'COMPLETE', 'PARTIAL'
97 true
98 when 'FAILED'
99 raise "TnOptions order failed with status: #{status}"
100 when 'RECEIVED', 'PROCESSING'
101 EMPromise.new { |resolve, reject|
102 EM.add_timer(2) do
103 poll_order(order_id, client, attempt + 1, max_attempts)
104 .then { |result| resolve.call(result) }
105 .catch { |error| reject.call(error) }
106 end
107 }
108 else
109 raise "Unexpected poll status: #{status.inspect}"
110 end
111 end
112 end
113end