smr/src/lua/endpoints/read_get.lua

192 lines
4.9 KiB
Lua

local sql = require("lsqlite3")
local session = require("session")
local tags = require("tags")
local db = require("db")
local queries = require("queries")
local util = require("util")
local cache = require("cache")
local pages = require("pages")
local config = require("config")
local zlib = require("zlib")
local stmnt_read, stmnt_update_views, stmnt_comments
local oldconfigure = configure
function configure(...)
stmnt_read = assert(db.conn:prepare(queries.select_post))
stmnt_update_views = assert(db.conn:prepare(queries.update_views))
stmnt_comments = assert(db.conn:prepare(queries.select_comments))
return oldconfigure(...)
end
--[[
Increases a story's hit counter by 1
]]
local function add_view(storyid)
stmnt_update_views:bind_names{
id = storyid
}
local err = util.do_sql(stmnt_update_views)
assert(err == sql.DONE, "Failed to update view counter:"..tostring(err))
stmnt_update_views:reset()
end
--[[
Populates ps with story settings, returns true if story was found,
or nil if it wasn't
]]
local function populate_ps_story(req,ps)
--Make sure our story exists
stmnt_read:bind_names{
id = ps.storyid,
}
local err = util.do_sql(stmnt_read)
if err == sql.DONE then
--We got no story
stmnt_read:reset()
log(LOG_DEBUG,"No story with id:" .. ps.storyid)
return false
end
--If we've made it here, we have a story. Populate our settings
--with title, text, ect.
assert(err == sql.ROW)
local title, storytext, tauthor, isanon, authorname, views, unlisted, hash = unpack(
stmnt_read:get_values()
)
ps.unlisted = unlisted == 1
if ps.unlisted and hash ~= ps.hash then
log(LOG_DEBUG,"Tried to get story id:" .. ps.storyid .. " but it was unlisted and hash was incorrect.")
stmnt_read:reset()
return false
end
ps.title = title
ps.text = zlib.decompress(storytext)
ps.tauthor = tauthor
ps.isanon = isanon == 1
ps.author = authorname
ps.views = views
stmnt_read:reset()
--Tags
ps.tags = tags.get(ps.storyid)
return true
end
--[[
Get the comments for a story
]]
local function get_comments(req,ps)
stmnt_comments:bind_names{
id = ps.storyid
}
local comments = {}
for com_author, com_isanon, com_text in util.sql_rows(stmnt_comments) do
table.insert(comments,{
author = com_author,
isanon = com_isanon == 1, --int to boolean
text = com_text
})
end
return comments
end
local function read_get(req)
--Pages settings
local ps = {
domain = config.domain,
host = http_request_get_host(req),
path = http_request_get_path(req),
method = http_method_text(req),
extra_load = {
'<script src="/_js/bookmark.js"></script>',
'<script src="/_js/intervine_deletion.js"></script>',
}
}
local err
--Get our story id
assert(string.len(ps.path) > 0,"Tried to read 0-length story id")
ps.idp = string.sub(ps.path,2)--remove leading "/"
ps.storyid,err = util.decode_id(ps.idp)
if not ps.storyid then
local page = pages.error{
errcode = 400,
errcodemsg = "Bad Request",
explanation = string.format("Failed to find story id %q: %s",ps.path,err)
}
http_response(req,400,page)
return
end
add_view(ps.storyid)
--If we're logged in, set author and authorid
local author, authorid = session.get(req)
if author and authorid then
ps.loggedauthor = author
ps.iam = author
ps.loggedauthorid = authorid
end
--If we need to show comments
http_request_populate_qs(req)
ps.show_comments = http_argument_get_string(req,"comments")
if ps.show_comments then
ps.comments = get_comments(req,ps)
end
--If this post is unlisted, get the hash
local hashstr = http_argument_get_string(req,"pwd")
if hashstr then
ps.hash = util.decode_unlisted(hashstr)
ps.hashstr = hashstr
end
local text
--normal story display
if (not ps.loggedauthor) then
local params = {}
if ps.show_comments then
table.insert(params,"comments=1")
end
if ps.hash then
table.insert(params,"pwd=" .. hashstr)
end
local cachestrparts = {
ps.path,
}
if #params > 0 then
table.insert(cachestrparts,"?")
table.insert(cachestrparts,table.concat(params,"&"))
end
local cachestr = table.concat(cachestrparts)
text = cache.render(cachestr,function()
log(LOG_DEBUG,"Cache miss, rendering story " .. cachestr)
if not populate_ps_story(req,ps) then
return pages.nostory(ps)
end
local output = pages.read(ps)
assert(output,"failed to read page:" .. cachestr)
return output
end)
else --we are logged in, don't cache
if not populate_ps_story(req,ps) then
text = pages.nostory(ps)
else
ps.owner = (ps.loggedauthorid == ps.tauthor)
text = pages.read(ps)
end
end
--If this isn't unlisted, dirty everywhere the hit counter is shown
cache.dirty(string.format("%s",config.domain))
cache.dirty(string.format("%s/%s",config.domain,ps.idp)) -- This place to read this post
cache.dirty(string.format("%s/%s",config.domain,ps.idp)) -- The author's index page
assert(text)
http_response(req,200,text)
return
end
return read_get