You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

feishu.go 5.2KB

Webhook for Wiki changes (#20219) Add support for triggering webhook notifications on wiki changes. This PR contains frontend and backend for webhook notifications on wiki actions (create a new page, rename a page, edit a page and delete a page). The frontend got a new checkbox under the Custom Event -> Repository Events section. There is only one checkbox for create/edit/rename/delete actions, because it makes no sense to separate it and others like releases or packages follow the same schema. ![image](https://user-images.githubusercontent.com/121972/177018803-26851196-831f-4fde-9a4c-9e639b0e0d6b.png) The actions itself are separated, so that different notifications will be executed (with the "action" field). All the webhook receivers implement the new interface method (Wiki) and the corresponding tests. When implementing this, I encounter a little bug on editing a wiki page. Creating and editing a wiki page is technically the same action and will be handled by the ```updateWikiPage``` function. But the function need to know if it is a new wiki page or just a change. This distinction is done by the ```action``` parameter, but this will not be sent by the frontend (on form submit). This PR will fix this by adding the ```action``` parameter with the values ```_new``` or ```_edit```, which will be used by the ```updateWikiPage``` function. I've done integration tests with matrix and gitea (http). ![image](https://user-images.githubusercontent.com/121972/177018795-eb5cdc01-9ba3-483e-a6b7-ed0e313a71fb.png) Fix #16457 Signed-off-by: Aaron Fischer <mail@aaron-fischer.net>
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package webhook
  5. import (
  6. "fmt"
  7. "strings"
  8. webhook_model "code.gitea.io/gitea/models/webhook"
  9. "code.gitea.io/gitea/modules/git"
  10. "code.gitea.io/gitea/modules/json"
  11. api "code.gitea.io/gitea/modules/structs"
  12. )
  13. type (
  14. // FeishuPayload represents
  15. FeishuPayload struct {
  16. MsgType string `json:"msg_type"` // text / post / image / share_chat / interactive
  17. Content struct {
  18. Text string `json:"text"`
  19. } `json:"content"`
  20. }
  21. )
  22. func newFeishuTextPayload(text string) *FeishuPayload {
  23. return &FeishuPayload{
  24. MsgType: "text",
  25. Content: struct {
  26. Text string `json:"text"`
  27. }{
  28. Text: strings.TrimSpace(text),
  29. },
  30. }
  31. }
  32. // JSONPayload Marshals the FeishuPayload to json
  33. func (f *FeishuPayload) JSONPayload() ([]byte, error) {
  34. data, err := json.MarshalIndent(f, "", " ")
  35. if err != nil {
  36. return []byte{}, err
  37. }
  38. return data, nil
  39. }
  40. var _ PayloadConvertor = &FeishuPayload{}
  41. // Create implements PayloadConvertor Create method
  42. func (f *FeishuPayload) Create(p *api.CreatePayload) (api.Payloader, error) {
  43. // created tag/branch
  44. refName := git.RefEndName(p.Ref)
  45. text := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName)
  46. return newFeishuTextPayload(text), nil
  47. }
  48. // Delete implements PayloadConvertor Delete method
  49. func (f *FeishuPayload) Delete(p *api.DeletePayload) (api.Payloader, error) {
  50. // created tag/branch
  51. refName := git.RefEndName(p.Ref)
  52. text := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
  53. return newFeishuTextPayload(text), nil
  54. }
  55. // Fork implements PayloadConvertor Fork method
  56. func (f *FeishuPayload) Fork(p *api.ForkPayload) (api.Payloader, error) {
  57. text := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName)
  58. return newFeishuTextPayload(text), nil
  59. }
  60. // Push implements PayloadConvertor Push method
  61. func (f *FeishuPayload) Push(p *api.PushPayload) (api.Payloader, error) {
  62. var (
  63. branchName = git.RefEndName(p.Ref)
  64. commitDesc string
  65. )
  66. text := fmt.Sprintf("[%s:%s] %s\r\n", p.Repo.FullName, branchName, commitDesc)
  67. // for each commit, generate attachment text
  68. for i, commit := range p.Commits {
  69. var authorName string
  70. if commit.Author != nil {
  71. authorName = " - " + commit.Author.Name
  72. }
  73. text += fmt.Sprintf("[%s](%s) %s", commit.ID[:7], commit.URL,
  74. strings.TrimRight(commit.Message, "\r\n")) + authorName
  75. // add linebreak to each commit but the last
  76. if i < len(p.Commits)-1 {
  77. text += "\r\n"
  78. }
  79. }
  80. return newFeishuTextPayload(text), nil
  81. }
  82. // Issue implements PayloadConvertor Issue method
  83. func (f *FeishuPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
  84. text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
  85. return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
  86. }
  87. // IssueComment implements PayloadConvertor IssueComment method
  88. func (f *FeishuPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
  89. text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true)
  90. return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + p.Comment.Body), nil
  91. }
  92. // PullRequest implements PayloadConvertor PullRequest method
  93. func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) {
  94. text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
  95. return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
  96. }
  97. // Review implements PayloadConvertor Review method
  98. func (f *FeishuPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) {
  99. action, err := parseHookPullRequestEventType(event)
  100. if err != nil {
  101. return nil, err
  102. }
  103. title := fmt.Sprintf("[%s] Pull request review %s : #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title)
  104. text := p.Review.Content
  105. return newFeishuTextPayload(title + "\r\n\r\n" + text), nil
  106. }
  107. // Repository implements PayloadConvertor Repository method
  108. func (f *FeishuPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) {
  109. var text string
  110. switch p.Action {
  111. case api.HookRepoCreated:
  112. text = fmt.Sprintf("[%s] Repository created", p.Repository.FullName)
  113. return newFeishuTextPayload(text), nil
  114. case api.HookRepoDeleted:
  115. text = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName)
  116. return newFeishuTextPayload(text), nil
  117. }
  118. return nil, nil
  119. }
  120. // Wiki implements PayloadConvertor Wiki method
  121. func (f *FeishuPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
  122. text, _, _ := getWikiPayloadInfo(p, noneLinkFormatter, true)
  123. return newFeishuTextPayload(text), nil
  124. }
  125. // Release implements PayloadConvertor Release method
  126. func (f *FeishuPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
  127. text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true)
  128. return newFeishuTextPayload(text), nil
  129. }
  130. // GetFeishuPayload converts a ding talk webhook into a FeishuPayload
  131. func GetFeishuPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) {
  132. return convertPayloader(new(FeishuPayload), p, event)
  133. }