From c92306867f172feae751731c4e7a5fad0c4bca5b Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Wed, 12 Aug 2026 17:10:53 +0200 Subject: [PATCH] fix untagged behaviour in pagination --- src/inc/routeinc/f0cklib.mjs | 97 +++++++++++++++------------------- src/inc/routes/ajax.mjs | 5 +- src/inc/routes/apiv2/index.mjs | 26 ++++++++- src/inc/routes/index.mjs | 2 +- 4 files changed, 70 insertions(+), 60 deletions(-) diff --git a/src/inc/routeinc/f0cklib.mjs b/src/inc/routeinc/f0cklib.mjs index 1a1f6d8..c9b9bca 100644 --- a/src/inc/routeinc/f0cklib.mjs +++ b/src/inc/routeinc/f0cklib.mjs @@ -13,6 +13,45 @@ const getGlobalfilter = () => { return filteredTags.length ? filteredTags.map(n => `tag_id = ${n}`).join(" or ") : null; }; +const computeBaseMode = (mode, ratings, session) => { + const effMode = Number(mode ?? 0); + const ratingsArr = (Array.isArray(ratings) && ratings.length > 0) ? ratings : null; + + let baseMode; + if (effMode === 2) { + if (ratingsArr && ratingsArr.includes('untagged') && ratingsArr.length > 1) { + baseMode = lib.getMultiRatingMode(ratingsArr); + } else { + baseMode = lib.getMode(2); + } + } else if (effMode === 3) { + baseMode = (ratingsArr && ratingsArr.length > 1) ? lib.getMultiRatingMode(ratingsArr) : lib.getMode(3); + } else { + const multiRatingSQL = ratingsArr ? lib.getMultiRatingMode(ratingsArr) : null; + baseMode = multiRatingSQL ?? lib.getMode(effMode); + } + + if (!session) { + if ((effMode === 3 || mode === undefined || mode === null) && (!ratingsArr || ratingsArr.length <= 1)) { + if (cfg.websrv.public_nsfw) { + baseMode = cfg.websrv.public_untagged + ? "(items.id in (select item_id from tags_assign where tag_id in (1, 2)) or not exists (select 1 from tags_assign where item_id = items.id))" + : "items.id in (select item_id from tags_assign where tag_id in (1, 2))"; + } else { + baseMode = cfg.websrv.public_untagged + ? "(items.id in (select item_id from tags_assign where tag_id = 1) or not exists (select 1 from tags_assign where item_id = items.id))" + : "items.id in (select item_id from tags_assign where tag_id = 1)"; + } + } else if (!cfg.websrv.public_untagged) { + if (effMode === 2 || (ratingsArr && ratingsArr.length === 1 && ratingsArr[0] === 'untagged')) { + baseMode = "1 = 0"; + } + } + } + return baseMode; +}; + + const resolveNumericItemId = async (itemIdOrSlug) => { if (!itemIdOrSlug) return null; if (typeof itemIdOrSlug === 'number') return itemIdOrSlug; @@ -261,25 +300,7 @@ export default { const tagger = rawTagger ? lib.escapeLike(rawTagger) : null; const tmp = { user, tag: isTitleSearch ? _decodedTag : tag, hall: hallObj || hall, mime, page: actPage, mode: mode, view_mode: fav ? 'favs' : 'uploads', strict: strict, userHall: userHallObj || userHallSlug, userHallOwner, tagger }; - // Multi-rating support: if `ratings` array provided, build an OR-based SQL fragment - const multiRatingSQL = (Array.isArray(ratings) && ratings.length > 0) ? lib.getMultiRatingMode(ratings) : null; - let baseMode = multiRatingSQL ?? lib.getMode(mode ?? 0); - if (!session) { - if ((mode === 3 || mode === undefined || mode === null) && !multiRatingSQL) { - if (cfg.websrv.public_nsfw) { - baseMode = cfg.websrv.public_untagged - ? "(items.id in (select item_id from tags_assign where tag_id in (1, 2)) or not exists (select 1 from tags_assign where item_id = items.id))" - : "items.id in (select item_id from tags_assign where tag_id in (1, 2))"; - } else { - baseMode = cfg.websrv.public_untagged - ? "(items.id in (select item_id from tags_assign where tag_id = 1) or not exists (select 1 from tags_assign where item_id = items.id))" - : "items.id in (select item_id from tags_assign where tag_id = 1)"; - } - } else if (!cfg.websrv.public_untagged && (mode === 2 || (Array.isArray(ratings) && ratings.length === 1 && ratings[0] === 'untagged'))) { - baseMode = "1 = 0"; - } - } - const modequery = baseMode; + const modequery = computeBaseMode(mode, ratings, session); let tagFilter = db``; let titleFilter = db``; @@ -591,24 +612,7 @@ export default { const tmp = { user, tag: isTitleSearch ? _decodedTag : tag, hall, mime, itemid: rawIdOrSlug, strict: strict, userHall: userHallObj || userHallSlug, userHallOwner }; const effMode = Number(mode ?? 0); - const multiRatingSQL = (Array.isArray(ratings) && ratings.length > 0) ? lib.getMultiRatingMode(ratings) : null; - let baseMode = multiRatingSQL ?? lib.getMode(effMode); - if (!session) { - if ((mode === 3 || mode === undefined || mode === null) && !multiRatingSQL) { - if (cfg.websrv.public_nsfw) { - baseMode = cfg.websrv.public_untagged - ? "(items.id in (select item_id from tags_assign where tag_id in (1, 2)) or not exists (select 1 from tags_assign where item_id = items.id))" - : "items.id in (select item_id from tags_assign where tag_id in (1, 2))"; - } else { - baseMode = cfg.websrv.public_untagged - ? "(items.id in (select item_id from tags_assign where tag_id = 1) or not exists (select 1 from tags_assign where item_id = items.id))" - : "items.id in (select item_id from tags_assign where tag_id = 1)"; - } - } else if (!cfg.websrv.public_untagged && (mode === 2 || (Array.isArray(ratings) && ratings.length === 1 && ratings[0] === 'untagged'))) { - baseMode = "1 = 0"; - } - } - const modequery = baseMode; + const modequery = computeBaseMode(mode, ratings, session); let tagFilter = db``; let titleFilter = db``; @@ -1117,24 +1121,7 @@ export default { const strictParams = ((strict || (tag && tag.includes(','))) && tag) ? tag.split(',').map(t => lib.slugify(t)).filter(t => t) : []; const isStrict = strictParams.length > 0; - const multiRatingSQL = (Array.isArray(ratings) && ratings.length > 0) ? lib.getMultiRatingMode(ratings) : null; - let baseMode = multiRatingSQL ?? lib.getMode(mode ?? 0); - if (!session) { - if ((mode === 3 || mode === undefined || mode === null) && !multiRatingSQL) { - if (cfg.websrv.public_nsfw) { - baseMode = cfg.websrv.public_untagged - ? "(items.id in (select item_id from tags_assign where tag_id in (1, 2)) or not exists (select 1 from tags_assign where item_id = items.id))" - : "items.id in (select item_id from tags_assign where tag_id in (1, 2))"; - } else { - baseMode = cfg.websrv.public_untagged - ? "(items.id in (select item_id from tags_assign where tag_id = 1) or not exists (select 1 from tags_assign where item_id = items.id))" - : "items.id in (select item_id from tags_assign where tag_id = 1)"; - } - } else if (!cfg.websrv.public_untagged && (mode === 2 || (Array.isArray(ratings) && ratings.length === 1 && ratings[0] === 'untagged'))) { - baseMode = "1 = 0"; - } - } - const modequery = baseMode; + const modequery = computeBaseMode(mode, ratings, session); let item; diff --git a/src/inc/routes/ajax.mjs b/src/inc/routes/ajax.mjs index 23873e7..531c6dc 100644 --- a/src/inc/routes/ajax.mjs +++ b/src/inc/routes/ajax.mjs @@ -32,13 +32,14 @@ export default (router, tpl) => { if (cfg.main.development) console.log(`[${new Date().toISOString()}] [AJAX] Starting item load for ${req.params.itemid}`); const isRandom = query.random === '1' || req.cookies.random_mode === '1'; + const reqMode = query.mode !== undefined ? +query.mode : req.mode; const ratingsRaw = req.cookies.ratings; - const ratingsArr = ratingsRaw ? decodeURIComponent(ratingsRaw).split(/[|,]/).filter(r => ['sfw','nsfw','nsfl','untagged'].includes(r)) : null; + const ratingsArr = (reqMode === 2 || reqMode === 3) ? null : (ratingsRaw ? decodeURIComponent(ratingsRaw).split(/[|,]/).filter(r => ['sfw','nsfw','nsfl','untagged'].includes(r)) : null); const itemid = req.params.itemid || req.url.pathname.match(/\/ajax\/item\/([a-zA-Z0-9_-]{11}|\d+)/)?.[1]; const data = await f0cklib.getf0ck({ itemid: itemid, - mode: query.mode !== undefined ? +query.mode : req.mode, + mode: reqMode, ratings: ratingsArr, session: req.session, url: contextUrl, diff --git a/src/inc/routes/apiv2/index.mjs b/src/inc/routes/apiv2/index.mjs index d07daf9..082a6c0 100644 --- a/src/inc/routes/apiv2/index.mjs +++ b/src/inc/routes/apiv2/index.mjs @@ -785,8 +785,17 @@ export default router => { }); } + const effMode = req.query.mode !== undefined ? +req.query.mode : (req.mode ?? 3); + const ratingsRaw = req.cookies?.ratings || req.query.ratings; + const ratingsArr = (effMode === 3 || effMode === 2) ? null : (ratingsRaw ? (Array.isArray(ratingsRaw) ? ratingsRaw : decodeURIComponent(ratingsRaw).split(/[|,]/)).filter(r => ['sfw','nsfw','nsfl','untagged'].includes(r)) : null); + let guestTagFilter = db``; if (!session) { + const itemTags = await db`SELECT tag_id FROM tags_assign WHERE item_id = ${+id}`; + const isTagged = itemTags.length > 0; + if (!isTagged && !cfg.websrv.public_untagged) { + return res.json({ success: false, msg: 'no items found' }); + } if (cfg.websrv.public_nsfw) { guestTagFilter = cfg.websrv.public_untagged ? db`and (id in (select item_id from tags_assign where tag_id in (1, 2)) or not exists (select 1 from tags_assign where item_id = items.id))` @@ -798,17 +807,30 @@ export default router => { } } + let modeCondition = db``; + if (effMode === 2) { + modeCondition = db`and not exists (select 1 from tags_assign where item_id = items.id)`; + } else if (effMode === 0) { + modeCondition = db`and id in (select item_id from tags_assign where tag_id = 1)`; + } else if (effMode === 1) { + modeCondition = db`and id in (select item_id from tags_assign where tag_id = 2)`; + } else if (effMode === 4) { + modeCondition = db`and id in (select item_id from tags_assign where tag_id = ${parseInt(cfg.nsfl_tag_id, 10) || 3})`; + } else if (ratingsArr && ratingsArr.length > 0) { + modeCondition = db`and ${db.unsafe(lib.getMultiRatingMode(ratingsArr))}`; + } + const next = await db` select id from "items" - where id > ${+id} and active = true and coalesce(visibility, 0) = 0 ${guestTagFilter} + where id > ${+id} and active = true and coalesce(visibility, 0) = 0 ${guestTagFilter} ${modeCondition} order by id limit 1 `; const prev = await db` select id from "items" - where id < ${+id} and active = true and coalesce(visibility, 0) = 0 ${guestTagFilter} + where id < ${+id} and active = true and coalesce(visibility, 0) = 0 ${guestTagFilter} ${modeCondition} order by id desc limit 1 `; diff --git a/src/inc/routes/index.mjs b/src/inc/routes/index.mjs index 1253aa7..dda4a91 100644 --- a/src/inc/routes/index.mjs +++ b/src/inc/routes/index.mjs @@ -236,7 +236,7 @@ export default (router, tpl) => { hall: req.params.hall, fav: req.params.mode == 'favs', mode: req.mode, - ratings: (() => { const r = req.cookies.ratings; return r ? decodeURIComponent(r).split(/[|,]/).filter(x => ['sfw','nsfw','nsfl','untagged'].includes(x)) : null; })(), + ratings: (() => { if (req.mode === 2 || req.mode === 3) return null; const r = req.cookies.ratings; return r ? decodeURIComponent(r).split(/[|,]/).filter(x => ['sfw','nsfw','nsfl','untagged'].includes(x)) : null; })(), session: req.session, user_id: req.session?.id, is_admin: req.session?.admin,