aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-17 09:00:40 +0200
committerDanilo M. <danix@danix.xyz>2026-09-17 09:00:40 +0200
commite6c5c5e6443345e019549d8b41ffa0c19d050c9f (patch)
tree3ccb4be91e079954086ddb8835d21ecc86716663 /lib
parente9dd31b04324d9a95acf6561a4b6ebcee9d3b8c0 (diff)
downloadconky-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')
-rw-r--r--lib/weather.lua41
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