chore: cleanup 041f62de
Steve · 2026-06-07 14:06 1 file(s) · +23 −10
apps/posts/util.go +23 −10
5 5
	"fmt"
6 6
	"html/template"
7 7
	"net/http"
8 +
	"regexp"
8 9
	"strconv"
9 10
	"strings"
10 11
	"time"
11 -
	"regexp"
12 12
)
13 13
14 14
type parsedAttributes struct {
357 357
	return strings.ToUpper(cleaned[:1]) + cleaned[1:]
358 358
}
359 359
360 +
var weatherClient = &http.Client{Timeout: 10 * time.Second}
361 +
362 +
var qualifierRE = regexp.MustCompile(`(?i)^(slight chance|chance|isolated|scattered|patchy|areas)\s+(of\s+)?`)
363 +
360 364
func getWeather(location string) string {
361 365
	if location == "" {
362 366
		return ""
363 367
	}
364 368
	// Fetch Points data using lat,long
365 369
	pointURL := fmt.Sprintf("https://api.weather.gov/points/%s", location)
366 -
	resp, err := http.Get(pointURL)
370 +
	resp, err := weatherClient.Get(pointURL)
367 371
	if err != nil {
368 372
		fmt.Printf("Error fetching pointUrl: %s", err.Error())
369 373
		return ""
370 374
	}
371 375
	defer resp.Body.Close()
372 376
	var weatherPoint WeatherPointResponse
373 -
	json.NewDecoder(resp.Body).Decode(&weatherPoint)
377 +
	if err := json.NewDecoder(resp.Body).Decode(&weatherPoint); err != nil {
378 +
		fmt.Printf("Error decoding pointUrl: %s", err.Error())
379 +
		return ""
380 +
	}
374 381
	forecastURL := weatherPoint.Properties.ForecastHourly
375 382
	city := weatherPoint.Properties.RelativeLocation.Properties.City
376 383
	state := weatherPoint.Properties.RelativeLocation.Properties.State
377 384
378 385
	// Forcast using points data
379 -
	forecastResp, err := http.Get(forecastURL)
386 +
	forecastResp, err := weatherClient.Get(forecastURL)
380 387
	if err != nil {
381 388
		fmt.Printf("Error fetching forecast: %s", err.Error())
382 389
		return ""
383 390
	}
384 -
	defer resp.Body.Close()
391 +
	defer forecastResp.Body.Close()
385 392
	var weatherForecast WeatherForecastResponse
386 -
	json.NewDecoder(forecastResp.Body).Decode(&weatherForecast)
387 -
	temp := strconv.Itoa(weatherForecast.Properties.Periods[0].Temperature)
388 -
	conditions := weatherForecast.Properties.Periods[0].ShortForecast
389 -
	var qualifierRE = regexp.MustCompile(`(?i)^(slight chance|chance|isolated|scattered|patchy|areas)\s+(of\s+)?`)
390 -
	formattedConditions := strings.TrimSpace(qualifierRE.ReplaceAllString(conditions, ""))
393 +
	if err := json.NewDecoder(forecastResp.Body).Decode(&weatherForecast); err != nil {
394 +
		fmt.Printf("Error decoding forecast: %s", err.Error())
395 +
		return ""
396 +
	}
397 +
	if len(weatherForecast.Properties.Periods) == 0 {
398 +
		fmt.Printf("Error: no forecast periods returned for %q", location)
399 +
		return ""
400 +
	}
401 +
	period := weatherForecast.Properties.Periods[0]
402 +
	temp := strconv.Itoa(period.Temperature)
403 +
	formattedConditions := strings.TrimSpace(qualifierRE.ReplaceAllString(period.ShortForecast, ""))
391 404
	weather := fmt.Sprintf("%s,%s,%s,%s", formattedConditions, temp, city, state)
392 405
	return weather
393 406
}