mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-16 13:04:34 +00:00
add the forecast endpoint
This commit is contained in:
@@ -3,76 +3,150 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/micro/micro/v3/service/logger"
|
||||
"github.com/micro/micro/v3/service/config"
|
||||
"github.com/micro/micro/v3/service/errors"
|
||||
"github.com/micro/micro/v3/service/logger"
|
||||
pb "github.com/micro/services/weather/proto"
|
||||
)
|
||||
|
||||
type Weather struct{
|
||||
type Weather struct {
|
||||
Api string
|
||||
Key string
|
||||
}
|
||||
|
||||
func New() *Weather {
|
||||
// TODO: look for "weather.provider" to determine the handler
|
||||
v, err := config.Get("weatherapi.api")
|
||||
if err != nil {
|
||||
logger.Fatalf("weatherapi.api config not found: %v", err)
|
||||
}
|
||||
api := v.String("")
|
||||
if len(api) == 0 {
|
||||
logger.Fatal("weatherapi.api config not found")
|
||||
}
|
||||
v, err = config.Get("weatherapi.key")
|
||||
if err != nil {
|
||||
logger.Fatalf("weatherapi.key config not found: %v", err)
|
||||
}
|
||||
key := v.String("")
|
||||
if len(key) == 0 {
|
||||
logger.Fatal("weatherapi.key config not found")
|
||||
}
|
||||
// TODO: look for "weather.provider" to determine the handler
|
||||
v, err := config.Get("weatherapi.api")
|
||||
if err != nil {
|
||||
logger.Fatalf("weatherapi.api config not found: %v", err)
|
||||
}
|
||||
api := v.String("")
|
||||
if len(api) == 0 {
|
||||
logger.Fatal("weatherapi.api config not found")
|
||||
}
|
||||
v, err = config.Get("weatherapi.key")
|
||||
if err != nil {
|
||||
logger.Fatalf("weatherapi.key config not found: %v", err)
|
||||
}
|
||||
key := v.String("")
|
||||
if len(key) == 0 {
|
||||
logger.Fatal("weatherapi.key config not found")
|
||||
}
|
||||
|
||||
return &Weather{
|
||||
Api: api,
|
||||
Key: key,
|
||||
}
|
||||
return &Weather{
|
||||
Api: api,
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Weather) Forecast(ctx context.Context, req *pb.ForecastRequest, rsp *pb.ForecastResponse) error {
|
||||
if len(req.Location) <= 0 {
|
||||
return errors.BadRequest("weather.forecast", "invalid location")
|
||||
}
|
||||
if req.Days <= 0 || req.Days > 10 {
|
||||
req.Days = 1
|
||||
}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("key", w.Key)
|
||||
vals.Set("aqi", "no")
|
||||
vals.Set("q", req.Location)
|
||||
vals.Set("days", fmt.Sprintf("%d", req.Days))
|
||||
|
||||
resp, err := http.Get(w.Api + "forecast.json?" + vals.Encode())
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get weather forecast: %v\n", err)
|
||||
return errors.InternalServerError("weather.forecast", "failed to get weather forecast")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
logger.Errorf("Failed to get weather forecast (non 200): %d %v\n", resp.StatusCode, string(b))
|
||||
return errors.InternalServerError("weather.forecast", "failed to get weather forecast")
|
||||
}
|
||||
|
||||
var respBody map[string]interface{}
|
||||
|
||||
if err := json.Unmarshal(b, &respBody); err != nil {
|
||||
logger.Errorf("Failed to unmarshal forecast: %v\n", err)
|
||||
return errors.InternalServerError("weather.forecast", "failed to get forecast")
|
||||
}
|
||||
|
||||
forecast := respBody["forecast"].(map[string]interface{})
|
||||
|
||||
for _, v := range forecast["forecastday"].([]interface{}) {
|
||||
fc := v.(map[string]interface{})
|
||||
|
||||
day := fc["day"].(map[string]interface{})
|
||||
|
||||
willrain := false
|
||||
chancerain := int32(0)
|
||||
if v := day["daily_will_it_rain"].(float64); v == 1.0 {
|
||||
willrain = true
|
||||
}
|
||||
if v, _ := strconv.Atoi(day["daily_chance_of_rain"].(string)); v > 0 {
|
||||
chancerain = int32(v)
|
||||
}
|
||||
|
||||
// set the daily forecast
|
||||
rsp.Forecast = append(rsp.Forecast, &pb.Forecast{
|
||||
Date: fc["date"].(string),
|
||||
MaxTempC: day["maxtemp_c"].(float64),
|
||||
MinTempC: day["mintemp_c"].(float64),
|
||||
AvgTempC: day["avgtemp_c"].(float64),
|
||||
MaxTempF: day["maxtemp_f"].(float64),
|
||||
MinTempF: day["mintemp_f"].(float64),
|
||||
AvgTempF: day["avgtemp_f"].(float64),
|
||||
WillItRain: willrain,
|
||||
ChanceOfRain: chancerain,
|
||||
Condition: day["condition"].(map[string]interface{})["text"].(string),
|
||||
IconUrl: day["condition"].(map[string]interface{})["icon"].(string),
|
||||
Sunrise: fc["astro"].(map[string]interface{})["sunrise"].(string),
|
||||
Sunset: fc["astro"].(map[string]interface{})["sunset"].(string),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Weather) Now(ctx context.Context, req *pb.NowRequest, rsp *pb.NowResponse) error {
|
||||
if len(req.Location) <= 0 {
|
||||
return errors.BadRequest("weather.current", "invalid location")
|
||||
}
|
||||
if len(req.Location) <= 0 {
|
||||
return errors.BadRequest("weather.current", "invalid location")
|
||||
}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("key", w.Key)
|
||||
vals.Set("aqi", "no")
|
||||
vals.Set("q", req.Location)
|
||||
|
||||
resp, err := http.Get(w.Api + "current.json?" + vals.Encode())
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get current weather: %v\n", err)
|
||||
return errors.InternalServerError("weather.current", "failed to get current weather")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
resp, err := http.Get(w.Api + "current.json?" + vals.Encode())
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get current weather: %v\n", err)
|
||||
return errors.InternalServerError("weather.current", "failed to get current weather")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
logger.Errorf("Failed to get current weather (non 200): %d %v\n", resp.StatusCode, string(b))
|
||||
return errors.InternalServerError("weather.current", "failed to get current weather")
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
logger.Errorf("Failed to get current weather (non 200): %d %v\n", resp.StatusCode, string(b))
|
||||
return errors.InternalServerError("weather.current", "failed to get current weather")
|
||||
}
|
||||
|
||||
var respBody map[string]interface{}
|
||||
var respBody map[string]interface{}
|
||||
|
||||
if err := json.Unmarshal(b, &respBody); err != nil {
|
||||
logger.Errorf("Failed to unmarshal current: %v\n", err)
|
||||
return errors.InternalServerError("weather.current", "failed to get current")
|
||||
}
|
||||
if err := json.Unmarshal(b, &respBody); err != nil {
|
||||
logger.Errorf("Failed to unmarshal current: %v\n", err)
|
||||
return errors.InternalServerError("weather.current", "failed to get current")
|
||||
}
|
||||
|
||||
location := respBody["location"].(map[string]interface{})
|
||||
current := respBody["current"].(map[string]interface{})
|
||||
@@ -106,4 +180,3 @@ func (w *Weather) Now(ctx context.Context, req *pb.NowRequest, rsp *pb.NowRespon
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user