Skip to content

Commit

Permalink
Added weather forecast
Browse files Browse the repository at this point in the history
  • Loading branch information
djthorpe committed May 26, 2024
1 parent 7d6d4fd commit 51f3c6b
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 11 deletions.
28 changes: 28 additions & 0 deletions pkg/weatherapi/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,31 @@ func (c *Client) Current(q string) (Weather, error) {
return response, nil
}
}

// Forecast weather
func (c *Client) Forecast(q string, opts ...Opt) (Forecast, error) {
var request options
var response Forecast

// Set defaults
request.Values = url.Values{}
response.Query = q

// Set options
for _, opt := range opts {
if err := opt(&request); err != nil {
return Forecast{}, err
}
}

// Set query parameters
request.Set("key", c.key)
request.Set("q", q)

// Request -> Response
if err := c.Do(nil, &response, client.OptPath("forecast.json"), client.OptQuery(request.Values)); err != nil {
return Forecast{}, err
} else {
return response, nil
}
}
12 changes: 12 additions & 0 deletions pkg/weatherapi/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ func Test_client_002(t *testing.T) {
t.Log(weather)
}

func Test_client_003(t *testing.T) {
assert := assert.New(t)
client, err := weatherapi.New(GetApiKey(t), opts.OptTrace(os.Stderr, true))
assert.NoError(err)

forecast, err := client.Forecast("Berlin, Germany", weatherapi.OptDays(2))
if !assert.NoError(err) {
t.SkipNow()
}
t.Log(forecast)
}

///////////////////////////////////////////////////////////////////////////////
// ENVIRONMENT

Expand Down
47 changes: 47 additions & 0 deletions pkg/weatherapi/opt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package weatherapi

import (
"fmt"
"net/url"

// Namespace imports
. "github.com/djthorpe/go-errors"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

type options struct {
url.Values
}

type Opt func(*options) error

////////////////////////////////////////////////////////////////////////////////

// Number of days of weather forecast. Value ranges from 1 to 10
func OptDays(days int) Opt {
return func(o *options) error {
if days < 1 {
return ErrBadParameter.With("OptDays")
}
o.Set("days", fmt.Sprint(days))
return nil
}
}

// Get air quality data
func OptAirQuality() Opt {
return func(o *options) error {
o.Set("aqi", "yes")
return nil
}
}

// Get weather alert data
func OptAlerts() Opt {
return func(o *options) error {
o.Set("alerts", "yes")
return nil
}
}
93 changes: 82 additions & 11 deletions pkg/weatherapi/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,23 @@ type Location struct {
Localtime Time `json:"localtime,omitempty"`
}

type Current struct {
LastUpdatedEpoch int64 `json:"last_updated_epoch"`
LastUpdated Time `json:"last_updated,omitempty"`
TempC float64 `json:"temp_c"`
TempF float64 `json:"temp_f"`
IsDay int `json:"is_day"` // Whether to show day condition icon (1) or night icon (0)
Condition struct {
type CurrentConditions struct {
LastUpdatedEpoch int64 `json:"last_updated_epoch"`
LastUpdated Time `json:"last_updated,omitempty"`
Conditions
}

type ForecastConditions struct {
TimeEpoch int64 `json:"time_epoch"`
Time Time `json:"time,omitempty"`
Conditions
}

type Conditions struct {
TempC float64 `json:"temp_c"`
TempF float64 `json:"temp_f"`
IsDay int `json:"is_day"` // Whether to show day condition icon (1) or night icon (0)
Condition struct {
Text string `json:"text"`
Icon string `json:"icon"`
Code int `json:"code"`
Expand All @@ -50,11 +60,67 @@ type Current struct {
GustKph float64 `json:"gust_kph"`
}

type Day struct {
MaxTempC float64 `json:"maxtemp_c"`
MaxTempF float64 `json:"maxtemp_f"`
MinTempC float64 `json:"mintemp_c"`
MinTempF float64 `json:"mintemp_f"`
AvgTempC float64 `json:"avgtemp_c"`
AvgTempF float64 `json:"avgtemp_f"`
MaxWindMph float64 `json:"maxwind_mph"`
MaxWindKph float64 `json:"maxwind_kph"`
TotalPrecipMm float64 `json:"totalprecip_mm"`
TotalPrecipIn float64 `json:"totalprecip_in"`
TotalSnowCm float64 `json:"totalsnow_cm"`
AvgVisKm float64 `json:"avgvis_km"`
AvgVisMiles float64 `json:"avgvis_miles"`
AvgHumidity int `json:"avghumidity"`
WillItRain int `json:"daily_will_it_rain"`
WillItSnow int `json:"daily_will_it_snow"`
ChanceOfRainPercent int `json:"daily_chance_of_rain"`
ChanceOfSnowPercent int `json:"daily_chance_of_snow"`
Uv float32 `json:"uv"`
Condition struct {
Text string `json:"text"`
Icon string `json:"icon"`
Code int `json:"code"`
} `json:"condition"`
}

type ForecastDay struct {
Date string `json:"date"`
DateEpoch int64 `json:"date_epoch"`
Day *Day `json:"day"`
Hour []*ForecastConditions `json:"hour"`
Astro *Astro `json:"astro"`
}

type Astro struct {
SunRise string `json:"sunrise"`
SunSet string `json:"sunset"`
MoonRise string `json:"moonrise"`
MoonSet string `json:"moonset"`
MoonPhase string `json:"moon_phase"`
MoonIllumination int `json:"moon_illumination"`
IsMoonUp int `json:"is_moon_up"`
IsSunUp int `json:"is_sun_up"`
}

type Weather struct {
Id int `json:"custom_id,omitempty"`
Query string `json:"q,omitempty"`
Location *Location `json:"location,omitempty"`
Current *Current `json:"current,omitempty"`
Id int `json:"custom_id,omitempty"`
Query string `json:"q,omitempty"`
Location *Location `json:"location,omitempty"`
Current *CurrentConditions `json:"current,omitempty"`
}

type Forecast struct {
Id int `json:"custom_id,omitempty"`
Query string `json:"q,omitempty"`
Location *Location `json:"location,omitempty"`
Current *CurrentConditions `json:"current,omitempty"`
Forecast struct {
Day []*ForecastDay `json:"forecastday"`
} `json:"forecast,omitempty"`
}

type Time struct {
Expand All @@ -69,6 +135,11 @@ func (w Weather) String() string {
return string(data)
}

func (f Forecast) String() string {
data, _ := json.MarshalIndent(f, "", " ")
return string(data)
}

///////////////////////////////////////////////////////////////////////////////
// MARSHAL TIME

Expand Down

0 comments on commit 51f3c6b

Please sign in to comment.