Created
October 24, 2023 11:44
-
-
Save flydo/00e2c4141060610bc814ae36f536c455 to your computer and use it in GitHub Desktop.
飞书/钉钉群机器人通知发送的案例(Go、Shell)https://www.idev.top/d/385
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
/** | |
# 飞书/钉钉群机器人通知发送的案例 | |
1. 创建文件夹 `test` | |
2. 将下述代码粘贴至 test 目录下的 `main.go` 文件中 | |
3. 执行 `go mod tidy test`,创建 `module` 方式 | |
4. 使用 `go run main.go -u "https://open.feishu.cn/xxx" -s "Secret" -m "Message" -t 1234567890` 方式发送通知消息(-t 部分可省略) | |
5. 执行 `go build` 生成 `test` 可执行文件 | |
*/ | |
package main | |
import ( | |
"crypto/hmac" | |
"crypto/sha256" | |
"encoding/base64" | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"net/http" | |
"strings" | |
"time" | |
"log" | |
) | |
var ( | |
webhookUrl string | |
message string | |
secret string | |
ts int64 | |
) | |
func sendMsg(apiUrl, msg string) { | |
// json | |
contentType := "application/json" | |
if ts == 0 { | |
ts = time.Now().Unix() | |
} | |
var sign string | |
// data | |
sendData1 := `{ | |
"msg_type": "text", | |
"content": {"text": "消息通知: %s "}, | |
"sign": "%s", | |
"timestamp": %d | |
}` | |
sendData2 := `{ | |
"msgtype": "text", | |
"text": { | |
"content": "消息通知: %s " | |
}, | |
"at": { | |
"isAtAll": false | |
} | |
}` | |
var sendData string | |
if strings.HasPrefix(apiUrl, "https://oapi.dingtalk.com") { | |
sendData = sendData2 | |
if ts <= 10e9 { | |
ts *= 1000 | |
} | |
sign, _ = GenSign(secret, ts, 2) | |
sendData = fmt.Sprintf(sendData2, message) | |
apiUrl = fmt.Sprintf("%s×tamp=%d&sign=%s", apiUrl, ts, sign) | |
} else if strings.HasPrefix(apiUrl, "https://open.feishu.cn") { | |
sign, _ = GenSign(secret, ts, 1) | |
sendData = fmt.Sprintf(sendData1, message, sign, ts) | |
} else { | |
fmt.Printf("此方式(%s)不支持\n", apiUrl) | |
return | |
} | |
fmt.Printf(`%s | |
%s | |
timestamp: %d | |
secret: %s | |
sign: %s | |
`, apiUrl, sendData, ts, secret, sign) | |
// request | |
result, err := http.Post(apiUrl, contentType, strings.NewReader(sendData)) | |
if err != nil { | |
fmt.Printf("post failed, err:%v\n", err) | |
return | |
} | |
defer result.Body.Close() | |
rspBody, err := ioutil.ReadAll(result.Body) | |
if err != nil { | |
log.Fatalf("ReadAll failed, reqBody: %s, err: %v\n", rspBody, err) | |
return | |
} | |
fmt.Println("结果:" + string(rspBody)) | |
} | |
func main() { | |
flag.StringVar(&webhookUrl, "u", "", "飞书/钉钉webhook地址") | |
flag.StringVar(&secret, "s", "", "密钥") | |
flag.StringVar(&message, "m", "", "需要发送的消息内容") | |
flag.Int64Var(&ts, "t", 0, "时间戳") | |
flag.Parse() | |
//flag.Usage() | |
sendMsg(webhookUrl, message) | |
} | |
// GenSign 签名 | |
// mode: 1.飞书 2.钉钉 | |
func GenSign(secret string, timestamp int64, mode int) (string, error) { | |
stringToSign := fmt.Sprintf("%d\n%s", timestamp, secret) | |
var data []byte | |
var signStr string | |
if mode == 1 { | |
signStr = stringToSign | |
} else { | |
signStr = secret | |
data = []byte(stringToSign) | |
} | |
h := hmac.New(sha256.New, []byte(signStr)) | |
_, err := h.Write(data) | |
if err != nil { | |
return "", err | |
} | |
signature := base64.StdEncoding.EncodeToString(h.Sum(nil)) | |
return signature, 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
#!/bin/sh | |
# | |
# sh main.sh -u "https://open.feishu.cn/xxx" -s "Secret" -m "Message" -t 1234567890 (-t 部分可省略) | |
# | |
get_vars() { | |
while [ $# -gt 0 ] | |
do | |
case "${1}" in | |
# 需要发送的消息内容 | |
-m | --message ) | |
MESSAGE="${2}" | |
shift | |
;; | |
# 钉钉webhook地址 | |
-u | --url ) | |
URL="${2}" | |
shift | |
;; | |
# 密钥 | |
-s | --secret ) | |
SECRET="${2}" | |
shift | |
;; | |
# 时间戳(可省略) | |
-t | --timestamp ) | |
TS="${2}" | |
shift | |
;; | |
esac | |
shift | |
done | |
} | |
send_msg() { | |
[[ -n "${TS}" ]] || TS="$(date +%s)" | |
sendData1='{ | |
"msg_type": "text", | |
"content": {"text": "消息通知: %s "}, | |
"sign": "%s", | |
"timestamp": %d | |
}' | |
sendData2='{ | |
"msgtype": "text", | |
"text": { | |
"content": "消息通知: %s " | |
}, | |
"at": { | |
"isAtAll": false | |
} | |
}' | |
if [[ -n $(echo "${URL}" | grep "oapi.dingtalk.com") ]]; then | |
[[ ${#TS} -lt 11 ]] && TS="${TS}000" | |
get_sign 2 | |
semd_msg=$(printf "${sendData2}" ${MESSAGE} ) | |
URL=$(printf "${URL}×tamp=%s&sign=%s" ${TS} ${SIGN}) | |
elif [[ -n $(echo "${URL}" | grep "open.feishu.cn") ]]; then | |
get_sign 1 | |
semd_msg=$(printf "${sendData1}" ${MESSAGE} ${SIGN} ${TS}) | |
else | |
printf "此方式(%s)不支持\n" "${URL}" | |
return | |
fi | |
# echo "${semd_msg}" | |
# printf '%s\ntimestamp: %s\nsecret: %s\nsign: %s\n' ${URL} ${TS} ${SECRET} ${SIGN} | |
curl -XPOST -s -L "${URL}" -H "Content-Type:application/json" -H "charset:utf-8" -d "${semd_msg}" | |
} | |
get_sign() { | |
mode="${1}" | |
string_to_sign="${TS}\n${SECRET}" | |
data="" | |
if [[ "${mode}" = "1" ]]; then | |
sign_str="${string_to_sign}" | |
elif [[ "${mode}" = "2" ]]; then | |
sign_str="${SECRET}" | |
data="${string_to_sign}" | |
else | |
printf "此方式(%s)不支持\n" "${URL}" | |
exit 1 | |
fi | |
printf "${sign_str}" > ./key.dat | |
# printf "${data}" | |
SIGN=$(printf "${data}" | openssl dgst -sha256 -hmac "$(cat ./key.dat)" -binary | base64) | |
#echo $SIGN | |
rm -rf ./key.dat | |
} | |
main() { | |
get_vars "$@" | |
send_msg | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment