mirror of
https://github.com/gabehf/Koito.git
synced 2026-03-07 13:38:15 -08:00
fix: respect client timezone for requests (#119)
* maybe fixed for total listen activity * maybe actually fixed now * fix unset location panics
This commit is contained in:
parent
2925425750
commit
f48dd6c039
13 changed files with 368 additions and 343 deletions
|
|
@ -4,6 +4,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gabehf/koito/internal/db"
|
||||
"github.com/gabehf/koito/internal/logger"
|
||||
|
|
@ -19,7 +20,7 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
|
||||
rangeStr := r.URL.Query().Get("range")
|
||||
_range, err := strconv.Atoi(rangeStr)
|
||||
if err != nil {
|
||||
if err != nil && rangeStr != "" {
|
||||
l.Debug().AnErr("error", err).Msg("GetListenActivityHandler: Invalid range parameter")
|
||||
utils.WriteError(w, "invalid range parameter", http.StatusBadRequest)
|
||||
return
|
||||
|
|
@ -27,7 +28,7 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
|
||||
monthStr := r.URL.Query().Get("month")
|
||||
month, err := strconv.Atoi(monthStr)
|
||||
if err != nil {
|
||||
if err != nil && monthStr != "" {
|
||||
l.Debug().AnErr("error", err).Msg("GetListenActivityHandler: Invalid month parameter")
|
||||
utils.WriteError(w, "invalid month parameter", http.StatusBadRequest)
|
||||
return
|
||||
|
|
@ -35,7 +36,7 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
|
||||
yearStr := r.URL.Query().Get("year")
|
||||
year, err := strconv.Atoi(yearStr)
|
||||
if err != nil {
|
||||
if err != nil && yearStr != "" {
|
||||
l.Debug().AnErr("error", err).Msg("GetListenActivityHandler: Invalid year parameter")
|
||||
utils.WriteError(w, "invalid year parameter", http.StatusBadRequest)
|
||||
return
|
||||
|
|
@ -43,7 +44,7 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
|
||||
artistIdStr := r.URL.Query().Get("artist_id")
|
||||
artistId, err := strconv.Atoi(artistIdStr)
|
||||
if err != nil {
|
||||
if err != nil && artistIdStr != "" {
|
||||
l.Debug().AnErr("error", err).Msg("GetListenActivityHandler: Invalid artist ID parameter")
|
||||
utils.WriteError(w, "invalid artist ID parameter", http.StatusBadRequest)
|
||||
return
|
||||
|
|
@ -51,7 +52,7 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
|
||||
albumIdStr := r.URL.Query().Get("album_id")
|
||||
albumId, err := strconv.Atoi(albumIdStr)
|
||||
if err != nil {
|
||||
if err != nil && albumIdStr != "" {
|
||||
l.Debug().AnErr("error", err).Msg("GetListenActivityHandler: Invalid album ID parameter")
|
||||
utils.WriteError(w, "invalid album ID parameter", http.StatusBadRequest)
|
||||
return
|
||||
|
|
@ -59,7 +60,7 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
|
||||
trackIdStr := r.URL.Query().Get("track_id")
|
||||
trackId, err := strconv.Atoi(trackIdStr)
|
||||
if err != nil {
|
||||
if err != nil && trackIdStr != "" {
|
||||
l.Debug().AnErr("error", err).Msg("GetListenActivityHandler: Invalid track ID parameter")
|
||||
utils.WriteError(w, "invalid track ID parameter", http.StatusBadRequest)
|
||||
return
|
||||
|
|
@ -85,11 +86,17 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
Range: _range,
|
||||
Month: month,
|
||||
Year: year,
|
||||
Timezone: parseTZ(r),
|
||||
AlbumID: int32(albumId),
|
||||
ArtistID: int32(artistId),
|
||||
TrackID: int32(trackId),
|
||||
}
|
||||
|
||||
if strings.ToLower(opts.Timezone.String()) == "local" {
|
||||
opts.Timezone, _ = time.LoadLocation("UTC")
|
||||
l.Warn().Msg("GetListenActivityHandler: Timezone is unset, using UTC")
|
||||
}
|
||||
|
||||
l.Debug().Msgf("GetListenActivityHandler: Retrieving listen activity with options: %+v", opts)
|
||||
|
||||
activity, err := store.GetListenActivity(ctx, opts)
|
||||
|
|
@ -99,7 +106,51 @@ func GetListenActivityHandler(store db.DB) func(w http.ResponseWriter, r *http.R
|
|||
return
|
||||
}
|
||||
|
||||
activity = fillMissingActivity(activity, opts)
|
||||
|
||||
l.Debug().Msg("GetListenActivityHandler: Successfully retrieved listen activity")
|
||||
utils.WriteJSON(w, http.StatusOK, activity)
|
||||
}
|
||||
}
|
||||
|
||||
// ngl i hate this
|
||||
func fillMissingActivity(
|
||||
items []db.ListenActivityItem,
|
||||
opts db.ListenActivityOpts,
|
||||
) []db.ListenActivityItem {
|
||||
from, to := db.ListenActivityOptsToTimes(opts)
|
||||
|
||||
existing := make(map[string]int64, len(items))
|
||||
for _, item := range items {
|
||||
existing[item.Start.Format("2006-01-02")] = item.Listens
|
||||
}
|
||||
|
||||
var result []db.ListenActivityItem
|
||||
|
||||
for t := from; t.Before(to); t = addStep(t, opts.Step) {
|
||||
listens := int64(0)
|
||||
if v, ok := existing[t.Format("2006-01-02")]; ok {
|
||||
listens = v
|
||||
}
|
||||
|
||||
result = append(result, db.ListenActivityItem{
|
||||
Start: t,
|
||||
Listens: int64(listens),
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func addStep(t time.Time, step db.StepInterval) time.Time {
|
||||
switch step {
|
||||
case db.StepDay:
|
||||
return t.AddDate(0, 0, 1)
|
||||
case db.StepWeek:
|
||||
return t.AddDate(0, 0, 7)
|
||||
case db.StepMonth:
|
||||
return t.AddDate(0, 1, 0)
|
||||
default:
|
||||
return t.AddDate(0, 0, 1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gabehf/koito/internal/db"
|
||||
"github.com/gabehf/koito/internal/logger"
|
||||
|
|
@ -100,5 +101,23 @@ func TimeframeFromRequest(r *http.Request) db.Timeframe {
|
|||
Week: parseInt("week"),
|
||||
FromUnix: parseInt64("from"),
|
||||
ToUnix: parseInt64("to"),
|
||||
Timezone: parseTZ(r),
|
||||
}
|
||||
}
|
||||
|
||||
func parseTZ(r *http.Request) *time.Location {
|
||||
|
||||
if tz := r.URL.Query().Get("tz"); tz != "" {
|
||||
if loc, err := time.LoadLocation(tz); err == nil {
|
||||
return loc
|
||||
}
|
||||
}
|
||||
|
||||
if c, err := r.Cookie("tz"); err == nil {
|
||||
if loc, err := time.LoadLocation(c.Value); err == nil {
|
||||
return loc
|
||||
}
|
||||
}
|
||||
|
||||
return time.Now().Location()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue