From 638edc731936f9a4e276fedc1d65c60f41354df6 Mon Sep 17 00:00:00 2001 From: Flummi Date: Wed, 29 Dec 2021 16:26:44 +0100 Subject: [PATCH] f0cklib --- src/inc/lib.mjs | 2 +- src/inc/routes/inc/f0cklib.mjs | 212 +++++++++++++++++++++++++++++ src/inc/routes/index.mjs | 241 ++------------------------------- 3 files changed, 228 insertions(+), 227 deletions(-) create mode 100644 src/inc/routes/inc/f0cklib.mjs diff --git a/src/inc/lib.mjs b/src/inc/lib.mjs index 59f5888..e7de31d 100644 --- a/src/inc/lib.mjs +++ b/src/inc/lib.mjs @@ -59,8 +59,8 @@ export default new class { }; genLink(env) { const link = []; - if(env.user) link.push("user", env.user); if(env.tag) link.push("tag", env.tag); + if(env.user) link.push("user", env.user, env.type ?? 'f0cks'); if(env.mime.length > 2) link.push(env.mime); if(env.page) link.push("p", env.page); return link.join("/"); diff --git a/src/inc/routes/inc/f0cklib.mjs b/src/inc/routes/inc/f0cklib.mjs new file mode 100644 index 0000000..e67d78b --- /dev/null +++ b/src/inc/routes/inc/f0cklib.mjs @@ -0,0 +1,212 @@ +import sql from "../../sql.mjs"; +import lib from "../../lib.mjs"; +import cfg from "../../config.mjs"; +import fs from "fs"; +import url from "url"; + +export default { + getf0cks: async (o = { user, tag, mime, page, mode }) => { + const user = o.user ? decodeURI(o.user) : null; + const tag = lib.parseTag(o.tag ?? null); + const mime = (o.mime ?? ""); + const page = +(o.page ?? 1); + const smime = cfg.allowedMimes.includes(mime) ? mime + "/%" : mime === "" ? "%" : "%"; + + const tmp = { user, tag, mime, smime, page }; + + const modequery = mime == "audio" ? lib.getMode(0) : lib.getMode(o.mode ?? 0); + + let data; + let total; + + if(tag) { + if(tag.match(/sfw/) || tag.length <= 2) + return { + success: false, + message: "nope." + }; + + total = (await sql("items") + .select("items.id", "items.mime", "st.tag") + .innerJoin( + sql("tags") + .select("tags_assign.item_id", "tags.tag") + .leftJoin("tags_assign", "tags_assign.tag_id", "tags.id") + .where("tags.tag", "like", "%"+tag+"%") + .groupBy("tags_assign.item_id") + .as("st"), + "st.item_id", "items.id" + ) + .whereRaw(modequery) + .count("* as total") + )[0]?.total; + } + else { + total = (await sql("items") + .whereRaw(modequery) + .andWhere("items.mime", "like", smime) + .andWhere("items.username", "like", user ? user : "%") + .count("* as total") + )[0]?.total; + } + + if(!total || total.length === 0) + return { + success: false, + message: "404 - no f0cks given" + }; + + const pages = +Math.ceil(total / cfg.websrv.eps); + const act_page = Math.min(pages, page || 1); + const offset = Math.max(0, (act_page - 1) * cfg.websrv.eps); + + let rows = sql("items") + .select("items.id", "items.mime", "tags_assign.tag_id") + .joinRaw("left join tags_assign on tags_assign.item_id = items.id and (tags_assign.tag_id = 1 or tags_assign.tag_id = 2)") + .whereRaw(modequery) + .andWhere("items.mime", "like", smime) + .andWhere("items.username", "like", user ? user : "%") + .orderBy("items.id", "desc") + .offset(offset) + .limit(cfg.websrv.eps); + + if(tag) rows = rows + .innerJoin( + sql("tags") + .select("tags_assign.item_id", "tags.tag") + .leftJoin("tags_assign", "tags_assign.tag_id", "tags.id") + .where("tags.tag", "like", "%"+tag+"%") + .groupBy("tags_assign.item_id") + .as("st"), + "st.item_id", "items.id" + ); + + rows = await rows; + + + if(rows.length === 0) + return { + success: false, + message: "oopsi woopsi" + }; + + /*rows.forEach(e => { + if(!fs.existsSync(`public/t/${e.id}.png`)) + fs.copyFileSync("public/s/img/broken.png", `public/t/${e.id}.png`); + });*/ + + const cheat = []; + for(let i = Math.max(1, act_page - 3); i <= Math.min(act_page + 3, pages); i++) + cheat.push(i); + + const link = lib.genLink({ user, tag, mime, act_page }); + + data = { + success: true, + items: rows, + pagination: { + start: 1, + end: pages, + prev: (act_page > 1) ? act_page - 1 : null, + next: (act_page < pages) ? act_page + 1 : null, + page: act_page, + cheat: cheat, + uff: false + }, + link: link, + tmp: tmp + }; + return data; + }, + getf0ck: async (o = ({ user, tag, mime, itemid, mode })) => { + const user = o.user ? decodeURI(o.user) : null; + const tag = lib.parseTag(o.tag ?? null); + const mime = (o.mime ?? ""); + const itemid = +(o.itemid ?? 404); + const smime = cfg.allowedMimes.includes(mime) ? mime + "/%" : mime === "" ? "%" : "%"; + + const tmp = { user, tag, mime, smime, itemid }; + + const modequery = mime == "audio" ? lib.getMode(0) : lib.getMode(o.mode ?? 0); + + if(itemid === 404) { + return { + success: false, + message: "404 - f0ck not found" + }; + } + + let items = sql("items").select("*").orderBy("items.id", "desc").whereRaw(modequery); + if(tag) { + items = items.innerJoin( + sql("tags") + .select("tags_assign.item_id", "tags.tag") + .leftJoin("tags_assign", "tags_assign.tag_id", "tags.id") + .where("tags.tag", "like", "%"+tag+"%") + .groupBy("tags_assign.item_id") + .as("st"), + "st.item_id", "items.id" + ); + } + if(user) + items = items.andWhere("username", "like", "%" + user + "%"); + if(mime) + items = items.andWhere("mime", "like", mime + "/%"); + + items = await items; + + const item = items.findIndex(i => i.id === itemid); + const actitem = items[item]; + + if(!actitem) { // sfw-check! + return { + success: false, + message: "Sorry this post is currently not visible, possible causes are: not tagged, post doesn't exist(yet) or invalid filter settings" + }; + } + + const tags = await lib.getTags(itemid); + const cheat = items.slice(Math.max(0, item - 3), item + 4).map(i => i.id); + const link = lib.genLink({ user, tag, mime, act_page: itemid }); + + const data = { + success: true, + user: { + name: actitem.username, + channel: actitem.usernetwork == "Telegram" && actitem.userchannel !== "f0ck.me" ? "anonymous" : actitem.userchannel, + network: actitem.usernetwork + }, + item: { + id: actitem.id, + src: { + long: actitem.src, + short: url.parse(actitem.src).hostname, + }, + thumbnail: `${cfg.websrv.paths.thumbnails}/${actitem.id}.png`, + coverart: `${cfg.websrv.paths.coverarts}/${actitem.id}.png`, + dest: `${cfg.websrv.paths.images}/${actitem.dest}`, + mime: actitem.mime, + size: lib.formatSize(actitem.size), + timestamp: { + timeago: lib.timeAgo(new Date(actitem.stamp * 1e3).toISOString()), + timefull: new Date(actitem.stamp * 1e3).toISOString() + }, + tags: tags + }, + title: `${actitem.id} - f0ck.me`, + pagination: { + end: items[items.length - 1]?.id, + start: items[0]?.id, + next: items[item + 1]?.id, + prev: items[item - 1]?.id, + page: actitem.id, + cheat: cheat, + uff: true + }, + link: link, + phrase: cfg.websrv.phrases[~~(Math.random() * cfg.websrv.phrases.length)], + tmp: tmp + }; + return data; + } +}; diff --git a/src/inc/routes/index.mjs b/src/inc/routes/index.mjs index f6ae5da..7294551 100644 --- a/src/inc/routes/index.mjs +++ b/src/inc/routes/index.mjs @@ -1,10 +1,8 @@ import cfg from "../config.mjs"; import sql from "../sql.mjs"; import lib from "../lib.mjs"; -import fs from "fs"; -import url from "url"; +import f0cklib from "./inc/f0cklib.mjs"; -const allowedMimes = [ "audio", "image", "video" ]; const auth = async (req, res, next) => { if(!req.session) return res.redirect("/login"); @@ -12,236 +10,27 @@ const auth = async (req, res, next) => { }; export default (router, tpl) => { - router.get(/^\/?(?:tag\/(?.+?))?(?:user\/(?.+?))?(?:\/(?image|audio|video))?(?:\/p\/(?\d+))?(?:\/(?\d+))?$/, async (req, res) => { - const user = req.params.user ? decodeURI(req.params.user) : null; - const tag = lib.parseTag(req.params.tag ?? null); - const mime = (req.params.mime ?? ""); - const smime = allowedMimes.includes(mime) ? mime + "/%" : mime === "" ? "%" : "%"; - const page = +(req.params.page ?? 1); - const itemid = +(req.params.itemid ?? null); - - const output = { - user, tag, mime, smime, page, itemid - }; - - const mode = itemid > 0 ? "item" : "index"; - const modequery = mime == "audio" ? lib.getMode(0) : lib.getMode(req.session.mode ?? 0); - let data; - - if(user && (await sql("items").where("username", "like", user).count("* as total"))[0].total === 0) + router.get(/^\/?(?:\/tag\/(?.+?))?(?:\/user\/(?.+?)\/(?:f0cks|favs))?(?:\/(?image|audio|video))?(?:\/p\/(?\d+))?(?:\/(?\d+))?$/, async (req, res) => { + const mode = req.params.itemid ? 'item' : 'index'; + const data = await (req.params.itemid ? f0cklib.getf0ck : f0cklib.getf0cks)({ + user: req.params.user, + tag: req.params.tag, + mime: req.params.mime, + page: req.params.page, + itemid: req.params.itemid, + mode: req.session.mode + }); + if(!data.success) { return res.reply({ code: 404, body: tpl.render('error', { - message: "404 - user not found", + message: data.message, tmp: null }, req) }); - - if(mode === "item") { // item! - if(itemid === 404) { - return res.reply({ - code: 404, - body: tpl.render('error', { - message: "404 - f0ck not found", - tmp: null - }, req) - }); - } - - let items = sql("items").select("*").orderBy("items.id", "desc").whereRaw(modequery); - if(tag) { - items = items.innerJoin( - sql("tags") - .select("tags_assign.item_id", "tags.tag") - .leftJoin("tags_assign", "tags_assign.tag_id", "tags.id") - .where("tags.tag", "like", "%"+tag+"%") - .groupBy("tags_assign.item_id") - .as("st"), - "st.item_id", "items.id" - ); - } - if(user) - items = items.andWhere("username", "like", "%" + user + "%"); - if(mime) - items = items.andWhere("mime", "like", mime + "/%"); - - items = await items; - - const item = items.findIndex(i => i.id === itemid); - const actitem = items[item]; - - if(!actitem) { // sfw-check! - return res.reply({ - code: 404, - body: tpl.render('error', { - message: "Sorry this post is currently not visible, possible causes are: not tagged, post doesn't exist(yet) or invalid filter settings", - tmp: null - }, req) - }); - } - - const tags = await lib.getTags(itemid); - const cheat = items.slice(Math.max(0, item - 3), item + 4).map(i => i.id); - const link = lib.genLink({ user, tag, mime, act_page: itemid }); - - data = { - user: { - name: actitem.username, - channel: actitem.usernetwork == "Telegram" && actitem.userchannel !== "f0ck.me" ? "anonymous" : actitem.userchannel, - network: actitem.usernetwork - }, - item: { - id: actitem.id, - src: { - long: actitem.src, - short: url.parse(actitem.src).hostname, - }, - thumbnail: `${cfg.websrv.paths.thumbnails}/${actitem.id}.png`, - coverart: `${cfg.websrv.paths.coverarts}/${actitem.id}.png`, - dest: `${cfg.websrv.paths.images}/${actitem.dest}`, - mime: actitem.mime, - size: lib.formatSize(actitem.size), - timestamp: { - timeago: lib.timeAgo(new Date(actitem.stamp * 1e3).toISOString()), - timefull: new Date(actitem.stamp * 1e3).toISOString() - }, - tags: tags - }, - title: `${actitem.id} - f0ck.me`, - pagination: { - end: items[items.length - 1]?.id, - start: items[0]?.id, - next: items[item + 1]?.id, - prev: items[item - 1]?.id, - page: actitem.id, - cheat: cheat, - link: link, - uff: true - }, - link: link, - phrase: cfg.websrv.phrases[~~(Math.random() * cfg.websrv.phrases.length)], - tmp: output - }; - } - else { // page! - let total, rows; - - if(tag) { - if(tag.match(/sfw/) || tag.length <= 2) - return res.reply({ - code: 404, - body: tpl.render('error', { - message: "nope.", - tmp: null - }, req) - }); - - total = (await sql("items") - .select("items.id", "items.mime", "st.tag") - .innerJoin( - sql("tags") - .select("tags_assign.item_id", "tags.tag") - .leftJoin("tags_assign", "tags_assign.tag_id", "tags.id") - .where("tags.tag", "like", "%"+tag+"%") - .groupBy("tags_assign.item_id") - .as("st"), - "st.item_id", "items.id" - ) - .whereRaw(modequery) - .count("* as total") - )[0]?.total; - } - else { - total = (await sql("items") - .whereRaw(modequery) - .andWhere("items.mime", "like", smime) - .andWhere("items.username", "like", user ? user : "%") - .count("* as total") - )[0]?.total; - } - - if(!total || total.length === 0) - return res.reply({ - code: 404, - body: tpl.render('error', { - message: "404 - no f0cks given", - tmp: null - }, req) - }); - - const pages = +Math.ceil(total / cfg.websrv.eps); - const act_page = Math.min(pages, page || 1); - const offset = Math.max(0, (act_page - 1) * cfg.websrv.eps); - - if(tag) { - rows = await sql("items") - .select("items.id", "items.mime", "st.tag", "tags_assign.tag_id") - .joinRaw("left join tags_assign on tags_assign.item_id = items.id and (tags_assign.tag_id = 1 or tags_assign.tag_id = 2)") - .innerJoin( - sql("tags") - .select("tags_assign.item_id", "tags.tag") - .leftJoin("tags_assign", "tags_assign.tag_id", "tags.id") - .where("tags.tag", "like", "%"+tag+"%") - .groupBy("tags_assign.item_id") - .as("st"), - "st.item_id", "items.id" - ) - .whereRaw(modequery) - .orderBy("items.id", "desc") - .offset(offset) - .limit(cfg.websrv.eps); - } - else { - rows = await sql("items") - .select("items.id", "items.mime", "tags_assign.tag_id") - .joinRaw("left join tags_assign on tags_assign.item_id = items.id and (tags_assign.tag_id = 1 or tags_assign.tag_id = 2)") - .whereRaw(modequery) - .andWhere("items.mime", "like", smime) - .andWhere("items.username", "like", user ? user : "%") - .orderBy("items.id", "desc") - .offset(offset) - .limit(cfg.websrv.eps); - } - - if(rows.length === 0) - return res.reply({ - code: 404, - body: tpl.render('error', { - message: "oopsi woopsi", - tmp: null - }, req) - }); - - rows.forEach(e => { - if(!fs.existsSync(`public/t/${e.id}.png`)) - fs.copyFileSync("public/s/img/broken.png", `public/t/${e.id}.png`); - }); - - const cheat = []; - for(let i = Math.max(1, act_page - 3); i <= Math.min(act_page + 3, pages); i++) - cheat.push(i); - - const link = lib.genLink({ user, tag, mime, act_page }); - - data = { - items: rows, - pagination: { - start: 1, - end: pages, - prev: (act_page > 1) ? act_page - 1 : null, - next: (act_page < pages) ? act_page + 1 : null, - page: act_page, - cheat: cheat, - link: link, - uff: false - }, - last: rows[rows.length - 1].id, - link: link, - tmp: output - }; } - res.reply({ body: tpl.render(mode, data, req) }); + return res.reply({ body: tpl.render(mode, data, req) }); }); router.get(/^\/(about)$/, (req, res) => { @@ -271,7 +60,7 @@ export default (router, tpl) => { res.redirect(`/${referer}`); }); - router.get(/^\/ranking/, async (req, res) => { + router.get(/^\/ranking$/, async (req, res) => { try { const list = await sql('tags_assign') .select('user.user', sql.raw('count(distinct tag_id, item_id) count'))