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