pager_tree-integrations 1.1.6 → 1.1.7
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 +4 -4
- data/app/controllers/pager_tree/integrations/live_call_routing/twilio/v3_controller.rb +20 -0
- data/app/jobs/pager_tree/integrations/live_call_routing/twilio/v3/max_wait_time_job.rb +13 -0
- data/app/models/pager_tree/integrations/additional_datum.rb +2 -2
- data/app/models/pager_tree/integrations/alert.rb +2 -2
- data/app/models/pager_tree/integrations/aws_cloudwatch/v3.rb +15 -5
- data/app/models/pager_tree/integrations/boolean_store_accessor.rb +2 -2
- data/app/models/pager_tree/integrations/channel/hangouts/v3.rb +23 -2
- data/app/models/pager_tree/integrations/channel/mattermost/v3.rb +4 -0
- data/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb +74 -29
- data/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb +261 -0
- data/app/models/pager_tree/integrations/channel/slack/v3.rb +30 -3
- data/app/models/pager_tree/integrations/cloudflare/v3.rb +75 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3.rb +206 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.json +12 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.yaml +30 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_definition.json +9 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_example.yaml +27 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.json +25 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.yaml +33 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.json +40 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.yaml +32 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.json +30 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.yaml +23 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.json +12 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.yaml +48 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.json +21 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.yaml +43 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.json +31 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.yaml +24 -0
- data/app/models/pager_tree/integrations/datadog/v3.rb +10 -3
- data/app/models/pager_tree/integrations/dynatrace/v3.rb +67 -0
- data/app/models/pager_tree/integrations/echoes_hq/v3.rb +138 -0
- data/app/models/pager_tree/integrations/elast_alert/v3.rb +24 -0
- data/app/models/pager_tree/integrations/email/v3.rb +272 -22
- data/app/models/pager_tree/integrations/email/v3_examples/example.yml +24 -0
- data/app/models/pager_tree/integrations/form/v3.rb +15 -3
- data/app/models/pager_tree/integrations/freshdesk/v3.rb +7 -5
- data/app/models/pager_tree/integrations/freshservice/v3.rb +7 -5
- data/app/models/pager_tree/integrations/grafana/v3.rb +2 -2
- data/app/models/pager_tree/integrations/hetrix_tools/v3.rb +160 -0
- data/app/models/pager_tree/integrations/honeybadger/v3.rb +1 -1
- data/app/models/pager_tree/integrations/hydrozen/v3.rb +6 -0
- data/app/models/pager_tree/integrations/integration.rb +52 -9
- data/app/models/pager_tree/integrations/jira_server/v3.rb +12 -2
- data/app/models/pager_tree/integrations/kapacitor/v3.rb +1 -1
- data/app/models/pager_tree/integrations/live_call_routing/twilio/v3.rb +257 -22
- data/app/models/pager_tree/integrations/logic_monitor/v3.rb +193 -3
- data/app/models/pager_tree/integrations/mattermost/outgoing_webhook/v3.rb +1 -1
- data/app/models/pager_tree/integrations/meta/workplace/v3.rb +230 -0
- data/app/models/pager_tree/integrations/new_relic/v3.rb +9 -5
- data/app/models/pager_tree/integrations/outgoing_event.rb +8 -0
- data/app/models/pager_tree/integrations/outgoing_webhook/v3.rb +108 -13
- data/app/models/pager_tree/integrations/outgoing_webhook_delivery/hook_relay.rb +43 -33
- data/app/models/pager_tree/integrations/outgoing_webhook_delivery.rb +6 -5
- data/app/models/pager_tree/integrations/prtg/v3.rb +2 -1
- data/app/models/pager_tree/integrations/pulsetic/v3.rb +70 -0
- data/app/models/pager_tree/integrations/scom/pagertree.ps1 +153 -0
- data/app/models/pager_tree/integrations/scom/v3.rb +58 -0
- data/app/models/pager_tree/integrations/sentry/v3.rb +477 -0
- data/app/models/pager_tree/integrations/server_guard24/v3.rb +1 -1
- data/app/models/pager_tree/integrations/sixty_six_uptime/v3.rb +118 -0
- data/app/models/pager_tree/integrations/slack/webhook/v3.rb +1 -1
- data/app/models/pager_tree/integrations/solar_winds/v3.rb +66 -2
- data/app/models/pager_tree/integrations/status_gator/v3.rb +69 -0
- data/app/models/pager_tree/integrations/uptime_kuma/v3.rb +76 -0
- data/app/models/pager_tree/integrations/uptime_robot/v3.rb +6 -0
- data/app/models/pager_tree/integrations/webhook/v3.rb +25 -7
- data/app/models/pager_tree/integrations/zabbix/v3.rb +95 -0
- data/app/models/pager_tree/integrations/zendesk/v3.rb +2 -0
- data/app/views/pager_tree/integrations/channel/hangouts/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/channel/hangouts/v3/_show_options.html.erb +10 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb +14 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb +41 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb +54 -0
- data/app/views/pager_tree/integrations/channel/slack/v3/_form_options.html.erb +6 -3
- data/app/views/pager_tree/integrations/channel/slack/v3/_show_options.html.erb +1 -1
- data/app/views/pager_tree/integrations/cloudflare/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/cloudflare/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/custom_webhook/v3/_form_options.html.erb +8 -0
- data/app/views/pager_tree/integrations/custom_webhook/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/datadog/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/datadog/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/dynatrace/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/dynatrace/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/echoes_hq/v3/_form_options.html.erb +10 -0
- data/app/views/pager_tree/integrations/echoes_hq/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/email/v3/_form_options.html.erb +41 -11
- data/app/views/pager_tree/integrations/email/v3/_show_options.html.erb +18 -0
- data/app/views/pager_tree/integrations/form/v3/_form_options.html.erb +1 -5
- data/app/views/pager_tree/integrations/hetrix_tools/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/hetrix_tools/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/hydrozen/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/hydrozen/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb +44 -31
- data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb +93 -8
- data/app/views/pager_tree/integrations/logic_monitor/v3/_form_options.html.erb +31 -0
- data/app/views/pager_tree/integrations/logic_monitor/v3/_show_options.html.erb +60 -0
- data/app/views/pager_tree/integrations/meta/workplace/v3/_form_options.html.erb +44 -0
- data/app/views/pager_tree/integrations/meta/workplace/v3/_show_options.html.erb +68 -0
- data/app/views/pager_tree/integrations/outgoing_webhook/v3/_form_options.html.erb +17 -3
- data/app/views/pager_tree/integrations/outgoing_webhook/v3/_show_options.html.erb +20 -0
- data/app/views/pager_tree/integrations/pulsetic/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/pulsetic/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/scom/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/scom/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/sentry/v3/_form_options.html.erb +9 -0
- data/app/views/pager_tree/integrations/sentry/v3/_show_options.html.erb +15 -0
- data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/solar_winds/v3/_form_options.html.erb +40 -0
- data/app/views/pager_tree/integrations/solar_winds/v3/_show_options.html.erb +66 -0
- data/app/views/pager_tree/integrations/status_gator/v3/_form_options.html.erb +13 -0
- data/app/views/pager_tree/integrations/status_gator/v3/_show_options.html.erb +24 -0
- data/app/views/pager_tree/integrations/uptime_kuma/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/uptime_kuma/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/webhook/v3/_form_options.html.erb +8 -0
- data/app/views/pager_tree/integrations/webhook/v3/_show_options.html.erb +15 -0
- data/app/views/pager_tree/integrations/zabbix/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/zabbix/v3/_show_options.html.erb +12 -0
- data/config/locales/en.yml +158 -10
- data/config/routes.rb +1 -0
- data/lib/pager_tree/integrations/format_converters/yaml_json_converter.rb +67 -0
- data/lib/pager_tree/integrations/version.rb +1 -1
- data/lib/pager_tree/integrations.rb +11 -3
- metadata +84 -8
|
@@ -2,7 +2,7 @@ module PagerTree::Integrations
|
|
|
2
2
|
class Integration < PagerTree::Integrations.integration_parent_class.constantize
|
|
3
3
|
extend PagerTree::Integrations::BooleanStoreAccessor
|
|
4
4
|
|
|
5
|
-
serialize :options, JSON
|
|
5
|
+
serialize :options, coder: JSON
|
|
6
6
|
encrypts :options
|
|
7
7
|
|
|
8
8
|
GENERIC_OPTIONS = [
|
|
@@ -29,6 +29,9 @@ module PagerTree::Integrations
|
|
|
29
29
|
# the outgoing event
|
|
30
30
|
attribute :adapter_outgoing_event
|
|
31
31
|
|
|
32
|
+
def converts_to
|
|
33
|
+
end
|
|
34
|
+
|
|
32
35
|
# START basic incoming functions
|
|
33
36
|
def adapter_supports_incoming?
|
|
34
37
|
false
|
|
@@ -91,6 +94,14 @@ module PagerTree::Integrations
|
|
|
91
94
|
false
|
|
92
95
|
end
|
|
93
96
|
|
|
97
|
+
def adapter_supports_auto_aggregate?
|
|
98
|
+
true
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def adapter_supports_auto_resolve?
|
|
102
|
+
true
|
|
103
|
+
end
|
|
104
|
+
|
|
94
105
|
# START basic show functions
|
|
95
106
|
def adapter_show_alerts?
|
|
96
107
|
adapter_supports_incoming?
|
|
@@ -106,35 +117,67 @@ module PagerTree::Integrations
|
|
|
106
117
|
# END basic show functions
|
|
107
118
|
|
|
108
119
|
def adapter_response_rate_limit
|
|
109
|
-
adapter_controller&.head(
|
|
120
|
+
adapter_controller&.head(adapter_response_rate_limit_code)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def adapter_response_rate_limit_code
|
|
124
|
+
:too_many_requests
|
|
110
125
|
end
|
|
111
126
|
|
|
112
127
|
def adapter_response_disabled
|
|
113
|
-
adapter_controller&.head(
|
|
128
|
+
adapter_controller&.head(adapter_response_disabled_code)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def adapter_response_disabled_code
|
|
132
|
+
:method_not_allowed
|
|
114
133
|
end
|
|
115
134
|
|
|
116
135
|
def adapter_response_inactive_subscription
|
|
117
|
-
adapter_controller&.head(
|
|
136
|
+
adapter_controller&.head(adapter_response_inactive_subscription_code)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def adapter_response_inactive_subscription_code
|
|
140
|
+
:payment_required
|
|
118
141
|
end
|
|
119
142
|
|
|
120
143
|
def adapter_response_upgrade
|
|
121
|
-
adapter_controller&.head(
|
|
144
|
+
adapter_controller&.head(adapter_response_upgrade_code)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def adapter_response_upgrade_code
|
|
148
|
+
:payment_required
|
|
122
149
|
end
|
|
123
150
|
|
|
124
151
|
def adapter_response_maintenance_mode
|
|
125
|
-
adapter_controller&.head(
|
|
152
|
+
adapter_controller&.head(adapter_response_maintenance_mode_code)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def adapter_response_maintenance_mode_code
|
|
156
|
+
:ok
|
|
126
157
|
end
|
|
127
158
|
|
|
128
159
|
def adapter_response_blocked
|
|
129
|
-
adapter_controller&.head(
|
|
160
|
+
adapter_controller&.head(adapter_response_blocked_code)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def adapter_response_blocked_code
|
|
164
|
+
:forbidden
|
|
130
165
|
end
|
|
131
166
|
|
|
132
167
|
def adapter_response_deferred
|
|
133
|
-
adapter_controller&.head(
|
|
168
|
+
adapter_controller&.head(adapter_response_deferred_code)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def adapter_response_deferred_code
|
|
172
|
+
:ok
|
|
134
173
|
end
|
|
135
174
|
|
|
136
175
|
def adapter_response_incoming
|
|
137
|
-
adapter_controller&.head(
|
|
176
|
+
adapter_controller&.head(adapter_response_incoming_code)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def adapter_response_incoming_code
|
|
180
|
+
:ok
|
|
138
181
|
end
|
|
139
182
|
|
|
140
183
|
def cast_types
|
|
@@ -29,7 +29,7 @@ module PagerTree::Integrations
|
|
|
29
29
|
|
|
30
30
|
def adapter_action
|
|
31
31
|
event = adapter_incoming_request_params.dig("webhookEvent")
|
|
32
|
-
event == "jira:issue_created" || (
|
|
32
|
+
(event == "jira:issue_created" || (option_issue_updated == true && event == "jira:issue_updated")) ? :create : :other
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def adapter_process_create
|
|
@@ -53,8 +53,18 @@ module PagerTree::Integrations
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def _additional_datums
|
|
56
|
+
# links look like this: "https://jira.atlassian.com/rest/api/2/issue/99291"
|
|
57
|
+
# we want them to look like thish https://jira.atlassian.com/browse/CS-6157
|
|
58
|
+
jira_id = adapter_incoming_request_params.dig("issue", "id")
|
|
59
|
+
jira_link = adapter_incoming_request_params.dig("issue", "self")
|
|
60
|
+
jira_key = adapter_incoming_request_params.dig("issue", "key")
|
|
61
|
+
|
|
62
|
+
if jira_link.present? && jira_key.present? && jira_id.present?
|
|
63
|
+
jira_link = jira_link.gsub("/rest/api/2/issue/#{jira_id}", "/browse/#{jira_key}")
|
|
64
|
+
end
|
|
65
|
+
|
|
56
66
|
[
|
|
57
|
-
AdditionalDatum.new(format: "link", label: "Issue URL", value:
|
|
67
|
+
AdditionalDatum.new(format: "link", label: "Issue URL", value: jira_link)
|
|
58
68
|
]
|
|
59
69
|
end
|
|
60
70
|
end
|
|
@@ -4,33 +4,50 @@ module PagerTree::Integrations
|
|
|
4
4
|
{key: :account_sid, type: :string, default: nil},
|
|
5
5
|
{key: :api_key, type: :string, default: nil},
|
|
6
6
|
{key: :api_secret, type: :string, default: nil},
|
|
7
|
+
{key: :api_region, type: :string, default: "ashburn.us1"},
|
|
7
8
|
{key: :force_input, type: :boolean, default: false},
|
|
8
9
|
{key: :record, type: :boolean, default: false},
|
|
9
|
-
{key: :
|
|
10
|
+
{key: :send_straight_to_voicemail, type: :boolean, default: false},
|
|
11
|
+
{key: :record_email, type: :string, default: ""},
|
|
12
|
+
{key: :banned_phone, type: :string, default: ""},
|
|
13
|
+
{key: :dial_pause, type: :integer},
|
|
14
|
+
{key: :max_wait_time, type: :integer, default: nil},
|
|
15
|
+
{key: :skip_resolve_on_hangup, type: :boolean, default: false}
|
|
10
16
|
]
|
|
11
17
|
store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
|
|
12
18
|
|
|
19
|
+
API_REGIONS = ["ashburn.us1", "dublin.ie1", "sydney.au1"]
|
|
20
|
+
|
|
13
21
|
has_one_attached :option_connect_now_media
|
|
14
22
|
has_one_attached :option_music_media
|
|
15
23
|
has_one_attached :option_no_answer_media
|
|
16
24
|
has_one_attached :option_no_answer_thank_you_media
|
|
25
|
+
has_one_attached :option_no_answer_no_record_media
|
|
17
26
|
has_one_attached :option_please_wait_media
|
|
18
27
|
has_one_attached :option_welcome_media
|
|
19
28
|
|
|
20
29
|
validates :option_account_sid, presence: true
|
|
21
30
|
validates :option_api_key, presence: true
|
|
22
31
|
validates :option_api_secret, presence: true
|
|
32
|
+
validates :option_api_region, inclusion: {in: API_REGIONS}
|
|
23
33
|
validates :option_force_input, inclusion: {in: [true, false]}
|
|
24
34
|
validates :option_record, inclusion: {in: [true, false]}
|
|
35
|
+
validates :option_send_straight_to_voicemail, inclusion: {in: [true, false]}
|
|
36
|
+
validates :option_skip_resolve_on_hangup, inclusion: {in: [true, false]}
|
|
37
|
+
validates :option_max_wait_time, numericality: {greater_than_or_equal_to: 30, less_than_or_equal_to: 3600}, allow_nil: true
|
|
25
38
|
validate :validate_record_emails
|
|
26
39
|
|
|
27
40
|
after_initialize do
|
|
28
41
|
self.option_account_sid ||= nil
|
|
29
42
|
self.option_api_key ||= nil
|
|
30
43
|
self.option_api_secret ||= nil
|
|
44
|
+
self.option_api_region ||= "ashburn.us1"
|
|
31
45
|
self.option_force_input ||= false
|
|
32
46
|
self.option_record ||= false
|
|
47
|
+
self.option_send_straight_to_voicemail ||= false
|
|
33
48
|
self.option_record_email ||= ""
|
|
49
|
+
self.option_banned_phone ||= ""
|
|
50
|
+
self.option_skip_resolve_on_hangup ||= false
|
|
34
51
|
end
|
|
35
52
|
|
|
36
53
|
SPEAK_OPTIONS = {
|
|
@@ -58,12 +75,24 @@ module PagerTree::Integrations
|
|
|
58
75
|
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
|
|
59
76
|
end
|
|
60
77
|
|
|
78
|
+
def option_no_answer_no_record_media_url
|
|
79
|
+
option_no_answer_no_record_media.present? ? option_no_answer_no_record_media.url : nil
|
|
80
|
+
end
|
|
81
|
+
|
|
61
82
|
def option_record_emails=(x)
|
|
62
83
|
self.option_record_email = Array(x).join(",")
|
|
63
84
|
end
|
|
64
85
|
|
|
65
86
|
def option_record_emails
|
|
66
|
-
|
|
87
|
+
option_record_email.split(",")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def option_banned_phones=(x)
|
|
91
|
+
self.option_banned_phone = Array(x).join(",")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def option_banned_phones
|
|
95
|
+
option_banned_phone.split(",")
|
|
67
96
|
end
|
|
68
97
|
|
|
69
98
|
def option_record_emails_list=(x)
|
|
@@ -82,6 +111,22 @@ module PagerTree::Integrations
|
|
|
82
111
|
option_record_emails
|
|
83
112
|
end
|
|
84
113
|
|
|
114
|
+
def option_banned_phones_list=(x)
|
|
115
|
+
# what comes in as json, via tagify
|
|
116
|
+
uniq_array = []
|
|
117
|
+
begin
|
|
118
|
+
uniq_array = JSON.parse(x).map { |y| y["value"] }.uniq
|
|
119
|
+
rescue JSON::ParserError => exception
|
|
120
|
+
Rails.logger.debug(exception)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
self.option_banned_phones = uniq_array
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def option_banned_phones_list
|
|
127
|
+
option_banned_phones
|
|
128
|
+
end
|
|
129
|
+
|
|
85
130
|
def validate_record_emails
|
|
86
131
|
errors.add(:record_emails, "must be a valid email") if option_record_emails.any? { |x| !(x.match(URI::MailTo::EMAIL_REGEXP) || ["team", "team-admin", "on-call"].include?(x)) }
|
|
87
132
|
end
|
|
@@ -94,8 +139,12 @@ module PagerTree::Integrations
|
|
|
94
139
|
true
|
|
95
140
|
end
|
|
96
141
|
|
|
142
|
+
def adapter_supports_auto_aggregate?
|
|
143
|
+
false
|
|
144
|
+
end
|
|
145
|
+
|
|
97
146
|
def adapter_outgoing_interest?(event_name)
|
|
98
|
-
["alert_acknowledged", "alert_dropped"].include?(event_name)
|
|
147
|
+
["alert_acknowledged", "alert_dropped"].include?(event_name)
|
|
99
148
|
end
|
|
100
149
|
|
|
101
150
|
def adapter_incoming_can_defer?
|
|
@@ -106,8 +155,20 @@ module PagerTree::Integrations
|
|
|
106
155
|
true
|
|
107
156
|
end
|
|
108
157
|
|
|
158
|
+
def is_banned?
|
|
159
|
+
from_number = adapter_incoming_request_params.dig("From")
|
|
160
|
+
return false unless from_number.present?
|
|
161
|
+
option_banned_phones.any? { |x| from_number.include?(x) }
|
|
162
|
+
rescue
|
|
163
|
+
false
|
|
164
|
+
end
|
|
165
|
+
|
|
109
166
|
def adapter_action
|
|
110
|
-
|
|
167
|
+
if is_banned?
|
|
168
|
+
:other
|
|
169
|
+
else
|
|
170
|
+
:create
|
|
171
|
+
end
|
|
111
172
|
end
|
|
112
173
|
|
|
113
174
|
def adapter_thirdparty_id
|
|
@@ -126,12 +187,93 @@ module PagerTree::Integrations
|
|
|
126
187
|
end
|
|
127
188
|
|
|
128
189
|
def adapter_response_incoming
|
|
190
|
+
if is_banned?
|
|
191
|
+
_twiml.reject
|
|
192
|
+
|
|
193
|
+
adapter_source_log&.sublog("Caller #{adapter_incoming_request_params.dig("From")} on blocked list. Rejected call.")
|
|
194
|
+
adapter_source_log&.save
|
|
195
|
+
|
|
196
|
+
return adapter_controller&.render(xml: _twiml.to_xml)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
if adapter_alert.meta["live_call_status_callback_set"] != true
|
|
200
|
+
begin
|
|
201
|
+
# give us status updates on the call, so we can clean up if they hang up before leaving a message
|
|
202
|
+
_call.update(
|
|
203
|
+
status_callback: PagerTree::Integrations::Engine.routes.url_helpers.call_status_live_call_routing_twilio_v3_url(id, thirdparty_id: _thirdparty_id),
|
|
204
|
+
status_callback_method: "POST",
|
|
205
|
+
url: adapter_controller&.url_for || endpoint
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
adapter_alert.meta["live_call_status_callback_set"] = true
|
|
209
|
+
adapter_alert.save!
|
|
210
|
+
rescue ::Twilio::REST::RestError => e
|
|
211
|
+
if e.code == 21220
|
|
212
|
+
# 21220 - Unable to update record. Call is not in-progress. Cannot redirect.
|
|
213
|
+
adapter_alert.logs.create!(message: "Updating the call for status callbacks failed. The caller has already hung up.")
|
|
214
|
+
else
|
|
215
|
+
adapter_alert.logs.create!(message: "Updating the call for status callbacks failed. #{e.message}")
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
adapter_alert.logs.create!(message: "Marking alert as resolved due to call update failure.")
|
|
219
|
+
adapter_alert.resolve!(self, force: true)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
return adapter_controller&.render(xml: _twiml.to_xml)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# if this was attached to a router
|
|
226
|
+
if !adapter_alert.meta["live_call_router_team_prefix_ids"].present? && routers.size > 0 && account.subscription_feature_routers?
|
|
227
|
+
adapter_alert.logs.create!(message: "Routed to router. Attempting to get a list of teams...")
|
|
228
|
+
team_ids = []
|
|
229
|
+
default_receiver_team_ids = []
|
|
230
|
+
v3 = adapter_alert.v3_format
|
|
231
|
+
routers.each do |router|
|
|
232
|
+
if router.enabled? && router.kept?
|
|
233
|
+
actions = router.rules_eval({
|
|
234
|
+
always: true,
|
|
235
|
+
alert: v3
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
actions.flatten!
|
|
239
|
+
|
|
240
|
+
actions.each do |action|
|
|
241
|
+
team_ids << Array(action["receiver"]) if action["type"] == "assign"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# hold on to the default destination team ids in case we need them later
|
|
245
|
+
default_receiver_team_ids |= [router.default_receiver.prefix_id] if router.default_receiver.present?
|
|
246
|
+
end
|
|
247
|
+
end # end routers.each
|
|
248
|
+
|
|
249
|
+
team_ids.flatten!
|
|
250
|
+
team_ids.uniq!
|
|
251
|
+
|
|
252
|
+
# if the router didn't return any teams, use the default receiver teams
|
|
253
|
+
team_ids = default_receiver_team_ids if team_ids.size == 0
|
|
254
|
+
|
|
255
|
+
if team_ids.size > 0
|
|
256
|
+
adapter_alert.logs.create!(message: "Router provided #{team_ids.size} teams: #{team_ids}")
|
|
257
|
+
adapter_alert.meta["live_call_router_team_prefix_ids"] = team_ids
|
|
258
|
+
adapter_alert.save!
|
|
259
|
+
else
|
|
260
|
+
adapter_alert.logs.create!(message: "Router provided no teams.")
|
|
261
|
+
end
|
|
262
|
+
end # end if routers
|
|
263
|
+
|
|
129
264
|
if _teams_size == 0
|
|
265
|
+
adapter_alert.logs.create!(message: "This integration is not configured to route to any teams. Hang up.")
|
|
130
266
|
_twiml.say(message: "This integration is not configured to route to any teams. Goodbye", **SPEAK_OPTIONS)
|
|
131
267
|
_twiml.hangup
|
|
132
268
|
return adapter_controller&.render(xml: _twiml.to_xml)
|
|
133
269
|
end
|
|
134
270
|
|
|
271
|
+
if option_record && option_send_straight_to_voicemail && adapter_alert.meta["live_call_send_straight_to_voicemail"].nil?
|
|
272
|
+
# flag this call to send straight to voicemail
|
|
273
|
+
adapter_alert.meta["live_call_send_straight_to_voicemail"] = true
|
|
274
|
+
adapter_alert.save!
|
|
275
|
+
end
|
|
276
|
+
|
|
135
277
|
if !adapter_alert.meta["live_call_welcome"] && option_welcome_media.present?
|
|
136
278
|
adapter_alert.logs.create!(message: "Play welcome media to caller.")
|
|
137
279
|
_twiml.play(url: option_welcome_media.url)
|
|
@@ -142,6 +284,17 @@ module PagerTree::Integrations
|
|
|
142
284
|
if selected_team
|
|
143
285
|
adapter_alert.logs.create!(message: "Caller selected team '#{selected_team.name}'.") if _teams_size > 1 || option_force_input
|
|
144
286
|
|
|
287
|
+
if adapter_alert.meta["live_call_send_straight_to_voicemail"] == true
|
|
288
|
+
adapter_alert.destination_teams = [selected_team]
|
|
289
|
+
adapter_alert.save!
|
|
290
|
+
|
|
291
|
+
adapter_alert.logs.create!(message: "Send caller straight to voicemail (integration option).")
|
|
292
|
+
|
|
293
|
+
_twiml.redirect(PagerTree::Integrations::Engine.routes.url_helpers.dropped_live_call_routing_twilio_v3_url(id, thirdparty_id: _thirdparty_id), method: "POST")
|
|
294
|
+
|
|
295
|
+
return adapter_controller&.render(xml: _twiml.to_xml)
|
|
296
|
+
end
|
|
297
|
+
|
|
145
298
|
adapter_alert.logs.create!(message: "Play please wait media to caller.")
|
|
146
299
|
_twiml.play(url: option_please_wait_media_url)
|
|
147
300
|
friendly_name = adapter_alert.id
|
|
@@ -167,6 +320,12 @@ module PagerTree::Integrations
|
|
|
167
320
|
# kick off the alert workflow
|
|
168
321
|
adapter_alert.route_later
|
|
169
322
|
adapter_alert.logs.create!(message: "Successfully enqueued alert team workflow.")
|
|
323
|
+
|
|
324
|
+
if option_max_wait_time.present?
|
|
325
|
+
# set the max wait time for the queue
|
|
326
|
+
PagerTree::Integrations::LiveCallRouting::Twilio::V3::MaxWaitTimeJob.set(wait: option_max_wait_time.seconds).perform_later(id, adapter_alert.id)
|
|
327
|
+
adapter_alert.logs.create!(message: "Max wait time set to #{option_max_wait_time} seconds.")
|
|
328
|
+
end
|
|
170
329
|
else
|
|
171
330
|
adapter_alert.meta["live_call_repeat_count"] ||= 0
|
|
172
331
|
adapter_alert.meta["live_call_repeat_count"] += 1
|
|
@@ -181,7 +340,7 @@ module PagerTree::Integrations
|
|
|
181
340
|
end
|
|
182
341
|
end
|
|
183
342
|
else
|
|
184
|
-
adapter_alert.logs.create!(message: "Caller input bad input (too many times). Hangup.")
|
|
343
|
+
adapter_alert.logs.create!(message: "Caller input: bad input (too many times). Hangup.")
|
|
185
344
|
adapter_alert.resolve!(self)
|
|
186
345
|
_twiml.say(message: "Too much invalid input. Goodbye.", **SPEAK_OPTIONS)
|
|
187
346
|
_twiml.hangup
|
|
@@ -227,7 +386,7 @@ module PagerTree::Integrations
|
|
|
227
386
|
adapter_alert.additional_data.push(AdditionalDatum.new(format: "link", label: "Voicemail", value: recording_url).to_h)
|
|
228
387
|
adapter_alert.save!
|
|
229
388
|
|
|
230
|
-
adapter_alert.logs.create!(message: "Caller left a
|
|
389
|
+
adapter_alert.logs.create!(message: "Caller left a voicemail.")
|
|
231
390
|
|
|
232
391
|
if option_record_emails.any?
|
|
233
392
|
emails = option_record_emails.map do |x|
|
|
@@ -244,15 +403,32 @@ module PagerTree::Integrations
|
|
|
244
403
|
end
|
|
245
404
|
end.flatten.compact_blank.uniq
|
|
246
405
|
|
|
406
|
+
adapter_alert.logs.create!(message: "Sending voicemail recording to #{emails.size} emails.")
|
|
247
407
|
emails.each do |email|
|
|
248
408
|
LiveCallRouting::Twilio::V3Mailer.with(email: email, alert: adapter_alert, from: adapter_incoming_request_params.dig("From"), recording_url: recording_url).call_recording.deliver_later
|
|
249
409
|
end
|
|
250
410
|
end
|
|
411
|
+
|
|
412
|
+
if adapter_alert.meta["live_call_send_straight_to_voicemail"] == true
|
|
413
|
+
adapter_alert.logs.create!(message: "Call was sent straight to voicemail and caller left a message. Routing the alert.")
|
|
414
|
+
|
|
415
|
+
# kick off the alert workflow
|
|
416
|
+
adapter_alert.route_later
|
|
417
|
+
adapter_alert.logs.create!(message: "Successfully enqueued alert team workflow.")
|
|
418
|
+
end
|
|
251
419
|
elsif option_record
|
|
420
|
+
adapter_alert.logs.create!(message: "No one is available to answer this call. Requesting voicemail recording.")
|
|
252
421
|
_twiml.play(url: option_no_answer_media_url)
|
|
253
422
|
_twiml.record(max_length: 60)
|
|
254
423
|
else
|
|
255
|
-
|
|
424
|
+
# A friendly goodbye (when the integration has been configured to not record)
|
|
425
|
+
if option_no_answer_no_record_media_url.present?
|
|
426
|
+
adapter_alert.logs.create!(message: "No one is available to answer this call. Play media. Hangup on caller.")
|
|
427
|
+
_twiml.play(url: option_no_answer_no_record_media_url)
|
|
428
|
+
else
|
|
429
|
+
adapter_alert.logs.create!(message: "No one is available to answer this call. Say message. Hangup on caller.")
|
|
430
|
+
_twiml.say(message: "No one is available to answer this call. Goodbye.", **SPEAK_OPTIONS)
|
|
431
|
+
end
|
|
256
432
|
_twiml.hangup
|
|
257
433
|
end
|
|
258
434
|
|
|
@@ -261,19 +437,43 @@ module PagerTree::Integrations
|
|
|
261
437
|
|
|
262
438
|
def adapter_process_queue_status_deferred
|
|
263
439
|
queue_result = adapter_incoming_request_params.dig("QueueResult")
|
|
264
|
-
adapter_source_log&.sublog("Processing
|
|
440
|
+
adapter_source_log&.sublog("Processing queue status #{queue_result}")
|
|
265
441
|
|
|
266
442
|
if queue_result == "hangup"
|
|
267
443
|
self.adapter_alert = alerts.find_by(thirdparty_id: _thirdparty_id)
|
|
268
444
|
adapter_alert.logs.create!(message: "Caller hungup while waiting in queue.")
|
|
269
|
-
adapter_alert.resolve!(self)
|
|
445
|
+
adapter_alert.resolve!(self, force: true) unless option_skip_resolve_on_hangup
|
|
270
446
|
queue_destroy
|
|
271
447
|
end
|
|
272
448
|
|
|
273
449
|
adapter_source_log&.save!
|
|
274
450
|
end
|
|
275
451
|
|
|
452
|
+
def adapter_process_call_status_deferred
|
|
453
|
+
call_status = adapter_incoming_request_params.dig("CallStatus")
|
|
454
|
+
adapter_source_log&.sublog("Processing call status #{call_status}")
|
|
455
|
+
|
|
456
|
+
if ["completed"].include?(call_status)
|
|
457
|
+
self.adapter_alert = alerts.find_by(thirdparty_id: _thirdparty_id)
|
|
458
|
+
|
|
459
|
+
if adapter_alert.present? && adapter_alert.meta["live_call_send_straight_to_voicemail"] == true && !adapter_alert.additional_data.any? { |x| x["label"] == "Voicemail" }
|
|
460
|
+
if option_skip_resolve_on_hangup
|
|
461
|
+
adapter_alert.logs.create!(message: "Caller hung up without leaving a message.")
|
|
462
|
+
else
|
|
463
|
+
adapter_alert.logs.create!(message: "Caller hung up without leaving a message. Marking alert as resolved.")
|
|
464
|
+
adapter_alert.resolve!(self, force: true)
|
|
465
|
+
end
|
|
466
|
+
elsif adapter_alert.present? && adapter_alert.meta["live_call_send_straight_to_voicemail"] != true && !adapter_alert.meta["live_call_queue_sid"].present?
|
|
467
|
+
adapter_alert.logs.create!(message: "Caller hungup before being put in a queue. Marking alert as resolved.")
|
|
468
|
+
adapter_alert.resolve!(self, force: true)
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
276
473
|
def adapter_process_outgoing
|
|
474
|
+
return unless adapter_alert.source_id == id
|
|
475
|
+
return if adapter_alert.meta["live_call_send_straight_to_voicemail"] == true
|
|
476
|
+
|
|
277
477
|
event = adapter_outgoing_event.event_name.to_s
|
|
278
478
|
if event == "alert_acknowledged"
|
|
279
479
|
_on_acknowledge
|
|
@@ -282,6 +482,14 @@ module PagerTree::Integrations
|
|
|
282
482
|
end
|
|
283
483
|
end
|
|
284
484
|
|
|
485
|
+
def max_wait_time_reached!(alert_id)
|
|
486
|
+
# Handle max wait time reached logic
|
|
487
|
+
self.adapter_alert = alerts.find(alert_id)
|
|
488
|
+
return unless adapter_alert&.status_open?
|
|
489
|
+
|
|
490
|
+
_on_max_wait_time_reached
|
|
491
|
+
end
|
|
492
|
+
|
|
285
493
|
private
|
|
286
494
|
|
|
287
495
|
def _thirdparty_id
|
|
@@ -289,7 +497,7 @@ module PagerTree::Integrations
|
|
|
289
497
|
end
|
|
290
498
|
|
|
291
499
|
def _title
|
|
292
|
-
"Incoming call from #{adapter_incoming_request_params.dig("From")}"
|
|
500
|
+
"Incoming call from #{adapter_incoming_request_params.dig("From")&.chars&.join(" ")}"
|
|
293
501
|
end
|
|
294
502
|
|
|
295
503
|
def _additional_datums
|
|
@@ -302,8 +510,12 @@ module PagerTree::Integrations
|
|
|
302
510
|
]
|
|
303
511
|
end
|
|
304
512
|
|
|
513
|
+
def _api_region
|
|
514
|
+
API_REGIONS.include?(option_api_region) ? option_api_region : "ashburn.us1"
|
|
515
|
+
end
|
|
516
|
+
|
|
305
517
|
def _client
|
|
306
|
-
@_client ||= ::Twilio::REST::Client.new(
|
|
518
|
+
@_client ||= ::Twilio::REST::Client.new(option_api_key, option_api_secret, option_account_sid, _api_region)
|
|
307
519
|
end
|
|
308
520
|
|
|
309
521
|
def _call
|
|
@@ -314,12 +526,20 @@ module PagerTree::Integrations
|
|
|
314
526
|
@_twiml ||= ::Twilio::TwiML::VoiceResponse.new
|
|
315
527
|
end
|
|
316
528
|
|
|
529
|
+
def _teams
|
|
530
|
+
@_teams ||= adapter_alert.meta["live_call_router_team_prefix_ids"].present? ? Team.where(account_id: account_id, prefix_id: adapter_alert.meta["live_call_router_team_prefix_ids"]) : teams
|
|
531
|
+
end
|
|
532
|
+
|
|
317
533
|
def _teams_size
|
|
318
|
-
@_teams_size ||=
|
|
534
|
+
@_teams_size ||= _teams.size
|
|
319
535
|
end
|
|
320
536
|
|
|
321
537
|
def _teams_sorted
|
|
322
|
-
@_teams_sorted ||=
|
|
538
|
+
@_teams_sorted ||= adapter_alert.meta["live_call_router_team_prefix_ids"].present? ?
|
|
539
|
+
# sorts by the order the user gave us in the router
|
|
540
|
+
_teams.sort_by { |t| adapter_alert.meta["live_call_router_team_prefix_ids"].index(t.prefix_id) } :
|
|
541
|
+
# sorts in alpha order (not ascii, but dictionary style order)
|
|
542
|
+
_teams.order(name: :asc)
|
|
323
543
|
end
|
|
324
544
|
|
|
325
545
|
def _teams_message
|
|
@@ -349,21 +569,23 @@ module PagerTree::Integrations
|
|
|
349
569
|
|
|
350
570
|
if number.present?
|
|
351
571
|
_twiml.play(url: option_connect_now_media_url)
|
|
352
|
-
_twiml.pause(length: 1)
|
|
572
|
+
_twiml.pause(length: option_dial_pause.to_i.clamp(1, 15))
|
|
353
573
|
_twiml.dial(number: number, caller_id: _call.to, answer_on_bridge: true)
|
|
354
574
|
_call.update(twiml: _twiml.to_xml)
|
|
355
575
|
# log if we successfully transfered or failed
|
|
356
|
-
adapter_alert.logs.create!(message: "
|
|
576
|
+
adapter_alert.logs.create!(message: "Transferring the call succeeded.")
|
|
357
577
|
else
|
|
358
578
|
_twiml.say(message: "Someone has acknowledged this call, but they do not have a phone number on file. Goodbye.")
|
|
359
579
|
_twiml.hangup
|
|
360
580
|
_call.update(twiml: _twiml.to_xml)
|
|
361
|
-
adapter_alert.logs.create!(message: "
|
|
581
|
+
adapter_alert.logs.create!(message: "Transferring the call failed. #{account_user.user.name} has no phone number on file.")
|
|
362
582
|
end
|
|
363
583
|
rescue ::Twilio::REST::RestError => e
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
adapter_alert.logs.create!(message: "
|
|
584
|
+
if e.code == 21220
|
|
585
|
+
# 21220 - Unable to update record. Call is not in-progress. Cannot redirect.
|
|
586
|
+
adapter_alert.logs.create!(message: "[on_acknowledge] Transferring the call failed. The caller has already hung up.")
|
|
587
|
+
else
|
|
588
|
+
adapter_alert.logs.create!(message: "[on_acknowledge] Transferring the call failed. #{e.message}")
|
|
367
589
|
end
|
|
368
590
|
end
|
|
369
591
|
|
|
@@ -371,10 +593,23 @@ module PagerTree::Integrations
|
|
|
371
593
|
# log that we are going to transer
|
|
372
594
|
adapter_alert.logs.create!(message: "The alert was dropped. Attempting to transfer the call...")
|
|
373
595
|
_call.update(url: PagerTree::Integrations::Engine.routes.url_helpers.dropped_live_call_routing_twilio_v3_url(id, thirdparty_id: adapter_alert.thirdparty_id))
|
|
374
|
-
|
|
375
|
-
|
|
596
|
+
adapter_alert.logs.create!(message: "Transferring the call succeeded.")
|
|
597
|
+
rescue ::Twilio::REST::RestError => e
|
|
598
|
+
if e.code == 21220
|
|
599
|
+
# 21220 - Unable to update record. Call is not in-progress. Cannot redirect
|
|
600
|
+
adapter_alert.logs.create!(message: "[on_drop] Transferring the call failed. The caller has already hung up.")
|
|
601
|
+
else
|
|
602
|
+
adapter_alert.logs.create!(message: "[on_drop] Transferring the call failed. #{e.message}")
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
def _on_max_wait_time_reached
|
|
607
|
+
# log that we are going to transfer
|
|
608
|
+
adapter_alert.logs.create!(message: "The max wait time was reached. Attempting to transfer the caller (via max wait time, to voicemail or hangup)...")
|
|
609
|
+
_call.update(url: PagerTree::Integrations::Engine.routes.url_helpers.dropped_live_call_routing_twilio_v3_url(id, thirdparty_id: adapter_alert.thirdparty_id))
|
|
610
|
+
adapter_alert.logs.create!(message: "Transferring the caller (via max wait time, to voicemail or hangup) succeeded.")
|
|
376
611
|
rescue ::Twilio::REST::RestError => e
|
|
377
|
-
adapter_alert.logs.create!(message: "
|
|
612
|
+
adapter_alert.logs.create!(message: "Transferring the caller (via max wait time, to voicemail or hangup) failed. #{e.message}")
|
|
378
613
|
end
|
|
379
614
|
|
|
380
615
|
def queue_destroy
|