hako/internal/archival/domain/requests.go
2026-01-18 09:51:25 +01:00

98 lines
2.6 KiB
Go

package domain
import (
"fmt"
"net/url"
"strconv"
archivalStore "git.nakama.town/fmartingr/hako/internal/archival/store"
)
// LinkListRequest contains request parameters for listing links from the API
type LinkListRequest struct {
UserID string
Limit int
Offset int
CategoryID string
SearchQuery string
}
// Defaults sets sensible defaults for LinkListRequest
func (r *LinkListRequest) Defaults() {
if r.Limit == 0 {
r.Limit = archivalStore.DefaultListLimit
}
if r.Offset < 0 {
r.Offset = 0
}
}
// IsValid validates LinkListRequest
func (r *LinkListRequest) IsValid() error {
if r.UserID == "" {
return fmt.Errorf("userID is required")
}
if r.Limit < archivalStore.MinListLimit || r.Limit > archivalStore.MaxListLimit {
return fmt.Errorf("limit must be between %d and %d, got %d", archivalStore.MinListLimit, archivalStore.MaxListLimit, r.Limit)
}
if r.Offset < 0 {
return fmt.Errorf("offset must be >= 0, got %d", r.Offset)
}
return nil
}
// FromURLValues parses query parameters from url.Values into the request struct
func (r *LinkListRequest) FromURLValues(values url.Values) error {
// Parse limit
if limitStr := values.Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return fmt.Errorf("invalid limit parameter: %w", err)
}
r.Limit = limit
}
// Parse offset
if offsetStr := values.Get("offset"); offsetStr != "" {
offset, err := strconv.Atoi(offsetStr)
if err != nil {
return fmt.Errorf("invalid offset parameter: %w", err)
}
r.Offset = offset
}
// Parse category_id
if categoryID := values.Get("category_id"); categoryID != "" {
r.CategoryID = categoryID
}
// Parse search query (supports both 'q' and 'search' parameters)
// Only accept queries with at least 3 characters
if searchQuery := values.Get("q"); searchQuery != "" && len(searchQuery) >= 3 {
r.SearchQuery = searchQuery
} else if searchQuery := values.Get("search"); searchQuery != "" && len(searchQuery) >= 3 {
r.SearchQuery = searchQuery
}
return nil
}
// ToLinkListOptions converts LinkListRequest to archivalStore.LinkListOptions
func (r *LinkListRequest) ToLinkListOptions() archivalStore.LinkListOptions {
return archivalStore.LinkListOptions{
UserID: r.UserID,
Limit: r.Limit,
Offset: r.Offset,
CategoryID: r.CategoryID,
SearchQuery: r.SearchQuery,
}
}
// ToLinkCountOptions converts LinkListRequest to archivalStore.LinkCountOptions
func (r *LinkListRequest) ToLinkCountOptions() archivalStore.LinkCountOptions {
return archivalStore.LinkCountOptions{
UserID: r.UserID,
CategoryID: r.CategoryID,
SearchQuery: r.SearchQuery,
}
}