pager_tree-integrations 1.1.2 → 1.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 346fc5f836fd08b5e13984f0ead3c57af0bfb853c6c7bbe06eab9b9821693d47
4
- data.tar.gz: '09642e8b0aadff79bedeeec4a6508e0df60ace5ee8d5d751b9b881675bd5829c'
3
+ metadata.gz: 1232e60d15e2dce895e6cc02e391cb1ec4f0230bcb3642c65f7d2eebaf499666
4
+ data.tar.gz: 2b1b7bd0787d7d001127b0391ce02a25bb258e74f86609b128e488e90c9efae4
5
5
  SHA512:
6
- metadata.gz: 9ed77d1beebab497c91eebc46b0611beabf99fe463498aa993f53ff497d543f604b8ec8115276992d76dd877c665d13e1804786c60b94a08bb16581fe9d74f80
7
- data.tar.gz: 3f586f4688d333343ab300a79836947c29698d82372932a59e7ae2b5253fd6709bc9da57ef21fcc7c1e66f891ca034504bfbd997ad0f00321e2bb6713521c6d0
6
+ metadata.gz: 1d1efc213cc97634b6530653d5f06f14f79f80cf7df72c8f7130e890d968bfe74282cd95142dfc1fa4fbddd70c8634a538354049093f1b1617f9e6cd7f840df1
7
+ data.tar.gz: b2c8fea7246e9c3e00671b9fde25d0214fe254a28902056b4393e3623ee416113eb984e1b8d9f8b511c2e0b6f747513c1b3ed6c66f09ac416524c986005cb5ba
@@ -7,9 +7,20 @@ module PagerTree::Integrations
7
7
 
8
8
  @integration.adapter_source_log = @integration.logs.create!(level: :info, format: :json, message: params.to_unsafe_h) if @integration.try(:log_incoming_requests?)
9
9
  @integration.adapter_controller = self
10
+ @integration.adapter_incoming_request_params = params
10
11
  @integration.adapter_response_music
11
12
  end
12
13
 
14
+ def dropped
15
+ set_integration
16
+
17
+ @integration.adapter_source_log = @integration.logs.create!(level: :info, format: :json, message: params.to_unsafe_h) if @integration.try(:log_incoming_requests?)
18
+ @integration.adapter_controller = self
19
+ @integration.adapter_alert = @integration.alerts.find_by(thirdparty_id: params[:CallSid])
20
+ @integration.adapter_incoming_request_params = params
21
+ @integration.adapter_response_dropped
22
+ end
23
+
13
24
  def queue_status
14
25
  ::PagerTree::Integrations.deferred_request_class.constantize.perform_later_from_request!(request)
15
26
 
@@ -0,0 +1,17 @@
1
+ module PagerTree::Integrations
2
+ class LiveCallRouting::Twilio::V3Mailer < ::ApplicationMailer
3
+ # Subject can be set in your I18n file at config/locales/en.yml
4
+ # with the following lookup:
5
+ #
6
+ # en.live_call_routing.twilio.v3_mailer.call_recording.subject
7
+ #
8
+ def call_recording
9
+ @recording_url = params[:recording_url]
10
+ @alert = params[:alert]
11
+ @email = params[:email]
12
+ @from = params[:from]
13
+
14
+ mail(to: @email, subject: I18n.t("pager_tree.integrations.live_call_routing.twilio.v3_mailer.call_recording.subject", tiny_id: @alert.tiny_id, from: @from))
15
+ end
16
+ end
17
+ end
@@ -63,7 +63,7 @@ module PagerTree::Integrations
63
63
  private
64
64
 
65
65
  def _alert
66
- @_alert ||= adapter_outgoing_event.item
66
+ @_alert ||= adapter_outgoing_event.alert
67
67
  end
68
68
 
69
69
  def _blocks
@@ -63,7 +63,7 @@ module PagerTree::Integrations
63
63
  private
64
64
 
65
65
  def _alert
66
- @_alert ||= adapter_outgoing_event.item
66
+ @_alert ||= adapter_outgoing_event.alert
67
67
  end
68
68
 
69
69
  def _blocks
@@ -63,7 +63,7 @@ module PagerTree::Integrations
63
63
  private
64
64
 
65
65
  def _alert
66
- @_alert ||= adapter_outgoing_event.item
66
+ @_alert ||= adapter_outgoing_event.alert
67
67
  end
68
68
 
69
69
  def _blocks
@@ -58,6 +58,10 @@ module PagerTree::Integrations
58
58
 
59
59
  def adapter_process_other
60
60
  end
61
+
62
+ def adapter_will_route_alert?
63
+ false
64
+ end
61
65
  # END basic incoming functions
62
66
 
63
67
  # START basic outgoing functions
@@ -38,20 +38,24 @@ module PagerTree::Integrations
38
38
  voice: "man"
39
39
  }
40
40
 
41
- TWILIO_LIVECALL_CONNECT_NOW = "https://app.pagertree.com/assets/sounds/you-are-now-being-connected.mp3"
42
- TWILIO_LIVECALL_MUSIC = "http://com.twilio.sounds.music.s3.amazonaws.com/oldDog_-_endless_goodbye_%28instr.%29.mp3"
43
- TWILIO_LIVECALL_PLEASE_WAIT = "https://app.pagertree.com/assets/sounds/please-wait.mp3"
44
-
45
41
  def option_connect_now_media_url
46
- option_connect_now_media&.url || TWILIO_LIVECALL_CONNECT_NOW
42
+ option_connect_now_media.present? ? option_connect_now_media.url : URI.join(Rails.application.routes.url_helpers.root_url, "audios/you-are-now-being-connected.mp3").to_s
47
43
  end
48
44
 
49
45
  def option_music_media_url
50
- option_music_media&.url || TWILIO_LIVECALL_MUSIC
46
+ option_music_media.present? ? option_music_media.url : "http://com.twilio.sounds.music.s3.amazonaws.com/oldDog_-_endless_goodbye_%28instr.%29.mp3"
51
47
  end
52
48
 
53
49
  def option_please_wait_media_url
54
- option_please_wait_media&.url || TWILIO_LIVECALL_PLEASE_WAIT
50
+ option_please_wait_media.present? ? option_please_wait_media.url : URI.join(Rails.application.routes.url_helpers.root_url, "audios/please-wait.mp3").to_s
51
+ end
52
+
53
+ def option_no_answer_media_url
54
+ option_no_answer_media.present? ? option_no_answer_media.url : URI.join(Rails.application.routes.url_helpers.root_url, "audios/no-answer.mp3").to_s
55
+ end
56
+
57
+ def option_no_answer_thank_you_media_url
58
+ option_no_answer_thank_you_media.present? ? option_no_answer_thank_you_media.url : URI.join(Rails.application.routes.url_helpers.root_url, "audios/thanks-for-message.mp3").to_s
55
59
  end
56
60
 
57
61
  def option_record_emails=(x)
@@ -90,10 +94,18 @@ module PagerTree::Integrations
90
94
  true
91
95
  end
92
96
 
97
+ def adapter_outgoing_interest?(event_name)
98
+ ["alert_acknowledged", "alert_dropped"].include?(event_name) && adapter_alert.source_id == id
99
+ end
100
+
93
101
  def adapter_incoming_can_defer?
94
102
  false
95
103
  end
96
104
 
105
+ def adapter_will_route_alert?
106
+ true
107
+ end
108
+
97
109
  def adapter_action
98
110
  :create
99
111
  end
@@ -128,13 +140,19 @@ module PagerTree::Integrations
128
140
  end
129
141
 
130
142
  if selected_team
131
- adapter_alert.logs.create!(message: "Caller selected team '#{selected_team.name}'. Playing please wait media.")
132
- _twiml.play(url: option_please_wait_media&.url || TWILIO_LIVECALL_PLEASE_WAIT)
143
+ adapter_alert.logs.create!(message: "Caller selected team '#{selected_team.name}'.") if _teams_size > 1 || option_force_input
144
+
145
+ adapter_alert.logs.create!(message: "Play please wait media to caller.")
146
+ _twiml.play(url: option_please_wait_media_url)
133
147
  friendly_name = adapter_alert.id
134
148
 
135
149
  # create the queue and save it off
136
150
  queue = _client.queues.create(friendly_name: friendly_name)
137
151
  adapter_alert.meta["live_call_queue_sid"] = queue.sid
152
+
153
+ adapter_alert.destination_teams = [selected_team]
154
+
155
+ # save the alert
138
156
  adapter_alert.save!
139
157
 
140
158
  _twiml.enqueue(
@@ -144,6 +162,11 @@ module PagerTree::Integrations
144
162
  wait_url: PagerTree::Integrations::Engine.routes.url_helpers.music_live_call_routing_twilio_v3_path(id, thirdparty_id: _thirdparty_id),
145
163
  wait_url_method: "GET"
146
164
  )
165
+ adapter_alert.logs.create!(message: "Enqueue caller in Twilio queue '#{friendly_name}'.")
166
+
167
+ # kick off the alert workflow
168
+ adapter_alert.route_later
169
+ adapter_alert.logs.create!(message: "Successfully enqueued alert team workflow.")
147
170
  else
148
171
  adapter_alert.meta["live_call_repeat_count"] ||= 0
149
172
  adapter_alert.meta["live_call_repeat_count"] += 1
@@ -159,6 +182,7 @@ module PagerTree::Integrations
159
182
  end
160
183
  else
161
184
  adapter_alert.logs.create!(message: "Caller input bad input (too many times). Hangup.")
185
+ adapter_alert.resolve!(self)
162
186
  _twiml.say(message: "Too much invalid input. Goodbye.", **SPEAK_OPTIONS)
163
187
  _twiml.hangup
164
188
  end
@@ -193,15 +217,11 @@ module PagerTree::Integrations
193
217
  adapter_controller&.render(xml: _twiml.to_xml)
194
218
  end
195
219
 
196
- def response_dropped
220
+ def adapter_response_dropped
197
221
  recording_url = adapter_incoming_request_params.dig("RecordingUrl")
198
222
 
199
223
  if recording_url
200
- if option_no_answer_thank_you_media.present?
201
- _twiml.play(url: option_no_answer_thank_you_media.url)
202
- else
203
- _twiml.say(message: "Thank you for your message. Goodbye.")
204
- end
224
+ _twiml.play(url: option_no_answer_thank_you_media_url)
205
225
  _twiml.hangup
206
226
 
207
227
  adapter_alert.additional_data.push(AdditionalDatum.new(format: "link", label: "Voicemail", value: recording_url).to_h)
@@ -209,18 +229,18 @@ module PagerTree::Integrations
209
229
 
210
230
  adapter_alert.logs.create!(message: "Caller left a <a href='#{recording_url}' target='_blank'>voicemail</a>.")
211
231
 
212
- adapter_record_emails.each do |email|
213
- TwilioLiveCallRouting::V3Mailer.with(email: email, alert: alert).call_recording.deliver_later
232
+ option_record_emails.each do |email|
233
+ LiveCallRouting::Twilio::V3Mailer.with(email: email, alert: adapter_alert, from: adapter_incoming_request_params.dig("From"), recording_url: recording_url).call_recording.deliver_later
214
234
  end
215
- elsif record
235
+ elsif option_record
216
236
  _twiml.play(url: option_no_answer_media_url)
217
237
  _twiml.record(max_length: 60)
218
238
  else
219
- _twiml.say(message: "No one is available to answer this call. Goodbye.")
239
+ _twiml.say(message: "No one is available to answer this call. Goodbye.", **SPEAK_OPTIONS)
220
240
  _twiml.hangup
221
241
  end
222
242
 
223
- controller.render(xml: _twiml.to_xml)
243
+ adapter_controller.render(xml: _twiml.to_xml)
224
244
  end
225
245
 
226
246
  def adapter_process_queue_status_deferred
@@ -229,18 +249,20 @@ module PagerTree::Integrations
229
249
 
230
250
  if queue_result == "hangup"
231
251
  self.adapter_alert = alerts.find_by(thirdparty_id: _thirdparty_id)
252
+ adapter_alert.logs.create!(message: "Caller hungup while waiting in queue.")
253
+ adapter_alert.resolve!(self)
232
254
  queue_destroy
233
255
  end
234
256
 
235
257
  adapter_source_log&.save!
236
258
  end
237
259
 
238
- def perform_outgoing(**params)
239
- event = params[:event]
240
- if event == "alert.acknowledged"
241
- on_acknowledge
242
- elsif event == "alert.dropped"
243
- on_drop
260
+ def adapter_process_outgoing
261
+ event = adapter_outgoing_event.event_name.to_s
262
+ if event == "alert_acknowledged"
263
+ _on_acknowledge
264
+ elsif event == "alert_dropped"
265
+ _on_drop
244
266
  end
245
267
  end
246
268
 
@@ -269,7 +291,7 @@ module PagerTree::Integrations
269
291
  end
270
292
 
271
293
  def _call
272
- @_call ||= _client.calls(call_sid).fetch
294
+ @_call ||= _client.calls(adapter_alert.thirdparty_id).fetch
273
295
  end
274
296
 
275
297
  def _twiml
@@ -299,23 +321,44 @@ module PagerTree::Integrations
299
321
  nil
300
322
  end
301
323
 
302
- def on_acknowledge
324
+ def _on_acknowledge
303
325
  # log that we are going to transfer
304
- adapter_alert.logs.create!(message: "Attempting to transfer the call...")
326
+ adapter_alert.logs.create!(message: "The alert was acknowledged. Attempting to transfer the call...")
305
327
 
306
328
  # try to transfer the caller
307
- number = "+19402733696"
308
- _twiml.play(url: option_connect_now_media_url)
309
- _twiml.pause(length: 1)
310
- _twiml.dial(number: number, caller_id: _call.to, answer_on_bridge: true)
311
- _call.update(twiml: _twiml.to_xml)
312
-
313
- # log if we successfully transfered or failed
314
- adapter_alert.logs.create!(message: "Tranferring the call succeeded.")
329
+ account_user = adapter_outgoing_event.account_user
330
+ number = account_user.user.phone&.phone
331
+
332
+ adapter_alert.logs.create!(message: "Attempting to transfer the call to #{account_user.user.name} at #{number}...")
333
+
334
+ if number.present?
335
+ _twiml.play(url: option_connect_now_media_url)
336
+ _twiml.pause(length: 1)
337
+ _twiml.dial(number: number, caller_id: _call.to, answer_on_bridge: true)
338
+ _call.update(twiml: _twiml.to_xml)
339
+ # log if we successfully transfered or failed
340
+ adapter_alert.logs.create!(message: "Tranferring the call succeeded.")
341
+ else
342
+ _twiml.say(message: "Someone has acknowledged this call, but they do not have a phone number on file. Goodbye.")
343
+ _twiml.hangup
344
+ _call.update(twiml: _twiml.to_xml)
345
+ adapter_alert.logs.create!(message: "Tranferring the call failed. #{account_user.user.name} has no phone number on file.")
346
+ end
347
+ rescue ::Twilio::REST::RestError => e
348
+ # 21220 - Unable to update record. Call is not in-progress. Cannot redirect.
349
+ if e.code != 21220
350
+ adapter_alert.logs.create!(message: "Tranferring the call failed. #{e.message}")
351
+ end
315
352
  end
316
353
 
317
- def on_drop
318
- _call.update(url: PagerTree::Integrations::Engine.routes.url_helpers.dropped_twilio_live_call_routing_v3_url(id, thirdparty_id: thirdparty_id))
354
+ def _on_drop
355
+ # log that we are going to transer
356
+ adapter_alert.logs.create!(message: "The alert was dropped. Attempting to transfer the call...")
357
+ _call.update(url: PagerTree::Integrations::Engine.routes.url_helpers.dropped_live_call_routing_twilio_v3_url(id, thirdparty_id: adapter_alert.thirdparty_id))
358
+ music_live_call_routing_twilio_v3_path
359
+ adapter_alert.logs.create!(message: "Tranferring the call succeeded.")
360
+ rescue ::Twilio::REST::RestError => e
361
+ adapter_alert.logs.create!(message: "Tranferring the call failed. #{e.message}")
319
362
  end
320
363
 
321
364
  def queue_destroy
@@ -8,6 +8,10 @@ module PagerTree::Integrations
8
8
  attr_accessor :item
9
9
  attr_accessor :changes
10
10
  attr_accessor :outgoing_rules_data
11
+ attr_accessor :alert
12
+ attr_accessor :handoff
13
+ attr_accessor :team
14
+ attr_accessor :account_user
11
15
 
12
16
  define_model_callbacks :initialize
13
17
 
@@ -22,6 +26,11 @@ module PagerTree::Integrations
22
26
  self.item ||= nil
23
27
  self.changes ||= nil
24
28
  self.outgoing_rules_data ||= {}
29
+
30
+ self.alert ||= nil
31
+ self.handoff ||= nil
32
+ self.team ||= nil
33
+ self.account_user ||= nil
25
34
  end
26
35
  end
27
36
  end
@@ -71,7 +71,7 @@ module PagerTree::Integrations
71
71
  if self.option_template.present?
72
72
  begin
73
73
  body = JSON.parse(handlebars(self.option_template, {
74
- alert: adapter_outgoing_event.item.try(:v3_format) || adapter_outgoing_event.item,
74
+ alert: adapter_outgoing_event.alert.try(:v3_format) || adapter_outgoing_event.alert,
75
75
  event: {
76
76
  type: event_type
77
77
  }
@@ -84,7 +84,7 @@ module PagerTree::Integrations
84
84
  end
85
85
 
86
86
  body ||= {
87
- data: adapter_outgoing_event.item.try(:v3_format) || adapter_outgoing_event.item,
87
+ data: adapter_outgoing_event.alert.try(:v3_format) || adapter_outgoing_event.alert,
88
88
  type: event_type
89
89
  }
90
90
 
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+ <style>
6
+ /* Email styles need to be inline */
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <%= yield %>
12
+ </body>
13
+ </html>
@@ -0,0 +1 @@
1
+ <%= t(".body", tiny_id: @alert.tiny_id, from: @from) %>: <a href="<%=@recording_url%>"><%= @recording_url %></a>
@@ -0,0 +1 @@
1
+ <%= t(".body", tiny_id: @alert.tiny_id, from: @from) %>: <%= @recording_url %>
@@ -59,6 +59,10 @@ en:
59
59
  option_force_input_hint_html: "Force the caller to select a team (even if the integration only has one team)"
60
60
  option_record_hint_html: "Record a voicemail when no one acknowledges the call"
61
61
  option_record_emails_list_hint_html: "List of email addresses to notify when a voicemail has been recorded"
62
+ v3_mailer:
63
+ call_recording:
64
+ subject: "🎧 Alert #%{tiny_id} - New voicemail from %{from}"
65
+ body: "Alert #%{tiny_id} - New voicemail from %{from}"
62
66
  mattermost:
63
67
  outgoing_webhook:
64
68
  v3:
@@ -79,10 +83,10 @@ en:
79
83
  v3:
80
84
  form_options:
81
85
  option_token_hint_html: "The PagerTree-Token header can be used to authenticate requests (optional)"
82
- option_capture_additional_data_hint_html: "Capture additional data from the webhook (optional)"
86
+ option_capture_additional_data_hint_html: "Capture additional data from the webhook (optional)"
83
87
  # SCAFFOLD_INTEGRATION
84
88
 
85
-
89
+
86
90
  activerecord:
87
91
  attributes:
88
92
  "pager_tree/integrations/integration":
data/config/routes.rb CHANGED
@@ -5,6 +5,7 @@ PagerTree::Integrations::Engine.routes.draw do
5
5
  member do
6
6
  get :music
7
7
  post :queue_status
8
+ post :dropped
8
9
  end
9
10
  end
10
11
  end
@@ -1,5 +1,5 @@
1
1
  module PagerTree
2
2
  module Integrations
3
- VERSION = "1.1.2"
3
+ VERSION = "1.1.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pager_tree-integrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Austin Miller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-21 00:00:00.000000000 Z
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -85,6 +85,7 @@ files:
85
85
  - app/jobs/pager_tree/integrations/application_job.rb
86
86
  - app/jobs/pager_tree/integrations/outgoing_webhook_job.rb
87
87
  - app/mailers/pager_tree/integrations/application_mailer.rb
88
+ - app/mailers/pager_tree/integrations/live_call_routing/twilio/v3_mailer.rb
88
89
  - app/models/pager_tree/integrations/additional_datum.rb
89
90
  - app/models/pager_tree/integrations/alert.rb
90
91
  - app/models/pager_tree/integrations/apex_ping/v3.rb
@@ -137,6 +138,8 @@ files:
137
138
  - app/models/pager_tree/integrations/webhook/v3.rb
138
139
  - app/models/pager_tree/integrations/zendesk/v3.rb
139
140
  - app/views/layouts/pager_tree/integrations/application.html.erb
141
+ - app/views/layouts/pager_tree/integrations/live_call_routing/twilio/mailer.html.erb
142
+ - app/views/layouts/pager_tree/integrations/live_call_routing/twilio/mailer.text.erb
140
143
  - app/views/pager_tree/integrations/apex_ping/v3/_form_options.html.erb
141
144
  - app/views/pager_tree/integrations/apex_ping/v3/_show_options.html.erb
142
145
  - app/views/pager_tree/integrations/app_dynamics/v3/_form_options.html.erb
@@ -187,6 +190,8 @@ files:
187
190
  - app/views/pager_tree/integrations/kapacitor/v3/_show_options.html.erb
188
191
  - app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb
189
192
  - app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb
193
+ - app/views/pager_tree/integrations/live_call_routing/twilio/v3_mailer/call_recording.html.erb
194
+ - app/views/pager_tree/integrations/live_call_routing/twilio/v3_mailer/call_recording.text.erb
190
195
  - app/views/pager_tree/integrations/logic_monitor/v3/_form_options.html.erb
191
196
  - app/views/pager_tree/integrations/logic_monitor/v3/_show_options.html.erb
192
197
  - app/views/pager_tree/integrations/mattermost/outgoing_webhook/v3/_form_options.html.erb