]> 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:

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