Helper to parse Slack webhook payload. Extracts section block texts from attachments[0].blocks (new format).
(body []byte)
| 68 | // Helper to parse Slack webhook payload. |
| 69 | // Extracts section block texts from attachments[0].blocks (new format). |
| 70 | func parseSlackWebhook(body []byte) (title, description string, err error) { |
| 71 | var payload map[string]any |
| 72 | if err := json.Unmarshal(body, &payload); err != nil { |
| 73 | return "", "", err |
| 74 | } |
| 75 | |
| 76 | // New format: blocks are inside attachments[0].blocks. |
| 77 | var blocks []any |
| 78 | if attachments, ok := payload["attachments"].([]any); ok && len(attachments) > 0 { |
| 79 | if att, ok := attachments[0].(map[string]any); ok { |
| 80 | if b, ok := att["blocks"].([]any); ok { |
| 81 | blocks = b |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | if blocks == nil { |
| 86 | return "", "", nil |
| 87 | } |
| 88 | |
| 89 | // Collect section block texts. Layout for issue events: |
| 90 | // [0] event title (bold, with emoji/link) |
| 91 | // [1] action description (e.g. "Admin created issue X") |
| 92 | // [2] issue tile (*IssueName*) — bold-wrapped |
| 93 | // [3] issue description (if present) |
| 94 | var sectionTexts []string |
| 95 | for _, block := range blocks { |
| 96 | blockMap, ok := block.(map[string]any) |
| 97 | if !ok { |
| 98 | continue |
| 99 | } |
| 100 | if blockMap["type"] != "section" { |
| 101 | continue |
| 102 | } |
| 103 | textMap, ok := blockMap["text"].(map[string]any) |
| 104 | if !ok { |
| 105 | continue |
| 106 | } |
| 107 | text, ok := textMap["text"].(string) |
| 108 | if !ok { |
| 109 | continue |
| 110 | } |
| 111 | sectionTexts = append(sectionTexts, text) |
| 112 | } |
| 113 | |
| 114 | // Walk sections: find bold tile (*text*) as issue title, |
| 115 | // and the next plain section after the tile as issue description. |
| 116 | for i, s := range sectionTexts { |
| 117 | if i == 0 { |
| 118 | continue // skip event title |
| 119 | } |
| 120 | if strings.HasPrefix(s, "*") && strings.HasSuffix(s, "*") && !strings.Contains(s, "|") { |
| 121 | title = strings.Trim(s, "*") |
| 122 | // Next non-bold section is the issue description. |
| 123 | if i+1 < len(sectionTexts) { |
| 124 | next := sectionTexts[i+1] |
| 125 | if !strings.HasPrefix(next, "*") || !strings.HasSuffix(next, "*") { |
| 126 | description = next |
| 127 | } |
no test coverage detected