diff --git a/models/issue.go b/models/issue.go index 87f5eb08f..3596dc67e 100644 --- a/models/issue.go +++ b/models/issue.go @@ -86,6 +86,11 @@ func (issue *Issue) IsOverdue() bool { return util.TimeStampNow() >= issue.DeadlineUnix } +// LoadRepo loads repository +func (issue *Issue) LoadRepo() error { + return issue.loadRepo(x) +} + func (issue *Issue) loadRepo(e Engine) (err error) { if issue.Repo == nil { issue.Repo, err = getRepositoryByID(e, issue.RepoID) @@ -105,14 +110,9 @@ func (issue *Issue) IsTimetrackerEnabled() bool { return issue.Repo.IsTimetrackerEnabled() } -// GetPullRequest returns the issue pull request -func (issue *Issue) GetPullRequest() (pr *PullRequest, err error) { - if !issue.IsPull { - return nil, fmt.Errorf("Issue is not a pull request") - } - - pr, err = getPullRequestByIssueID(x, issue.ID) - return +// LoadPullRequest loads the issue pull request +func (issue *Issue) LoadPullRequest() error { + return issue.loadPullRequest(x) } func (issue *Issue) loadLabels(e Engine) (err error) { @@ -368,52 +368,6 @@ func (issue *Issue) HasLabel(labelID int64) bool { return issue.hasLabel(x, labelID) } -func (issue *Issue) sendLabelUpdatedWebhook(doer *User) { - var err error - - if err = issue.loadRepo(x); err != nil { - log.Error(4, "loadRepo: %v", err) - return - } - - if err = issue.loadPoster(x); err != nil { - log.Error(4, "loadPoster: %v", err) - return - } - - mode, _ := AccessLevel(issue.Poster.ID, issue.Repo) - if issue.IsPull { - if err = issue.loadPullRequest(x); err != nil { - log.Error(4, "loadPullRequest: %v", err) - return - } - if err = issue.PullRequest.LoadIssue(); err != nil { - log.Error(4, "LoadIssue: %v", err) - return - } - err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{ - Action: api.HookIssueLabelUpdated, - Index: issue.Index, - PullRequest: issue.PullRequest.APIFormat(), - Repository: issue.Repo.APIFormat(AccessModeNone), - Sender: doer.APIFormat(), - }) - } else { - err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{ - Action: api.HookIssueLabelUpdated, - Index: issue.Index, - Issue: issue.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } - if err != nil { - log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) - } else { - go HookQueue.Add(issue.RepoID) - } -} - func (issue *Issue) addLabel(e *xorm.Session, label *Label, doer *User) error { return newIssueLabel(e, issue, label, doer) } @@ -424,7 +378,6 @@ func (issue *Issue) AddLabel(doer *User, label *Label) error { return err } - issue.sendLabelUpdatedWebhook(doer) return nil } @@ -438,7 +391,6 @@ func (issue *Issue) AddLabels(doer *User, labels []*Label) error { return err } - issue.sendLabelUpdatedWebhook(doer) return nil } @@ -474,7 +426,6 @@ func (issue *Issue) RemoveLabel(doer *User, label *Label) error { return err } - issue.sendLabelUpdatedWebhook(doer) return nil } @@ -521,39 +472,6 @@ func (issue *Issue) ClearLabels(doer *User) (err error) { return fmt.Errorf("Commit: %v", err) } - if err = issue.loadPoster(x); err != nil { - return fmt.Errorf("loadPoster: %v", err) - } - - mode, _ := AccessLevel(issue.Poster.ID, issue.Repo) - if issue.IsPull { - err = issue.PullRequest.LoadIssue() - if err != nil { - log.Error(4, "LoadIssue: %v", err) - return - } - err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{ - Action: api.HookIssueLabelCleared, - Index: issue.Index, - PullRequest: issue.PullRequest.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } else { - err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{ - Action: api.HookIssueLabelCleared, - Index: issue.Index, - Issue: issue.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } - if err != nil { - log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) - } else { - go HookQueue.Add(issue.RepoID) - } - return nil } @@ -766,42 +684,6 @@ func (issue *Issue) ChangeTitle(doer *User, title string) (err error) { return err } - mode, _ := AccessLevel(issue.Poster.ID, issue.Repo) - if issue.IsPull { - issue.PullRequest.Issue = issue - err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{ - Action: api.HookIssueEdited, - Index: issue.Index, - Changes: &api.ChangesPayload{ - Title: &api.ChangesFromPayload{ - From: oldTitle, - }, - }, - PullRequest: issue.PullRequest.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } else { - err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{ - Action: api.HookIssueEdited, - Index: issue.Index, - Changes: &api.ChangesPayload{ - Title: &api.ChangesFromPayload{ - From: oldTitle, - }, - }, - Issue: issue.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: issue.Poster.APIFormat(), - }) - } - - if err != nil { - log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) - } else { - go HookQueue.Add(issue.RepoID) - } - return nil } @@ -825,48 +707,12 @@ func AddDeletePRBranchComment(doer *User, repo *Repository, issueID int64, branc // ChangeContent changes issue content, as the given user. func (issue *Issue) ChangeContent(doer *User, content string) (err error) { - oldContent := issue.Content issue.Content = content if err = UpdateIssueCols(issue, "content"); err != nil { return fmt.Errorf("UpdateIssueCols: %v", err) } - mode, _ := AccessLevel(issue.Poster.ID, issue.Repo) - if issue.IsPull { - issue.PullRequest.Issue = issue - err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{ - Action: api.HookIssueEdited, - Index: issue.Index, - Changes: &api.ChangesPayload{ - Body: &api.ChangesFromPayload{ - From: oldContent, - }, - }, - PullRequest: issue.PullRequest.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } else { - err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{ - Action: api.HookIssueEdited, - Index: issue.Index, - Changes: &api.ChangesPayload{ - Body: &api.ChangesFromPayload{ - From: oldContent, - }, - }, - Issue: issue.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } - if err != nil { - log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) - } else { - go HookQueue.Add(issue.RepoID) - } - return nil } diff --git a/models/issue_milestone.go b/models/issue_milestone.go index 177984a1f..b2801aa72 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -7,7 +7,6 @@ package models import ( "fmt" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" api "code.gitea.io/sdk/gitea" @@ -366,45 +365,6 @@ func ChangeMilestoneAssign(issue *Issue, doer *User, oldMilestoneID int64) (err return fmt.Errorf("Commit: %v", err) } - var hookAction api.HookIssueAction - if issue.MilestoneID > 0 { - hookAction = api.HookIssueMilestoned - } else { - hookAction = api.HookIssueDemilestoned - } - - if err = issue.LoadAttributes(); err != nil { - return err - } - - mode, _ := AccessLevel(doer.ID, issue.Repo) - if issue.IsPull { - err = issue.PullRequest.LoadIssue() - if err != nil { - log.Error(2, "LoadIssue: %v", err) - return - } - err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{ - Action: hookAction, - Index: issue.Index, - PullRequest: issue.PullRequest.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } else { - err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{ - Action: hookAction, - Index: issue.Index, - Issue: issue.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } - if err != nil { - log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) - } else { - go HookQueue.Add(issue.RepoID) - } return nil } diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index 1850bdfdb..1a417474f 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -96,3 +96,19 @@ func (r *actionNotifier) NotifyUpdateRelease(doer *models.User, rel *models.Rele func (r *actionNotifier) NotifyDeleteRelease(doer *models.User, rel *models.Release) { } + +func (r *actionNotifier) NotifyChangeMilestone(doer *models.User, issue *models.Issue) { +} + +func (r *actionNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { +} + +func (r *actionNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { +} + +func (r *actionNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) { +} + +func (r *actionNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) { +} diff --git a/modules/notification/base/base.go b/modules/notification/base/base.go index 82a5fb39b..88bf8205b 100644 --- a/modules/notification/base/base.go +++ b/modules/notification/base/base.go @@ -25,4 +25,10 @@ type Notifier interface { NotifyNewRelease(rel *models.Release) NotifyUpdateRelease(doer *models.User, rel *models.Release) NotifyDeleteRelease(doer *models.User, rel *models.Release) + NotifyChangeMilestone(doer *models.User, issue *models.Issue) + NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) + NotifyIssueClearLabels(doer *models.User, issue *models.Issue) + NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) + NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) } diff --git a/modules/notification/indexer/indexer.go b/modules/notification/indexer/indexer.go index 736c59350..d2d9a1663 100644 --- a/modules/notification/indexer/indexer.go +++ b/modules/notification/indexer/indexer.go @@ -72,3 +72,19 @@ func (r *indexerNotifier) NotifyUpdateRelease(doer *models.User, rel *models.Rel func (r *indexerNotifier) NotifyDeleteRelease(doer *models.User, rel *models.Release) { } + +func (r *indexerNotifier) NotifyChangeMilestone(doer *models.User, issue *models.Issue) { +} + +func (r *indexerNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { +} + +func (r *indexerNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { +} + +func (r *indexerNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) { +} + +func (r *indexerNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) { +} diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index 2d81f00a5..669445c1a 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -72,3 +72,19 @@ func (m *mailNotifier) NotifyUpdateRelease(doer *models.User, rel *models.Releas func (m *mailNotifier) NotifyDeleteRelease(doer *models.User, rel *models.Release) { } + +func (m *mailNotifier) NotifyChangeMilestone(doer *models.User, issue *models.Issue) { +} + +func (m *mailNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { +} + +func (m *mailNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { +} + +func (m *mailNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) { +} + +func (m *mailNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) { +} diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 24f7c41f1..8a142ff09 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -117,3 +117,39 @@ func NotifyDeleteRelease(doer *models.User, rel *models.Release) { notifier.NotifyDeleteRelease(doer, rel) } } + +// NotifyChangeMilestone notifies change milestone to notifiers +func NotifyChangeMilestone(doer *models.User, issue *models.Issue) { + for _, notifier := range notifiers { + notifier.NotifyChangeMilestone(doer, issue) + } +} + +// NotifyIssueChangeContent notifies change content to notifiers +func NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { + for _, notifier := range notifiers { + notifier.NotifyIssueChangeContent(doer, issue, oldContent) + } +} + +// NotifyIssueClearLabels notifies clear labels to notifiers +func NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { + for _, notifier := range notifiers { + notifier.NotifyIssueClearLabels(doer, issue) + } +} + +// NotifyIssueChangeTitle notifies change title to notifiers +func NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) { + for _, notifier := range notifiers { + notifier.NotifyIssueChangeTitle(doer, issue, oldTitle) + } +} + +// NotifyIssueChangeLabels notifies change labels to notifiers +func NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) { + for _, notifier := range notifiers { + notifier.NotifyIssueChangeLabels(doer, issue, addedLabels, removedLabels) + } +} diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index 231fc8243..7c34785f8 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -96,3 +96,19 @@ func (ns *notificationService) NotifyUpdateRelease(doer *models.User, rel *model func (ns *notificationService) NotifyDeleteRelease(doer *models.User, rel *models.Release) { } + +func (ns *notificationService) NotifyChangeMilestone(doer *models.User, issue *models.Issue) { +} + +func (ns *notificationService) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { +} + +func (ns *notificationService) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { +} + +func (ns *notificationService) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) { +} + +func (ns *notificationService) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) { +} diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index 30aa44b09..ed6927366 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -262,3 +262,237 @@ func (w *webhookNotifier) NotifyDeleteRelease(doer *models.User, rel *models.Rel go models.HookQueue.Add(rel.Repo.ID) } } + +func (w *webhookNotifier) NotifyChangeMilestone(doer *models.User, issue *models.Issue) { + var hookAction api.HookIssueAction + if issue.MilestoneID > 0 { + hookAction = api.HookIssueMilestoned + } else { + hookAction = api.HookIssueDemilestoned + } + + var err error + if err = issue.LoadAttributes(); err != nil { + log.Error(2, "LoadAttributes: %v", err) + return + } + + mode, _ := models.AccessLevel(doer.ID, issue.Repo) + if issue.IsPull { + err = issue.PullRequest.LoadIssue() + if err != nil { + log.Error(2, "LoadIssue: %v", err) + return + } + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: hookAction, + Index: issue.Index, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } else { + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ + Action: hookAction, + Index: issue.Index, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } + if err != nil { + log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } else { + go models.HookQueue.Add(issue.RepoID) + } +} + +func (w *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { + mode, _ := models.AccessLevel(doer.ID, issue.Repo) + var err error + if issue.IsPull { + issue.PullRequest.Issue = issue + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } else { + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } + if err != nil { + log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } else { + go models.HookQueue.Add(issue.RepoID) + } +} + +func (w *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { + var err error + mode, _ := models.AccessLevel(doer.ID, issue.Repo) + if issue.IsPull { + err = issue.PullRequest.LoadIssue() + if err != nil { + log.Error(4, "LoadIssue: %v", err) + return + } + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueLabelCleared, + Index: issue.Index, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } else { + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueLabelCleared, + Index: issue.Index, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } + if err != nil { + log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } else { + go models.HookQueue.Add(issue.RepoID) + } +} + +func (w *webhookNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) { + mode, _ := models.AccessLevel(doer.ID, issue.Repo) + var err error + if issue.IsPull { + issue.PullRequest.Issue = issue + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Title: &api.ChangesFromPayload{ + From: oldTitle, + }, + }, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } else { + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Title: &api.ChangesFromPayload{ + From: oldTitle, + }, + }, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: issue.Poster.APIFormat(), + }) + } + + if err != nil { + log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } else { + go models.HookQueue.Add(issue.RepoID) + } +} + +/* +func (w *webhookNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models.Issue, isClosed bool) { + mode, _ := models.AccessLevel(doer.ID, issue.Repo) + var err error + if issue.IsPull { + // Merge pull request calls issue.changeStatus so we need to handle separately. + issue.PullRequest.Issue = issue + apiPullRequest := &api.PullRequestPayload{ + Index: issue.Index, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + } + if isClosed { + apiPullRequest.Action = api.HookIssueClosed + } else { + apiPullRequest.Action = api.HookIssueReOpened + } + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest) + } else { + apiIssue := &api.IssuePayload{ + Index: issue.Index, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + } + if isClosed { + apiIssue.Action = api.HookIssueClosed + } else { + apiIssue.Action = api.HookIssueReOpened + } + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue) + } + if err != nil { + log.Error(4, "PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err) + } else { + go models.HookQueue.Add(issue.Repo.ID) + } +}*/ + +func (w *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, + addedLabels []*models.Label, removedLabels []*models.Label) { + var err error + if err = issue.LoadRepo(); err != nil { + log.Error(4, "LoadRepo: %v", err) + return + } + + mode, _ := models.AccessLevel(doer.ID, issue.Repo) + if issue.IsPull { + if err = issue.LoadPullRequest(); err != nil { + log.Error(4, "LoadPullRequest: %v", err) + return + } + if err = issue.PullRequest.LoadIssue(); err != nil { + log.Error(4, "LoadIssue: %v", err) + return + } + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueLabelUpdated, + Index: issue.Index, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } else { + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueLabelUpdated, + Index: issue.Index, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } + if err != nil { + log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } else { + go models.HookQueue.Add(issue.RepoID) + } +} diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 37683215a..e31a23a4b 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -320,6 +320,8 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { ctx.Error(500, "ChangeMilestoneAssign", err) return } + + notification.NotifyChangeMilestone(ctx.User, issue) } if err = models.UpdateIssue(issue); err != nil { diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go index 3657f02c6..38280785e 100644 --- a/routers/api/v1/repo/issue_label.go +++ b/routers/api/v1/repo/issue_label.go @@ -7,6 +7,7 @@ package repo import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/notification" api "code.gitea.io/sdk/gitea" ) @@ -113,6 +114,7 @@ func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { ctx.Error(500, "AddLabels", err) return } + notification.NotifyIssueChangeLabels(ctx.User, issue, labels, nil) labels, err = models.GetLabelsByIssueID(issue.ID) if err != nil { @@ -308,5 +310,7 @@ func ClearIssueLabels(ctx *context.APIContext) { return } + notification.NotifyIssueClearLabels(ctx.User, issue) + ctx.Status(204) } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 639b36689..bf90e5b9e 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -371,6 +371,8 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { ctx.Error(500, "ChangeMilestoneAssign", err) return } + + notification.NotifyChangeMilestone(ctx.User, issue) } if err = models.UpdateIssue(issue); err != nil { diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 56a4cb920..434d0ac54 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -861,11 +861,14 @@ func UpdateIssueTitle(ctx *context.Context) { return } + oldTitle := issue.Title if err := issue.ChangeTitle(ctx.User, title); err != nil { ctx.ServerError("ChangeTitle", err) return } + notification.NotifyIssueChangeTitle(ctx.User, issue, oldTitle) + ctx.JSON(200, map[string]interface{}{ "title": issue.Title, }) @@ -884,11 +887,14 @@ func UpdateIssueContent(ctx *context.Context) { } content := ctx.Query("content") + oldContent := issue.Content if err := issue.ChangeContent(ctx.User, content); err != nil { ctx.ServerError("ChangeContent", err) return } + notification.NotifyIssueChangeContent(ctx.User, issue, oldContent) + ctx.JSON(200, map[string]interface{}{ "content": string(markdown.Render([]byte(issue.Content), ctx.Query("context"), ctx.Repo.Repository.ComposeMetas())), }) @@ -912,6 +918,8 @@ func UpdateIssueMilestone(ctx *context.Context) { ctx.ServerError("ChangeMilestoneAssign", err) return } + + notification.NotifyChangeMilestone(ctx.User, issue) } ctx.JSON(200, map[string]interface{}{ diff --git a/routers/repo/issue_label.go b/routers/repo/issue_label.go index 8631ef0d0..e1886b295 100644 --- a/routers/repo/issue_label.go +++ b/routers/repo/issue_label.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" ) const ( @@ -145,6 +146,7 @@ func UpdateIssueLabel(ctx *context.Context) { ctx.ServerError("ClearLabels", err) return } + notification.NotifyIssueClearLabels(ctx.User, issue) } case "attach", "detach", "toggle": label, err := models.GetLabelByID(ctx.QueryInt64("id")) @@ -168,21 +170,29 @@ func UpdateIssueLabel(ctx *context.Context) { } } + var addedLabels = make(map[int][]*models.Label) + var removedLabels = make(map[int][]*models.Label) if action == "attach" { - for _, issue := range issues { + for i, issue := range issues { if err = issue.AddLabel(ctx.User, label); err != nil { ctx.ServerError("AddLabel", err) return } + addedLabels[i] = append(addedLabels[i], label) } } else { - for _, issue := range issues { + for i, issue := range issues { if err = issue.RemoveLabel(ctx.User, label); err != nil { ctx.ServerError("RemoveLabel", err) return } + removedLabels[i] = append(removedLabels[i], label) } } + + for i, issue := range issues { + notification.NotifyIssueChangeLabels(ctx.User, issue, addedLabels[i], removedLabels[i]) + } default: log.Warn("Unrecognized action: %s", action) ctx.Error(500)