Modify the content format of the Feishu webhook (#25106)
close https://github.com/go-gitea/gitea/issues/24368 ## what my pull request does Since the official documentation states that custom bots do not support hyperlink functionality, simply adding it without making some formatting changes would result in an unappealing output. Therefore, I have modified the formatting of the output. Currently, it is only used for Feishu. --- [docs](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/im-v1/message/create_json#%E8%B6%85%E9%93%BE%E6%8E%A5%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E) <img width="641" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/360e1c81-ab64-4ef6-851e-aa450d6e85a4"> - Issue <img width="423" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/519f6fae-81ab-4ec8-89b8-f6a73ff93783"> - Issue Comment <img width="548" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/749c0d1c-3657-431e-b787-8bf4c23cce83"> - Assign <img width="431" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/066f99e5-eabb-455d-91fb-a8359cc26dc7"> <img width="457" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/c6c10f99-db83-46ef-a775-4c91979fa68f"> - Merge <img width="408" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/e627bf43-5954-45aa-acf6-261ee046802f"> - PullRequest <img width="425" alt="image" src="https://github.com/go-gitea/gitea/assets/75628309/72cfa714-d3fa-4fb9-abdd-e8508d756056">
This commit is contained in:
parent
f67f57a4c2
commit
5104c887d3
4 changed files with 111 additions and 15 deletions
|
@ -97,23 +97,40 @@ func (f *FeishuPayload) Push(p *api.PushPayload) (api.Payloader, error) {
|
||||||
|
|
||||||
// Issue implements PayloadConvertor Issue method
|
// Issue implements PayloadConvertor Issue method
|
||||||
func (f *FeishuPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
|
func (f *FeishuPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
|
||||||
text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
|
title, link, by, operator, result, assignees := getIssuesInfo(p)
|
||||||
|
var res api.Payloader
|
||||||
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
|
if assignees != "" {
|
||||||
|
if p.Action == api.HookIssueAssigned || p.Action == api.HookIssueUnassigned || p.Action == api.HookIssueMilestoned {
|
||||||
|
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, result, assignees, p.Issue.Body))
|
||||||
|
} else {
|
||||||
|
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, assignees, p.Issue.Body))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, p.Issue.Body))
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IssueComment implements PayloadConvertor IssueComment method
|
// IssueComment implements PayloadConvertor IssueComment method
|
||||||
func (f *FeishuPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
|
func (f *FeishuPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
|
||||||
text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true)
|
title, link, by, operator := getIssuesCommentInfo(p)
|
||||||
|
return newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, p.Comment.Body)), nil
|
||||||
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + p.Comment.Body), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullRequest implements PayloadConvertor PullRequest method
|
// PullRequest implements PayloadConvertor PullRequest method
|
||||||
func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) {
|
func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) {
|
||||||
text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
|
title, link, by, operator, result, assignees := getPullRequestInfo(p)
|
||||||
|
var res api.Payloader
|
||||||
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
|
if assignees != "" {
|
||||||
|
if p.Action == api.HookIssueAssigned || p.Action == api.HookIssueUnassigned || p.Action == api.HookIssueMilestoned {
|
||||||
|
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, result, assignees, p.PullRequest.Body))
|
||||||
|
} else {
|
||||||
|
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, assignees, p.PullRequest.Body))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, p.PullRequest.Body))
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Review implements PayloadConvertor Review method
|
// Review implements PayloadConvertor Review method
|
||||||
|
|
|
@ -72,7 +72,7 @@ func TestFeishuPayload(t *testing.T) {
|
||||||
require.NotNil(t, pl)
|
require.NotNil(t, pl)
|
||||||
require.IsType(t, &FeishuPayload{}, pl)
|
require.IsType(t, &FeishuPayload{}, pl)
|
||||||
|
|
||||||
assert.Equal(t, "#2 crash\r\n[test/repo] Issue opened: #2 crash by user1\r\n\r\nissue body", pl.(*FeishuPayload).Content.Text)
|
assert.Equal(t, "[Issue-test/repo #2]: opened\ncrash\nhttp://localhost:3000/test/repo/issues/2\nIssue by user1\nOperator: user1\nAssignees: user1\n\nissue body", pl.(*FeishuPayload).Content.Text)
|
||||||
|
|
||||||
p.Action = api.HookIssueClosed
|
p.Action = api.HookIssueClosed
|
||||||
pl, err = d.Issue(p)
|
pl, err = d.Issue(p)
|
||||||
|
@ -80,7 +80,7 @@ func TestFeishuPayload(t *testing.T) {
|
||||||
require.NotNil(t, pl)
|
require.NotNil(t, pl)
|
||||||
require.IsType(t, &FeishuPayload{}, pl)
|
require.IsType(t, &FeishuPayload{}, pl)
|
||||||
|
|
||||||
assert.Equal(t, "#2 crash\r\n[test/repo] Issue closed: #2 crash by user1", pl.(*FeishuPayload).Content.Text)
|
assert.Equal(t, "[Issue-test/repo #2]: closed\ncrash\nhttp://localhost:3000/test/repo/issues/2\nIssue by user1\nOperator: user1\nAssignees: user1\n\nissue body", pl.(*FeishuPayload).Content.Text)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("IssueComment", func(t *testing.T) {
|
t.Run("IssueComment", func(t *testing.T) {
|
||||||
|
@ -92,7 +92,7 @@ func TestFeishuPayload(t *testing.T) {
|
||||||
require.NotNil(t, pl)
|
require.NotNil(t, pl)
|
||||||
require.IsType(t, &FeishuPayload{}, pl)
|
require.IsType(t, &FeishuPayload{}, pl)
|
||||||
|
|
||||||
assert.Equal(t, "#2 crash\r\n[test/repo] New comment on issue #2 crash by user1\r\n\r\nmore info needed", pl.(*FeishuPayload).Content.Text)
|
assert.Equal(t, "[Comment-test/repo #2]: created\ncrash\nhttp://localhost:3000/test/repo/issues/2\nIssue by user1\nOperator: user1\n\nmore info needed", pl.(*FeishuPayload).Content.Text)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PullRequest", func(t *testing.T) {
|
t.Run("PullRequest", func(t *testing.T) {
|
||||||
|
@ -104,7 +104,7 @@ func TestFeishuPayload(t *testing.T) {
|
||||||
require.NotNil(t, pl)
|
require.NotNil(t, pl)
|
||||||
require.IsType(t, &FeishuPayload{}, pl)
|
require.IsType(t, &FeishuPayload{}, pl)
|
||||||
|
|
||||||
assert.Equal(t, "#12 Fix bug\r\n[test/repo] Pull request opened: #12 Fix bug by user1\r\n\r\nfixes bug #2", pl.(*FeishuPayload).Content.Text)
|
assert.Equal(t, "[PullRequest-test/repo #12]: opened\nFix bug\nhttp://localhost:3000/test/repo/pulls/12\nPullRequest by user1\nOperator: user1\nAssignees: user1\n\nfixes bug #2", pl.(*FeishuPayload).Content.Text)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PullRequestComment", func(t *testing.T) {
|
t.Run("PullRequestComment", func(t *testing.T) {
|
||||||
|
@ -116,7 +116,7 @@ func TestFeishuPayload(t *testing.T) {
|
||||||
require.NotNil(t, pl)
|
require.NotNil(t, pl)
|
||||||
require.IsType(t, &FeishuPayload{}, pl)
|
require.IsType(t, &FeishuPayload{}, pl)
|
||||||
|
|
||||||
assert.Equal(t, "#12 Fix bug\r\n[test/repo] New comment on pull request #12 Fix bug by user1\r\n\r\nchanges requested", pl.(*FeishuPayload).Content.Text)
|
assert.Equal(t, "[Comment-test/repo #12]: created\nFix bug\nhttp://localhost:3000/test/repo/pulls/12\nPullRequest by user1\nOperator: user1\n\nchanges requested", pl.(*FeishuPayload).Content.Text)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Review", func(t *testing.T) {
|
t.Run("Review", func(t *testing.T) {
|
||||||
|
|
|
@ -28,6 +28,69 @@ func htmlLinkFormatter(url, text string) string {
|
||||||
return fmt.Sprintf(`<a href="%s">%s</a>`, html.EscapeString(url), html.EscapeString(text))
|
return fmt.Sprintf(`<a href="%s">%s</a>`, html.EscapeString(url), html.EscapeString(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPullRequestInfo gets the information for a pull request
|
||||||
|
func getPullRequestInfo(p *api.PullRequestPayload) (title, link, by, operator, operateResult, assignees string) {
|
||||||
|
title = fmt.Sprintf("[PullRequest-%s #%d]: %s\n%s", p.Repository.FullName, p.PullRequest.Index, p.Action, p.PullRequest.Title)
|
||||||
|
assignList := p.PullRequest.Assignees
|
||||||
|
assignStringList := make([]string, len(assignList))
|
||||||
|
|
||||||
|
for i, user := range assignList {
|
||||||
|
assignStringList[i] = user.UserName
|
||||||
|
}
|
||||||
|
if p.Action == api.HookIssueAssigned {
|
||||||
|
operateResult = fmt.Sprintf("%s assign this to %s", p.Sender.UserName, assignList[len(assignList)-1].UserName)
|
||||||
|
} else if p.Action == api.HookIssueUnassigned {
|
||||||
|
operateResult = fmt.Sprintf("%s unassigned this for someone", p.Sender.UserName)
|
||||||
|
} else if p.Action == api.HookIssueMilestoned {
|
||||||
|
operateResult = fmt.Sprintf("%s/milestone/%d", p.Repository.HTMLURL, p.PullRequest.Milestone.ID)
|
||||||
|
}
|
||||||
|
link = p.PullRequest.HTMLURL
|
||||||
|
by = fmt.Sprintf("PullRequest by %s", p.PullRequest.Poster.UserName)
|
||||||
|
if len(assignStringList) > 0 {
|
||||||
|
assignees = fmt.Sprintf("Assignees: %s", strings.Join(assignStringList, ", "))
|
||||||
|
}
|
||||||
|
operator = fmt.Sprintf("Operator: %s", p.Sender.UserName)
|
||||||
|
return title, link, by, operator, operateResult, assignees
|
||||||
|
}
|
||||||
|
|
||||||
|
// getIssuesInfo gets the information for an issue
|
||||||
|
func getIssuesInfo(p *api.IssuePayload) (issueTitle, link, by, operator, operateResult, assignees string) {
|
||||||
|
issueTitle = fmt.Sprintf("[Issue-%s #%d]: %s\n%s", p.Repository.FullName, p.Issue.Index, p.Action, p.Issue.Title)
|
||||||
|
assignList := p.Issue.Assignees
|
||||||
|
assignStringList := make([]string, len(assignList))
|
||||||
|
|
||||||
|
for i, user := range assignList {
|
||||||
|
assignStringList[i] = user.UserName
|
||||||
|
}
|
||||||
|
if p.Action == api.HookIssueAssigned {
|
||||||
|
operateResult = fmt.Sprintf("%s assign this to %s", p.Sender.UserName, assignList[len(assignList)-1].UserName)
|
||||||
|
} else if p.Action == api.HookIssueUnassigned {
|
||||||
|
operateResult = fmt.Sprintf("%s unassigned this for someone", p.Sender.UserName)
|
||||||
|
} else if p.Action == api.HookIssueMilestoned {
|
||||||
|
operateResult = fmt.Sprintf("%s/milestone/%d", p.Repository.HTMLURL, p.Issue.Milestone.ID)
|
||||||
|
}
|
||||||
|
link = p.Issue.HTMLURL
|
||||||
|
by = fmt.Sprintf("Issue by %s", p.Issue.Poster.UserName)
|
||||||
|
if len(assignStringList) > 0 {
|
||||||
|
assignees = fmt.Sprintf("Assignees: %s", strings.Join(assignStringList, ", "))
|
||||||
|
}
|
||||||
|
operator = fmt.Sprintf("Operator: %s", p.Sender.UserName)
|
||||||
|
return issueTitle, link, by, operator, operateResult, assignees
|
||||||
|
}
|
||||||
|
|
||||||
|
// getIssuesCommentInfo gets the information for a comment
|
||||||
|
func getIssuesCommentInfo(p *api.IssueCommentPayload) (title, link, by, operator string) {
|
||||||
|
title = fmt.Sprintf("[Comment-%s #%d]: %s\n%s", p.Repository.FullName, p.Issue.Index, p.Action, p.Issue.Title)
|
||||||
|
link = p.Issue.HTMLURL
|
||||||
|
if p.IsPull {
|
||||||
|
by = fmt.Sprintf("PullRequest by %s", p.Issue.Poster.UserName)
|
||||||
|
} else {
|
||||||
|
by = fmt.Sprintf("Issue by %s", p.Issue.Poster.UserName)
|
||||||
|
}
|
||||||
|
operator = fmt.Sprintf("Operator: %s", p.Sender.UserName)
|
||||||
|
return title, link, by, operator
|
||||||
|
}
|
||||||
|
|
||||||
func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, withSender bool) (string, string, string, int) {
|
func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, withSender bool) (string, string, string, int) {
|
||||||
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
|
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
|
||||||
issueTitle := fmt.Sprintf("#%d %s", p.Index, p.Issue.Title)
|
issueTitle := fmt.Sprintf("#%d %s", p.Index, p.Issue.Title)
|
||||||
|
|
|
@ -123,6 +123,10 @@ func issueTestPayload() *api.IssuePayload {
|
||||||
HTMLURL: "http://localhost:3000/test/repo/issues/2",
|
HTMLURL: "http://localhost:3000/test/repo/issues/2",
|
||||||
Title: "crash",
|
Title: "crash",
|
||||||
Body: "issue body",
|
Body: "issue body",
|
||||||
|
Poster: &api.User{
|
||||||
|
UserName: "user1",
|
||||||
|
AvatarURL: "http://localhost:3000/user1/avatar",
|
||||||
|
},
|
||||||
Assignees: []*api.User{
|
Assignees: []*api.User{
|
||||||
{
|
{
|
||||||
UserName: "user1",
|
UserName: "user1",
|
||||||
|
@ -161,6 +165,10 @@ func issueCommentTestPayload() *api.IssueCommentPayload {
|
||||||
URL: "http://localhost:3000/api/v1/repos/test/repo/issues/2",
|
URL: "http://localhost:3000/api/v1/repos/test/repo/issues/2",
|
||||||
HTMLURL: "http://localhost:3000/test/repo/issues/2",
|
HTMLURL: "http://localhost:3000/test/repo/issues/2",
|
||||||
Title: "crash",
|
Title: "crash",
|
||||||
|
Poster: &api.User{
|
||||||
|
UserName: "user1",
|
||||||
|
AvatarURL: "http://localhost:3000/user1/avatar",
|
||||||
|
},
|
||||||
Body: "this happened",
|
Body: "this happened",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -190,6 +198,10 @@ func pullRequestCommentTestPayload() *api.IssueCommentPayload {
|
||||||
HTMLURL: "http://localhost:3000/test/repo/pulls/12",
|
HTMLURL: "http://localhost:3000/test/repo/pulls/12",
|
||||||
Title: "Fix bug",
|
Title: "Fix bug",
|
||||||
Body: "fixes bug #2",
|
Body: "fixes bug #2",
|
||||||
|
Poster: &api.User{
|
||||||
|
UserName: "user1",
|
||||||
|
AvatarURL: "http://localhost:3000/user1/avatar",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
IsPull: true,
|
IsPull: true,
|
||||||
}
|
}
|
||||||
|
@ -254,6 +266,10 @@ func pullRequestTestPayload() *api.PullRequestPayload {
|
||||||
Title: "Fix bug",
|
Title: "Fix bug",
|
||||||
Body: "fixes bug #2",
|
Body: "fixes bug #2",
|
||||||
Mergeable: true,
|
Mergeable: true,
|
||||||
|
Poster: &api.User{
|
||||||
|
UserName: "user1",
|
||||||
|
AvatarURL: "http://localhost:3000/user1/avatar",
|
||||||
|
},
|
||||||
Assignees: []*api.User{
|
Assignees: []*api.User{
|
||||||
{
|
{
|
||||||
UserName: "user1",
|
UserName: "user1",
|
||||||
|
|
Loading…
Reference in a new issue