65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"reanimator/internal/repository/timeline"
|
|
)
|
|
|
|
func writeTimelineResponse(w http.ResponseWriter, r *http.Request, repo *timeline.EventRepository, subjectType string, subjectID int64) {
|
|
limit := 50
|
|
if raw := r.URL.Query().Get("limit"); raw != "" {
|
|
if parsed, err := strconv.Atoi(raw); err == nil {
|
|
limit = parsed
|
|
} else {
|
|
writeError(w, http.StatusBadRequest, "invalid limit")
|
|
return
|
|
}
|
|
}
|
|
|
|
var cursor *timeline.Cursor
|
|
if raw := r.URL.Query().Get("cursor"); raw != "" {
|
|
decoded, err := timeline.DecodeCursor(raw)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid cursor")
|
|
return
|
|
}
|
|
cursor = &decoded
|
|
}
|
|
|
|
items, next, err := repo.List(r.Context(), subjectType, subjectID, limit, cursor)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "list timeline failed")
|
|
return
|
|
}
|
|
|
|
var nextCursor *string
|
|
if next != nil {
|
|
value := timeline.EncodeCursor(*next)
|
|
nextCursor = &value
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
"items": items,
|
|
"next_cursor": nextCursor,
|
|
})
|
|
}
|
|
|
|
func parseTimelineID(path, prefix string) int64 {
|
|
if !strings.HasPrefix(path, prefix) || !strings.HasSuffix(path, "/timeline") {
|
|
return 0
|
|
}
|
|
trimmed := strings.TrimPrefix(path, prefix)
|
|
trimmed = strings.TrimSuffix(trimmed, "/timeline")
|
|
if trimmed == "" || strings.Contains(trimmed, "/") {
|
|
return 0
|
|
}
|
|
id, err := strconv.ParseInt(trimmed, 10, 64)
|
|
if err != nil || id <= 0 {
|
|
return 0
|
|
}
|
|
return id
|
|
}
|