rcs 2.0.19 → 2.0.20.pre.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.fern/metadata.json +5 -6
  3. data/lib/pinnacle/calls/client.rb +359 -0
  4. data/lib/pinnacle/calls/types/calls_download_recording_request.rb +13 -0
  5. data/lib/pinnacle/calls/types/calls_list_events_request.rb +15 -0
  6. data/lib/pinnacle/calls/types/calls_list_request.rb +25 -0
  7. data/lib/pinnacle/calls/types/create_call_params.rb +17 -0
  8. data/lib/pinnacle/calls/types/create_stream_token_params.rb +17 -0
  9. data/lib/pinnacle/calls/types/update_call_params.rb +13 -0
  10. data/lib/pinnacle/client.rb +11 -1
  11. data/lib/pinnacle/forms/client.rb +1 -1
  12. data/lib/pinnacle/network/client.rb +34 -0
  13. data/lib/pinnacle/network/requests/client.rb +94 -0
  14. data/lib/pinnacle/network/requests/types/list_network_requests_params.rb +21 -0
  15. data/lib/pinnacle/network/silent_auth/client.rb +107 -0
  16. data/lib/pinnacle/network/silent_auth/types/silent_auth_check_request.rb +15 -0
  17. data/lib/pinnacle/network/silent_auth/types/silent_auth_request.rb +17 -0
  18. data/lib/pinnacle/network/sim_swap/client.rb +55 -0
  19. data/lib/pinnacle/network/sim_swap/types/sim_swap_request.rb +15 -0
  20. data/lib/pinnacle/network/subscriber_match/client.rb +55 -0
  21. data/lib/pinnacle/network/subscriber_match/types/subscriber_match_request.rb +15 -0
  22. data/lib/pinnacle/pinnacle_client.rb +8 -0
  23. data/lib/pinnacle/types/agent_summary_carrier_launches.rb +1 -1
  24. data/lib/pinnacle/types/call.rb +31 -0
  25. data/lib/pinnacle/types/call_direction.rb +12 -0
  26. data/lib/pinnacle/types/call_event.rb +27 -0
  27. data/lib/pinnacle/types/call_event_source.rb +14 -0
  28. data/lib/pinnacle/types/call_metadata.rb +23 -0
  29. data/lib/pinnacle/types/call_state.rb +19 -0
  30. data/lib/pinnacle/types/call_status_event.rb +14 -0
  31. data/lib/pinnacle/types/call_status_event_call.rb +17 -0
  32. data/lib/pinnacle/types/call_stream_token.rb +13 -0
  33. data/lib/pinnacle/types/created_call.rb +33 -0
  34. data/lib/pinnacle/types/e_164_phone_number.rb +23 -0
  35. data/lib/pinnacle/types/hosted_silent_auth_response.rb +13 -0
  36. data/lib/pinnacle/types/json_silent_auth_response.rb +13 -0
  37. data/lib/pinnacle/types/list_call_events_response.rb +11 -0
  38. data/lib/pinnacle/types/list_calls_response.rb +11 -0
  39. data/lib/pinnacle/types/list_network_requests_response.rb +13 -0
  40. data/lib/pinnacle/types/network_insight_status.rb +14 -0
  41. data/lib/pinnacle/types/network_request_id.rb +23 -0
  42. data/lib/pinnacle/types/network_request_result.rb +16 -0
  43. data/lib/pinnacle/types/network_request_status.rb +15 -0
  44. data/lib/pinnacle/types/network_request_summary.rb +27 -0
  45. data/lib/pinnacle/types/network_request_type.rb +13 -0
  46. data/lib/pinnacle/types/recording_download.rb +11 -0
  47. data/lib/pinnacle/types/recording_state.rb +14 -0
  48. data/lib/pinnacle/types/silent_auth_check_response.rb +11 -0
  49. data/lib/pinnacle/types/silent_auth_check_response_status.rb +12 -0
  50. data/lib/pinnacle/types/silent_auth_response.rb +15 -0
  51. data/lib/pinnacle/types/sim_swap_response.rb +15 -0
  52. data/lib/pinnacle/types/subscriber_match_attributes.rb +30 -0
  53. data/lib/pinnacle/types/subscriber_match_response.rb +13 -0
  54. data/lib/pinnacle/types/subscriber_match_response_matches.rb +41 -0
  55. data/lib/pinnacle/types/subscriber_match_result.rb +18 -0
  56. data/lib/pinnacle/types/webhook_event_enum.rb +1 -0
  57. data/lib/pinnacle/version.rb +1 -1
  58. data/lib/pinnacle/wrapper/messages/client.rb +4 -1
  59. data/lib/pinnacle/wrapper/voice/client.rb +125 -0
  60. data/lib/pinnacle/wrapper/voice/types.rb +38 -0
  61. data/lib/pinnacle/wrapper/voice/voice_socket.rb +354 -0
  62. data/lib/pinnacle.rb +49 -0
  63. data/reference.md +1903 -696
  64. metadata +75 -3
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ module NetworkRequestId
6
+ # NetworkRequestId is an alias for String
7
+
8
+ # @option str [String]
9
+ #
10
+ # @return [untyped]
11
+ def self.load(str)
12
+ ::JSON.parse(str)
13
+ end
14
+
15
+ # @option value [untyped]
16
+ #
17
+ # @return [String]
18
+ def self.dump(value)
19
+ ::JSON.generate(value)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ # Result from the original check, or null while the request is still pending or no result is available.
6
+ class NetworkRequestResult < Internal::Types::Model
7
+ extend Pinnacle::Internal::Types::Union
8
+
9
+ member -> { Pinnacle::Types::SimSwapResponse }
10
+
11
+ member -> { Pinnacle::Types::SubscriberMatchResponse }
12
+
13
+ member -> { Pinnacle::Types::SilentAuthCheckResponse }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ module NetworkRequestStatus
6
+ extend Pinnacle::Internal::Types::Enum
7
+
8
+ STARTED = "started"
9
+ CHALLENGE_ISSUED = "challenge-issued"
10
+ COMPLETED = "completed"
11
+ FAILED = "failed"
12
+ EXPIRED = "expired"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ class NetworkRequestSummary < Internal::Types::Model
6
+ field :request_id, -> { String }, optional: false, nullable: false, api_name: "requestId"
7
+
8
+ field :type, -> { Pinnacle::Types::NetworkRequestType }, optional: false, nullable: false
9
+
10
+ field :status, -> { Pinnacle::Types::NetworkRequestStatus }, optional: false, nullable: false
11
+
12
+ field :client_ref, -> { String }, optional: false, nullable: true, api_name: "clientRef"
13
+
14
+ field :created_at, -> { String }, optional: false, nullable: false, api_name: "createdAt"
15
+
16
+ field :updated_at, -> { String }, optional: false, nullable: false, api_name: "updatedAt"
17
+
18
+ field :completed_at, -> { String }, optional: false, nullable: true, api_name: "completedAt"
19
+
20
+ field :expires_at, -> { String }, optional: false, nullable: true, api_name: "expiresAt"
21
+
22
+ field :error_message, -> { String }, optional: false, nullable: true, api_name: "errorMessage"
23
+
24
+ field :result, -> { Pinnacle::Types::NetworkRequestResult }, optional: false, nullable: true
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ module NetworkRequestType
6
+ extend Pinnacle::Internal::Types::Enum
7
+
8
+ SILENT_AUTH = "silent-auth"
9
+ SIM_SWAP = "sim-swap"
10
+ SUBSCRIBER_MATCH = "subscriber-match"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ class RecordingDownload < Internal::Types::Model
6
+ field :url, -> { String }, optional: false, nullable: false
7
+
8
+ field :expires_at, -> { String }, optional: false, nullable: false
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ module RecordingState
6
+ extend Pinnacle::Internal::Types::Enum
7
+
8
+ PENDING = "PENDING"
9
+ READY = "READY"
10
+ FAILED = "FAILED"
11
+ DELETED = "DELETED"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ class SilentAuthCheckResponse < Internal::Types::Model
6
+ field :request_id, -> { String }, optional: false, nullable: false, api_name: "requestId"
7
+
8
+ field :status, -> { Pinnacle::Types::SilentAuthCheckResponseStatus }, optional: false, nullable: false
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ module SilentAuthCheckResponseStatus
6
+ extend Pinnacle::Internal::Types::Enum
7
+
8
+ COMPLETED = "completed"
9
+ FAILED = "failed"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ class SilentAuthResponse < Internal::Types::Model
6
+ extend Pinnacle::Internal::Types::Union
7
+
8
+ discriminant :format
9
+
10
+ member -> { Pinnacle::Types::HostedSilentAuthResponse }, key: "HOSTED"
11
+
12
+ member -> { Pinnacle::Types::JsonSilentAuthResponse }, key: "JSON_"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ class SimSwapResponse < Internal::Types::Model
6
+ field :request_id, -> { String }, optional: false, nullable: false, api_name: "requestId"
7
+
8
+ field :status, -> { Pinnacle::Types::NetworkInsightStatus }, optional: false, nullable: false
9
+
10
+ field :sim_swapped, -> { Internal::Types::Boolean }, optional: false, nullable: true, api_name: "simSwapped"
11
+
12
+ field :latest_sim_swap_at, -> { String }, optional: false, nullable: true, api_name: "latestSimSwapAt"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ # User-provided subscriber details to compare with the carrier record. Provide at least one non-empty field.
6
+ class SubscriberMatchAttributes < Internal::Types::Model
7
+ field :id_document, -> { String }, optional: true, nullable: false, api_name: "idDocument"
8
+
9
+ field :given_name, -> { String }, optional: true, nullable: false, api_name: "givenName"
10
+
11
+ field :family_name, -> { String }, optional: true, nullable: false, api_name: "familyName"
12
+
13
+ field :street_name, -> { String }, optional: true, nullable: false, api_name: "streetName"
14
+
15
+ field :street_number, -> { String }, optional: true, nullable: false, api_name: "streetNumber"
16
+
17
+ field :postal_code, -> { String }, optional: true, nullable: false, api_name: "postalCode"
18
+
19
+ field :locality, -> { String }, optional: true, nullable: false
20
+
21
+ field :region, -> { String }, optional: true, nullable: false
22
+
23
+ field :country, -> { String }, optional: true, nullable: false
24
+
25
+ field :street_number_suffix, -> { String }, optional: true, nullable: false, api_name: "streetNumberSuffix"
26
+
27
+ field :birthdate, -> { String }, optional: true, nullable: false
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ class SubscriberMatchResponse < Internal::Types::Model
6
+ field :request_id, -> { String }, optional: false, nullable: false, api_name: "requestId"
7
+
8
+ field :status, -> { Pinnacle::Types::NetworkInsightStatus }, optional: false, nullable: false
9
+
10
+ field :matches, -> { Pinnacle::Types::SubscriberMatchResponseMatches }, optional: false, nullable: false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ # Match strength for each evaluated subscriber attribute.
6
+ #
7
+ # - `exact`: Carrier record matches the submitted value exactly.
8
+ # - `high`: Strong match with minor formatting or normalization differences.
9
+ # - `partial`: Some parts match, but the value is not a strong match.
10
+ # - `low`: Weak match.
11
+ # - `none`: Carrier record does not match the submitted value.
12
+ # - `unavailable`: Carrier could not evaluate this attribute.
13
+ # - `included-with-address-match`: Attribute was evaluated as part of the overall address match.
14
+ # - `unknown`: Carrier returned a match value Pinnacle does not recognize yet.
15
+ class SubscriberMatchResponseMatches < Internal::Types::Model
16
+ field :id_document, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "idDocument"
17
+
18
+ field :given_name, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "givenName"
19
+
20
+ field :family_name, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "familyName"
21
+
22
+ field :address, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false
23
+
24
+ field :street_name, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "streetName"
25
+
26
+ field :street_number, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "streetNumber"
27
+
28
+ field :postal_code, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "postalCode"
29
+
30
+ field :locality, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false
31
+
32
+ field :region, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false
33
+
34
+ field :country, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false
35
+
36
+ field :street_number_suffix, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false, api_name: "streetNumberSuffix"
37
+
38
+ field :birthdate, -> { Pinnacle::Types::SubscriberMatchResult }, optional: true, nullable: false
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Types
5
+ module SubscriberMatchResult
6
+ extend Pinnacle::Internal::Types::Enum
7
+
8
+ EXACT = "exact"
9
+ HIGH = "high"
10
+ PARTIAL = "partial"
11
+ LOW = "low"
12
+ NONE = "none"
13
+ UNAVAILABLE = "unavailable"
14
+ INCLUDED_WITH_ADDRESS_MATCH = "included-with-address-match"
15
+ UNKNOWN = "unknown"
16
+ end
17
+ end
18
+ end
@@ -10,6 +10,7 @@ module Pinnacle
10
10
  USER_TYPING = "USER.TYPING"
11
11
  FORM_SUBMISSION = "FORM.SUBMISSION"
12
12
  CAMPAIGN_STATUS = "CAMPAIGN.STATUS"
13
+ CALL_STATUS = "CALL.STATUS"
13
14
  end
14
15
  end
15
16
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pinnacle
4
- VERSION = "2.0.19"
4
+ VERSION = "2.0.20.pre.rc.1"
5
5
  end
@@ -5,6 +5,7 @@ require_relative "../../types/message_event"
5
5
  require_relative "../../types/user_event"
6
6
  require_relative "../../types/form_submission_event"
7
7
  require_relative "../../types/campaign_status_event"
8
+ require_relative "../../types/call_status_event"
8
9
 
9
10
  module Pinnacle
10
11
  module Wrapper
@@ -23,7 +24,7 @@ module Pinnacle
23
24
  # @param request [Hash] Request with :headers and :body keys
24
25
  # @param secret [String, nil] Webhook secret (falls back to PINNACLE_SIGNING_SECRET env var)
25
26
  #
26
- # @return [Pinnacle::Types::MessageEvent, Pinnacle::Types::UserEvent, Pinnacle::Types::FormSubmissionEvent, Pinnacle::Types::CampaignStatusEvent]
27
+ # @return [Pinnacle::Types::MessageEvent, Pinnacle::Types::UserEvent, Pinnacle::Types::FormSubmissionEvent, Pinnacle::Types::CampaignStatusEvent, Pinnacle::Types::CallStatusEvent]
27
28
  # @raise [Pinnacle::Errors::UnauthorizedError] If webhook signature is invalid or missing
28
29
  # @raise [Pinnacle::Errors::ClientError] If request body cannot be parsed
29
30
  def process(request, secret: nil)
@@ -66,6 +67,8 @@ module Pinnacle
66
67
  Pinnacle::Types::FormSubmissionEvent.coerce(parsed)
67
68
  when "CAMPAIGN.STATUS"
68
69
  Pinnacle::Types::CampaignStatusEvent.coerce(parsed)
70
+ when "CALL.STATUS"
71
+ Pinnacle::Types::CallStatusEvent.coerce(parsed)
69
72
  else
70
73
  Pinnacle::Types::MessageEvent.coerce(parsed)
71
74
  end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../calls/client"
4
+ require_relative "voice_socket"
5
+
6
+ module Pinnacle
7
+ module Wrapper
8
+ module Voice
9
+ class Client
10
+ DEFAULT_RECONNECT = { enabled: true }.freeze
11
+
12
+ class DefaultSocket
13
+ attr_reader :ready_state
14
+
15
+ def initialize(url, protocols = nil)
16
+ @ready_state = 0
17
+ @listeners = Hash.new { |hash, key| hash[key] = [] }
18
+ headers = if protocols.nil?
19
+ {}
20
+ else
21
+ { "Sec-WebSocket-Protocol" => Array(protocols).join(", ") }
22
+ end
23
+ @socket = WebSocket::Client::Simple.connect(url, headers: headers)
24
+ @socket.on(:open) do |event|
25
+ @ready_state = 1
26
+ emit("open", event)
27
+ end
28
+ @socket.on(:message) { |message| emit("message", { data: message.data }) }
29
+ @socket.on(:error) { |error| emit("error", error) }
30
+ @socket.on(:close) do |event|
31
+ @ready_state = 3
32
+ emit("close", event)
33
+ end
34
+ end
35
+
36
+ def add_event_listener(event, &listener)
37
+ @listeners[event.to_s] << listener
38
+ end
39
+
40
+ def send(data)
41
+ @socket.send(data)
42
+ end
43
+
44
+ def close(*)
45
+ @socket.close
46
+ end
47
+
48
+ private
49
+
50
+ def emit(event, payload)
51
+ @listeners[event].each { |listener| listener.call(payload) }
52
+ end
53
+ end
54
+
55
+ def initialize(client:)
56
+ @calls = Pinnacle::Calls::Client.new(client: client)
57
+ end
58
+
59
+ def create_and_connect(
60
+ to:,
61
+ from:,
62
+ record: nil,
63
+ metadata: nil,
64
+ token: nil,
65
+ protocols: nil,
66
+ reconnect: nil,
67
+ socket: nil,
68
+ request_options: {}
69
+ )
70
+ call_params = { to: to, from: from }
71
+ call_params[:record] = record unless record.nil?
72
+ call_params[:metadata] = metadata unless metadata.nil?
73
+ call = @calls.create(**call_params, request_options: request_options)
74
+ connection = connect(
75
+ call_id: call.id,
76
+ token: token,
77
+ protocols: protocols,
78
+ reconnect: DEFAULT_RECONNECT.merge(reconnect || {}),
79
+ socket: socket
80
+ )
81
+ connection.call = call
82
+ connection.call_id = call.id
83
+ connection
84
+ end
85
+
86
+ def connect(call_id:, token: nil, protocols: nil, reconnect: nil, socket: nil)
87
+ socket_class = socket || default_socket
88
+ token_params = token || {}
89
+ stream_token = @calls.create_stream_token(**token_params, id: call_id)
90
+ create_socket = -> do
91
+ next_token = @calls.create_stream_token(**token_params, id: call_id)
92
+ new_socket(socket_class, next_token.stream_url, protocols)
93
+ end
94
+
95
+ VoiceSocket.new(
96
+ new_socket(socket_class, stream_token.stream_url, protocols),
97
+ create_socket: create_socket,
98
+ reconnect: DEFAULT_RECONNECT.merge(reconnect || {})
99
+ )
100
+ end
101
+
102
+ def connect_stream(stream_url, protocols: nil, reconnect: nil, socket: nil)
103
+ socket_class = socket || default_socket
104
+ create_socket = -> { new_socket(socket_class, stream_url, protocols) }
105
+ VoiceSocket.new(create_socket.call, create_socket: create_socket, reconnect: reconnect)
106
+ end
107
+
108
+ private
109
+
110
+ def default_socket
111
+ require "websocket-client-simple" unless defined?(::WebSocket::Client::Simple)
112
+ DefaultSocket
113
+ rescue LoadError => e
114
+ raise e, "The rcs gem could not load its websocket-client-simple dependency. Reinstall rcs or pass socket: to client.voice.connect."
115
+ end
116
+
117
+ def new_socket(socket_class, stream_url, protocols)
118
+ return socket_class.new(stream_url) if protocols.nil?
119
+
120
+ socket_class.new(stream_url, protocols)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pinnacle
4
+ module Wrapper
5
+ module Voice
6
+ module Types
7
+ VOICE_COMMAND_ACTIONS = [
8
+ CALL_ANSWER = "call.answer",
9
+ CALL_END = "call.end",
10
+ CALL_TRANSFER = "call.transfer",
11
+ RECORDING_START = "recording.start",
12
+ RECORDING_STOP = "recording.stop",
13
+ AUDIO_PLAY = "audio.play",
14
+ AUDIO_STOP = "audio.stop",
15
+ AUDIO_REDUCE_NOISE = "audio.reduce_noise",
16
+ INPUT_GET = "input.get",
17
+ INPUT_CANCEL = "input.cancel",
18
+ DTMF_SEND = "dtmf.send",
19
+ CALL_UPDATE_STATE = "call.update_state"
20
+ ].freeze
21
+
22
+ USER_BUSY = "user_busy"
23
+ CALL_REJECTED = "call_rejected"
24
+
25
+ NOISE_DEFAULT = "default"
26
+ NOISE_KRISP = "krisp"
27
+ NOISE_AICOUSTICS = "aicoustics"
28
+
29
+ DIRECTION_INBOUND = "inbound"
30
+ DIRECTION_OUTBOUND = "outbound"
31
+ DIRECTION_BOTH = "both"
32
+
33
+ TRACK_INBOUND = "inbound"
34
+ TRACK_OUTBOUND = "outbound"
35
+ end
36
+ end
37
+ end
38
+ end