| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | // GoToSocial | 
					
						
							|  |  |  | // Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | // SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | // GNU Affero General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package paging | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/gin-gonic/gin" | 
					
						
							|  |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseIDPage parses an ID Page from a request context, returning BadRequest on error parsing. | 
					
						
							|  |  |  | // The min, max and default parameters define the page size limit minimum, maximum and default | 
					
						
							|  |  |  | // value, where a non-zero default will enforce paging for the endpoint on which this is called. | 
					
						
							|  |  |  | // While conversely, a zero default limit will not enforce paging, returning a nil page value. | 
					
						
							|  |  |  | func ParseIDPage(c *gin.Context, min, max, _default int) (*Page, gtserror.WithCode) { | 
					
						
							|  |  |  | 	// Extract request query params. | 
					
						
							| 
									
										
										
										
											2023-09-12 14:00:35 +01:00
										 |  |  | 	sinceID, haveSince := c.GetQuery("since_id") | 
					
						
							|  |  |  | 	minID, haveMin := c.GetQuery("min_id") | 
					
						
							|  |  |  | 	maxID, haveMax := c.GetQuery("max_id") | 
					
						
							| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Extract request limit parameter. | 
					
						
							|  |  |  | 	limit, errWithCode := ParseLimit(c, min, max, _default) | 
					
						
							|  |  |  | 	if errWithCode != nil { | 
					
						
							|  |  |  | 		return nil, errWithCode | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-12 14:00:35 +01:00
										 |  |  | 	switch { | 
					
						
							|  |  |  | 	case haveMin: | 
					
						
							|  |  |  | 		// A min_id was supplied, even if the value | 
					
						
							|  |  |  | 		// itself is empty. This indicates ASC order. | 
					
						
							|  |  |  | 		return &Page{ | 
					
						
							|  |  |  | 			Min:   MinID(minID), | 
					
						
							|  |  |  | 			Max:   MaxID(maxID), | 
					
						
							|  |  |  | 			Limit: limit, | 
					
						
							|  |  |  | 		}, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case haveMax || haveSince: | 
					
						
							|  |  |  | 		// A max_id or since_id was supplied, even if the | 
					
						
							|  |  |  | 		// value itself is empty. This indicates DESC order. | 
					
						
							|  |  |  | 		return &Page{ | 
					
						
							|  |  |  | 			Min:   SinceID(sinceID), | 
					
						
							|  |  |  | 			Max:   MaxID(maxID), | 
					
						
							|  |  |  | 			Limit: limit, | 
					
						
							|  |  |  | 		}, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case limit == 0: | 
					
						
							| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | 		// No ID paging params provided, and no default | 
					
						
							|  |  |  | 		// limit value which indicates paging not enforced. | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-12 14:00:35 +01:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		// only limit. | 
					
						
							|  |  |  | 		return &Page{ | 
					
						
							|  |  |  | 			Min:   SinceID(""), | 
					
						
							|  |  |  | 			Max:   MaxID(""), | 
					
						
							|  |  |  | 			Limit: limit, | 
					
						
							|  |  |  | 		}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseShortcodeDomainPage parses an emoji shortcode domain Page from a request context, returning BadRequest | 
					
						
							|  |  |  | // on error parsing. The min, max and default parameters define the page size limit minimum, maximum and default | 
					
						
							|  |  |  | // value where a non-zero default will enforce paging for the endpoint on which this is called. While conversely, | 
					
						
							|  |  |  | // a zero default limit will not enforce paging, returning a nil page value. | 
					
						
							|  |  |  | func ParseShortcodeDomainPage(c *gin.Context, min, max, _default int) (*Page, gtserror.WithCode) { | 
					
						
							|  |  |  | 	// Extract request query parameters. | 
					
						
							| 
									
										
										
										
											2023-09-12 14:00:35 +01:00
										 |  |  | 	minShortcode, haveMin := c.GetQuery("min_shortcode_domain") | 
					
						
							|  |  |  | 	maxShortcode, haveMax := c.GetQuery("max_shortcode_domain") | 
					
						
							| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Extract request limit parameter. | 
					
						
							|  |  |  | 	limit, errWithCode := ParseLimit(c, min, max, _default) | 
					
						
							|  |  |  | 	if errWithCode != nil { | 
					
						
							|  |  |  | 		return nil, errWithCode | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-12 14:00:35 +01:00
										 |  |  | 	if !haveMin && | 
					
						
							|  |  |  | 		!haveMax && | 
					
						
							| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | 		limit == 0 { | 
					
						
							|  |  |  | 		// No ID paging params provided, and no default | 
					
						
							|  |  |  | 		// limit value which indicates paging not enforced. | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &Page{ | 
					
						
							|  |  |  | 		Min:   MinShortcodeDomain(minShortcode), | 
					
						
							|  |  |  | 		Max:   MaxShortcodeDomain(maxShortcode), | 
					
						
							|  |  |  | 		Limit: limit, | 
					
						
							|  |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseLimit parses the limit query parameter from a request context, returning BadRequest on error parsing and _default if zero limit given. | 
					
						
							|  |  |  | func ParseLimit(c *gin.Context, min, max, _default int) (int, gtserror.WithCode) { | 
					
						
							|  |  |  | 	// Get limit query param. | 
					
						
							| 
									
										
										
										
											2023-09-12 14:00:35 +01:00
										 |  |  | 	str, ok := c.GetQuery("limit") | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return _default, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-09-07 15:58:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Attempt to parse limit int. | 
					
						
							|  |  |  | 	i, err := strconv.Atoi(str) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		const help = "bad integer limit value" | 
					
						
							|  |  |  | 		return 0, gtserror.NewErrorBadRequest(err, help) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case i == 0: | 
					
						
							|  |  |  | 		return _default, nil | 
					
						
							|  |  |  | 	case i < min: | 
					
						
							|  |  |  | 		return min, nil | 
					
						
							|  |  |  | 	case i > max: | 
					
						
							|  |  |  | 		return max, nil | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return i, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |