Files
tz-snipe/internal/geodata/fetcher.go

78 lines
1.5 KiB
Go

package geodata
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
)
func fetchLive() (TimezoneMap, error) {
client := http.Client{Timeout: 10 * time.Second}
// from: https://restcountries.com
url := "https://restcountries.com/v3.1/all?fields=name,population,timezones"
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("failed to fetch country data")
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to fetch country data")
}
var apiData []countryApiReponse
if err := json.NewDecoder(resp.Body).Decode(&apiData); err != nil {
return nil, fmt.Errorf("failed to fetch ")
}
return buildTzMap(apiData), nil
}
func Fetch() (TimezoneMap, error) {
// try to get from cache
tzMap, err := loadFromCache()
if err == nil {
return tzMap, nil
}
// fetch live and save
tzMap, err = fetchLive()
if err != nil {
return nil, err
}
if err = saveToCache(tzMap); err != nil {
return nil, err
}
return tzMap, nil
}
func buildTzMap(data []countryApiReponse) TimezoneMap {
tzMap := make(TimezoneMap)
for _, countryRaw := range data {
country := Country{
Name: countryRaw.Name.Common,
Population: countryRaw.Population,
}
for _, rawTZ := range countryRaw.Timezones {
rawTZ = strings.TrimPrefix(rawTZ, "UTC")
rawTZ = strings.ReplaceAll(rawTZ, ":", "")
if rawTZ == "" {
rawTZ = "+0000" // api quirk
}
tzMap[rawTZ] = append(tzMap[rawTZ], country)
}
}
return tzMap
}