-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
648 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,98 @@ | ||
package action | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/mylxsw/adanos-alert/internal/repository" | ||
"github.com/mylxsw/adanos-alert/pkg/messager/dingding" | ||
"github.com/mylxsw/adanos-alert/pkg/template" | ||
"github.com/mylxsw/asteria/log" | ||
"github.com/mylxsw/coll" | ||
"go.mongodb.org/mongo-driver/bson" | ||
) | ||
|
||
type DingdingAction struct { | ||
manager *Manager | ||
manager *Manager | ||
userRepo repository.UserRepo | ||
} | ||
|
||
func NewDingdingAction(manager *Manager) *DingdingAction { | ||
return &DingdingAction{manager:manager} | ||
dingdingAction := DingdingAction{manager: manager} | ||
manager.MustResolve(func(userRepo repository.UserRepo) { | ||
dingdingAction.userRepo = userRepo | ||
}) | ||
return &dingdingAction | ||
} | ||
|
||
func (d DingdingAction) Handle(trigger repository.Trigger, grp repository.MessageGroup) error { | ||
panic("implement me") | ||
} | ||
func (d DingdingAction) Handle(rule repository.Rule, trigger repository.Trigger, grp repository.MessageGroup) error { | ||
payload := Payload{ | ||
Action: "dingding", | ||
Rule: rule, | ||
Trigger: trigger, | ||
Group: grp, | ||
} | ||
|
||
res, err := template.Parse(rule.Template, payload) | ||
if err != nil { | ||
res = fmt.Sprintf("Template parse failed: %s", err) | ||
log.WithFields(log.Fields{ | ||
"err": err.Error(), | ||
"template": rule.Template, | ||
"payload": payload, | ||
}).Errorf("template parse failed: %v", err) | ||
} | ||
|
||
mobiles := make([]string, 0) | ||
if len(trigger.UserRefs) > 0 { | ||
users, err := d.userRepo.Find(bson.M{"_id": bson.M{"$in": trigger.UserRefs}}) | ||
if err != nil { | ||
log.WithFields(log.Fields{ | ||
"err": err.Error(), | ||
"trigger": trigger, | ||
}).Errorf("load user from repo failed: %s", err) | ||
} else { | ||
if err := coll.MustNew(users).Filter(func(user repository.User) bool { | ||
for _, m := range user.Metas { | ||
if strings.ToLower(m.Key) == "phone" { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
}).Map(func(user repository.User) string { | ||
for _, m := range user.Metas { | ||
if strings.ToLower(m.Key) == "phone" { | ||
return m.Value | ||
} | ||
} | ||
return "" | ||
}).All(&mobiles); err != nil { | ||
log.WithFields(log.Fields{ | ||
"err": err.Error(), | ||
"trigger": trigger, | ||
"users": users, | ||
}).Errorf("convert user's phone to array failed: %v", err) | ||
} | ||
} | ||
} | ||
|
||
msg := dingding.NewMarkdownMessage(rule.Name, res, mobiles) | ||
if err := dingding.NewDingding(trigger.Meta).Send(msg); err != nil { | ||
log.WithFields(log.Fields{ | ||
"title": rule.Name, | ||
"content": res, | ||
"mobiles": mobiles, | ||
"err": err, | ||
}).Errorf("send message to dingding failed: %v", err) | ||
return err | ||
} | ||
|
||
log.WithFields(log.Fields{ | ||
"title": rule.Name, | ||
"content": res, | ||
"mobiles": mobiles, | ||
}).Debug("send message to dingding succeed") | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package dingding | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
) | ||
|
||
// DingdingMessage is a message holds all informations for a dingding sender | ||
type DingdingMessage struct { | ||
Message MarkdownMessage `json:"message"` | ||
Token string `json:"token"` | ||
} | ||
|
||
func (dm *DingdingMessage) Encode() []byte { | ||
data, _ := json.Marshal(dm) | ||
return data | ||
} | ||
|
||
func (dm *DingdingMessage) Decode(data []byte) error { | ||
return json.Unmarshal(data, &dm) | ||
} | ||
|
||
// MarkdownMessage is a markdown message for dingding | ||
type MarkdownMessage struct { | ||
Type string `json:"msgtype,omitempty"` | ||
Markdown MarkdownMessageBody `json:"markdown,omitempty"` | ||
At MessageAtSomebody `json:"at,omitempty"` | ||
} | ||
|
||
// Encode encode markdown message to json bytes | ||
func (m MarkdownMessage) Encode() ([]byte, error) { | ||
return json.Marshal(m) | ||
} | ||
|
||
// NewMarkdownMessage create a new MarkdownMessage | ||
func NewMarkdownMessage(title string, body string, mobiles []string) MarkdownMessage { | ||
return MarkdownMessage{ | ||
Type: "markdown", | ||
Markdown: MarkdownMessageBody{ | ||
Title: title, | ||
Text: body, | ||
}, | ||
At: MessageAtSomebody{ | ||
Mobiles: mobiles, | ||
}, | ||
} | ||
} | ||
|
||
// MarkdownMessageBody is markdown body | ||
type MarkdownMessageBody struct { | ||
Title string `json:"title,omitempty"` | ||
Text string `json:"text,omitempty"` | ||
MessageURL string `json:"messageUrl,omitempty"` | ||
} | ||
|
||
// MessageAtSomebody @ someone | ||
type MessageAtSomebody struct { | ||
Mobiles []string `json:"atMobiles"` | ||
ToAll bool `json:"isAtAll"` | ||
} | ||
|
||
type Dingding struct { | ||
Endpoint string | ||
Token string | ||
} | ||
|
||
func NewDingding(token string) *Dingding { | ||
return &Dingding{Endpoint: "https://oapi.dingtalk.com/robot/send?access_token=", Token: token} | ||
} | ||
|
||
type Message interface { | ||
Encode() ([]byte, error) | ||
} | ||
|
||
// dingResponse 钉钉响应 | ||
type dingResponse struct { | ||
ErrorCode int `json:"errcode"` | ||
ErrorMessage string `json:"errmsg"` | ||
} | ||
|
||
func (ding *Dingding) Send(msg Message) error { | ||
url := ding.Endpoint + ding.Token | ||
|
||
msgEncoded, err := msg.Encode() | ||
if err != nil { | ||
return fmt.Errorf("dingding message encode failed: %s", err.Error()) | ||
} | ||
|
||
reader := bytes.NewReader(msgEncoded) | ||
request, err := http.NewRequest("POST", url, reader) | ||
if err != nil { | ||
return fmt.Errorf("dingding create request failed: %w", err) | ||
} | ||
|
||
request.Header.Set("Content-Type", "application/json;charset=UTF-8") | ||
client := http.Client{} | ||
resp, err := client.Do(request) | ||
if err != nil { | ||
return fmt.Errorf("dingding send msg failed: %w", err) | ||
} | ||
|
||
respBytes, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return fmt.Errorf("dingding read response failed: %w", err) | ||
} | ||
|
||
var dresp dingResponse | ||
if err := json.Unmarshal(respBytes, &dresp); err != nil { | ||
return fmt.Errorf("send finished, response: %s", string(respBytes)) | ||
} | ||
|
||
if dresp.ErrorCode > 0 { | ||
return fmt.Errorf("[%d] %s", dresp.ErrorCode, dresp.ErrorMessage) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package template | ||
|
||
import ( | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/mylxsw/asteria/log" | ||
) | ||
|
||
type OpenFalconIM struct { | ||
Priority int | ||
Status string | ||
Endpoint string | ||
Body string | ||
CurrentStep int | ||
FormatTime string | ||
} | ||
|
||
// ParseOpenFalconImMessage 解析 Open-Falcon IM 消息 | ||
// https://github.com/open-falcon/falcon-plus/blob/2648553f82dd3986a91239d590461c0d795f63a4/modules/alarm/cron/builder.go#L43:6 | ||
func ParseOpenFalconImMessage(msg string) OpenFalconIM { | ||
defer func() { | ||
if err := recover(); err != nil { | ||
log.Errorf("parse open falcon message failed") | ||
} | ||
}() | ||
|
||
res := OpenFalconIM{} | ||
// [P3][PROBLEM][192.168.200.4][][ all(#1) agent.alive 1==1][O1 2019-07-08 23:35:00] | ||
segs := strings.Split(strings.TrimRight(strings.TrimLeft(msg, "["), "]"), "][") | ||
if len(segs) > 0 { | ||
res.Priority, _ = strconv.Atoi(strings.TrimLeft(segs[0], "P")) | ||
} | ||
|
||
if len(segs) > 1 { | ||
res.Status = segs[1] | ||
} | ||
|
||
if len(segs) > 2 { | ||
res.Endpoint = segs[2] | ||
} | ||
|
||
if len(segs) > 4 { | ||
res.Body = segs[4] | ||
} | ||
|
||
if len(segs) > 5 { | ||
ss := strings.SplitN(segs[5], " ", 2) | ||
res.CurrentStep, _ = strconv.Atoi(ss[0][1:]) | ||
res.FormatTime = ss[1] | ||
} | ||
|
||
return res | ||
} |
Oops, something went wrong.