214 lines
6.1 KiB
Lua
214 lines
6.1 KiB
Lua
local app = require("lapis").Application()
|
|
local lapis_util = require("lapis.util")
|
|
|
|
local db = require("lapis.db")
|
|
local constants = require("constants")
|
|
|
|
local util = require("util")
|
|
|
|
local models = require("models")
|
|
local Users = models.Users
|
|
local Avatars = models.Avatars
|
|
local Topics = models.Topics
|
|
local Threads = models.Threads
|
|
|
|
local THREADS_PER_PAGE = 10
|
|
|
|
local ThreadCreateError = {
|
|
OK = 0,
|
|
GUEST = 1,
|
|
LOGGED_OUT = 2,
|
|
TOPIC_LOCKED = 3,
|
|
}
|
|
|
|
app:get("all_topics", "", function(self)
|
|
self.topic_list = db.query([[
|
|
SELECT
|
|
topics.name, topics.slug, topics.description, topics.is_locked,
|
|
users.username AS latest_thread_username,
|
|
threads.title AS latest_thread_title,
|
|
threads.slug AS latest_thread_slug,
|
|
threads.created_at AS latest_thread_created_at
|
|
FROM
|
|
topics
|
|
LEFT JOIN (
|
|
SELECT
|
|
*,
|
|
row_number() OVER (PARTITION BY threads.topic_id ORDER BY threads.created_at DESC) as rn
|
|
FROM
|
|
threads
|
|
) threads ON threads.topic_id = topics.id AND threads.rn = 1
|
|
LEFT JOIN
|
|
users on users.id = threads.user_id
|
|
ORDER BY
|
|
topics.sort_order ASC
|
|
]])
|
|
self.me = util.get_logged_in_user_or_transient(self)
|
|
return {render = "topics.topics"}
|
|
end)
|
|
|
|
app:get("topic_create", "/create", function(self)
|
|
local user = util.get_logged_in_user(self) or util.TransientUser
|
|
if not user:is_mod() then
|
|
return {status = 403}
|
|
end
|
|
|
|
self.page_title = "creating a topic"
|
|
self.me = user
|
|
|
|
return {render = "topics.create"}
|
|
end)
|
|
|
|
app:post("topic_create", "/create", function(self)
|
|
local user = util.get_logged_in_user(self) or util.TransientUser
|
|
if not user:is_mod() then
|
|
return {redirect_to = "all_topics"}
|
|
end
|
|
|
|
local topic_name = lapis_util.trim(self.params.name)
|
|
local topic_description = self.params.description
|
|
local time = os.time()
|
|
local slug = lapis_util.slugify(topic_name) .. "-" .. time
|
|
|
|
local topic_count = Topics:count()
|
|
local topic = Topics:create({
|
|
name = topic_name,
|
|
description = topic_description,
|
|
slug = slug,
|
|
sort_order = topic_count + 1,
|
|
})
|
|
|
|
util.inject_infobox(self, "Topic created.")
|
|
|
|
return {redirect_to = self:url_for("topic", {slug = topic.slug})}
|
|
end)
|
|
|
|
app:get("topic", "/:slug", function(self)
|
|
local topic = Topics:find({
|
|
slug = self.params.slug
|
|
})
|
|
if not topic then
|
|
return {status = 404}
|
|
end
|
|
local threads_count = Threads:count(db.clause({
|
|
topic_id = topic.id
|
|
}))
|
|
self.topic = topic
|
|
|
|
self.pages = math.max(math.ceil(threads_count / THREADS_PER_PAGE), 1)
|
|
self.page = math.max(1, math.min(tonumber(self.params.page) or 1, self.pages))
|
|
-- self.threads_list = db.query("SELECT * FROM threads WHERE topic_id = ? ORDER BY is_stickied DESC, created_at DESC", topic.id)
|
|
self.threads_list = db.query([[
|
|
SELECT
|
|
threads.title, threads.slug, threads.created_at, threads.is_locked, threads.is_stickied,
|
|
users.username AS started_by,
|
|
u.username AS latest_post_username,
|
|
ph.content AS latest_post_content,
|
|
posts.created_at AS latest_post_created_at,
|
|
posts.id AS latest_post_id
|
|
FROM
|
|
threads
|
|
JOIN users ON users.id = threads.user_id
|
|
JOIN (
|
|
SELECT
|
|
posts.thread_id,
|
|
posts.id,
|
|
posts.user_id,
|
|
posts.created_at,
|
|
posts.current_revision_id,
|
|
ROW_NUMBER() OVER (PARTITION BY posts.thread_id ORDER BY posts.created_at DESC) AS rn
|
|
FROM
|
|
posts
|
|
) posts ON posts.thread_id = threads.id AND posts.rn = 1
|
|
JOIN
|
|
post_history ph ON ph.id = posts.current_revision_id
|
|
JOIN
|
|
users u ON u.id = posts.user_id
|
|
WHERE
|
|
threads.topic_id = ?
|
|
ORDER BY
|
|
threads.is_stickied DESC,
|
|
threads.created_at DESC
|
|
LIMIT ? OFFSET ?
|
|
]], topic.id, THREADS_PER_PAGE, (self.page - 1) * THREADS_PER_PAGE)
|
|
|
|
local user = util.get_logged_in_user_or_transient(self)
|
|
self.me = user
|
|
|
|
self.ThreadCreateError = ThreadCreateError
|
|
self.thread_create_error = ThreadCreateError.OK
|
|
if user:is_logged_in_guest() then
|
|
self.thread_create_error = ThreadCreateError.GUEST
|
|
elseif user:is_guest() then
|
|
self.thread_create_error = ThreadCreateError.LOGGED_OUT
|
|
elseif util.ntob(topic.is_locked) and not user:is_mod() then
|
|
self.thread_create_error = ThreadCreateError.TOPIC_LOCKED
|
|
end
|
|
|
|
self.page_title = "browsing topic " .. topic.name
|
|
|
|
return {render = "topics.topic"}
|
|
end)
|
|
|
|
app:get("topic_edit", "/:slug/edit", function(self)
|
|
local user = util.get_logged_in_user_or_transient(self)
|
|
if not user:is_mod() then
|
|
return {redirect_to = self:url_for("topic", {slug = self.params.slug})}
|
|
end
|
|
local topic = Topics:find({
|
|
slug = self.params.slug
|
|
})
|
|
if not topic then
|
|
return {redirect_to = self:url_for("all_topics")}
|
|
end
|
|
self.topic = topic
|
|
self.me = user
|
|
self.page_title = "editing topic " .. topic.name
|
|
|
|
return {render = "topics.edit"}
|
|
end)
|
|
|
|
app:post("topic_edit", "/:slug/edit", function(self)
|
|
local user = util.get_logged_in_user_or_transient(self)
|
|
if not user:is_mod() then
|
|
return {redirect_to = self:url_for("topic", {slug = self.params.slug})}
|
|
end
|
|
local topic = Topics:find({
|
|
slug = self.params.slug
|
|
})
|
|
if not topic then
|
|
return {redirect_to = self:url_for("all_topics")}
|
|
end
|
|
local name = self.params.name or topic.name
|
|
local description = self.params.description or topic.description
|
|
local is_locked = topic.is_locked
|
|
if self.params.is_locked ~= nil then
|
|
is_locked = util.form_bool_to_sqlite(self.params.is_locked)
|
|
end
|
|
|
|
topic:update({
|
|
name = name,
|
|
description = description,
|
|
is_locked = is_locked,
|
|
})
|
|
return {redirect_to = self:url_for("topic", {slug = self.params.slug})}
|
|
end)
|
|
|
|
app:post("topic_delete", "/:slug/delete", function(self)
|
|
local user = util.get_logged_in_user(self)
|
|
if not user then
|
|
return {redirect_to = self:url_for("topic", {slug = self.params.slug})}
|
|
end
|
|
|
|
if not user:is_mod() then
|
|
return {redirect_to = self:url_for("topic", {slug = self.params.slug})}
|
|
end
|
|
|
|
local topic = Topics:find({slug = self.params.slug})
|
|
topic:delete()
|
|
util.inject_infobox(self, "Topic deleted.")
|
|
return {redirect_to = self:url_for("all_topics")}
|
|
end)
|
|
|
|
return app
|