diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-17 09:00:40 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-17 09:00:40 +0200 |
| commit | e6c5c5e6443345e019549d8b41ffa0c19d050c9f (patch) | |
| tree | 3ccb4be91e079954086ddb8835d21ecc86716663 /lib/weather.lua | |
| parent | e9dd31b04324d9a95acf6561a4b6ebcee9d3b8c0 (diff) | |
| download | conky-theme-udt-e6c5c5e6443345e019549d8b41ffa0c19d050c9f.tar.gz conky-theme-udt-e6c5c5e6443345e019549d8b41ffa0c19d050c9f.zip | |
feat: parse the cached OWM response
Lua patterns instead of a JSON library: the current-weather response
is flat and known, so six scalars do not justify a dependency. Every
failure path (truncated write, empty file, garbage, an API error body,
nil input) returns nil rather than raising, since a Lua error here is
a blank dashboard.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'lib/weather.lua')
| -rw-r--r-- | lib/weather.lua | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/weather.lua b/lib/weather.lua index 84f355a..a66d79a 100644 --- a/lib/weather.lua +++ b/lib/weather.lua @@ -142,4 +142,45 @@ function M.is_day(now, sunrise, sunset) return now >= sunrise and now <= sunset end +-- Parse the cached OWM response. +-- +-- Lua patterns, not a JSON library: the current-weather response is flat and +-- its shape is known, so six scalars do not justify a dependency. Returns nil +-- on anything unreadable, never an error. +function M.parse(src) + if type(src) ~= 'string' or src == '' then return nil end + + -- Scalars are matched inside their own object where the key would otherwise + -- be ambiguous. "temp" appears as a prefix of "temp_min" and "temp_max", so + -- it is anchored to the character that follows it. + local function num(pat) + return tonumber(src:match(pat)) + end + + local main = src:match('"main"%s*:%s*(%b{})') or '' + local wind = src:match('"wind"%s*:%s*(%b{})') or '' + local sys = src:match('"sys"%s*:%s*(%b{})') or '' + local cond = src:match('"weather"%s*:%s*%[%s*(%b{})') or '' + + local w = { + id = tonumber(cond:match('"id"%s*:%s*(%-?%d+)')), + description = cond:match('"description"%s*:%s*"([^"]*)"'), + temp = tonumber(main:match('"temp"%s*:%s*(%-?[%d%.]+)')), + feels_like = tonumber(main:match('"feels_like"%s*:%s*(%-?[%d%.]+)')), + humidity = tonumber(main:match('"humidity"%s*:%s*(%d+)')), + wind_speed = tonumber(wind:match('"speed"%s*:%s*([%d%.]+)')), + wind_deg = tonumber(wind:match('"deg"%s*:%s*(%d+)')), + sunrise = tonumber(sys:match('"sunrise"%s*:%s*(%d+)')), + sunset = tonumber(sys:match('"sunset"%s*:%s*(%d+)')), + city = src:match('"name"%s*:%s*"([^"]*)"'), + dt = num('"dt"%s*:%s*(%d+)'), + } + + -- Without these the card has nothing to draw, and a partial card is worse + -- than an honest "no data". An API error body fails here too: it carries a + -- cod and a message, no weather. + if not (w.id and w.temp and w.sunrise and w.sunset) then return nil end + return w +end + return M |
