]> git.madduck.net Git - etc/awesome.git/blob - widgets/yawn/init.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Initial commit
[etc/awesome.git] / widgets / yawn / init.lua
1
2 --[[
3                                                
4      Yahoo's Awesome (WM) Weather Notification 
5                                                
6      Licensed under WTFPL v2                   
7       * (c) 2013, Luke Bonham                  
8                                                
9 --]]
10
11 local markup       = require("lain.util.markup")
12
13 local beautiful    = require("beautiful")
14 local naughty      = require("naughty")
15 local wibox        = require("wibox")
16
17 local debug        = { getinfo = debug.getinfo }
18 local io           = io
19 local os           = { date    = os.date,
20                        getenv  = os.getenv }
21 local string       = { find    = string.find,
22                        match   = string.match,
23                        gsub    = string.gsub,
24                        sub     = string.sub }
25 local tonumber     = tonumber
26
27 local setmetatable = setmetatable
28
29 -- yawn integration
30 -- https://github.com/copycat-killer/yawn
31 -- lain.widgets.yawn
32 local yawn =
33 {
34     units    = "",
35     forecast = "",
36     icon     = wibox.widget.imagebox(),
37     widget   = wibox.widget.textbox()
38 }
39
40 local project_path       = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
41 local localizations_path = project_path .. 'localizations/'
42 local icon_path          = project_path .. 'icons/'
43 local api_url            = 'http://weather.yahooapis.com/forecastrss'
44 local units_set          = '?u=c&w=' -- Default is Celsius
45 local language           = string.match(os.getenv("LANG"), "(%S*$*)[.]")
46 local weather_data       = nil
47 local notification       = nil
48 local city_id            = nil
49 local sky                = nil
50 local settings           = {}
51 local update_timer       = nil
52
53 local function fetch_weather(args)
54     local toshow = args.toshow or "forecast"
55     local spr = args.spr or " "
56     local footer = args.footer or ""
57
58     local url = api_url .. units_set .. city_id
59     local f = io.popen("curl --connect-timeout 1 -fsm 2 '"
60                        .. url .. "'" )
61     local text = f:read("*all")
62     io.close(f)
63
64     -- In case of no connection or invalid city ID
65     -- widgets won't display
66     if text == "" or text:match("City not found")
67     then
68         sky = icon_path .. "na.png"
69         if text == "" then
70             weather_data = "Service not available at the moment."
71             return "N/A"
72         else
73             weather_data = "City not found!\n" ..
74                            "Are you sure " .. city_id ..
75                            " is your Yahoo city ID?"
76             return "?"
77         end
78     end
79
80     -- Processing raw data
81     weather_data = text:gsub("<.->", "")
82     weather_data = weather_data:match("Current Conditions:.-Full")
83     weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ")
84     weather_data = weather_data:gsub("Forecast:.-\n", "")
85     weather_data = weather_data:gsub("\nFull", "")
86     weather_data = weather_data:gsub("[\n]$", "")
87     weather_data = weather_data:gsub(" [-] " , ": ")
88     weather_data = weather_data:gsub("[.]", ",")
89     weather_data = weather_data:gsub("High: ", "")
90     weather_data = weather_data:gsub(" Low: ", " - ")
91
92     -- Getting info for text widget
93     local now      = weather_data:sub(weather_data:find("Now:")+5,
94                      weather_data:find("\n")-1)
95     local forecast = now:sub(1, now:find(",")-1)
96     local units    = now:sub(now:find(",")+2, -2)
97
98     -- Day/Night icon change
99     local hour = tonumber(os.date("%H"))
100     sky = icon_path
101
102     if forecast == "Clear"         or
103        forecast == "Fair"          or
104        forecast == "Partly Cloudy" or
105        forecast == "Mostly Cloudy"
106        then
107            if hour >= 6 and hour <= 18
108            then
109                sky = sky .. "Day"
110            else
111                sky = sky .. "Night"
112            end
113     end
114
115     sky = sky  .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
116
117     -- In case there's no defined icon for current forecast
118     f = io.popen(sky)
119     if f == nil then
120         sky = icon_path .. "na.png"
121     else
122         io.close(f)
123     end
124
125     -- Localization
126     local f = io.open(localizations_path .. language, "r")
127     if language:find("en_") == nil and f ~= nil
128     then
129         io.close(f)
130         for line in io.lines(localizations_path .. language)
131         do
132             word = string.sub(line, 1, line:find("|")-1)
133             translation = string.sub(line, line:find("|")+1)
134             weather_data = string.gsub(weather_data, word, translation)
135         end
136     end
137
138     -- Finally setting infos
139     forecast = weather_data:match(": %S+"):gsub(": ", ""):gsub(",", "")
140     yawn.forecast = markup(yawn.forecast_color, markup.font(beautiful.font, forecast))
141     yawn.units = markup(yawn.units_color, markup.font(beautiful.font, units))
142     yawn.icon:set_image(sky)
143
144     if toshow == "forecast" then
145         return yawn.forecast
146     elseif toshow == "units" then
147         return yawn.units
148     else -- "both"
149         return yawn.forecast .. spr
150                .. yawn.units .. footer
151     end
152 end
153
154 function yawn.hide()
155     if notification ~= nil then
156         naughty.destroy(notification)
157         notification = nil
158     end
159 end
160
161 function yawn.show(t_out)
162     if yawn.widget._layout.text == "?"
163     then
164         if update_timer ~= nil
165         then
166             update_timer:emit_signal("timeout")
167         else
168             fetch_weather(settings)
169         end
170     end
171
172     yawn.hide()
173
174     notification = naughty.notify({
175         text = weather_data,
176         icon = sky,
177         timeout = t_out,
178         fg = yawn.notification_color
179     })
180 end
181
182 function yawn.register(id, args)
183     local args = args or {}
184
185     settings = { args.toshow, args.spr, args.footer }
186
187     yawn.units_color        = args.units_color or
188                               beautiful.fg_normal or "#FFFFFF"
189     yawn.forecast_color     = args.forecast_color or
190                               yawn.units_color
191     yawn.notification_color = args.notification_color or
192                               beautiful.fg_focus or "#FFFFFF"
193
194     if args.u == "f" then units_set = '?u=f&w=' end
195
196     city_id = id
197
198     update_timer = timer({ timeout = 600 }) -- 10 mins
199     update_timer:connect_signal("timeout", function()
200         yawn.widget:set_markup(fetch_weather(settings))
201     end)
202     update_timer:start()
203     update_timer:emit_signal("timeout")
204
205     yawn.icon:connect_signal("mouse::enter", function()
206         yawn.show(0)
207     end)
208     yawn.icon:connect_signal("mouse::leave", function()
209         yawn.hide()
210     end)
211 end
212
213 function yawn.attach(widget, id, args)
214     yawn.register(id, args)
215
216     widget:connect_signal("mouse::enter", function()
217         yawn.show(0)
218     end)
219
220     widget:connect_signal("mouse::leave", function()
221         yawn.hide()
222     end)
223 end
224
225 -- }}}
226
227 return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end })