diff --git a/src/inc/lib.mjs b/src/inc/lib.mjs index f62646e..5cda18b 100644 --- a/src/inc/lib.mjs +++ b/src/inc/lib.mjs @@ -96,27 +96,36 @@ export default new class { const derivedKey = await scrypt(str, salt, 64); return crypto.timingSafeEqual(keyBuffer, derivedKey); }; + async auth(req, res, next) { + if(!req.session) { + return res.reply({ + code: 401, + body: "401 - Unauthorized" + }); + } + return next(); + }; async getTags(itemid) { const tags = await sql("tags_assign") .select("tags.id", "tags.tag", "tags.normalized", "user.user") .leftJoin("tags", "tags.id", "tags_assign.tag_id") .leftJoin("user", "user.id", "tags_assign.user_id") - .where("tags_assign.item_id", itemid) + .where("tags_assign.item_id", +itemid) .orderBy("tags.id", "asc"); for(let t = 0; t < tags.length; t++) { if(tags[t].tag.startsWith(">")) tags[t].badge = "badge-greentext badge-light"; - else if(tags[t].tag.match(/ukraine/i)) + else if(tags[t].normalized === "ukraine") tags[t].badge = "badge-ukraine badge-light"; - else if(/[а-яА-ЯЁё]/.test(tags[t].tag) || tags[t].tag.match(/russia/)) + else if(/[а-яё]/.test(tags[t].normalized) || tags[t].normalized === "russia") tags[t].badge = "badge-russia badge-light"; - else if(tags[t].tag.match(/german/i)) + else if(tags[t].normalized === "german") tags[t].badge = "badge-german badge-light"; - else if(tags[t].tag.match(/dutch/i)) + else if(tags[t].normalized === "dutch") tags[t].badge = "badge-dutch badge-light"; - else if(tags[t].tag === "sfw") + else if(tags[t].normalized === "sfw") tags[t].badge = "badge-success"; - else if(tags[t].tag === "nsfw") + else if(tags[t].normalized === "nsfw") tags[t].badge = "badge-danger"; else tags[t].badge = "badge-light"; diff --git a/src/inc/routes/apiv2.mjs b/src/inc/routes/apiv2/index.mjs similarity index 54% rename from src/inc/routes/apiv2.mjs rename to src/inc/routes/apiv2/index.mjs index 789b9b2..f620b61 100644 --- a/src/inc/routes/apiv2.mjs +++ b/src/inc/routes/apiv2/index.mjs @@ -1,24 +1,13 @@ -import sql from "../sql.mjs"; -import lib from "../lib.mjs"; +import sql from '../../sql.mjs'; +import lib from '../../lib.mjs'; const allowedMimes = [ "audio", "image", "video", "%" ]; -const auth = async (req, res, next) => { - if(!req.session) { - return res.reply({ - code: 401, - body: "401 - Unauthorized" - }); - } - return next(); -}; - -export default (router, tpl) => { +export default router => { router.group(/^\/api\/v2/, group => { - group.get(/$/, (req, res) => { res.end("api lol"); }); - + group.get(/\/random(\/user\/.+|\/image|\/video|\/audio)?$/, async (req, res) => { const user = req.url.split[3] === "user" ? req.url.split[4] : "%"; const mime = (allowedMimes.filter(n => req.url.split[3]?.startsWith(n))[0] ? req.url.split[3] : "") + "%"; @@ -95,147 +84,49 @@ export default (router, tpl) => { items: rows.length > 0 ? rows : [] }); }); - - // adminzeugs - group.delete(/\/admin\/(?\d+)\/tags\/(?.*)/, auth, async (req, res) => { - // delete tag - if(!req.params.postid || !req.params.tagname) { + + // tags lol + + group.put(/\/admin\/tags\/(?.*)/, lib.auth, async (req, res) => { + if(!req.params.tagname || !req.post.newtag) { return res.json({ success: false, - msg: 'missing postid or tagname' - }); + msg: 'missing tagname or newtag', + debug: { + params: req.params.tagname, + post: req.post + } + }, 400); // bad request } - const postid = +req.params.postid; - const tagname = decodeURIComponent(req.params.tagname); + const tagname = req.params.tagname; + const newtag = req.post.newtag; - const tags = await lib.getTags(postid); - - const tagid = tags.filter(t => t.tag === tagname)[0]?.id ?? null; + const tmptag = ( + await sql('tags') + .where('tag', tagname) + .limit(1) + )[0]; - if(!tagid) { + if(!tmptag) { return res.json({ success: false, - msg: 'tag is not assigned', - tags: await lib.getTags(postid) - }); + msg: 'no tag found' + }, 404); // not found } - let q = sql("tags_assign").where("tag_id", tagid).andWhere("item_id", postid).del(); - if(req.session.level < 50) - q = q.andWhere("user_id", req.session.id); - const reply = !!(await q); - - return res.json({ - success: reply, - tagid, - tags: await lib.getTags(postid) - }) - }); - - group.post(/\/admin\/(?\d+)\/tags/, auth, async (req, res) => { - // assign and/or create tag - if(!req.params.postid || !req.post.tagname) { - return res.json({ - success: false, - msg: 'missing postid or tag' - }); - } - - const postid = +req.params.postid; - const tagname = req.post.tagname?.trim(); - - if(tagname.length >= 45) { - return res.json({ - success: false, - msg: 'tag is too long!' - }); - } - - try { - let tagid = ( - await sql("tags") - .select("id") - .whereRaw("normalized = slugify(?)", [ tagname ]) - )?.[0]?.id; - - if(!tagid) { // create new tag - tagid = (await sql("tags").returning("id").insert({ - tag: tagname - }))[0]; - } - await sql("tags_assign").insert({ - tag_id: tagid, - item_id: postid, - user_id: req.session.id - }); - } catch(err) { - return res.json({ - success: false, - msg: err.message, - tags: await lib.getTags(postid) - }); - } - - return res.json({ - success: true, - postid: postid, - tag: tagname, - tags: await lib.getTags(postid) - }); - }); - - group.get(/\/admin\/(?\d+)\/tags$/, auth, async (req, res) => { - // get tags - if(!req.params.postid) { - return res.json({ - success: false, - msg: 'missing postid' - }); - } - - return res.json({ - success: true, - tags: await lib.getTags(+req.params.postid) - }); - }); - - group.put(/\/admin\/(?\d+)\/tags\/toggle$/, auth, async (req, res) => { - // xD - if(!req.params.postid) { - return res.json({ - success: false, - msg: 'missing postid' - }); - } - - const postid = +req.params.postid; - - if(!(await lib.getTags(postid)).filter(tag => [1,2].includes(tag.id)).length) { - // insert - await sql('tags_assign').insert({ - item_id: postid, - tag_id: 1, - user_id: req.session.id - }); - } - else { - // update - await sql('tags_assign') + const q = ( + await sql('tags') .update({ - tag_id: sql.raw('(array[2,1])[tag_id]') - }) - .whereRaw('tag_id = any(array[1,2])') - .andWhere('item_id', postid); - } + tag: newtag + }, [ 'tag', 'normalized' ]) + .where('tag', tagname) + )?.[0]; - return res.json({ - success: true, - tags: await lib.getTags(postid) - }); + return res.json(q, tagname === newtag ? 200 : 201); // created (modified) }); - group.get(/\/admin\/tags\/suggest$/, auth, async (req, res) => { + group.get(/\/admin\/tags\/suggest$/, lib.auth, async (req, res) => { const reply = { success: false, suggestions: {} @@ -264,8 +155,8 @@ export default (router, tpl) => { return res.json(reply); }); - - group.post(/\/admin\/deletepost$/, auth, async (req, res) => { + + group.post(/\/admin\/deletepost$/, lib.auth, async (req, res) => { if(!req.post.postid) { return res.json({ success: false, @@ -281,7 +172,7 @@ export default (router, tpl) => { }); }); - group.post(/\/admin\/togglefav$/, auth, async (req, res) => { + group.post(/\/admin\/togglefav$/, lib.auth, async (req, res) => { const postid = +req.post.postid; let favs = await sql('favorites').select('user_id').where('item_id', postid); @@ -310,7 +201,7 @@ export default (router, tpl) => { favs }); }); - + }); return router; diff --git a/src/inc/routes/apiv2/tags.mjs b/src/inc/routes/apiv2/tags.mjs new file mode 100644 index 0000000..93b4770 --- /dev/null +++ b/src/inc/routes/apiv2/tags.mjs @@ -0,0 +1,147 @@ +import sql from '../../sql.mjs'; +import lib from '../../lib.mjs'; + +export default router => { + router.group(/^\/api\/v2\/admin\/(?\d+)\/tags/, group => { + group.get(/$/, lib.auth, async (req, res) => { + // get tags + if(!req.params.postid) { + return res.json({ + success: false, + msg: 'missing postid' + }); + } + + return res.json({ + success: true, + tags: await lib.getTags(+req.params.postid) + }); + }); + + group.post(/$/, lib.auth, async (req, res) => { + // assign and/or create tag + if(!req.params.postid || !req.post.tagname) { + return res.json({ + success: false, + msg: 'missing postid or tag' + }); + } + + const postid = +req.params.postid; + const tagname = req.post.tagname?.trim(); + + if(tagname.length >= 45) { + return res.json({ + success: false, + msg: 'tag is too long!' + }); + } + + try { + let tagid = ( + await sql("tags") + .select("id") + .whereRaw("normalized = slugify(?)", [ tagname ]) + )?.[0]?.id; + + if(!tagid) { // create new tag + tagid = (await sql("tags").returning("id").insert({ + tag: tagname + }))[0]; + } + await sql("tags_assign").insert({ + tag_id: tagid, + item_id: postid, + user_id: req.session.id + }); + } catch(err) { + return res.json({ + success: false, + msg: err.message, + tags: await lib.getTags(postid) + }); + } + + return res.json({ + success: true, + postid: postid, + tag: tagname, + tags: await lib.getTags(postid) + }); + }); + + group.put(/\/toggle$/, lib.auth, async (req, res) => { + // xD + if(!req.params.postid) { + return res.json({ + success: false, + msg: 'missing postid' + }); + } + + const postid = +req.params.postid; + + if(!(await lib.getTags(postid)).filter(tag => [1,2].includes(tag.id)).length) { + // insert + await sql('tags_assign').insert({ + item_id: postid, + tag_id: 1, + user_id: req.session.id + }); + } + else { + // update + await sql('tags_assign') + .update({ + tag_id: sql.raw('(array[2,1])[tag_id]') + }) + .whereRaw('tag_id = any(array[1,2])') + .andWhere('item_id', postid); + } + + return res.json({ + success: true, + tags: await lib.getTags(postid) + }); + }); + + group.delete(/\/(?.*)/, lib.auth, async (req, res) => { + // delete tag + if(!req.params.postid || !req.params.tagname) { + return res.json({ + success: false, + msg: 'missing postid or tagname' + }); + } + + const postid = +req.params.postid; + const tagname = decodeURIComponent(req.params.tagname); + + const tags = await lib.getTags(postid); + + const tagid = tags.filter(t => t.tag === tagname)[0]?.id ?? null; + + if(!tagid) { + return res.json({ + success: false, + msg: 'tag is not assigned', + tags: await lib.getTags(postid) + }); + } + + let q = sql("tags_assign").where("tag_id", tagid).andWhere("item_id", postid).del(); + if(req.session.level < 50) + q = q.andWhere("user_id", req.session.id); + const reply = !!(await q); + + return res.json({ + success: reply, + tagid, + tags: await lib.getTags(postid) + }) + }); + + }); + + return router; +}; \ No newline at end of file