Skip to content

Commit 44de66b

Browse files
6543sapk
authored andcommitted
[API] add endpoint to check notifications [Extend #9488] (#9595)
* introduce GET /notifications/new * add TEST * use Sprintf instead of path.Join * Error more verbose * return number of notifications if unreaded exist * 200 http status for available notifications
1 parent ce274d6 commit 44de66b

File tree

9 files changed

+107
-5
lines changed

9 files changed

+107
-5
lines changed

integrations/api_notification_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ func TestAPINotification(t *testing.T) {
8181
assert.EqualValues(t, thread5.Issue.APIURL(), apiN.Subject.URL)
8282
assert.EqualValues(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL)
8383

84+
// -- check notifications --
85+
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/new?token=%s", token))
86+
resp = session.MakeRequest(t, req, http.StatusOK)
87+
8488
// -- mark notifications as read --
8589
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
8690
resp = session.MakeRequest(t, req, http.StatusOK)
@@ -103,4 +107,8 @@ func TestAPINotification(t *testing.T) {
103107
assert.Equal(t, models.NotificationStatusUnread, thread5.Status)
104108
thread5 = models.AssertExistsAndLoadBean(t, &models.Notification{ID: 5}).(*models.Notification)
105109
assert.Equal(t, models.NotificationStatusRead, thread5.Status)
110+
111+
// -- check notifications --
112+
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/new?token=%s", token))
113+
resp = session.MakeRequest(t, req, http.StatusNoContent)
106114
}

models/issue.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package models
77

88
import (
99
"fmt"
10-
"path"
1110
"regexp"
1211
"sort"
1312
"strconv"
@@ -324,7 +323,7 @@ func (issue *Issue) GetIsRead(userID int64) error {
324323

325324
// APIURL returns the absolute APIURL to this issue.
326325
func (issue *Issue) APIURL() string {
327-
return issue.Repo.APIURL() + "/" + path.Join("issues", fmt.Sprint(issue.Index))
326+
return fmt.Sprintf("%s/issues/%d", issue.Repo.APIURL(), issue.Index)
328327
}
329328

330329
// HTMLURL returns the absolute URL to this issue.

models/issue_comment.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package models
88

99
import (
1010
"fmt"
11-
"path"
1211
"strings"
1312

1413
"code.gitea.io/gitea/modules/git"
@@ -249,7 +248,7 @@ func (c *Comment) APIURL() string {
249248
return ""
250249
}
251250

252-
return c.Issue.Repo.APIURL() + "/" + path.Join("issues/comments", fmt.Sprint(c.ID))
251+
return fmt.Sprintf("%s/issues/comments/%d", c.Issue.Repo.APIURL(), c.ID)
253252
}
254253

255254
// IssueURL formats a URL-string to the issue

models/notification.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"path"
1010

11+
"code.gitea.io/gitea/modules/log"
1112
"code.gitea.io/gitea/modules/setting"
1213
api "code.gitea.io/gitea/modules/structs"
1314
"code.gitea.io/gitea/modules/timeutil"
@@ -294,6 +295,20 @@ func notificationsForUser(e Engine, user *User, statuses []NotificationStatus, p
294295
return
295296
}
296297

298+
// CountUnread count unread notifications for a user
299+
func CountUnread(user *User) int64 {
300+
return countUnread(x, user.ID)
301+
}
302+
303+
func countUnread(e Engine, userID int64) int64 {
304+
exist, err := e.Where("user_id = ?", userID).And("status = ?", NotificationStatusUnread).Count(new(Notification))
305+
if err != nil {
306+
log.Error("countUnread", err)
307+
return 0
308+
}
309+
return exist
310+
}
311+
297312
// APIFormat converts a Notification to api.NotificationThread
298313
func (n *Notification) APIFormat() *api.NotificationThread {
299314
result := &api.NotificationThread{
@@ -388,7 +403,7 @@ func (n *Notification) loadComment(e Engine) (err error) {
388403
if n.Comment == nil && n.CommentID > 0 {
389404
n.Comment, err = GetCommentByID(n.CommentID)
390405
if err != nil {
391-
return fmt.Errorf("GetCommentByID [%d]: %v", n.CommentID, err)
406+
return fmt.Errorf("GetCommentByID [%d] for issue ID [%d]: %v", n.CommentID, n.IssueID, err)
392407
}
393408
}
394409
return nil

modules/structs/notifications.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ type NotificationSubject struct {
2626
LatestCommentURL string `json:"latest_comment_url"`
2727
Type string `json:"type" binding:"In(Issue,Pull,Commit)"`
2828
}
29+
30+
// NotificationCount number of unread notifications
31+
type NotificationCount struct {
32+
New int64 `json:"new"`
33+
}

routers/api/v1/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ func RegisterRoutes(m *macaron.Macaron) {
518518
m.Combo("").
519519
Get(notify.ListNotifications).
520520
Put(notify.ReadNotifications)
521+
m.Get("/new", notify.NewAvailable)
521522
m.Combo("/threads/:id").
522523
Get(notify.GetThread).
523524
Patch(notify.ReadThread)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2020 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package notify
6+
7+
import (
8+
"net/http"
9+
10+
"code.gitea.io/gitea/models"
11+
"code.gitea.io/gitea/modules/context"
12+
api "code.gitea.io/gitea/modules/structs"
13+
)
14+
15+
// NewAvailable check if unread notifications exist
16+
func NewAvailable(ctx *context.APIContext) {
17+
// swagger:operation GET /notifications/new notification notifyNewAvailable
18+
// ---
19+
// summary: Check if unread notifications exist
20+
// responses:
21+
// "200":
22+
// "$ref": "#/responses/NotificationCount"
23+
// "204":
24+
// description: No unread notification
25+
26+
count := models.CountUnread(ctx.User)
27+
28+
if count > 0 {
29+
ctx.JSON(http.StatusOK, api.NotificationCount{New: count})
30+
} else {
31+
ctx.Status(http.StatusNoContent)
32+
}
33+
}

routers/api/v1/swagger/notify.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,10 @@ type swaggerNotificationThreadList struct {
2121
// in:body
2222
Body []api.NotificationThread `json:"body"`
2323
}
24+
25+
// Number of unread notifications
26+
// swagger:response NotificationCount
27+
type swaggerNotificationCount struct {
28+
// in:body
29+
Body api.NotificationCount `json:"body"`
30+
}

templates/swagger/v1_json.tmpl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,23 @@
494494
}
495495
}
496496
},
497+
"/notifications/new": {
498+
"get": {
499+
"tags": [
500+
"notification"
501+
],
502+
"summary": "Check if unread notifications exist",
503+
"operationId": "notifyNewAvailable",
504+
"responses": {
505+
"200": {
506+
"$ref": "#/responses/NotificationCount"
507+
},
508+
"204": {
509+
"description": "No unread notification"
510+
}
511+
}
512+
}
513+
},
497514
"/notifications/threads/{id}": {
498515
"get": {
499516
"consumes": [
@@ -10911,6 +10928,18 @@
1091110928
},
1091210929
"x-go-package": "code.gitea.io/gitea/modules/structs"
1091310930
},
10931+
"NotificationCount": {
10932+
"description": "NotificationCount number of unread notifications",
10933+
"type": "object",
10934+
"properties": {
10935+
"new": {
10936+
"type": "integer",
10937+
"format": "int64",
10938+
"x-go-name": "New"
10939+
}
10940+
},
10941+
"x-go-package": "code.gitea.io/gitea/modules/structs"
10942+
},
1091410943
"NotificationSubject": {
1091510944
"description": "NotificationSubject contains the notification subject (Issue/Pull/Commit)",
1091610945
"type": "object",
@@ -12397,6 +12426,12 @@
1239712426
}
1239812427
}
1239912428
},
12429+
"NotificationCount": {
12430+
"description": "Number of unread notifications",
12431+
"schema": {
12432+
"$ref": "#/definitions/NotificationCount"
12433+
}
12434+
},
1240012435
"NotificationThread": {
1240112436
"description": "NotificationThread",
1240212437
"schema": {

0 commit comments

Comments
 (0)