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

Merge branch 'master' of https://github.com/copycat-killer/lain
[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           = { lines   = io.lines,
17                        open    = io.open }
18 local os           = { date    = os.date,
19                        getenv  = os.getenv }
20 local string       = { find    = string.find,
21                        match   = string.match,
22                        gsub    = string.gsub,
23                        sub     = string.sub }
24 local tonumber     = tonumber
25
26 local setmetatable = setmetatable
27
28 -- YAhoo! Weather Notification
29 -- lain.widgets.yawn
30 local yawn =
31 {
32     icon   = wibox.widget.imagebox(),
33     widget = wibox.widget.textbox('')
34 }
35
36 local project_path        = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
37 local localizations_path  = project_path .. 'localizations/'
38 local icon_path           = project_path .. 'icons/'
39 local api_url             = 'http://weather.yahooapis.com/forecastrss'
40 local units_set           = '?u=c&w=' -- Default is Celsius
41 local language            = string.match(os.getenv("LANG"), "(%S*$*)[.]") or "en_US" -- if LANG is not set
42 local weather_data        = nil
43 local notification        = nil
44 local city_id             = nil
45 local sky                 = nil
46 local settings            = function() end
47
48 yawn_notification_preset  = {}
49
50 function yawn.fetch_weather()
51     local url = api_url .. units_set .. city_id
52     local cmd = "curl --connect-timeout 1 -fsm 3 '" .. url .. "'"
53
54     async.request(cmd, function(f)
55         local text = f:read("*a")
56         f:close()
57
58         -- In case of no connection or invalid city ID
59         -- widgets won't display
60         if text == "" or text:match("City not found")
61         then
62             yawn.icon:set_image(icon_path .. "na.png")
63             if text == "" then
64                 weather_data = "Service not available at the moment."
65                 yawn.widget:set_text(" N/A ")
66             else
67                 weather_data = "City not found!\n" ..
68                                "Are you sure " .. city_id ..
69                                " is your Yahoo city ID?"
70                 yawn.widget:set_text(" ? ")
71             end
72             return
73         end
74
75         -- Processing raw data
76         weather_data = text:gsub("<.->", "")
77         weather_data = weather_data:match("Current Conditions:.-Full") or ""
78
79         -- may still happens in case of bad connectivity
80         if weather_data == "" then
81             yawn.icon:set_image(icon_path .. "na.png")
82             yawn.widget:set_text(" ? ")
83             return
84         end
85
86         weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ")
87         weather_data = weather_data:gsub("Forecast:.-\n", "")
88         weather_data = weather_data:gsub("\nFull", "")
89         weather_data = weather_data:gsub("[\n]$", "")
90         weather_data = weather_data:gsub(" [-] " , ": ")
91         weather_data = weather_data:gsub("[.]", ",")
92         weather_data = weather_data:gsub("High: ", "")
93         weather_data = weather_data:gsub(" Low: ", " - ")
94
95         -- Getting info for text widget
96         local now      = weather_data:sub(weather_data:find("Now:")+5,
97                          weather_data:find("\n")-1)
98         forecast       = now:sub(1, now:find(",")-1)
99         units          = now:sub(now:find(",")+2, -2)
100
101         -- Day/Night icon change
102         local hour = tonumber(os.date("%H"))
103         sky = icon_path
104
105         if string.find(forecast, "Clear")         or
106            string.find(forecast, "Fair")          or
107            string.find(forecast, "Partly Cloudy") or
108            string.find(forecast, "Mostly Cloudy")
109            then
110                if hour >= 6 and hour <= 18
111                then
112                    sky = sky .. "Day"
113                else
114                    sky = sky .. "Night"
115                end
116         end
117
118         sky = sky  .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
119
120         -- In case there's no defined icon for current forecast
121         if io.open(sky) == nil then
122             sky = icon_path .. "na.png"
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             f:close()
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         yawn.icon:set_image(sky)
140         widget = yawn.widget
141
142         _data = weather_data:match(": %S.-,") or weather_data
143         forecast = _data:gsub(": ", ""):gsub(",", "")
144         units = units:gsub(" ", "")
145
146         settings()
147     end)
148 end
149
150 function yawn.hide()
151     if notification ~= nil then
152         naughty.destroy(notification)
153         notification = nil
154     end
155 end
156
157 function yawn.show(t_out)
158     if yawn.widget._layout.text:match("?")
159     then
160         yawn.fetch_weather()
161     end
162
163     yawn.hide()
164
165     notification = naughty.notify({
166         preset = yawn_notification_preset,
167         text = weather_data,
168         icon = sky,
169         timeout = t_out,
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, yawn.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 })