Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor webhooks to reduce code duplication #9422

Merged
merged 13 commits into from
Dec 28, 2019
51 changes: 8 additions & 43 deletions modules/webhook/discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,56 +227,21 @@ func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPaylo
}

func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPayload, error) {
var text, title string
var color int
url := fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index)
switch p.Action {
case api.HookIssueOpened:
title = fmt.Sprintf("[%s] Issue opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
text = p.Issue.Body
color = orangeColor
case api.HookIssueClosed:
title = fmt.Sprintf("[%s] Issue closed: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = redColor
case api.HookIssueReOpened:
title = fmt.Sprintf("[%s] Issue re-opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueEdited:
title = fmt.Sprintf("[%s] Issue edited: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
text = p.Issue.Body
color = yellowColor
case api.HookIssueAssigned:
title = fmt.Sprintf("[%s] Issue assigned to %s: #%d %s", p.Repository.FullName,
p.Issue.Assignee.UserName, p.Index, p.Issue.Title)
color = greenColor
case api.HookIssueUnassigned:
title = fmt.Sprintf("[%s] Issue unassigned: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueLabelUpdated:
title = fmt.Sprintf("[%s] Issue labels updated: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueLabelCleared:
title = fmt.Sprintf("[%s] Issue labels cleared: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueSynchronized:
title = fmt.Sprintf("[%s] Issue synchronized: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueMilestoned:
title = fmt.Sprintf("[%s] Issue milestone: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueDemilestoned:
title = fmt.Sprintf("[%s] Issue clear milestone: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
text, _, color := getIssuesPayloadInfo(p, noneLinkFormatter)

var attachmentText string
if p.Action == api.HookIssueOpened || p.Action == api.HookIssueEdited {
attachmentText = p.Issue.Body
}

return &DiscordPayload{
Username: meta.Username,
AvatarURL: meta.IconURL,
Embeds: []DiscordEmbed{
{
Title: title,
Description: text,
URL: url,
Title: text,
Description: attachmentText,
URL: p.Issue.URL,
Color: color,
Author: DiscordEmbedAuthor{
Name: p.Sender.UserName,
Expand Down
109 changes: 109 additions & 0 deletions modules/webhook/general.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package webhook
cornelk marked this conversation as resolved.
Show resolved Hide resolved

import (
"fmt"
"strings"

"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
)

type linkFormatter = func(string, string) string

func noneLinkFormatter(url string, text string) string {
return text
}

func htmlLinkFormatter(url string, text string) string {
return fmt.Sprintf(`<a href="%s">%s</a>`, url, text)
}

func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter) (string, string, int) {
senderLink := linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
issueTitle := fmt.Sprintf("#%d %s", p.Index, p.Issue.Title)
titleLink := linkFormatter(p.Issue.URL, issueTitle)
var text string
color := yellowColor

switch p.Action {
case api.HookIssueOpened:
text = fmt.Sprintf("[%s] Issue opened by %s", repoLink, senderLink)
zeripath marked this conversation as resolved.
Show resolved Hide resolved
color = orangeColor
case api.HookIssueClosed:
text = fmt.Sprintf("[%s] Issue closed: %s by %s", repoLink, titleLink, senderLink)
color = redColor
case api.HookIssueReOpened:
text = fmt.Sprintf("[%s] Issue re-opened: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueEdited:
text = fmt.Sprintf("[%s] Issue edited: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueAssigned:
text = fmt.Sprintf("[%s] Issue assigned to %s: %s by %s", repoLink,
linkFormatter(setting.AppURL+p.Issue.Assignee.UserName, p.Issue.Assignee.UserName),
titleLink, senderLink)
color = greenColor
case api.HookIssueUnassigned:
text = fmt.Sprintf("[%s] Issue unassigned: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueLabelUpdated:
text = fmt.Sprintf("[%s] Issue labels updated: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueLabelCleared:
text = fmt.Sprintf("[%s] Issue labels cleared: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueSynchronized:
text = fmt.Sprintf("[%s] Issue synchronized: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueMilestoned:
mileStoneLink := fmt.Sprintf("%s/milestone/%d", p.Repository.HTMLURL, p.Issue.Milestone.ID)
text = fmt.Sprintf("[%s] Issue milestoned to %s: %s by %s", repoLink,
linkFormatter(mileStoneLink, p.Issue.Milestone.Title), titleLink, senderLink)
case api.HookIssueDemilestoned:
text = fmt.Sprintf("[%s] Issue milestone cleared: %s by %s", repoLink, titleLink, senderLink)
}

return text, issueTitle, color
}

func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkFormatter) (string, string) {
senderLink := linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
issueTitle := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title)
titleLink := linkFormatter(p.PullRequest.URL, issueTitle)
var text string

switch p.Action {
case api.HookIssueOpened:
text = fmt.Sprintf("[%s] Pull request opened by %s", repoLink, senderLink)
case api.HookIssueClosed:
if p.PullRequest.HasMerged {
text = fmt.Sprintf("[%s] Pull request merged: %s by %s", repoLink, titleLink, senderLink)
} else {
text = fmt.Sprintf("[%s] Pull request closed: %s by %s", repoLink, titleLink, senderLink)
}
case api.HookIssueReOpened:
text = fmt.Sprintf("[%s] Pull request re-opened: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueEdited:
text = fmt.Sprintf("[%s] Pull request edited: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueAssigned:
list := make([]string, len(p.PullRequest.Assignees))
for i, user := range p.PullRequest.Assignees {
list[i] = linkFormatter(setting.AppURL+user.UserName, user.UserName)
}
text = fmt.Sprintf("[%s] Pull request assigned to %s: %s by %s", repoLink,
strings.Join(list, ", "),
titleLink, senderLink)
case api.HookIssueUnassigned:
text = fmt.Sprintf("[%s] Pull request unassigned: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueLabelUpdated:
text = fmt.Sprintf("[%s] Pull request labels updated: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueLabelCleared:
text = fmt.Sprintf("[%s] Pull request labels cleared: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueSynchronized:
text = fmt.Sprintf("[%s] Pull request synchronized: %s by %s", repoLink, titleLink, senderLink)
case api.HookIssueMilestoned:
mileStoneLink := fmt.Sprintf("%s/milestone/%d", p.Repository.HTMLURL, p.PullRequest.Milestone.ID)
text = fmt.Sprintf("[%s] Pull request milestoned to %s: %s by %s", repoLink,
linkFormatter(mileStoneLink, p.PullRequest.Milestone.Title), titleLink, senderLink)
case api.HookIssueDemilestoned:
text = fmt.Sprintf("[%s] Pull request milestone cleared: %s %s", repoLink, titleLink, senderLink)
}

return text, issueTitle
}
53 changes: 9 additions & 44 deletions modules/webhook/msteams.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,60 +266,25 @@ func getMSTeamsPushPayload(p *api.PushPayload) (*MSTeamsPayload, error) {
}

func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) {
var text, title string
var color int
url := fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index)
switch p.Action {
case api.HookIssueOpened:
title = fmt.Sprintf("[%s] Issue opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
text = p.Issue.Body
color = orangeColor
case api.HookIssueClosed:
title = fmt.Sprintf("[%s] Issue closed: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = redColor
case api.HookIssueReOpened:
title = fmt.Sprintf("[%s] Issue re-opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueEdited:
title = fmt.Sprintf("[%s] Issue edited: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
text = p.Issue.Body
color = yellowColor
case api.HookIssueAssigned:
title = fmt.Sprintf("[%s] Issue assigned to %s: #%d %s", p.Repository.FullName,
p.Issue.Assignee.UserName, p.Index, p.Issue.Title)
color = greenColor
case api.HookIssueUnassigned:
title = fmt.Sprintf("[%s] Issue unassigned: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueLabelUpdated:
title = fmt.Sprintf("[%s] Issue labels updated: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueLabelCleared:
title = fmt.Sprintf("[%s] Issue labels cleared: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueSynchronized:
title = fmt.Sprintf("[%s] Issue synchronized: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueMilestoned:
title = fmt.Sprintf("[%s] Issue milestone: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
case api.HookIssueDemilestoned:
title = fmt.Sprintf("[%s] Issue clear milestone: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
color = yellowColor
text, _, color := getIssuesPayloadInfo(p, noneLinkFormatter)

var attachmentText string
if p.Action == api.HookIssueOpened || p.Action == api.HookIssueEdited {
attachmentText = p.Issue.Body
}

return &MSTeamsPayload{
Type: "MessageCard",
Context: "https://schema.org/extensions",
ThemeColor: fmt.Sprintf("%x", color),
Title: title,
Summary: title,
Title: text,
Summary: text,
Sections: []MSTeamsSection{
{
ActivityTitle: p.Sender.FullName,
ActivitySubtitle: p.Sender.UserName,
ActivityImage: p.Sender.AvatarURL,
Text: text,
Text: attachmentText,
Facts: []MSTeamsFact{
{
Name: "Repository:",
Expand All @@ -339,7 +304,7 @@ func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) {
Targets: []MSTeamsActionTarget{
{
Os: "default",
URI: url,
URI: p.Issue.URL,
},
},
},
Expand Down
90 changes: 12 additions & 78 deletions modules/webhook/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,41 +144,11 @@ func getSlackForkPayload(p *api.ForkPayload, slack *SlackMeta) (*SlackPayload, e
}

func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload, error) {
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
title := SlackTextFormatter(fmt.Sprintf("#%d %s", p.Index, p.Issue.Title))
titleLink := fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Index)
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
var text, attachmentText string
text, issueTitle, _ := getIssuesPayloadInfo(p, SlackLinkFormatter)

switch p.Action {
case api.HookIssueOpened:
text = fmt.Sprintf("[%s] Issue opened by %s", repoLink, senderLink)
attachmentText = SlackTextFormatter(p.Issue.Body)
case api.HookIssueClosed:
text = fmt.Sprintf("[%s] Issue closed: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueReOpened:
text = fmt.Sprintf("[%s] Issue re-opened: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueEdited:
text = fmt.Sprintf("[%s] Issue edited: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
var attachmentText string
if p.Action == api.HookIssueOpened || p.Action == api.HookIssueEdited {
attachmentText = SlackTextFormatter(p.Issue.Body)
case api.HookIssueAssigned:
text = fmt.Sprintf("[%s] Issue assigned to %s: [%s](%s) by %s", repoLink,
SlackLinkFormatter(setting.AppURL+p.Issue.Assignee.UserName, p.Issue.Assignee.UserName),
title, titleLink, senderLink)
case api.HookIssueUnassigned:
text = fmt.Sprintf("[%s] Issue unassigned: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueLabelUpdated:
text = fmt.Sprintf("[%s] Issue labels updated: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueLabelCleared:
text = fmt.Sprintf("[%s] Issue labels cleared: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueSynchronized:
text = fmt.Sprintf("[%s] Issue synchronized: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueMilestoned:
mileStoneLink := fmt.Sprintf("%s/milestone/%d", p.Repository.HTMLURL, p.Issue.Milestone.ID)
text = fmt.Sprintf("[%s] Issue milestoned to [%s](%s): [%s](%s) by %s", repoLink,
p.Issue.Milestone.Title, mileStoneLink, title, titleLink, senderLink)
case api.HookIssueDemilestoned:
text = fmt.Sprintf("[%s] Issue milestone cleared: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
}

pl := &SlackPayload{
Expand All @@ -188,10 +158,11 @@ func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload
IconURL: slack.IconURL,
}
if attachmentText != "" {
issueTitle = SlackTextFormatter(issueTitle)
pl.Attachments = []SlackAttachment{{
Color: slack.Color,
Title: title,
TitleLink: titleLink,
Title: issueTitle,
TitleLink: p.Issue.URL,
Text: attachmentText,
}}
}
Expand Down Expand Up @@ -301,49 +272,11 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e
}

func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*SlackPayload, 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)
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
var text, attachmentText string
text, issueTitle := getPullRequestPayloadInfo(p, SlackLinkFormatter)

switch p.Action {
case api.HookIssueOpened:
text = fmt.Sprintf("[%s] Pull request opened by %s", repoLink, senderLink)
attachmentText = SlackTextFormatter(p.PullRequest.Body)
case api.HookIssueClosed:
if p.PullRequest.HasMerged {
text = fmt.Sprintf("[%s] Pull request merged: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
} else {
text = fmt.Sprintf("[%s] Pull request closed: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
}
case api.HookIssueReOpened:
text = fmt.Sprintf("[%s] Pull request re-opened: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueEdited:
text = fmt.Sprintf("[%s] Pull request edited: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
var attachmentText string
if p.Action == api.HookIssueOpened || p.Action == api.HookIssueEdited {
attachmentText = SlackTextFormatter(p.PullRequest.Body)
case api.HookIssueAssigned:
list := make([]string, len(p.PullRequest.Assignees))
for i, user := range p.PullRequest.Assignees {
list[i] = SlackLinkFormatter(setting.AppURL+user.UserName, user.UserName)
}
text = fmt.Sprintf("[%s] Pull request assigned to %s: [%s](%s) by %s", repoLink,
strings.Join(list, ", "),
title, titleLink, senderLink)
case api.HookIssueUnassigned:
text = fmt.Sprintf("[%s] Pull request unassigned: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueLabelUpdated:
text = fmt.Sprintf("[%s] Pull request labels updated: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueLabelCleared:
text = fmt.Sprintf("[%s] Pull request labels cleared: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueSynchronized:
text = fmt.Sprintf("[%s] Pull request synchronized: [%s](%s) by %s", repoLink, title, titleLink, senderLink)
case api.HookIssueMilestoned:
mileStoneLink := fmt.Sprintf("%s/milestone/%d", p.Repository.HTMLURL, p.PullRequest.Milestone.ID)
text = fmt.Sprintf("[%s] Pull request milestoned to [%s](%s): [%s](%s) %s", repoLink,
p.PullRequest.Milestone.Title, mileStoneLink, title, titleLink, senderLink)
case api.HookIssueDemilestoned:
text = fmt.Sprintf("[%s] Pull request milestone cleared: [%s](%s) %s", repoLink, title, titleLink, senderLink)
}

pl := &SlackPayload{
Expand All @@ -353,10 +286,11 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
IconURL: slack.IconURL,
}
if attachmentText != "" {
issueTitle = SlackTextFormatter(issueTitle)
pl.Attachments = []SlackAttachment{{
Color: slack.Color,
Title: title,
TitleLink: titleLink,
Title: issueTitle,
TitleLink: p.PullRequest.URL,
Text: attachmentText,
}}
}
Expand Down
Loading