summaryrefslogtreecommitdiff
path: root/lupin.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lupin.lua')
-rwxr-xr-xlupin.lua255
1 files changed, 222 insertions, 33 deletions
diff --git a/lupin.lua b/lupin.lua
index c2ba662..851830b 100755
--- a/lupin.lua
+++ b/lupin.lua
@@ -1,7 +1,72 @@
posix = require 'posix'
+json = require 'json'
+http = require 'lcurl'
+
+require 'tokyocabinet'
require 'corz'
-local function printf(...) print(string.format(...)) end
+CACHE = "/home/bie/tmp.db"
+
+cache = tokyocabinet.bdbnew()
+
+function oembed(endpoint, id)
+ cache:open(CACHE, cache.OWRITER + cache.OREADER)
+ local url = endpoint .. id
+ local cached = cache:get(id)
+ if cached then
+ local data = json.decode(cached)
+ cache:close()
+ return data.html
+ end
+
+ local body = ""
+ local result = http.easy{url=url, writefunction=function(s)
+ body = body .. s
+ end}:perform()
+ if result:getinfo(http.INFO_RESPONSE_CODE) == 200 then
+ cache:put(id, body)
+ cache:close()
+ local data = json.decode(body)
+ return data.html
+ else
+ return ("<b>Klarte ikke embedde %s :(</b>"):format(url)
+ end
+end
+
+function twitter(id)
+ return oembed("https://publish.twitter.com/oembed?url=", id)
+end
+
+function youtube(id)
+ return oembed("http://www.youtube.com/oembed?url=", id)
+end
+
+function soundcloud(id)
+ return oembed("https://soundcloud.com/oembed?format=json&url=", id)
+end
+
+function vimeo(id)
+ return oembed("https://developer.vimeo.com/apis/oembed.json?url=", id)
+end
+
+function twitch(id)
+ return oembed("https://api.twitch.tv/v4/oembed?url=", id)
+end
+
+function instagram(id)
+ return oembed("https://api.instagram.com/oembed?url=", id)
+end
+
+function flickr(id)
+ return oembed("https://www.flickr.com/services/oembed?url=", id)
+end
+
+function facebook(id)
+ return oembed("https://www.facebook.com/plugins/video/oembed.json?url=", id)
+end
+
+
+local function printf(...) io.write(string.format(...)) end
local function setfenv(fn, env)
local i = 1
@@ -15,76 +80,151 @@ local function setfenv(fn, env)
elseif not name then
break
end
-
i = i + 1
end
-
return fn
end
local html = {}
-function html.label(label)
- printf("<label>%s</label>", label)
+function html.print(...)
+ printf(...)
end
-function html.orz(k, v)
- printf("<img class='orz' data-name=%s src='%s' data-uri='/orz/'>", k, v)
- printf("<input name='%s' value='%s' type='hidden'>", k, v)
+function html.tag(tag, options)
+ options = options or {}
+ local text = options.text; options.text = nil
+ printf("<%s", tag)
+ for k, v in pairs(options) do
+ if v and v ~= "" then
+ printf(" %s='%s'", k, v)
+ else
+ printf(" %s", k)
+ end
+ end
+ printf(">")
+ if text then
+ printf(text or "")
+ printf("</%s>", tag)
+ end
+ printf("\n")
+end
+function html.label(options)
+ options.text = options.text or error("no text")
+ html.tag("label", options)
end
-function html.date(k, v, s)
- printf("<input type=date name=%s size=%s value='%s'>", k, s or 10, v or '')
+function html.orz(options)
+ if options.inline then
+ html.tag("a", { class = 'orz', text = 'orz'})
+ return
+ end
+ local n = options.name or "orz"
+ local v = options.value or "//:0"
+ local uri = options.uri or "/orz/"
+ html.tag('img', { class='orz', ['data-name']=n, src=v, ['data-uri']=uri})
+ html.tag('input', { name=n, value=v, type='hidden'})
+ html.tag('a', { class='orz', ['data-name']=n, ['data-uri']=uri, text='orz'})
+end
+function html.infobox(options)
+ html.print("<ul class=infobox>")
+ options.terms = options.terms or {}
+ options.terms[''] = ""
+ -- table.insert(options.terms, "")
+ local n = options.name or "info[]"
+ for k, v in ipairs(options.values) do
+ html.print("<li>")
+ local term, fact = v:match("^(.-)%s*:%s*(.-)$")
+ html.select(n, options.terms, term)
+ html.tag('input', { name=n, value=fact})
+ end
+ html.print("<li class=last>")
+ html.select(n, options.terms, "")
+ html.tag('input', { name=n })
+ html.print("</ul>")
end
-function html.text(k, v, s)
- printf("<input type=text name=%s size=%s value='%s'>", k, s or 18, v or '')
+function html.date(options)
+ local n = options.name or "date"
+ local s = options.size or 10
+ local v = options.value or ""
+ html.tag('input', { type='date', name=n, size=s, value=v})
end
-function html.hidden(k, v)
- printf("<input type=hidden name=%s value='%s'>", k, v)
+function html.text(options)
+ local n = options.name or "text"
+ local s = options.size or 18
+ local v = options.value or ""
+ html.tag("input", { type='text', name=n, size=s, value=v})
end
-function html.textarea(k, v, r, c)
- c = c or 72
- r = r or 16
- printf("<textarea name=%s cols=%s rows=%s>%s</textarea>", k, c, r, v or '')
+function html.hidden(options)
+ local n = options.name or "hidden"
+ local v = options.value or ""
+ html.tag('input', { type='hidden', name=n, value=v})
end
-function html.print(s)
- printf("%s", s)
+function html.textarea(options)
+ local n = options.name or "textarea"
+ local v = (options.value or ""):gsub("[\n]$", "")
+ local cols = options.cols or 72
+ local rows = options.rows or 12
+ html.tag('textarea', { name=n, cols=cols, rows=rows, text=v})
end
function html.select(k, options, selected)
local p = ""
printf("<select name='%s'>", k)
for k,v in pairs(options) do
- if selected and selected == tostring(v) then
+ if selected and selected == tostring(k) then
p = "selected "
end
- printf("<option %svalue='%s'>%s</option>", p, v, v)
+ printf("<option %svalue='%s'>%s</option>", p, k, v)
p = ""
end
- print("</select>")
+ printf("</select>")
end
function html.submit(value)
printf("<input type=submit value='%s'>", value)
end
-function html.p(...)
- printf("<p>%s", ... or '')
+function html.img(options)
+ html.tag('img', { src=options.src, alt=options.alt})
+end
+function html.p(options)
+ html.tag("p", options)
end
function html.h1(...)
printf("<h1>%s</h1>", ... or '')
end
+function html.h2(...)
+ printf("<h2>%s</h2>", ... or '')
+end
+function html.h3(...)
+ printf("<h3>%s</h3>", ... or '')
+end
+function html.marxup(raw)
+ corz.marxup(raw, io.output())
+end
-help = { html = html, os = os, posix = posix, pairs = pairs }
+help = { html = html, os = os, posix = posix, pairs = pairs, ipairs = ipairs }
lupin = {}
lupin.blueprints = {}
lupin.blueprints.default = {
- purestrain = function(body, data)
+ pure = function(body, data)
print(data.title)
if data.type ~= "default" then
- printf("# type: %s", data.type)
+ printf("# type: %s\n", data.type)
end
data.title = nil
data.type = nil
print(body)
for key, value in pairs(data) do
- print(("# %s: %s"):format(key, value))
+ if key == "info" then
+ local term
+ for i,v in ipairs(data.info) do
+ if i % 2 == 1 then
+ term = v
+ else
+ if #data.info >= i then print(("# info: %s: %s"):format(term, v)) end
+ end
+ end
+ else
+ print(("# %s: %s"):format(key, value))
+ end
end
end,
form = function(body, data)
@@ -97,7 +237,7 @@ lupin.blueprints.default = {
elseif data.mode == "full" then
printf("<h1>%s</h1>", data.title)
end
- printf(corz.marxup(body, io.stdout))
+ corz.marxup(body, io.output())
if not next(data) then return end
print("<dl>")
for key, value in pairs(data) do
@@ -122,26 +262,40 @@ function lupin.loadblueprints(path)
end
end
-function lupin.transform(format, env, mode)
+function lupin.transform(path, format, env, mode)
+ if path ~= "-" then
+ io.input(path)
+ end
+
local raw, data = "", {}
+ data.info = {}
if env then
data.type = os.getenv("POST_type") or "default"
data.title = os.getenv("POST_title") or "default"
raw = os.getenv("POST_text") or ""
+ raw = raw:gsub("\r\n", "\n")
+ raw = raw:gsub("[\n]+$", "")
raw = raw:match("(.-)%s*$")
if lupin.blueprints[data.type] and lupin.blueprints[data.type].env then
lupin.blueprints[data.type].env(data)
end
+ if os.getenv("POST_info") then
+ for line in os.getenv("POST_info"):gmatch("[^\r\n]+") do
+ table.insert(data.info, line)
+ end
+ end
else
for line in io.lines() do
if line:match("^#") then
local key, value = line:match("^#%s*(.-):%s*(.+)")
- if key and value then data[key] = value end
+ if key and value and key == "info" then table.insert(data.info, value)
+ elseif key and value then data[key] = value end
else
if not data.title then
data.title = line
else
+ line = line:gsub("[\r\n]*", "")
raw = raw .. line .. "\n"
end
end
@@ -150,8 +304,43 @@ function lupin.transform(format, env, mode)
end
data.mode = mode
if data.mode == "short" then
- raw = raw:match("[^\r\n]+")
+ raw = data.lead or raw:match("[^\r\n]+")
end
+ if path ~= "-" then
+ local stat = posix.stat(path)
+ local pwd = posix.getpasswd(stat.uid)
+ data.author = pwd.name
+ data.group = posix.getgroup(stat.gid).name
+
+ if posix.stat(pwd.dir .. "/portrait.jpg") then
+ data.portrait = ("/users/%s.jpg"):format(data.author)
+ end
+
+ if posix.stat(pwd.dir .. "/.name") then
+ data.author = io.open(pwd.dir .. "/.name"):read("*l")
+ end
+ end
+
+ if format == "later" then
+ data.raw = raw
+ data.text = function()
+ local f = io.tmpfile()
+ corz.marxup(data.raw, f)
+ f:seek("set")
+ local result = f:read("*a")
+ result = result:gsub("$%s*twitter:%s*(.-)\n", twitter)
+ result = result:gsub("$%s*youtube:%s*(.-)\n", youtube)
+ result = result:gsub("$%s*soundcloud:%s*(.-)\n", soundcloud)
+ result = result:gsub("$%s*twitch:%s*(.-)\n", twitch)
+ result = result:gsub("$%s*vimeo:%s*(.-)\n", vimeo)
+ result = result:gsub("$%s*instagram:%s*(.-)\n", instagram)
+ result = result:gsub("$%s*flickr:%s*(.-)\n", flickr)
+ result = result:gsub("$%s*facebook:%s*(.-)\n", facebook)
+ return result
+ end
+ return data
+ end
+
lupin.blueprints[data.type][format](raw, data)
end