Refactor webhook (#31587)

A more complete fix for #31588

1. Make "generic" code more readable
2. Clarify HTML or Markdown for the payload content
pull/31605/head^2
wxiaoguang 4 months ago committed by GitHub
parent 4ea2a6de81
commit 72b6bc8caf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      models/activities/action_test.go
  2. 9
      models/repo/repo.go
  3. 2
      routers/web/repo/repo.go
  4. 2
      services/convert/repository.go
  5. 17
      services/webhook/dingtalk.go
  6. 24
      services/webhook/discord.go
  7. 9
      services/webhook/feishu.go
  8. 32
      services/webhook/general.go
  9. 8
      services/webhook/general_test.go
  10. 6
      services/webhook/matrix.go
  11. 17
      services/webhook/msteams.go
  12. 2
      services/webhook/notifier.go
  13. 12
      services/webhook/packagist.go
  14. 8
      services/webhook/payloader.go
  15. 22
      services/webhook/slack.go
  16. 107
      services/webhook/telegram.go
  17. 55
      services/webhook/telegram_test.go
  18. 17
      services/webhook/wechatwork.go

@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
)
@ -33,7 +34,8 @@ func TestAction_GetRepoLink(t *testing.T) {
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{ID: 2})
action := &activities_model.Action{RepoID: repo.ID, CommentID: comment.ID}
setting.AppSubURL = "/suburl"
defer test.MockVariableValue(&setting.AppURL, "https://try.gitea.io/suburl/")()
defer test.MockVariableValue(&setting.AppSubURL, "/suburl")()
expected := path.Join(setting.AppSubURL, owner.Name, repo.Name)
assert.Equal(t, expected, action.GetRepoLink(db.DefaultContext))
assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink(db.DefaultContext))

@ -18,6 +18,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/optional"
@ -321,8 +322,12 @@ func (repo *Repository) FullName() string {
}
// HTMLURL returns the repository HTML URL
func (repo *Repository) HTMLURL() string {
return setting.AppURL + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name)
func (repo *Repository) HTMLURL(ctxs ...context.Context) string {
ctx := context.TODO()
if len(ctxs) > 0 {
ctx = ctxs[0]
}
return httplib.MakeAbsoluteURL(ctx, repo.Link())
}
// CommitLink make link to by commit full ID

@ -668,7 +668,7 @@ func SearchRepo(ctx *context.Context) {
Template: repo.IsTemplate,
Mirror: repo.IsMirror,
Stars: repo.NumStars,
HTMLURL: repo.HTMLURL(),
HTMLURL: repo.HTMLURL(ctx),
Link: repo.Link(),
Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate,
},

@ -191,7 +191,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
Fork: repo.IsFork,
Parent: parent,
Mirror: repo.IsMirror,
HTMLURL: repo.HTMLURL(),
HTMLURL: repo.HTMLURL(ctx),
URL: repoAPIURL,
SSHURL: cloneLink.SSH,
CloneURL: cloneLink.HTTPS,

@ -20,8 +20,8 @@ import (
)
type (
// DingtalkPayload represents
DingtalkPayload dingtalk.Payload
dingtalkConvertor struct{}
)
// Create implements PayloadConvertor Create method
@ -92,9 +92,9 @@ func (dc dingtalkConvertor) Push(p *api.PushPayload) (DingtalkPayload, error) {
// Issue implements PayloadConvertor Issue method
func (dc dingtalkConvertor) Issue(p *api.IssuePayload) (DingtalkPayload, error) {
text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
text, issueTitle, extraMarkdown, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
return createDingtalkPayload(issueTitle, text+"\r\n\r\n"+attachmentText, "view issue", p.Issue.HTMLURL), nil
return createDingtalkPayload(issueTitle, text+"\r\n\r\n"+extraMarkdown, "view issue", p.Issue.HTMLURL), nil
}
// Wiki implements PayloadConvertor Wiki method
@ -114,9 +114,9 @@ func (dc dingtalkConvertor) IssueComment(p *api.IssueCommentPayload) (DingtalkPa
// PullRequest implements PayloadConvertor PullRequest method
func (dc dingtalkConvertor) PullRequest(p *api.PullRequestPayload) (DingtalkPayload, error) {
text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
text, issueTitle, extraMarkdown, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
return createDingtalkPayload(issueTitle, text+"\r\n\r\n"+attachmentText, "view pull request", p.PullRequest.HTMLURL), nil
return createDingtalkPayload(issueTitle, text+"\r\n\r\n"+extraMarkdown, "view pull request", p.PullRequest.HTMLURL), nil
}
// Review implements PayloadConvertor Review method
@ -186,10 +186,7 @@ func createDingtalkPayload(title, text, singleTitle, singleURL string) DingtalkP
}
}
type dingtalkConvertor struct{}
var _ payloadConvertor[DingtalkPayload] = dingtalkConvertor{}
func newDingtalkRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
return newJSONRequest(dingtalkConvertor{}, w, t, true)
var pc payloadConvertor[DingtalkPayload] = dingtalkConvertor{}
return newJSONRequest(pc, w, t, true)
}

@ -100,6 +100,11 @@ var (
redColor = color("ff3232")
)
type discordConvertor struct {
Username string
AvatarURL string
}
// Create implements PayloadConvertor Create method
func (d discordConvertor) Create(p *api.CreatePayload) (DiscordPayload, error) {
// created tag/branch
@ -162,9 +167,9 @@ func (d discordConvertor) Push(p *api.PushPayload) (DiscordPayload, error) {
// Issue implements PayloadConvertor Issue method
func (d discordConvertor) Issue(p *api.IssuePayload) (DiscordPayload, error) {
title, _, text, color := getIssuesPayloadInfo(p, noneLinkFormatter, false)
title, _, extraMarkdown, color := getIssuesPayloadInfo(p, noneLinkFormatter, false)
return d.createPayload(p.Sender, title, text, p.Issue.HTMLURL, color), nil
return d.createPayload(p.Sender, title, extraMarkdown, p.Issue.HTMLURL, color), nil
}
// IssueComment implements PayloadConvertor IssueComment method
@ -176,9 +181,9 @@ func (d discordConvertor) IssueComment(p *api.IssueCommentPayload) (DiscordPaylo
// PullRequest implements PayloadConvertor PullRequest method
func (d discordConvertor) PullRequest(p *api.PullRequestPayload) (DiscordPayload, error) {
title, _, text, color := getPullRequestPayloadInfo(p, noneLinkFormatter, false)
title, _, extraMarkdown, color := getPullRequestPayloadInfo(p, noneLinkFormatter, false)
return d.createPayload(p.Sender, title, text, p.PullRequest.HTMLURL, color), nil
return d.createPayload(p.Sender, title, extraMarkdown, p.PullRequest.HTMLURL, color), nil
}
// Review implements PayloadConvertor Review method
@ -253,23 +258,16 @@ func (d discordConvertor) Package(p *api.PackagePayload) (DiscordPayload, error)
return d.createPayload(p.Sender, text, "", p.Package.HTMLURL, color), nil
}
type discordConvertor struct {
Username string
AvatarURL string
}
var _ payloadConvertor[DiscordPayload] = discordConvertor{}
func newDiscordRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
meta := &DiscordMeta{}
if err := json.Unmarshal([]byte(w.Meta), meta); err != nil {
return nil, nil, fmt.Errorf("newDiscordRequest meta json: %w", err)
}
sc := discordConvertor{
var pc payloadConvertor[DiscordPayload] = discordConvertor{
Username: meta.Username,
AvatarURL: meta.IconURL,
}
return newJSONRequest(sc, w, t, true)
return newJSONRequest(pc, w, t, true)
}
func parseHookPullRequestEventType(event webhook_module.HookEventType) (string, error) {

@ -36,6 +36,8 @@ func newFeishuTextPayload(text string) FeishuPayload {
}
}
type feishuConvertor struct{}
// Create implements PayloadConvertor Create method
func (fc feishuConvertor) Create(p *api.CreatePayload) (FeishuPayload, error) {
// created tag/branch
@ -164,10 +166,7 @@ func (fc feishuConvertor) Package(p *api.PackagePayload) (FeishuPayload, error)
return newFeishuTextPayload(text), nil
}
type feishuConvertor struct{}
var _ payloadConvertor[FeishuPayload] = feishuConvertor{}
func newFeishuRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
return newJSONRequest(feishuConvertor{}, w, t, true)
var pc payloadConvertor[FeishuPayload] = feishuConvertor{}
return newJSONRequest(pc, w, t, true)
}

@ -91,12 +91,11 @@ func getIssuesCommentInfo(p *api.IssueCommentPayload) (title, link, by, operator
return title, link, by, operator
}
func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, withSender bool) (string, string, string, int) {
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
issueTitle := fmt.Sprintf("#%d %s", p.Index, p.Issue.Title)
func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, withSender bool) (text, issueTitle, extraMarkdown string, color int) {
color = yellowColor
issueTitle = fmt.Sprintf("#%d %s", p.Index, p.Issue.Title)
titleLink := linkFormatter(fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Index), issueTitle)
var text string
color := yellowColor
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
switch p.Action {
case api.HookIssueOpened:
@ -135,26 +134,23 @@ func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, with
text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName))
}
var attachmentText string
if p.Action == api.HookIssueOpened || p.Action == api.HookIssueEdited {
attachmentText = p.Issue.Body
extraMarkdown = p.Issue.Body
}
return text, issueTitle, attachmentText, color
return text, issueTitle, extraMarkdown, color
}
func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkFormatter, withSender bool) (string, string, string, int) {
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
issueTitle := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title)
func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkFormatter, withSender bool) (text, issueTitle, extraMarkdown string, color int) {
color = yellowColor
issueTitle = fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title)
titleLink := linkFormatter(p.PullRequest.URL, issueTitle)
var text string
var attachmentText string
color := yellowColor
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
switch p.Action {
case api.HookIssueOpened:
text = fmt.Sprintf("[%s] Pull request opened: %s", repoLink, titleLink)
attachmentText = p.PullRequest.Body
extraMarkdown = p.PullRequest.Body
color = greenColor
case api.HookIssueClosed:
if p.PullRequest.HasMerged {
@ -168,7 +164,7 @@ func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkForm
text = fmt.Sprintf("[%s] Pull request re-opened: %s", repoLink, titleLink)
case api.HookIssueEdited:
text = fmt.Sprintf("[%s] Pull request edited: %s", repoLink, titleLink)
attachmentText = p.PullRequest.Body
extraMarkdown = p.PullRequest.Body
case api.HookIssueAssigned:
list := make([]string, len(p.PullRequest.Assignees))
for i, user := range p.PullRequest.Assignees {
@ -193,7 +189,7 @@ func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkForm
text = fmt.Sprintf("[%s] Pull request milestone cleared: %s", repoLink, titleLink)
case api.HookIssueReviewed:
text = fmt.Sprintf("[%s] Pull request reviewed: %s", repoLink, titleLink)
attachmentText = p.Review.Content
extraMarkdown = p.Review.Content
case api.HookIssueReviewRequested:
text = fmt.Sprintf("[%s] Pull request review requested: %s", repoLink, titleLink)
case api.HookIssueReviewRequestRemoved:
@ -203,7 +199,7 @@ func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkForm
text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName))
}
return text, issueTitle, attachmentText, color
return text, issueTitle, extraMarkdown, color
}
func getReleasePayloadInfo(p *api.ReleasePayload, linkFormatter linkFormatter, withSender bool) (text string, color int) {

@ -424,10 +424,10 @@ func TestGetIssuesPayloadInfo(t *testing.T) {
for i, c := range cases {
p.Action = c.action
text, issueTitle, attachmentText, color := getIssuesPayloadInfo(p, noneLinkFormatter, true)
text, issueTitle, extraMarkdown, color := getIssuesPayloadInfo(p, noneLinkFormatter, true)
assert.Equal(t, c.text, text, "case %d", i)
assert.Equal(t, c.issueTitle, issueTitle, "case %d", i)
assert.Equal(t, c.attachmentText, attachmentText, "case %d", i)
assert.Equal(t, c.attachmentText, extraMarkdown, "case %d", i)
assert.Equal(t, c.color, color, "case %d", i)
}
}
@ -523,10 +523,10 @@ func TestGetPullRequestPayloadInfo(t *testing.T) {
for i, c := range cases {
p.Action = c.action
text, issueTitle, attachmentText, color := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
text, issueTitle, extraMarkdown, color := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
assert.Equal(t, c.text, text, "case %d", i)
assert.Equal(t, c.issueTitle, issueTitle, "case %d", i)
assert.Equal(t, c.attachmentText, attachmentText, "case %d", i)
assert.Equal(t, c.attachmentText, extraMarkdown, "case %d", i)
assert.Equal(t, c.color, color, "case %d", i)
}
}

@ -29,10 +29,10 @@ func newMatrixRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_mo
if err := json.Unmarshal([]byte(w.Meta), meta); err != nil {
return nil, nil, fmt.Errorf("GetMatrixPayload meta json: %w", err)
}
mc := matrixConvertor{
var pc payloadConvertor[MatrixPayload] = matrixConvertor{
MsgType: messageTypeText[meta.MessageType],
}
payload, err := newPayload(mc, []byte(t.PayloadContent), t.EventType)
payload, err := newPayload(pc, []byte(t.PayloadContent), t.EventType)
if err != nil {
return nil, nil, err
}
@ -87,8 +87,6 @@ type MatrixPayload struct {
Commits []*api.PayloadCommit `json:"io.gitea.commits,omitempty"`
}
var _ payloadConvertor[MatrixPayload] = matrixConvertor{}
type matrixConvertor struct {
MsgType string
}

@ -58,6 +58,8 @@ type (
}
)
type msteamsConvertor struct{}
// Create implements PayloadConvertor Create method
func (m msteamsConvertor) Create(p *api.CreatePayload) (MSTeamsPayload, error) {
// created tag/branch
@ -152,13 +154,13 @@ func (m msteamsConvertor) Push(p *api.PushPayload) (MSTeamsPayload, error) {
// Issue implements PayloadConvertor Issue method
func (m msteamsConvertor) Issue(p *api.IssuePayload) (MSTeamsPayload, error) {
title, _, attachmentText, color := getIssuesPayloadInfo(p, noneLinkFormatter, false)
title, _, extraMarkdown, color := getIssuesPayloadInfo(p, noneLinkFormatter, false)
return createMSTeamsPayload(
p.Repository,
p.Sender,
title,
attachmentText,
extraMarkdown,
p.Issue.HTMLURL,
color,
&MSTeamsFact{"Issue #:", fmt.Sprintf("%d", p.Issue.ID)},
@ -182,13 +184,13 @@ func (m msteamsConvertor) IssueComment(p *api.IssueCommentPayload) (MSTeamsPaylo
// PullRequest implements PayloadConvertor PullRequest method
func (m msteamsConvertor) PullRequest(p *api.PullRequestPayload) (MSTeamsPayload, error) {
title, _, attachmentText, color := getPullRequestPayloadInfo(p, noneLinkFormatter, false)
title, _, extraMarkdown, color := getPullRequestPayloadInfo(p, noneLinkFormatter, false)
return createMSTeamsPayload(
p.Repository,
p.Sender,
title,
attachmentText,
extraMarkdown,
p.PullRequest.HTMLURL,
color,
&MSTeamsFact{"Pull request #:", fmt.Sprintf("%d", p.PullRequest.ID)},
@ -343,10 +345,7 @@ func createMSTeamsPayload(r *api.Repository, s *api.User, title, text, actionTar
}
}
type msteamsConvertor struct{}
var _ payloadConvertor[MSTeamsPayload] = msteamsConvertor{}
func newMSTeamsRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
return newJSONRequest(msteamsConvertor{}, w, t, true)
var pc payloadConvertor[MSTeamsPayload] = msteamsConvertor{}
return newJSONRequest(pc, w, t, true)
}

@ -23,7 +23,7 @@ import (
)
func init() {
notify_service.RegisterNotifier(&webhookNotifier{})
notify_service.RegisterNotifier(NewNotifier())
}
type webhookNotifier struct {

@ -40,6 +40,10 @@ func GetPackagistHook(w *webhook_model.Webhook) *PackagistMeta {
return s
}
type packagistConvertor struct {
PackageURL string
}
// Create implements PayloadConvertor Create method
func (pc packagistConvertor) Create(_ *api.CreatePayload) (PackagistPayload, error) {
return PackagistPayload{}, nil
@ -106,18 +110,12 @@ func (pc packagistConvertor) Package(_ *api.PackagePayload) (PackagistPayload, e
return PackagistPayload{}, nil
}
type packagistConvertor struct {
PackageURL string
}
var _ payloadConvertor[PackagistPayload] = packagistConvertor{}
func newPackagistRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
meta := &PackagistMeta{}
if err := json.Unmarshal([]byte(w.Meta), meta); err != nil {
return nil, nil, fmt.Errorf("newpackagistRequest meta json: %w", err)
}
pc := packagistConvertor{
var pc payloadConvertor[PackagistPayload] = packagistConvertor{
PackageURL: meta.PackageURL,
}
return newJSONRequest(pc, w, t, true)

@ -30,16 +30,15 @@ type payloadConvertor[T any] interface {
Package(*api.PackagePayload) (T, error)
}
func convertUnmarshalledJSON[T, P any](convert func(P) (T, error), data []byte) (T, error) {
func convertUnmarshalledJSON[T, P any](convert func(P) (T, error), data []byte) (t T, err error) {
var p P
if err := json.Unmarshal(data, &p); err != nil {
var t T
if err = json.Unmarshal(data, &p); err != nil {
return t, fmt.Errorf("could not unmarshal payload: %w", err)
}
return convert(p)
}
func newPayload[T any](rc payloadConvertor[T], data []byte, event webhook_module.HookEventType) (T, error) {
func newPayload[T any](rc payloadConvertor[T], data []byte, event webhook_module.HookEventType) (t T, err error) {
switch event {
case webhook_module.HookEventCreate:
return convertUnmarshalledJSON(rc.Create, data)
@ -79,7 +78,6 @@ func newPayload[T any](rc payloadConvertor[T], data []byte, event webhook_module
case webhook_module.HookEventPackage:
return convertUnmarshalledJSON(rc.Package, data)
}
var t T
return t, fmt.Errorf("newPayload unsupported event: %s", event)
}

@ -118,17 +118,17 @@ func (s slackConvertor) Fork(p *api.ForkPayload) (SlackPayload, error) {
// Issue implements payloadConvertor Issue method
func (s slackConvertor) Issue(p *api.IssuePayload) (SlackPayload, error) {
text, issueTitle, attachmentText, color := getIssuesPayloadInfo(p, SlackLinkFormatter, true)
text, issueTitle, extraMarkdown, color := getIssuesPayloadInfo(p, SlackLinkFormatter, true)
var attachments []SlackAttachment
if attachmentText != "" {
attachmentText = SlackTextFormatter(attachmentText)
if extraMarkdown != "" {
extraMarkdown = SlackTextFormatter(extraMarkdown)
issueTitle = SlackTextFormatter(issueTitle)
attachments = append(attachments, SlackAttachment{
Color: fmt.Sprintf("%x", color),
Title: issueTitle,
TitleLink: p.Issue.HTMLURL,
Text: attachmentText,
Text: extraMarkdown,
})
}
@ -210,17 +210,17 @@ func (s slackConvertor) Push(p *api.PushPayload) (SlackPayload, error) {
// PullRequest implements payloadConvertor PullRequest method
func (s slackConvertor) PullRequest(p *api.PullRequestPayload) (SlackPayload, error) {
text, issueTitle, attachmentText, color := getPullRequestPayloadInfo(p, SlackLinkFormatter, true)
text, issueTitle, extraMarkdown, color := getPullRequestPayloadInfo(p, SlackLinkFormatter, true)
var attachments []SlackAttachment
if attachmentText != "" {
attachmentText = SlackTextFormatter(p.PullRequest.Body)
if extraMarkdown != "" {
extraMarkdown = SlackTextFormatter(p.PullRequest.Body)
issueTitle = SlackTextFormatter(issueTitle)
attachments = append(attachments, SlackAttachment{
Color: fmt.Sprintf("%x", color),
Title: issueTitle,
TitleLink: p.PullRequest.HTMLURL,
Text: attachmentText,
Text: extraMarkdown,
})
}
@ -281,20 +281,18 @@ type slackConvertor struct {
Color string
}
var _ payloadConvertor[SlackPayload] = slackConvertor{}
func newSlackRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
meta := &SlackMeta{}
if err := json.Unmarshal([]byte(w.Meta), meta); err != nil {
return nil, nil, fmt.Errorf("newSlackRequest meta json: %w", err)
}
sc := slackConvertor{
var pc payloadConvertor[SlackPayload] = slackConvertor{
Channel: meta.Channel,
Username: meta.Username,
IconURL: meta.IconURL,
Color: meta.Color,
}
return newJSONRequest(sc, w, t, true)
return newJSONRequest(pc, w, t, true)
}
var slackChannel = regexp.MustCompile(`^#?[a-z0-9_-]{1,80}$`)

@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
"html"
"net/http"
"strings"
@ -13,7 +14,9 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
)
@ -42,41 +45,43 @@ func GetTelegramHook(w *webhook_model.Webhook) *TelegramMeta {
return s
}
type telegramConvertor struct{}
// Create implements PayloadConvertor Create method
func (t telegramConvertor) Create(p *api.CreatePayload) (TelegramPayload, error) {
// created tag/branch
refName := git.RefName(p.Ref).ShortName()
title := fmt.Sprintf(`[<a href="%s">%s</a>] %s <a href="%s">%s</a> created`, p.Repo.HTMLURL, p.Repo.FullName, p.RefType,
p.Repo.HTMLURL+"/src/"+refName, refName)
title := fmt.Sprintf(`[%s] %s %s created`,
htmlLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName),
html.EscapeString(p.RefType),
htmlLinkFormatter(p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName), refName),
)
return createTelegramPayload(title), nil
return createTelegramPayloadHTML(title), nil
}
// Delete implements PayloadConvertor Delete method
func (t telegramConvertor) Delete(p *api.DeletePayload) (TelegramPayload, error) {
// created tag/branch
refName := git.RefName(p.Ref).ShortName()
title := fmt.Sprintf(`[<a href="%s">%s</a>] %s <a href="%s">%s</a> deleted`, p.Repo.HTMLURL, p.Repo.FullName, p.RefType,
p.Repo.HTMLURL+"/src/"+refName, refName)
return createTelegramPayload(title), nil
title := fmt.Sprintf(`[%s] %s %s deleted`,
htmlLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName),
html.EscapeString(p.RefType),
htmlLinkFormatter(p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName), refName),
)
return createTelegramPayloadHTML(title), nil
}
// Fork implements PayloadConvertor Fork method
func (t telegramConvertor) Fork(p *api.ForkPayload) (TelegramPayload, error) {
title := fmt.Sprintf(`%s is forked to <a href="%s">%s</a>`, p.Forkee.FullName, p.Repo.HTMLURL, p.Repo.FullName)
return createTelegramPayload(title), nil
title := fmt.Sprintf(`%s is forked to %s`, html.EscapeString(p.Forkee.FullName), htmlLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName))
return createTelegramPayloadHTML(title), nil
}
// Push implements PayloadConvertor Push method
func (t telegramConvertor) Push(p *api.PushPayload) (TelegramPayload, error) {
var (
branchName = git.RefName(p.Ref).ShortName()
commitDesc string
)
var titleLink string
branchName := git.RefName(p.Ref).ShortName()
var titleLink, commitDesc string
if p.TotalCommits == 1 {
commitDesc = "1 new commit"
titleLink = p.Commits[0].URL
@ -85,52 +90,42 @@ func (t telegramConvertor) Push(p *api.PushPayload) (TelegramPayload, error) {
titleLink = p.CompareURL
}
if titleLink == "" {
titleLink = p.Repo.HTMLURL + "/src/" + branchName
titleLink = p.Repo.HTMLURL + "/src/" + util.PathEscapeSegments(branchName)
}
title := fmt.Sprintf(`[<a href="%s">%s</a>:<a href="%s">%s</a>] %s`, p.Repo.HTMLURL, p.Repo.FullName, titleLink, branchName, commitDesc)
title := fmt.Sprintf(`[%s:%s] %s`, htmlLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName), htmlLinkFormatter(titleLink, branchName), html.EscapeString(commitDesc))
var text string
// for each commit, generate attachment text
for i, commit := range p.Commits {
var authorName string
var htmlCommits string
for _, commit := range p.Commits {
htmlCommits += fmt.Sprintf("\n[%s] %s", htmlLinkFormatter(commit.URL, commit.ID[:7]), html.EscapeString(strings.TrimRight(commit.Message, "\r\n")))
if commit.Author != nil {
authorName = " - " + commit.Author.Name
htmlCommits += " - " + html.EscapeString(commit.Author.Name)
}
text += fmt.Sprintf(`[<a href="%s">%s</a>] %s`, commit.URL, commit.ID[:7],
strings.TrimRight(commit.Message, "\r\n")) + authorName
// add linebreak to each commit but the last
if i < len(p.Commits)-1 {
text += "\n"
}
}
return createTelegramPayload(title + "\n" + text), nil
return createTelegramPayloadHTML(title + htmlCommits), nil
}
// Issue implements PayloadConvertor Issue method
func (t telegramConvertor) Issue(p *api.IssuePayload) (TelegramPayload, error) {
text, _, attachmentText, _ := getIssuesPayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayload(text + "\n\n" + attachmentText), nil
text, _, extraMarkdown, _ := getIssuesPayloadInfo(p, htmlLinkFormatter, true)
// TODO: at the moment the markdown can't be rendered easily because it has context-aware links (eg: attachments)
return createTelegramPayloadHTML(text + "\n\n" + html.EscapeString(extraMarkdown)), nil
}
// IssueComment implements PayloadConvertor IssueComment method
func (t telegramConvertor) IssueComment(p *api.IssueCommentPayload) (TelegramPayload, error) {
text, _, _ := getIssueCommentPayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayload(text + "\n" + p.Comment.Body), nil
return createTelegramPayloadHTML(text + "\n" + html.EscapeString(p.Comment.Body)), nil
}
// PullRequest implements PayloadConvertor PullRequest method
func (t telegramConvertor) PullRequest(p *api.PullRequestPayload) (TelegramPayload, error) {
text, _, attachmentText, _ := getPullRequestPayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayload(text + "\n" + attachmentText), nil
text, _, extraMarkdown, _ := getPullRequestPayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayloadHTML(text + "\n" + html.EscapeString(extraMarkdown)), nil
}
// Review implements PayloadConvertor Review method
func (t telegramConvertor) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (TelegramPayload, error) {
var text, attachmentText string
var text, extraMarkdown string
switch p.Action {
case api.HookIssueReviewed:
action, err := parseHookPullRequestEventType(event)
@ -138,11 +133,11 @@ func (t telegramConvertor) Review(p *api.PullRequestPayload, event webhook_modul
return TelegramPayload{}, err
}
text = fmt.Sprintf("[%s] Pull request review %s: #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title)
attachmentText = p.Review.Content
text = fmt.Sprintf("[%s] Pull request review %s: #%d %s", html.EscapeString(p.Repository.FullName), html.EscapeString(action), p.Index, html.EscapeString(p.PullRequest.Title))
extraMarkdown = p.Review.Content
}
return createTelegramPayload(text + "\n" + attachmentText), nil
return createTelegramPayloadHTML(text + "\n" + html.EscapeString(extraMarkdown)), nil
}
// Repository implements PayloadConvertor Repository method
@ -150,11 +145,11 @@ func (t telegramConvertor) Repository(p *api.RepositoryPayload) (TelegramPayload
var title string
switch p.Action {
case api.HookRepoCreated:
title = fmt.Sprintf(`[<a href="%s">%s</a>] Repository created`, p.Repository.HTMLURL, p.Repository.FullName)
return createTelegramPayload(title), nil
title = fmt.Sprintf(`[%s] Repository created`, htmlLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName))
return createTelegramPayloadHTML(title), nil
case api.HookRepoDeleted:
title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName)
return createTelegramPayload(title), nil
title = fmt.Sprintf("[%s] Repository deleted", html.EscapeString(p.Repository.FullName))
return createTelegramPayloadHTML(title), nil
}
return TelegramPayload{}, nil
}
@ -163,34 +158,32 @@ func (t telegramConvertor) Repository(p *api.RepositoryPayload) (TelegramPayload
func (t telegramConvertor) Wiki(p *api.WikiPayload) (TelegramPayload, error) {
text, _, _ := getWikiPayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayload(text), nil
return createTelegramPayloadHTML(text), nil
}
// Release implements PayloadConvertor Release method
func (t telegramConvertor) Release(p *api.ReleasePayload) (TelegramPayload, error) {
text, _ := getReleasePayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayload(text), nil
return createTelegramPayloadHTML(text), nil
}
func (t telegramConvertor) Package(p *api.PackagePayload) (TelegramPayload, error) {
text, _ := getPackagePayloadInfo(p, htmlLinkFormatter, true)
return createTelegramPayload(text), nil
return createTelegramPayloadHTML(text), nil
}
func createTelegramPayload(message string) TelegramPayload {
func createTelegramPayloadHTML(msgHTML string) TelegramPayload {
// https://core.telegram.org/bots/api#formatting-options
return TelegramPayload{
Message: strings.TrimSpace(message),
Message: strings.TrimSpace(markup.Sanitize(msgHTML)),
ParseMode: "HTML",
DisableWebPreview: true,
}
}
type telegramConvertor struct{}
var _ payloadConvertor[TelegramPayload] = telegramConvertor{}
func newTelegramRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
return newJSONRequest(telegramConvertor{}, w, t, true)
var pc payloadConvertor[TelegramPayload] = telegramConvertor{}
return newJSONRequest(pc, w, t, true)
}

@ -20,11 +20,12 @@ func TestTelegramPayload(t *testing.T) {
tc := telegramConvertor{}
t.Run("Correct webhook params", func(t *testing.T) {
p := createTelegramPayload("testMsg ")
assert.Equal(t, "HTML", p.ParseMode)
assert.Equal(t, true, p.DisableWebPreview)
assert.Equal(t, "testMsg", p.Message)
p := createTelegramPayloadHTML(`<a href=".">testMsg</a> <bad>`)
assert.Equal(t, TelegramPayload{
Message: `<a href="." rel="nofollow">testMsg</a>`,
ParseMode: "HTML",
DisableWebPreview: true,
}, p)
})
t.Run("Create", func(t *testing.T) {
@ -33,7 +34,7 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Create(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] branch <a href="http://localhost:3000/test/repo/src/test">test</a> created`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] branch <a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a> created`, pl.Message)
})
t.Run("Delete", func(t *testing.T) {
@ -42,7 +43,7 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Delete(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] branch <a href="http://localhost:3000/test/repo/src/test">test</a> deleted`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] branch <a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a> deleted`, pl.Message)
})
t.Run("Fork", func(t *testing.T) {
@ -51,7 +52,7 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Fork(p)
require.NoError(t, err)
assert.Equal(t, `test/repo2 is forked to <a href="http://localhost:3000/test/repo">test/repo</a>`, pl.Message)
assert.Equal(t, `test/repo2 is forked to <a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>`, pl.Message)
})
t.Run("Push", func(t *testing.T) {
@ -60,7 +61,9 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Push(p)
require.NoError(t, err)
assert.Equal(t, "[<a href=\"http://localhost:3000/test/repo\">test/repo</a>:<a href=\"http://localhost:3000/test/repo/src/test\">test</a>] 2 new commits\n[<a href=\"http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778\">2020558</a>] commit message - user1\n[<a href=\"http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778\">2020558</a>] commit message - user1", pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>:<a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a>] 2 new commits
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1`, pl.Message)
})
t.Run("Issue", func(t *testing.T) {
@ -70,13 +73,15 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Issue(p)
require.NoError(t, err)
assert.Equal(t, "[<a href=\"http://localhost:3000/test/repo\">test/repo</a>] Issue opened: <a href=\"http://localhost:3000/test/repo/issues/2\">#2 crash</a> by <a href=\"https://try.gitea.io/user1\">user1</a>\n\nissue body", pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Issue opened: <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
issue body`, pl.Message)
p.Action = api.HookIssueClosed
pl, err = tc.Issue(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Issue closed: <a href="http://localhost:3000/test/repo/issues/2">#2 crash</a> by <a href="https://try.gitea.io/user1">user1</a>`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Issue closed: <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>`, pl.Message)
})
t.Run("IssueComment", func(t *testing.T) {
@ -85,7 +90,8 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.IssueComment(p)
require.NoError(t, err)
assert.Equal(t, "[<a href=\"http://localhost:3000/test/repo\">test/repo</a>] New comment on issue <a href=\"http://localhost:3000/test/repo/issues/2\">#2 crash</a> by <a href=\"https://try.gitea.io/user1\">user1</a>\nmore info needed", pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New comment on issue <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
more info needed`, pl.Message)
})
t.Run("PullRequest", func(t *testing.T) {
@ -94,7 +100,8 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.PullRequest(p)
require.NoError(t, err)
assert.Equal(t, "[<a href=\"http://localhost:3000/test/repo\">test/repo</a>] Pull request opened: <a href=\"http://localhost:3000/test/repo/pulls/12\">#12 Fix bug</a> by <a href=\"https://try.gitea.io/user1\">user1</a>\nfixes bug #2", pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Pull request opened: <a href="http://localhost:3000/test/repo/pulls/12" rel="nofollow">#12 Fix bug</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
fixes bug #2`, pl.Message)
})
t.Run("PullRequestComment", func(t *testing.T) {
@ -103,7 +110,8 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.IssueComment(p)
require.NoError(t, err)
assert.Equal(t, "[<a href=\"http://localhost:3000/test/repo\">test/repo</a>] New comment on pull request <a href=\"http://localhost:3000/test/repo/pulls/12\">#12 Fix bug</a> by <a href=\"https://try.gitea.io/user1\">user1</a>\nchanges requested", pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New comment on pull request <a href="http://localhost:3000/test/repo/pulls/12" rel="nofollow">#12 Fix bug</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
changes requested`, pl.Message)
})
t.Run("Review", func(t *testing.T) {
@ -113,7 +121,8 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Review(p, webhook_module.HookEventPullRequestReviewApproved)
require.NoError(t, err)
assert.Equal(t, "[test/repo] Pull request review approved: #12 Fix bug\ngood job", pl.Message)
assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug
good job`, pl.Message)
})
t.Run("Repository", func(t *testing.T) {
@ -122,7 +131,7 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Repository(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Repository created`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Repository created`, pl.Message)
})
t.Run("Package", func(t *testing.T) {
@ -131,7 +140,7 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Package(p)
require.NoError(t, err)
assert.Equal(t, `Package created: <a href="http://localhost:3000/user1/-/packages/container/GiteaContainer/latest">GiteaContainer:latest</a> by <a href="https://try.gitea.io/user1">user1</a>`, pl.Message)
assert.Equal(t, `Package created: <a href="http://localhost:3000/user1/-/packages/container/GiteaContainer/latest" rel="nofollow">GiteaContainer:latest</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>`, pl.Message)
})
t.Run("Wiki", func(t *testing.T) {
@ -141,19 +150,19 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Wiki(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] New wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New wiki page &#39;<a href="http://localhost:3000/test/repo/wiki/index" rel="nofollow">index</a>&#39; (Wiki change comment) by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>`, pl.Message)
p.Action = api.HookWikiEdited
pl, err = tc.Wiki(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' edited (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Wiki page &#39;<a href="http://localhost:3000/test/repo/wiki/index" rel="nofollow">index</a>&#39; edited (Wiki change comment) by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>`, pl.Message)
p.Action = api.HookWikiDeleted
pl, err = tc.Wiki(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' deleted by <a href="https://try.gitea.io/user1">user1</a>`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Wiki page &#39;<a href="http://localhost:3000/test/repo/wiki/index" rel="nofollow">index</a>&#39; deleted by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>`, pl.Message)
})
t.Run("Release", func(t *testing.T) {
@ -162,7 +171,7 @@ func TestTelegramPayload(t *testing.T) {
pl, err := tc.Release(p)
require.NoError(t, err)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Release created: <a href="http://localhost:3000/test/repo/releases/tag/v1.0">v1.0</a> by <a href="https://try.gitea.io/user1">user1</a>`, pl.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Release created: <a href="http://localhost:3000/test/repo/releases/tag/v1.0" rel="nofollow">v1.0</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>`, pl.Message)
})
}
@ -198,5 +207,7 @@ func TestTelegramJSONPayload(t *testing.T) {
var body TelegramPayload
err = json.NewDecoder(req.Body).Decode(&body)
assert.NoError(t, err)
assert.Equal(t, "[<a href=\"http://localhost:3000/test/repo\">test/repo</a>:<a href=\"http://localhost:3000/test/repo/src/test\">test</a>] 2 new commits\n[<a href=\"http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778\">2020558</a>] commit message - user1\n[<a href=\"http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778\">2020558</a>] commit message - user1", body.Message)
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>:<a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a>] 2 new commits
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1`, body.Message)
}

@ -41,6 +41,8 @@ func newWechatworkMarkdownPayload(title string) WechatworkPayload {
}
}
type wechatworkConvertor struct{}
// Create implements PayloadConvertor Create method
func (wc wechatworkConvertor) Create(p *api.CreatePayload) (WechatworkPayload, error) {
// created tag/branch
@ -97,9 +99,9 @@ func (wc wechatworkConvertor) Push(p *api.PushPayload) (WechatworkPayload, error
// Issue implements PayloadConvertor Issue method
func (wc wechatworkConvertor) Issue(p *api.IssuePayload) (WechatworkPayload, error) {
text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
text, issueTitle, extraMarkdown, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
var content string
content += fmt.Sprintf(" ><font color=\"info\">%s</font>\n >%s \n ><font color=\"warning\"> %s</font> \n [%s](%s)", text, attachmentText, issueTitle, p.Issue.HTMLURL, p.Issue.HTMLURL)
content += fmt.Sprintf(" ><font color=\"info\">%s</font>\n >%s \n ><font color=\"warning\"> %s</font> \n [%s](%s)", text, extraMarkdown, issueTitle, p.Issue.HTMLURL, p.Issue.HTMLURL)
return newWechatworkMarkdownPayload(content), nil
}
@ -115,9 +117,9 @@ func (wc wechatworkConvertor) IssueComment(p *api.IssueCommentPayload) (Wechatwo
// PullRequest implements PayloadConvertor PullRequest method
func (wc wechatworkConvertor) PullRequest(p *api.PullRequestPayload) (WechatworkPayload, error) {
text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
text, issueTitle, extraMarkdown, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
pr := fmt.Sprintf("> <font color=\"info\"> %s </font> \r\n > <font color=\"comment\">%s </font> \r\n > <font color=\"comment\">%s </font> \r\n",
text, issueTitle, attachmentText)
text, issueTitle, extraMarkdown)
return newWechatworkMarkdownPayload(pr), nil
}
@ -173,10 +175,7 @@ func (wc wechatworkConvertor) Package(p *api.PackagePayload) (WechatworkPayload,
return newWechatworkMarkdownPayload(text), nil
}
type wechatworkConvertor struct{}
var _ payloadConvertor[WechatworkPayload] = wechatworkConvertor{}
func newWechatworkRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
return newJSONRequest(wechatworkConvertor{}, w, t, true)
var pc payloadConvertor[WechatworkPayload] = wechatworkConvertor{}
return newJSONRequest(pc, w, t, true)
}

Loading…
Cancel
Save