Last active
February 27, 2021 22:12
-
-
Save folknor/32f703b270c6ad72bc12d98feb2f7034 to your computer and use it in GitHub Desktop.
Firefox Release Checker using RSS Feed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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