All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
4 Licensed under GNU General Public License v2
5 * (c) 2013, Luke Bonham
9 local markup = require("lain.util.markup")
11 local beautiful = require("beautiful")
12 local naughty = require("naughty")
13 local wibox = require("wibox")
15 local debug = { getinfo = debug.getinfo }
17 local os = { date = os.date,
19 local string = { find = string.find,
23 local tonumber = tonumber
25 local setmetatable = setmetatable
27 -- YAhoo! Weather Notification
33 icon = wibox.widget.imagebox(),
34 widget = wibox.widget.textbox()
37 local project_path = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
38 local localizations_path = project_path .. 'localizations/'
39 local icon_path = project_path .. 'icons/'
40 local api_url = 'http://weather.yahooapis.com/forecastrss'
41 local units_set = '?u=c&w=' -- Default is Celsius
42 local language = string.match(os.getenv("LANG"), "(%S*$*)[.]")
43 local weather_data = nil
44 local notification = nil
48 local update_timer = nil
50 local function fetch_weather(args)
51 local toshow = args.toshow or "forecast"
53 local url = api_url .. units_set .. city_id
54 local f = io.popen("curl --connect-timeout 1 -fsm 2 '"
56 local text = f:read("*all")
59 -- In case of no connection or invalid city ID
60 -- widgets won't display
61 if text == "" or text:match("City not found")
63 sky = icon_path .. "na.png"
64 yawn.icon:set_image(sky)
66 weather_data = "Service not available at the moment."
69 weather_data = "City not found!\n" ..
70 "Are you sure " .. city_id ..
71 " is your Yahoo city ID?"
76 -- Processing raw data
77 weather_data = text:gsub("<.->", "")
78 weather_data = weather_data:match("Current Conditions:.-Full")
79 weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ")
80 weather_data = weather_data:gsub("Forecast:.-\n", "")
81 weather_data = weather_data:gsub("\nFull", "")
82 weather_data = weather_data:gsub("[\n]$", "")
83 weather_data = weather_data:gsub(" [-] " , ": ")
84 weather_data = weather_data:gsub("[.]", ",")
85 weather_data = weather_data:gsub("High: ", "")
86 weather_data = weather_data:gsub(" Low: ", " - ")
88 -- Getting info for text widget
89 local now = weather_data:sub(weather_data:find("Now:")+5,
90 weather_data:find("\n")-1)
91 local forecast = now:sub(1, now:find(",")-1)
92 local units = now:sub(now:find(",")+2, -2)
94 -- Day/Night icon change
95 local hour = tonumber(os.date("%H"))
98 if forecast == "Clear" or
100 forecast == "Partly Cloudy" or
101 forecast == "Mostly Cloudy"
103 if hour >= 6 and hour <= 18
111 sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
113 -- In case there's no defined icon for current forecast
116 sky = icon_path .. "na.png"
122 local f = io.open(localizations_path .. language, "r")
123 if language:find("en_") == nil and f ~= nil
126 for line in io.lines(localizations_path .. language)
128 word = string.sub(line, 1, line:find("|")-1)
129 translation = string.sub(line, line:find("|")+1)
130 weather_data = string.gsub(weather_data, word, translation)
134 -- Finally setting infos
135 both = weather_data:match(": %S+.-\n"):gsub(": ", "")
136 forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n")
137 units = units:gsub(" ", "")
139 yawn.forecast = markup(yawn.color, " " .. markup.font(beautiful.font, forecast) .. " ")
140 yawn.units = markup(yawn.color, " " .. markup.font(beautiful.font, units))
141 yawn.icon:set_image(sky)
143 if toshow == "forecast" then
145 elseif toshow == "units" then
153 if notification ~= nil then
154 naughty.destroy(notification)
159 function yawn.show(t_out)
160 if yawn.widget._layout.text == "?"
162 if update_timer ~= nil
164 update_timer:emit_signal("timeout")
166 fetch_weather(settings)
172 notification = naughty.notify({
180 function yawn.register(id, args)
181 local args = args or {}
185 yawn.color = args.color or beautiful.fg_normal or "#FFFFFF"
187 if args.u == "f" then units_set = '?u=f&w=' end
191 update_timer = timer({ timeout = 600 }) -- 10 mins
192 update_timer:connect_signal("timeout", function()
193 yawn.widget:set_markup(fetch_weather(settings))
196 update_timer:emit_signal("timeout")
198 yawn.icon:connect_signal("mouse::enter", function()
201 yawn.icon:connect_signal("mouse::leave", function()
208 function yawn.attach(widget, id, args)
209 yawn.register(id, args)
211 widget:connect_signal("mouse::enter", function()
215 widget:connect_signal("mouse::leave", function()
222 return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end })