From 09d1124794a25efbbcf77c099e6648cf1ac33c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Thu, 12 May 2022 00:59:42 +0200 Subject: [PATCH] fix: work around invalid all_time_since_today data schema to fix failing import (resolve #370) --- services/imports/wakatime.go | 6 ++++-- utils/json.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 utils/json.go diff --git a/services/imports/wakatime.go b/services/imports/wakatime.go index d210161..8b1e00e 100644 --- a/services/imports/wakatime.go +++ b/services/imports/wakatime.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "github.com/duke-git/lancet/v2/datetime" + "github.com/muety/wakapi/utils" "net/http" "time" @@ -154,8 +155,9 @@ func (w *WakatimeHeartbeatImporter) fetchRange(baseUrl string) (time.Time, time. return notime, notime, err } - var allTimeData wakatime.AllTimeViewModel - if err := json.NewDecoder(res.Body).Decode(&allTimeData); err != nil { + // see https://github.com/muety/wakapi/issues/370 + allTimeData, err := utils.ParseJsonDropKeys[wakatime.AllTimeViewModel](res.Body, "text") + if err != nil { return notime, notime, err } diff --git a/utils/json.go b/utils/json.go new file mode 100644 index 0000000..1aa6d0a --- /dev/null +++ b/utils/json.go @@ -0,0 +1,34 @@ +package utils + +import ( + "bytes" + "encoding/json" + "io" +) + +// ParseJsonDropKeys parses the given JSON input object to an object of given type, while omitting the specified keys on the way. +// This can be useful if parsing would normally fail due to ambiguous typing of some key, but that key is not of interest and can be dropped to avoid parse errors. +// Dropping keys only works on top level of the object. +func ParseJsonDropKeys[T any](r io.Reader, dropKeys ...string) (T, error) { + var ( + result T + resultTmp map[string]interface{} + resultTmpBuf = new(bytes.Buffer) + ) + if err := json.NewDecoder(r).Decode(&resultTmp); err != nil { + return result, err + } + + for _, k := range dropKeys { + delete(resultTmp, k) + } + + if err := json.NewEncoder(resultTmpBuf).Encode(resultTmp); err != nil { + return result, err + } + if err := json.NewDecoder(resultTmpBuf).Decode(&result); err != nil { + return result, err + } + + return result, nil +}