mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 06:50:18 +00:00
MG-853 - Add Slack output integration (#315)
* add slack integration Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * allow support for multiple message options Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * add message to slack struct Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * update template name Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> * group postgres and slack Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com> --------- Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a4abb61239
commit
7ef90440f2
@@ -45,6 +45,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/slack-go/slack v0.17.3 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
)
|
||||
|
||||
@@ -442,6 +442,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/slack-go/slack v0.17.3 h1:zV5qO3Q+WJAQ/XwbGfNFrRMaJ5T/naqaonyPV/1TP4g=
|
||||
github.com/slack-go/slack v0.17.3/go.mod h1:X+UqOufi3LYQHDnMG1vxf0J8asC6+WllXrVrhl8/Prk=
|
||||
github.com/smarty/assertions v1.16.0 h1:EvHNkdRA4QHMrn75NZSoUQ/mAUXAYWfatfB01yTCzfY=
|
||||
github.com/smarty/assertions v1.16.0/go.mod h1:duaaFdCS0K9dnoM50iyek/eYINOZ64gbh1Xlf6LG7AI=
|
||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||
|
||||
+2
-2
@@ -103,14 +103,14 @@ func (re *re) handleOutput(ctx context.Context, o Runnable, r Rule, msg *messagi
|
||||
case *outputs.Email:
|
||||
o.Emailer = re.email
|
||||
return o.Run(ctx, msg, val)
|
||||
case *outputs.Postgres:
|
||||
return o.Run(ctx, msg, val)
|
||||
case *outputs.ChannelPublisher:
|
||||
o.RePubSub = re.rePubSub
|
||||
return o.Run(ctx, msg, val)
|
||||
case *outputs.SenML:
|
||||
o.WritersPub = re.writersPub
|
||||
return o.Run(ctx, msg, val)
|
||||
case *outputs.Postgres, *outputs.Slack:
|
||||
return o.Run(ctx, msg, val)
|
||||
default:
|
||||
return fmt.Errorf("unknown output type: %T", o)
|
||||
}
|
||||
|
||||
@@ -26,16 +26,18 @@ const (
|
||||
SaveSenMLType
|
||||
EmailType
|
||||
SaveRemotePgType
|
||||
SlackType
|
||||
)
|
||||
|
||||
var (
|
||||
scriptKindToString = [...]string{"channels", "alarms", "save_senml", "email", "save_remote_pg"}
|
||||
scriptKindToString = [...]string{"channels", "alarms", "save_senml", "email", "save_remote_pg", "slack"}
|
||||
stringToScriptKind = map[string]OutputType{
|
||||
"channels": ChannelsType,
|
||||
"alarms": AlarmsType,
|
||||
"save_senml": SaveSenMLType,
|
||||
"email": EmailType,
|
||||
"save_remote_pg": SaveRemotePgType,
|
||||
"slack": SlackType,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package outputs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"text/template"
|
||||
|
||||
"github.com/absmach/supermq/pkg/messaging"
|
||||
"github.com/slack-go/slack"
|
||||
)
|
||||
|
||||
type Slack struct {
|
||||
Token string `json:"token"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (s *Slack) Run(ctx context.Context, msg *messaging.Message, val any) error {
|
||||
templData := templateVal{
|
||||
Message: msg,
|
||||
Result: val,
|
||||
}
|
||||
|
||||
tmpl, err := template.New("slack").Parse(s.Message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var output bytes.Buffer
|
||||
if err := tmpl.Execute(&output, templData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mapping := output.String()
|
||||
|
||||
var message slack.Msg
|
||||
if err := json.Unmarshal([]byte(mapping), &message); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
slackClient := slack.New(s.Token)
|
||||
|
||||
var opts []slack.MsgOption
|
||||
|
||||
if message.Text != "" {
|
||||
opts = append(opts, slack.MsgOptionText(message.Text, false))
|
||||
}
|
||||
if len(message.Attachments) > 0 {
|
||||
opts = append(opts, slack.MsgOptionAttachments(message.Attachments...))
|
||||
}
|
||||
if len(message.Blocks.BlockSet) > 0 {
|
||||
opts = append(opts, slack.MsgOptionBlocks(message.Blocks.BlockSet...))
|
||||
}
|
||||
_, _, err = slackClient.PostMessage(s.ChannelID, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Slack) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]any{
|
||||
"type": SlackType.String(),
|
||||
"token": s.Token,
|
||||
"channel_id": s.ChannelID,
|
||||
"message": s.Message,
|
||||
})
|
||||
}
|
||||
@@ -50,6 +50,7 @@ var outputRegistry = map[outputs.OutputType]func() Runnable{
|
||||
outputs.SaveRemotePgType: func() Runnable { return &outputs.Postgres{} },
|
||||
outputs.ChannelsType: func() Runnable { return &outputs.ChannelPublisher{} },
|
||||
outputs.SaveSenMLType: func() Runnable { return &outputs.SenML{} },
|
||||
outputs.SlackType: func() Runnable { return &outputs.Slack{} },
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
|
||||
Reference in New Issue
Block a user