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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/pager_tree/integrations/live_call_routing/twilio/v3_controller.rb +20 -0
  3. data/app/jobs/pager_tree/integrations/live_call_routing/twilio/v3/max_wait_time_job.rb +13 -0
  4. data/app/models/pager_tree/integrations/additional_datum.rb +2 -2
  5. data/app/models/pager_tree/integrations/alert.rb +2 -2
  6. data/app/models/pager_tree/integrations/aws_cloudwatch/v3.rb +15 -5
  7. data/app/models/pager_tree/integrations/boolean_store_accessor.rb +2 -2
  8. data/app/models/pager_tree/integrations/channel/hangouts/v3.rb +23 -2
  9. data/app/models/pager_tree/integrations/channel/mattermost/v3.rb +4 -0
  10. data/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb +74 -29
  11. data/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb +261 -0
  12. data/app/models/pager_tree/integrations/channel/slack/v3.rb +30 -3
  13. data/app/models/pager_tree/integrations/cloudflare/v3.rb +75 -0
  14. data/app/models/pager_tree/integrations/custom_webhook/v3.rb +206 -0
  15. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.json +12 -0
  16. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.yaml +30 -0
  17. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_definition.json +9 -0
  18. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_example.yaml +27 -0
  19. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.json +25 -0
  20. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.yaml +33 -0
  21. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.json +40 -0
  22. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.yaml +32 -0
  23. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.json +30 -0
  24. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.yaml +23 -0
  25. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.json +12 -0
  26. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.yaml +48 -0
  27. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.json +21 -0
  28. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.yaml +43 -0
  29. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.json +31 -0
  30. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.yaml +24 -0
  31. data/app/models/pager_tree/integrations/datadog/v3.rb +10 -3
  32. data/app/models/pager_tree/integrations/dynatrace/v3.rb +67 -0
  33. data/app/models/pager_tree/integrations/echoes_hq/v3.rb +138 -0
  34. data/app/models/pager_tree/integrations/elast_alert/v3.rb +24 -0
  35. data/app/models/pager_tree/integrations/email/v3.rb +272 -22
  36. data/app/models/pager_tree/integrations/email/v3_examples/example.yml +24 -0
  37. data/app/models/pager_tree/integrations/form/v3.rb +15 -3
  38. data/app/models/pager_tree/integrations/freshdesk/v3.rb +7 -5
  39. data/app/models/pager_tree/integrations/freshservice/v3.rb +7 -5
  40. data/app/models/pager_tree/integrations/grafana/v3.rb +2 -2
  41. data/app/models/pager_tree/integrations/hetrix_tools/v3.rb +160 -0
  42. data/app/models/pager_tree/integrations/honeybadger/v3.rb +1 -1
  43. data/app/models/pager_tree/integrations/hydrozen/v3.rb +6 -0
  44. data/app/models/pager_tree/integrations/integration.rb +52 -9
  45. data/app/models/pager_tree/integrations/jira_server/v3.rb +12 -2
  46. data/app/models/pager_tree/integrations/kapacitor/v3.rb +1 -1
  47. data/app/models/pager_tree/integrations/live_call_routing/twilio/v3.rb +257 -22
  48. data/app/models/pager_tree/integrations/logic_monitor/v3.rb +193 -3
  49. data/app/models/pager_tree/integrations/mattermost/outgoing_webhook/v3.rb +1 -1
  50. data/app/models/pager_tree/integrations/meta/workplace/v3.rb +230 -0
  51. data/app/models/pager_tree/integrations/new_relic/v3.rb +9 -5
  52. data/app/models/pager_tree/integrations/outgoing_event.rb +8 -0
  53. data/app/models/pager_tree/integrations/outgoing_webhook/v3.rb +108 -13
  54. data/app/models/pager_tree/integrations/outgoing_webhook_delivery/hook_relay.rb +43 -33
  55. data/app/models/pager_tree/integrations/outgoing_webhook_delivery.rb +6 -5
  56. data/app/models/pager_tree/integrations/prtg/v3.rb +2 -1
  57. data/app/models/pager_tree/integrations/pulsetic/v3.rb +70 -0
  58. data/app/models/pager_tree/integrations/scom/pagertree.ps1 +153 -0
  59. data/app/models/pager_tree/integrations/scom/v3.rb +58 -0
  60. data/app/models/pager_tree/integrations/sentry/v3.rb +477 -0
  61. data/app/models/pager_tree/integrations/server_guard24/v3.rb +1 -1
  62. data/app/models/pager_tree/integrations/sixty_six_uptime/v3.rb +118 -0
  63. data/app/models/pager_tree/integrations/slack/webhook/v3.rb +1 -1
  64. data/app/models/pager_tree/integrations/solar_winds/v3.rb +66 -2
  65. data/app/models/pager_tree/integrations/status_gator/v3.rb +69 -0
  66. data/app/models/pager_tree/integrations/uptime_kuma/v3.rb +76 -0
  67. data/app/models/pager_tree/integrations/uptime_robot/v3.rb +6 -0
  68. data/app/models/pager_tree/integrations/webhook/v3.rb +25 -7
  69. data/app/models/pager_tree/integrations/zabbix/v3.rb +95 -0
  70. data/app/models/pager_tree/integrations/zendesk/v3.rb +2 -0
  71. data/app/views/pager_tree/integrations/channel/hangouts/v3/_form_options.html.erb +7 -0
  72. data/app/views/pager_tree/integrations/channel/hangouts/v3/_show_options.html.erb +10 -0
  73. data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb +7 -0
  74. data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb +14 -0
  75. data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb +41 -0
  76. data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb +54 -0
  77. data/app/views/pager_tree/integrations/channel/slack/v3/_form_options.html.erb +6 -3
  78. data/app/views/pager_tree/integrations/channel/slack/v3/_show_options.html.erb +1 -1
  79. data/app/views/pager_tree/integrations/cloudflare/v3/_form_options.html.erb +7 -0
  80. data/app/views/pager_tree/integrations/cloudflare/v3/_show_options.html.erb +12 -0
  81. data/app/views/pager_tree/integrations/custom_webhook/v3/_form_options.html.erb +8 -0
  82. data/app/views/pager_tree/integrations/custom_webhook/v3/_show_options.html.erb +0 -0
  83. data/app/views/pager_tree/integrations/datadog/v3/_form_options.html.erb +7 -0
  84. data/app/views/pager_tree/integrations/datadog/v3/_show_options.html.erb +12 -0
  85. data/app/views/pager_tree/integrations/dynatrace/v3/_form_options.html.erb +0 -0
  86. data/app/views/pager_tree/integrations/dynatrace/v3/_show_options.html.erb +0 -0
  87. data/app/views/pager_tree/integrations/echoes_hq/v3/_form_options.html.erb +10 -0
  88. data/app/views/pager_tree/integrations/echoes_hq/v3/_show_options.html.erb +12 -0
  89. data/app/views/pager_tree/integrations/email/v3/_form_options.html.erb +41 -11
  90. data/app/views/pager_tree/integrations/email/v3/_show_options.html.erb +18 -0
  91. data/app/views/pager_tree/integrations/form/v3/_form_options.html.erb +1 -5
  92. data/app/views/pager_tree/integrations/hetrix_tools/v3/_form_options.html.erb +7 -0
  93. data/app/views/pager_tree/integrations/hetrix_tools/v3/_show_options.html.erb +12 -0
  94. data/app/views/pager_tree/integrations/hydrozen/v3/_form_options.html.erb +0 -0
  95. data/app/views/pager_tree/integrations/hydrozen/v3/_show_options.html.erb +0 -0
  96. data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb +44 -31
  97. data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb +93 -8
  98. data/app/views/pager_tree/integrations/logic_monitor/v3/_form_options.html.erb +31 -0
  99. data/app/views/pager_tree/integrations/logic_monitor/v3/_show_options.html.erb +60 -0
  100. data/app/views/pager_tree/integrations/meta/workplace/v3/_form_options.html.erb +44 -0
  101. data/app/views/pager_tree/integrations/meta/workplace/v3/_show_options.html.erb +68 -0
  102. data/app/views/pager_tree/integrations/outgoing_webhook/v3/_form_options.html.erb +17 -3
  103. data/app/views/pager_tree/integrations/outgoing_webhook/v3/_show_options.html.erb +20 -0
  104. data/app/views/pager_tree/integrations/pulsetic/v3/_form_options.html.erb +0 -0
  105. data/app/views/pager_tree/integrations/pulsetic/v3/_show_options.html.erb +0 -0
  106. data/app/views/pager_tree/integrations/scom/v3/_form_options.html.erb +0 -0
  107. data/app/views/pager_tree/integrations/scom/v3/_show_options.html.erb +0 -0
  108. data/app/views/pager_tree/integrations/sentry/v3/_form_options.html.erb +9 -0
  109. data/app/views/pager_tree/integrations/sentry/v3/_show_options.html.erb +15 -0
  110. data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_form_options.html.erb +0 -0
  111. data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_show_options.html.erb +0 -0
  112. data/app/views/pager_tree/integrations/solar_winds/v3/_form_options.html.erb +40 -0
  113. data/app/views/pager_tree/integrations/solar_winds/v3/_show_options.html.erb +66 -0
  114. data/app/views/pager_tree/integrations/status_gator/v3/_form_options.html.erb +13 -0
  115. data/app/views/pager_tree/integrations/status_gator/v3/_show_options.html.erb +24 -0
  116. data/app/views/pager_tree/integrations/uptime_kuma/v3/_form_options.html.erb +0 -0
  117. data/app/views/pager_tree/integrations/uptime_kuma/v3/_show_options.html.erb +0 -0
  118. data/app/views/pager_tree/integrations/webhook/v3/_form_options.html.erb +8 -0
  119. data/app/views/pager_tree/integrations/webhook/v3/_show_options.html.erb +15 -0
  120. data/app/views/pager_tree/integrations/zabbix/v3/_form_options.html.erb +7 -0
  121. data/app/views/pager_tree/integrations/zabbix/v3/_show_options.html.erb +12 -0
  122. data/config/locales/en.yml +158 -10
  123. data/config/routes.rb +1 -0
  124. data/lib/pager_tree/integrations/format_converters/yaml_json_converter.rb +67 -0
  125. data/lib/pager_tree/integrations/version.rb +1 -1
  126. data/lib/pager_tree/integrations.rb +11 -3
  127. metadata +84 -8
@@ -1,9 +1,22 @@
1
1
  module PagerTree::Integrations
2
2
  class LogicMonitor::V3 < Integration
3
- OPTIONS = []
3
+ OPTIONS = [
4
+ {key: :alert_acknowledged, type: :boolean, default: false},
5
+ {key: :logic_monitor_account_name, type: :string, default: nil},
6
+ {key: :access_id, type: :string, default: nil},
7
+ {key: :access_key, type: :string, default: nil},
8
+ {key: :bearer_token, type: :string, default: nil}
9
+ ]
4
10
  store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
5
11
 
12
+ validates :option_alert_acknowledged, inclusion: {in: [true, false]}
13
+ validates :option_logic_monitor_account_name, presence: true, if: -> { option_alert_acknowledged == true }
14
+ validates :option_access_key, presence: true, if: -> { option_alert_acknowledged == true }
15
+ validates :option_access_id, presence: true, if: -> { option_alert_acknowledged == true }
16
+ validates :option_bearer_token, presence: true, if: -> { option_alert_acknowledged == true }
17
+
6
18
  after_initialize do
19
+ self.option_alert_acknowledged = false if option_alert_acknowledged.nil?
7
20
  end
8
21
 
9
22
  def adapter_supports_incoming?
@@ -11,7 +24,15 @@ module PagerTree::Integrations
11
24
  end
12
25
 
13
26
  def adapter_supports_outgoing?
14
- false
27
+ true
28
+ end
29
+
30
+ def adapter_outgoing_interest?(event_name)
31
+ try("option_#{event_name}") || false
32
+ end
33
+
34
+ def adapter_show_outgoing_webhook_delivery?
35
+ true
15
36
  end
16
37
 
17
38
  def adapter_incoming_can_defer?
@@ -19,7 +40,7 @@ module PagerTree::Integrations
19
40
  end
20
41
 
21
42
  def adapter_thirdparty_id
22
- adapter_incoming_request_params.dig("alertid")
43
+ adapter_incoming_request_params.dig("internalid")
23
44
  end
24
45
 
25
46
  def adapter_action
@@ -27,6 +48,8 @@ module PagerTree::Integrations
27
48
  case alert_status
28
49
  when "active", "test"
29
50
  :create
51
+ when "ack"
52
+ :acknowledge
30
53
  when "clear"
31
54
  :resolve
32
55
  else
@@ -45,6 +68,15 @@ module PagerTree::Integrations
45
68
  )
46
69
  end
47
70
 
71
+ def adapter_process_outgoing
72
+ event = adapter_outgoing_event.event_name.to_s
73
+
74
+ # only send sync to logic monitor if logic monitor is the source
75
+ if event == "alert_acknowledged" && option_alert_acknowledged == true && adapter_outgoing_event.alert.source == self
76
+ _on_acknowledge
77
+ end
78
+ end
79
+
48
80
  private
49
81
 
50
82
  def _title
@@ -73,5 +105,163 @@ module PagerTree::Integrations
73
105
  AdditionalDatum.new(format: "text", label: "Service", value: adapter_incoming_request_params.dig("service"))
74
106
  ]
75
107
  end
108
+
109
+ def _on_acknowledge
110
+ lm_alert_id = adapter_outgoing_event.alert.thirdparty_id
111
+ acknowledger = adapter_outgoing_event.account_user&.name || name || "someone"
112
+ http_verb = "POST"
113
+
114
+ if adapter_outgoing_event.alert.source_log&.message&.dig("params", "alerttype") == "agentDownAlert"
115
+ # try to get the collector id
116
+ collector_id = lm_alert_id.gsub(/[^0-9]/, "")
117
+ resource_path = "/setting/collector/collectors/#{collector_id}/ackdown?v=2"
118
+ data = {comment: "Acknowledged by #{acknowledger}"}
119
+ send_request_with_bearer_token(resource_path, http_verb, data)
120
+ else
121
+ resource_path = "/alert/alerts/#{lm_alert_id}/ack"
122
+ data = {ackComment: "Acknowledged by #{acknowledger}"}
123
+ send_request_with_hmac(resource_path, http_verb, data)
124
+ end
125
+ end
126
+
127
+ # https://www.logicmonitor.com/support/rest-api-authentication
128
+ def send_request_with_hmac(resource_path, http_verb, data)
129
+ base_url = "https://#{option_logic_monitor_account_name}.logicmonitor.com/santaba/rest"
130
+ url = base_url + resource_path
131
+ timestamp_ms = Time.current.to_i * 1000
132
+ data_string = data.to_json
133
+ # https://gist.github.com/abeland/e09a559e243f70670f2f4da3fd0fdabd
134
+ signature = Base64.urlsafe_encode64(
135
+ OpenSSL::HMAC.hexdigest(
136
+ "SHA256",
137
+ option_access_key,
138
+ http_verb.upcase + timestamp_ms.to_s + data_string + resource_path
139
+ )
140
+ )
141
+ headers = {
142
+ "Content-Type" => "application/json",
143
+ "Authorization" => "LMv1 #{option_access_id}:#{signature}:#{timestamp_ms}"
144
+ }
145
+
146
+ # note outgoing webhook delivery only supports the post method
147
+ outgoing_webhook_delivery = OutgoingWebhookDelivery.factory(
148
+ resource: self,
149
+ url: url,
150
+ body: data,
151
+ options: {headers: headers}
152
+ )
153
+ outgoing_webhook_delivery.save!
154
+ outgoing_webhook_delivery.deliver_later
155
+
156
+ outgoing_webhook_delivery
157
+ end
158
+
159
+ def send_request_with_bearer_token(resource_path, http_verb, data)
160
+ base_url = "https://#{option_logic_monitor_account_name}.logicmonitor.com/santaba/rest"
161
+ url = base_url + resource_path
162
+ headers = {
163
+ "Content-Type" => "application/json",
164
+ "Authorization" => "Bearer #{option_bearer_token}"
165
+ }
166
+
167
+ # note outgoing webhook delivery only supports the post method
168
+ outgoing_webhook_delivery = OutgoingWebhookDelivery.factory(
169
+ resource: self,
170
+ url: url,
171
+ body: data,
172
+ options: {headers: headers}
173
+ )
174
+ outgoing_webhook_delivery.save!
175
+ outgoing_webhook_delivery.deliver_later
176
+
177
+ outgoing_webhook_delivery
178
+ end
76
179
  end
77
180
  end
181
+
182
+ # https://www.logicmonitor.com/support/alerts/integrations/custom-http-delivery
183
+ # {
184
+ # "alertid": "LMS22",
185
+ # "alertstatus": "active",
186
+ # "datasource": "WinVolumeUsage-C:\",
187
+ # "datapoint": "PercentUsed",
188
+ # "date": "2014-05-02 14:21:40 PDT",
189
+ # "dsdesc": "Monitors space usage on logical volumes.",
190
+ # "dsidesc": null,
191
+ # "datapointdesc": "Percentage Used on the volume",
192
+ # "group": "group1,group2",
193
+ # "host": "opsgenie-test-server",
194
+ # "hostdesc": "Server used for testing OpsGenie integrations",
195
+ # "instance": "C:\",
196
+ # "level": "warning",
197
+ # "duration": "1465",
198
+ # "threshold": "10",
199
+ # "eventsource": "WinVolumeUsage-C:\",
200
+ # "eventlogfile": "Application",
201
+ # "eventtype": "information",
202
+ # "eventmsg": "Percentage used on the volume exceeded 80%",
203
+ # "eventlogmsg": "Remaining capacity(1456750MB) of volume C:\ is lower than 25%",
204
+ # "eventcode": "1847502394",
205
+ # "eventuser": "test-user",
206
+ # "value": "83",
207
+ # "batchdesc": "Monitors space usage on logical volumes everyday.",
208
+ # "hostips": "123.456.789.012",
209
+ # "hosturl": "https://opsgenie-test-server.net/",
210
+ # "service": "webservice",
211
+ # "alerttype": "error",
212
+ # "agent": "opsgenie-test-server",
213
+ # "checkpoint": "1879234",
214
+ # "hostinfo": null,
215
+ # "servicedetail": null,
216
+ # "serviceurl": "https://opsgenie-test-server.net/",
217
+ # "servicegroup": "Functional Testing",
218
+ # "clearvalue": "1"
219
+ # }
220
+
221
+ # {
222
+ # "service": "##SERVICE##",
223
+ # "alertid": "##ALERTID##",
224
+ # "alerttype": "##ALERTTYPE##",
225
+ # "alertstatus": "##ALERTSTATUS##",
226
+ # "level": "##LEVEL##",
227
+ # "host": "##HOST##",
228
+ # "datasource": "##DATASOURCE##",
229
+ # "eventsource": "##EVENTSOURCE##",
230
+ # "batchjob": "##BATCHJOB##",
231
+ # "group": "##GROUP##",
232
+ # "datapoint": "##DATAPOINT##",
233
+ # "start": "##START##",
234
+ # "finish": "##FINISH##",
235
+ # "duration": "##DURATION##",
236
+ # "value": "##VALUE##",
237
+ # "threshold": "##THRESHOLD##",
238
+ # "userdata": "##USERDATA##",
239
+ # "cmdline": "##CMDLINE##",
240
+ # "exitCode": "##EXITCODE##",
241
+ # "stdout": "##STDOUT##",
242
+ # "stderr": "##STDERR##",
243
+ # "agent": "##AGENT_DESCRIPTION##",
244
+ # "checkpoint": "##CHECKPOINT##",
245
+ # "datapointdesc": "##DPDESCRIPTION##",
246
+ # "hostdesc": "##HOSTDESCRIPTION##",
247
+ # "hostinfo": "##system.sysinfo##",
248
+ # "hostips": "##system.ips##",
249
+ # "hosturl": "##DEVICEURL##",
250
+ # "instance": "##INSTANCE##",
251
+ # "dsidesc": "##DSIDESCRIPTION##",
252
+ # "batchdesc": "##BJDESCRIPTION##",
253
+ # "dsdesc": "##DSDESCRIPTION##",
254
+ # "eventmsg": "##LIMITEDMESSAGE##",
255
+ # "eventlogmsg": "##MESSAGE##",
256
+ # "eventcode": "##EVENTCODE##",
257
+ # "eventtype": "##TYPE##",
258
+ # "eventuser": "##USER##",
259
+ # "eventlogfile": "##LOGFILE##",
260
+ # "eventsource": "##SOURCENAME##",
261
+ # "servicedetail": "##DETAIL##",
262
+ # "serviceurl": "##URL##",
263
+ # "servicegroup": "##SERVICEGROUP##",
264
+ # "date": "##DATE##",
265
+ # "clearvalue": "##CLEARVALUE##",
266
+ # "hostname": "##system.hostname##"
267
+ # }
@@ -10,7 +10,7 @@ module PagerTree::Integrations
10
10
  end
11
11
 
12
12
  def adapter_should_block_incoming?(request)
13
- self.option_token.present? && (request.params["token"] != self.option_token)
13
+ option_token.present? && (request.params["token"] != option_token)
14
14
  end
15
15
 
16
16
  def adapter_supports_incoming?
@@ -0,0 +1,230 @@
1
+ module PagerTree::Integrations
2
+ class Meta::Workplace::V3 < Integration
3
+ OPTIONS = [
4
+ {key: :incoming_enabled, type: :boolean, default: false},
5
+ {key: :outgoing_enabled, type: :boolean, default: true},
6
+ {key: :access_token, type: :string, default: nil},
7
+ {key: :app_secret, type: :string, default: nil},
8
+ {key: :group_id, type: :string, default: nil},
9
+ {key: :outgoing_rules, type: :string, default: nil}
10
+ ]
11
+ store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
12
+
13
+ validates :option_incoming_enabled, inclusion: {in: [true, false]}
14
+ validates :option_outgoing_enabled, inclusion: {in: [true, false]}
15
+ validates :option_access_token, presence: true
16
+ # validates :option_app_secret, presence: true
17
+ validates :option_group_id, presence: true
18
+
19
+ after_initialize do
20
+ self.option_incoming_enabled = false if option_incoming_enabled.nil?
21
+ self.option_outgoing_enabled = true if option_outgoing_enabled.nil?
22
+ self.option_outgoing_rules ||= ""
23
+ end
24
+
25
+ def endpoint
26
+ super + "/g"
27
+ end
28
+
29
+ def adapter_should_block_incoming?(request)
30
+ should_block = false
31
+
32
+ if option_app_secret.present? && request.headers["x-hub-signature-256"].present?
33
+ signature = request.headers["x-hub-signature-256"].delete_prefix("sha256=")
34
+ data = request.body.read
35
+ digest = OpenSSL::HMAC.hexdigest("SHA256", option_app_secret, data)
36
+ should_block = signature != digest
37
+ end
38
+
39
+ should_block
40
+ end
41
+
42
+ def adapter_supports_incoming?
43
+ # TODO - change this to true once we are ready to support this. The code currently works, but we don't want to confuse our users.
44
+ # Let's work with them to see what they want the functionality to look like
45
+ false
46
+ end
47
+
48
+ def adapter_supports_outgoing?
49
+ true
50
+ end
51
+
52
+ def adapter_show_outgoing_webhook_delivery?
53
+ true
54
+ end
55
+
56
+ def adapter_incoming_can_defer?
57
+ false
58
+ end
59
+
60
+ def adapter_supports_title_template?
61
+ false
62
+ end
63
+
64
+ def adapter_supports_description_template?
65
+ false
66
+ end
67
+
68
+ def adapter_thirdparty_id
69
+ [_entry&.dig("id"), _entry&.dig("time")].compact_blank.join("-")
70
+ end
71
+
72
+ def adapter_action
73
+ if option_incoming_enabled && adapter_incoming_request_params.dig("object") == "page" && _entry_changes&.dig("field") == "mention"
74
+ :create
75
+ else
76
+ :other
77
+ end
78
+ end
79
+
80
+ def adapter_response_incoming
81
+ if adapter_incoming_request_params["hub.mode"] == "subscribe"
82
+ adapter_controller&.render(plain: adapter_incoming_request_params["hub.challenge"])
83
+ else
84
+ adapter_controller&.head(:ok)
85
+ end
86
+ end
87
+
88
+ def adapter_process_create
89
+ # send back an ok
90
+ post_id = _entry_changes&.dig("value", "post_id")
91
+ _post_comment(post_id, "Ok") if post_id.present?
92
+
93
+ Alert.new(
94
+ title: _title,
95
+ thirdparty_id: adapter_thirdparty_id
96
+ )
97
+ end
98
+
99
+ def adapter_process_other
100
+ end
101
+
102
+ def adapter_outgoing_interest?(event_name)
103
+ option_outgoing_enabled && [
104
+ "alert_assigned",
105
+ "alert_acknowledged",
106
+ "alert_rejected",
107
+ "alert_resolved",
108
+ "alert_dropped",
109
+ "alert_handoff",
110
+ "comment_created"
111
+ ].include?(event_name.to_s)
112
+ end
113
+
114
+ def adapter_process_outgoing
115
+ event_type = adapter_outgoing_event.event_name.to_s
116
+ message = _generate_message(event_type)
117
+
118
+ return unless message.present?
119
+
120
+ if event_type == "alert_assigned"
121
+ _post_message(option_group_id, message)
122
+ else
123
+ post_id = _alert.meta["#{id}_meta_workplace_post_id"]
124
+
125
+ if post_id.blank?
126
+ outgoing_webhook_delivery_id = _alert.meta["#{id}_meta_workplace_outgoing_webhook_delivery_id"]
127
+ outgoing_webhook_delivery = OutgoingWebhookDelivery.find_by(id: outgoing_webhook_delivery_id)
128
+ post_id = begin
129
+ JSON.parse(outgoing_webhook_delivery.responses.first.dig("body"))["id"]
130
+ rescue
131
+ nil
132
+ end
133
+
134
+ if post_id.present?
135
+ _alert.meta["#{id}_meta_workplace_post_id"] = post_id
136
+ _alert.save!
137
+ end
138
+ end
139
+
140
+ _post_comment(post_id, message) if post_id.present?
141
+ end
142
+ rescue => e
143
+ Rails.logger.error "[Workplace] Error processing outgoing event: #{e.message}"
144
+ end
145
+
146
+ private
147
+
148
+ # INCOMING
149
+ def _entry
150
+ @_entry ||= adapter_incoming_request_params&.dig("entry", 0)
151
+ end
152
+
153
+ def _entry_changes
154
+ @_entry_changes ||= _entry&.dig("changes", 0)
155
+ end
156
+
157
+ def _title
158
+ _entry_changes&.dig("value", "message")
159
+ end
160
+
161
+ def _additional_datums
162
+ []
163
+ end
164
+
165
+ # OUTGOING
166
+ def _alert
167
+ @_alert ||= adapter_outgoing_event.alert
168
+ end
169
+
170
+ def _post_message(group_id, message)
171
+ # This operation needs to happen immediately because we need to attach the post_id to the alert
172
+ url = "https://graph.facebook.com/#{group_id}/feed?message=#{CGI.escape(message)}&formatting=MARKDOWN"
173
+ outgoing_webhook_delivery = _send_outgoing(url)
174
+ _alert.meta["#{id}_meta_workplace_outgoing_webhook_delivery_id"] = outgoing_webhook_delivery.id
175
+ _alert.save!
176
+
177
+ outgoing_webhook_delivery
178
+ end
179
+
180
+ def _post_comment(post_id, message)
181
+ url = "https://graph.facebook.com/#{post_id}/comments?message=#{CGI.escape(message)}"
182
+ _send_outgoing(url)
183
+ end
184
+
185
+ def _send_outgoing(url)
186
+ outgoing_webhook_delivery = OutgoingWebhookDelivery.factory(
187
+ resource: self,
188
+ url: url,
189
+ options: {
190
+ headers: {
191
+ "Authorization" => "Bearer #{option_access_token}"
192
+ }
193
+ }
194
+ )
195
+ outgoing_webhook_delivery.save!
196
+ outgoing_webhook_delivery.deliver_later
197
+
198
+ outgoing_webhook_delivery
199
+ end
200
+
201
+ def _generate_message(event_name)
202
+ case event_name
203
+ when "alert_assigned"
204
+ if _alert.incident?
205
+ "[Incident ##{_alert.tiny_id}](#{Rails.application.routes.url_helpers.try(:alert_url, _alert, script_name: "/#{_alert.account_id}")}) [#{_alert.incident_severity.upcase.dasherize}] #{_alert.incident_message} - #{_alert.title}"
206
+ else
207
+ "[Alert ##{_alert.tiny_id}](#{Rails.application.routes.url_helpers.try(:alert_url, _alert, script_name: "/#{_alert.account_id}")}) #{_alert.title}"
208
+ end
209
+ when "alert_acknowledged"
210
+ acknowledger = adapter_outgoing_event.account_user || adapter_outgoing_event.team
211
+ acknowledger&.name&.present? ? "Acknowledged by #{acknowledger.name}" : "Acknowledged"
212
+ when "alert_rejected"
213
+ rejecter = adapter_outgoing_event.account_user
214
+ rejecter&.name&.present? ? "Rejected by #{rejecter.name}" : "Rejected"
215
+ when "alert_resolved"
216
+ resolver = adapter_outgoing_event.account_user || adapter_outgoing_event.team
217
+ resolver&.name&.present? ? "Resolved by #{resolver.name}" : "Resolved"
218
+ when "alert_dropped"
219
+ "Dropped"
220
+ when "alert_handoff"
221
+ handoff = adapter_outgoing_event.handoff
222
+ "Handed off from #{handoff.source.name} to #{handoff.destination.name}"
223
+ when "comment_created"
224
+ comment = adapter_outgoing_event.comment
225
+ commenter = comment.account_user&.name || "PagerTree"
226
+ "#{commenter} commented: \"#{comment.body.to_plain_text}\""
227
+ end
228
+ end
229
+ end
230
+ end
@@ -19,16 +19,19 @@ module PagerTree::Integrations
19
19
  end
20
20
 
21
21
  def adapter_thirdparty_id
22
- adapter_incoming_request_params.dig("incident_id")
22
+ adapter_incoming_request_params.dig("incident_id") || adapter_incoming_request_params.dig("id")
23
23
  end
24
24
 
25
25
  def adapter_action
26
26
  event_type = adapter_incoming_request_params.dig("event_type")
27
27
  current_state = adapter_incoming_request_params.dig("current_state")
28
+ state = adapter_incoming_request_params.dig("state")
28
29
 
29
- if event_type == "INCIDENT_OPEN" || (event_type == "INCIDENT" && current_state == "open")
30
+ if event_type == "INCIDENT_OPEN" || (event_type == "INCIDENT" && current_state == "open") || (state == "CREATED" || state == "ACTIVATED")
30
31
  :create
31
- elsif event_type == "INCIDENT_RESOLVED" || (event_type == "INCIDENT" && current_state == "closed")
32
+ elsif event_type == "INCIDENT_ACKNOWLEDGED" || (event_type == "INCIDENT" && current_state == "acknowledged")
33
+ :acknowledge
34
+ elsif event_type == "INCIDENT_RESOLVED" || (event_type == "INCIDENT" && current_state == "closed") || state == "CLOSED"
32
35
  :resolve
33
36
  else
34
37
  :other
@@ -48,7 +51,7 @@ module PagerTree::Integrations
48
51
  private
49
52
 
50
53
  def _title
51
- adapter_incoming_request_params.dig("condition_name")
54
+ adapter_incoming_request_params.dig("condition_name") || adapter_incoming_request_params.dig("title")
52
55
  end
53
56
 
54
57
  def _description
@@ -58,7 +61,8 @@ module PagerTree::Integrations
58
61
  def _additional_datums
59
62
  [
60
63
  AdditionalDatum.new(format: "text", label: "Account Name", value: adapter_incoming_request_params.dig("account_name")),
61
- AdditionalDatum.new(format: "text", label: "Incident URL", value: adapter_incoming_request_params.dig("incident_url"))
64
+ AdditionalDatum.new(format: "link", label: "Incident URL", value: adapter_incoming_request_params.dig("incident_url")),
65
+ AdditionalDatum.new(format: "link", label: "Issue URL", value: adapter_incoming_request_params.dig("issueUrl"))
62
66
  ]
63
67
  end
64
68
  end
@@ -5,6 +5,8 @@ module PagerTree::Integrations
5
5
  extend ActiveModel::Callbacks
6
6
 
7
7
  attr_accessor :event_name
8
+ attr_accessor :account_id
9
+ attr_accessor :item_id
8
10
  attr_accessor :item
9
11
  attr_accessor :changes
10
12
  attr_accessor :outgoing_rules_data
@@ -12,6 +14,8 @@ module PagerTree::Integrations
12
14
  attr_accessor :handoff
13
15
  attr_accessor :team
14
16
  attr_accessor :account_user
17
+ attr_accessor :comment
18
+ attr_accessor :event_reminder
15
19
 
16
20
  define_model_callbacks :initialize
17
21
 
@@ -23,6 +27,8 @@ module PagerTree::Integrations
23
27
 
24
28
  after_initialize do
25
29
  self.event_name ||= nil
30
+ self.account_id ||= nil
31
+ self.item_id ||= nil
26
32
  self.item ||= nil
27
33
  self.changes ||= nil
28
34
  self.outgoing_rules_data ||= {}
@@ -31,6 +37,8 @@ module PagerTree::Integrations
31
37
  self.handoff ||= nil
32
38
  self.team ||= nil
33
39
  self.account_user ||= nil
40
+ self.comment ||= nil
41
+ self.event_reminder ||= nil
34
42
  end
35
43
  end
36
44
  end