From b51bd7f1d62cd623601185162d84ac29adb25366 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 5 Sep 2020 10:57:13 +0800 Subject: [PATCH] Refactor webhook payload convertion (#12310) * Refactor webhook payload convertion * Fix lint Co-authored-by: techknowlogick --- modules/webhook/dingtalk.go | 74 +++++++--------- modules/webhook/dingtalk_test.go | 14 ++-- modules/webhook/discord.go | 116 +++++++++++-------------- modules/webhook/feishu.go | 73 +++++++--------- modules/webhook/matrix.go | 113 +++++++++++-------------- modules/webhook/matrix_test.go | 50 +++++------ modules/webhook/msteams.go | 75 +++++++---------- modules/webhook/payloader.go | 56 +++++++++++++ modules/webhook/slack.go | 140 ++++++++++++++----------------- modules/webhook/slack_test.go | 56 ++++++------- modules/webhook/telegram.go | 80 +++++++----------- modules/webhook/telegram_test.go | 4 +- 12 files changed, 397 insertions(+), 454 deletions(-) create mode 100644 modules/webhook/payloader.go diff --git a/modules/webhook/dingtalk.go b/modules/webhook/dingtalk.go index 4e0e52451..a9032db04 100644 --- a/modules/webhook/dingtalk.go +++ b/modules/webhook/dingtalk.go @@ -21,19 +21,24 @@ type ( DingtalkPayload dingtalk.Payload ) +var ( + _ PayloadConvertor = &DingtalkPayload{} +) + // SetSecret sets the dingtalk secret -func (p *DingtalkPayload) SetSecret(_ string) {} +func (d *DingtalkPayload) SetSecret(_ string) {} // JSONPayload Marshals the DingtalkPayload to json -func (p *DingtalkPayload) JSONPayload() ([]byte, error) { - data, err := json.MarshalIndent(p, "", " ") +func (d *DingtalkPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(d, "", " ") if err != nil { return []byte{}, err } return data, nil } -func getDingtalkCreatePayload(p *api.CreatePayload) (*DingtalkPayload, error) { +// Create implements PayloadConvertor Create method +func (d *DingtalkPayload) Create(p *api.CreatePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName) @@ -50,7 +55,8 @@ func getDingtalkCreatePayload(p *api.CreatePayload) (*DingtalkPayload, error) { }, nil } -func getDingtalkDeletePayload(p *api.DeletePayload) (*DingtalkPayload, error) { +// Delete implements PayloadConvertor Delete method +func (d *DingtalkPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName) @@ -67,7 +73,8 @@ func getDingtalkDeletePayload(p *api.DeletePayload) (*DingtalkPayload, error) { }, nil } -func getDingtalkForkPayload(p *api.ForkPayload) (*DingtalkPayload, error) { +// Fork implements PayloadConvertor Fork method +func (d *DingtalkPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName) return &DingtalkPayload{ @@ -82,7 +89,8 @@ func getDingtalkForkPayload(p *api.ForkPayload) (*DingtalkPayload, error) { }, nil } -func getDingtalkPushPayload(p *api.PushPayload) (*DingtalkPayload, error) { +// Push implements PayloadConvertor Push method +func (d *DingtalkPayload) Push(p *api.PushPayload) (api.Payloader, error) { var ( branchName = git.RefEndName(p.Ref) commitDesc string @@ -131,7 +139,8 @@ func getDingtalkPushPayload(p *api.PushPayload) (*DingtalkPayload, error) { }, nil } -func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) { +// Issue implements PayloadConvertor Issue method +func (d *DingtalkPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true) return &DingtalkPayload{ @@ -147,7 +156,8 @@ func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) { }, nil } -func getDingtalkIssueCommentPayload(p *api.IssueCommentPayload) (*DingtalkPayload, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (d *DingtalkPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true) return &DingtalkPayload{ @@ -162,7 +172,8 @@ func getDingtalkIssueCommentPayload(p *api.IssueCommentPayload) (*DingtalkPayloa }, nil } -func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (d *DingtalkPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true) return &DingtalkPayload{ @@ -178,7 +189,8 @@ func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload, }, nil } -func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*DingtalkPayload, error) { +// Review implements PayloadConvertor Review method +func (d *DingtalkPayload) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { var text, title string switch p.Action { case api.HookIssueReviewed: @@ -204,7 +216,8 @@ func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event mode }, nil } -func getDingtalkRepositoryPayload(p *api.RepositoryPayload) (*DingtalkPayload, error) { +// Repository implements PayloadConvertor Repository method +func (d *DingtalkPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { var title, url string switch p.Action { case api.HookRepoCreated: @@ -235,7 +248,8 @@ func getDingtalkRepositoryPayload(p *api.RepositoryPayload) (*DingtalkPayload, e return nil, nil } -func getDingtalkReleasePayload(p *api.ReleasePayload) (*DingtalkPayload, error) { +// Release implements PayloadConvertor Release method +func (d *DingtalkPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true) return &DingtalkPayload{ @@ -251,36 +265,6 @@ func getDingtalkReleasePayload(p *api.ReleasePayload) (*DingtalkPayload, error) } // GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload -func GetDingtalkPayload(p api.Payloader, event models.HookEventType, meta string) (*DingtalkPayload, error) { - s := new(DingtalkPayload) - - switch event { - case models.HookEventCreate: - return getDingtalkCreatePayload(p.(*api.CreatePayload)) - case models.HookEventDelete: - return getDingtalkDeletePayload(p.(*api.DeletePayload)) - case models.HookEventFork: - return getDingtalkForkPayload(p.(*api.ForkPayload)) - case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: - return getDingtalkIssuesPayload(p.(*api.IssuePayload)) - case models.HookEventIssueComment, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getDingtalkIssueCommentPayload(pl) - } - return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPush: - return getDingtalkPushPayload(p.(*api.PushPayload)) - case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, - models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: - return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewComment: - return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) - case models.HookEventRepository: - return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload)) - case models.HookEventRelease: - return getDingtalkReleasePayload(p.(*api.ReleasePayload)) - } - - return s, nil +func GetDingtalkPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { + return convertPayloader(new(DingtalkPayload), p, event) } diff --git a/modules/webhook/dingtalk_test.go b/modules/webhook/dingtalk_test.go index 4cb7a913e..e5aa0fca3 100644 --- a/modules/webhook/dingtalk_test.go +++ b/modules/webhook/dingtalk_test.go @@ -14,18 +14,18 @@ import ( func TestGetDingTalkIssuesPayload(t *testing.T) { p := issueTestPayload() - + d := new(DingtalkPayload) p.Action = api.HookIssueOpened - pl, err := getDingtalkIssuesPayload(p) + pl, err := d.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "#2 crash", pl.ActionCard.Title) - assert.Equal(t, "[test/repo] Issue opened: #2 crash by user1\r\n\r\n", pl.ActionCard.Text) + assert.Equal(t, "#2 crash", pl.(*DingtalkPayload).ActionCard.Title) + assert.Equal(t, "[test/repo] Issue opened: #2 crash by user1\r\n\r\n", pl.(*DingtalkPayload).ActionCard.Text) p.Action = api.HookIssueClosed - pl, err = getDingtalkIssuesPayload(p) + pl, err = d.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "#2 crash", pl.ActionCard.Title) - assert.Equal(t, "[test/repo] Issue closed: #2 crash by user1\r\n\r\n", pl.ActionCard.Text) + assert.Equal(t, "#2 crash", pl.(*DingtalkPayload).ActionCard.Title) + assert.Equal(t, "[test/repo] Issue closed: #2 crash by user1\r\n\r\n", pl.(*DingtalkPayload).ActionCard.Text) } diff --git a/modules/webhook/discord.go b/modules/webhook/discord.go index 761129d8d..530e7adbd 100644 --- a/modules/webhook/discord.go +++ b/modules/webhook/discord.go @@ -97,25 +97,30 @@ var ( ) // SetSecret sets the discord secret -func (p *DiscordPayload) SetSecret(_ string) {} +func (d *DiscordPayload) SetSecret(_ string) {} // JSONPayload Marshals the DiscordPayload to json -func (p *DiscordPayload) JSONPayload() ([]byte, error) { - data, err := json.MarshalIndent(p, "", " ") +func (d *DiscordPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(d, "", " ") if err != nil { return []byte{}, err } return data, nil } -func getDiscordCreatePayload(p *api.CreatePayload, meta *DiscordMeta) (*DiscordPayload, error) { +var ( + _ PayloadConvertor = &DiscordPayload{} +) + +// Create implements PayloadConvertor Create method +func (d *DiscordPayload) Create(p *api.CreatePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName) return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: title, @@ -131,14 +136,15 @@ func getDiscordCreatePayload(p *api.CreatePayload, meta *DiscordMeta) (*DiscordP }, nil } -func getDiscordDeletePayload(p *api.DeletePayload, meta *DiscordMeta) (*DiscordPayload, error) { +// Delete implements PayloadConvertor Delete method +func (d *DiscordPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { // deleted tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName) return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: title, @@ -154,13 +160,13 @@ func getDiscordDeletePayload(p *api.DeletePayload, meta *DiscordMeta) (*DiscordP }, nil } -func getDiscordForkPayload(p *api.ForkPayload, meta *DiscordMeta) (*DiscordPayload, error) { - // fork +// Fork implements PayloadConvertor Fork method +func (d *DiscordPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName) return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: title, @@ -176,7 +182,8 @@ func getDiscordForkPayload(p *api.ForkPayload, meta *DiscordMeta) (*DiscordPaylo }, nil } -func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPayload, error) { +// Push implements PayloadConvertor Push method +func (d *DiscordPayload) Push(p *api.PushPayload) (api.Payloader, error) { var ( branchName = git.RefEndName(p.Ref) commitDesc string @@ -208,8 +215,8 @@ func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPaylo } return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: title, @@ -226,12 +233,13 @@ func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPaylo }, nil } -func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPayload, error) { +// Issue implements PayloadConvertor Issue method +func (d *DiscordPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, _, attachmentText, color := getIssuesPayloadInfo(p, noneLinkFormatter, false) return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: text, @@ -248,12 +256,13 @@ func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPa }, nil } -func getDiscordIssueCommentPayload(p *api.IssueCommentPayload, discord *DiscordMeta) (*DiscordPayload, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (d *DiscordPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, _, color := getIssueCommentPayloadInfo(p, noneLinkFormatter, false) return &DiscordPayload{ - Username: discord.Username, - AvatarURL: discord.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: text, @@ -270,12 +279,13 @@ func getDiscordIssueCommentPayload(p *api.IssueCommentPayload, discord *DiscordM }, nil } -func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta) (*DiscordPayload, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (d *DiscordPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, _, attachmentText, color := getPullRequestPayloadInfo(p, noneLinkFormatter, false) return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: text, @@ -292,7 +302,8 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta) }, nil } -func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *DiscordMeta, event models.HookEventType) (*DiscordPayload, error) { +// Review implements PayloadConvertor Review method +func (d *DiscordPayload) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { var text, title string var color int switch p.Action { @@ -318,8 +329,8 @@ func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *Disco } return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: title, @@ -336,7 +347,8 @@ func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *Disco }, nil } -func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (*DiscordPayload, error) { +// Repository implements PayloadConvertor Repository method +func (d *DiscordPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { var title, url string var color int switch p.Action { @@ -350,8 +362,8 @@ func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (* } return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: title, @@ -367,12 +379,13 @@ func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (* }, nil } -func getDiscordReleasePayload(p *api.ReleasePayload, meta *DiscordMeta) (*DiscordPayload, error) { +// Release implements PayloadConvertor Release method +func (d *DiscordPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, color := getReleasePayloadInfo(p, noneLinkFormatter, false) return &DiscordPayload{ - Username: meta.Username, - AvatarURL: meta.IconURL, + Username: d.Username, + AvatarURL: d.AvatarURL, Embeds: []DiscordEmbed{ { Title: text, @@ -390,47 +403,20 @@ func getDiscordReleasePayload(p *api.ReleasePayload, meta *DiscordMeta) (*Discor } // GetDiscordPayload converts a discord webhook into a DiscordPayload -func GetDiscordPayload(p api.Payloader, event models.HookEventType, meta string) (*DiscordPayload, error) { +func GetDiscordPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { s := new(DiscordPayload) discord := &DiscordMeta{} if err := json.Unmarshal([]byte(meta), &discord); err != nil { return s, errors.New("GetDiscordPayload meta json:" + err.Error()) } + s.Username = discord.Username + s.AvatarURL = discord.IconURL - switch event { - case models.HookEventCreate: - return getDiscordCreatePayload(p.(*api.CreatePayload), discord) - case models.HookEventDelete: - return getDiscordDeletePayload(p.(*api.DeletePayload), discord) - case models.HookEventFork: - return getDiscordForkPayload(p.(*api.ForkPayload), discord) - case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: - return getDiscordIssuesPayload(p.(*api.IssuePayload), discord) - case models.HookEventIssueComment, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getDiscordIssueCommentPayload(pl, discord) - } - return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) - case models.HookEventPush: - return getDiscordPushPayload(p.(*api.PushPayload), discord) - case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, - models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: - return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) - case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: - return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event) - case models.HookEventRepository: - return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord) - case models.HookEventRelease: - return getDiscordReleasePayload(p.(*api.ReleasePayload), discord) - } - - return s, nil + return convertPayloader(s, p, event) } func parseHookPullRequestEventType(event models.HookEventType) (string, error) { - switch event { case models.HookEventPullRequestReviewApproved: diff --git a/modules/webhook/feishu.go b/modules/webhook/feishu.go index 4beda9014..8e60dbba1 100644 --- a/modules/webhook/feishu.go +++ b/modules/webhook/feishu.go @@ -23,18 +23,23 @@ type ( ) // SetSecret sets the Feishu secret -func (p *FeishuPayload) SetSecret(_ string) {} +func (f *FeishuPayload) SetSecret(_ string) {} // JSONPayload Marshals the FeishuPayload to json -func (p *FeishuPayload) JSONPayload() ([]byte, error) { - data, err := json.MarshalIndent(p, "", " ") +func (f *FeishuPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(f, "", " ") if err != nil { return []byte{}, err } return data, nil } -func getFeishuCreatePayload(p *api.CreatePayload) (*FeishuPayload, error) { +var ( + _ PayloadConvertor = &FeishuPayload{} +) + +// Create implements PayloadConvertor Create method +func (f *FeishuPayload) Create(p *api.CreatePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName) @@ -45,7 +50,8 @@ func getFeishuCreatePayload(p *api.CreatePayload) (*FeishuPayload, error) { }, nil } -func getFeishuDeletePayload(p *api.DeletePayload) (*FeishuPayload, error) { +// Delete implements PayloadConvertor Delete method +func (f *FeishuPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName) @@ -56,7 +62,8 @@ func getFeishuDeletePayload(p *api.DeletePayload) (*FeishuPayload, error) { }, nil } -func getFeishuForkPayload(p *api.ForkPayload) (*FeishuPayload, error) { +// Fork implements PayloadConvertor Fork method +func (f *FeishuPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName) return &FeishuPayload{ @@ -65,7 +72,8 @@ func getFeishuForkPayload(p *api.ForkPayload) (*FeishuPayload, error) { }, nil } -func getFeishuPushPayload(p *api.PushPayload) (*FeishuPayload, error) { +// Push implements PayloadConvertor Push method +func (f *FeishuPayload) Push(p *api.PushPayload) (api.Payloader, error) { var ( branchName = git.RefEndName(p.Ref) commitDesc string @@ -94,7 +102,8 @@ func getFeishuPushPayload(p *api.PushPayload) (*FeishuPayload, error) { }, nil } -func getFeishuIssuesPayload(p *api.IssuePayload) (*FeishuPayload, error) { +// Issue implements PayloadConvertor Issue method +func (f *FeishuPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true) return &FeishuPayload{ @@ -103,7 +112,8 @@ func getFeishuIssuesPayload(p *api.IssuePayload) (*FeishuPayload, error) { }, nil } -func getFeishuIssueCommentPayload(p *api.IssueCommentPayload) (*FeishuPayload, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (f *FeishuPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true) return &FeishuPayload{ @@ -112,7 +122,8 @@ func getFeishuIssueCommentPayload(p *api.IssueCommentPayload) (*FeishuPayload, e }, nil } -func getFeishuPullRequestPayload(p *api.PullRequestPayload) (*FeishuPayload, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true) return &FeishuPayload{ @@ -121,7 +132,8 @@ func getFeishuPullRequestPayload(p *api.PullRequestPayload) (*FeishuPayload, err }, nil } -func getFeishuPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*FeishuPayload, error) { +// Review implements PayloadConvertor Review method +func (f *FeishuPayload) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { var text, title string switch p.Action { case api.HookIssueSynchronized: @@ -141,7 +153,8 @@ func getFeishuPullRequestApprovalPayload(p *api.PullRequestPayload, event models }, nil } -func getFeishuRepositoryPayload(p *api.RepositoryPayload) (*FeishuPayload, error) { +// Repository implements PayloadConvertor Repository method +func (f *FeishuPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { var title string switch p.Action { case api.HookRepoCreated: @@ -161,7 +174,8 @@ func getFeishuRepositoryPayload(p *api.RepositoryPayload) (*FeishuPayload, error return nil, nil } -func getFeishuReleasePayload(p *api.ReleasePayload) (*FeishuPayload, error) { +// Release implements PayloadConvertor Release method +func (f *FeishuPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true) return &FeishuPayload{ @@ -171,35 +185,6 @@ func getFeishuReleasePayload(p *api.ReleasePayload) (*FeishuPayload, error) { } // 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, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getFeishuIssueCommentPayload(pl) - } - return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPush: - return getFeishuPushPayload(p.(*api.PushPayload)) - case models.HookEventPullRequest: - return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected: - 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 +func GetFeishuPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { + return convertPayloader(new(FeishuPayload), p, event) } diff --git a/modules/webhook/matrix.go b/modules/webhook/matrix.go index d6309000a..063147198 100644 --- a/modules/webhook/matrix.go +++ b/modules/webhook/matrix.go @@ -51,14 +51,18 @@ type MatrixPayloadUnsafe struct { AccessToken string `json:"access_token"` } +var ( + _ PayloadConvertor = &MatrixPayloadUnsafe{} +) + // safePayload "converts" a unsafe payload to a safe payload -func (p *MatrixPayloadUnsafe) safePayload() *MatrixPayloadSafe { +func (m *MatrixPayloadUnsafe) safePayload() *MatrixPayloadSafe { return &MatrixPayloadSafe{ - Body: p.Body, - MsgType: p.MsgType, - Format: p.Format, - FormattedBody: p.FormattedBody, - Commits: p.Commits, + Body: m.Body, + MsgType: m.MsgType, + Format: m.Format, + FormattedBody: m.FormattedBody, + Commits: m.Commits, } } @@ -72,11 +76,11 @@ type MatrixPayloadSafe struct { } // SetSecret sets the Matrix secret -func (p *MatrixPayloadUnsafe) SetSecret(_ string) {} +func (m *MatrixPayloadUnsafe) SetSecret(_ string) {} // JSONPayload Marshals the MatrixPayloadUnsafe to json -func (p *MatrixPayloadUnsafe) JSONPayload() ([]byte, error) { - data, err := json.MarshalIndent(p, "", " ") +func (m *MatrixPayloadUnsafe) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(m, "", " ") if err != nil { return []byte{}, err } @@ -101,51 +105,56 @@ func MatrixLinkToRef(repoURL, ref string) string { } } -func getMatrixCreatePayload(p *api.CreatePayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Create implements PayloadConvertor Create method +func (m *MatrixPayloadUnsafe) Create(p *api.CreatePayload) (api.Payloader, error) { repoLink := MatrixLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) refLink := MatrixLinkToRef(p.Repo.HTMLURL, p.Ref) text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -// getMatrixDeletePayload composes Matrix payload for delete a branch or tag. -func getMatrixDeletePayload(p *api.DeletePayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Delete composes Matrix payload for delete a branch or tag. +func (m *MatrixPayloadUnsafe) Delete(p *api.DeletePayload) (api.Payloader, error) { refName := git.RefEndName(p.Ref) repoLink := MatrixLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) text := fmt.Sprintf("[%s:%s] %s deleted by %s", repoLink, refName, p.RefType, p.Sender.UserName) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -// getMatrixForkPayload composes Matrix payload for forked by a repository. -func getMatrixForkPayload(p *api.ForkPayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Fork composes Matrix payload for forked by a repository. +func (m *MatrixPayloadUnsafe) Fork(p *api.ForkPayload) (api.Payloader, error) { baseLink := MatrixLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName) forkLink := MatrixLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -func getMatrixIssuesPayload(p *api.IssuePayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Issue implements PayloadConvertor Issue method +func (m *MatrixPayloadUnsafe) Issue(p *api.IssuePayload) (api.Payloader, error) { text, _, _, _ := getIssuesPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -func getMatrixIssueCommentPayload(p *api.IssueCommentPayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (m *MatrixPayloadUnsafe) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, _, _ := getIssueCommentPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -func getMatrixReleasePayload(p *api.ReleasePayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Release implements PayloadConvertor Release method +func (m *MatrixPayloadUnsafe) Release(p *api.ReleasePayload) (api.Payloader, error) { text, _ := getReleasePayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -func getMatrixPushPayload(p *api.PushPayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Push implements PayloadConvertor Push method +func (m *MatrixPayloadUnsafe) Push(p *api.PushPayload) (api.Payloader, error) { var commitDesc string if len(p.Commits) == 1 { @@ -168,16 +177,18 @@ func getMatrixPushPayload(p *api.PushPayload, matrix *MatrixMeta) (*MatrixPayloa } - return getMatrixPayloadUnsafe(text, p.Commits, matrix), nil + return getMatrixPayloadUnsafe(text, p.Commits, m.AccessToken, m.MsgType), nil } -func getMatrixPullRequestPayload(p *api.PullRequestPayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (m *MatrixPayloadUnsafe) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, _, _, _ := getPullRequestPayloadInfo(p, MatrixLinkFormatter, true) - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -func getMatrixPullRequestApprovalPayload(p *api.PullRequestPayload, matrix *MatrixMeta, event models.HookEventType) (*MatrixPayloadUnsafe, error) { +// Review implements PayloadConvertor Review method +func (m *MatrixPayloadUnsafe) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title) titleLink := fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index) @@ -194,10 +205,11 @@ func getMatrixPullRequestApprovalPayload(p *api.PullRequestPayload, matrix *Matr text = fmt.Sprintf("[%s] Pull request review %s: [%s](%s) by %s", repoLink, action, title, titleLink, senderLink) } - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } -func getMatrixRepositoryPayload(p *api.RepositoryPayload, matrix *MatrixMeta) (*MatrixPayloadUnsafe, error) { +// Repository implements PayloadConvertor Repository method +func (m *MatrixPayloadUnsafe) Repository(p *api.RepositoryPayload) (api.Payloader, error) { senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) repoLink := MatrixLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName) var text string @@ -209,11 +221,11 @@ func getMatrixRepositoryPayload(p *api.RepositoryPayload, matrix *MatrixMeta) (* text = fmt.Sprintf("[%s] Repository deleted by %s", repoLink, senderLink) } - return getMatrixPayloadUnsafe(text, nil, matrix), nil + return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil } // GetMatrixPayload converts a Matrix webhook into a MatrixPayloadUnsafe -func GetMatrixPayload(p api.Payloader, event models.HookEventType, meta string) (*MatrixPayloadUnsafe, error) { +func GetMatrixPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { s := new(MatrixPayloadUnsafe) matrix := &MatrixMeta{} @@ -221,44 +233,19 @@ func GetMatrixPayload(p api.Payloader, event models.HookEventType, meta string) return s, errors.New("GetMatrixPayload meta json:" + err.Error()) } - switch event { - case models.HookEventCreate: - return getMatrixCreatePayload(p.(*api.CreatePayload), matrix) - case models.HookEventDelete: - return getMatrixDeletePayload(p.(*api.DeletePayload), matrix) - case models.HookEventFork: - return getMatrixForkPayload(p.(*api.ForkPayload), matrix) - case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: - return getMatrixIssuesPayload(p.(*api.IssuePayload), matrix) - case models.HookEventIssueComment, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getMatrixIssueCommentPayload(pl, matrix) - } - return getMatrixPullRequestPayload(p.(*api.PullRequestPayload), matrix) - case models.HookEventPush: - return getMatrixPushPayload(p.(*api.PushPayload), matrix) - case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, - models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: - return getMatrixPullRequestPayload(p.(*api.PullRequestPayload), matrix) - case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: - return getMatrixPullRequestApprovalPayload(p.(*api.PullRequestPayload), matrix, event) - case models.HookEventRepository: - return getMatrixRepositoryPayload(p.(*api.RepositoryPayload), matrix) - case models.HookEventRelease: - return getMatrixReleasePayload(p.(*api.ReleasePayload), matrix) - } + s.AccessToken = matrix.AccessToken + s.MsgType = messageTypeText[matrix.MessageType] - return s, nil + return convertPayloader(s, p, event) } -func getMatrixPayloadUnsafe(text string, commits []*api.PayloadCommit, matrix *MatrixMeta) *MatrixPayloadUnsafe { +func getMatrixPayloadUnsafe(text string, commits []*api.PayloadCommit, accessToken, msgType string) *MatrixPayloadUnsafe { p := MatrixPayloadUnsafe{} - p.AccessToken = matrix.AccessToken + p.AccessToken = accessToken p.FormattedBody = text p.Body = getMessageBody(text) p.Format = "org.matrix.custom.html" - p.MsgType = messageTypeText[matrix.MessageType] + p.MsgType = msgType p.Commits = commits return &p } diff --git a/modules/webhook/matrix_test.go b/modules/webhook/matrix_test.go index 3d1c66012..771146f2f 100644 --- a/modules/webhook/matrix_test.go +++ b/modules/webhook/matrix_test.go @@ -16,73 +16,69 @@ import ( func TestMatrixIssuesPayloadOpened(t *testing.T) { p := issueTestPayload() - sl := &MatrixMeta{} + m := new(MatrixPayloadUnsafe) p.Action = api.HookIssueOpened - pl, err := getMatrixIssuesPayload(p, sl) + pl, err := m.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue opened: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.Body) - assert.Equal(t, "[test/repo] Issue opened: #2 crash by user1", pl.FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue opened: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) + assert.Equal(t, "[test/repo] Issue opened: #2 crash by user1", pl.(*MatrixPayloadUnsafe).FormattedBody) p.Action = api.HookIssueClosed - pl, err = getMatrixIssuesPayload(p, sl) + pl, err = m.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue closed: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.Body) - assert.Equal(t, "[test/repo] Issue closed: #2 crash by user1", pl.FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Issue closed: [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) + assert.Equal(t, "[test/repo] Issue closed: #2 crash by user1", pl.(*MatrixPayloadUnsafe).FormattedBody) } func TestMatrixIssueCommentPayload(t *testing.T) { p := issueCommentTestPayload() + m := new(MatrixPayloadUnsafe) - sl := &MatrixMeta{} - - pl, err := getMatrixIssueCommentPayload(p, sl) + pl, err := m.IssueComment(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on issue [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.Body) - assert.Equal(t, "[test/repo] New comment on issue #2 crash by user1", pl.FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on issue [#2 crash](http://localhost:3000/test/repo/issues/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) + assert.Equal(t, "[test/repo] New comment on issue #2 crash by user1", pl.(*MatrixPayloadUnsafe).FormattedBody) } func TestMatrixPullRequestCommentPayload(t *testing.T) { p := pullRequestCommentTestPayload() + m := new(MatrixPayloadUnsafe) - sl := &MatrixMeta{} - - pl, err := getMatrixIssueCommentPayload(p, sl) + pl, err := m.IssueComment(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on pull request [#2 Fix bug](http://localhost:3000/test/repo/pulls/2) by [user1](https://try.gitea.io/user1)", pl.Body) - assert.Equal(t, "[test/repo] New comment on pull request #2 Fix bug by user1", pl.FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New comment on pull request [#2 Fix bug](http://localhost:3000/test/repo/pulls/2) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) + assert.Equal(t, "[test/repo] New comment on pull request #2 Fix bug by user1", pl.(*MatrixPayloadUnsafe).FormattedBody) } func TestMatrixReleasePayload(t *testing.T) { p := pullReleaseTestPayload() + m := new(MatrixPayloadUnsafe) - sl := &MatrixMeta{} - - pl, err := getMatrixReleasePayload(p, sl) + pl, err := m.Release(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Release created: [v1.0](http://localhost:3000/test/repo/src/v1.0) by [user1](https://try.gitea.io/user1)", pl.Body) - assert.Equal(t, "[test/repo] Release created: v1.0 by user1", pl.FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Release created: [v1.0](http://localhost:3000/test/repo/src/v1.0) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) + assert.Equal(t, "[test/repo] Release created: v1.0 by user1", pl.(*MatrixPayloadUnsafe).FormattedBody) } func TestMatrixPullRequestPayload(t *testing.T) { p := pullRequestTestPayload() + m := new(MatrixPayloadUnsafe) - sl := &MatrixMeta{} - - pl, err := getMatrixPullRequestPayload(p, sl) + pl, err := m.PullRequest(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Pull request opened: [#2 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.Body) - assert.Equal(t, "[test/repo] Pull request opened: #2 Fix bug by user1", pl.FormattedBody) + assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Pull request opened: [#2 Fix bug](http://localhost:3000/test/repo/pulls/12) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body) + assert.Equal(t, "[test/repo] Pull request opened: #2 Fix bug by user1", pl.(*MatrixPayloadUnsafe).FormattedBody) } func TestMatrixHookRequest(t *testing.T) { diff --git a/modules/webhook/msteams.go b/modules/webhook/msteams.go index e7ec396f2..80998d9f8 100644 --- a/modules/webhook/msteams.go +++ b/modules/webhook/msteams.go @@ -56,18 +56,23 @@ type ( ) // SetSecret sets the MSTeams secret -func (p *MSTeamsPayload) SetSecret(_ string) {} +func (m *MSTeamsPayload) SetSecret(_ string) {} // JSONPayload Marshals the MSTeamsPayload to json -func (p *MSTeamsPayload) JSONPayload() ([]byte, error) { - data, err := json.MarshalIndent(p, "", " ") +func (m *MSTeamsPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(m, "", " ") if err != nil { return []byte{}, err } return data, nil } -func getMSTeamsCreatePayload(p *api.CreatePayload) (*MSTeamsPayload, error) { +var ( + _ PayloadConvertor = &MSTeamsPayload{} +) + +// Create implements PayloadConvertor Create method +func (m *MSTeamsPayload) Create(p *api.CreatePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName) @@ -110,7 +115,8 @@ func getMSTeamsCreatePayload(p *api.CreatePayload) (*MSTeamsPayload, error) { }, nil } -func getMSTeamsDeletePayload(p *api.DeletePayload) (*MSTeamsPayload, error) { +// Delete implements PayloadConvertor Delete method +func (m *MSTeamsPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { // deleted tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName) @@ -153,8 +159,8 @@ func getMSTeamsDeletePayload(p *api.DeletePayload) (*MSTeamsPayload, error) { }, nil } -func getMSTeamsForkPayload(p *api.ForkPayload) (*MSTeamsPayload, error) { - // fork +// Fork implements PayloadConvertor Fork method +func (m *MSTeamsPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName) return &MSTeamsPayload{ @@ -195,7 +201,8 @@ func getMSTeamsForkPayload(p *api.ForkPayload) (*MSTeamsPayload, error) { }, nil } -func getMSTeamsPushPayload(p *api.PushPayload) (*MSTeamsPayload, error) { +// Push implements PayloadConvertor Push method +func (m *MSTeamsPayload) Push(p *api.PushPayload) (api.Payloader, error) { var ( branchName = git.RefEndName(p.Ref) commitDesc string @@ -265,7 +272,8 @@ func getMSTeamsPushPayload(p *api.PushPayload) (*MSTeamsPayload, error) { }, nil } -func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) { +// Issue implements PayloadConvertor Issue method +func (m *MSTeamsPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, _, attachmentText, color := getIssuesPayloadInfo(p, noneLinkFormatter, false) return &MSTeamsPayload{ @@ -307,7 +315,8 @@ func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) { }, nil } -func getMSTeamsIssueCommentPayload(p *api.IssueCommentPayload) (*MSTeamsPayload, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (m *MSTeamsPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, _, color := getIssueCommentPayloadInfo(p, noneLinkFormatter, false) return &MSTeamsPayload{ @@ -349,7 +358,8 @@ func getMSTeamsIssueCommentPayload(p *api.IssueCommentPayload) (*MSTeamsPayload, }, nil } -func getMSTeamsPullRequestPayload(p *api.PullRequestPayload) (*MSTeamsPayload, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (m *MSTeamsPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, _, attachmentText, color := getPullRequestPayloadInfo(p, noneLinkFormatter, false) return &MSTeamsPayload{ @@ -391,7 +401,8 @@ func getMSTeamsPullRequestPayload(p *api.PullRequestPayload) (*MSTeamsPayload, e }, nil } -func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*MSTeamsPayload, error) { +// Review implements PayloadConvertor Review method +func (m *MSTeamsPayload) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { var text, title string var color int switch p.Action { @@ -455,7 +466,8 @@ func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event model }, nil } -func getMSTeamsRepositoryPayload(p *api.RepositoryPayload) (*MSTeamsPayload, error) { +// Repository implements PayloadConvertor Repository method +func (m *MSTeamsPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { var title, url string var color int switch p.Action { @@ -502,7 +514,8 @@ func getMSTeamsRepositoryPayload(p *api.RepositoryPayload) (*MSTeamsPayload, err }, nil } -func getMSTeamsReleasePayload(p *api.ReleasePayload) (*MSTeamsPayload, error) { +// Release implements PayloadConvertor Release method +func (m *MSTeamsPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, color := getReleasePayloadInfo(p, noneLinkFormatter, false) return &MSTeamsPayload{ @@ -545,36 +558,6 @@ func getMSTeamsReleasePayload(p *api.ReleasePayload) (*MSTeamsPayload, error) { } // GetMSTeamsPayload converts a MSTeams webhook into a MSTeamsPayload -func GetMSTeamsPayload(p api.Payloader, event models.HookEventType, meta string) (*MSTeamsPayload, error) { - s := new(MSTeamsPayload) - - switch event { - case models.HookEventCreate: - return getMSTeamsCreatePayload(p.(*api.CreatePayload)) - case models.HookEventDelete: - return getMSTeamsDeletePayload(p.(*api.DeletePayload)) - case models.HookEventFork: - return getMSTeamsForkPayload(p.(*api.ForkPayload)) - case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: - return getMSTeamsIssuesPayload(p.(*api.IssuePayload)) - case models.HookEventIssueComment, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getMSTeamsIssueCommentPayload(pl) - } - return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPush: - return getMSTeamsPushPayload(p.(*api.PushPayload)) - case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, - models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: - return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: - return getMSTeamsPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) - case models.HookEventRepository: - return getMSTeamsRepositoryPayload(p.(*api.RepositoryPayload)) - case models.HookEventRelease: - return getMSTeamsReleasePayload(p.(*api.ReleasePayload)) - } - - return s, nil +func GetMSTeamsPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { + return convertPayloader(new(MSTeamsPayload), p, event) } diff --git a/modules/webhook/payloader.go b/modules/webhook/payloader.go new file mode 100644 index 000000000..f1cdaf659 --- /dev/null +++ b/modules/webhook/payloader.go @@ -0,0 +1,56 @@ +// 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 ( + "code.gitea.io/gitea/models" + api "code.gitea.io/gitea/modules/structs" +) + +// PayloadConvertor defines the interface to convert system webhook payload to external payload +type PayloadConvertor interface { + api.Payloader + Create(*api.CreatePayload) (api.Payloader, error) + Delete(*api.DeletePayload) (api.Payloader, error) + Fork(*api.ForkPayload) (api.Payloader, error) + Issue(*api.IssuePayload) (api.Payloader, error) + IssueComment(*api.IssueCommentPayload) (api.Payloader, error) + Push(*api.PushPayload) (api.Payloader, error) + PullRequest(*api.PullRequestPayload) (api.Payloader, error) + Review(*api.PullRequestPayload, models.HookEventType) (api.Payloader, error) + Repository(*api.RepositoryPayload) (api.Payloader, error) + Release(*api.ReleasePayload) (api.Payloader, error) +} + +func convertPayloader(s PayloadConvertor, p api.Payloader, event models.HookEventType) (api.Payloader, error) { + switch event { + case models.HookEventCreate: + return s.Create(p.(*api.CreatePayload)) + case models.HookEventDelete: + return s.Delete(p.(*api.DeletePayload)) + case models.HookEventFork: + return s.Fork(p.(*api.ForkPayload)) + case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: + return s.Issue(p.(*api.IssuePayload)) + case models.HookEventIssueComment, models.HookEventPullRequestComment: + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return s.IssueComment(pl) + } + return s.PullRequest(p.(*api.PullRequestPayload)) + case models.HookEventPush: + return s.Push(p.(*api.PushPayload)) + case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, + models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: + return s.PullRequest(p.(*api.PullRequestPayload)) + case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewComment: + return s.Review(p.(*api.PullRequestPayload), event) + case models.HookEventRepository: + return s.Repository(p.(*api.RepositoryPayload)) + case models.HookEventRelease: + return s.Release(p.(*api.ReleasePayload)) + } + return s, nil +} diff --git a/modules/webhook/slack.go b/modules/webhook/slack.go index 4177bd125..4c0b50eca 100644 --- a/modules/webhook/slack.go +++ b/modules/webhook/slack.go @@ -38,6 +38,7 @@ func GetSlackHook(w *models.Webhook) *SlackMeta { type SlackPayload struct { Channel string `json:"channel"` Text string `json:"text"` + Color string `json:"-"` Username string `json:"username"` IconURL string `json:"icon_url"` UnfurlLinks int `json:"unfurl_links"` @@ -55,11 +56,11 @@ type SlackAttachment struct { } // SetSecret sets the slack secret -func (p *SlackPayload) SetSecret(_ string) {} +func (s *SlackPayload) SetSecret(_ string) {} // JSONPayload Marshals the SlackPayload to json -func (p *SlackPayload) JSONPayload() ([]byte, error) { - data, err := json.MarshalIndent(p, "", " ") +func (s *SlackPayload) JSONPayload() ([]byte, error) { + data, err := json.MarshalIndent(s, "", " ") if err != nil { return []byte{}, err } @@ -98,53 +99,59 @@ func SlackLinkToRef(repoURL, ref string) string { return SlackLinkFormatter(url, refName) } -func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayload, error) { +var ( + _ PayloadConvertor = &SlackPayload{} +) + +// Create implements PayloadConvertor Create method +func (s *SlackPayload) Create(p *api.CreatePayload) (api.Payloader, error) { repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) refLink := SlackLinkToRef(p.Repo.HTMLURL, p.Ref) text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName) return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, }, nil } -// getSlackDeletePayload composes Slack payload for delete a branch or tag. -func getSlackDeletePayload(p *api.DeletePayload, slack *SlackMeta) (*SlackPayload, error) { +// Delete composes Slack payload for delete a branch or tag. +func (s *SlackPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { refName := git.RefEndName(p.Ref) repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) text := fmt.Sprintf("[%s:%s] %s deleted by %s", repoLink, refName, p.RefType, p.Sender.UserName) return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, }, nil } -// getSlackForkPayload composes Slack payload for forked by a repository. -func getSlackForkPayload(p *api.ForkPayload, slack *SlackMeta) (*SlackPayload, error) { +// Fork composes Slack payload for forked by a repository. +func (s *SlackPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { baseLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName) forkLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName) text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink) return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, }, nil } -func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload, error) { +// Issue implements PayloadConvertor Issue method +func (s *SlackPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, issueTitle, attachmentText, color := getIssuesPayloadInfo(p, SlackLinkFormatter, true) pl := &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, } if attachmentText != "" { attachmentText = SlackTextFormatter(attachmentText) @@ -160,14 +167,15 @@ func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload return pl, nil } -func getSlackIssueCommentPayload(p *api.IssueCommentPayload, slack *SlackMeta) (*SlackPayload, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (s *SlackPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, issueTitle, color := getIssueCommentPayloadInfo(p, SlackLinkFormatter, true) return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, Attachments: []SlackAttachment{{ Color: fmt.Sprintf("%x", color), Title: issueTitle, @@ -177,18 +185,20 @@ func getSlackIssueCommentPayload(p *api.IssueCommentPayload, slack *SlackMeta) ( }, nil } -func getSlackReleasePayload(p *api.ReleasePayload, slack *SlackMeta) (*SlackPayload, error) { +// Release implements PayloadConvertor Release method +func (s *SlackPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, _ := getReleasePayloadInfo(p, SlackLinkFormatter, true) return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, }, nil } -func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, error) { +// Push implements PayloadConvertor Push method +func (s *SlackPayload) Push(p *api.PushPayload) (api.Payloader, error) { // n new commits var ( commitDesc string @@ -221,12 +231,12 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e } return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, Attachments: []SlackAttachment{{ - Color: slack.Color, + Color: s.Color, Title: p.Repo.HTMLURL, TitleLink: p.Repo.HTMLURL, Text: attachmentText, @@ -234,14 +244,15 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e }, nil } -func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*SlackPayload, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (s *SlackPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, issueTitle, attachmentText, color := getPullRequestPayloadInfo(p, SlackLinkFormatter, true) pl := &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, } if attachmentText != "" { attachmentText = SlackTextFormatter(p.PullRequest.Body) @@ -257,7 +268,8 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S return pl, nil } -func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackMeta, event models.HookEventType) (*SlackPayload, error) { +// Review implements PayloadConvertor Review method +func (s *SlackPayload) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title) titleLink := fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index) @@ -275,14 +287,15 @@ func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackM } return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, }, nil } -func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) { +// Repository implements PayloadConvertor Repository method +func (s *SlackPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName) var text string @@ -295,15 +308,15 @@ func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*Sla } return &SlackPayload{ - Channel: slack.Channel, + Channel: s.Channel, Text: text, - Username: slack.Username, - IconURL: slack.IconURL, + Username: s.Username, + IconURL: s.IconURL, }, nil } // GetSlackPayload converts a slack webhook into a SlackPayload -func GetSlackPayload(p api.Payloader, event models.HookEventType, meta string) (*SlackPayload, error) { +func GetSlackPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { s := new(SlackPayload) slack := &SlackMeta{} @@ -311,33 +324,10 @@ func GetSlackPayload(p api.Payloader, event models.HookEventType, meta string) ( return s, errors.New("GetSlackPayload meta json:" + err.Error()) } - switch event { - case models.HookEventCreate: - return getSlackCreatePayload(p.(*api.CreatePayload), slack) - case models.HookEventDelete: - return getSlackDeletePayload(p.(*api.DeletePayload), slack) - case models.HookEventFork: - return getSlackForkPayload(p.(*api.ForkPayload), slack) - case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: - return getSlackIssuesPayload(p.(*api.IssuePayload), slack) - case models.HookEventIssueComment, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getSlackIssueCommentPayload(pl, slack) - } - return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) - case models.HookEventPush: - return getSlackPushPayload(p.(*api.PushPayload), slack) - case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, - models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: - return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) - case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: - return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event) - case models.HookEventRepository: - return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack) - case models.HookEventRelease: - return getSlackReleasePayload(p.(*api.ReleasePayload), slack) - } + s.Channel = slack.Channel + s.Username = slack.Username + s.IconURL = slack.IconURL + s.Color = slack.Color - return s, nil + return convertPayloader(s, p, event) } diff --git a/modules/webhook/slack_test.go b/modules/webhook/slack_test.go index 15503434f..20de80bd6 100644 --- a/modules/webhook/slack_test.go +++ b/modules/webhook/slack_test.go @@ -14,75 +14,67 @@ import ( func TestSlackIssuesPayloadOpened(t *testing.T) { p := issueTestPayload() - sl := &SlackMeta{ - Username: p.Sender.UserName, - } - p.Action = api.HookIssueOpened - pl, err := getSlackIssuesPayload(p, sl) + + s := new(SlackPayload) + s.Username = p.Sender.UserName + + pl, err := s.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[] Issue opened: by ", pl.Text) + assert.Equal(t, "[] Issue opened: by ", pl.(*SlackPayload).Text) p.Action = api.HookIssueClosed - pl, err = getSlackIssuesPayload(p, sl) + pl, err = s.Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[] Issue closed: by ", pl.Text) + assert.Equal(t, "[] Issue closed: by ", pl.(*SlackPayload).Text) } func TestSlackIssueCommentPayload(t *testing.T) { p := issueCommentTestPayload() + s := new(SlackPayload) + s.Username = p.Sender.UserName - sl := &SlackMeta{ - Username: p.Sender.UserName, - } - - pl, err := getSlackIssueCommentPayload(p, sl) + pl, err := s.IssueComment(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[] New comment on issue by ", pl.Text) + assert.Equal(t, "[] New comment on issue by ", pl.(*SlackPayload).Text) } func TestSlackPullRequestCommentPayload(t *testing.T) { p := pullRequestCommentTestPayload() + s := new(SlackPayload) + s.Username = p.Sender.UserName - sl := &SlackMeta{ - Username: p.Sender.UserName, - } - - pl, err := getSlackIssueCommentPayload(p, sl) + pl, err := s.IssueComment(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[] New comment on pull request by ", pl.Text) + assert.Equal(t, "[] New comment on pull request by ", pl.(*SlackPayload).Text) } func TestSlackReleasePayload(t *testing.T) { p := pullReleaseTestPayload() + s := new(SlackPayload) + s.Username = p.Sender.UserName - sl := &SlackMeta{ - Username: p.Sender.UserName, - } - - pl, err := getSlackReleasePayload(p, sl) + pl, err := s.Release(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[] Release created: by ", pl.Text) + assert.Equal(t, "[] Release created: by ", pl.(*SlackPayload).Text) } func TestSlackPullRequestPayload(t *testing.T) { p := pullRequestTestPayload() + s := new(SlackPayload) + s.Username = p.Sender.UserName - sl := &SlackMeta{ - Username: p.Sender.UserName, - } - - pl, err := getSlackPullRequestPayload(p, sl) + pl, err := s.PullRequest(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[] Pull request opened: by ", pl.Text) + assert.Equal(t, "[] Pull request opened: by ", pl.(*SlackPayload).Text) } diff --git a/modules/webhook/telegram.go b/modules/webhook/telegram.go index 6d2f804a7..84fc21004 100644 --- a/modules/webhook/telegram.go +++ b/modules/webhook/telegram.go @@ -40,22 +40,27 @@ func GetTelegramHook(w *models.Webhook) *TelegramMeta { return s } +var ( + _ PayloadConvertor = &TelegramPayload{} +) + // SetSecret sets the telegram secret -func (p *TelegramPayload) SetSecret(_ string) {} +func (t *TelegramPayload) SetSecret(_ string) {} // JSONPayload Marshals the TelegramPayload to json -func (p *TelegramPayload) JSONPayload() ([]byte, error) { - p.ParseMode = "HTML" - p.DisableWebPreview = true - p.Message = markup.Sanitize(p.Message) - data, err := json.MarshalIndent(p, "", " ") +func (t *TelegramPayload) JSONPayload() ([]byte, error) { + t.ParseMode = "HTML" + t.DisableWebPreview = true + t.Message = markup.Sanitize(t.Message) + data, err := json.MarshalIndent(t, "", " ") if err != nil { return []byte{}, err } return data, nil } -func getTelegramCreatePayload(p *api.CreatePayload) (*TelegramPayload, error) { +// Create implements PayloadConvertor Create method +func (t *TelegramPayload) Create(p *api.CreatePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf(`[%s] %s %s created`, p.Repo.HTMLURL, p.Repo.FullName, p.RefType, @@ -66,7 +71,8 @@ func getTelegramCreatePayload(p *api.CreatePayload) (*TelegramPayload, error) { }, nil } -func getTelegramDeletePayload(p *api.DeletePayload) (*TelegramPayload, error) { +// Delete implements PayloadConvertor Delete method +func (t *TelegramPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { // created tag/branch refName := git.RefEndName(p.Ref) title := fmt.Sprintf(`[%s] %s %s deleted`, p.Repo.HTMLURL, p.Repo.FullName, p.RefType, @@ -77,7 +83,8 @@ func getTelegramDeletePayload(p *api.DeletePayload) (*TelegramPayload, error) { }, nil } -func getTelegramForkPayload(p *api.ForkPayload) (*TelegramPayload, error) { +// Fork implements PayloadConvertor Fork method +func (t *TelegramPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { title := fmt.Sprintf(`%s is forked to %s`, p.Forkee.FullName, p.Repo.HTMLURL, p.Repo.FullName) return &TelegramPayload{ @@ -85,7 +92,8 @@ func getTelegramForkPayload(p *api.ForkPayload) (*TelegramPayload, error) { }, nil } -func getTelegramPushPayload(p *api.PushPayload) (*TelegramPayload, error) { +// Push implements PayloadConvertor Push method +func (t *TelegramPayload) Push(p *api.PushPayload) (api.Payloader, error) { var ( branchName = git.RefEndName(p.Ref) commitDesc string @@ -124,7 +132,8 @@ func getTelegramPushPayload(p *api.PushPayload) (*TelegramPayload, error) { }, nil } -func getTelegramIssuesPayload(p *api.IssuePayload) (*TelegramPayload, error) { +// Issue implements PayloadConvertor Issue method +func (t *TelegramPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { text, _, attachmentText, _ := getIssuesPayloadInfo(p, htmlLinkFormatter, true) return &TelegramPayload{ @@ -132,7 +141,8 @@ func getTelegramIssuesPayload(p *api.IssuePayload) (*TelegramPayload, error) { }, nil } -func getTelegramIssueCommentPayload(p *api.IssueCommentPayload) (*TelegramPayload, error) { +// IssueComment implements PayloadConvertor IssueComment method +func (t *TelegramPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { text, _, _ := getIssueCommentPayloadInfo(p, htmlLinkFormatter, true) return &TelegramPayload{ @@ -140,7 +150,8 @@ func getTelegramIssueCommentPayload(p *api.IssueCommentPayload) (*TelegramPayloa }, nil } -func getTelegramPullRequestPayload(p *api.PullRequestPayload) (*TelegramPayload, error) { +// PullRequest implements PayloadConvertor PullRequest method +func (t *TelegramPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { text, _, attachmentText, _ := getPullRequestPayloadInfo(p, htmlLinkFormatter, true) return &TelegramPayload{ @@ -148,7 +159,8 @@ func getTelegramPullRequestPayload(p *api.PullRequestPayload) (*TelegramPayload, }, nil } -func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*TelegramPayload, error) { +// Review implements PayloadConvertor Review method +func (t *TelegramPayload) Review(p *api.PullRequestPayload, event models.HookEventType) (api.Payloader, error) { var text, attachmentText string switch p.Action { case api.HookIssueReviewed: @@ -167,7 +179,8 @@ func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event mode }, nil } -func getTelegramRepositoryPayload(p *api.RepositoryPayload) (*TelegramPayload, error) { +// Repository implements PayloadConvertor Repository method +func (t *TelegramPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { var title string switch p.Action { case api.HookRepoCreated: @@ -184,7 +197,8 @@ func getTelegramRepositoryPayload(p *api.RepositoryPayload) (*TelegramPayload, e return nil, nil } -func getTelegramReleasePayload(p *api.ReleasePayload) (*TelegramPayload, error) { +// Release implements PayloadConvertor Release method +func (t *TelegramPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { text, _ := getReleasePayloadInfo(p, htmlLinkFormatter, true) return &TelegramPayload{ @@ -193,36 +207,6 @@ func getTelegramReleasePayload(p *api.ReleasePayload) (*TelegramPayload, error) } // GetTelegramPayload converts a telegram webhook into a TelegramPayload -func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string) (*TelegramPayload, error) { - s := new(TelegramPayload) - - switch event { - case models.HookEventCreate: - return getTelegramCreatePayload(p.(*api.CreatePayload)) - case models.HookEventDelete: - return getTelegramDeletePayload(p.(*api.DeletePayload)) - case models.HookEventFork: - return getTelegramForkPayload(p.(*api.ForkPayload)) - case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: - return getTelegramIssuesPayload(p.(*api.IssuePayload)) - case models.HookEventIssueComment, models.HookEventPullRequestComment: - pl, ok := p.(*api.IssueCommentPayload) - if ok { - return getTelegramIssueCommentPayload(pl) - } - return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPush: - return getTelegramPushPayload(p.(*api.PushPayload)) - case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, - models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: - return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: - return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) - case models.HookEventRepository: - return getTelegramRepositoryPayload(p.(*api.RepositoryPayload)) - case models.HookEventRelease: - return getTelegramReleasePayload(p.(*api.ReleasePayload)) - } - - return s, nil +func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string) (api.Payloader, error) { + return convertPayloader(new(TelegramPayload), p, event) } diff --git a/modules/webhook/telegram_test.go b/modules/webhook/telegram_test.go index 1686188b9..0e909343a 100644 --- a/modules/webhook/telegram_test.go +++ b/modules/webhook/telegram_test.go @@ -16,9 +16,9 @@ func TestGetTelegramIssuesPayload(t *testing.T) { p := issueTestPayload() p.Action = api.HookIssueClosed - pl, err := getTelegramIssuesPayload(p) + pl, err := new(TelegramPayload).Issue(p) require.NoError(t, err) require.NotNil(t, pl) - assert.Equal(t, "[test/repo] Issue closed: #2 crash by user1\n\n", pl.Message) + assert.Equal(t, "[test/repo] Issue closed: #2 crash by user1\n\n", pl.(*TelegramPayload).Message) }