+++ /dev/null
-
---[[
-
- Licensed under GNU General Public License v2
- * (c) 2015, worron
- * (c) 2013, Alexander Yakushev
-
---]]
-
--- Asynchronous io.popen for Awesome WM.
--- How to use:
--- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
-
--- Grab environment
-local awful = require('awful')
-
--- Avoid discrepancies across multiple shells
-awful.util.shell = '/bin/sh'
-
--- Initialize tables for module
-asyncshell = { request_table = {}, id_counter = 0 }
-
--- Request counter
-local function next_id()
- asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000
- return asyncshell.id_counter
-end
-
--- Remove given request
-function asyncshell.clear(id)
- if asyncshell.request_table[id] then
- if asyncshell.request_table[id].timer then
- asyncshell.request_table[id].timer:stop()
- asyncshell.request_table[id].timer = nil
- end
- asyncshell.request_table[id] = nil
- end
-end
-
--- Sends an asynchronous request for an output of the shell command
--- @param command Command to be executed and taken output from
--- @param callback Function to be called when the command finishes
--- @param timeout Maximum amount of time to wait for the result (optional)
-function asyncshell.request(command, callback, timeout)
- local id = next_id()
- asyncshell.request_table[id] = { callback = callback }
-
- local formatted_command = string.gsub(command, '"','\"')
-
- local req = string.format(
- "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &",
- id, formatted_command
- )
-
- if type(awful.spawn) == 'table' and awful.spawn.with_shell then
- awful.spawn.with_shell(req)
- else
- awful.util.spawn_with_shell(req)
- end
-
- if timeout then
- asyncshell.request_table[id].timer = timer({ timeout = timeout })
- asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end)
- asyncshell.request_table[id].timer:start()
- end
-end
-
--- Calls the remembered callback function on the output of the shell command
--- @param id Request ID
--- @param output Shell command output to be delievered
-function asyncshell.deliver(id, output)
- local output = string.sub(output, 2, -2)
- if asyncshell.request_table[id] then
- asyncshell.request_table[id].callback(output)
- asyncshell.clear(id)
- end
-end
-
-return asyncshell
--]]
-local debug = require("debug")
-local assert = assert
-local capi = { timer = require("gears.timer") }
-local io = { open = io.open,
- lines = io.lines,
- popen = io.popen }
-local rawget = rawget
-local table = { sort = table.sort }
+local debug = require("debug")
+local io = { lines = io.lines,
+ open = io.open,
+ popen = io.popen }
+local rawget = rawget
+local table = { sort = table.sort }
-local wibox = require("wibox")
+local easy_async = require("awful.spawn").easy_async
+local timer = require("gears.timer")
+local wibox = require("wibox")
-- Lain helper functions for internal use
-- lain.helpers
function helpers.newtimer(_name, timeout, fun, nostart)
local name = timeout
if not helpers.timer_table[name] then
- helpers.timer_table[name] = capi.timer({ timeout = timeout })
+ helpers.timer_table[name] = timer({ timeout = timeout })
helpers.timer_table[name]:start()
end
helpers.timer_table[name]:connect_signal("timeout", fun)
-- {{{ Pipe operations
--- read the full output of a command output
+-- return the full output of an input command (synchronous pipe)
+-- @param cmd the input command
+-- @return command output (string)
function helpers.read_pipe(cmd)
- local f = assert(io.popen(cmd))
+ local f = io.popen(cmd)
local output = f:read("*all")
f:close()
return output
end
--- return line iterator of a command output
-function helpers.pipelines(...)
- local f = assert(io.popen(...))
- return function () -- iterator
- local data = f:read()
- if data == nil then f:close() end
- return data
- end
+-- run a command and execute a function on its output (asynchronous pipe)
+-- @param cmd the input command
+-- @param callback function to execute on cmd output
+-- @return cmd PID
+function helpers.async(cmd, callback)
+ return easy_async(cmd,
+ function (stdout, stderr, reason, exit_code)
+ callback(stdout)
+ end)
end
-- }}}
--]]
-local newtimer = require("lain.helpers").newtimer
-local async = require("lain.asyncshell")
+local helpers = require("lain.helpers")
local wibox = require("wibox")
-
local setmetatable = setmetatable
-- Basic template for custom widgets (asynchronous version)
local cmd = args.cmd or ""
local settings = args.settings or function() end
- abase.widget = wibox.widget.textbox('')
+ abase.widget = wibox.widget.textbox()
function abase.update()
- async.request(cmd, function(f)
+ helpers.async(cmd, function(f)
output = f
if output ~= abase.prev then
widget = abase.widget
end)
end
- newtimer(cmd, timeout, abase.update)
+ helpers.newtimer(cmd, timeout, abase.update)
return setmetatable(abase, { __index = abase.widget })
end
--]]
local helpers = require("lain.helpers")
-local read_pipe = require("lain.helpers").read_pipe
-
local wibox = require("wibox")
-
local string = { match = string.match,
format = string.format }
-
local setmetatable = setmetatable
-- ALSA volume
local timeout = args.timeout or 5
local settings = args.settings or function() end
- alsa.cmd = args.cmd or "amixer"
- alsa.channel = args.channel or "Master"
- alsa.togglechannel = args.togglechannel
- alsa.last_level = "0"
- alsa.last_status = ""
+ alsa.cmd = args.cmd or "amixer"
+ alsa.channel = args.channel or "Master"
+ alsa.last = {}
function alsa.update()
- mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
- l, s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-
- -- HDMIs can have a channel different from Master for toggling mute
- if alsa.togglechannel then
- s = string.match(read_pipe(string.format("%s get %s", alsa.cmd, alsa.togglechannel)), "%[(%a+)%]")
- end
-
- if alsa.last_level ~= l or alsa.last_status ~= s then
- volume_now = { level = l, status = s }
- alsa.last_level = l
- alsa.last_status = s
-
- widget = alsa.widget
- settings()
- end
+ helpers.async(alsa.cmd, function(mixer)
+ local l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+ if alsa.last.level ~= l or alsa.last.status ~= s then
+ volume_now = { level = l, status = s }
+ widget = alsa.widget
+ settings()
+ alsa.last = volume_now
+ end
+ end)
end
timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel)
--]]
-local newtimer = require("lain.helpers").newtimer
-local read_pipe = require("lain.helpers").read_pipe
+local helpers = require("lain.helpers")
local awful = require("awful")
local beautiful = require("beautiful")
unmute = "#A4CE8A"
},
- terminal = terminal or "xterm",
- mixer = string.format("%s -e alsamixer", terminal),
-
notifications = {
font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
font_size = "11",
_muted = false
}
-function alsabar.notify()
- alsabar.update()
-
- local preset = {
- title = "",
- text = "",
- timeout = 5,
- screen = alsabar.notifications.screen,
- font = string.format("%s %s", alsabar.notifications.font,
- alsabar.notifications.font_size),
- fg = alsabar.notifications.color
- }
-
- if alsabar._muted
- then
- preset.title = string.format("%s - Muted", alsabar.channel)
- else
- preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
- end
-
- int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
- preset.text = string.format("[%s%s]", string.rep("|", int),
- string.rep(" ", awful.screen.focused().mywibox.height - int))
-
- if alsabar.followtag then
- preset.screen = awful.screen.focused()
- end
-
- if alsabar._notify ~= nil then
- alsabar._notify = naughty.notify ({
- replaces_id = alsabar._notify.id,
- preset = preset,
- })
- else
- alsabar._notify = naughty.notify ({
- preset = preset,
- })
- end
-end
-
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
alsabar.cmd = args.cmd or "amixer"
alsabar.channel = args.channel or alsabar.channel
- alsabar.togglechannel = args.togglechannel
alsabar.step = args.step or alsabar.step
alsabar.colors = args.colors or alsabar.colors
alsabar.notifications = args.notifications or alsabar.notifications
alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
- function alsabar.update()
- -- Get mixer control contents
- local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel))
-
- -- Capture mixer control state: [5%] ... ... [on]
- local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-
- -- HDMIs can have a channel different from Master for toggling mute
- if alsabar.togglechannel then
- mute = string.match(read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.togglechannel)), "%[(%a+)%]")
- end
-
- if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
- then
- alsabar._current_level = tonumber(volu) or alsabar._current_level
- alsabar.bar:set_value(alsabar._current_level / 100)
- if (not mute and tonumber(volu) == 0) or mute == "off"
+ function alsabar.update(callback)
+ helpers.async(alsabar.cmd, function(mixer)
+ local volu,mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+ if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
then
- alsabar._muted = true
- alsabar.tooltip:set_text ("[Muted]")
- alsabar.bar.color = alsabar.colors.mute
+ alsabar._current_level = tonumber(volu) or alsabar._current_level
+ alsabar.bar:set_value(alsabar._current_level / 100)
+ if (not mute and tonumber(volu) == 0) or mute == "off"
+ then
+ alsabar._muted = true
+ alsabar.tooltip:set_text ("[Muted]")
+ alsabar.bar.color = alsabar.colors.mute
+ else
+ alsabar._muted = false
+ alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
+ alsabar.bar.color = alsabar.colors.unmute
+ end
+
+ volume_now = {}
+ volume_now.level = tonumber(volu)
+ volume_now.status = mute
+
+ settings()
+
+ if callback then callback() end
+ end
+ end)
+ end
+
+ function alsabar.notify()
+ alsabar.update(function()
+ local preset = {
+ title = "",
+ text = "",
+ timeout = 5,
+ screen = alsabar.notifications.screen,
+ font = string.format("%s %s", alsabar.notifications.font,
+ alsabar.notifications.font_size),
+ fg = alsabar.notifications.color
+ }
+
+ if alsabar._muted then
+ preset.title = string.format("%s - Muted", alsabar.channel)
else
- alsabar._muted = false
- alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
- alsabar.bar.color = alsabar.colors.unmute
+ preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
end
- volume_now = {}
- volume_now.level = tonumber(volu)
- volume_now.status = mute
+ int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
+ preset.text = string.format("[%s%s]", string.rep("|", int),
+ string.rep(" ", awful.screen.focused().mywibox.height - int))
- settings()
- end
- end
+ if alsabar.followtag then preset.screen = awful.screen.focused() end
- alsabar.bar:buttons(awful.util.table.join (
- awful.button({}, 1, function()
- awful.util.spawn(alsabar.mixer)
- end),
- awful.button({}, 2, function()
- awful.util.spawn(string.format("%s set %s 100%%", alsabar.cmd, alsabar.channel))
- alsabar.update()
- end),
- awful.button({}, 3, function()
- awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.togglechannel or alsabar.channel))
- alsabar.update()
- end),
- awful.button({}, 4, function()
- awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
- alsabar.update()
- end),
- awful.button({}, 5, function()
- awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
- alsabar.update()
- end)
- ))
+ if alsabar._notify then
+ alsabar._notify = naughty.notify ({
+ replaces_id = alsabar._notify.id,
+ preset = preset,
+ })
+ else
+ alsabar._notify = naughty.notify ({ preset = preset })
+ end
+ end)
+ end
timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel)
-
- newtimer(timer_id, timeout, alsabar.update)
+ helpers.newtimer(timer_id, timeout, alsabar.update)
return alsabar
end
function gpmdp.update()
local filelines = helpers.lines_from(file_location)
- if not next(filelines)
- then
+ if not next(filelines) then
local gpm_now = { running = false, playing = false }
else
dict, pos, err = json.decode(table.concat(filelines), 1, nil)
widget = gpmdp.widget
settings()
- if gpm_now.playing
- then
- if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current")
- then
+ if gpm_now.playing then
+ if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current") then
helpers.set_map("gpmdp_current", gpm_now.title)
os.execute(string.format("curl %d -o /tmp/gpmcover.png", gpm_now.cover_url))
- if followtag then
- gpmdp_notification_preset.screen = focused()
- end
+ if followtag then gpmdp_notification_preset.screen = focused() end
gpmdp.id = naughty.notify({
preset = gpmdp_notification_preset,
local function run_settings(layout, variant)
widget = kbdlayout.widget
- kbdlayout_now = { layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
- variant=variant }
+ kbdlayout_now = {
+ layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
+ variant=variant
+ }
settings()
end
--]]
-local helpers = require("lain.helpers")
-local async = require("lain.asyncshell")
+local helpers = require("lain.helpers")
-local focused = require("awful.screen").focused
-local escape_f = require("awful.util").escape
-local naughty = require("naughty")
-local wibox = require("wibox")
+local shell = require("awful.util").shell
+local focused = require("awful.screen").focused
+local escape_f = require("awful.util").escape
+local naughty = require("naughty")
+local wibox = require("wibox")
-local io = { popen = io.popen }
-local os = { execute = os.execute,
- getenv = os.getenv }
-local string = { format = string.format,
- gmatch = string.gmatch }
+local os = { getenv = os.getenv }
+local string = { format = string.format,
+ gmatch = string.gmatch }
local setmetatable = setmetatable
-- MOC audio player
-- lain.widgets.contrib.moc
-local moc = {}
+local moc = helpers.make_widget_textbox()
local function worker(args)
- local args = args or {}
- local timeout = args.timeout or 2
- local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
- local cover_size = args.cover_size or 100
- local default_art = args.default_art or ""
- local followtag = args.followtag or false
- local settings = args.settings or function() end
+ local args = args or {}
+ local timeout = args.timeout or 2
+ local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
+ local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
+ local cover_size = args.cover_size or 100
+ local default_art = args.default_art or ""
+ local followtag = args.followtag or false
+ local settings = args.settings or function() end
- local mpdcover = helpers.scripts_dir .. "mpdcover"
-
- moc.widget = wibox.widget.textbox('')
-
- moc_notification_preset = {
- title = "Now playing",
- timeout = 6
- }
+ moc_notification_preset = { title = "Now playing", timeout = 6 }
helpers.set_map("current moc track", nil)
function moc.update()
- -- mocp -i will produce output like:
- -- Artist: Travis
- -- Album: The Man Who
- -- etc.
- async.request("mocp -i", function(f)
+ helpers.async("mocp -i", function(f)
moc_now = {
state = "N/A",
file = "N/A",
for line in string.gmatch(f, "[^\n]+") do
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
- if k == "State" then moc_now.state = v
- elseif k == "File" then moc_now.file = v
- elseif k == "Artist" then moc_now.artist = escape_f(v)
- elseif k == "SongTitle" then moc_now.title = escape_f(v)
- elseif k == "Album" then moc_now.album = escape_f(v)
+ if k == "State" then moc_now.state = v
+ elseif k == "File" then moc_now.file = v
+ elseif k == "Artist" then moc_now.artist = escape_f(v)
+ elseif k == "SongTitle" then moc_now.title = escape_f(v)
+ elseif k == "Album" then moc_now.album = escape_f(v)
elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v)
- elseif k == "TotalTime" then moc_now.total = escape_f(v)
+ elseif k == "TotalTime" then moc_now.total = escape_f(v)
end
end
end
if moc_now.state == "PLAY" then
if moc_now.title ~= helpers.get_map("current moc track") then
helpers.set_map("current moc track", moc_now.title)
- os.execute(string.format("%s %q %q %d %q", mpdcover, "",
- moc_now.file, cover_size, default_art))
- if followtag then
- moc_notification_preset.screen = focused()
- end
+ if followtag then moc_notification_preset.screen = focused() end
- moc.id = naughty.notify({
- preset = moc_notification_preset,
- icon = "/tmp/mpdcover.png",
+ local common = {
+ preset = moc_notification_preset,
+ icon = default_art,
+ icon_size = cover_size,
replaces_id = moc.id,
- }).id
+ }
+
+ local path = string.format("%s/%s", music_dir, string.match(moc_now.file, ".*/"))
+ local cover = string.format("%s -c \"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'\"", shell, path, cover_pattern)
+ helpers.async(cover, function(current_icon)
+ common.icon = current_icon:gsub("\n", "")
+ moc.id = naughty.notify(common).id
+ end)
end
elseif moc_now.state ~= "PAUSE" then
helpers.set_map("current moc track", nil)
local beautiful = require("beautiful")
local naughty = require("naughty")
-local mouse = mouse
local io = io
local string = { len = string.len }
local tonumber = tonumber
--]]
local helpers = require("lain.helpers")
-local async = require("lain.asyncshell")
local naughty = require("naughty")
local wibox = require("wibox")
curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%q %s -k",
head_command, server, port, mail, password, request)
- async.request(curl, function(f)
+ helpers.async(curl, function(f)
_, mailcount = string.gsub(f, "%d+", "")
- _ = nil
widget = imap.widget
settings()
- if mailcount >= 1 and mailcount > helpers.get_map(mail)
- then
+ if mailcount >= 1 and mailcount > helpers.get_map(mail) then
if mailcount == 1 then
nt = mail .. " has one new message"
else
nt = mail .. " has <b>" .. mailcount .. "</b> new messages"
end
- naughty.notify({
- preset = mail_notification_preset,
- text = nt
- })
+ naughty.notify({ preset = mail_notification_preset, text = nt })
end
helpers.set_map(mail, mailcount)
--]]
-local async = require("lain.asyncshell")
local helpers = require("lain.helpers")
+local shell = require("awful.util").shell
local escape_f = require("awful.util").escape
local focused = require("awful.screen").focused
local naughty = require("naughty")
local function worker(args)
local args = args or {}
local timeout = args.timeout or 2
- local password = args.password or ""
+ local password = (args.password and #args.password > 0 and string.format("password %s\\n", args.password)) or ""
local host = args.host or "127.0.0.1"
local port = args.port or "6600"
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
local default_art = args.default_art or ""
local notify = args.notify or "on"
local followtag = args.followtag or false
- local echo_cmd = args.echo_cmd or "echo"
local settings = args.settings or function() end
local mpdh = string.format("telnet://%s:%s", host, port)
- local echo = string.format("%s 'password %s\nstatus\ncurrentsong\nclose'", echo_cmd, password)
+ local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password)
+ local cmd = string.format("%s -c '%s | curl --connect-timeout 1 -fsm 3 %s'", shell, echo, mpdh)
- mpd_notification_preset = {
- title = "Now playing",
- timeout = 6
- }
+ mpd_notification_preset = { title = "Now playing", timeout = 6 }
helpers.set_map("current mpd track", nil)
function mpd.update()
- async.request(string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh), function (f)
+ helpers.async(cmd, function(f)
mpd_now = {
random_mode = false,
single_mode = false,
if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track") then
helpers.set_map("current mpd track", mpd_now.title)
- local current icon = default_art
-
- if not string.match(mpd_now.file, "http.*://") then -- local file instead of http stream
- local path = string.format("%s/%s", music_dir, string.match(mpd_now.file, ".*/"))
- local cover = string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", path, cover_pattern)
- current_icon = helpers.read_pipe(cover):gsub("\n", "")
- end
-
if followtag then mpd_notification_preset.screen = focused() end
- mpd.id = naughty.notify({
+ local common = {
preset = mpd_notification_preset,
- icon = current_icon,
+ icon = default_art,
icon_size = cover_size,
replaces_id = mpd.id,
- }).id
+ }
+
+ if not string.match(mpd_now.file, "http.*://") then -- local file instead of http stream
+ local path = string.format("%s/%s", music_dir, string.match(mpd_now.file, ".*/"))
+ local cover = string.format("%s -c \"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'\"", shell, path, cover_pattern)
+ helpers.async(cover, function(current_icon)
+ common.icon = current_icon:gsub("\n", "")
+ mpd.id = naughty.notify(common).id
+ end)
+ else
+ mpd.id = naughty.notify(common).id
+ end
+
end
elseif mpd_now.state ~= "pause" then
helpers.set_map("current mpd track", nil)
--]]
+local async = require("lain.helpers").async
local newtimer = require("lain.helpers").newtimer
-local read_pipe = require("lain.helpers").read_pipe
-
-local async = require("lain.asyncshell")
-local json = require("lain.util").dkjson
local lain_icons = require("lain.helpers").icons_dir
+local json = require("lain.util").dkjson
local focused = require("awful.screen").focused
local naughty = require("naughty")
local notification_preset = args.notification_preset or {}
local notification_text_fun = args.notification_text_fun or
function (wn)
- local day = string.gsub(read_pipe(string.format(date_cmd, wn["dt"])), "\n", "")
+ local day = os.date("%a %d", wn["dt"])
local tmin = math.floor(wn["temp"]["min"])
local tmax = math.floor(wn["temp"]["max"])
local desc = wn["weather"][1]["description"]
return string.format("<b>%s</b>: %s, %d - %d ", day, desc, tmin, tmax)
end
local weather_na_markup = args.weather_na_markup or " N/A "
- local followtag = args.followtag or false
+ local followtag = args.followtag or false
local settings = args.settings or function() end
weather.widget = wibox.widget.textbox(weather_na_markup)
function weather.forecast_update()
local cmd = string.format(forecast_call, city_id, units, lang, cnt, APPID)
- async.request(cmd, function(f)
+ async(cmd, function(f)
local pos, err
weather_now, pos, err = json.decode(f, 1, nil)
function weather.update()
local cmd = string.format(current_call, city_id, units, lang, APPID)
- async.request(cmd, function(f)
+ async(cmd, function(f)
local pos, err, icon
weather_now, pos, err = json.decode(f, 1, nil)
local sunrise = tonumber(weather_now["sys"]["sunrise"])
local sunset = tonumber(weather_now["sys"]["sunset"])
local icon = weather_now["weather"][1]["icon"]
- local utc_m = string.gsub(read_pipe(string.format("date -u -d 'today 00:00:00' +'%%s'")), "\n", "")
- local loc_m = string.gsub(read_pipe(string.format("date -d 'today 00:00:00' +'%%s'")), "\n", "")
-
- loc_m = tonumber(loc_m)
- utc_m = tonumber(utc_m)
- offset = utc_offset()
+ local loc_m = os.time { year = os.date("%Y"), month = os.date("%m"), day = os.date("%d"), hour = 0 }
+ local offset = utc_offset()
+ local utc_m = loc_m + offset
-- if we are 1 day after the GMT, return 1 day back, and viceversa
if offset > 0 and loc_m >= utc_m then
-Subproject commit cf17caf2b889d58d4f00a47cd168f53ae85b6d9f
+Subproject commit fd369119050a6674c7bb4ef3b2b1d6c6dbdecb83