Add convective outlook HTTP routes

This commit is contained in:
2026-06-11 15:38:19 +00:00
parent 63c8f33a2a
commit d6734d5ffc
6 changed files with 419 additions and 0 deletions

View File

@@ -8,7 +8,9 @@ import (
"time"
"gitea.maximumdirect.net/ejr/feedapi/bind"
apierrors "gitea.maximumdirect.net/ejr/feedapi/errors"
"gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/inbound/httpapi/presenter"
"gitea.maximumdirect.net/ejr/weatherapi/internal/app"
)
type queryRequest struct {
@@ -26,6 +28,12 @@ type timezoneQueryRequest struct {
Timezone *time.Location
}
type outlookQueryRequest struct {
Units presenter.Units
Timezone *time.Location
Filter app.OutlookFilter
}
func bindQuery(r *http.Request) (queryRequest, error) {
normalizeCommonQueryValue(r, "units")
normalizeCommonQueryValue(r, "format")
@@ -135,3 +143,91 @@ func bindPrecisionQueryInternal(r *http.Request, allowTimezone bool) (precisionQ
Timezone: tz,
}, nil
}
func bindOutlookQuery(r *http.Request) (outlookQueryRequest, error) {
return bindOutlookQueryInternal(r, true)
}
func bindOutlookLocationQuery(r *http.Request) (outlookQueryRequest, error) {
return bindOutlookQueryInternal(r, false)
}
func bindOutlookQueryInternal(r *http.Request, allowContainsLocation bool) (outlookQueryRequest, error) {
normalizeCommonQueryValue(r, "units")
normalizeCommonQueryValue(r, "format")
normalizeCommonQueryValue(r, "outlookType")
allowedExtra := []string{"tz", "TZ", "day", "outlookType"}
if allowContainsLocation {
allowedExtra = append(allowedExtra, "containsLocation")
}
common, err := bind.CommonQueryParams(r, bind.QueryPolicy{
AllowUnits: true,
AllowFormat: true,
DefaultUnits: string(presenter.UnitsMetric),
RejectUnknown: true,
}, allowedExtra...)
if err != nil {
return outlookQueryRequest{}, err
}
units := presenter.Units(strings.ToLower(strings.TrimSpace(common.Units)))
if units == "" {
units = presenter.UnitsMetric
}
tz, err := parseTimezoneQuery(r)
if err != nil {
return outlookQueryRequest{}, err
}
filter, err := bindOutlookFilter(r, allowContainsLocation)
if err != nil {
return outlookQueryRequest{}, err
}
return outlookQueryRequest{
Units: units,
Timezone: tz,
Filter: filter,
}, nil
}
func bindOutlookFilter(r *http.Request, allowContainsLocation bool) (app.OutlookFilter, error) {
var filter app.OutlookFilter
if strings.TrimSpace(r.URL.Query().Get("day")) != "" {
day, err := bind.OptionalInt(r, "day", 0)
if err != nil {
return app.OutlookFilter{}, err
}
if day < 1 || day > 3 {
return app.OutlookFilter{}, apierrors.InvalidParameter("day must be one of [1, 2, 3]")
}
filter.Day = &day
}
outlookType := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("outlookType")))
if outlookType != "" {
switch outlookType {
case "categorical", "tornado", "hail", "wind":
filter.OutlookType = outlookType
default:
return app.OutlookFilter{}, apierrors.InvalidParameter("outlookType must be one of [categorical, tornado, hail, wind]")
}
}
if strings.TrimSpace(r.URL.Query().Get("containsLocation")) != "" {
if !allowContainsLocation {
return app.OutlookFilter{}, apierrors.InvalidParameter("containsLocation is not allowed on this endpoint")
}
containsLocation, err := bind.OptionalBool(r, "containsLocation", false)
if err != nil {
return app.OutlookFilter{}, err
}
filter.ContainsLocation = &containsLocation
}
return filter, nil
}