Ctrl K
ComunidadGuías…

internal/issues/page.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package issues

import (
	"encoding/base64"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/sophotechlabs/spinoza/internal/api"
)

const Shown = 50

const (
	ByWorst  = "worst"
	ByNewest = "newest"
	ByOldest = "oldest"
)

func OrderOf(asked string) string {
	if asked == ByNewest || asked == ByOldest {
		return asked
	}
	return ByWorst
}

const (
	foldCeiling = 999999999
	timeCeiling = 9999999999
)

func issueKey(row api.Issue, order string) string {
	if order == ByNewest {
		return strings.Join([]string{
			countDown(secondsOf(seenAt(row.Since)), timeCeiling),
			row.Cluster,
			row.ID,
		}, "\x00")
	}
	if order == ByOldest {
		return strings.Join([]string{
			countUp(secondsOf(seenAt(row.Since)), timeCeiling),
			row.Cluster,
			row.ID,
		}, "\x00")
	}
	return strings.Join([]string{
		strconv.Itoa(severityFatal - severityRank(row.Severity)),
		countDown(row.Folded, foldCeiling),
		countDown(secondsOf(seenAt(row.Since)), timeCeiling),
		row.Cluster,
		row.ID,
	}, "\x00")
}

func countUp(value, ceiling int) string {
	if value < 0 {
		value = 0
	}
	if value > ceiling {
		value = ceiling
	}
	width := len(strconv.Itoa(ceiling))
	return fmt.Sprintf("%0*d", width, value)
}

func countDown(value, ceiling int) string {
	if value < 0 {
		value = 0
	}
	if value > ceiling {
		value = ceiling
	}
	width := len(strconv.Itoa(ceiling))
	return fmt.Sprintf("%0*d", width, ceiling-value)
}

func secondsOf(at time.Time) int {
	if at.IsZero() {
		return 0
	}
	return int(at.Unix())
}

var (
	ErrInvalidCursor = errors.New("that page marker is invalid")
	ErrCursorOrder   = errors.New("that page marker belongs to a different sort order")
)

func EncodeCursor(key, order string) string {
	if key == "" {
		return ""
	}
	return base64.RawURLEncoding.EncodeToString([]byte(order + "\x00" + key))
}

func DecodeCursor(cursor, order string) (string, error) {
	if cursor == "" {
		return "", nil
	}
	raw, err := base64.RawURLEncoding.DecodeString(cursor)
	if err != nil {
		return "", ErrInvalidCursor
	}
	minted, key, found := strings.Cut(string(raw), "\x00")
	if !found || minted == "" || key == "" {
		return "", ErrInvalidCursor
	}
	if minted != order {
		return "", ErrCursorOrder
	}
	return key, nil
}

func Page(rows []api.Issue, after string, limit int, order string) ([]api.Issue, string) {
	limit = PageSize(limit)
	out := make([]api.Issue, 0, min(limit, len(rows)))
	last := ""
	for _, row := range rows {
		key := issueKey(row, order)
		if key <= after {
			continue
		}
		if len(out) == limit {
			return out, EncodeCursor(last, order)
		}
		out = append(out, row)
		last = key
	}
	return out, ""
}

func PageSize(shown int) int {
	if shown <= 0 {
		return Shown
	}
	return shown
}