func (c *wwoConfig) Fetch(loc string, numdays int) iface.Data { var params []string var resp wwoResponse var ret iface.Data coordChan := make(chan *iface.LatLon) if len(c.apiKey) == 0 { log.Fatal("No API key specified. Setup instructions are in the README.") } params = append(params, "key="+c.apiKey) if len(loc) > 0 { params = append(params, "q="+url.QueryEscape(loc)) } params = append(params, "format=json") params = append(params, "num_of_days="+strconv.Itoa(numdays)) params = append(params, "tp=3") go c.getCoordinatesFromAPI(params, coordChan) if c.language != "" { params = append(params, "lang="+c.language) } requri := wwoWuri + strings.Join(params, "&") res, err := http.Get(requri) if err != nil { log.Fatal("Unable to get weather data: ", err) } else if res.StatusCode != 200 { log.Fatal("Unable to get weather data: http status ", res.StatusCode) } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatal(err) } if c.debug { log.Println("Weather request:", requri) log.Println("Weather response:", string(body)) } if c.language == "" { if err = json.Unmarshal(body, &resp); err != nil { log.Println(err) } } else { if err = wwoUnmarshalLang(body, &resp, c.language); err != nil { log.Println(err) } } if resp.Data.Req == nil || len(resp.Data.Req) < 1 { if resp.Data.Err != nil && len(resp.Data.Err) >= 1 { log.Fatal(resp.Data.Err[0].Msg) } log.Fatal("Malformed response.") } ret.Location = resp.Data.Req[0].Type + ": " + resp.Data.Req[0].Query ret.GeoLoc = <-coordChan if resp.Data.CurCond != nil && len(resp.Data.CurCond) > 0 { ret.Current = wwoParseCond(resp.Data.CurCond[0], time.Now()) } if resp.Data.Days != nil && numdays > 0 { for i, day := range resp.Data.Days { ret.Forecast = append(ret.Forecast, wwoParseDay(day, i)) } } return ret }
func (c *forecastConfig) Fetch(location string, numdays int) iface.Data { var ret iface.Data todayChan := make(chan []iface.Cond) if len(c.apiKey) == 0 { log.Fatal("No forecast.io API key specified.\nYou have to register for one at https://developer.forecast.io/register") } if matched, err := regexp.MatchString(`^-?[0-9]*(\.[0-9]+)?,-?[0-9]*(\.[0-9]+)?$`, location); !matched || err != nil { log.Fatalf("Error: The forecast.io backend only supports latitude,longitude pairs as location.\nInstead of `%s` try `40.748,-73.985` for example to get a forecast for New York", location) } c.tz = time.Local go func() { slots, err := c.fetchToday(location) if err != nil { log.Fatalf("Failed to fetch todays weather data: %v\n", err) } todayChan <- slots }() resp, err := c.fetch(fmt.Sprintf(forecastWuri, c.apiKey, location, c.lang)) if err != nil { log.Fatalf("Failed to fetch weather data: %v\n", err) } if resp.Latitude == nil || resp.Longitude == nil { log.Println("nil response for latitude,longitude") ret.Location = location } else { ret.GeoLoc = &iface.LatLon{Latitude: *resp.Latitude, Longitude: *resp.Longitude} ret.Location = fmt.Sprintf("%f,%f", *resp.Latitude, *resp.Longitude) } if ret.Current, err = c.parseCond(resp.Currently); err != nil { log.Fatalf("Could not parse current weather condition: %v", err) } ret.Forecast = c.ParseDaily(resp.Hourly, numdays) if numdays >= 1 { var tHistory, tFuture = <-todayChan, ret.Forecast[0].Slots var tRet []iface.Cond h, f := 0, 0 // merge forecast and history from current day for h < len(tHistory) || f < len(tFuture) { if f >= len(tFuture) { tRet = append(tRet, tHistory[h]) h++ } else if h >= len(tHistory) || tHistory[h].Time.After(tFuture[f].Time) { tRet = append(tRet, tFuture[f]) f++ } else if tHistory[h].Time.Before(tFuture[f].Time) { tRet = append(tRet, tHistory[h]) h++ } else { tRet = append(tRet, tFuture[f]) h++ f++ } } ret.Forecast[0].Slots = tRet } return ret }