diff --git a/main.go b/main.go index 63294b3..a9e4450 100644 --- a/main.go +++ b/main.go @@ -29,13 +29,13 @@ import ( ) type apiKey struct { - openWeatherMap string + accuWeather string } type location struct { - lat float32 - lon float32 - ianaName string + displayName string + ianaName string + key string } // pageTemplate stores all pre-compiled HTML templates for the application @@ -75,6 +75,8 @@ type state struct { apiKey apiKey template pageTemplate + usePlaceholder bool + // summaries maps location keys to their latest weather summary summaries sync.Map // summaryChans stores a map of location key to the corresponding summary channel @@ -96,65 +98,28 @@ type state struct { //go:embed web var webDir embed.FS -var envKeys = []string{"GEMINI_API_KEY", "OPEN_WEATHER_MAP_API_KEY", "VAPID_PRIVATE_KEY_BASE64", "VAPID_PUBLIC_KEY_BASE64"} +var envKeys = []string{"GEMINI_API_KEY", "ACCU_WEATHER_API_KEY", "VAPID_PRIVATE_KEY_BASE64", "VAPID_PUBLIC_KEY_BASE64"} -var prompt = `The current time is 5pm. Provide a short summary of the weather forecast for the next 48 hours in JSON in %v below. - -This is the JSON schema of the JSON: -current Current weather data API response -current.dt Current time, Unix, UTC -current.sunrise Sunrise time, Unix, UTC. For polar areas in midnight sun and polar night periods this parameter is not returned in the response -current.sunset Sunset time, Unix, UTC. For polar areas in midnight sun and polar night periods this parameter is not returned in the response -current.temp Temperature. Units - default: kelvin, metric: Celsius, imperial: Fahrenheit. How to change units used -current.feels_like Temperature. This temperature parameter accounts for the human perception of weather. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. -current.pressure Atmospheric pressure on the sea level, hPa -current.humidity Humidity, percentage -current.dew_point Atmospheric temperature (varying according to pressure and humidity) below which water droplets begin to condense and dew can form. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit -current.clouds Cloudiness, percentage -current.uvi Current UV index. -current.visibility Average visibility, metres. The maximum value of the visibility is 10 km -current.wind_speed Wind speed. Wind speed. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used -current.wind_gust (where available) Wind gust. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used -current.wind_deg Wind direction, degrees (meteorological) -current.rain.1h (where available) Precipitation, mm/h. Please note that only mm/h as units of measurement are available for this parameter -current.snow.1h (where available) Precipitation, mm/h. Please note that only mm/h as units of measurement are available for this parameter -current.weather -current.weather.id Weather condition id -current.weather.main Group of weather parameters (Rain, Snow etc.) -current.weather.description Weather condition within the group (full list of weather conditions). Get the output in your language -current.weather.icon -hourly Hourly forecast weather data API response -hourly.dt Time of the forecasted data, Unix, UTC -hourly.temp Temperature. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. How to change units used -hourly.feels_like Temperature. This accounts for the human perception of weather. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. -hourly.pressure Atmospheric pressure on the sea level, hPa -hourly.humidity Humidity, percentage -hourly.dew_point Atmospheric temperature (varying according to pressure and humidity) below which water droplets begin to condense and dew can form. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. -hourly.uvi UV index -hourly.clouds Cloudiness, percentage -hourly.visibility Average visibility, metres. The maximum value of the visibility is 10 km -hourly.wind_speed Wind speed. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour.How to change units used -hourly.wind_gust (where available) Wind gust. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used -hourly.wind_deg Wind direction, degrees (meteorological) -hourly.pop Probability of precipitation. The values of the parameter vary between 0 and 1, where 0 is equal to 0 percent, 1 is equal to 100 percent -hourly.rain.1h (where available) Precipitation, mm/h. Please note that only mm/h as units of measurement are available for this parameter -hourly.snow.1h (where available) Precipitation, mm/h. Please note that only mm/h as units of measurement are available for this parameter -hourly.weather.id Weather condition id -hourly.weather.main Group of weather parameters (Rain, Snow etc.) -hourly.weather.description Weather condition within the group (full list of weather conditions). Get the output in your language - -Summarize hourly weather until midnight today. Keep it concise. Suggest how to deal with the weather, such as how to dress for the weather, and whether they need an umbrella. +var prompt = `The current time is 5pm. Provide a short summary of the weather forecast in JSON in %v below. Keep it concise. Suggest how to deal with the weather, such as how to dress for the weather, and whether they need an umbrella. Use celsius and fahrenheit but not Kelvin for temperature. Mention %v in the summary, but don't add anything else, as the summary will be displayed on a website. -The summary should be in plaintext for humans. Do not output in JSON. -` +The summary should be in plaintext for humans. Do not output in JSON.` + +var placeholderWeather = map[string]string{ + "london": "{\"Headline\":{\"EffectiveDate\":\"2025-05-11T08:00:00+01:00\",\"EffectiveEpochDate\":1746946800,\"Severity\":4,\"Text\":\"Pleasant Sunday\",\"Category\":\"mild\",\"EndDate\":null,\"EndEpochDate\":null,\"MobileLink\":\"http://www.accuweather.com/en/gb/london/ec4a-2/daily-weather-forecast/328328?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/gb/london/ec4a-2/daily-weather-forecast/328328?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2025-05-10T07:00:00+01:00\",\"EpochDate\":1746856800,\"Sun\":{\"Rise\":\"2025-05-10T05:17:00+01:00\",\"EpochRise\":1746850620,\"Set\":\"2025-05-10T20:38:00+01:00\",\"EpochSet\":1746905880},\"Moon\":{\"Rise\":\"2025-05-10T18:40:00+01:00\",\"EpochRise\":1746898800,\"Set\":\"2025-05-11T04:21:00+01:00\",\"EpochSet\":1746933660,\"Phase\":\"WaxingGibbous\",\"Age\":13},\"Temperature\":{\"Minimum\":{\"Value\":50,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":69,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":49,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Chilly\"},\"Maximum\":{\"Value\":70,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":49,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Chilly\"},\"Maximum\":{\"Value\":66,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"HoursOfSun\":12.8,\"DegreeDaySummary\":{\"Heating\":{\"Value\":5,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":0,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":0,\"Category\":\"Good\",\"CategoryValue\":1,\"Type\":\"Ozone\"},{\"Name\":\"Grass\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Mold\",\"Value\":32767,\"Category\":\"High\",\"CategoryValue\":3},{\"Name\":\"Ragweed\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"UVIndex\",\"Value\":7,\"Category\":\"High\",\"CategoryValue\":3}],\"Day\":{\"Icon\":1,\"IconPhrase\":\"Sunny\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Sunshine, breezy and pleasant\",\"LongPhrase\":\"Breezy and pleasant with sunshine\",\"PrecipitationProbability\":1,\"ThunderstormProbability\":0,\"RainProbability\":1,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":13.8,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":97,\"Localized\":\"E\",\"English\":\"E\"}},\"WindGust\":{\"Speed\":{\"Value\":32.2,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":88,\"Localized\":\"E\",\"English\":\"E\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":6,\"Evapotranspiration\":{\"Value\":0.18,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":7999.7,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":27,\"Maximum\":71,\"Average\":39},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":46,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":49,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":50,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":61,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":57,\"Unit\":\"F\",\"UnitType\":18}}},\"Night\":{\"Icon\":38,\"IconPhrase\":\"Mostly cloudy\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Increasing cloudiness\",\"LongPhrase\":\"Increasing cloudiness\",\"PrecipitationProbability\":1,\"ThunderstormProbability\":0,\"RainProbability\":1,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":6.9,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":69,\"Localized\":\"ENE\",\"English\":\"ENE\"}},\"WindGust\":{\"Speed\":{\"Value\":20.7,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":106,\"Localized\":\"ESE\",\"English\":\"ESE\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":32,\"Evapotranspiration\":{\"Value\":0.02,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":155.7,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":44,\"Maximum\":82,\"Average\":67},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":48,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":50,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":54,\"Unit\":\"F\",\"UnitType\":18}}},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://www.accuweather.com/en/gb/london/ec4a-2/daily-weather-forecast/328328?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/gb/london/ec4a-2/daily-weather-forecast/328328?day=1&lang=en-us\"}]}", + "sf": "{\"Headline\":{\"EffectiveDate\":\"2025-05-10T08:00:00-07:00\",\"EffectiveEpochDate\":1746889200,\"Severity\":4,\"Text\":\"Pleasant today\",\"Category\":\"mild\",\"EndDate\":null,\"EndEpochDate\":null,\"MobileLink\":\"http://www.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2025-05-10T07:00:00-07:00\",\"EpochDate\":1746885600,\"Sun\":{\"Rise\":\"2025-05-10T06:04:00-07:00\",\"EpochRise\":1746882240,\"Set\":\"2025-05-10T20:08:00-07:00\",\"EpochSet\":1746932880},\"Moon\":{\"Rise\":\"2025-05-10T18:41:00-07:00\",\"EpochRise\":1746927660,\"Set\":\"2025-05-11T05:13:00-07:00\",\"EpochSet\":1746965580,\"Phase\":\"WaxingGibbous\",\"Age\":13},\"Temperature\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":71,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":48,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Chilly\"},\"Maximum\":{\"Value\":73,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":48,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Chilly\"},\"Maximum\":{\"Value\":67,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"HoursOfSun\":10.2,\"DegreeDaySummary\":{\"Heating\":{\"Value\":3,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":0,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":49,\"Category\":\"Good\",\"CategoryValue\":1,\"Type\":\"Particle Pollution\"},{\"Name\":\"Grass\",\"Value\":12,\"Category\":\"Moderate\",\"CategoryValue\":2},{\"Name\":\"Mold\",\"Value\":3250,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Ragweed\",\"Value\":5,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":7,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"UVIndex\",\"Value\":10,\"Category\":\"Very High\",\"CategoryValue\":4}],\"Day\":{\"Icon\":2,\"IconPhrase\":\"Mostly sunny\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Sunshine and pleasant\",\"LongPhrase\":\"Sunny to partly cloudy and pleasant\",\"PrecipitationProbability\":1,\"ThunderstormProbability\":0,\"RainProbability\":1,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":11.5,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":254,\"Localized\":\"WSW\",\"English\":\"WSW\"}},\"WindGust\":{\"Speed\":{\"Value\":29.9,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":257,\"Localized\":\"WSW\",\"English\":\"WSW\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":28,\"Evapotranspiration\":{\"Value\":0.15,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":8489.7,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":51,\"Maximum\":91,\"Average\":65},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":61,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":57,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":56,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":66,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":62,\"Unit\":\"F\",\"UnitType\":18}}},\"Night\":{\"Icon\":35,\"IconPhrase\":\"Partly cloudy\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Partly cloudy\",\"LongPhrase\":\"Partly cloudy\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":0,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":11.5,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":268,\"Localized\":\"W\",\"English\":\"W\"}},\"WindGust\":{\"Speed\":{\"Value\":19.6,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":264,\"Localized\":\"W\",\"English\":\"W\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":45,\"Evapotranspiration\":{\"Value\":0.02,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":190.9,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":57,\"Maximum\":84,\"Average\":73},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":50,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":54,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":55,\"Unit\":\"F\",\"UnitType\":18}}},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://www.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?day=1&lang=en-us\"}]}", + "sj": "{\"Headline\":{\"EffectiveDate\":\"2025-05-11T08:00:00-07:00\",\"EffectiveEpochDate\":1746975600,\"Severity\":4,\"Text\":\"Pleasant tomorrow\",\"Category\":\"mild\",\"EndDate\":null,\"EndEpochDate\":null,\"MobileLink\":\"http://www.accuweather.com/en/us/san-jose-ca/95110/daily-weather-forecast/347630?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/san-jose-ca/95110/daily-weather-forecast/347630?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2025-05-10T07:00:00-07:00\",\"EpochDate\":1746885600,\"Sun\":{\"Rise\":\"2025-05-10T06:03:00-07:00\",\"EpochRise\":1746882180,\"Set\":\"2025-05-10T20:05:00-07:00\",\"EpochSet\":1746932700},\"Moon\":{\"Rise\":\"2025-05-10T18:38:00-07:00\",\"EpochRise\":1746927480,\"Set\":\"2025-05-11T05:11:00-07:00\",\"EpochSet\":1746965460,\"Phase\":\"WaxingGibbous\",\"Age\":13},\"Temperature\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":84,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Cool\"},\"Maximum\":{\"Value\":87,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Very Warm\"}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Cool\"},\"Maximum\":{\"Value\":81,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"HoursOfSun\":12.7,\"DegreeDaySummary\":{\"Heating\":{\"Value\":0,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":4,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":70,\"Category\":\"Moderate\",\"CategoryValue\":2,\"Type\":\"Ozone\"},{\"Name\":\"Grass\",\"Value\":12,\"Category\":\"Moderate\",\"CategoryValue\":2},{\"Name\":\"Mold\",\"Value\":3250,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Ragweed\",\"Value\":5,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":7,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"UVIndex\",\"Value\":10,\"Category\":\"Very High\",\"CategoryValue\":4}],\"Day\":{\"Icon\":1,\"IconPhrase\":\"Sunny\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Sunny\",\"LongPhrase\":\"Sunny\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":0,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":8.1,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":321,\"Localized\":\"NW\",\"English\":\"NW\"}},\"WindGust\":{\"Speed\":{\"Value\":21.9,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":321,\"Localized\":\"NW\",\"English\":\"NW\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":9,\"Evapotranspiration\":{\"Value\":0.23,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":8666.2,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":22,\"Maximum\":74,\"Average\":36},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":55,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":60,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":61,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":72,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":67,\"Unit\":\"F\",\"UnitType\":18}}},\"Night\":{\"Icon\":35,\"IconPhrase\":\"Partly cloudy\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Partly cloudy\",\"LongPhrase\":\"Partly cloudy\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":0,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":5.8,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":313,\"Localized\":\"NW\",\"English\":\"NW\"}},\"WindGust\":{\"Speed\":{\"Value\":18.4,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":318,\"Localized\":\"NW\",\"English\":\"NW\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":30,\"Evapotranspiration\":{\"Value\":0.02,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":199.8,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":35,\"Maximum\":71,\"Average\":58},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":49,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":55,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":63,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":57,\"Unit\":\"F\",\"UnitType\":18}}},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://www.accuweather.com/en/us/san-jose-ca/95110/daily-weather-forecast/347630?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/san-jose-ca/95110/daily-weather-forecast/347630?day=1&lang=en-us\"}]}", + "la": "{\"Headline\":{\"EffectiveDate\":\"2025-05-10T08:00:00-07:00\",\"EffectiveEpochDate\":1746889200,\"Severity\":4,\"Text\":\"Record-breaking high temperatures today\",\"Category\":\"record heat\",\"EndDate\":\"2025-05-10T20:00:00-07:00\",\"EndEpochDate\":1746932400,\"MobileLink\":\"http://www.accuweather.com/en/us/los-angeles-ca/90012/daily-weather-forecast/347625?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/los-angeles-ca/90012/daily-weather-forecast/347625?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2025-05-10T07:00:00-07:00\",\"EpochDate\":1746885600,\"Sun\":{\"Rise\":\"2025-05-10T05:55:00-07:00\",\"EpochRise\":1746881700,\"Set\":\"2025-05-10T19:44:00-07:00\",\"EpochSet\":1746931440},\"Moon\":{\"Rise\":\"2025-05-10T18:17:00-07:00\",\"EpochRise\":1746926220,\"Set\":\"2025-05-11T05:03:00-07:00\",\"EpochSet\":1746964980,\"Phase\":\"WaxingGibbous\",\"Age\":13},\"Temperature\":{\"Minimum\":{\"Value\":66,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":100,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":64,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"},\"Maximum\":{\"Value\":106,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Very Hot\"}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":64,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"},\"Maximum\":{\"Value\":98,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Hot\"}},\"HoursOfSun\":12.5,\"DegreeDaySummary\":{\"Heating\":{\"Value\":0,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":18,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":73,\"Category\":\"Moderate\",\"CategoryValue\":2,\"Type\":\"Ozone\"},{\"Name\":\"Grass\",\"Value\":2,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Mold\",\"Value\":3250,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Ragweed\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":50,\"Category\":\"Moderate\",\"CategoryValue\":2},{\"Name\":\"UVIndex\",\"Value\":11,\"Category\":\"Extreme\",\"CategoryValue\":5}],\"Day\":{\"Icon\":1,\"IconPhrase\":\"Sunny\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Sunny; record-breaking heat\",\"LongPhrase\":\"Sunny and hot with the temperature breaking the record of 95 set in 1934; caution advised if outside for extended periods of time\",\"PrecipitationProbability\":1,\"ThunderstormProbability\":0,\"RainProbability\":1,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":4.6,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":228,\"Localized\":\"SW\",\"English\":\"SW\"}},\"WindGust\":{\"Speed\":{\"Value\":18.4,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":246,\"Localized\":\"WSW\",\"English\":\"WSW\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":4,\"Evapotranspiration\":{\"Value\":0.27,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":8761.5,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":18,\"Maximum\":52,\"Average\":26},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":66,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":71,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":68,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":74,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":86,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":82,\"Unit\":\"F\",\"UnitType\":18}}},\"Night\":{\"Icon\":35,\"IconPhrase\":\"Partly cloudy\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Partly cloudy\",\"LongPhrase\":\"Partly cloudy\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":0,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":4.6,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":160,\"Localized\":\"SSE\",\"English\":\"SSE\"}},\"WindGust\":{\"Speed\":{\"Value\":13.8,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":233,\"Localized\":\"SW\",\"English\":\"SW\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":45,\"Evapotranspiration\":{\"Value\":0.03,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":174.5,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":30,\"Maximum\":66,\"Average\":52},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":59,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":66,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":62,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":65,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":79,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":70,\"Unit\":\"F\",\"UnitType\":18}}},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://www.accuweather.com/en/us/los-angeles-ca/90012/daily-weather-forecast/347625?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/los-angeles-ca/90012/daily-weather-forecast/347625?day=1&lang=en-us\"}]}", + "nyc": "{\"Headline\":{\"EffectiveDate\":\"2025-05-11T08:00:00-04:00\",\"EffectiveEpochDate\":1746964800,\"Severity\":4,\"Text\":\"Pleasant tomorrow\",\"Category\":\"mild\",\"EndDate\":null,\"EndEpochDate\":null,\"MobileLink\":\"http://www.accuweather.com/en/us/new-york-ny/10021/daily-weather-forecast/14-349727_1_al?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/new-york-ny/10021/daily-weather-forecast/14-349727_1_al?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2025-05-10T07:00:00-04:00\",\"EpochDate\":1746874800,\"Sun\":{\"Rise\":\"2025-05-10T05:44:00-04:00\",\"EpochRise\":1746870240,\"Set\":\"2025-05-10T20:01:00-04:00\",\"EpochSet\":1746921660},\"Moon\":{\"Rise\":\"2025-05-10T18:24:00-04:00\",\"EpochRise\":1746915840,\"Set\":\"2025-05-11T04:49:00-04:00\",\"EpochSet\":1746953340,\"Phase\":\"WaxingGibbous\",\"Age\":13},\"Temperature\":{\"Minimum\":{\"Value\":57,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":71,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Cool\"},\"Maximum\":{\"Value\":74,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Cool\"},\"Maximum\":{\"Value\":67,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"HoursOfSun\":9.8,\"DegreeDaySummary\":{\"Heating\":{\"Value\":1,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":0,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":54,\"Category\":\"Moderate\",\"CategoryValue\":2,\"Type\":\"Nitrogen Dioxide\"},{\"Name\":\"Grass\",\"Value\":2,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Mold\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Ragweed\",\"Value\":5,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":50,\"Category\":\"Moderate\",\"CategoryValue\":2},{\"Name\":\"UVIndex\",\"Value\":9,\"Category\":\"Very High\",\"CategoryValue\":4}],\"Day\":{\"Icon\":3,\"IconPhrase\":\"Partly sunny\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Partly sunny; breezy, warmer\",\"LongPhrase\":\"Partly sunny, breezy and warmer\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":0,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":10.4,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":300,\"Localized\":\"WNW\",\"English\":\"WNW\"}},\"WindGust\":{\"Speed\":{\"Value\":24.2,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":296,\"Localized\":\"WNW\",\"English\":\"WNW\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":37,\"Evapotranspiration\":{\"Value\":0.15,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":7814.5,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":26,\"Maximum\":63,\"Average\":41},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":47,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":53,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":62,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18}}},\"Night\":{\"Icon\":33,\"IconPhrase\":\"Clear\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Clear\",\"LongPhrase\":\"Clear\",\"PrecipitationProbability\":1,\"ThunderstormProbability\":0,\"RainProbability\":1,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":3.5,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":268,\"Localized\":\"W\",\"English\":\"W\"}},\"WindGust\":{\"Speed\":{\"Value\":11.5,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":281,\"Localized\":\"W\",\"English\":\"W\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":6,\"Evapotranspiration\":{\"Value\":0.02,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":240.1,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":34,\"Maximum\":63,\"Average\":48},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":50,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":52,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":51,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":56,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":61,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18}}},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://www.accuweather.com/en/us/new-york-ny/10021/daily-weather-forecast/14-349727_1_al?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/new-york-ny/10021/daily-weather-forecast/14-349727_1_al?day=1&lang=en-us\"}]}", + "tokyo": "{\"Headline\":{\"EffectiveDate\":\"2025-05-11T19:00:00+09:00\",\"EffectiveEpochDate\":1746957600,\"Severity\":5,\"Text\":\"Rain Sunday night\",\"Category\":\"rain\",\"EndDate\":\"2025-05-12T07:00:00+09:00\",\"EndEpochDate\":1747000800,\"MobileLink\":\"http://www.accuweather.com/en/jp/tokyo/226396/daily-weather-forecast/226396?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/jp/tokyo/226396/daily-weather-forecast/226396?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2025-05-11T07:00:00+09:00\",\"EpochDate\":1746914400,\"Sun\":{\"Rise\":\"2025-05-11T04:40:00+09:00\",\"EpochRise\":1746906000,\"Set\":\"2025-05-11T18:35:00+09:00\",\"EpochSet\":1746956100},\"Moon\":{\"Rise\":\"2025-05-11T17:24:00+09:00\",\"EpochRise\":1746951840,\"Set\":\"2025-05-12T03:55:00+09:00\",\"EpochSet\":1746989700,\"Phase\":\"WaxingGibbous\",\"Age\":13},\"Temperature\":{\"Minimum\":{\"Value\":62,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":81,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Cool\"},\"Maximum\":{\"Value\":82,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Very Warm\"}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":58,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Cool\"},\"Maximum\":{\"Value\":77,\"Unit\":\"F\",\"UnitType\":18,\"Phrase\":\"Pleasant\"}},\"HoursOfSun\":1,\"DegreeDaySummary\":{\"Heating\":{\"Value\":0,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":6,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":0,\"Category\":\"Good\",\"CategoryValue\":1,\"Type\":\"Ozone\"},{\"Name\":\"Grass\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Mold\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Ragweed\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"UVIndex\",\"Value\":5,\"Category\":\"Moderate\",\"CategoryValue\":2}],\"Day\":{\"Icon\":4,\"IconPhrase\":\"Intermittent clouds\",\"HasPrecipitation\":false,\"ShortPhrase\":\"Breezy in the afternoon\",\"LongPhrase\":\"Sun through high clouds and less humid; breezy in the afternoon\",\"PrecipitationProbability\":9,\"ThunderstormProbability\":0,\"RainProbability\":9,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":10.4,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":261,\"Localized\":\"W\",\"English\":\"W\"}},\"WindGust\":{\"Speed\":{\"Value\":17.3,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":179,\"Localized\":\"S\",\"English\":\"S\"}},\"TotalLiquid\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0,\"HoursOfRain\":0,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":99,\"Evapotranspiration\":{\"Value\":0.13,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":512,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":42,\"Maximum\":70,\"Average\":51},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":62,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":65,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":64,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":64,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":71,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":68,\"Unit\":\"F\",\"UnitType\":18}}},\"Night\":{\"Icon\":18,\"IconPhrase\":\"Rain\",\"HasPrecipitation\":true,\"PrecipitationType\":\"Rain\",\"PrecipitationIntensity\":\"Light\",\"ShortPhrase\":\"On-and-off rain and drizzle\",\"LongPhrase\":\"On-and-off rain and drizzle\",\"PrecipitationProbability\":84,\"ThunderstormProbability\":0,\"RainProbability\":84,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":9.2,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":233,\"Localized\":\"SW\",\"English\":\"SW\"}},\"WindGust\":{\"Speed\":{\"Value\":13.8,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":334,\"Localized\":\"NNW\",\"English\":\"NNW\"}},\"TotalLiquid\":{\"Value\":0.09,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0.09,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":1.5,\"HoursOfRain\":1.5,\"HoursOfSnow\":0,\"HoursOfIce\":0,\"CloudCover\":100,\"Evapotranspiration\":{\"Value\":0.03,\"Unit\":\"in\",\"UnitType\":1},\"SolarIrradiance\":{\"Value\":9.8,\"Unit\":\"W/m²\",\"UnitType\":33},\"RelativeHumidity\":{\"Minimum\":58,\"Maximum\":85,\"Average\":73},\"WetBulbTemperature\":{\"Minimum\":{\"Value\":59,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":63,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":61,\"Unit\":\"F\",\"UnitType\":18}},\"WetBulbGlobeTemperature\":{\"Minimum\":{\"Value\":60,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":67,\"Unit\":\"F\",\"UnitType\":18},\"Average\":{\"Value\":63,\"Unit\":\"F\",\"UnitType\":18}}},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://www.accuweather.com/en/jp/tokyo/226396/daily-weather-forecast/226396?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/jp/tokyo/226396/daily-weather-forecast/226396?day=1&lang=en-us\"}]}", +} var supportedLocations = map[string]location{ - "london": {51.507351, -0.127758, "Europe/London"}, - "sf": {37.774929, -122.419418, "America/Los_Angeles"}, - "sj": {37.338207, -121.886330, "America/Los_Angeles"}, - "la": {34.052235, -118.243683, "America/Los_Angeles"}, - "nyc": {40.712776, -74.005974, "America/New_York"}, - "tokyo": {35.689487, 139.691711, "Asia/Tokyo"}, + "london": {"London", "Europe/London", "328328"}, + "sf": {"San Francisco", "America/Los_Angeles", "347629"}, + "sj": {"San Jose", "America/Los_Angeles", "347630"}, + "la": {"Los Angeles", "America/Los_Angeles", "347625"}, + "nyc": {"New York City", "America/New_York", "14-349727_1_AL"}, + "tokyo": {"Tokyo", "Asia/Tokyo", "226396"}, } var locationNames = map[string]string{ @@ -169,6 +134,7 @@ var locationNames = map[string]string{ func main() { port := flag.Int("port", 8080, "the port that the server should listen on") genKeys := flag.Bool("generate-vapid-keys", false, "generate a new vapid key pair, which will be outputted to stdout.") + usePlaceholder := flag.Bool("use-placeholder", false, "use placeholder data instead of real API data.") flag.Parse() @@ -206,7 +172,7 @@ func main() { ctx: ctx, db: db, apiKey: apiKey{ - openWeatherMap: os.Getenv("OPEN_WEATHER_MAP_API_KEY"), + accuWeather: os.Getenv("ACCU_WEATHER_API_KEY"), }, template: pageTemplate{ summary: summaryPageTemplate, @@ -215,6 +181,8 @@ func main() { summaryChans: map[string]chan string{}, genai: genaiClient, + usePlaceholder: *usePlaceholder, + subscriptions: map[string][]*registeredSubscription{}, vapidPublicKey: os.Getenv("VAPID_PUBLIC_KEY_BASE64"), @@ -583,23 +551,30 @@ func deleteSubscription(state *state, regID uuid.UUID) error { func updateSummaries(state *state, locKey string, loc *location) { log.Printf("updating summary for %v...\n", locKey) - resp, err := http.Get(fmt.Sprintf("https://api.openweathermap.org/data/3.0/onecall?lat=%v&lon=%v&exclude=minutely,daily&appid=%v", loc.lat, loc.lon, state.apiKey.openWeatherMap)) - if err != nil { - log.Printf("error updating summaries for %s: %e\n", locKey, err) - return - } + var weatherJSON string + if state.usePlaceholder { + weatherJSON = placeholderWeather[locKey] + } else { + resp, err := http.Get(fmt.Sprintf("http://dataservice.accuweather.com/forecasts/v1/daily/1day/%v?apikey=%v&detail=true", loc.key, state.apiKey.accuWeather)) + if err != nil { + log.Printf("error updating summaries for %s: %e\n", locKey, err) + return + } - b, err := io.ReadAll(resp.Body) - defer resp.Body.Close() - if err != nil { - log.Printf("error updating summaries for %s: %e\n", locKey, err) - return + b, err := io.ReadAll(resp.Body) + defer resp.Body.Close() + if err != nil { + log.Printf("error updating summaries for %s: %e\n", locKey, err) + return + } + + weatherJSON = string(b) } result, err := state.genai.Models.GenerateContent(state.ctx, "gemini-2.0-flash", []*genai.Content{{ Parts: []*genai.Part{ {Text: fmt.Sprintf(prompt, locationNames[locKey], locationNames[locKey])}, - {Text: string(b)}, + {Text: weatherJSON}, }, }}, nil) if err != nil {