From 7df7528ccfd3c7a66c33bf052496d14470b5b65b Mon Sep 17 00:00:00 2001 From: Bel LaPointe <153096461+breel-render@users.noreply.github.com> Date: Mon, 15 Apr 2024 07:34:21 -0600 Subject: [PATCH] can parse slack messages from scraping channel history too --- message.go | 26 ++++++++-- message_test.go | 31 ++++++----- testdata/slack_events/reingested_alert.json | 57 +++++++++++++++++++++ 3 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 testdata/slack_events/reingested_alert.json diff --git a/message.go b/message.go index 627dd04..8a1ad20 100644 --- a/message.go +++ b/message.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "regexp" + "strconv" "strings" "time" ) @@ -59,8 +60,11 @@ func Deserialize(b []byte) (Message, error) { type ( slackMessage struct { - TS uint64 `json:"event_time"` - Event slackEvent + slackEvent + Type string + TS uint64 `json:"event_time"` + Event slackEvent + MessageTS string `json:"ts"` } slackEvent struct { @@ -108,7 +112,11 @@ type ( ) func ParseSlack(b []byte, assetPattern, datacenterPattern, eventNamePattern string) (Message, error) { - m, err := parseSlackJSON(b) + return ParseSlackFromChannel(b, assetPattern, datacenterPattern, eventNamePattern, "") +} + +func ParseSlackFromChannel(b []byte, assetPattern, datacenterPattern, eventNamePattern string, ch string) (Message, error) { + m, err := parseSlackJSON(b, ch) if err != nil { return Message{}, err } @@ -131,12 +139,16 @@ func ParseSlack(b []byte, assetPattern, datacenterPattern, eventNamePattern stri return m, nil } -func parseSlackJSON(b []byte) (Message, error) { +func parseSlackJSON(b []byte, ch string) (Message, error) { s, err := _parseSlackJSON(b) if err != nil { return Message{}, err } + if ch != "" { + s.Event.Channel = ch + } + if s.Event.Bot.Name != "" { if len(s.Event.Attachments) == 0 { return Message{}, ErrIrrelevantMessage @@ -184,6 +196,12 @@ func parseSlackJSON(b []byte) (Message, error) { func _parseSlackJSON(b []byte) (slackMessage, error) { var result slackMessage err := json.Unmarshal(b, &result) + switch result.Type { + case "message": + result.Event = result.slackEvent + result.TS, _ = strconv.ParseUint(strings.Split(result.MessageTS, ".")[0], 10, 64) + result.Event.ID = result.MessageTS + } if result.Event.Nested != nil && !result.Event.Nested.Empty() { result.Event.Blocks = result.Event.Nested.Blocks result.Event.Bot = result.Event.Nested.Bot diff --git a/message_test.go b/message_test.go index 44ed012..f5ea93f 100644 --- a/message_test.go +++ b/message_test.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "os" "path" "testing" @@ -9,6 +8,7 @@ import ( func TestParseSlackTestdata(t *testing.T) { cases := map[string]struct { + inCh string slackMessage slackMessage message Message }{ @@ -114,6 +114,21 @@ func TestParseSlackTestdata(t *testing.T) { Resolved: true, }, }, + "reingested_alert.json": { + inCh: "C06U1DDBBU4", + message: Message{ + ID: "1712892637.037639/1712892637", + TS: 1712892637, + Source: "https://renderinc.slack.com/archives/C06U1DDBBU4/p1712892637037639", + Channel: "C06U1DDBBU4", + Thread: "1712892637.037639", + EventName: "Alertconfig Workflow Failed", + Event: "11061", + Plaintext: "At least one alertconfig run has failed unexpectedly.\nDashboard: \nPanel: \nSource: ", + Asset: "", + Resolved: true, + }, + }, } for name, d := range cases { @@ -124,18 +139,8 @@ func TestParseSlackTestdata(t *testing.T) { t.Fatal(err) } - t.Run("_parseSlackJSON", func(t *testing.T) { - got, err := _parseSlackJSON(b) - if err != nil { - t.Fatal(err) - } - if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", want.slackMessage) { - t.Errorf("wanted \n\t%+v, got\n\t%+v", want.slackMessage, got) - } - }) - - t.Run("ParseSlack", func(t *testing.T) { - got, err := ParseSlack(b, renderAssetPattern, renderDatacenterPattern, renderEventNamePattern) + t.Run("ParseSlackFromChannel "+want.inCh, func(t *testing.T) { + got, err := ParseSlackFromChannel(b, renderAssetPattern, renderDatacenterPattern, renderEventNamePattern, want.inCh) if err != nil { t.Fatal(err) } diff --git a/testdata/slack_events/reingested_alert.json b/testdata/slack_events/reingested_alert.json new file mode 100644 index 0000000..a01a218 --- /dev/null +++ b/testdata/slack_events/reingested_alert.json @@ -0,0 +1,57 @@ +{ + "user": "U03RUK7FBUY", + "type": "message", + "ts": "1712892637.037639", + "edited": { + "user": "B03RHGBPH2M", + "ts": "1712896236.000000" + }, + "bot_id": "B03RHGBPH2M", + "app_id": "A286WATV2", + "text": "", + "team": "T9RQLQ0KV", + "bot_profile": { + "id": "B03RHGBPH2M", + "app_id": "A286WATV2", + "name": "Opsgenie for Alert Management", + "icons": { + "image_36": "https://avatars.slack-edge.com/2019-05-30/652285939191_7831939cc30ef7159561_36.png", + "image_48": "https://avatars.slack-edge.com/2019-05-30/652285939191_7831939cc30ef7159561_48.png", + "image_72": "https://avatars.slack-edge.com/2019-05-30/652285939191_7831939cc30ef7159561_72.png" + }, + "deleted": false, + "updated": 1658887059, + "team_id": "T9RQLQ0KV" + }, + "attachments": [ + { + "id": 1, + "color": "2ecc71", + "fallback": "\"[Grafana]: Firing: Alertconfig Workflow Failed\" \nTags: alertname:Alertconfig Workflow Failed, grafana_folder:Datastores, rule_uid:a7639f7e-6950-41be-850a-b22119f74cbb", + "text": "At least one alertconfig run has failed unexpectedly.\nDashboard: \nPanel: \nSource: ", + "title": "#11061: [Grafana]: Firing: Alertconfig Workflow Failed", + "title_link": "https://opsg.in/a/i/render/bdbbe5a6-738b-4643-9267-39d8dfc$2ead-1712892636514", + "callback_id": "bbd4a269-08a9-470e-ba79-ce238ac03dc7_05fa2e9b-bec4-4a7e-842d-36043d267a13_11061", + "fields": [ + { + "value": "P3", + "title": "Priority", + "short": true + }, + { + "value": "alertname:Alertconfig Workflow Failed, grafana_folder:Datastores, rule_uid:a7639f7e-6950-41be-850a-b22119f74cbb", + "title": "Tags", + "short": true + }, + { + "value": "Datastores Non-Critical", + "title": "Routed Teams", + "short": true + } + ], + "mrkdwn_in": [ + "text" + ] + } + ] +}