view src/lib/Post.luan @ 20:3ea49246d6a7

bbcode work
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 13 Jul 2022 22:00:00 -0600
parents 94e26bffd4fb
children 0c1b820fff34
line wrap: on
line source

local Luan = require "luan:Luan.luan"
local error = Luan.error
local ipairs = Luan.ipairs or error()
local set_metatable = Luan.set_metatable or error()
local Time = require "luan:Time.luan"
local time_now = Time.now or error()
local Html = require "luan:Html.luan"
local html_encode = Html.encode or error()
local Db = require "site:/lib/Db.luan"


local Post = {}

local times = {
	{
		time = 1000*60*60*24*365
		unit = "year"
	}
	{
		time = 1000*60*60*24*7
		unit = "week"
	}
	{
		time = 1000*60*60*24
		unit = "day"
	}
	{
		time = 1000*60*60
		unit = "hour"
	}
	{
		time = 1000*60
		unit = "minute"
	}
}

local function from_doc(doc)
	doc.type == "post" or error "wrong type"
	return Post.new {
		id = doc.id
		content = doc.content
		date = doc.date
		author_name = doc.post_author_name
		root_id = doc.post_root_id
		is_deleted = doc.is_deleted == "true"

		-- root only
		subject = doc.subject
		is_root = doc.post_is_root == "true"

		-- replies only
		parent_id = doc.parent_id
	}
end

local function to_doc(post)
	return {
		type = "post"
		id = post.id
		content = post.content or error()
		date = post.date or time_now()
		post_author_name = post.author_name or error()
		post_root_id = post.root_id
		is_deleted = post.is_deleted and "true" or nil

		-- root only
		subject = post.subject
		post_is_root = post.is_root and "true" or nil

		-- replies only
		parent_id = post.parent_id
	}
end

local metatable = {}
function metatable.__index(post,key)
	if key == "author" then
		local User = require "site:/lib/User.luan"
		return User.get_by_name(post.author_name)
	end
	if key == "subject_html" then
		return post.subject and html_encode(post.subject)
	end
	if key == "root" then
		return post.is_root and post or Post.get_by_id(post.root_id)
	end
	return nil
end

function Post.new(post)

	function post.save()
		local doc = to_doc(post)
		Db.save(doc)
		post.id = doc.id
	end

	function post.reply(author,content)
		return Db.run_in_transaction( function()
			local post = Post.new{
				root_id = post.root_id
				parent_id = post.id
				content = content
				author_name = author.name
			}
			post.save()
			return post
		end )
	end

	function post.author_is_current()
		local User = require "site:/lib/User.luan"
		local user = User.current()
		return user ~= nil and user.name == post.author_name
	end

	function post.ago(now)
		local diff = now - post.date
		for _, t in ipairs(times) do
			local n = diff // t.time
			if n > 0 then
				%><%=n%> <%=t.unit%><%
				if n > 1 then
					%>s<%
				end
				return
			end
		end
		%>0 minutes<%
	end

	set_metatable(post,metatable)
	return post
end

function Post.get_by_id(id)
	local doc = Db.get_document("id:"..id)
	return doc and from_doc(doc)
end

function Post.new_thread(author,subject,content)
	return Db.run_in_transaction( function()
		local post = Post.new{
			subject = subject or error()
			content = content
			author_name = author.name
			is_root = true
		}
		post.save()
		post.root_id = post.id or error()
		post.save()
		return post
	end )
end

function Post.from_docs(docs)
	local posts = {}
	for _, doc in ipairs(docs) do
		local post = from_doc(doc)
		posts[#posts+1] = post
	end
	return posts
end

return Post