To prepare myself for the transition to lua and practice some syntax along the way (and maybe out of boredom), I recently decided to implement a simple link-preview widget using the Open Graph protocol properties found in many websites.
My code consists of two functions:
og.fetch
, wich extracts tags and their properties from a website
and og.card
, wich uses the data returned by og.fetch
to display an info card in plain html.
Some examples:
${og.card("https://xkcd.com/1272/", 300)}
${og.card("https://medium.com/@TeddyYeung/what-is-open-graph-f3abadd7d1f9", 300)}
${og.card("https://www.youtube.com/watch?v=0FBxnKxxMhU", 300)}
This is my first time writing lua and I’m sure there’s lots of room for improvement, but at least it’s self-contained and works (so far xD).
space-lua:
og = {}
function og.fetch(url)
local function extract_prop(header, prop_name)
local prop_start, prop_end = string.find(header, 'og:'..prop_name..'" content="[^"]+"/?>')
local prop = string.sub(header, prop_start, prop_end)
local tag_closer_length = 0
if string.find(prop, "/>") == nil then
-- <tag prop="value">
tag_closer_length = 2
else
-- <tag prop="value"/>
tag_closer_length = 3
end
return string.sub(prop, 15 + string.len(prop_name), prop_end - prop_start - tag_closer_length)
end
local response = http.request(url)
if response.ok then
local body = response.body
local head_start, _ = string.find(body, "<head>")
local head_end, _ = string.find(body, "</head>")
local header = string.sub(body, head_start, head_end)
local title = extract_prop(header, "title")
local url = extract_prop(header, "url")
local image = extract_prop(header, "image")
-- description and site_name are optional properties, might return nil/""
local description = extract_prop(header, "description")
local sitename = extract_prop(header, "site_name")
return {title = title, url = url, image = image, description = description, sitename = sitename}
else
return "Error: got status code "..response.status
end
end
function og.card(url, width)
local og_data = og.fetch(url)
return {
html = "<div style='background-color:rgba(0,0,0,0.15);padding:10px;border-radius:5px;display:flex;flex-direction:column;align-items:space-evenly;width:"..width.."px;'><span class='sb-sub'>"..og_data.sitename.."</span><a href = '"..og_data.url.."'><b>"..og_data.title.."</b></a>"..og_data.description.."<img src='"..og_data.image.."' style='margin-top:10px;'/></div>"
}
end
Open for any feedback!