code.gitea.io/gitea@v1.22.3/routers/api/v1/notify/user.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package notify 5 6 import ( 7 "net/http" 8 "time" 9 10 activities_model "code.gitea.io/gitea/models/activities" 11 "code.gitea.io/gitea/models/db" 12 "code.gitea.io/gitea/modules/structs" 13 "code.gitea.io/gitea/services/context" 14 "code.gitea.io/gitea/services/convert" 15 ) 16 17 // ListNotifications list users's notification threads 18 func ListNotifications(ctx *context.APIContext) { 19 // swagger:operation GET /notifications notification notifyGetList 20 // --- 21 // summary: List users's notification threads 22 // consumes: 23 // - application/json 24 // produces: 25 // - application/json 26 // parameters: 27 // - name: all 28 // in: query 29 // description: If true, show notifications marked as read. Default value is false 30 // type: boolean 31 // - name: status-types 32 // in: query 33 // description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned." 34 // type: array 35 // collectionFormat: multi 36 // items: 37 // type: string 38 // - name: subject-type 39 // in: query 40 // description: "filter notifications by subject type" 41 // type: array 42 // collectionFormat: multi 43 // items: 44 // type: string 45 // enum: [issue,pull,commit,repository] 46 // - name: since 47 // in: query 48 // description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format 49 // type: string 50 // format: date-time 51 // - name: before 52 // in: query 53 // description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format 54 // type: string 55 // format: date-time 56 // - name: page 57 // in: query 58 // description: page number of results to return (1-based) 59 // type: integer 60 // - name: limit 61 // in: query 62 // description: page size of results 63 // type: integer 64 // responses: 65 // "200": 66 // "$ref": "#/responses/NotificationThreadList" 67 opts := getFindNotificationOptions(ctx) 68 if ctx.Written() { 69 return 70 } 71 72 totalCount, err := db.Count[activities_model.Notification](ctx, opts) 73 if err != nil { 74 ctx.InternalServerError(err) 75 return 76 } 77 78 nl, err := db.Find[activities_model.Notification](ctx, opts) 79 if err != nil { 80 ctx.InternalServerError(err) 81 return 82 } 83 err = activities_model.NotificationList(nl).LoadAttributes(ctx) 84 if err != nil { 85 ctx.InternalServerError(err) 86 return 87 } 88 89 ctx.SetTotalCountHeader(totalCount) 90 ctx.JSON(http.StatusOK, convert.ToNotifications(ctx, nl)) 91 } 92 93 // ReadNotifications mark notification threads as read, unread, or pinned 94 func ReadNotifications(ctx *context.APIContext) { 95 // swagger:operation PUT /notifications notification notifyReadList 96 // --- 97 // summary: Mark notification threads as read, pinned or unread 98 // consumes: 99 // - application/json 100 // produces: 101 // - application/json 102 // parameters: 103 // - name: last_read_at 104 // in: query 105 // description: Describes the last point that notifications were checked. Anything updated since this time will not be updated. 106 // type: string 107 // format: date-time 108 // required: false 109 // - name: all 110 // in: query 111 // description: If true, mark all notifications on this repo. Default value is false 112 // type: string 113 // required: false 114 // - name: status-types 115 // in: query 116 // description: "Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread." 117 // type: array 118 // collectionFormat: multi 119 // items: 120 // type: string 121 // required: false 122 // - name: to-status 123 // in: query 124 // description: Status to mark notifications as, Defaults to read. 125 // type: string 126 // required: false 127 // responses: 128 // "205": 129 // "$ref": "#/responses/NotificationThreadList" 130 131 lastRead := int64(0) 132 qLastRead := ctx.FormTrim("last_read_at") 133 if len(qLastRead) > 0 { 134 tmpLastRead, err := time.Parse(time.RFC3339, qLastRead) 135 if err != nil { 136 ctx.Error(http.StatusBadRequest, "Parse", err) 137 return 138 } 139 if !tmpLastRead.IsZero() { 140 lastRead = tmpLastRead.Unix() 141 } 142 } 143 opts := &activities_model.FindNotificationOptions{ 144 UserID: ctx.Doer.ID, 145 UpdatedBeforeUnix: lastRead, 146 } 147 if !ctx.FormBool("all") { 148 statuses := ctx.FormStrings("status-types") 149 opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) 150 } 151 nl, err := db.Find[activities_model.Notification](ctx, opts) 152 if err != nil { 153 ctx.InternalServerError(err) 154 return 155 } 156 157 targetStatus := statusStringToNotificationStatus(ctx.FormString("to-status")) 158 if targetStatus == 0 { 159 targetStatus = activities_model.NotificationStatusRead 160 } 161 162 changed := make([]*structs.NotificationThread, 0, len(nl)) 163 164 for _, n := range nl { 165 notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) 166 if err != nil { 167 ctx.InternalServerError(err) 168 return 169 } 170 _ = notif.LoadAttributes(ctx) 171 changed = append(changed, convert.ToNotificationThread(ctx, notif)) 172 } 173 174 ctx.JSON(http.StatusResetContent, changed) 175 }