This commit is contained in:
2026-09-11 19:00:58 +02:00
parent 8d6edfef5e
commit d72eae7509
14 changed files with 681 additions and 373 deletions
+71 -40
View File
@@ -650,12 +650,28 @@ export default router => {
});
}
const rows = await db`
SELECT *
FROM "items"
WHERE id = ${data.itemid} AND active = true
LIMIT 1
`;
// Run item fetch + page lookup in parallel — saves one sequential DB round-trip
const [rows, itemPage] = await Promise.all([
db`
SELECT *
FROM "items"
WHERE id = ${data.itemid} AND active = true
LIMIT 1
`,
f0cklib.getItemPage({
targetItemId: data.itemid,
user, tag, hall, userHall, userHallOwner, mime,
fav: isFav,
mode,
ratings: ratingsArr && ratingsArr.length > 0 ? ratingsArr : null,
strict: isStrict,
session: !!req.session,
exclude: req.session?.excluded_tags || [],
user_id: req.session?.id,
is_admin: req.session?.admin
}).catch(() => 1)
]);
const item = rows[0];
if (!item) {
@@ -685,7 +701,8 @@ export default router => {
slug: (getEnableItemSlugs() && item.slug) ? item.slug : null,
dest: relativeDest,
url: directUrl,
direct_url: directUrl
direct_url: directUrl,
page: itemPage
}
});
});
@@ -1436,49 +1453,63 @@ export default router => {
return res.json({ success: false, msg: 'Item not found' }, 404);
}
const isOwner = item[0].username === req.session.user;
const isAdmin = req.session.admin || req.session.is_moderator;
const isOwner = !!(item[0].username && req.session.user && item[0].username.toLowerCase() === req.session.user.toLowerCase());
const isAdmin = !!(req.session.admin || req.session.is_moderator);
if (!isOwner && !isAdmin) {
return res.json({ success: false, msg: 'Unauthorized' }, 403);
}
const nsfl_id = cfg.nsfl_tag_id || 3;
const existingRating = await db`
SELECT tag_id FROM tags_assign
WHERE item_id = ${itemid} AND tag_id IN (1, 2, ${nsfl_id})
LIMIT 1
`;
const currentRatingId = existingRating.length > 0 ? existingRating[0].tag_id : null;
const nsflTagRow = await db`SELECT id FROM tags WHERE normalized = 'nsfl' LIMIT 1`;
const nsfl_id = nsflTagRow.length > 0 ? nsflTagRow[0].id : (cfg.nsfl_tag_id || 11517);
let newRatingId;
const reqRating = req.body?.rating || req.post?.rating || req.url?.qs?.rating;
if (reqRating === 'sfw') {
newRatingId = 1;
} else if (reqRating === 'nsfw') {
newRatingId = 2;
} else if (reqRating === 'nsfl') {
newRatingId = nsfl_id;
} else {
// fallback to cycling
if (currentRatingId === 1) {
newRatingId = 2; // SFW -> NSFW
} else if (currentRatingId === 2) {
newRatingId = cfg.enable_nsfl ? nsfl_id : 1; // NSFW -> NSFL (if enabled) or SFW
} else {
newRatingId = 1; // NSFL or none -> SFW
}
}
let currentRatingId = null;
await db.begin(async sql => {
// Remove old rating tags
await sql`DELETE FROM tags_assign WHERE item_id = ${itemid} AND tag_id IN (1, 2, ${nsfl_id})`;
// Lock the item row exclusively so any concurrent rating update for this post MUST wait
await sql`SELECT id FROM items WHERE id = ${itemid} FOR UPDATE`;
const existingRating = await sql`
SELECT tag_id FROM tags_assign
WHERE item_id = ${itemid}
AND (tag_id IN (1, 2, ${nsfl_id}) OR tag_id IN (SELECT id FROM tags WHERE normalized IN ('sfw', 'nsfw', 'nsfl')))
ORDER BY tag_id DESC
LIMIT 1
`;
currentRatingId = existingRating.length > 0 ? existingRating[0].tag_id : null;
const reqRating = req.body?.rating || req.post?.rating || req.url?.qs?.rating;
if (reqRating === 'sfw') {
newRatingId = 1;
} else if (reqRating === 'nsfw') {
newRatingId = 2;
} else if (reqRating === 'nsfl') {
newRatingId = nsfl_id;
} else {
// fallback to cycling
if (currentRatingId === 1) {
newRatingId = 2; // SFW -> NSFW
} else if (currentRatingId === 2) {
newRatingId = cfg.enable_nsfl ? nsfl_id : 1; // NSFW -> NSFL (if enabled) or SFW
} else {
newRatingId = 1; // NSFL or none -> SFW
}
}
// Remove ALL existing rating tags for this item atomically
await sql`
DELETE FROM tags_assign
WHERE item_id = ${itemid}
AND (tag_id IN (1, 2, ${nsfl_id}) OR tag_id IN (SELECT id FROM tags WHERE normalized IN ('sfw', 'nsfw', 'nsfl')))
`;
// Insert new rating tag
await sql`
INSERT INTO tags_assign (item_id, tag_id, user_id)
VALUES (${itemid}, ${newRatingId}, ${req.session.id})
`;
if (newRatingId > 0) {
await sql`
INSERT INTO tags_assign (item_id, tag_id, user_id)
VALUES (${itemid}, ${newRatingId}, ${req.session.id})
`;
}
// Ensure blurred thumbnail exists
await queue.genBlurredThumbnail(itemid).catch(err => {