-
Notifications
You must be signed in to change notification settings - Fork 1
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
0 parents
commit d5d8622
Showing
11 changed files
with
527 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
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,2 @@ | ||
.idea/ | ||
.vim/ |
Binary file not shown.
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,140 @@ | ||
package dingtalk_notify | ||
|
||
import ( | ||
"bytes" | ||
"crypto/hmac" | ||
"crypto/sha256" | ||
"encoding/base64" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"net/url" | ||
"time" | ||
) | ||
|
||
func NewRobot(token, secret string) *Robot { | ||
return &Robot{ | ||
token: token, | ||
secret: secret, | ||
} | ||
} | ||
|
||
func sign(t int64, secret string) string { | ||
strToHash := fmt.Sprintf("%d\n%s", t, secret) | ||
hmac256 := hmac.New(sha256.New, []byte(secret)) | ||
hmac256.Write([]byte(strToHash)) | ||
data := hmac256.Sum(nil) | ||
return base64.StdEncoding.EncodeToString(data) | ||
} | ||
|
||
type Robot struct { | ||
token, secret string | ||
} | ||
|
||
func (robot *Robot) SendMessage(msg interface{}) error { | ||
body := bytes.NewBuffer(nil) | ||
err := json.NewEncoder(body).Encode(msg) | ||
if err != nil { | ||
return fmt.Errorf("msg json failed, msg: %v, err: %v", msg, err.Error()) | ||
} | ||
|
||
value := url.Values{} | ||
value.Set("access_token", robot.token) | ||
if robot.secret != "" { | ||
t := time.Now().UnixNano() / 1e6 | ||
value.Set("timestamp", fmt.Sprintf("%d", t)) | ||
value.Set("sign", sign(t, robot.secret)) | ||
} | ||
|
||
request, err := http.NewRequest(http.MethodPost, "https://oapi.dingtalk.com/robot/send", body) | ||
if err != nil { | ||
return fmt.Errorf("error request: %v", err.Error()) | ||
} | ||
request.URL.RawQuery = value.Encode() | ||
request.Header.Add("Content-Type", "application/json;charset=utf-8") | ||
res, err := (&http.Client{}).Do(request) | ||
if err != nil { | ||
return fmt.Errorf("send dingTalk message failed, error: %v", err.Error()) | ||
} | ||
defer func() { _ = res.Body.Close() }() | ||
result, err := ioutil.ReadAll(res.Body) | ||
|
||
if res.StatusCode != 200 { | ||
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, "http code is not 200")) | ||
} | ||
if err != nil { | ||
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, err.Error())) | ||
} | ||
|
||
type response struct { | ||
ErrCode int `json:"errcode"` | ||
} | ||
var ret response | ||
|
||
if err := json.Unmarshal(result, &ret); err != nil { | ||
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, err.Error())) | ||
} | ||
|
||
if ret.ErrCode != 0 { | ||
return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, "errcode is not 0")) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func httpError(request *http.Request, response *http.Response, body []byte, error string) string { | ||
return fmt.Sprintf( | ||
"http request failure, error: %s, status code: %d, %s %s, body:\n%s", | ||
error, | ||
response.StatusCode, | ||
request.Method, | ||
request.URL.String(), | ||
string(body), | ||
) | ||
} | ||
|
||
func (robot *Robot) SendTextMessage(content string, atUserIds []string, isAtAll bool) error { | ||
msg := map[string]interface{}{ | ||
"msgtype": "text", | ||
"text": map[string]string{ | ||
"content": content, | ||
}, | ||
"at": map[string]interface{}{ | ||
"atUserIds": atUserIds, | ||
"isAtAll": isAtAll, | ||
}, | ||
} | ||
|
||
return robot.SendMessage(msg) | ||
} | ||
|
||
func (robot *Robot) SendMarkdownMessage(title string, text string, atUserIds []string, isAtAll bool) error { | ||
msg := map[string]interface{}{ | ||
"msgtype": "markdown", | ||
"markdown": map[string]string{ | ||
"title": title, | ||
"text": text, | ||
}, | ||
"at": map[string]interface{}{ | ||
"atUserIds": atUserIds, | ||
"isAtAll": isAtAll, | ||
}, | ||
} | ||
|
||
return robot.SendMessage(msg) | ||
} | ||
|
||
func (robot *Robot) SendActionCardMessage(title string, text string, singleTitle string, singleURL string) error { | ||
msg := map[string]interface{}{ | ||
"msgtype": "actionCard", | ||
"actionCard": map[string]string{ | ||
"title": title, | ||
"text": text, | ||
"singleTitle": singleTitle, | ||
"singleURL": singleURL, | ||
}, | ||
} | ||
|
||
return robot.SendMessage(msg) | ||
} |
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,60 @@ | ||
package dingtalk_notify | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestRobot_SendMessage(t *testing.T) { | ||
//t.SkipNow() | ||
|
||
msg := map[string]interface{}{ | ||
"msgtype": "text", | ||
"text": map[string]string{ | ||
"content": "这是一条golang钉钉消息测试.", | ||
}, | ||
"at": map[string]interface{}{ | ||
"atMobiles": []string{}, | ||
"isAtAll": false, | ||
}, | ||
} | ||
|
||
robot := NewRobot("37849051cc270053f33a0d683bff85d58712e38790dfe1ddfcf86a17ad9df895", "x") | ||
if err := robot.SendMessage(msg); err != nil { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
func TestRobot_SendTextMessage(t *testing.T) { | ||
robot := NewRobot(os.Getenv("ROBOT_TOKEN"), os.Getenv("ROBOT_SECRET")) | ||
if err := robot.SendTextMessage("普通文本消息", []string{}, false); err != nil { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
func TestRobot_SendMarkdownMessage(t *testing.T) { | ||
robot := NewRobot(os.Getenv("ROBOT_TOKEN"), os.Getenv("ROBOT_SECRET")) | ||
err := robot.SendMarkdownMessage( | ||
"Markdown Test Title", | ||
"### Markdown 测试消息\n* 谷歌: [Google](https://www.google.com/)\n* 一张图片\n ![](https://avatars0.githubusercontent.com/u/40748346)", | ||
[]string{}, | ||
false, | ||
) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
func TestRobot_SendLinkMessage(t *testing.T) { | ||
robot := NewRobot(os.Getenv("ROBOT_TOKEN"), os.Getenv("ROBOT_SECRET")) | ||
err := robot.SendLinkMessage( | ||
"Link Test Title", | ||
"这是一条链接测试消息", | ||
"https://github.com/JetBlink", | ||
"https://avatars0.githubusercontent.com/u/40748346", | ||
) | ||
|
||
if err != nil { | ||
t.Error(err) | ||
} | ||
} |
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,3 @@ | ||
module github.com/AGou-ops/dingtalk | ||
|
||
go 1.17 |
Empty file.
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,8 @@ | ||
package main | ||
|
||
func main() { | ||
|
||
// run a simple http server | ||
HTTPServer() | ||
|
||
} |
Oops, something went wrong.