code.gitea.io/gitea@v1.21.7/routers/api/v1/notify/repo.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  	"strings"
     9  	"time"
    10  
    11  	activities_model "code.gitea.io/gitea/models/activities"
    12  	"code.gitea.io/gitea/modules/context"
    13  	"code.gitea.io/gitea/modules/log"
    14  	"code.gitea.io/gitea/modules/structs"
    15  	"code.gitea.io/gitea/services/convert"
    16  )
    17  
    18  func statusStringToNotificationStatus(status string) activities_model.NotificationStatus {
    19  	switch strings.ToLower(strings.TrimSpace(status)) {
    20  	case "unread":
    21  		return activities_model.NotificationStatusUnread
    22  	case "read":
    23  		return activities_model.NotificationStatusRead
    24  	case "pinned":
    25  		return activities_model.NotificationStatusPinned
    26  	default:
    27  		return 0
    28  	}
    29  }
    30  
    31  func statusStringsToNotificationStatuses(statuses, defaultStatuses []string) []activities_model.NotificationStatus {
    32  	if len(statuses) == 0 {
    33  		statuses = defaultStatuses
    34  	}
    35  	results := make([]activities_model.NotificationStatus, 0, len(statuses))
    36  	for _, status := range statuses {
    37  		notificationStatus := statusStringToNotificationStatus(status)
    38  		if notificationStatus > 0 {
    39  			results = append(results, notificationStatus)
    40  		}
    41  	}
    42  	return results
    43  }
    44  
    45  // ListRepoNotifications list users's notification threads on a specific repo
    46  func ListRepoNotifications(ctx *context.APIContext) {
    47  	// swagger:operation GET /repos/{owner}/{repo}/notifications notification notifyGetRepoList
    48  	// ---
    49  	// summary: List users's notification threads on a specific repo
    50  	// consumes:
    51  	// - application/json
    52  	// produces:
    53  	// - application/json
    54  	// parameters:
    55  	// - name: owner
    56  	//   in: path
    57  	//   description: owner of the repo
    58  	//   type: string
    59  	//   required: true
    60  	// - name: repo
    61  	//   in: path
    62  	//   description: name of the repo
    63  	//   type: string
    64  	//   required: true
    65  	// - name: all
    66  	//   in: query
    67  	//   description: If true, show notifications marked as read. Default value is false
    68  	//   type: boolean
    69  	// - name: status-types
    70  	//   in: query
    71  	//   description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned"
    72  	//   type: array
    73  	//   collectionFormat: multi
    74  	//   items:
    75  	//     type: string
    76  	// - name: subject-type
    77  	//   in: query
    78  	//   description: "filter notifications by subject type"
    79  	//   type: array
    80  	//   collectionFormat: multi
    81  	//   items:
    82  	//     type: string
    83  	//     enum: [issue,pull,commit,repository]
    84  	// - name: since
    85  	//   in: query
    86  	//   description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
    87  	//   type: string
    88  	//   format: date-time
    89  	// - name: before
    90  	//   in: query
    91  	//   description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
    92  	//   type: string
    93  	//   format: date-time
    94  	// - name: page
    95  	//   in: query
    96  	//   description: page number of results to return (1-based)
    97  	//   type: integer
    98  	// - name: limit
    99  	//   in: query
   100  	//   description: page size of results
   101  	//   type: integer
   102  	// responses:
   103  	//   "200":
   104  	//     "$ref": "#/responses/NotificationThreadList"
   105  	opts := getFindNotificationOptions(ctx)
   106  	if ctx.Written() {
   107  		return
   108  	}
   109  	opts.RepoID = ctx.Repo.Repository.ID
   110  
   111  	totalCount, err := activities_model.CountNotifications(ctx, opts)
   112  	if err != nil {
   113  		ctx.InternalServerError(err)
   114  		return
   115  	}
   116  
   117  	nl, err := activities_model.GetNotifications(ctx, opts)
   118  	if err != nil {
   119  		ctx.InternalServerError(err)
   120  		return
   121  	}
   122  	err = nl.LoadAttributes(ctx)
   123  	if err != nil {
   124  		ctx.InternalServerError(err)
   125  		return
   126  	}
   127  
   128  	ctx.SetTotalCountHeader(totalCount)
   129  
   130  	ctx.JSON(http.StatusOK, convert.ToNotifications(ctx, nl))
   131  }
   132  
   133  // ReadRepoNotifications mark notification threads as read on a specific repo
   134  func ReadRepoNotifications(ctx *context.APIContext) {
   135  	// swagger:operation PUT /repos/{owner}/{repo}/notifications notification notifyReadRepoList
   136  	// ---
   137  	// summary: Mark notification threads as read, pinned or unread on a specific repo
   138  	// consumes:
   139  	// - application/json
   140  	// produces:
   141  	// - application/json
   142  	// parameters:
   143  	// - name: owner
   144  	//   in: path
   145  	//   description: owner of the repo
   146  	//   type: string
   147  	//   required: true
   148  	// - name: repo
   149  	//   in: path
   150  	//   description: name of the repo
   151  	//   type: string
   152  	//   required: true
   153  	// - name: all
   154  	//   in: query
   155  	//   description: If true, mark all notifications on this repo. Default value is false
   156  	//   type: string
   157  	//   required: false
   158  	// - name: status-types
   159  	//   in: query
   160  	//   description: "Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread."
   161  	//   type: array
   162  	//   collectionFormat: multi
   163  	//   items:
   164  	//     type: string
   165  	//   required: false
   166  	// - name: to-status
   167  	//   in: query
   168  	//   description: Status to mark notifications as. Defaults to read.
   169  	//   type: string
   170  	//   required: false
   171  	// - name: last_read_at
   172  	//   in: query
   173  	//   description: Describes the last point that notifications were checked. Anything updated since this time will not be updated.
   174  	//   type: string
   175  	//   format: date-time
   176  	//   required: false
   177  	// responses:
   178  	//   "205":
   179  	//     "$ref": "#/responses/NotificationThreadList"
   180  
   181  	lastRead := int64(0)
   182  	qLastRead := ctx.FormTrim("last_read_at")
   183  	if len(qLastRead) > 0 {
   184  		tmpLastRead, err := time.Parse(time.RFC3339, qLastRead)
   185  		if err != nil {
   186  			ctx.Error(http.StatusBadRequest, "Parse", err)
   187  			return
   188  		}
   189  		if !tmpLastRead.IsZero() {
   190  			lastRead = tmpLastRead.Unix()
   191  		}
   192  	}
   193  
   194  	opts := &activities_model.FindNotificationOptions{
   195  		UserID:            ctx.Doer.ID,
   196  		RepoID:            ctx.Repo.Repository.ID,
   197  		UpdatedBeforeUnix: lastRead,
   198  	}
   199  
   200  	if !ctx.FormBool("all") {
   201  		statuses := ctx.FormStrings("status-types")
   202  		opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"})
   203  		log.Error("%v", opts.Status)
   204  	}
   205  	nl, err := activities_model.GetNotifications(ctx, opts)
   206  	if err != nil {
   207  		ctx.InternalServerError(err)
   208  		return
   209  	}
   210  
   211  	targetStatus := statusStringToNotificationStatus(ctx.FormString("to-status"))
   212  	if targetStatus == 0 {
   213  		targetStatus = activities_model.NotificationStatusRead
   214  	}
   215  
   216  	changed := make([]*structs.NotificationThread, 0, len(nl))
   217  
   218  	for _, n := range nl {
   219  		notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus)
   220  		if err != nil {
   221  			ctx.InternalServerError(err)
   222  			return
   223  		}
   224  		_ = notif.LoadAttributes(ctx)
   225  		changed = append(changed, convert.ToNotificationThread(ctx, notif))
   226  	}
   227  	ctx.JSON(http.StatusResetContent, changed)
   228  }