Skip to content

Commit 4afa0e9

Browse files
Merge pull request #29 from SerhiiZahuba/feature/add_teams_notify
Feature/add teams notify
2 parents dee330e + 912d416 commit 4afa0e9

File tree

25 files changed

+440
-68
lines changed

25 files changed

+440
-68
lines changed

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/postgresus.iml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/prettier.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/internal/features/notifiers/enums.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ const (
88
NotifierTypeWebhook NotifierType = "WEBHOOK"
99
NotifierTypeSlack NotifierType = "SLACK"
1010
NotifierTypeDiscord NotifierType = "DISCORD"
11+
NotifierTypeTeams NotifierType = "TEAMS"
1112
)

backend/internal/features/notifiers/model.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
slack_notifier "postgresus-backend/internal/features/notifiers/models/slack"
99
telegram_notifier "postgresus-backend/internal/features/notifiers/models/telegram"
1010
webhook_notifier "postgresus-backend/internal/features/notifiers/models/webhook"
11+
teams_notifier "postgresus-backend/internal/features/notifiers/models/teams"
1112

1213
"github.com/google/uuid"
1314
)
@@ -25,6 +26,7 @@ type Notifier struct {
2526
WebhookNotifier *webhook_notifier.WebhookNotifier `json:"webhookNotifier" gorm:"foreignKey:NotifierID"`
2627
SlackNotifier *slack_notifier.SlackNotifier `json:"slackNotifier" gorm:"foreignKey:NotifierID"`
2728
DiscordNotifier *discord_notifier.DiscordNotifier `json:"discordNotifier" gorm:"foreignKey:NotifierID"`
29+
TeamsNotifier *teams_notifier.TeamsNotifier `gorm:"foreignKey:NotifierID;constraint:OnDelete:CASCADE" json:"teamsNotifier,omitempty"`
2830
}
2931

3032
func (n *Notifier) TableName() string {
@@ -64,6 +66,8 @@ func (n *Notifier) getSpecificNotifier() NotificationSender {
6466
return n.SlackNotifier
6567
case NotifierTypeDiscord:
6668
return n.DiscordNotifier
69+
case NotifierTypeTeams:
70+
return n.TeamsNotifier
6771
default:
6872
panic("unknown notifier type: " + string(n.NotifierType))
6973
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package teams_notifier
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
8+
"log/slog"
9+
"net/http"
10+
"net/url"
11+
12+
"github.com/google/uuid"
13+
)
14+
15+
type TeamsNotifier struct {
16+
NotifierID uuid.UUID `gorm:"type:uuid;primaryKey;column:notifier_id" json:"notifierId"`
17+
WebhookURL string `gorm:"type:text;not null;column:power_automate_url" json:"powerAutomateUrl"`
18+
}
19+
20+
func (TeamsNotifier) TableName() string {
21+
return "teams_notifiers"
22+
}
23+
24+
func (n *TeamsNotifier) Validate() error {
25+
if n.WebhookURL == "" {
26+
return errors.New("webhook_url is required")
27+
}
28+
u, err := url.Parse(n.WebhookURL)
29+
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
30+
return errors.New("invalid webhook_url")
31+
}
32+
return nil
33+
}
34+
35+
type сardAttachment struct {
36+
ContentType string `json:"contentType"`
37+
Content interface{} `json:"content"`
38+
}
39+
40+
type payload struct {
41+
Title string `json:"title"`
42+
Text string `json:"text"`
43+
Attachments []сardAttachment `json:"attachments,omitempty"`
44+
}
45+
46+
func (n *TeamsNotifier) Send(logger *slog.Logger, heading, message string) error {
47+
if err := n.Validate(); err != nil {
48+
return err
49+
}
50+
51+
card := map[string]interface{}{
52+
"type": "AdaptiveCard",
53+
"version": "1.4",
54+
"body": []interface{}{
55+
map[string]interface{}{"type": "TextBlock", "size": "Medium", "weight": "Bolder", "text": heading},
56+
map[string]interface{}{"type": "TextBlock", "wrap": true, "text": message},
57+
},
58+
}
59+
60+
p := payload{
61+
Title: heading,
62+
Text: message,
63+
Attachments: []cardAttachment{
64+
{ContentType: "application/vnd.microsoft.card.adaptive", Content: card},
65+
},
66+
}
67+
68+
body, _ := json.Marshal(p)
69+
req, err := http.NewRequest(http.MethodPost, n.WebhookURL, bytes.NewReader(body))
70+
if err != nil {
71+
return err
72+
}
73+
req.Header.Set("Content-Type", "application/json")
74+
75+
resp, err := http.DefaultClient.Do(req)
76+
if err != nil {
77+
return err
78+
}
79+
defer resp.Body.Close()
80+
81+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
82+
return fmt.Errorf("teams webhook returned status %d", resp.StatusCode)
83+
}
84+
return nil
85+
}

0 commit comments

Comments
 (0)