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  }