* Initial work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add PR reviews and API coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Split up events Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add migration and locale Signed-off-by: jolheiser <john.olheiser@gmail.com> * Format Signed-off-by: jolheiser <john.olheiser@gmail.com> * Revert IsPull Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix comments Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix PR reviews Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix issue_comment Signed-off-by: jolheiser <john.olheiser@gmail.com> * Make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Migrations Signed-off-by: jolheiser <john.olheiser@gmail.com> * Backwards compatible API Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix feishu Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move session commit Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>tags/v1.10.5
NewMigration("fix merge base for pull requests", fixMergeBase), | NewMigration("fix merge base for pull requests", fixMergeBase), | ||||
// v129 -> v130 | // v129 -> v130 | ||||
NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), | NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), | ||||
// v130 -> v131 | |||||
NewMigration("Expand webhooks for more granularity", expandWebhooks), | |||||
} | } | ||||
// Migrate database to current version | // Migrate database to current version |
// 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 migrations | |||||
import ( | |||||
"encoding/json" | |||||
"xorm.io/xorm" | |||||
) | |||||
func expandWebhooks(x *xorm.Engine) error { | |||||
type ChooseEvents struct { | |||||
Issues bool `json:"issues"` | |||||
IssueAssign bool `json:"issue_assign"` | |||||
IssueLabel bool `json:"issue_label"` | |||||
IssueMilestone bool `json:"issue_milestone"` | |||||
IssueComment bool `json:"issue_comment"` | |||||
PullRequest bool `json:"pull_request"` | |||||
PullRequestAssign bool `json:"pull_request_assign"` | |||||
PullRequestLabel bool `json:"pull_request_label"` | |||||
PullRequestMilestone bool `json:"pull_request_milestone"` | |||||
PullRequestComment bool `json:"pull_request_comment"` | |||||
PullRequestReview bool `json:"pull_request_review"` | |||||
PullRequestSync bool `json:"pull_request_sync"` | |||||
} | |||||
type Events struct { | |||||
PushOnly bool `json:"push_only"` | |||||
SendEverything bool `json:"send_everything"` | |||||
ChooseEvents bool `json:"choose_events"` | |||||
BranchFilter string `json:"branch_filter"` | |||||
Events ChooseEvents `json:"events"` | |||||
} | |||||
type Webhook struct { | |||||
ID int64 | |||||
Events string | |||||
} | |||||
var events Events | |||||
var bytes []byte | |||||
var last int | |||||
const batchSize = 50 | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
for { | |||||
if err := sess.Begin(); err != nil { | |||||
return err | |||||
} | |||||
var results = make([]Webhook, 0, batchSize) | |||||
err := x.OrderBy("id"). | |||||
Limit(batchSize, last). | |||||
Find(&results) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
if len(results) == 0 { | |||||
break | |||||
} | |||||
last += len(results) | |||||
for _, res := range results { | |||||
if err = json.Unmarshal([]byte(res.Events), &events); err != nil { | |||||
return err | |||||
} | |||||
if events.Events.Issues { | |||||
events.Events.IssueAssign = true | |||||
events.Events.IssueLabel = true | |||||
events.Events.IssueMilestone = true | |||||
events.Events.IssueComment = true | |||||
} | |||||
if events.Events.PullRequest { | |||||
events.Events.PullRequestAssign = true | |||||
events.Events.PullRequestLabel = true | |||||
events.Events.PullRequestMilestone = true | |||||
events.Events.PullRequestComment = true | |||||
events.Events.PullRequestReview = true | |||||
events.Events.PullRequestSync = true | |||||
} | |||||
if bytes, err = json.Marshal(&events); err != nil { | |||||
return err | |||||
} | |||||
_, err = sess.Exec("UPDATE webhook SET events = ? WHERE id = ?", string(bytes), res.ID) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
} | |||||
if err := sess.Commit(); err != nil { | |||||
return err | |||||
} | |||||
} | |||||
return nil | |||||
} |
// HookEvents is a set of web hook events | // HookEvents is a set of web hook events | ||||
type HookEvents struct { | type HookEvents struct { | ||||
Create bool `json:"create"` | |||||
Delete bool `json:"delete"` | |||||
Fork bool `json:"fork"` | |||||
Issues bool `json:"issues"` | |||||
IssueComment bool `json:"issue_comment"` | |||||
Push bool `json:"push"` | |||||
PullRequest bool `json:"pull_request"` | |||||
Repository bool `json:"repository"` | |||||
Release bool `json:"release"` | |||||
Create bool `json:"create"` | |||||
Delete bool `json:"delete"` | |||||
Fork bool `json:"fork"` | |||||
Issues bool `json:"issues"` | |||||
IssueAssign bool `json:"issue_assign"` | |||||
IssueLabel bool `json:"issue_label"` | |||||
IssueMilestone bool `json:"issue_milestone"` | |||||
IssueComment bool `json:"issue_comment"` | |||||
Push bool `json:"push"` | |||||
PullRequest bool `json:"pull_request"` | |||||
PullRequestAssign bool `json:"pull_request_assign"` | |||||
PullRequestLabel bool `json:"pull_request_label"` | |||||
PullRequestMilestone bool `json:"pull_request_milestone"` | |||||
PullRequestComment bool `json:"pull_request_comment"` | |||||
PullRequestReview bool `json:"pull_request_review"` | |||||
PullRequestSync bool `json:"pull_request_sync"` | |||||
Repository bool `json:"repository"` | |||||
Release bool `json:"release"` | |||||
} | } | ||||
// HookEvent represents events that will delivery hook. | // HookEvent represents events that will delivery hook. | ||||
(w.ChooseEvents && w.HookEvents.Issues) | (w.ChooseEvents && w.HookEvents.Issues) | ||||
} | } | ||||
// HasIssuesAssignEvent returns true if hook enabled issues assign event. | |||||
func (w *Webhook) HasIssuesAssignEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.IssueAssign) | |||||
} | |||||
// HasIssuesLabelEvent returns true if hook enabled issues label event. | |||||
func (w *Webhook) HasIssuesLabelEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.IssueLabel) | |||||
} | |||||
// HasIssuesMilestoneEvent returns true if hook enabled issues milestone event. | |||||
func (w *Webhook) HasIssuesMilestoneEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.IssueMilestone) | |||||
} | |||||
// HasIssueCommentEvent returns true if hook enabled issue_comment event. | // HasIssueCommentEvent returns true if hook enabled issue_comment event. | ||||
func (w *Webhook) HasIssueCommentEvent() bool { | func (w *Webhook) HasIssueCommentEvent() bool { | ||||
return w.SendEverything || | return w.SendEverything || | ||||
(w.ChooseEvents && w.HookEvents.PullRequest) | (w.ChooseEvents && w.HookEvents.PullRequest) | ||||
} | } | ||||
// HasPullRequestAssignEvent returns true if hook enabled pull request assign event. | |||||
func (w *Webhook) HasPullRequestAssignEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestAssign) | |||||
} | |||||
// HasPullRequestLabelEvent returns true if hook enabled pull request label event. | |||||
func (w *Webhook) HasPullRequestLabelEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestLabel) | |||||
} | |||||
// HasPullRequestMilestoneEvent returns true if hook enabled pull request milestone event. | |||||
func (w *Webhook) HasPullRequestMilestoneEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestMilestone) | |||||
} | |||||
// HasPullRequestCommentEvent returns true if hook enabled pull_request_comment event. | |||||
func (w *Webhook) HasPullRequestCommentEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestComment) | |||||
} | |||||
// HasPullRequestApprovedEvent returns true if hook enabled pull request review event. | |||||
func (w *Webhook) HasPullRequestApprovedEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestReview) | |||||
} | |||||
// HasPullRequestRejectedEvent returns true if hook enabled pull request review event. | |||||
func (w *Webhook) HasPullRequestRejectedEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestReview) | |||||
} | |||||
// HasPullRequestReviewCommentEvent returns true if hook enabled pull request review event. | |||||
func (w *Webhook) HasPullRequestReviewCommentEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestReview) | |||||
} | |||||
// HasPullRequestSyncEvent returns true if hook enabled pull request sync event. | |||||
func (w *Webhook) HasPullRequestSyncEvent() bool { | |||||
return w.SendEverything || | |||||
(w.ChooseEvents && w.HookEvents.PullRequestSync) | |||||
} | |||||
// HasReleaseEvent returns if hook enabled release event. | // HasReleaseEvent returns if hook enabled release event. | ||||
func (w *Webhook) HasReleaseEvent() bool { | func (w *Webhook) HasReleaseEvent() bool { | ||||
return w.SendEverything || | return w.SendEverything || | ||||
{w.HasForkEvent, HookEventFork}, | {w.HasForkEvent, HookEventFork}, | ||||
{w.HasPushEvent, HookEventPush}, | {w.HasPushEvent, HookEventPush}, | ||||
{w.HasIssuesEvent, HookEventIssues}, | {w.HasIssuesEvent, HookEventIssues}, | ||||
{w.HasIssuesAssignEvent, HookEventIssueAssign}, | |||||
{w.HasIssuesLabelEvent, HookEventIssueLabel}, | |||||
{w.HasIssuesMilestoneEvent, HookEventIssueMilestone}, | |||||
{w.HasIssueCommentEvent, HookEventIssueComment}, | {w.HasIssueCommentEvent, HookEventIssueComment}, | ||||
{w.HasPullRequestEvent, HookEventPullRequest}, | {w.HasPullRequestEvent, HookEventPullRequest}, | ||||
{w.HasPullRequestAssignEvent, HookEventPullRequestAssign}, | |||||
{w.HasPullRequestLabelEvent, HookEventPullRequestLabel}, | |||||
{w.HasPullRequestMilestoneEvent, HookEventPullRequestMilestone}, | |||||
{w.HasPullRequestCommentEvent, HookEventPullRequestComment}, | |||||
{w.HasPullRequestApprovedEvent, HookEventPullRequestReviewApproved}, | |||||
{w.HasPullRequestRejectedEvent, HookEventPullRequestReviewRejected}, | |||||
{w.HasPullRequestCommentEvent, HookEventPullRequestReviewComment}, | |||||
{w.HasPullRequestSyncEvent, HookEventPullRequestSync}, | |||||
{w.HasRepositoryEvent, HookEventRepository}, | {w.HasRepositoryEvent, HookEventRepository}, | ||||
{w.HasReleaseEvent, HookEventRelease}, | {w.HasReleaseEvent, HookEventRelease}, | ||||
} | } | ||||
// Types of hook events | // Types of hook events | ||||
const ( | const ( | ||||
HookEventCreate HookEventType = "create" | |||||
HookEventDelete HookEventType = "delete" | |||||
HookEventFork HookEventType = "fork" | |||||
HookEventPush HookEventType = "push" | |||||
HookEventIssues HookEventType = "issues" | |||||
HookEventIssueComment HookEventType = "issue_comment" | |||||
HookEventPullRequest HookEventType = "pull_request" | |||||
HookEventRepository HookEventType = "repository" | |||||
HookEventRelease HookEventType = "release" | |||||
HookEventPullRequestApproved HookEventType = "pull_request_approved" | |||||
HookEventPullRequestRejected HookEventType = "pull_request_rejected" | |||||
HookEventPullRequestComment HookEventType = "pull_request_comment" | |||||
HookEventCreate HookEventType = "create" | |||||
HookEventDelete HookEventType = "delete" | |||||
HookEventFork HookEventType = "fork" | |||||
HookEventPush HookEventType = "push" | |||||
HookEventIssues HookEventType = "issues" | |||||
HookEventIssueAssign HookEventType = "issue_assign" | |||||
HookEventIssueLabel HookEventType = "issue_label" | |||||
HookEventIssueMilestone HookEventType = "issue_milestone" | |||||
HookEventIssueComment HookEventType = "issue_comment" | |||||
HookEventPullRequest HookEventType = "pull_request" | |||||
HookEventPullRequestAssign HookEventType = "pull_request_assign" | |||||
HookEventPullRequestLabel HookEventType = "pull_request_label" | |||||
HookEventPullRequestMilestone HookEventType = "pull_request_milestone" | |||||
HookEventPullRequestComment HookEventType = "pull_request_comment" | |||||
HookEventPullRequestReviewApproved HookEventType = "pull_request_review_approved" | |||||
HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected" | |||||
HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment" | |||||
HookEventPullRequestSync HookEventType = "pull_request_sync" | |||||
HookEventRepository HookEventType = "repository" | |||||
HookEventRelease HookEventType = "release" | |||||
) | ) | ||||
// Event returns the HookEventType as an event string | |||||
func (h HookEventType) Event() string { | |||||
switch h { | |||||
case HookEventCreate: | |||||
return "create" | |||||
case HookEventDelete: | |||||
return "delete" | |||||
case HookEventFork: | |||||
return "fork" | |||||
case HookEventPush: | |||||
return "push" | |||||
case HookEventIssues, HookEventIssueAssign, HookEventIssueLabel, HookEventIssueMilestone: | |||||
return "issues" | |||||
case HookEventPullRequest, HookEventPullRequestAssign, HookEventPullRequestLabel, HookEventPullRequestMilestone, | |||||
HookEventPullRequestSync: | |||||
return "pull_request" | |||||
case HookEventIssueComment, HookEventPullRequestComment: | |||||
return "issue_comment" | |||||
case HookEventPullRequestReviewApproved: | |||||
return "pull_request_approved" | |||||
case HookEventPullRequestReviewRejected: | |||||
return "pull_request_rejected" | |||||
case HookEventPullRequestReviewComment: | |||||
return "pull_request_comment" | |||||
case HookEventRepository: | |||||
return "repository" | |||||
case HookEventRelease: | |||||
return "release" | |||||
} | |||||
return "" | |||||
} | |||||
// HookRequest represents hook task request information. | // HookRequest represents hook task request information. | ||||
type HookRequest struct { | type HookRequest struct { | ||||
Headers map[string]string `json:"headers"` | Headers map[string]string `json:"headers"` |
} | } | ||||
func TestWebhook_EventsArray(t *testing.T) { | func TestWebhook_EventsArray(t *testing.T) { | ||||
assert.Equal(t, []string{"create", "delete", "fork", "push", "issues", "issue_comment", "pull_request", "repository", "release"}, | |||||
assert.Equal(t, []string{"create", "delete", "fork", "push", | |||||
"issues", "issue_assign", "issue_label", "issue_milestone", "issue_comment", | |||||
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone", | |||||
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected", | |||||
"pull_request_review_comment", "pull_request_sync", "repository", "release"}, | |||||
(&Webhook{ | (&Webhook{ | ||||
HookEvent: &HookEvent{SendEverything: true}, | HookEvent: &HookEvent{SendEverything: true}, | ||||
}).EventsArray(), | }).EventsArray(), |
// WebhookForm form for changing web hook | // WebhookForm form for changing web hook | ||||
type WebhookForm struct { | type WebhookForm struct { | ||||
Events string | |||||
Create bool | |||||
Delete bool | |||||
Fork bool | |||||
Issues bool | |||||
IssueComment bool | |||||
Release bool | |||||
Push bool | |||||
PullRequest bool | |||||
Repository bool | |||||
Active bool | |||||
BranchFilter string `binding:"GlobPattern"` | |||||
Events string | |||||
Create bool | |||||
Delete bool | |||||
Fork bool | |||||
Issues bool | |||||
IssueAssign bool | |||||
IssueLabel bool | |||||
IssueMilestone bool | |||||
IssueComment bool | |||||
Release bool | |||||
Push bool | |||||
PullRequest bool | |||||
PullRequestAssign bool | |||||
PullRequestLabel bool | |||||
PullRequestMilestone bool | |||||
PullRequestComment bool | |||||
PullRequestReview bool | |||||
PullRequestSync bool | |||||
Repository bool | |||||
Active bool | |||||
BranchFilter string `binding:"GlobPattern"` | |||||
} | } | ||||
// PushOnly if the hook will be triggered when push | // PushOnly if the hook will be triggered when push |
return | return | ||||
} | } | ||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestLabel, &api.PullRequestPayload{ | |||||
Action: api.HookIssueLabelCleared, | Action: api.HookIssueLabelCleared, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
PullRequest: convert.ToAPIPullRequest(issue.PullRequest), | PullRequest: convert.ToAPIPullRequest(issue.PullRequest), | ||||
Sender: doer.APIFormat(), | Sender: doer.APIFormat(), | ||||
}) | }) | ||||
} else { | } else { | ||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueLabel, &api.IssuePayload{ | |||||
Action: api.HookIssueLabelCleared, | Action: api.HookIssueLabelCleared, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
Issue: convert.ToAPIIssue(issue), | Issue: convert.ToAPIIssue(issue), | ||||
apiPullRequest.Action = api.HookIssueAssigned | apiPullRequest.Action = api.HookIssueAssigned | ||||
} | } | ||||
// Assignee comment triggers a webhook | // Assignee comment triggers a webhook | ||||
if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest); err != nil { | |||||
if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestAssign, apiPullRequest); err != nil { | |||||
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) | log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) | ||||
return | return | ||||
} | } | ||||
apiIssue.Action = api.HookIssueAssigned | apiIssue.Action = api.HookIssueAssigned | ||||
} | } | ||||
// Assignee comment triggers a webhook | // Assignee comment triggers a webhook | ||||
if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue); err != nil { | |||||
if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueAssign, apiIssue); err != nil { | |||||
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) | log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) | ||||
return | return | ||||
} | } | ||||
} | } | ||||
func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) { | func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) { | ||||
if err := c.LoadPoster(); err != nil { | |||||
var err error | |||||
if err = c.LoadPoster(); err != nil { | |||||
log.Error("LoadPoster: %v", err) | log.Error("LoadPoster: %v", err) | ||||
return | return | ||||
} | } | ||||
if err := c.LoadIssue(); err != nil { | |||||
if err = c.LoadIssue(); err != nil { | |||||
log.Error("LoadIssue: %v", err) | log.Error("LoadIssue: %v", err) | ||||
return | return | ||||
} | } | ||||
if err := c.Issue.LoadAttributes(); err != nil { | |||||
if err = c.Issue.LoadAttributes(); err != nil { | |||||
log.Error("LoadAttributes: %v", err) | log.Error("LoadAttributes: %v", err) | ||||
return | return | ||||
} | } | ||||
mode, _ := models.AccessLevel(doer, c.Issue.Repo) | mode, _ := models.AccessLevel(doer, c.Issue.Repo) | ||||
if err := webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentEdited, | |||||
Issue: convert.ToAPIIssue(c.Issue), | |||||
Comment: c.APIFormat(), | |||||
Changes: &api.ChangesPayload{ | |||||
Body: &api.ChangesFromPayload{ | |||||
From: oldContent, | |||||
if c.Issue.IsPull { | |||||
err = webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentEdited, | |||||
Issue: convert.ToAPIIssue(c.Issue), | |||||
Comment: c.APIFormat(), | |||||
Changes: &api.ChangesPayload{ | |||||
Body: &api.ChangesFromPayload{ | |||||
From: oldContent, | |||||
}, | |||||
}, | }, | ||||
}, | |||||
Repository: c.Issue.Repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: c.Issue.IsPull, | |||||
}); err != nil { | |||||
Repository: c.Issue.Repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: true, | |||||
}) | |||||
} else { | |||||
err = webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentEdited, | |||||
Issue: convert.ToAPIIssue(c.Issue), | |||||
Comment: c.APIFormat(), | |||||
Changes: &api.ChangesPayload{ | |||||
Body: &api.ChangesFromPayload{ | |||||
From: oldContent, | |||||
}, | |||||
}, | |||||
Repository: c.Issue.Repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: false, | |||||
}) | |||||
} | |||||
if err != nil { | |||||
log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) | log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) | ||||
} | } | ||||
} | } | ||||
func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository, | func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository, | ||||
issue *models.Issue, comment *models.Comment) { | issue *models.Issue, comment *models.Comment) { | ||||
mode, _ := models.AccessLevel(doer, repo) | mode, _ := models.AccessLevel(doer, repo) | ||||
if err := webhook_module.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentCreated, | |||||
Issue: convert.ToAPIIssue(issue), | |||||
Comment: comment.APIFormat(), | |||||
Repository: repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: issue.IsPull, | |||||
}); err != nil { | |||||
var err error | |||||
if issue.IsPull { | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentCreated, | |||||
Issue: convert.ToAPIIssue(issue), | |||||
Comment: comment.APIFormat(), | |||||
Repository: repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: true, | |||||
}) | |||||
} else { | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentCreated, | |||||
Issue: convert.ToAPIIssue(issue), | |||||
Comment: comment.APIFormat(), | |||||
Repository: repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: false, | |||||
}) | |||||
} | |||||
if err != nil { | |||||
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) | log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) | ||||
} | } | ||||
} | } | ||||
func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) { | func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) { | ||||
if err := comment.LoadPoster(); err != nil { | |||||
var err error | |||||
if err = comment.LoadPoster(); err != nil { | |||||
log.Error("LoadPoster: %v", err) | log.Error("LoadPoster: %v", err) | ||||
return | return | ||||
} | } | ||||
if err := comment.LoadIssue(); err != nil { | |||||
if err = comment.LoadIssue(); err != nil { | |||||
log.Error("LoadIssue: %v", err) | log.Error("LoadIssue: %v", err) | ||||
return | return | ||||
} | } | ||||
if err := comment.Issue.LoadAttributes(); err != nil { | |||||
if err = comment.Issue.LoadAttributes(); err != nil { | |||||
log.Error("LoadAttributes: %v", err) | log.Error("LoadAttributes: %v", err) | ||||
return | return | ||||
} | } | ||||
mode, _ := models.AccessLevel(doer, comment.Issue.Repo) | mode, _ := models.AccessLevel(doer, comment.Issue.Repo) | ||||
if err := webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentDeleted, | |||||
Issue: convert.ToAPIIssue(comment.Issue), | |||||
Comment: comment.APIFormat(), | |||||
Repository: comment.Issue.Repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: comment.Issue.IsPull, | |||||
}); err != nil { | |||||
if comment.Issue.IsPull { | |||||
err = webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentDeleted, | |||||
Issue: convert.ToAPIIssue(comment.Issue), | |||||
Comment: comment.APIFormat(), | |||||
Repository: comment.Issue.Repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: true, | |||||
}) | |||||
} else { | |||||
err = webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ | |||||
Action: api.HookIssueCommentDeleted, | |||||
Issue: convert.ToAPIIssue(comment.Issue), | |||||
Comment: comment.APIFormat(), | |||||
Repository: comment.Issue.Repo.APIFormat(mode), | |||||
Sender: doer.APIFormat(), | |||||
IsPull: false, | |||||
}) | |||||
} | |||||
if err != nil { | |||||
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) | log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) | ||||
} | } | ||||
} | } | ||||
func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, | func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, | ||||
log.Error("LoadIssue: %v", err) | log.Error("LoadIssue: %v", err) | ||||
return | return | ||||
} | } | ||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestLabel, &api.PullRequestPayload{ | |||||
Action: api.HookIssueLabelUpdated, | Action: api.HookIssueLabelUpdated, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
PullRequest: convert.ToAPIPullRequest(issue.PullRequest), | PullRequest: convert.ToAPIPullRequest(issue.PullRequest), | ||||
Sender: doer.APIFormat(), | Sender: doer.APIFormat(), | ||||
}) | }) | ||||
} else { | } else { | ||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueLabel, &api.IssuePayload{ | |||||
Action: api.HookIssueLabelUpdated, | Action: api.HookIssueLabelUpdated, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
Issue: convert.ToAPIIssue(issue), | Issue: convert.ToAPIIssue(issue), | ||||
log.Error("LoadIssue: %v", err) | log.Error("LoadIssue: %v", err) | ||||
return | return | ||||
} | } | ||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestMilestone, &api.PullRequestPayload{ | |||||
Action: hookAction, | Action: hookAction, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
PullRequest: convert.ToAPIPullRequest(issue.PullRequest), | PullRequest: convert.ToAPIPullRequest(issue.PullRequest), | ||||
Sender: doer.APIFormat(), | Sender: doer.APIFormat(), | ||||
}) | }) | ||||
} else { | } else { | ||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ | |||||
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueMilestone, &api.IssuePayload{ | |||||
Action: hookAction, | Action: hookAction, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
Issue: convert.ToAPIIssue(issue), | Issue: convert.ToAPIIssue(issue), | ||||
switch review.Type { | switch review.Type { | ||||
case models.ReviewTypeApprove: | case models.ReviewTypeApprove: | ||||
reviewHookType = models.HookEventPullRequestApproved | |||||
reviewHookType = models.HookEventPullRequestReviewApproved | |||||
case models.ReviewTypeComment: | case models.ReviewTypeComment: | ||||
reviewHookType = models.HookEventPullRequestComment | reviewHookType = models.HookEventPullRequestComment | ||||
case models.ReviewTypeReject: | case models.ReviewTypeReject: | ||||
reviewHookType = models.HookEventPullRequestRejected | |||||
reviewHookType = models.HookEventPullRequestReviewRejected | |||||
default: | default: | ||||
// unsupported review webhook type here | // unsupported review webhook type here | ||||
log.Error("Unsupported review webhook type") | log.Error("Unsupported review webhook type") | ||||
return | return | ||||
} | } | ||||
if err := webhook_module.PrepareWebhooks(review.Issue.Repo, reviewHookType, &api.PullRequestPayload{ | if err := webhook_module.PrepareWebhooks(review.Issue.Repo, reviewHookType, &api.PullRequestPayload{ | ||||
Action: api.HookIssueSynchronized, | |||||
Action: api.HookIssueReviewed, | |||||
Index: review.Issue.Index, | Index: review.Issue.Index, | ||||
PullRequest: convert.ToAPIPullRequest(pr), | PullRequest: convert.ToAPIPullRequest(pr), | ||||
Repository: review.Issue.Repo.APIFormat(mode), | Repository: review.Issue.Repo.APIFormat(mode), | ||||
return | return | ||||
} | } | ||||
if err := webhook_module.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ | |||||
if err := webhook_module.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequestSync, &api.PullRequestPayload{ | |||||
Action: api.HookIssueSynchronized, | Action: api.HookIssueSynchronized, | ||||
Index: pr.Issue.Index, | Index: pr.Issue.Index, | ||||
PullRequest: convert.ToAPIPullRequest(pr), | PullRequest: convert.ToAPIPullRequest(pr), |
HookIssueMilestoned HookIssueAction = "milestoned" | HookIssueMilestoned HookIssueAction = "milestoned" | ||||
// HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue. | // HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue. | ||||
HookIssueDemilestoned HookIssueAction = "demilestoned" | HookIssueDemilestoned HookIssueAction = "demilestoned" | ||||
// HookIssueReviewed is an issue action for when a pull request is reviewed | |||||
HookIssueReviewed HookIssueAction = "reviewed" | |||||
) | ) | ||||
// IssuePayload represents the payload information that is sent along with an issue event. | // IssuePayload represents the payload information that is sent along with an issue event. |
} | } | ||||
req.Header.Add("X-Gitea-Delivery", t.UUID) | req.Header.Add("X-Gitea-Delivery", t.UUID) | ||||
req.Header.Add("X-Gitea-Event", string(t.EventType)) | |||||
req.Header.Add("X-Gitea-Event", t.EventType.Event()) | |||||
req.Header.Add("X-Gitea-Signature", t.Signature) | req.Header.Add("X-Gitea-Signature", t.Signature) | ||||
req.Header.Add("X-Gogs-Delivery", t.UUID) | req.Header.Add("X-Gogs-Delivery", t.UUID) | ||||
req.Header.Add("X-Gogs-Event", string(t.EventType)) | |||||
req.Header.Add("X-Gogs-Event", t.EventType.Event()) | |||||
req.Header.Add("X-Gogs-Signature", t.Signature) | req.Header.Add("X-Gogs-Signature", t.Signature) | ||||
req.Header["X-GitHub-Delivery"] = []string{t.UUID} | req.Header["X-GitHub-Delivery"] = []string{t.UUID} | ||||
req.Header["X-GitHub-Event"] = []string{string(t.EventType)} | |||||
req.Header["X-GitHub-Event"] = []string{t.EventType.Event()} | |||||
// Record delivery information. | // Record delivery information. | ||||
t.RequestInfo = &models.HookRequest{ | t.RequestInfo = &models.HookRequest{ |
func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*DingtalkPayload, error) { | func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*DingtalkPayload, error) { | ||||
var text, title string | var text, title string | ||||
switch p.Action { | switch p.Action { | ||||
case api.HookIssueSynchronized: | |||||
case api.HookIssueReviewed: | |||||
action, err := parseHookPullRequestEventType(event) | action, err := parseHookPullRequestEventType(event) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
return getDingtalkDeletePayload(p.(*api.DeletePayload)) | return getDingtalkDeletePayload(p.(*api.DeletePayload)) | ||||
case models.HookEventFork: | case models.HookEventFork: | ||||
return getDingtalkForkPayload(p.(*api.ForkPayload)) | return getDingtalkForkPayload(p.(*api.ForkPayload)) | ||||
case models.HookEventIssues: | |||||
case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: | |||||
return getDingtalkIssuesPayload(p.(*api.IssuePayload)) | return getDingtalkIssuesPayload(p.(*api.IssuePayload)) | ||||
case models.HookEventIssueComment: | |||||
case models.HookEventIssueComment, models.HookEventPullRequestComment: | |||||
return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload)) | return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload)) | ||||
case models.HookEventPush: | case models.HookEventPush: | ||||
return getDingtalkPushPayload(p.(*api.PushPayload)) | return getDingtalkPushPayload(p.(*api.PushPayload)) | ||||
case models.HookEventPullRequest: | |||||
case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, | |||||
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: | |||||
return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) | return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) | ||||
case models.HookEventPullRequestApproved, models.HookEventPullRequestRejected, models.HookEventPullRequestComment: | |||||
case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewComment: | |||||
return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | ||||
case models.HookEventRepository: | case models.HookEventRepository: | ||||
return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload)) | return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload)) |
var text, title string | var text, title string | ||||
var color int | var color int | ||||
switch p.Action { | switch p.Action { | ||||
case api.HookIssueSynchronized: | |||||
case api.HookIssueReviewed: | |||||
action, err := parseHookPullRequestEventType(event) | action, err := parseHookPullRequestEventType(event) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
text = p.Review.Content | text = p.Review.Content | ||||
switch event { | switch event { | ||||
case models.HookEventPullRequestApproved: | |||||
case models.HookEventPullRequestReviewApproved: | |||||
color = greenColor | color = greenColor | ||||
case models.HookEventPullRequestRejected: | |||||
case models.HookEventPullRequestReviewRejected: | |||||
color = redColor | color = redColor | ||||
case models.HookEventPullRequestComment: | case models.HookEventPullRequestComment: | ||||
color = greyColor | color = greyColor | ||||
return getDiscordDeletePayload(p.(*api.DeletePayload), discord) | return getDiscordDeletePayload(p.(*api.DeletePayload), discord) | ||||
case models.HookEventFork: | case models.HookEventFork: | ||||
return getDiscordForkPayload(p.(*api.ForkPayload), discord) | return getDiscordForkPayload(p.(*api.ForkPayload), discord) | ||||
case models.HookEventIssues: | |||||
case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: | |||||
return getDiscordIssuesPayload(p.(*api.IssuePayload), discord) | return getDiscordIssuesPayload(p.(*api.IssuePayload), discord) | ||||
case models.HookEventIssueComment: | |||||
case models.HookEventIssueComment, models.HookEventPullRequestComment: | |||||
return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord) | return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord) | ||||
case models.HookEventPush: | case models.HookEventPush: | ||||
return getDiscordPushPayload(p.(*api.PushPayload), discord) | return getDiscordPushPayload(p.(*api.PushPayload), discord) | ||||
case models.HookEventPullRequest: | |||||
case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, | |||||
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: | |||||
return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) | return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) | ||||
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: | |||||
case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: | |||||
return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event) | return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event) | ||||
case models.HookEventRepository: | case models.HookEventRepository: | ||||
return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord) | return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord) | ||||
switch event { | switch event { | ||||
case models.HookEventPullRequestApproved: | |||||
case models.HookEventPullRequestReviewApproved: | |||||
return "approved", nil | return "approved", nil | ||||
case models.HookEventPullRequestRejected: | |||||
case models.HookEventPullRequestReviewRejected: | |||||
return "rejected", nil | return "rejected", nil | ||||
case models.HookEventPullRequestComment: | case models.HookEventPullRequestComment: | ||||
return "comment", nil | return "comment", nil |
return getFeishuPushPayload(p.(*api.PushPayload)) | return getFeishuPushPayload(p.(*api.PushPayload)) | ||||
case models.HookEventPullRequest: | case models.HookEventPullRequest: | ||||
return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) | return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) | ||||
case models.HookEventPullRequestApproved, models.HookEventPullRequestRejected, models.HookEventPullRequestComment: | |||||
case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestComment: | |||||
return getFeishuPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | return getFeishuPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | ||||
case models.HookEventRepository: | case models.HookEventRepository: | ||||
return getFeishuRepositoryPayload(p.(*api.RepositoryPayload)) | return getFeishuRepositoryPayload(p.(*api.RepositoryPayload)) |
var text, title string | var text, title string | ||||
var color int | var color int | ||||
switch p.Action { | switch p.Action { | ||||
case api.HookIssueSynchronized: | |||||
case api.HookIssueReviewed: | |||||
action, err := parseHookPullRequestEventType(event) | action, err := parseHookPullRequestEventType(event) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
text = p.Review.Content | text = p.Review.Content | ||||
switch event { | switch event { | ||||
case models.HookEventPullRequestApproved: | |||||
case models.HookEventPullRequestReviewApproved: | |||||
color = greenColor | color = greenColor | ||||
case models.HookEventPullRequestRejected: | |||||
case models.HookEventPullRequestReviewRejected: | |||||
color = redColor | color = redColor | ||||
case models.HookEventPullRequestComment: | case models.HookEventPullRequestComment: | ||||
color = greyColor | color = greyColor | ||||
return getMSTeamsDeletePayload(p.(*api.DeletePayload)) | return getMSTeamsDeletePayload(p.(*api.DeletePayload)) | ||||
case models.HookEventFork: | case models.HookEventFork: | ||||
return getMSTeamsForkPayload(p.(*api.ForkPayload)) | return getMSTeamsForkPayload(p.(*api.ForkPayload)) | ||||
case models.HookEventIssues: | |||||
case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: | |||||
return getMSTeamsIssuesPayload(p.(*api.IssuePayload)) | return getMSTeamsIssuesPayload(p.(*api.IssuePayload)) | ||||
case models.HookEventIssueComment: | |||||
case models.HookEventIssueComment, models.HookEventPullRequestComment: | |||||
return getMSTeamsIssueCommentPayload(p.(*api.IssueCommentPayload)) | return getMSTeamsIssueCommentPayload(p.(*api.IssueCommentPayload)) | ||||
case models.HookEventPush: | case models.HookEventPush: | ||||
return getMSTeamsPushPayload(p.(*api.PushPayload)) | return getMSTeamsPushPayload(p.(*api.PushPayload)) | ||||
case models.HookEventPullRequest: | |||||
case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, | |||||
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: | |||||
return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) | return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) | ||||
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: | |||||
case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: | |||||
return getMSTeamsPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | return getMSTeamsPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | ||||
case models.HookEventRepository: | case models.HookEventRepository: | ||||
return getMSTeamsRepositoryPayload(p.(*api.RepositoryPayload)) | return getMSTeamsRepositoryPayload(p.(*api.RepositoryPayload)) |
var text string | var text string | ||||
switch p.Action { | switch p.Action { | ||||
case api.HookIssueSynchronized: | |||||
case api.HookIssueReviewed: | |||||
action, err := parseHookPullRequestEventType(event) | action, err := parseHookPullRequestEventType(event) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
return getSlackDeletePayload(p.(*api.DeletePayload), slack) | return getSlackDeletePayload(p.(*api.DeletePayload), slack) | ||||
case models.HookEventFork: | case models.HookEventFork: | ||||
return getSlackForkPayload(p.(*api.ForkPayload), slack) | return getSlackForkPayload(p.(*api.ForkPayload), slack) | ||||
case models.HookEventIssues: | |||||
case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: | |||||
return getSlackIssuesPayload(p.(*api.IssuePayload), slack) | return getSlackIssuesPayload(p.(*api.IssuePayload), slack) | ||||
case models.HookEventIssueComment: | |||||
case models.HookEventIssueComment, models.HookEventPullRequestComment: | |||||
return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack) | return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack) | ||||
case models.HookEventPush: | case models.HookEventPush: | ||||
return getSlackPushPayload(p.(*api.PushPayload), slack) | return getSlackPushPayload(p.(*api.PushPayload), slack) | ||||
case models.HookEventPullRequest: | |||||
case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, | |||||
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: | |||||
return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) | return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) | ||||
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: | |||||
case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: | |||||
return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event) | return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event) | ||||
case models.HookEventRepository: | case models.HookEventRepository: | ||||
return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack) | return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack) |
func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*TelegramPayload, error) { | func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*TelegramPayload, error) { | ||||
var text, attachmentText string | var text, attachmentText string | ||||
switch p.Action { | switch p.Action { | ||||
case api.HookIssueSynchronized: | |||||
case api.HookIssueReviewed: | |||||
action, err := parseHookPullRequestEventType(event) | action, err := parseHookPullRequestEventType(event) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
return getTelegramDeletePayload(p.(*api.DeletePayload)) | return getTelegramDeletePayload(p.(*api.DeletePayload)) | ||||
case models.HookEventFork: | case models.HookEventFork: | ||||
return getTelegramForkPayload(p.(*api.ForkPayload)) | return getTelegramForkPayload(p.(*api.ForkPayload)) | ||||
case models.HookEventIssues: | |||||
case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: | |||||
return getTelegramIssuesPayload(p.(*api.IssuePayload)) | return getTelegramIssuesPayload(p.(*api.IssuePayload)) | ||||
case models.HookEventIssueComment: | |||||
case models.HookEventIssueComment, models.HookEventPullRequestComment: | |||||
return getTelegramIssueCommentPayload(p.(*api.IssueCommentPayload)) | return getTelegramIssueCommentPayload(p.(*api.IssueCommentPayload)) | ||||
case models.HookEventPush: | case models.HookEventPush: | ||||
return getTelegramPushPayload(p.(*api.PushPayload)) | return getTelegramPushPayload(p.(*api.PushPayload)) | ||||
case models.HookEventPullRequest: | |||||
case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, | |||||
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync: | |||||
return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) | return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) | ||||
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: | |||||
case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment: | |||||
return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) | ||||
case models.HookEventRepository: | case models.HookEventRepository: | ||||
return getTelegramRepositoryPayload(p.(*api.RepositoryPayload)) | return getTelegramRepositoryPayload(p.(*api.RepositoryPayload)) |
settings.event_push_only = Push Events | settings.event_push_only = Push Events | ||||
settings.event_send_everything = All Events | settings.event_send_everything = All Events | ||||
settings.event_choose = Custom Events… | settings.event_choose = Custom Events… | ||||
settings.event_header_repository = Repository Events | |||||
settings.event_create = Create | settings.event_create = Create | ||||
settings.event_create_desc = Branch or tag created. | settings.event_create_desc = Branch or tag created. | ||||
settings.event_delete = Delete | settings.event_delete = Delete | ||||
settings.event_delete_desc = Branch or tag deleted | |||||
settings.event_delete_desc = Branch or tag deleted. | |||||
settings.event_fork = Fork | settings.event_fork = Fork | ||||
settings.event_fork_desc = Repository forked | |||||
settings.event_issues = Issues | |||||
settings.event_issues_desc = Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned. | |||||
settings.event_issue_comment = Issue Comment | |||||
settings.event_issue_comment_desc = Issue comment created, edited, or deleted. | |||||
settings.event_fork_desc = Repository forked. | |||||
settings.event_release = Release | settings.event_release = Release | ||||
settings.event_release_desc = Release published, updated or deleted in a repository. | settings.event_release_desc = Release published, updated or deleted in a repository. | ||||
settings.event_pull_request = Pull Request | |||||
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, approved, rejected, review comment, assigned, unassigned, label updated, label cleared or synchronized. | |||||
settings.event_push = Push | settings.event_push = Push | ||||
settings.event_push_desc = Git push to a repository. | settings.event_push_desc = Git push to a repository. | ||||
settings.branch_filter = Branch filter | |||||
settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>. | |||||
settings.event_repository = Repository | settings.event_repository = Repository | ||||
settings.event_repository_desc = Repository created or deleted. | settings.event_repository_desc = Repository created or deleted. | ||||
settings.event_header_issue = Issue Events | |||||
settings.event_issues = Issues | |||||
settings.event_issues_desc = Issue opened, closed, reopened, or edited. | |||||
settings.event_issue_assign = Issue Assigned | |||||
settings.event_issue_assign_desc = Issue assigned or unassigned. | |||||
settings.event_issue_label = Issue Labeled | |||||
settings.event_issue_label_desc = Issue labels updated or cleared. | |||||
settings.event_issue_milestone = Issue Milestoned | |||||
settings.event_issue_milestone_desc = Issue milestoned or demilestoned. | |||||
settings.event_issue_comment = Issue Comment | |||||
settings.event_issue_comment_desc = Issue comment created, edited, or deleted. | |||||
settings.event_header_pull_request = Pull Request Events | |||||
settings.event_pull_request = Pull Request | |||||
settings.event_pull_request_desc = Pull request opened, closed, reopened, or edited. | |||||
settings.event_pull_request_assign = Pull Request Assigned | |||||
settings.event_pull_request_assign_desc = Pull request assigned or unassigned. | |||||
settings.event_pull_request_label = Pull Request Labeled | |||||
settings.event_pull_request_label_desc = Pull request labels updated or cleared. | |||||
settings.event_pull_request_milestone = Pull Request Milestoned | |||||
settings.event_pull_request_milestone_desc = Pull request milestoned or demilestoned. | |||||
settings.event_pull_request_comment = Pull Request Comment | |||||
settings.event_pull_request_comment_desc = Pull request comment created, edited, or deleted. | |||||
settings.event_pull_request_review = Pull Request Reviewed | |||||
settings.event_pull_request_review_desc = Pull request approved, rejected, or review comment. | |||||
settings.event_pull_request_sync = Pull Request Synchronized | |||||
settings.event_pull_request_sync_desc = Pull request synchronized. | |||||
settings.branch_filter = Branch filter | |||||
settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>. | |||||
settings.active = Active | settings.active = Active | ||||
settings.active_helper = Information about triggered events will be sent to this webhook URL. | settings.active_helper = Information about triggered events will be sent to this webhook URL. | ||||
settings.add_hook_success = The webhook has been added. | settings.add_hook_success = The webhook has been added. |
} | } | ||||
} | } | ||||
func issuesHook(events []string, event string) bool { | |||||
return com.IsSliceContainsStr(events, event) || com.IsSliceContainsStr(events, string(models.HookEventIssues)) | |||||
} | |||||
func pullHook(events []string, event string) bool { | |||||
return com.IsSliceContainsStr(events, event) || com.IsSliceContainsStr(events, string(models.HookEventPullRequest)) | |||||
} | |||||
// addHook add the hook specified by `form`, `orgID` and `repoID`. If there is | // addHook add the hook specified by `form`, `orgID` and `repoID`. If there is | ||||
// an error, write to `ctx` accordingly. Return (webhook, ok) | // an error, write to `ctx` accordingly. Return (webhook, ok) | ||||
func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID int64) (*models.Webhook, bool) { | func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID int64) (*models.Webhook, bool) { | ||||
HookEvent: &models.HookEvent{ | HookEvent: &models.HookEvent{ | ||||
ChooseEvents: true, | ChooseEvents: true, | ||||
HookEvents: models.HookEvents{ | HookEvents: models.HookEvents{ | ||||
Create: com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)), | |||||
Delete: com.IsSliceContainsStr(form.Events, string(models.HookEventDelete)), | |||||
Fork: com.IsSliceContainsStr(form.Events, string(models.HookEventFork)), | |||||
Issues: com.IsSliceContainsStr(form.Events, string(models.HookEventIssues)), | |||||
IssueComment: com.IsSliceContainsStr(form.Events, string(models.HookEventIssueComment)), | |||||
Push: com.IsSliceContainsStr(form.Events, string(models.HookEventPush)), | |||||
PullRequest: com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest)), | |||||
Repository: com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)), | |||||
Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)), | |||||
Create: com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)), | |||||
Delete: com.IsSliceContainsStr(form.Events, string(models.HookEventDelete)), | |||||
Fork: com.IsSliceContainsStr(form.Events, string(models.HookEventFork)), | |||||
Issues: issuesHook(form.Events, "issues_only"), | |||||
IssueAssign: issuesHook(form.Events, string(models.HookEventIssueAssign)), | |||||
IssueLabel: issuesHook(form.Events, string(models.HookEventIssueLabel)), | |||||
IssueMilestone: issuesHook(form.Events, string(models.HookEventIssueMilestone)), | |||||
IssueComment: issuesHook(form.Events, string(models.HookEventIssueComment)), | |||||
Push: com.IsSliceContainsStr(form.Events, string(models.HookEventPush)), | |||||
PullRequest: pullHook(form.Events, "pull_request_only"), | |||||
PullRequestAssign: pullHook(form.Events, string(models.HookEventPullRequestAssign)), | |||||
PullRequestLabel: pullHook(form.Events, string(models.HookEventPullRequestLabel)), | |||||
PullRequestMilestone: pullHook(form.Events, string(models.HookEventPullRequestMilestone)), | |||||
PullRequestComment: pullHook(form.Events, string(models.HookEventPullRequestComment)), | |||||
PullRequestReview: pullHook(form.Events, "pull_request_review"), | |||||
PullRequestSync: pullHook(form.Events, string(models.HookEventPullRequestSync)), | |||||
Repository: com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)), | |||||
Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)), | |||||
}, | }, | ||||
BranchFilter: form.BranchFilter, | BranchFilter: form.BranchFilter, | ||||
}, | }, |
SendEverything: form.SendEverything(), | SendEverything: form.SendEverything(), | ||||
ChooseEvents: form.ChooseEvents(), | ChooseEvents: form.ChooseEvents(), | ||||
HookEvents: models.HookEvents{ | HookEvents: models.HookEvents{ | ||||
Create: form.Create, | |||||
Delete: form.Delete, | |||||
Fork: form.Fork, | |||||
Issues: form.Issues, | |||||
IssueComment: form.IssueComment, | |||||
Release: form.Release, | |||||
Push: form.Push, | |||||
PullRequest: form.PullRequest, | |||||
Repository: form.Repository, | |||||
Create: form.Create, | |||||
Delete: form.Delete, | |||||
Fork: form.Fork, | |||||
Issues: form.Issues, | |||||
IssueAssign: form.IssueAssign, | |||||
IssueLabel: form.IssueLabel, | |||||
IssueMilestone: form.IssueMilestone, | |||||
IssueComment: form.IssueComment, | |||||
Release: form.Release, | |||||
Push: form.Push, | |||||
PullRequest: form.PullRequest, | |||||
PullRequestAssign: form.PullRequestAssign, | |||||
PullRequestLabel: form.PullRequestLabel, | |||||
PullRequestMilestone: form.PullRequestMilestone, | |||||
PullRequestComment: form.PullRequestComment, | |||||
PullRequestReview: form.PullRequestReview, | |||||
PullRequestSync: form.PullRequestSync, | |||||
Repository: form.Repository, | |||||
}, | }, | ||||
BranchFilter: form.BranchFilter, | BranchFilter: form.BranchFilter, | ||||
} | } |
</div> | </div> | ||||
<div class="events fields ui grid" {{if not .Webhook.ChooseEvents}}style="display:none"{{end}}> | <div class="events fields ui grid" {{if not .Webhook.ChooseEvents}}style="display:none"{{end}}> | ||||
<!-- Repository Events --> | |||||
<div class="fourteen wide column"> | |||||
<label>{{.i18n.Tr "repo.settings.event_header_repository"}}</label> | |||||
</div> | |||||
<!-- Create --> | <!-- Create --> | ||||
<div class="seven wide column"> | <div class="seven wide column"> | ||||
<div class="field"> | <div class="field"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- Repository --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="repository" type="checkbox" tabindex="0" {{if .Webhook.Repository}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_repository"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_repository_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Release --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="release" type="checkbox" tabindex="0" {{if .Webhook.Release}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_release"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_release_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Issue Events --> | |||||
<div class="fourteen wide column"> | |||||
<label>{{.i18n.Tr "repo.settings.event_header_issue"}}</label> | |||||
</div> | |||||
<!-- Issues --> | <!-- Issues --> | ||||
<div class="seven wide column"> | <div class="seven wide column"> | ||||
<div class="field"> | <div class="field"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- Issue Assign --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="issue_assign" type="checkbox" tabindex="0" {{if .Webhook.IssueAssign}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_issue_assign"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_issue_assign_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Issue Label --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="issue_label" type="checkbox" tabindex="0" {{if .Webhook.IssueLabel}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_issue_label"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_issue_label_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Issue Milestone --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="issue_milestone" type="checkbox" tabindex="0" {{if .Webhook.IssueMilestone}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_issue_milestone"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_issue_milestone_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Issue Comment --> | <!-- Issue Comment --> | ||||
<div class="seven wide column"> | <div class="seven wide column"> | ||||
<div class="field"> | <div class="field"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- Pull Request Events --> | |||||
<div class="fourteen wide column"> | |||||
<label>{{.i18n.Tr "repo.settings.event_header_pull_request"}}</label> | |||||
</div> | |||||
<!-- Pull Request --> | <!-- Pull Request --> | ||||
<div class="seven wide column"> | <div class="seven wide column"> | ||||
<div class="field"> | <div class="field"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- Repository --> | |||||
<!-- Pull Request Assign --> | |||||
<div class="seven wide column"> | <div class="seven wide column"> | ||||
<div class="field"> | <div class="field"> | ||||
<div class="ui checkbox"> | <div class="ui checkbox"> | ||||
<input class="hidden" name="repository" type="checkbox" tabindex="0" {{if .Webhook.Repository}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_repository"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_repository_desc"}}</span> | |||||
<input class="hidden" name="pull_request_assign" type="checkbox" tabindex="0" {{if .Webhook.PullRequestAssign}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_pull_request_assign"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_assign_desc"}}</span> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- Release --> | |||||
<!-- Pull Request Label --> | |||||
<div class="seven wide column"> | <div class="seven wide column"> | ||||
<div class="field"> | <div class="field"> | ||||
<div class="ui checkbox"> | <div class="ui checkbox"> | ||||
<input class="hidden" name="release" type="checkbox" tabindex="0" {{if .Webhook.Release}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_release"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_release_desc"}}</span> | |||||
<input class="hidden" name="pull_request_label" type="checkbox" tabindex="0" {{if .Webhook.PullRequestLabel}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_pull_request_label"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_label_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Pull Request Milestone --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="pull_request_milestone" type="checkbox" tabindex="0" {{if .Webhook.PullRequestMilestone}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_pull_request_milestone"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_milestone_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Pull Request Comment --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="pull_request_comment" type="checkbox" tabindex="0" {{if .Webhook.PullRequestComment}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_pull_request_comment"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_comment_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Pull Request Review --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="pull_request_review" type="checkbox" tabindex="0" {{if .Webhook.PullRequestReview}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_pull_request_review"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_review_desc"}}</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<!-- Pull Request Sync --> | |||||
<div class="seven wide column"> | |||||
<div class="field"> | |||||
<div class="ui checkbox"> | |||||
<input class="hidden" name="pull_request_sync" type="checkbox" tabindex="0" {{if .Webhook.PullRequestSync}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.event_pull_request_sync"}}</label> | |||||
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_sync_desc"}}</span> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> |