Compare commits
3 Commits
1038e8ea1e
...
f3aaa6d24d
Author | SHA1 | Date | |
---|---|---|---|
f3aaa6d24d | |||
f071919fa8 | |||
d70b27cda0 |
3
app.lua
3
app.lua
@ -21,6 +21,9 @@ local function inject_methods(req)
|
|||||||
return util.ntob(v)
|
return util.ntob(v)
|
||||||
end
|
end
|
||||||
req.PermissionLevelString = constants.PermissionLevelString
|
req.PermissionLevelString = constants.PermissionLevelString
|
||||||
|
req.infobox_message = function (_, s)
|
||||||
|
return util.infobox_message(s)
|
||||||
|
end
|
||||||
|
|
||||||
util.pop_infobox(req)
|
util.pop_infobox(req)
|
||||||
end
|
end
|
||||||
|
@ -35,7 +35,10 @@ app:post("thread_create", "/create", function(self)
|
|||||||
end
|
end
|
||||||
local topic = Topics:find(self.params.topic_id)
|
local topic = Topics:find(self.params.topic_id)
|
||||||
if not topic then
|
if not topic then
|
||||||
return {redirect_to = self:url_for("topics")}
|
return {redirect_to = self:url_for("all_topics")}
|
||||||
|
end
|
||||||
|
if util.is_topic_locked(topic) and not user:is_mod() then
|
||||||
|
return {redirect_to = self:url_for("all_topics")}
|
||||||
end
|
end
|
||||||
|
|
||||||
local title = lapis_util.trim(self.params.title)
|
local title = lapis_util.trim(self.params.title)
|
||||||
@ -54,7 +57,7 @@ app:post("thread_create", "/create", function(self)
|
|||||||
|
|
||||||
local post = util.create_post(thread.id, user.id, post_content)
|
local post = util.create_post(thread.id, user.id, post_content)
|
||||||
if not post then
|
if not post then
|
||||||
return {redirect_to = self:url_for("topics")}
|
return {redirect_to = self:url_for("all_topics")}
|
||||||
end
|
end
|
||||||
|
|
||||||
return {redirect_to = self:url_for("thread", {slug = slug})}
|
return {redirect_to = self:url_for("thread", {slug = slug})}
|
||||||
|
164
util.lua
164
util.lua
@ -3,6 +3,7 @@ local magick = require("magick")
|
|||||||
local db = require("lapis.db")
|
local db = require("lapis.db")
|
||||||
local html_escape = require("lapis.html").escape
|
local html_escape = require("lapis.html").escape
|
||||||
local constants = require("constants")
|
local constants = require("constants")
|
||||||
|
local string_trim = require("lapis.util").trim
|
||||||
|
|
||||||
local Avatars = require("models").Avatars
|
local Avatars = require("models").Avatars
|
||||||
local Users = require("models").Users
|
local Users = require("models").Users
|
||||||
@ -33,10 +34,131 @@ util.TransientUser = {
|
|||||||
username = "Deleted User",
|
username = "Deleted User",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- PURE API
|
||||||
|
|
||||||
function util.get_user_avatar_url(req, user)
|
function util.get_user_avatar_url(req, user)
|
||||||
return Avatars:find(user.avatar_id).file_path
|
return Avatars:find(user.avatar_id).file_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---split a string
|
||||||
|
---@param s string subject
|
||||||
|
---@param delimiter string? string to split by, can be empty to split by character
|
||||||
|
---@param max_matches integer? the maximum number of returned elements
|
||||||
|
---@param trim boolean? whether to trim whitespace off matches
|
||||||
|
---@param allow_empty boolean? should empty matches be in the resulting table
|
||||||
|
---@return string[]
|
||||||
|
function util.s_split(s, delimiter, max_matches, trim, allow_empty)
|
||||||
|
local result = {}
|
||||||
|
if s == "" then
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
trim = trim == nil and true or trim
|
||||||
|
local tr = function(subj)
|
||||||
|
if trim then return string_trim(subj) else return subj end
|
||||||
|
end
|
||||||
|
max_matches = max_matches or -1
|
||||||
|
allow_empty = allow_empty == nil and true or allow_empty
|
||||||
|
|
||||||
|
if delimiter == "" then
|
||||||
|
for i=1, #s do
|
||||||
|
local c = s:sub(i, 1)
|
||||||
|
if allow_empty or c ~= "" then
|
||||||
|
table.insert(result, c)
|
||||||
|
if max_matches > 0 and #result == max_matches then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local current_pos = 1
|
||||||
|
local delim_len = #delimiter
|
||||||
|
|
||||||
|
while true do
|
||||||
|
if max_matches > 0 and #result >= max_matches then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
|
local start_pos, end_pos = s:find(delimiter, current_pos, true)
|
||||||
|
if not start_pos then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local substr = s:sub(current_pos, start_pos - 1)
|
||||||
|
if allow_empty or substr ~= "" then
|
||||||
|
table.insert(result, tr(substr))
|
||||||
|
end
|
||||||
|
current_pos = end_pos + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local substr = s:sub(current_pos)
|
||||||
|
if allow_empty or substr ~= "" then
|
||||||
|
table.insert(result, tr(substr))
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.split_sentences(sentences, max_sentences)
|
||||||
|
return util.s_split(sentences, ".", max_sentences or 2, true, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.infobox_message(msg)
|
||||||
|
local sentences = util.split_sentences(msg)
|
||||||
|
if #sentences == 1 then
|
||||||
|
return "<b>" .. sentences[1] .. ". " .. "</b>"
|
||||||
|
end
|
||||||
|
return "<span><b>" .. sentences[1] .. ". " .. "</b> " .. sentences[2] .. ".</span>"
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.get_logged_in_user(req)
|
||||||
|
if req.session.session_key == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local session = db.select('* FROM "sessions" WHERE "key" = ? AND "expires_at" > "?" LIMIT 1', req.session.session_key, os.time())
|
||||||
|
if #session > 0 then
|
||||||
|
return Users:find({id = session[1].user_id})
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.get_logged_in_user_or_transient(req)
|
||||||
|
return util.get_logged_in_user(req) or util.TransientUser
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.ntob(v)
|
||||||
|
return v ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.bton(b)
|
||||||
|
return 1 and b or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.stob(s)
|
||||||
|
if s == "true" then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if s == "false" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.form_bool_to_sqlite(s)
|
||||||
|
return util.bton(util.stob(s))
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.is_thread_locked(thread)
|
||||||
|
return util.ntob(thread.is_locked)
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.is_topic_locked(topic)
|
||||||
|
return util.ntob(topic.is_locked)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- OTHER API
|
||||||
|
|
||||||
function util.validate_and_create_image(input_image, filename)
|
function util.validate_and_create_image(input_image, filename)
|
||||||
local img = magick.load_image_from_blob(input_image)
|
local img = magick.load_image_from_blob(input_image)
|
||||||
|
|
||||||
@ -92,48 +214,6 @@ function util.destroy_avatar(avatar_id)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function util.get_logged_in_user(req)
|
|
||||||
if req.session.session_key == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local session = db.select('* FROM "sessions" WHERE "key" = ? AND "expires_at" > "?" LIMIT 1', req.session.session_key, os.time())
|
|
||||||
if #session > 0 then
|
|
||||||
return Users:find({id = session[1].user_id})
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.get_logged_in_user_or_transient(req)
|
|
||||||
return util.get_logged_in_user(req) or util.TransientUser
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.ntob(v)
|
|
||||||
return v ~= 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.bton(b)
|
|
||||||
return 1 and b or 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.stob(s)
|
|
||||||
if s == "true" then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if s == "false" then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.form_bool_to_sqlite(s)
|
|
||||||
return util.bton(util.stob(s))
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.is_thread_locked(thread)
|
|
||||||
return util.ntob(thread.is_locked)
|
|
||||||
end
|
|
||||||
|
|
||||||
function util.create_post(thread_id, user_id, content)
|
function util.create_post(thread_id, user_id, content)
|
||||||
db.query("BEGIN")
|
db.query("BEGIN")
|
||||||
local post = Posts:create({
|
local post = Posts:create({
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<title>Porom</title>
|
<title>Porom</title>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% math.randomseed(os.time()) %>
|
<% math.randomseed(os.time()) %>
|
||||||
<link rel="stylesheet" href="<%= "/static/style.css?" .. math.random(1, 100) %>">
|
<link rel="stylesheet" href="<%= "/static/style.css?v=" .. math.random(1, 100) %>">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<% render("views.common.topnav") -%>
|
<% render("views.common.topnav") -%>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<%
|
<%
|
||||||
local class = "infobox " .. constants.InfoboxHTMLClass[kind]
|
local class = "infobox " .. constants.InfoboxHTMLClass[kind]
|
||||||
local icon = constants.InfoboxIcons[kind]
|
local icon = constants.InfoboxIcons[kind]
|
||||||
|
local sentences = infobox_message(msg)
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<div class="<%= class %>">
|
<div class="<%= class %>">
|
||||||
@ -8,6 +9,6 @@
|
|||||||
<div class="infobox-icon-container">
|
<div class="infobox-icon-container">
|
||||||
<% render(icon) %>
|
<% render(icon) %>
|
||||||
</div>
|
</div>
|
||||||
<%= msg %>
|
<%- sentences %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
<% render("views.common.infobox", infobox) %>
|
<% render("views.common.infobox", infobox) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% local is_locked = ntob(topic.is_locked) %>
|
||||||
|
|
||||||
<nav class="darkbg">
|
<nav class="darkbg">
|
||||||
<h1 class="thread-title">All threads in "<%= topic.name %>"</h1>
|
<h1 class="thread-title">All threads in "<%= topic.name %>"</h1>
|
||||||
<span><%= topic.description %></span>
|
<span><%= topic.description %></span>
|
||||||
@ -12,25 +14,27 @@
|
|||||||
<p>Your account is still pending confirmation by a moderator. You are not able to create a new thread or post at this time.</p>
|
<p>Your account is still pending confirmation by a moderator. You are not able to create a new thread or post at this time.</p>
|
||||||
<% elseif thread_create_error == ThreadCreateError.LOGGED_OUT then %>
|
<% elseif thread_create_error == ThreadCreateError.LOGGED_OUT then %>
|
||||||
<p>Only logged in users can create threads. <a href="<%= url_for("user_signup") %>">Sign up</a> or <a href="<%= url_for("user_login")%>">log in</a> to create a thread.</p>
|
<p>Only logged in users can create threads. <a href="<%= url_for("user_signup") %>">Sign up</a> or <a href="<%= url_for("user_login")%>">log in</a> to create a thread.</p>
|
||||||
<% else %>
|
|
||||||
<p>This topic is locked.</p>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if me:is_mod() then %>
|
<% if me:is_mod() then %>
|
||||||
<a class="linkbutton" href="<%= url_for("topic_edit", {slug = topic.slug}) %>">Edit topic</a>
|
<a class="linkbutton" href="<%= url_for("topic_edit", {slug = topic.slug}) %>">Edit topic</a>
|
||||||
<form class="modform" method="post" action="<%= url_for("topic_edit", {slug = topic.slug}) %>">
|
<form class="modform" method="post" action="<%= url_for("topic_edit", {slug = topic.slug}) %>">
|
||||||
<input type="hidden" name="is_locked" value="<%= not ntob(topic.is_locked) %>">
|
<input type="hidden" name="is_locked" value="<%= not is_locked %>">
|
||||||
<input class="warn" type="submit" id="lock" value="<%= ntob(topic.is_locked) and "Unlock topic" or "Lock topic" %>">
|
<input class="warn" type="submit" id="lock" value="<%= is_locked and "Unlock topic" or "Lock topic" %>">
|
||||||
</form>
|
</form>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<% if is_locked then -%>
|
||||||
|
<% render("views.common.infobox", {kind = constants.InfoboxKind.LOCK, msg = "This topic is locked. Only moderators can create new threads."}) %>
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
<% if #threads_list == 0 then %>
|
<% if #threads_list == 0 then %>
|
||||||
<p>There are no threads in this topic.</p>
|
<p>There are no threads in this topic.</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<% for _, thread in ipairs(threads_list) do %>
|
<% for _, thread in ipairs(threads_list) do %>
|
||||||
<% local is_stickied = ntob(thread.is_stickied) %>
|
<% local is_stickied = ntob(thread.is_stickied) %>
|
||||||
<% local is_locked = ntob(thread.is_locked) %>
|
<% local thread_is_locked = ntob(thread.is_locked) %>
|
||||||
<div class="thread">
|
<div class="thread">
|
||||||
<div class="thread-sticky-container contain-svg">
|
<div class="thread-sticky-container contain-svg">
|
||||||
<% if is_stickied then -%>
|
<% if is_stickied then -%>
|
||||||
@ -54,7 +58,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="thread-locked-container contain-svg">
|
<div class="thread-locked-container contain-svg">
|
||||||
<% if is_locked then -%>
|
<% if thread_is_locked then -%>
|
||||||
<% render("svg-icons.lock") %>
|
<% render("svg-icons.lock") %>
|
||||||
<i>Locked</i>
|
<i>Locked</i>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<% local is_locked = ntob(topic.is_locked) %>
|
<% local is_locked = ntob(topic.is_locked) %>
|
||||||
<div class="topic">
|
<div class="topic">
|
||||||
<div class="topic-info-container">
|
<div class="topic-info-container">
|
||||||
<a href=<%= url_for("topic", {slug = topic.slug}) %>><%= topic.name %></a>
|
<a class="thread-title" href=<%= url_for("topic", {slug = topic.slug}) %>><%= topic.name %></a>
|
||||||
<%= topic.description %>
|
<%= topic.description %>
|
||||||
<% if topic.latest_thread_username then %>
|
<% if topic.latest_thread_username then %>
|
||||||
<span>
|
<span>
|
||||||
|
Loading…
Reference in New Issue
Block a user