mirror of
https://github.com/lddsb/drone-dingtalk-message.git
synced 2026-06-16 14:50:42 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0529a41a36 | |||
| 45450d3115 | |||
| 3beae7de72 | |||
| 6615f9033d | |||
| d8514a85d7 | |||
| dc155b39c7 | |||
| 6722997241 | |||
| c100d9e56f | |||
| 9dad7f2a03 | |||
| 20aaaf3454 | |||
| 74c317b189 |
+46
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /go
|
||||||
|
path: src/github.com/lddsb/drone-dingtalk-message
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: golang
|
||||||
|
commands:
|
||||||
|
- go get -u github.com/golang/dep/cmd/dep
|
||||||
|
- dep ensure
|
||||||
|
- CGO_ENABLED=0 GOOS=linux go build -a -o drone-dingtalk-message .
|
||||||
|
- go test -race -coverprofile=coverage.txt -covermode=atomic
|
||||||
|
- ./drone-dingtalk-message -h
|
||||||
|
- name: codecov
|
||||||
|
image: plugins/codecov
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
settings:
|
||||||
|
token:
|
||||||
|
from_secret: codecov_token
|
||||||
|
- name: publish
|
||||||
|
image: plugins/docker
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
settings:
|
||||||
|
repo: lddsb/drone-dingtalk-message
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
tags:
|
||||||
|
- latest
|
||||||
|
- 1.0.0
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
- tags
|
||||||
Generated
+9
@@ -12,6 +12,14 @@
|
|||||||
revision = "23d116af351c84513e1946b527c88823e476be13"
|
revision = "23d116af351c84513e1946b527c88823e476be13"
|
||||||
version = "v1.3.0"
|
version = "v1.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:9142979c770f3d0f3c42c2eec532048bbbe2571134da91e8946cd8610c85c04b"
|
||||||
|
name = "github.com/lddsb/dingtalk-webhook"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "b4abe34b5fa9af8ea7d5f28c02bd314558b21f7f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:b24d38b282bacf9791408a080f606370efa3d364e4b5fd9ba0f7b87786d3b679"
|
digest = "1:b24d38b282bacf9791408a080f606370efa3d364e4b5fd9ba0f7b87786d3b679"
|
||||||
name = "github.com/urfave/cli"
|
name = "github.com/urfave/cli"
|
||||||
@@ -25,6 +33,7 @@
|
|||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
input-imports = [
|
input-imports = [
|
||||||
"github.com/joho/godotenv/autoload",
|
"github.com/joho/godotenv/autoload",
|
||||||
|
"github.com/lddsb/dingtalk-webhook",
|
||||||
"github.com/urfave/cli",
|
"github.com/urfave/cli",
|
||||||
]
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
|
|||||||
@@ -36,3 +36,7 @@
|
|||||||
[prune]
|
[prune]
|
||||||
go-tests = true
|
go-tests = true
|
||||||
unused-packages = true
|
unused-packages = true
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/lddsb/dingtalk-webhook"
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Dee Luo
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# Drone CI DingTalk Message Plugin
|
# Drone CI DingTalk Message Plugin
|
||||||
|
[](https://drone.lddsb.com/lddsb/drone-dingtalk-message) [](https://goreportcard.com/report/github.com/lddsb/drone-dingtalk-message) [](https://codecov.io/gh/lddsb/drone-dingtalk-message) [](https://codebeat.co/projects/github-com-lddsb-drone-dingtalk-message-master) [](LICENSE)
|
||||||
|
|
||||||
### Drone CI Plugin Config
|
### Drone CI Plugin Config
|
||||||
`0.8.x`
|
`0.8.x`
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Version of cli
|
||||||
var Version = "0.1.1202"
|
var Version = "0.1.1202"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -25,6 +26,11 @@ func main() {
|
|||||||
app.Action = run
|
app.Action = run
|
||||||
app.Version = Version
|
app.Version = Version
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "config.debug",
|
||||||
|
Usage: "debug mode",
|
||||||
|
EnvVar: "PLUGIN_DEBUG",
|
||||||
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "config.token,access_token,token",
|
Name: "config.token,access_token,token",
|
||||||
Usage: "dingtalk webhook access token",
|
Usage: "dingtalk webhook access token",
|
||||||
@@ -37,7 +43,7 @@ func main() {
|
|||||||
EnvVar: "PLUGIN_LANG",
|
EnvVar: "PLUGIN_LANG",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "config.message.type,msg_type,message_type,type",
|
Name: "config.message.type,message_type",
|
||||||
Usage: "dingtalk message type, like text, markdown, action card, link and feed card...",
|
Usage: "dingtalk message type, like text, markdown, action card, link and feed card...",
|
||||||
EnvVar: "PLUGIN_MSG_TYPE,PLUGIN_TYPE,PLUGIN_MESSAGE_TYPE",
|
EnvVar: "PLUGIN_MSG_TYPE,PLUGIN_TYPE,PLUGIN_MESSAGE_TYPE",
|
||||||
},
|
},
|
||||||
@@ -51,22 +57,6 @@ func main() {
|
|||||||
Usage: "at someone in a dingtalk group need this guy bind's mobile",
|
Usage: "at someone in a dingtalk group need this guy bind's mobile",
|
||||||
EnvVar: "PLUGIN_MSG_AT_MOBILES",
|
EnvVar: "PLUGIN_MSG_AT_MOBILES",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "drone",
|
|
||||||
Usage: "indicates the runtime environment is Drone",
|
|
||||||
EnvVar: "DRONE",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "branch",
|
|
||||||
Usage: "providers the branch for the current build",
|
|
||||||
EnvVar: "DRONE_BRANCH",
|
|
||||||
},
|
|
||||||
// commit args start
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "remote.url",
|
|
||||||
Usage: "git remote url",
|
|
||||||
EnvVar: "DRONE_REMOTE_URL",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "commit.author.avatar",
|
Name: "commit.author.avatar",
|
||||||
Usage: "providers the author avatar url for the current commit",
|
Usage: "providers the author avatar url for the current commit",
|
||||||
@@ -98,161 +88,16 @@ func main() {
|
|||||||
Usage: "providers the commit message for the current build",
|
Usage: "providers the commit message for the current build",
|
||||||
EnvVar: "DRONE_COMMIT_MESSAGE",
|
EnvVar: "DRONE_COMMIT_MESSAGE",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit.ref",
|
|
||||||
Usage: "providers the reference for the current build",
|
|
||||||
EnvVar: "DRONE_COMMIT_REF",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "commit.sha",
|
Name: "commit.sha",
|
||||||
Usage: "providers the commit sha for the current build",
|
Usage: "providers the commit sha for the current build",
|
||||||
EnvVar: "DRONE_COMMIT_SHA",
|
EnvVar: "DRONE_COMMIT_SHA",
|
||||||
},
|
},
|
||||||
// commit args end
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "git.url.http",
|
|
||||||
Usage: "providers the repository git+http url",
|
|
||||||
EnvVar: "DRONE_GIT_HTTP_URL",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "git.url.ssh",
|
|
||||||
Usage: "providers the repository git+ssh url",
|
|
||||||
EnvVar: "DRONE_GIT_SSH_URL",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "machine",
|
|
||||||
Usage: "providers the Drone agent hostname",
|
|
||||||
EnvVar: "DRONE_MACHINE",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "pull.request",
|
|
||||||
Usage: "providers the pull request number for the current build.This value is only set if the build event is of type pull request",
|
|
||||||
EnvVar: "DRONE_PULL_REQUEST",
|
|
||||||
},
|
|
||||||
// repo args start
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "repo.fullname",
|
Name: "repo.fullname",
|
||||||
Usage: "providers the full name of the repository",
|
Usage: "providers the full name of the repository",
|
||||||
EnvVar: "DRONE_REPO",
|
EnvVar: "DRONE_REPO",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo.owner",
|
|
||||||
Usage: "repository owner",
|
|
||||||
EnvVar: "DRONE_REPO_OWNER",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo.branch",
|
|
||||||
Usage: "providers the default repository branch(e.g.master)",
|
|
||||||
EnvVar: "DRONE_REPO_BRANCH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo.link",
|
|
||||||
Usage: "providers the repository http link",
|
|
||||||
EnvVar: "DRONE_REPO_LINK",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo.name",
|
|
||||||
Usage: "providers the repository name",
|
|
||||||
EnvVar: "DRONE_REPO_NAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo.avatar",
|
|
||||||
Usage: "repository avatar",
|
|
||||||
EnvVar: "DRONE_REPO_AVATAR",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo.namespace",
|
|
||||||
Usage: "providers the repository namespace(e.g. account owner)",
|
|
||||||
EnvVar: "DRONE_REPO_NAMESPACE",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "repo.private",
|
|
||||||
Usage: "indicates the repository is public or private",
|
|
||||||
EnvVar: "DRONE_REPO_PRIVATE",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "repo.trusted",
|
|
||||||
Usage: "repository is trusted",
|
|
||||||
EnvVar: "DRONE_REPO_TRUSTED",
|
|
||||||
},
|
|
||||||
// repo args end
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "runner.host",
|
|
||||||
Usage: "provider are Drone agent hostname",
|
|
||||||
EnvVar: "DRONE_RUNNER_HOST",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "runner.hostname",
|
|
||||||
Usage: "providers the Drone agent hostname",
|
|
||||||
EnvVar: "DRONE_RUNNER_HOSTNAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "runner.platform",
|
|
||||||
Usage: "providers the Drone agent os and architecture",
|
|
||||||
EnvVar: "DRONE_RUNNER_PLATFORM",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "runner.label",
|
|
||||||
Usage: "404 not found",
|
|
||||||
EnvVar: "DRONE_RUNNER_LABEL",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "source.branch",
|
|
||||||
Usage: "providers the source branch for a pull request",
|
|
||||||
EnvVar: "DRONE_SOURCE_BRANCH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "target.branch",
|
|
||||||
Usage: "providers the target branch for a pull request",
|
|
||||||
EnvVar: "DRONE_TARGET_BRANCH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "system.host",
|
|
||||||
Usage: "providers the Drone server hostname",
|
|
||||||
EnvVar: "DRONE_SYSTEM_HOST",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "system.hostname",
|
|
||||||
Usage: "providers the Drone server hostname",
|
|
||||||
EnvVar: "DRONE_SYSTEM_HOSTNAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "system.version",
|
|
||||||
Usage: "providers the Drone server version",
|
|
||||||
EnvVar: "DRONE_SYSTEM_VERSION",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "tag",
|
|
||||||
Usage: "providers the tag name for the current build.This value is only set if the build event is of type tag",
|
|
||||||
EnvVar: "DRONE_TAG",
|
|
||||||
},
|
|
||||||
// build args start
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "build.event",
|
|
||||||
Value: "push",
|
|
||||||
Usage: "build event",
|
|
||||||
EnvVar: "DRONE_BUILD_EVENT",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "build.number",
|
|
||||||
Usage: "build number",
|
|
||||||
EnvVar: "DRONE_BUILD_NUMBER",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "build.created",
|
|
||||||
Usage: "build created",
|
|
||||||
EnvVar: "DRONE_BUILD_CREATED",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "build.started",
|
|
||||||
Usage: "build started",
|
|
||||||
EnvVar: "DRONE_BUILD_STARTED",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "build.finished",
|
|
||||||
Usage: "build finished",
|
|
||||||
EnvVar: "DRONE_BUILD_FINISHED",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "build.status",
|
Name: "build.status",
|
||||||
Usage: "build status",
|
Usage: "build status",
|
||||||
@@ -264,37 +109,6 @@ func main() {
|
|||||||
Usage: "build link",
|
Usage: "build link",
|
||||||
EnvVar: "DRONE_BUILD_LINK",
|
EnvVar: "DRONE_BUILD_LINK",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "build.deploy",
|
|
||||||
Usage: "build deployment target",
|
|
||||||
EnvVar: "DRONE_DEPLOY_TO",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "yaml.verified",
|
|
||||||
Usage: "build yaml is verified",
|
|
||||||
EnvVar: "DRONE_YAML_VERIFIED",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "yaml.signed",
|
|
||||||
Usage: "build yaml is signed",
|
|
||||||
EnvVar: "DRONE_YAML_SIGNED",
|
|
||||||
},
|
|
||||||
// build args end
|
|
||||||
cli.Float64Flag{
|
|
||||||
Name: "job.started",
|
|
||||||
Usage: "job started",
|
|
||||||
EnvVar: "DRONE_JOB_STARTED",
|
|
||||||
},
|
|
||||||
cli.Float64Flag{
|
|
||||||
Name: "job.finished",
|
|
||||||
Usage: "job finished",
|
|
||||||
EnvVar: "DRONE_JOB_FINISHED",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "ci.repo.link",
|
|
||||||
Usage: "ci repo link",
|
|
||||||
EnvVar: "CI_REPO_LINK",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "config.success.pic.url",
|
Name: "config.success.pic.url",
|
||||||
Usage: "config success picture url",
|
Usage: "config success picture url",
|
||||||
@@ -334,66 +148,63 @@ func main() {
|
|||||||
|
|
||||||
if err := app.Run(os.Args); nil != err {
|
if err := app.Run(os.Args); nil != err {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run with args
|
// run with args
|
||||||
func run(c *cli.Context) {
|
func run(c *cli.Context) {
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
// repo info
|
Drone: Drone{
|
||||||
Repo: Repo{
|
// repo info
|
||||||
FullName: c.String("repo.fullname"),
|
Repo: Repo{
|
||||||
Owner: c.String("repo.owner"),
|
FullName: c.String("repo.fullname"),
|
||||||
Name: c.String("repo.name"),
|
},
|
||||||
},
|
// build info
|
||||||
// build info
|
Build: Build{
|
||||||
Build: Build{
|
Status: c.String("build.status"),
|
||||||
Action: c.String("build.action"),
|
Link: c.String("build.link"),
|
||||||
Number: c.Int("build.number"),
|
},
|
||||||
Started: c.Float64("build.started"),
|
Commit: Commit{
|
||||||
Created: c.Float64("build.created"),
|
Sha: c.String("commit.sha"),
|
||||||
Event: c.String("build.event"),
|
Branch: c.String("commit.branch"),
|
||||||
Status: c.String("build.status"),
|
Message: c.String("commit.message"),
|
||||||
Link: c.String("build.link"),
|
Link: c.String("commit.link"),
|
||||||
},
|
Authors: struct {
|
||||||
Commit: Commit{
|
Avatar string
|
||||||
Sha: c.String("commit.sha"),
|
Email string
|
||||||
Branch: c.String("commit.branch"),
|
Name string
|
||||||
Message: c.String("commit.message"),
|
}{
|
||||||
Link: c.String("commit.link"),
|
Avatar: c.String("commit.author.avatar"),
|
||||||
Authors: struct {
|
Email: c.String("commit.author.email"),
|
||||||
Avatar string
|
Name: c.String("commit.author.name"),
|
||||||
Email string
|
},
|
||||||
Name string
|
|
||||||
}{
|
|
||||||
Avatar: c.String("commit.author.avatar"),
|
|
||||||
Email: c.String("commit.author.email"),
|
|
||||||
Name: c.String("commit.author.name"),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// custom config
|
// custom config
|
||||||
Config: Config{
|
Config: Config{
|
||||||
AccessToken: c.String("config.token"),
|
AccessToken: c.String("config.token"),
|
||||||
Lang: c.String("config.lang"),
|
//Lang: c.String("config.lang"),
|
||||||
IsAtALL: c.Bool("config.message.at.all"),
|
IsAtALL: c.Bool("config.message.at.all"),
|
||||||
MsgType: c.String("config.message.type"),
|
MsgType: c.String("config.message.type"),
|
||||||
Mobiles: c.String("config.message.at.mobiles"),
|
Mobiles: c.String("config.message.at.mobiles"),
|
||||||
SuccessPicUrl: c.String("config.success.pic.url"),
|
Debug: c.Bool("config.debug"),
|
||||||
FailurePicUrl: c.String("config.failure.pic.url"),
|
|
||||||
SuccessColor: c.String("config.success.color"),
|
|
||||||
FailureColor: c.String("config.failure.color"),
|
|
||||||
WithColor: c.Bool("config.message.color"),
|
|
||||||
WithPic: c.Bool("config.message.pic"),
|
|
||||||
LinkSha: c.Bool("config.message.sha.link"),
|
|
||||||
},
|
},
|
||||||
CI: CI{
|
Extra: Extra{
|
||||||
RepoLink: c.String("ci.repo.link"),
|
Pic: ExtraPic{
|
||||||
|
WithPic: c.Bool("config.message.pic"),
|
||||||
|
SuccessPicURL: c.String("config.success.pic.url"),
|
||||||
|
FailurePicURL: c.String("config.failure.pic.url"),
|
||||||
|
},
|
||||||
|
Color: ExtraColor{
|
||||||
|
SuccessColor: c.String("config.success.color"),
|
||||||
|
FailureColor: c.String("config.failure.color"),
|
||||||
|
WithColor: c.Bool("config.message.color"),
|
||||||
|
},
|
||||||
|
LinkSha: c.Bool("config.message.sha.link"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := plugin.Exec(); nil != err {
|
if err := plugin.Exec(); nil != err {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(t *testing.T) {
|
||||||
|
main()
|
||||||
|
t.Log("main testing finished")
|
||||||
|
}
|
||||||
@@ -5,210 +5,174 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
webhook "github.com/lddsb/dingtalk-webhook"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// repo base info
|
// Repo `repo base info`
|
||||||
Repo struct {
|
Repo struct {
|
||||||
Owner string // providers the repository owner name
|
FullName string // repository full name
|
||||||
Name string // providers the repository name
|
|
||||||
Branch string // providers the default repository branch(e.g.master)
|
|
||||||
Link string // providers the repository http link
|
|
||||||
NameSpace string // providers the repository namespace(e.g.account owner)
|
|
||||||
Private bool // indicates the repository is public or private
|
|
||||||
Visibility string // providers the repository visibility level.Possible values are public,private and internal
|
|
||||||
SCM string // providers the repository version control system
|
|
||||||
FullName string // repository full name
|
|
||||||
}
|
}
|
||||||
// build info
|
|
||||||
|
// Build `build info`
|
||||||
Build struct {
|
Build struct {
|
||||||
Action string // document description not found
|
Status string // providers the current build status
|
||||||
Created float64 // providers the date and time when the build was created in the system
|
Link string // providers the current build link
|
||||||
Event string // providers the current build event
|
|
||||||
Number int // providers the current build number
|
|
||||||
Started float64 // providers the date and time when the build was started
|
|
||||||
Status string // providers the current build status
|
|
||||||
Link string // providers the current build link
|
|
||||||
}
|
}
|
||||||
// commit info
|
|
||||||
|
// Commit `commit info`
|
||||||
Commit struct {
|
Commit struct {
|
||||||
After string // providers the commit sha for the current build
|
|
||||||
Author string // providers the author username for the current commit
|
|
||||||
Before string // providers the parent commit sha for the current build
|
|
||||||
Branch string // providers the branch for the current commit
|
Branch string // providers the branch for the current commit
|
||||||
Link string // providers the http link to the current commit in the remote source code management system(e.g.GitHub)
|
Link string // providers the http link to the current commit in the remote source code management system(e.g.GitHub)
|
||||||
Message string // providers the commit message for the current build
|
Message string // providers the commit message for the current build
|
||||||
Ref string // providers the reference for the current build
|
|
||||||
Sha string // providers the commit sha for the current build
|
Sha string // providers the commit sha for the current build
|
||||||
// repo author info
|
Authors CommitAuthors
|
||||||
Authors struct {
|
|
||||||
Avatar string // providers the author avatar for the current commit
|
|
||||||
Email string // providers the author email for the current commit
|
|
||||||
Name string // providers the author name for the current commit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// git url info
|
|
||||||
Git struct {
|
// CommitAuthors `commit author info`
|
||||||
HttpUrl string // providers the repository git+http url
|
CommitAuthors struct {
|
||||||
SSHUrl string // providers the repository git+ssh url
|
Avatar string // providers the author avatar for the current commit
|
||||||
|
Email string // providers the author email for the current commit
|
||||||
|
Name string // providers the author name for the current commit
|
||||||
}
|
}
|
||||||
// Drone runner info
|
|
||||||
Runner struct {
|
// Drone `drone info`
|
||||||
Host string // providers the Drone agent hostname
|
Drone struct {
|
||||||
Hostname string // providers the Drone agent hostname
|
Repo Repo
|
||||||
Platform string // providers the Drone agent os and architecture
|
Build Build
|
||||||
Label string // document description not found
|
Commit Commit
|
||||||
}
|
}
|
||||||
// Drone system info
|
|
||||||
System struct {
|
// Config `plugin private config`
|
||||||
Host string // providers the Drone server hostname
|
|
||||||
Hostname string // providers the Drone server hostname
|
|
||||||
Version string // providers the Drone server version
|
|
||||||
}
|
|
||||||
// Drone CI Info
|
|
||||||
CI struct {
|
|
||||||
RepoLink string
|
|
||||||
}
|
|
||||||
// plugin private config
|
|
||||||
Config struct {
|
Config struct {
|
||||||
AccessToken string
|
Debug bool
|
||||||
Message string
|
AccessToken string
|
||||||
Lang string
|
IsAtALL bool
|
||||||
IsAtALL bool
|
Mobiles string
|
||||||
Mobiles string
|
Username string
|
||||||
Username string
|
MsgType string
|
||||||
AvatarURL string
|
}
|
||||||
MsgType string
|
|
||||||
|
// MessageConfig `DingTalk message struct`
|
||||||
|
MessageConfig struct {
|
||||||
|
ActionCard ActionCard
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActionCard `action card message struct`
|
||||||
|
ActionCard struct {
|
||||||
LinkUrls string
|
LinkUrls string
|
||||||
LinkTitles string
|
LinkTitles string
|
||||||
HideAvatar bool
|
HideAvatar bool
|
||||||
BtnOrientation bool
|
BtnOrientation bool
|
||||||
PicURL string
|
|
||||||
MsgURL string
|
|
||||||
SuccessPicUrl string
|
|
||||||
FailurePicUrl string
|
|
||||||
SuccessColor string
|
|
||||||
FailureColor string
|
|
||||||
WithColor bool
|
|
||||||
WithPic bool
|
|
||||||
LinkSha bool
|
|
||||||
}
|
}
|
||||||
// plugin all config
|
|
||||||
|
// Extra `extra variables`
|
||||||
|
Extra struct {
|
||||||
|
Color ExtraColor
|
||||||
|
Pic ExtraPic
|
||||||
|
LinkSha bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtraPic `extra config for pic`
|
||||||
|
ExtraPic struct {
|
||||||
|
WithPic bool
|
||||||
|
SuccessPicURL string
|
||||||
|
FailurePicURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtraColor `extra config for color`
|
||||||
|
ExtraColor struct {
|
||||||
|
WithColor bool
|
||||||
|
SuccessColor string
|
||||||
|
FailureColor string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin `plugin all config`
|
||||||
Plugin struct {
|
Plugin struct {
|
||||||
CI CI
|
Drone Drone
|
||||||
Git Git
|
Config Config
|
||||||
Runner Runner
|
Extra Extra
|
||||||
System System
|
|
||||||
Commit Commit
|
|
||||||
Repo Repo
|
|
||||||
Build Build
|
|
||||||
Config Config
|
|
||||||
WebHook *WebHook
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Exec `execute webhook`
|
||||||
func (p *Plugin) Exec() error {
|
func (p *Plugin) Exec() error {
|
||||||
log.Println("start execute sending...")
|
var err error
|
||||||
if 0 == len(p.Config.AccessToken) {
|
if 0 == len(p.Config.AccessToken) {
|
||||||
msg := "missing dingtalk access token"
|
msg := "missing dingtalk access token"
|
||||||
log.Println(msg)
|
|
||||||
return errors.New(msg)
|
return errors.New(msg)
|
||||||
}
|
}
|
||||||
log.Println("access token pass...")
|
|
||||||
p.WebHook = NewWebHook(p.Config.AccessToken)
|
if 6 > len(p.Drone.Commit.Sha) {
|
||||||
|
return errors.New("commit sha cannot short than 6")
|
||||||
|
}
|
||||||
|
|
||||||
|
newWebhook := webhook.NewWebHook(p.Config.AccessToken)
|
||||||
mobiles := strings.Split(p.Config.Mobiles, ",")
|
mobiles := strings.Split(p.Config.Mobiles, ",")
|
||||||
linkUrls := strings.Split(p.Config.LinkUrls, ",")
|
|
||||||
linkTitles := strings.Split(p.Config.LinkTitles, ",")
|
|
||||||
log.Println("sending message type: " + p.Config.MsgType)
|
|
||||||
switch strings.ToLower(p.Config.MsgType) {
|
switch strings.ToLower(p.Config.MsgType) {
|
||||||
case "markdown":
|
case "markdown":
|
||||||
err := p.WebHook.SendMarkdownMsg(
|
err = newWebhook.SendMarkdownMsg("You have a new message...", p.baseTpl(), p.Config.IsAtALL, mobiles...)
|
||||||
"You have a new message...",
|
|
||||||
p.baseTpl(),
|
|
||||||
p.Config.IsAtALL,
|
|
||||||
mobiles...
|
|
||||||
)
|
|
||||||
if nil != err {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "text":
|
case "text":
|
||||||
err := p.WebHook.SendTextMsg(p.baseTpl(), p.Config.IsAtALL, mobiles...)
|
err = newWebhook.SendTextMsg(p.baseTpl(), p.Config.IsAtALL, mobiles...)
|
||||||
if nil != err {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "actioncard":
|
|
||||||
err := p.WebHook.SendActionCardMsg(
|
|
||||||
"A actionCard title",
|
|
||||||
p.baseTpl(),
|
|
||||||
linkUrls,
|
|
||||||
linkTitles,
|
|
||||||
p.Config.HideAvatar,
|
|
||||||
p.Config.BtnOrientation,
|
|
||||||
)
|
|
||||||
if nil != err {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "link":
|
case "link":
|
||||||
err := p.WebHook.SendLinkMsg(p.Build.Status, p.baseTpl(), p.Commit.Authors.Avatar, p.Build.Link)
|
err = newWebhook.SendLinkMsg(p.Drone.Build.Status, p.baseTpl(), p.Drone.Commit.Authors.Avatar, p.Drone.Build.Link)
|
||||||
if nil != err {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
msg := "not support message type"
|
msg := "not support message type"
|
||||||
log.Println(msg)
|
err = errors.New(msg)
|
||||||
return errors.New(msg)
|
|
||||||
}
|
}
|
||||||
log.Println("send " + p.Config.MsgType + " message success!")
|
|
||||||
return nil
|
if err == nil {
|
||||||
|
log.Println("send message success!")
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// markdownTpl `output the tpl of markdown`
|
||||||
func (p *Plugin) markdownTpl() string {
|
func (p *Plugin) markdownTpl() string {
|
||||||
var tpl string
|
var tpl string
|
||||||
|
|
||||||
// title
|
// title
|
||||||
title := fmt.Sprintf(" %s *Branch Build %s*",
|
title := fmt.Sprintf(" %s *Branch Build %s*",
|
||||||
strings.Title(p.Commit.Branch),
|
strings.Title(p.Drone.Commit.Branch),
|
||||||
strings.Title(p.Build.Status))
|
strings.Title(p.Drone.Build.Status))
|
||||||
// with color on title
|
// with color on title
|
||||||
if p.Config.WithColor {
|
if p.Extra.Color.WithColor {
|
||||||
title = fmt.Sprintf("<font color=%s>%s</font>", p.getColor(), title)
|
title = fmt.Sprintf("<font color=%s>%s</font>", p.getColor(), title)
|
||||||
}
|
}
|
||||||
|
|
||||||
tpl = fmt.Sprintf("# %s \n", title)
|
tpl = fmt.Sprintf("# %s \n", title)
|
||||||
|
|
||||||
// with pic
|
// with pic
|
||||||
if p.Config.WithPic {
|
if p.Extra.Pic.WithPic {
|
||||||
tpl += fmt.Sprintf("\n\n",
|
tpl += fmt.Sprintf("\n\n",
|
||||||
p.Build.Status,
|
p.Drone.Build.Status,
|
||||||
p.getPicUrl())
|
p.getPicURL())
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit message
|
// commit message
|
||||||
commitMsg := fmt.Sprintf("%s", p.Commit.Message)
|
commitMsg := fmt.Sprintf("%s", p.Drone.Commit.Message)
|
||||||
if p.Config.WithColor {
|
if p.Extra.Color.WithColor {
|
||||||
commitMsg = fmt.Sprintf("<font color=%s>%s</font>", p.getColor(), commitMsg)
|
commitMsg = fmt.Sprintf("<font color=%s>%s</font>", p.getColor(), commitMsg)
|
||||||
}
|
}
|
||||||
tpl += commitMsg + "\n\n"
|
tpl += commitMsg + "\n\n"
|
||||||
|
|
||||||
// sha info
|
// sha info
|
||||||
commitSha := p.Commit.Sha
|
commitSha := p.Drone.Commit.Sha
|
||||||
if p.Config.LinkSha {
|
if p.Extra.LinkSha {
|
||||||
commitSha = fmt.Sprintf("[Click To %s Commit Detail Page](%s)", commitSha[:6], p.Commit.Link)
|
commitSha = fmt.Sprintf("[Click To %s Commit Detail Page](%s)", commitSha[:6], p.Drone.Commit.Link)
|
||||||
}
|
}
|
||||||
tpl += commitSha + "\n\n"
|
tpl += commitSha + "\n\n"
|
||||||
|
|
||||||
// author info
|
// author info
|
||||||
authorInfo := fmt.Sprintf("`%s(%s)`", p.Commit.Authors.Name, p.Commit.Authors.Email)
|
authorInfo := fmt.Sprintf("`%s(%s)`", p.Drone.Commit.Authors.Name, p.Drone.Commit.Authors.Email)
|
||||||
tpl += authorInfo + "\n\n"
|
tpl += authorInfo + "\n\n"
|
||||||
|
|
||||||
// build detail link
|
// build detail link
|
||||||
buildDetail := fmt.Sprintf("[Click To The Build Detail Page %s](%s)",
|
buildDetail := fmt.Sprintf("[Click To The Build Detail Page %s](%s)",
|
||||||
p.getEmoticon(),
|
p.getEmoticon(),
|
||||||
p.Build.Link)
|
p.Drone.Build.Link)
|
||||||
tpl += buildDetail
|
tpl += buildDetail
|
||||||
return tpl
|
return tpl
|
||||||
}
|
}
|
||||||
@@ -224,20 +188,20 @@ func (p *Plugin) baseTpl() string {
|
|||||||
@%s
|
@%s
|
||||||
%s (%s)
|
%s (%s)
|
||||||
`,
|
`,
|
||||||
p.Build.Status,
|
p.Drone.Build.Status,
|
||||||
strings.TrimSpace(p.Commit.Message),
|
strings.TrimSpace(p.Drone.Commit.Message),
|
||||||
p.Repo.FullName,
|
p.Drone.Repo.FullName,
|
||||||
p.Commit.Branch,
|
p.Drone.Commit.Branch,
|
||||||
p.Commit.Sha,
|
p.Drone.Commit.Sha,
|
||||||
p.Commit.Authors.Name,
|
p.Drone.Commit.Authors.Name,
|
||||||
p.Commit.Authors.Email)
|
p.Drone.Commit.Authors.Email)
|
||||||
case "link":
|
case "link":
|
||||||
tpl = fmt.Sprintf(`%s(%s) @%s %s(%s)`,
|
tpl = fmt.Sprintf(`%s(%s) @%s %s(%s)`,
|
||||||
p.Repo.FullName,
|
p.Drone.Repo.FullName,
|
||||||
p.Commit.Branch,
|
p.Drone.Commit.Branch,
|
||||||
p.Commit.Sha[:6],
|
p.Drone.Commit.Sha[:6],
|
||||||
p.Commit.Authors.Name,
|
p.Drone.Commit.Authors.Name,
|
||||||
p.Commit.Authors.Email)
|
p.Drone.Commit.Authors.Email)
|
||||||
case "actionCard":
|
case "actionCard":
|
||||||
// coming soon
|
// coming soon
|
||||||
|
|
||||||
@@ -248,13 +212,13 @@ func (p *Plugin) baseTpl() string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
get emoticon
|
get emoticon
|
||||||
*/
|
*/
|
||||||
func (p *Plugin) getEmoticon() string {
|
func (p *Plugin) getEmoticon() string {
|
||||||
emoticons := make(map[string]string)
|
emoticons := make(map[string]string)
|
||||||
emoticons["success"] = ":)"
|
emoticons["success"] = ":)"
|
||||||
emoticons["failure"] = ":("
|
emoticons["failure"] = ":("
|
||||||
|
|
||||||
emoticon, ok := emoticons[p.Build.Status]
|
emoticon, ok := emoticons[p.Drone.Build.Status]
|
||||||
if ok {
|
if ok {
|
||||||
return emoticon
|
return emoticon
|
||||||
}
|
}
|
||||||
@@ -264,21 +228,21 @@ func (p *Plugin) getEmoticon() string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
get picture url
|
get picture url
|
||||||
*/
|
*/
|
||||||
func (p *Plugin) getPicUrl() string {
|
func (p *Plugin) getPicURL() string {
|
||||||
pics := make(map[string]string)
|
pics := make(map[string]string)
|
||||||
// success picture url
|
// success picture url
|
||||||
pics["success"] = "https://ws4.sinaimg.cn/large/006tNc79gy1fz05g5a7utj30he0bfjry.jpg"
|
pics["success"] = "https://ws4.sinaimg.cn/large/006tNc79gy1fz05g5a7utj30he0bfjry.jpg"
|
||||||
if p.Config.SuccessPicUrl != "" {
|
if p.Extra.Pic.SuccessPicURL != "" {
|
||||||
pics["success"] = p.Config.SuccessPicUrl
|
pics["success"] = p.Extra.Pic.SuccessPicURL
|
||||||
}
|
}
|
||||||
// failure picture url
|
// failure picture url
|
||||||
pics["failure"] = "https://ws1.sinaimg.cn/large/006tNc79gy1fz0b4fghpnj30hd0bdmxn.jpg"
|
pics["failure"] = "https://ws1.sinaimg.cn/large/006tNc79gy1fz0b4fghpnj30hd0bdmxn.jpg"
|
||||||
if p.Config.FailurePicUrl != "" {
|
if p.Extra.Pic.FailurePicURL != "" {
|
||||||
pics["failure"] = p.Config.FailurePicUrl
|
pics["failure"] = p.Extra.Pic.FailurePicURL
|
||||||
}
|
}
|
||||||
|
|
||||||
url, ok := pics[p.Build.Status]
|
url, ok := pics[p.Drone.Build.Status]
|
||||||
if ok {
|
if ok {
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
@@ -288,21 +252,21 @@ func (p *Plugin) getPicUrl() string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
get color for message title
|
get color for message title
|
||||||
*/
|
*/
|
||||||
func (p *Plugin) getColor() string {
|
func (p *Plugin) getColor() string {
|
||||||
colors := make(map[string]string)
|
colors := make(map[string]string)
|
||||||
// success color
|
// success color
|
||||||
colors["success"] = "#008000"
|
colors["success"] = "#008000"
|
||||||
if p.Config.SuccessColor != "" {
|
if p.Extra.Color.SuccessColor != "" {
|
||||||
colors["success"] = "#" + p.Config.SuccessColor
|
colors["success"] = "#" + p.Extra.Color.SuccessColor
|
||||||
}
|
}
|
||||||
// failure color
|
// failure color
|
||||||
colors["failure"] = "#FF0000"
|
colors["failure"] = "#FF0000"
|
||||||
if p.Config.FailureColor != "" {
|
if p.Extra.Color.FailureColor != "" {
|
||||||
colors["failure"] = "#" + p.Config.FailureColor
|
colors["failure"] = "#" + p.Extra.Color.FailureColor
|
||||||
}
|
}
|
||||||
|
|
||||||
color, ok := colors[p.Build.Status]
|
color, ok := colors[p.Drone.Build.Status]
|
||||||
if ok {
|
if ok {
|
||||||
return color
|
return color
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPlugin(t *testing.T) {
|
||||||
|
p := Plugin{}
|
||||||
|
err := p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("access token empty error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Config.AccessToken = "example-access-token"
|
||||||
|
err = p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("commit sha length error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Drone.Commit.Sha = "53729847dfksj"
|
||||||
|
err = p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("not support message type error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Config.MsgType = "text"
|
||||||
|
err = p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("access token invalid error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Config.MsgType = "link"
|
||||||
|
err = p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("access token invalid error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Extra.Color.WithColor = true
|
||||||
|
p.Extra.Color.FailureColor = "#555555"
|
||||||
|
p.Extra.Color.SuccessColor = "#222222"
|
||||||
|
p.Extra.Pic.WithPic = true
|
||||||
|
p.Extra.Pic.FailurePicURL = "https://www.baidu.com"
|
||||||
|
p.Extra.Pic.SuccessPicURL = "https://www.baidu.com"
|
||||||
|
p.Extra.LinkSha = true
|
||||||
|
// p.Drone.Build.Status = "failure"
|
||||||
|
p.Config.MsgType = "markdown"
|
||||||
|
err = p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("access token invalid error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Drone.Build.Status = "failure"
|
||||||
|
err = p.Exec()
|
||||||
|
if nil == err {
|
||||||
|
t.Error("access token invalid error should be catch!")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("plugin testing finished")
|
||||||
|
}
|
||||||
-241
@@ -1,241 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// link message struct
|
|
||||||
type LinkMsg struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
MessageURL string `json:"messageURL"`
|
|
||||||
PicURL string `json:"picURL"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// action card message struct
|
|
||||||
type ActionCard struct {
|
|
||||||
Text string `json:"text"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
SingleTitle string `json:"singleTitle"`
|
|
||||||
SingleURL string `json:"singleURL"`
|
|
||||||
BtnOrientation string `json:"btnOrientation"`
|
|
||||||
HideAvatar string `json:"hideAvatar"` // robot message avatar
|
|
||||||
Buttons []struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
ActionURL string `json:"actionURL"`
|
|
||||||
} `json:"btns"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// payload
|
|
||||||
type PayLoad struct {
|
|
||||||
MsgType string `json:"msgtype"`
|
|
||||||
Text struct {
|
|
||||||
Content string `json:"content"`
|
|
||||||
} `json:"text"`
|
|
||||||
Link struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
PicUrl string `json:"picUrl"`
|
|
||||||
MessageUrl string `json:"messageUrl"`
|
|
||||||
} `json:"link"`
|
|
||||||
Markdown struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
} `json:"markdown"`
|
|
||||||
ActionCard ActionCard `json:"actionCard"`
|
|
||||||
FeedCard struct {
|
|
||||||
Links []LinkMsg `json:"links"`
|
|
||||||
} `json:"feedCard"`
|
|
||||||
At struct {
|
|
||||||
AtMobiles []string `json:"atMobiles"`
|
|
||||||
IsAtAll bool `json:"isAtAll"`
|
|
||||||
} `json:"at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// web hook base config
|
|
||||||
type WebHook struct {
|
|
||||||
AccessToken string `json:"accessToken"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWebHook(accessToken string) *WebHook {
|
|
||||||
return &WebHook{AccessToken: accessToken}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Response struct {
|
|
||||||
ErrorCode int `json:"errcode"`
|
|
||||||
ErrorMessage string `json:"errmsg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var baseApi = "https://oapi.dingtalk.com/robot/send?access_token="
|
|
||||||
var reg = `^1([38][0-9]|14[57]|5[^4])\d{8}$`
|
|
||||||
var regx = regexp.MustCompile(reg)
|
|
||||||
|
|
||||||
// real send request to api
|
|
||||||
func (w *WebHook) sendPayload(payload *PayLoad) error {
|
|
||||||
// get config
|
|
||||||
bs, err := json.Marshal(payload)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// request api
|
|
||||||
resp, err := http.Post(baseApi+w.AccessToken, "application/json", bytes.NewReader(bs))
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// read response body
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// api unusual
|
|
||||||
if 200 != resp.StatusCode {
|
|
||||||
return fmt.Errorf("%d: %s", resp.StatusCode, string(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
var result Response
|
|
||||||
// json decode
|
|
||||||
err = json.Unmarshal(body, &result)
|
|
||||||
if nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if 0 != result.ErrorCode {
|
|
||||||
return fmt.Errorf("%d: %s", result.ErrorCode, result.ErrorMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// text message
|
|
||||||
func (w *WebHook) SendTextMsg(content string, isAtAll bool, mobiles ...string) error {
|
|
||||||
// send request
|
|
||||||
return w.sendPayload(&PayLoad{
|
|
||||||
MsgType: "text",
|
|
||||||
Text: struct {
|
|
||||||
Content string `json:"content"`
|
|
||||||
}{
|
|
||||||
Content: content,
|
|
||||||
},
|
|
||||||
At: struct {
|
|
||||||
AtMobiles []string `json:"atMobiles"`
|
|
||||||
IsAtAll bool `json:"isAtAll"`
|
|
||||||
}{
|
|
||||||
AtMobiles: mobiles,
|
|
||||||
IsAtAll: isAtAll,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// with link message
|
|
||||||
func (w *WebHook) SendLinkMsg(title, content, picURL, msgURL string) error {
|
|
||||||
return w.sendPayload(&PayLoad{
|
|
||||||
MsgType: "link",
|
|
||||||
Link: struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
PicUrl string `json:"picUrl"`
|
|
||||||
MessageUrl string `json:"messageUrl"`
|
|
||||||
}{
|
|
||||||
Title: title,
|
|
||||||
Text: content,
|
|
||||||
PicUrl: picURL,
|
|
||||||
MessageUrl: msgURL,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// send markdown msg
|
|
||||||
func (w *WebHook) SendMarkdownMsg(title, content string, isAtAll bool, mobiles ...string) error {
|
|
||||||
firstLine := false
|
|
||||||
for _, mobile := range mobiles {
|
|
||||||
if regx.MatchString(mobile) {
|
|
||||||
if false == firstLine {
|
|
||||||
content += "#####"
|
|
||||||
}
|
|
||||||
content += " @" + mobile
|
|
||||||
firstLine = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// send request
|
|
||||||
return w.sendPayload(&PayLoad{
|
|
||||||
MsgType: "markdown",
|
|
||||||
Markdown: struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
}{
|
|
||||||
Title: title,
|
|
||||||
Text: content,
|
|
||||||
},
|
|
||||||
At: struct {
|
|
||||||
AtMobiles []string `json:"atMobiles"`
|
|
||||||
IsAtAll bool `json:"isAtAll"`
|
|
||||||
}{
|
|
||||||
AtMobiles: mobiles,
|
|
||||||
IsAtAll: isAtAll,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// send single action card
|
|
||||||
func (w *WebHook) SendActionCardMsg(title, content string, linkTitles, linkUrls []string, hideAvatar, btnOrientation bool) error {
|
|
||||||
// validation is empty
|
|
||||||
if 0 == len(linkTitles) || 0 == len(linkUrls) {
|
|
||||||
return errors.New("links or titles is empty!")
|
|
||||||
}
|
|
||||||
// validation is equal
|
|
||||||
if len(linkUrls) != len(linkTitles) {
|
|
||||||
return errors.New("links length and titles length is not equal!")
|
|
||||||
}
|
|
||||||
// hide robot avatar
|
|
||||||
var strHideAvatar = "0"
|
|
||||||
if hideAvatar {
|
|
||||||
strHideAvatar = "1"
|
|
||||||
}
|
|
||||||
// button sort
|
|
||||||
var strBtnOrientation = "0"
|
|
||||||
if btnOrientation {
|
|
||||||
strBtnOrientation = "1"
|
|
||||||
}
|
|
||||||
// button struct
|
|
||||||
var buttons []struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
ActionURL string `json:"actionURL"`
|
|
||||||
}
|
|
||||||
// inject to button
|
|
||||||
for i := 0; i < len(linkTitles); i++ {
|
|
||||||
buttons = append(buttons, struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
ActionURL string `json:"actionURL"`
|
|
||||||
}{
|
|
||||||
Title: linkTitles[i],
|
|
||||||
ActionURL: linkUrls[i],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// send request
|
|
||||||
return w.sendPayload(&PayLoad{
|
|
||||||
MsgType: "actionCard",
|
|
||||||
ActionCard: ActionCard{
|
|
||||||
Title: title,
|
|
||||||
Text: content,
|
|
||||||
HideAvatar: strHideAvatar,
|
|
||||||
BtnOrientation: strBtnOrientation,
|
|
||||||
Buttons: buttons,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// send link card message
|
|
||||||
func (w *WebHook) SendLinkCardMsg(messages []LinkMsg) error {
|
|
||||||
return w.sendPayload(&PayLoad{
|
|
||||||
MsgType: "feedCard",
|
|
||||||
FeedCard: struct {
|
|
||||||
Links []LinkMsg `json:"links"`
|
|
||||||
}{
|
|
||||||
Links: messages,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user