add item titles
This commit is contained in:
@@ -65,7 +65,7 @@
|
||||
"cancel_upload": "Cancel Upload",
|
||||
"shitpost_success": "Successfully shitposted {n} items!",
|
||||
"shitposting_status": "Uploading",
|
||||
"item_comment_placeholder": "Comment (optional)...",
|
||||
"item_comment_placeholder": "Write a Comment...",
|
||||
"item_tags_placeholder": "Tags...",
|
||||
"btn_add_urls": "Add URL(s)",
|
||||
"tags_required_shitpost": "All items need tags",
|
||||
|
||||
@@ -657,6 +657,7 @@ export default {
|
||||
author_avatar: actitem.author_avatar,
|
||||
author_avatar_file: actitem.author_avatar_file,
|
||||
author_description: actitem.author_description,
|
||||
title: actitem.title || null,
|
||||
|
||||
src: {
|
||||
long: actitem.src,
|
||||
|
||||
@@ -817,6 +817,33 @@ export default router => {
|
||||
});
|
||||
|
||||
|
||||
// PATCH /api/v2/items/:id/title — set or clear the title for an item
|
||||
// Allowed by: item owner, moderators, admins
|
||||
group.patch(/\/items\/(?<id>\d+)\/title$/, lib.loggedin, async (req, res) => {
|
||||
const id = +req.params.id;
|
||||
if (!id) return res.json({ success: false, msg: 'Invalid item id' }, 400);
|
||||
|
||||
// Fetch item to check ownership
|
||||
const rows = await db`SELECT id, username FROM items WHERE id = ${id} AND active = true LIMIT 1`;
|
||||
if (!rows.length) return res.json({ success: false, msg: 'Item not found' }, 404);
|
||||
|
||||
const item = rows[0];
|
||||
const isOwner = req.session.user === item.username;
|
||||
const isMod = !!(req.session.is_moderator || req.session.admin);
|
||||
if (!isOwner && !isMod) return res.json({ success: false, msg: 'Forbidden' }, 403);
|
||||
|
||||
// Accept title from JSON or URL-encoded body
|
||||
let rawTitle = req.post?.title ?? req.body?.title ?? null;
|
||||
if (rawTitle !== null) rawTitle = String(rawTitle).trim();
|
||||
// Empty string → null (clears the title)
|
||||
const title = (rawTitle === '' || rawTitle === null) ? null : rawTitle.substring(0, 500);
|
||||
|
||||
await db`UPDATE items SET title = ${title} WHERE id = ${id}`;
|
||||
|
||||
return res.json({ success: true, title });
|
||||
});
|
||||
|
||||
|
||||
group.post(/\/admin\/deletepost$/, lib.modAuth, async (req, res) => {
|
||||
if (req.post.postid === undefined || req.post.postid === null) {
|
||||
return res.json({
|
||||
|
||||
@@ -204,7 +204,8 @@ export default router => {
|
||||
return res.json({ success: false, msg: 'URL uploads are disabled' }, 403);
|
||||
}
|
||||
|
||||
const { url: inputUrl, rating, tags: tagsRaw, comment, is_oc, is_shitpost } = req.post || {};
|
||||
const { url: inputUrl, rating, tags: tagsRaw, comment, is_oc, is_shitpost, title: rawTitle } = req.post || {};
|
||||
const title = (rawTitle && typeof rawTitle === 'string' && rawTitle.trim()) ? rawTitle.trim().substring(0, 500) : null;
|
||||
|
||||
const maxLen = cfg.main.comment_max_length;
|
||||
if (comment && maxLen !== null && maxLen !== undefined && comment.length > maxLen) {
|
||||
@@ -280,8 +281,9 @@ export default router => {
|
||||
usernetwork: 'web',
|
||||
stamp: ~~(Date.now() / 1000),
|
||||
active: !isApprovalRequired,
|
||||
is_oc: !!is_oc
|
||||
}, 'src', 'dest', 'mime', 'size', 'checksum', 'phash', 'username', 'userchannel', 'usernetwork', 'stamp', 'active', 'is_oc')}
|
||||
is_oc: !!is_oc,
|
||||
title: title
|
||||
}, 'src', 'dest', 'mime', 'size', 'checksum', 'phash', 'username', 'userchannel', 'usernetwork', 'stamp', 'active', 'is_oc', 'title')}
|
||||
RETURNING id
|
||||
`;
|
||||
|
||||
@@ -564,8 +566,9 @@ export default router => {
|
||||
usernetwork: 'web',
|
||||
stamp: ~~(Date.now() / 1000),
|
||||
active: !isApprovalRequired,
|
||||
is_oc: !!is_oc
|
||||
}, 'src', 'dest', 'mime', 'size', 'checksum', 'phash', 'username', 'userchannel', 'usernetwork', 'stamp', 'active', 'is_oc')}
|
||||
is_oc: !!is_oc,
|
||||
title: title
|
||||
}, 'src', 'dest', 'mime', 'size', 'checksum', 'phash', 'username', 'userchannel', 'usernetwork', 'stamp', 'active', 'is_oc', 'title')}
|
||||
RETURNING id
|
||||
`;
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ const sendJson = (res, data, code = 200) => {
|
||||
// One-time migration: add original_filename column if it doesn't exist
|
||||
db`ALTER TABLE items ADD COLUMN IF NOT EXISTS original_filename text`.catch(() => {});
|
||||
|
||||
// One-time migration: restore title column for backwards compatibility with old databases
|
||||
db`ALTER TABLE items ADD COLUMN IF NOT EXISTS title text`.catch(() => {});
|
||||
|
||||
export const handleUpload = async (req, res, self) => {
|
||||
// Manual session lookup is required here because this handler is called from a
|
||||
// bypass middleware that runs in parallel with the main session middleware.
|
||||
@@ -106,6 +109,8 @@ export const handleUpload = async (req, res, self) => {
|
||||
const rating = parts.rating;
|
||||
const tagsRaw = parts.tags;
|
||||
const comment = parts.comment ? parts.comment.trim() : '';
|
||||
const rawTitle = parts.title ? parts.title.trim() : '';
|
||||
const title = rawTitle.length > 0 ? rawTitle.substring(0, 500) : null;
|
||||
|
||||
const is_oc = (parts.is_oc === 'true' || parts.is_oc === '1');
|
||||
|
||||
@@ -354,8 +359,9 @@ export const handleUpload = async (req, res, self) => {
|
||||
stamp: ~~(Date.now() / 1000),
|
||||
active: !manualApproval,
|
||||
is_oc: is_oc,
|
||||
original_filename: originalFilename
|
||||
}, 'src', 'dest', 'mime', 'size', 'checksum', 'phash', 'username', 'userchannel', 'usernetwork', 'stamp', 'active', 'is_oc', 'original_filename')
|
||||
original_filename: originalFilename,
|
||||
title: title
|
||||
}, 'src', 'dest', 'mime', 'size', 'checksum', 'phash', 'username', 'userchannel', 'usernetwork', 'stamp', 'active', 'is_oc', 'original_filename', 'title')
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user