You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
6.6 KiB
Lua
227 lines
6.6 KiB
Lua
local db = require "lapis.db"
|
|
local giflib = require "giflib"
|
|
local lfs = require "lfs"
|
|
local magick = require "magick"
|
|
local Model = require("lapis.db.model").Model
|
|
local Boards = Model:extend("boards", {
|
|
relations = {
|
|
{ "announcements", has_many="Announcements" },
|
|
{ "bans", has_many="Bans" },
|
|
{ "posts", has_many="Posts" },
|
|
{ "reports", has_many="Reports" },
|
|
{ "threads", has_many="Threads", where={ archive=false }, order="sticky desc, last_active desc" },
|
|
{ "archived", has_many="Threads", where={ archive=true }, order="last_active desc" },
|
|
}
|
|
})
|
|
|
|
Boards.valid_record = {
|
|
{ "name", max_length=255, exists=true },
|
|
{ "title", max_length=255, exists=true },
|
|
{ "subtext", max_length=255 },
|
|
{ "ban_message", max_length=255 },
|
|
{ "anon_name", max_length=255 },
|
|
{ "theme", max_length=255 },
|
|
{ "pages", exists=true },
|
|
{ "threads_per_page", exists=true },
|
|
{ "thread_file_limit", exists=true },
|
|
{ "post_limit", exists=true },
|
|
{ "archive_time", exists=true },
|
|
{ "group", exists=true }
|
|
}
|
|
|
|
--- Create a board
|
|
-- @tparam table params Board parameters
|
|
-- @treturn boolean success
|
|
-- @treturn string error
|
|
function Boards:new(params)
|
|
local board = self:create(params)
|
|
if not board then
|
|
return false, { "err_create_board", { params.name, params.title } }
|
|
end
|
|
|
|
lfs.mkdir(string.format("./static/%s/", board.name))
|
|
return board
|
|
end
|
|
|
|
--- Modify a board
|
|
-- @tparam table params Board parameters
|
|
-- @tparam old_name Board's current short name
|
|
-- @treturn boolean success
|
|
-- @treturn string error
|
|
function Boards:modify(params, old_name)
|
|
local board = self:get(old_name)
|
|
if not board then
|
|
return false, { "err_create_board", { params.name, params.title } } -- FIXME: wrong error message
|
|
end
|
|
|
|
local success, err = board:update(params)
|
|
if not success then
|
|
return false, "FIXME: " .. tostring(err)
|
|
end
|
|
|
|
if board.name ~= old_name then
|
|
local old = string.format("./static/%s/", old_name)
|
|
local new = string.format("./static/%s/", board.name)
|
|
os.rename(old, new)
|
|
end
|
|
|
|
return board
|
|
end
|
|
|
|
--- Delete a board
|
|
-- @tparam string name Board's short name
|
|
-- @treturn boolean success
|
|
-- @treturn string error
|
|
function Boards:delete(name)
|
|
local board = self:get(name)
|
|
if not board then
|
|
return false, { "err_create_board", { name, name } } -- FIXME: wrong error message
|
|
end
|
|
|
|
local announcements = board:get_announcements()
|
|
local bans = board:get_bans()
|
|
local posts = board:get_posts()
|
|
local reports = board:get_reports()
|
|
local threads = board:get_threads()
|
|
local dir = string.format("./static/%s/", board.name)
|
|
|
|
-- Clear data
|
|
for _, announcement in ipairs(announcements) do announcement:delete() end
|
|
for _, ban in ipairs(bans) do ban:delete() end
|
|
for _, post in ipairs(posts) do post:delete() end
|
|
for _, report in ipairs(reports) do report:delete() end
|
|
for _, thread in ipairs(threads) do thread:delete() end
|
|
|
|
-- Clear filesystem
|
|
if lfs.attributes(dir, "mode") == "directory" then
|
|
-- Delete files
|
|
for file in lfs.dir(dir) do
|
|
os.remove(dir .. file)
|
|
end
|
|
|
|
-- Delete directory
|
|
lfs.rmdir(dir)
|
|
end
|
|
|
|
-- Clear board
|
|
local success = board:delete()
|
|
return success and board or false, { "err_delete_board", { board.name, board.title } }
|
|
end
|
|
|
|
--- Get all boards
|
|
-- @treturn table boards
|
|
function Boards:get_all()
|
|
local boards = self:select("order by boards.group asc, name asc")
|
|
return boards and boards or false, "FIXME: ALART!"
|
|
end
|
|
|
|
--- Get board data
|
|
-- @tparam string name Board's short name
|
|
-- @treturn table board
|
|
function Boards:get(name)
|
|
local board = self:find { name=name }
|
|
return board and board or false, "FIXME: ALART!"
|
|
end
|
|
|
|
--- Format board paramaters for DB insertion
|
|
-- @tparam table params Board parameters
|
|
function Boards.format_to_db(_, params)
|
|
-- Convert archive_time from days to seconds
|
|
params.archive_time = (tonumber(params.archive_time) or 0) * 86400
|
|
end
|
|
|
|
--- Format board parameters for User consumption
|
|
-- @tparam table params Board parameters
|
|
function Boards.format_from_db(_, params)
|
|
-- Convert archive_time from seconds to days
|
|
params.archive_time = tonumber(params.archive_time) / 86400
|
|
end
|
|
|
|
--- Regenerate thumbnails for all posts
|
|
-- @treturn none
|
|
function Boards.regen_thumbs(_)
|
|
local sql = [[
|
|
select
|
|
boards.name as board,
|
|
posts.thread_id,
|
|
posts.file_path,
|
|
posts.file_width,
|
|
posts.file_height,
|
|
posts.file_type
|
|
from posts
|
|
left join boards on
|
|
board_id = boards.id
|
|
where
|
|
file_path is not null and
|
|
file_width is not null and
|
|
file_height is not null and
|
|
file_type = 'image' and
|
|
file_spoiler = false
|
|
order by
|
|
board_id asc,
|
|
thread_id asc,
|
|
post_id asc
|
|
]]
|
|
local dir
|
|
local board
|
|
local thread = 0
|
|
local results = db.query(sql)
|
|
|
|
for _, result in ipairs(results) do
|
|
-- Change board, reset thread counter and image directory
|
|
if result.board ~= board then
|
|
board = result.board
|
|
thread = 0
|
|
dir = string.format("./static/%s/", board)
|
|
end
|
|
|
|
-- Filesystem paths
|
|
local name, ext = result.file_path:match("^(.+)(%..+)$")
|
|
ext = string.lower(ext)
|
|
|
|
local full_path = dir .. result.file_path
|
|
local thumb_path = dir .. "s" .. result.file_path
|
|
|
|
-- Generate a thumbnail
|
|
if ext == ".webm" then
|
|
thumb_path = dir .. "s" .. name .. ".png"
|
|
|
|
-- Create screenshot of first frame
|
|
os.execute(string.format("ffmpeg -i %s -ss 00:00:01 -vframes 1 %s -y", full_path, thumb_path))
|
|
end
|
|
|
|
-- Save thumbnail
|
|
local w, h
|
|
if result.thread_id > thread then
|
|
thread = result.thread_id
|
|
w = result.file_width < 250 and result.file_width or 250
|
|
h = result.file_height < 250 and result.file_height or 250
|
|
else
|
|
w = result.file_width < 125 and result.file_width or 125
|
|
h = result.file_height < 125 and result.file_height or 125
|
|
end
|
|
|
|
-- Grab first frame from video
|
|
if ext == ".webm" then
|
|
magick.thumb(thumb_path, string.format("%sx%s", w, h), thumb_path)
|
|
elseif ext == ".svg" then
|
|
thumb_path = dir .. "s" .. name .. ".png"
|
|
os.execute(string.format("convert -background none -resize %dx%d %s %s", w, h, full_path, thumb_path))
|
|
elseif ext == ".gif" then
|
|
-- Grab first frame of a gif instead of the last
|
|
local gif, err = giflib.load_gif(full_path)
|
|
|
|
if err then
|
|
magick.thumb(full_path, string.format("%sx%s", w, h), thumb_path)
|
|
else
|
|
gif:write_first_frame(thumb_path)
|
|
magick.thumb(thumb_path, string.format("%sx%s", w, h), thumb_path)
|
|
end
|
|
else
|
|
magick.thumb(full_path, string.format("%sx%s", w, h), thumb_path)
|
|
end
|
|
end
|
|
end
|
|
|
|
return Boards
|