Show comments

Show comments on a story's short description, and automatically load
comments when reading a story.
This commit is contained in:
Robin Malley 2023-03-01 00:41:51 +00:00
parent 443a6331e6
commit 652e673d39
9 changed files with 108 additions and 75 deletions

View File

@ -5,7 +5,6 @@ Notably, holds a connection to the open sqlite3 database in .conn
local sql = require("lsqlite3") local sql = require("lsqlite3")
local queries = require("queries") local queries = require("queries")
local util = require("util")
local config = require("config") local config = require("config")
local db = {} local db = {}
@ -16,7 +15,11 @@ message on fail, and returns true on success.
]] ]]
function db.sqlassert(r, errcode, err) function db.sqlassert(r, errcode, err)
if not r then if not r then
error(string.format("%d: %s",errcode, err)) if err then
error(string.format("%d: %s",errcode, err))
elseif errcode then
error(string.format("%d: %s",errcode, db.conn:errmsg()))
end
end end
return r return r
end end

View File

@ -15,21 +15,21 @@ local stmnt_index, stmnt_author, stmnt_author_bio
local oldconfigure = configure local oldconfigure = configure
function configure(...) function configure(...)
stmnt_index = assert(db.conn:prepare(queries.select_site_index)) stmnt_index = db.sqlassert(db.conn:prepare(queries.select_site_index))
--TODO: actually let authors edit their bio --TODO: actually let authors edit their bio
stmnt_author_bio = assert(db.conn:prepare([[ stmnt_author_bio = db.sqlassert(db.conn:prepare([[
SELECT authors.biography FROM authors WHERE authors.name = :author; SELECT authors.biography FROM authors WHERE authors.name = :author;
]])) ]]))
stmnt_author = assert(db.conn:prepare(queries.select_author_index)) stmnt_author = db.sqlassert(db.conn:prepare(queries.select_author_index))
return oldconfigure(...) return oldconfigure(...)
end end
local function get_site_home(req, loggedin) local function get_site_home(req, loggedin)
log(LOG_DEBUG,"Cache miss, rendering site index") log(LOG_DEBUG,"Cache miss, rendering site index")
stmnt_index:bind_names{} stmnt_index:bind_names{offset=0}
local latest = {} local latest = {}
for idr, title, iar, dater, author, hits in db.sql_rows(stmnt_index) do for idr, title, iar, dater, author, hits, cmts in db.sql_rows(stmnt_index) do
table.insert(latest,{ local story = {
url = util.encode_id(idr), url = util.encode_id(idr),
title = title, title = title,
isanon = tonumber(iar) == 1, isanon = tonumber(iar) == 1,
@ -37,12 +37,19 @@ local function get_site_home(req, loggedin)
author = author, author = author,
tags = libtags.get(idr), tags = libtags.get(idr),
hits = hits, hits = hits,
}) ncomments = cmts
}
table.insert(latest,story)
end end
return pages.index{ return pages.index{
domain = config.domain, domain = config.domain,
stories = latest, stories = latest,
loggedin = loggedin loggedin = loggedin,
extra_load = {
'<script src="/_js/index_scroll.js"></script>'
}
} }
end end
local function get_author_home(req, loggedin) local function get_author_home(req, loggedin)
@ -71,7 +78,7 @@ local function get_author_home(req, loggedin)
stmnt_author_bio:reset() stmnt_author_bio:reset()
stmnt_author:bind_names{author=subdomain} stmnt_author:bind_names{author=subdomain}
local stories = {} local stories = {}
for id, title, time, hits, unlisted, hash in db.sql_rows(stmnt_author) do for id, title, time, hits, unlisted, hash, cmts in db.sql_rows(stmnt_author) do
if unlisted == 1 and author == subdomain then if unlisted == 1 and author == subdomain then
local url = util.encode_id(id) .. "?pwd=" .. util.encode_unlisted(hash) local url = util.encode_id(id) .. "?pwd=" .. util.encode_unlisted(hash)
table.insert(stories,{ table.insert(stories,{
@ -82,6 +89,7 @@ local function get_author_home(req, loggedin)
tags = libtags.get(id), tags = libtags.get(id),
hits = hits, hits = hits,
unlisted = true, unlisted = true,
ncomments = cmts
}) })
elseif unlisted == 0 then elseif unlisted == 0 then
table.insert(stories,{ table.insert(stories,{
@ -92,6 +100,7 @@ local function get_author_home(req, loggedin)
tags = libtags.get(id), tags = libtags.get(id),
hits = hits, hits = hits,
unlisted = false, unlisted = false,
ncomments = cmts
}) })
end end
end end

View File

@ -24,6 +24,7 @@ local function preview_post(req)
idp = "preview", idp = "preview",
text = parsed, text = parsed,
tags = tags, tags = tags,
comments = {}
} }
http_response(req,200,ret) http_response(req,200,ret)
end end

View File

@ -73,24 +73,6 @@ local function populate_ps_story(req,ps)
return true return true
end 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 db.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) local function read_get(req)
--Pages settings --Pages settings
local ps = { local ps = {
@ -130,9 +112,9 @@ local function read_get(req)
--If we need to show comments --If we need to show comments
http_request_populate_qs(req) http_request_populate_qs(req)
ps.show_comments = http_argument_get_string(req,"comments") ps.show_comments = true
if ps.show_comments then if ps.show_comments then
ps.comments = get_comments(req,ps) ps.comments = util.get_comments(ps.storyid)
end end
--If this post is unlisted, get the hash --If this post is unlisted, get the hash

View File

@ -2,8 +2,19 @@
local sql = require("lsqlite3") local sql = require("lsqlite3")
local config = require("config") local config = require("config")
local types = require("types") local types = require("types")
local db = require("db")
local queries = require("queries")
local util = {} local util = {}
local stmnt_comments
local oldconfigure = configure
function configure(...)
stmnt_comments = assert(db.conn:prepare(queries.select_comments))
return oldconfigure(...)
end
--see https://perishablepress.com/stop-using-unsafe-characters-in-urls/ --see https://perishablepress.com/stop-using-unsafe-characters-in-urls/
--no underscore because we use that for our operative pages --no underscore because we use that for our operative pages
local url_characters = local url_characters =
@ -147,6 +158,32 @@ function util.parse_tags(str)
return tags return tags
end end
--[[
Get the comments for a story
Comments are a table with the structure:
comment :: table {
author :: string - The author's text name
isanon :: boolean - True if the author is anon (author string will be "Anonymous")
text :: string - The text of the comment
}
]]
function util.get_comments(sid)
stmnt_comments:bind_names{
id = sid
}
local comments = {}
for com_author, com_isanon, com_text in db.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
if config.debugging then if config.debugging then
function util.checktypes(...) function util.checktypes(...)
local args = {...} local args = {...}

View File

@ -15,6 +15,8 @@
<% end %> <% end %>
</td><td> </td><td>
<%= story.hits %> hits <%= story.hits %> hits
</td><td>
<%= story.ncomments %> comments
</td><td> </td><td>
<ul class="row tag-list"> <ul class="row tag-list">
<% for i = 1,math.min(#story.tags, 5) do %> <% for i = 1,math.min(#story.tags, 5) do %>

View File

@ -35,7 +35,7 @@
<hr/> <hr/>
<p><%= views %> Hits</p> <p><%= views %> Hits, <%= #comments %> Comments</p>
<div class="row"> <div class="row">
<% for _, spec in ipairs(api.get.page_reader(getfenv(1))) do %> <% for _, spec in ipairs(api.get.page_reader(getfenv(1))) do %>
@ -49,46 +49,36 @@
<% end %> <% end %>
</div> </div>
<% if not show_comments then -%> <form action="https://<%= domain %>/<%= short %>" method="POST">
<form action="https://<%= domain %>/<%= short %>"><fieldset> <% if unlisted then %>
<input type="hidden" name="comments" value="1"> <input type="hidden" name="pwd" value="<%= hashstr %>"/>
<% if unlisted then %>
<input type="hidden" name="pwd" value="<%= hashstr %>"/>
<% end %>
<input type="submit" value="load comments" class="button">
</fieldset></form>
<% else %>
<form action="https://<%= domain %>/<%= short %>" method="POST">
<% if unlisted then %>
<input type="hidden" name="pwd" value="<%= hashstr %>"/>
<% end %>
<textarea name="text" cols=60 rows=10 class="column"></textarea>
</div><% if iam then %>
<select id="postas" name="postas">
<option value="Anonymous">Anonymous</option>
<option value="<%= iam %>"><%= iam %></option>
</select>
<input type="submit" value="post" class="button">
<% else %>
<input type="hidden" name="postas" value="Anonymous">
<input type="submit" value="post" class="button">
<% end %>
</form>
<% if comments and #comments == 0 then %>
<p><i>No comments yet</i></p>
<% else %>
<section>
<% for _,comment in pairs(comments) do %>
<article>
<% if comment.isanon then %>
<p><b>Anonymous</b></p>
<% else %>
<p><b><%= comment.author %></b></p>
<% end %>
<p><%= comment.text %></p>
</article>
<% end %>
</section>
<% end %> <% end %>
<textarea name="text" cols=60 rows=10 class="column"></textarea>
</div><% if iam then %>
<select id="postas" name="postas">
<option value="Anonymous">Anonymous</option>
<option value="<%= iam %>"><%= iam %></option>
</select>
<input type="submit" value="post" class="button">
<% else %>
<input type="hidden" name="postas" value="Anonymous">
<input type="submit" value="post" class="button">
<% end %>
</form>
<% if comments and #comments == 0 then %>
<p><i>No comments yet</i></p>
<% else %>
<section>
<% for _,comment in pairs(comments) do %>
<article>
<% if comment.isanon then %>
<p><b>Anonymous</b></p>
<% else %>
<p><b><%= comment.author %></b></p>
<% end %>
<p><%= comment.text %></p>
</article>
<% end %>
</section>
<% end %> <% end %>
<{system cat src/pages/parts/footer.etlua}> <{system cat src/pages/parts/footer.etlua}>

View File

@ -6,13 +6,17 @@ SELECT
posts.post_time, posts.post_time,
posts.views, posts.views,
posts.unlisted, posts.unlisted,
posts.hash posts.hash,
COUNT(comments.id)
FROM FROM
posts, posts,
authors authors
LEFT JOIN comments ON comments.postid = posts.id
WHERE WHERE
posts.isanon = 0 AND posts.isanon = 0 AND
posts.authorid = authors.id AND posts.authorid = authors.id AND
authors.name = :author authors.name = :author
GROUP BY
posts.id
ORDER BY ORDER BY
posts.post_time DESC posts.post_time DESC

View File

@ -5,13 +5,18 @@ SELECT
posts.isanon, posts.isanon,
posts.post_time, posts.post_time,
authors.name, authors.name,
posts.views posts.views,
COUNT(comments.id)
FROM FROM
posts, posts,
authors authors
LEFT JOIN comments ON comments.postid = posts.id
WHERE WHERE
posts.authorid = authors.id AND posts.authorid = authors.id AND
posts.unlisted = 0 posts.unlisted = 0
GROUP BY
posts.id
ORDER BY ORDER BY
posts.post_time DESC posts.post_time DESC
LIMIT 50; LIMIT 50
OFFSET :offset;