Skip to content

Instantly share code, notes, and snippets.

@folknor
Last active February 27, 2021 22:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save folknor/32f703b270c6ad72bc12d98feb2f7034 to your computer and use it in GitHub Desktop.
Save folknor/32f703b270c6ad72bc12d98feb2f7034 to your computer and use it in GitHub Desktop.
Firefox Release Checker using RSS Feed
#!/usr/bin/lua
local xml2lua = require("xml2lua") -- Just fail early if these dont exist
local handler = require("xmlhandler.tree")
-- Requires either curl, lua-curl or luasec later
-- Uses either notify-send if available or prints new releases to stdout
local DEBUG = false
local VERSION = 20210229
local RSSURL = "https://hg.mozilla.org/mozilla-unified/rss-tags"
local NOTIFY_TITLE = "New Firefox Release"
local NOTIFY_TEXT = "Firefox %s was released on %s."
local function helpExit(err)
if err then print("Error: " .. tostring(err)) end
print(([[
Firefox release notifier script version %d
]]):format(VERSION))
os.exit()
end
local function perhaps(...) local s, l = pcall(require, ...) if s then return l end end
local _ = function(s) if type(s) ~= "nil" then return tostring(s) end end
local notify
local fetch = DEBUG and (function() local f = io.open("rssdump", "r"); local c = f:read("*a"); f:close(); return c end) or nil
local which
local sh = perhaps("sh")
if type(sh) == "table" and type(sh.fork) == "string" and sh.fork == "folknor" and sh.version >= 4 then
if not which then which = function(c) return sh._(("which " .. tostring(c))).__exitcode == 0 end end
if not notify and which("notify-send") then
notify = function(t, m) sh._(("notify-send -i firefox %q %q"):format(t, m)) end
end
if not fetch and which("curl") then
fetch = function(url) return _(sh.command("curl")("-s", url)) end
end
end
if not which then
which = function(c)
local h = io.popen("which " .. tostring(c))
local r = h:read("*a"); h:close()
return #r > 0
end
end
if not notify then
if which("notify-send") then
notify = function(t, m) os.execute(("notify-send -i firefox %q %q"):format(t, m)) end
else
notify = function(t, m) print("[" .. tostring(t) .. "][" .. tostring(m) .. "]") end
end
end
if not fetch then
local sec = perhaps("ssl.https")
if type(sec) == "table" then
fetch = function(url)
local res, code = sec.request(url)
if code == 200 then return res end
end
else
local curl = perhaps("lcurl")
if type(curl) == "table" then
fetch = function(url)
local raw = ""
local easy = curl.easy({
url = url,
writefunction = function(inc)
raw = raw .. inc
return true
end
})
easy:perform()
easy:close()
return raw
end
end
end
end
if not fetch then helpExit("Can't fetch.") end
local versionMt = {
__eq = function(self, other) return self[1] == other[1] and self[2] == other[2] and self[3] == other[3] end,
__lt = function(self, other)
if self[1] ~= other[1] then return self[1] < other[1] end
if self[2] ~= other[2] then return self[2] < other[2] end
return self[3] < other[3]
end,
__tostring = function(self) return ("%d.%d.%d"):format(unpack(self)) end,
}
local function parseVersion(...)
local v = {...}
if select("#", ...) == 1 then
v[1], v[2], v[3] = tostring((select(1, ...))):match("^(%d+)%.?(%d*)%.?(%d*)")
end
v[1], v[2], v[3] = tonumber(v[1]) or 0, tonumber(v[2]) or 0, tonumber(v[3]) or 0
if v[1] == 0 then return false end
return setmetatable(v, versionMt)
end
local lN -- last notified
do
local f = io.open("notified", "r")
lN = parseVersion(f:read("*a"))
f:close()
end
local content = fetch(RSSURL)
if type(content) ~= "string" then helpExit("Unable to fetch " .. RSSURL) end
local parser = xml2lua.parser(handler)
parser:parse(content)
for i, ev in next, handler.root.rss.channel.item do
if ( ev.title:find("^FIREFOX%_") and ev.title:find("%_RELEASE$") ) then
local sv = parseVersion(ev.title:match("^FIREFOX%_(%d+)%_?(%d*)%_?(%d*)%_?RELEASE$"))
if sv and sv > lN then
notify(NOTIFY_TITLE:format(tostring(sv)), NOTIFY_TEXT:format(tostring(sv), tostring(ev.pubDate)))
if not DEBUG then
lN = sv
local f = io.open("notified", "w+")
f:write(tostring(lN))
f:close()
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment