diff --git a/models/webhook.go b/models/webhook.go index 54cd9b6565841..26701900645e5 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -560,18 +560,20 @@ const ( MSTEAMS FEISHU MATRIX + WORKWECHAT ) var hookTaskTypes = map[string]HookTaskType{ - "gitea": GITEA, - "gogs": GOGS, - "slack": SLACK, - "discord": DISCORD, - "dingtalk": DINGTALK, - "telegram": TELEGRAM, - "msteams": MSTEAMS, - "feishu": FEISHU, - "matrix": MATRIX, + "gitea": GITEA, + "gogs": GOGS, + "slack": SLACK, + "discord": DISCORD, + "dingtalk": DINGTALK, + "telegram": TELEGRAM, + "msteams": MSTEAMS, + "feishu": FEISHU, + "matrix": MATRIX, + "workwechat": WORKWECHAT, } // ToHookTaskType returns HookTaskType by given name. @@ -600,6 +602,8 @@ func (t HookTaskType) Name() string { return "feishu" case MATRIX: return "matrix" + case WORKWECHAT: + return "workwechat" } return "" } diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index 039b0cb583a09..14eee7adb4d10 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -359,6 +359,18 @@ func (f *NewFeishuHookForm) Validate(ctx *macaron.Context, errs binding.Errors) return validate(errs, ctx.Data, f, ctx.Locale) } +// NewWorkwechatHookForm form for creating work wechat hook +type NewWorkwechatHookForm struct { + PayloadURL string `binding:"Required;ValidUrl"` + ChatID string `form:"chatid"` + WebhookForm +} + +// Validate validates the fields +func (f *NewWorkwechatHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { + return validate(errs, ctx.Data, f, ctx.Locale) +} + // .___ // | | ______ ________ __ ____ // | |/ ___// ___/ | \_/ __ \ diff --git a/modules/convert/convert.go b/modules/convert/convert.go index ec676002b93f7..1c593f29fafab 100644 --- a/modules/convert/convert.go +++ b/modules/convert/convert.go @@ -230,6 +230,9 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook { config["username"] = s.Username config["icon_url"] = s.IconURL config["color"] = s.Color + } else if w.HookTaskType == models.WORKWECHAT { + we := webhook.GetWorkwechatHook(w) + config["chatid"] = we.ChatID } return &api.Hook{ diff --git a/modules/webhook/webhook.go b/modules/webhook/webhook.go index 2ef150210e71c..44cc019ca46a0 100644 --- a/modules/webhook/webhook.go +++ b/modules/webhook/webhook.go @@ -132,6 +132,11 @@ func prepareWebhook(w *models.Webhook, repo *models.Repository, event models.Hoo if err != nil { return fmt.Errorf("GetMatrixPayload: %v", err) } + case models.WORKWECHAT: + payloader, err = GetWorkwechatPayload(p, event, w.Meta) + if err != nil { + return fmt.Errorf("GetWorkwechatPayload: %v", err) + } default: p.SetSecret(w.Secret) payloader = p diff --git a/modules/webhook/workwechat.go b/modules/webhook/workwechat.go new file mode 100644 index 0000000000000..83a6322f6a925 --- /dev/null +++ b/modules/webhook/workwechat.go @@ -0,0 +1,287 @@ +// Copyright 2018 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" + "errors" + "fmt" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + api "code.gitea.io/gitea/modules/structs" +) + +type ( + // Text message + Text struct { + Content string `json:"content"` + } + + //TextCard message + TextCard struct { + Title string `json:"title"` + Description string `json:"description"` + URL string `json:"url"` + ButtonText string `json:"btntxt"` + } + //WorkwechatPayload represents + WorkwechatPayload struct { + ChatID string `json:"chatid"` + MsgType string `json:"msgtype"` + Text Text `json:"text"` + TextCard TextCard `json:"textcard"` + Safe int `json:"safe"` + } + + // WorkwechatMeta contains the work wechat metadata + WorkwechatMeta struct { + ChatID string `json:"chatid"` + } +) + +// GetWorkwechatHook returns workwechat metadata +func GetWorkwechatHook(w *models.Webhook) *WorkwechatMeta { + we := &WorkwechatMeta{} + if err := json.Unmarshal([]byte(w.Meta), we); err != nil { + log.Error("webhook.GetWorkwechatHook(%d): %v", w.ID, err) + } + return we +} + +// SetSecret sets the workwechat secret +func (p *WorkwechatPayload) SetSecret(_ string) {} + +// JSONPayload Marshals the WorkwechatPayload to json +func (p *WorkwechatPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(p, "", " ") + if err != nil { + return []byte{}, err + } + return data, nil +} + +func getWorkwechatCreatePayload(p *api.CreatePayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + // created tag/branch + refName := git.RefEndName(p.Ref) + title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Title: title, + Description: title, + ButtonText: fmt.Sprintf("view ref %s", refName), + URL: p.Repo.HTMLURL + "/src/" + refName, + }, + }, nil +} + +func getWorkwechatDeletePayload(p *api.DeletePayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + // created tag/branch + refName := git.RefEndName(p.Ref) + title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Title: title, + Description: title, + ButtonText: fmt.Sprintf("view ref %s", refName), + URL: p.Repo.HTMLURL + "/src/" + refName, + }, + }, nil +} + +func getWorkwechatForkPayload(p *api.ForkPayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: title, + Title: title, + ButtonText: fmt.Sprintf("view forked repo %s", p.Repo.FullName), + URL: p.Repo.HTMLURL, + }, + }, nil +} + +func getWorkwechatPushPayload(p *api.PushPayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + var ( + branchName = git.RefEndName(p.Ref) + commitDesc string + ) + + var titleLink, linkText string + if len(p.Commits) == 1 { + commitDesc = "1 new commit" + titleLink = p.Commits[0].URL + linkText = fmt.Sprintf("view commit %s", p.Commits[0].ID[:7]) + } else { + commitDesc = fmt.Sprintf("%d new commits", len(p.Commits)) + titleLink = p.CompareURL + linkText = fmt.Sprintf("view commit %s...%s", p.Commits[0].ID[:7], p.Commits[len(p.Commits)-1].ID[:7]) + } + if titleLink == "" { + titleLink = p.Repo.HTMLURL + "/src/" + branchName + } + + 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 &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: text, + Title: title, + ButtonText: linkText, + URL: titleLink, + }, + }, nil +} + +func getWorkwechatIssuesPayload(p *api.IssuePayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: text + "\r\n\r\n" + attachmentText, + Title: issueTitle, + ButtonText: "view issue", + URL: p.Issue.URL, + }, + }, nil +} + +func getWorkwechatIssueCommentPayload(p *api.IssueCommentPayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: text + "\r\n\r\n" + p.Comment.Body, + Title: issueTitle, + ButtonText: "view issue comment", + URL: p.Comment.HTMLURL, + }, + }, nil +} + +func getWorkwechatPullRequestPayload(p *api.PullRequestPayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: text + "\r\n\r\n" + attachmentText, + Title: issueTitle, + ButtonText: "view pull request", + URL: p.PullRequest.HTMLURL, + }, + }, nil +} + +func getWorkwechatRepositoryPayload(p *api.RepositoryPayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + var title, url string + switch p.Action { + case api.HookRepoCreated: + title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName) + url = p.Repository.HTMLURL + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: title, + Title: title, + ButtonText: "view repository", + URL: url, + }, + }, nil + case api.HookRepoDeleted: + title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) + return &WorkwechatPayload{ + MsgType: "text", + Text: struct { + Content string `json:"content"` + }{ + Content: title, + }, + }, nil + } + + return nil, nil +} + +func getWorkwechatReleasePayload(p *api.ReleasePayload, meta *WorkwechatMeta) (*WorkwechatPayload, error) { + text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true) + + return &WorkwechatPayload{ + ChatID: meta.ChatID, + MsgType: "textcard", + TextCard: TextCard{ + Description: text, + Title: text, + ButtonText: "view release", + URL: p.Release.URL, + }, + }, nil +} + +// GetWorkwechatPayload converts a work wechat webhook into a WorkwechatPayload +func GetWorkwechatPayload(p api.Payloader, event models.HookEventType, meta string) (*WorkwechatPayload, error) { + s := new(WorkwechatPayload) + + workwechatMeta := &WorkwechatMeta{} + if err := json.Unmarshal([]byte(meta), &workwechatMeta); err != nil { + return s, errors.New("GetWorkwechatPayload meta json:" + err.Error()) + } + switch event { + case models.HookEventCreate: + return getWorkwechatCreatePayload(p.(*api.CreatePayload), workwechatMeta) + case models.HookEventDelete: + return getWorkwechatDeletePayload(p.(*api.DeletePayload), workwechatMeta) + case models.HookEventFork: + return getWorkwechatForkPayload(p.(*api.ForkPayload), workwechatMeta) + case models.HookEventIssues: + return getWorkwechatIssuesPayload(p.(*api.IssuePayload), workwechatMeta) + case models.HookEventIssueComment: + return getWorkwechatIssueCommentPayload(p.(*api.IssueCommentPayload), workwechatMeta) + case models.HookEventPush: + return getWorkwechatPushPayload(p.(*api.PushPayload), workwechatMeta) + case models.HookEventPullRequest: + return getWorkwechatPullRequestPayload(p.(*api.PullRequestPayload), workwechatMeta) + case models.HookEventRepository: + return getWorkwechatRepositoryPayload(p.(*api.RepositoryPayload), workwechatMeta) + case models.HookEventRelease: + return getWorkwechatReleasePayload(p.(*api.ReleasePayload), workwechatMeta) + } + + return s, nil +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 9acc9b8bf6411..2bd0e5a0fb050 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -954,7 +954,7 @@ issues.new.no_reviewers = No reviewers issues.new.add_reviewer_title = Request review issues.choose.get_started = Get Started issues.choose.blank = Default -issues.choose.blank_about = Create an issue from default template. +issues.choose.blank_about = Create an issue from default template. issues.no_ref = No Branch/Tag Specified issues.create = Create Issue issues.new_label = New Label @@ -1617,6 +1617,8 @@ settings.add_dingtalk_hook_desc = Integrate Dingtalk into your settings.add_telegram_hook_desc = Integrate Telegram into your repository. settings.add_matrix_hook_desc = Integrate Matrix into your repository. settings.add_msteams_hook_desc = Integrate Microsoft Teams into your repository. +settings.add_workwechat_hook_desc = Integrate Work Wechat into your repository. +settings.workwechat_chatid=Chat ID settings.add_feishu_hook_desc = Integrate Feishu into your repository. settings.deploy_keys = Deploy Keys settings.add_deploy_key = Add Deploy Key diff --git a/public/img/workwechat.png b/public/img/workwechat.png new file mode 100644 index 0000000000000..e553e01779b89 Binary files /dev/null and b/public/img/workwechat.png differ diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index bec401021cc5a..cb41570f255d9 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -138,6 +138,10 @@ func WebhooksNew(ctx *context.Context) { "Username": "Gitea", "IconURL": setting.AppURL + "img/favicon.png", } + } else if hookType == "workwechat" { + ctx.Data["WorkwechatHook"] = map[string]interface{}{ + "ChatID": "gitea", + } } ctx.Data["BaseLink"] = orCtx.Link @@ -617,6 +621,52 @@ func FeishuHooksNewPost(ctx *context.Context, form auth.NewFeishuHookForm) { ctx.Redirect(orCtx.Link) } +// WorkwechatHooksNewPost response for creating work wechat hook +func WorkwechatHooksNewPost(ctx *context.Context, form auth.NewWorkwechatHookForm) { + ctx.Data["Title"] = ctx.Tr("repo.settings") + ctx.Data["PageIsSettingsHooks"] = true + ctx.Data["PageIsSettingsHooksNew"] = true + ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}} + + orCtx, err := getOrgRepoCtx(ctx) + if err != nil { + ctx.ServerError("getOrgRepoCtx", err) + return + } + + if ctx.HasError() { + ctx.HTML(200, orCtx.NewTemplate) + return + } + meta, err := json.Marshal(&webhook.WorkwechatMeta{ + ChatID: form.ChatID, + }) + if err != nil { + ctx.ServerError("Marshal", err) + return + } + w := &models.Webhook{ + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.WORKWECHAT, + Meta: string(meta), + OrgID: orCtx.OrgID, + } + if err := w.UpdateEvent(); err != nil { + ctx.ServerError("UpdateEvent", err) + return + } else if err := models.CreateWebhook(w); err != nil { + ctx.ServerError("CreateWebhook", err) + return + } + + ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success")) + ctx.Redirect(orCtx.Link) +} + func checkWebhook(ctx *context.Context) (*orgRepoCtx, *models.Webhook) { ctx.Data["RequireHighlightJS"] = true @@ -656,6 +706,8 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *models.Webhook) { ctx.Data["TelegramHook"] = webhook.GetTelegramHook(w) case models.MATRIX: ctx.Data["MatrixHook"] = webhook.GetMatrixHook(w) + case models.WORKWECHAT: + ctx.Data["WorkwechatHook"] = webhook.GetWorkwechatHook(w) } ctx.Data["History"], err = w.History(1) @@ -851,7 +903,7 @@ func DiscordHooksEditPost(ctx *context.Context, form auth.NewDiscordHookForm) { ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID)) } -// DingtalkHooksEditPost response for editing discord hook +// DingtalkHooksEditPost response for editing dingtalk hook func DingtalkHooksEditPost(ctx *context.Context, form auth.NewDingtalkHookForm) { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true @@ -1030,6 +1082,46 @@ func FeishuHooksEditPost(ctx *context.Context, form auth.NewFeishuHookForm) { ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID)) } +// WorkwechatHooksEditPost response for editing work wechat hook +func WorkwechatHooksEditPost(ctx *context.Context, form auth.NewWorkwechatHookForm) { + ctx.Data["Title"] = ctx.Tr("repo.settings") + ctx.Data["PageIsSettingsHooks"] = true + ctx.Data["PageIsSettingsHooksEdit"] = true + + orCtx, w := checkWebhook(ctx) + if ctx.Written() { + return + } + ctx.Data["Webhook"] = w + + if ctx.HasError() { + ctx.HTML(200, orCtx.NewTemplate) + return + } + meta, err := json.Marshal(&webhook.WorkwechatMeta{ + ChatID: form.ChatID, + }) + if err != nil { + ctx.ServerError("Marshal", err) + return + } + + w.URL = form.PayloadURL + w.Meta = string(meta) + w.HookEvent = ParseHookEvent(form.WebhookForm) + w.IsActive = form.Active + if err := w.UpdateEvent(); err != nil { + ctx.ServerError("UpdateEvent", err) + return + } else if err := models.UpdateWebhook(w); err != nil { + ctx.ServerError("UpdateWebhook", err) + return + } + + ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success")) + ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID)) +} + // TestWebhook test if web hook is work fine func TestWebhook(ctx *context.Context) { hookID := ctx.ParamsInt64(":id") diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 97f4e5aeaf899..92ee3b951087f 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -478,6 +478,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/telegram/new", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksNewPost) m.Post("/matrix/new", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksNewPost) m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost) + m.Post("/workwechat/new", bindIgnErr(auth.NewWorkwechatHookForm{}), repo.WorkwechatHooksNewPost) m.Post("/feishu/new", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksNewPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) @@ -489,6 +490,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) + m.Post("/workwechat/:id", bindIgnErr(auth.NewWorkwechatHookForm{}), repo.WorkwechatHooksEditPost) }) m.Group("/auths", func() { @@ -584,6 +586,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/new", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksNewPost) m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost) m.Post("/feishu/new", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksNewPost) + m.Post("/workwechat/new", bindIgnErr(auth.NewWorkwechatHookForm{}), repo.WorkwechatHooksNewPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksEditPost) @@ -594,6 +597,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) + m.Post("/workwechat/:id", bindIgnErr(auth.NewWorkwechatHookForm{}), repo.WorkwechatHooksEditPost) }) m.Group("/labels", func() { @@ -660,6 +664,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/new", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksNewPost) m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost) m.Post("/feishu/new", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksNewPost) + m.Post("/workwechat/new", bindIgnErr(auth.NewWorkwechatHookForm{}), repo.WorkwechatHooksEditPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/:id/test", repo.TestWebhook) m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) @@ -671,6 +676,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) + m.Post("/workwechat/:id", bindIgnErr(auth.NewWorkwechatHookForm{}), repo.WorkwechatHooksEditPost) m.Group("/git", func() { m.Get("", repo.GitHooks) diff --git a/templates/org/settings/hook_new.tmpl b/templates/org/settings/hook_new.tmpl index 35bb1610a872b..dc9d170c60295 100644 --- a/templates/org/settings/hook_new.tmpl +++ b/templates/org/settings/hook_new.tmpl @@ -27,6 +27,8 @@ {{else if eq .HookType "matrix"}} + {{else if eq .HookType "workwechat"}} + {{end}} diff --git a/templates/repo/settings/webhook/list.tmpl b/templates/repo/settings/webhook/list.tmpl index 29994d8197176..b880e719a6747 100644 --- a/templates/repo/settings/webhook/list.tmpl +++ b/templates/repo/settings/webhook/list.tmpl @@ -30,7 +30,10 @@ Feishu - Matrix + Matrix + + + Work Wechat diff --git a/templates/repo/settings/webhook/new.tmpl b/templates/repo/settings/webhook/new.tmpl index cf4c541bb0de3..dfd414a9e2fcc 100644 --- a/templates/repo/settings/webhook/new.tmpl +++ b/templates/repo/settings/webhook/new.tmpl @@ -25,6 +25,8 @@ {{else if eq .HookType "matrix"}} + {{else if eq .HookType "workwechat"}} + {{end}} @@ -38,6 +40,7 @@ {{template "repo/settings/webhook/msteams" .}} {{template "repo/settings/webhook/feishu" .}} {{template "repo/settings/webhook/matrix" .}} + {{template "repo/settings/webhook/workwechat" .}} {{template "repo/settings/webhook/history" .}} diff --git a/templates/repo/settings/webhook/workwechat.tmpl b/templates/repo/settings/webhook/workwechat.tmpl new file mode 100644 index 0000000000000..fb35cb82cc1f5 --- /dev/null +++ b/templates/repo/settings/webhook/workwechat.tmpl @@ -0,0 +1,15 @@ +{{if eq .HookType "workwechat"}} +

{{.i18n.Tr "repo.settings.add_workwechat_hook_desc" "https://work.weixin.qq.com" | Str2html}}

+
+ {{.CsrfTokenHtml}} +
+ + +
+
+ + +
+ {{template "repo/settings/webhook/settings" .}} +
+{{end}}