diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2020-02-12 16:48:28 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-12 08:48:28 +0000 |
commit | 83a8944fcf64af9bf5b0a4e233f9a7f917838a4d (patch) | |
tree | ebb4436506a4e36939fcfa358ccb09dfd3a01d3a /modules | |
parent | ea7ad382e78486fc881bf46d9c1c004e3f311163 (diff) | |
download | gitea-83a8944fcf64af9bf5b0a4e233f9a7f917838a4d.tar.gz gitea-83a8944fcf64af9bf5b0a4e233f9a7f917838a4d.zip |
Add feishu webhook support (#10229)
Add feishu webhook support
Diffstat (limited to 'modules')
-rw-r--r-- | modules/auth/repo_form.go | 11 | ||||
-rw-r--r-- | modules/setting/webhook.go | 2 | ||||
-rw-r--r-- | modules/structs/hook.go | 2 | ||||
-rw-r--r-- | modules/webhook/feishu.go | 201 | ||||
-rw-r--r-- | modules/webhook/webhook.go | 5 |
5 files changed, 219 insertions, 2 deletions
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index a5071de47e..932976b6f9 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -313,6 +313,17 @@ func (f *NewMSTeamsHookForm) Validate(ctx *macaron.Context, errs binding.Errors) return validate(errs, ctx.Data, f, ctx.Locale) } +// NewFeishuHookForm form for creating feishu hook +type NewFeishuHookForm struct { + PayloadURL string `binding:"Required;ValidUrl"` + WebhookForm +} + +// Validate validates the fields +func (f *NewFeishuHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { + return validate(errs, ctx.Data, f, ctx.Locale) +} + // .___ // | | ______ ________ __ ____ // | |/ ___// ___/ | \_/ __ \ diff --git a/modules/setting/webhook.go b/modules/setting/webhook.go index 4a953616f1..3e6040a605 100644 --- a/modules/setting/webhook.go +++ b/modules/setting/webhook.go @@ -36,7 +36,7 @@ func newWebhookService() { Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000) Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5) Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool() - Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams"} + Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu"} Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10) Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("") if Webhook.ProxyURL != "" { diff --git a/modules/structs/hook.go b/modules/structs/hook.go index 7ec46254eb..f2bc4f16e1 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -41,7 +41,7 @@ type CreateHookOptionConfig map[string]string // CreateHookOption options when create a hook type CreateHookOption struct { // required: true - // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram + // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu Type string `json:"type" binding:"Required"` // required: true Config CreateHookOptionConfig `json:"config" binding:"Required"` diff --git a/modules/webhook/feishu.go b/modules/webhook/feishu.go new file mode 100644 index 0000000000..6af78494c9 --- /dev/null +++ b/modules/webhook/feishu.go @@ -0,0 +1,201 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package webhook + +import ( + "encoding/json" + "fmt" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + api "code.gitea.io/gitea/modules/structs" +) + +type ( + // FeishuPayload represents + FeishuPayload struct { + Title string `json:"title"` + Text string `json:"text"` + } +) + +// SetSecret sets the Feishu secret +func (p *FeishuPayload) SetSecret(_ string) {} + +// JSONPayload Marshals the FeishuPayload to json +func (p *FeishuPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(p, "", " ") + if err != nil { + return []byte{}, err + } + return data, nil +} + +func getFeishuCreatePayload(p *api.CreatePayload) (*FeishuPayload, error) { + // created tag/branch + refName := git.RefEndName(p.Ref) + title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName) + + return &FeishuPayload{ + Text: title, + Title: title, + }, nil +} + +func getFeishuDeletePayload(p *api.DeletePayload) (*FeishuPayload, error) { + // created tag/branch + refName := git.RefEndName(p.Ref) + title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName) + + return &FeishuPayload{ + Text: title, + Title: title, + }, nil +} + +func getFeishuForkPayload(p *api.ForkPayload) (*FeishuPayload, error) { + title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName) + + return &FeishuPayload{ + Text: title, + Title: title, + }, nil +} + +func getFeishuPushPayload(p *api.PushPayload) (*FeishuPayload, error) { + var ( + branchName = git.RefEndName(p.Ref) + commitDesc string + ) + + title := fmt.Sprintf("[%s:%s] %s", p.Repo.FullName, branchName, commitDesc) + + var text string + // for each commit, generate attachment text + for i, commit := range p.Commits { + var authorName string + if commit.Author != nil { + authorName = " - " + commit.Author.Name + } + text += fmt.Sprintf("[%s](%s) %s", commit.ID[:7], commit.URL, + strings.TrimRight(commit.Message, "\r\n")) + authorName + // add linebreak to each commit but the last + if i < len(p.Commits)-1 { + text += "\n" + } + } + + return &FeishuPayload{ + Text: text, + Title: title, + }, nil +} + +func getFeishuIssuesPayload(p *api.IssuePayload) (*FeishuPayload, error) { + text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true) + + return &FeishuPayload{ + Text: text + "\r\n\r\n" + attachmentText, + Title: issueTitle, + }, nil +} + +func getFeishuIssueCommentPayload(p *api.IssueCommentPayload) (*FeishuPayload, error) { + text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true) + + return &FeishuPayload{ + Text: text + "\r\n\r\n" + p.Comment.Body, + Title: issueTitle, + }, nil +} + +func getFeishuPullRequestPayload(p *api.PullRequestPayload) (*FeishuPayload, error) { + text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true) + + return &FeishuPayload{ + Text: text + "\r\n\r\n" + attachmentText, + Title: issueTitle, + }, nil +} + +func getFeishuPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*FeishuPayload, error) { + var text, title string + switch p.Action { + case api.HookIssueSynchronized: + action, err := parseHookPullRequestEventType(event) + if err != nil { + return nil, err + } + + title = fmt.Sprintf("[%s] Pull request review %s : #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title) + text = p.Review.Content + + } + + return &FeishuPayload{ + Text: title + "\r\n\r\n" + text, + Title: title, + }, nil +} + +func getFeishuRepositoryPayload(p *api.RepositoryPayload) (*FeishuPayload, error) { + var title string + switch p.Action { + case api.HookRepoCreated: + title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName) + return &FeishuPayload{ + Text: title, + Title: title, + }, nil + case api.HookRepoDeleted: + title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) + return &FeishuPayload{ + Title: title, + Text: title, + }, nil + } + + return nil, nil +} + +func getFeishuReleasePayload(p *api.ReleasePayload) (*FeishuPayload, error) { + text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true) + + return &FeishuPayload{ + Text: text, + Title: text, + }, nil +} + +// GetFeishuPayload converts a ding talk webhook into a FeishuPayload +func GetFeishuPayload(p api.Payloader, event models.HookEventType, meta string) (*FeishuPayload, error) { + s := new(FeishuPayload) + + switch event { + case models.HookEventCreate: + return getFeishuCreatePayload(p.(*api.CreatePayload)) + case models.HookEventDelete: + return getFeishuDeletePayload(p.(*api.DeletePayload)) + case models.HookEventFork: + return getFeishuForkPayload(p.(*api.ForkPayload)) + case models.HookEventIssues: + return getFeishuIssuesPayload(p.(*api.IssuePayload)) + case models.HookEventIssueComment: + return getFeishuIssueCommentPayload(p.(*api.IssueCommentPayload)) + case models.HookEventPush: + return getFeishuPushPayload(p.(*api.PushPayload)) + case models.HookEventPullRequest: + return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) + case models.HookEventPullRequestApproved, models.HookEventPullRequestRejected, models.HookEventPullRequestComment: + return getFeishuPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) + case models.HookEventRepository: + return getFeishuRepositoryPayload(p.(*api.RepositoryPayload)) + case models.HookEventRelease: + return getFeishuReleasePayload(p.(*api.ReleasePayload)) + } + + return s, nil +} diff --git a/modules/webhook/webhook.go b/modules/webhook/webhook.go index 410e47461f..2fab0803bc 100644 --- a/modules/webhook/webhook.go +++ b/modules/webhook/webhook.go @@ -114,6 +114,11 @@ func prepareWebhook(w *models.Webhook, repo *models.Repository, event models.Hoo if err != nil { return fmt.Errorf("GetMSTeamsPayload: %v", err) } + case models.FEISHU: + payloader, err = GetFeishuPayload(p, event, w.Meta) + if err != nil { + return fmt.Errorf("GetFeishuPayload: %v", err) + } default: p.SetSecret(w.Secret) payloader = p |