115 lines
2.6 KiB
Go
115 lines
2.6 KiB
Go
package nws
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"time"
|
|
|
|
"gitea.maximumdirect.net/ejr/feedkit/config"
|
|
"gitea.maximumdirect.net/ejr/feedkit/event"
|
|
fksources "gitea.maximumdirect.net/ejr/feedkit/sources"
|
|
nwscommon "gitea.maximumdirect.net/ejr/weatherfeeder/internal/providers/nws"
|
|
)
|
|
|
|
const nwsForecastAccept = "application/geo+json, application/json"
|
|
|
|
type forecastSource struct {
|
|
http *fksources.HTTPSource
|
|
rawSchema string
|
|
}
|
|
|
|
type forecastMeta struct {
|
|
Properties struct {
|
|
GeneratedAt string `json:"generatedAt"`
|
|
UpdateTime string `json:"updateTime"`
|
|
Updated string `json:"updated"`
|
|
} `json:"properties"`
|
|
|
|
ParsedGeneratedAt time.Time `json:"-"`
|
|
ParsedUpdateTime time.Time `json:"-"`
|
|
}
|
|
|
|
func newForecastSource(cfg config.SourceConfig, driver, rawSchema string) (*forecastSource, error) {
|
|
hs, err := fksources.NewHTTPSource(driver, cfg, nwsForecastAccept)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &forecastSource{
|
|
http: hs,
|
|
rawSchema: rawSchema,
|
|
}, nil
|
|
}
|
|
|
|
func (s *forecastSource) Name() string { return s.http.Name }
|
|
|
|
func (s *forecastSource) Kind() event.Kind { return event.Kind("forecast") }
|
|
|
|
func (s *forecastSource) Poll(ctx context.Context) ([]event.Event, error) {
|
|
raw, meta, changed, err := s.fetchRaw(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !changed {
|
|
return nil, nil
|
|
}
|
|
|
|
var effectiveAt *time.Time
|
|
switch {
|
|
case !meta.ParsedGeneratedAt.IsZero():
|
|
t := meta.ParsedGeneratedAt.UTC()
|
|
effectiveAt = &t
|
|
case !meta.ParsedUpdateTime.IsZero():
|
|
t := meta.ParsedUpdateTime.UTC()
|
|
effectiveAt = &t
|
|
}
|
|
|
|
emittedAt := time.Now().UTC()
|
|
eventID := fksources.DefaultEventID("", s.http.Name, effectiveAt, emittedAt)
|
|
|
|
return fksources.SingleEvent(
|
|
s.Kind(),
|
|
s.http.Name,
|
|
s.rawSchema,
|
|
eventID,
|
|
emittedAt,
|
|
effectiveAt,
|
|
raw,
|
|
)
|
|
}
|
|
|
|
func (s *forecastSource) fetchRaw(ctx context.Context) (json.RawMessage, forecastMeta, bool, error) {
|
|
raw, changed, err := s.http.FetchJSONIfChanged(ctx)
|
|
if err != nil {
|
|
return nil, forecastMeta{}, false, err
|
|
}
|
|
if !changed {
|
|
return nil, forecastMeta{}, false, nil
|
|
}
|
|
|
|
var meta forecastMeta
|
|
if err := json.Unmarshal(raw, &meta); err != nil {
|
|
return raw, forecastMeta{}, true, nil
|
|
}
|
|
|
|
genStr := strings.TrimSpace(meta.Properties.GeneratedAt)
|
|
if genStr != "" {
|
|
if t, err := nwscommon.ParseTime(genStr); err == nil {
|
|
meta.ParsedGeneratedAt = t.UTC()
|
|
}
|
|
}
|
|
|
|
updStr := strings.TrimSpace(meta.Properties.UpdateTime)
|
|
if updStr == "" {
|
|
updStr = strings.TrimSpace(meta.Properties.Updated)
|
|
}
|
|
if updStr != "" {
|
|
if t, err := nwscommon.ParseTime(updStr); err == nil {
|
|
meta.ParsedUpdateTime = t.UTC()
|
|
}
|
|
}
|
|
|
|
return raw, meta, true, nil
|
|
}
|