Allow specifying state in weather location

This commit is contained in:
Svilen Markov 2024-05-02 19:54:20 +01:00
parent ad06146784
commit d8d6625478
4 changed files with 79 additions and 3 deletions

View File

@ -579,6 +579,15 @@ Example:
location: London, United Kingdom location: London, United Kingdom
``` ```
> [!NOTE]
>
> US cities which have common names can have their state specified as the second parameter like such:
>
> * Greenville, North Carolina, United States
> * Greenville, South Carolina, United States
> * Greenville, Mississippi, United States
Preview: Preview:
![](images/weather-widget-preview.png) ![](images/weather-widget-preview.png)
@ -592,6 +601,7 @@ Each bar represents a 2 hour interval. The yellow background represents sunrise
| location | string | yes | | | location | string | yes | |
| units | string | no | metric | | units | string | no | metric |
| hide-location | boolean | no | false | | hide-location | boolean | no | false |
| show-area-name | boolean | no | false |
##### `location` ##### `location`
The name of the city and country to fetch weather information for. Attempting to launch the applcation with an invalid location will result in an error. You can use the [gecoding API page](https://open-meteo.com/en/docs/geocoding-api) to search for your specific location. Glance will use the first result from the list if there are multiple. The name of the city and country to fetch weather information for. Attempting to launch the applcation with an invalid location will result in an error. You can use the [gecoding API page](https://open-meteo.com/en/docs/geocoding-api) to search for your specific location. Glance will use the first result from the list if there are multiple.
@ -602,6 +612,19 @@ Whether to show the temperature in celsius or fahrenheit, possible values are `m
##### `hide-location` ##### `hide-location`
Optionally don't display the location name on the widget. Optionally don't display the location name on the widget.
##### `show-area-name`
Whether to display the state/administrative area in the location name. If set to `true` the location will be displayed as:
```
Greenville, North Carolina, United States
```
Otherwise, if set to `false` (which is the default) it'll be displayed as:
```
Greenville, United States
```
### Monitor ### Monitor
Display a list of sites and whether they are reachable (online) or not. This is determined by sending a HEAD request to the specified URL, if the response is 200 then the site is OK. The time it took to receive a response is also shown in milliseconds. Display a list of sites and whether they are reachable (online) or not. This is determined by sending a HEAD request to the specified URL, if the response is 200 then the site is OK. The time it took to receive a response is also shown in milliseconds.

View File

@ -23,7 +23,7 @@
{{ if not .HideLocation }} {{ if not .HideLocation }}
<div class="flex items-center justify-center margin-top-15 gap-7 size-h5"> <div class="flex items-center justify-center margin-top-15 gap-7 size-h5">
<div class="location-icon"></div> <div class="location-icon"></div>
<div class="text-truncate">{{ .Place.Name }}, {{ .Place.Country }}</div> <div class="text-truncate">{{ .Place.Name }},{{ if .ShowAreaName }} {{ .Place.Area }},{{ end }} {{ .Place.Country }}</div>
</div> </div>
{{ end }} {{ end }}
{{ end }} {{ end }}

View File

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"slices" "slices"
"strings"
"time" "time"
_ "time/tzdata" _ "time/tzdata"
@ -17,6 +18,7 @@ type PlacesResponseJson struct {
type PlaceJson struct { type PlaceJson struct {
Name string Name string
Area string `json:"admin1"`
Latitude float64 Latitude float64
Longitude float64 Longitude float64
Timezone string Timezone string
@ -48,8 +50,41 @@ type weatherColumn struct {
HasPrecipitation bool HasPrecipitation bool
} }
var commonCountryAbbreviations = map[string]string{
"US": "United States",
"USA": "United States",
"UK": "United Kingdom",
}
func expandCountryAbbreviations(name string) string {
if expanded, ok := commonCountryAbbreviations[strings.TrimSpace(name)]; ok {
return expanded
}
return name
}
// Separates the location that Open Meteo accepts from the administrative area
// which can then be used to filter to the correct place after the list of places
// has been retrieved. Also expands abbreviations since Open Meteo does not accept
// country names like "US", "USA" and "UK"
func parsePlaceName(name string) (string, string) {
parts := strings.Split(name, ",")
if len(parts) == 1 {
return name, ""
}
if len(parts) == 2 {
return parts[0] + ", " + expandCountryAbbreviations(parts[1]), ""
}
return parts[0] + ", " + expandCountryAbbreviations(parts[2]), strings.TrimSpace(parts[1])
}
func FetchPlaceFromName(location string) (*PlaceJson, error) { func FetchPlaceFromName(location string) (*PlaceJson, error) {
requestUrl := fmt.Sprintf("https://geocoding-api.open-meteo.com/v1/search?name=%s&count=1&language=en&format=json", url.QueryEscape(location)) location, area := parsePlaceName(location)
requestUrl := fmt.Sprintf("https://geocoding-api.open-meteo.com/v1/search?name=%s&count=10&language=en&format=json", url.QueryEscape(location))
request, _ := http.NewRequest("GET", requestUrl, nil) request, _ := http.NewRequest("GET", requestUrl, nil)
responseJson, err := decodeJsonFromRequest[PlacesResponseJson](defaultClient, request) responseJson, err := decodeJsonFromRequest[PlacesResponseJson](defaultClient, request)
@ -61,7 +96,24 @@ func FetchPlaceFromName(location string) (*PlaceJson, error) {
return nil, fmt.Errorf("no places found for %s", location) return nil, fmt.Errorf("no places found for %s", location)
} }
place := &responseJson.Results[0] var place *PlaceJson
if area != "" {
area = strings.ToLower(area)
for i := range responseJson.Results {
if strings.ToLower(responseJson.Results[i].Area) == area {
place = &responseJson.Results[i]
break
}
}
if place == nil {
return nil, fmt.Errorf("no place found for %s in %s", location, area)
}
} else {
place = &responseJson.Results[0]
}
loc, err := time.LoadLocation(place.Timezone) loc, err := time.LoadLocation(place.Timezone)

View File

@ -12,6 +12,7 @@ import (
type Weather struct { type Weather struct {
widgetBase `yaml:",inline"` widgetBase `yaml:",inline"`
Location string `yaml:"location"` Location string `yaml:"location"`
ShowAreaName bool `yaml:"show-area-name"`
HideLocation bool `yaml:"hide-location"` HideLocation bool `yaml:"hide-location"`
Units string `yaml:"units"` Units string `yaml:"units"`
Place *feed.PlaceJson `yaml:"-"` Place *feed.PlaceJson `yaml:"-"`