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

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