318 lines
8.1 KiB
JavaScript
318 lines
8.1 KiB
JavaScript
import { promises as fs } from "fs";
|
|
import db from '../../sql.mjs';
|
|
import lib from '../../lib.mjs';
|
|
import search from '../../routeinc/search.mjs';
|
|
|
|
const allowedMimes = [ "audio", "image", "video", "%" ];
|
|
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] : "") + "%";
|
|
|
|
const rows = await db`
|
|
select *
|
|
from "items"
|
|
where
|
|
mime ilike ${mime} and
|
|
username ilike ${user} and
|
|
active = 'true'
|
|
order by random()
|
|
limit 1
|
|
`;
|
|
|
|
return res.json({
|
|
success: rows.length > 0,
|
|
items: rows.length > 0 ? rows[0] : []
|
|
});
|
|
});
|
|
|
|
group.get(/\/items\/get/, async (req, res) => {
|
|
let eps = 150;
|
|
|
|
const opt = {
|
|
older: req.url.qs.older ?? null,
|
|
newer: req.url.qs.newer ?? null,
|
|
mode: +req.url.qs.mode ?? 0 // 0 sfw, 1 nsfw, 2 untagged, 3 all
|
|
};
|
|
|
|
const newest = (await db`select max(id) as id from "items"`)[0].id;
|
|
const oldest = (await db`select min(id) as id from "items"`)[0].id;
|
|
const modequery = lib.getMode(opt.mode);
|
|
|
|
const rows = (await db`
|
|
select "items".id, "items".mime, coalesce("tags_assign".tag_id, 0) as tag_id
|
|
from "items"
|
|
left join "tags_assign" on "tags_assign".item_id = "items".id and ("tags_assign".tag_id = 1 or "tags_assign".tag_id = 2)
|
|
where
|
|
${db.unsafe(modequery)} and
|
|
active = 'true'
|
|
${
|
|
opt.older
|
|
? db`and id <= ${opt.older}`
|
|
: opt.newer
|
|
? db`and id >= ${opt.newer}`
|
|
: db``
|
|
}
|
|
order by id ${
|
|
opt.newer
|
|
? db`asc`
|
|
: db`desc`
|
|
}
|
|
limit ${eps}
|
|
`).sort((a, b) => b.id - a.id);
|
|
|
|
return res.json({
|
|
atEnd: rows[0].id === newest,
|
|
atStart: rows[rows.length - 1].id === oldest,
|
|
success: true,
|
|
items: rows
|
|
}, 200);
|
|
});
|
|
|
|
group.get(/\/item\/[0-9]+$/, async (req, res) => {
|
|
const id = +req.url.split[3];
|
|
|
|
const item = await db`
|
|
select *
|
|
from "items"
|
|
where id = ${+id} and active = 'true'
|
|
limit 1
|
|
`;
|
|
const next = await db`
|
|
select id
|
|
from "items"
|
|
where id > ${+id} and active = 'true'
|
|
order by id
|
|
limit 1
|
|
`;
|
|
const prev = await db`
|
|
select id
|
|
from "items"
|
|
where id < ${+id} and active = 'true'
|
|
order by id desc
|
|
limit 1
|
|
`;
|
|
|
|
if(item.length === 0) {
|
|
return res.json({
|
|
success: false,
|
|
msg: 'no items found'
|
|
});
|
|
}
|
|
|
|
const rows = {
|
|
...item[0],
|
|
...{
|
|
next: next[0]?.id ?? null,
|
|
prev: prev[0]?.id ?? null
|
|
}
|
|
};
|
|
|
|
return res.json({
|
|
success: true,
|
|
rows
|
|
});
|
|
});
|
|
|
|
group.get(/\/user\/.*(\/\d+)?$/, async (req, res) => {
|
|
const user = req.url.split[3];
|
|
const eps = +req.url.split[4] || 50;
|
|
|
|
const rows = db`
|
|
select id, mime, size, src, stamp, userchannel, username, usernetwork
|
|
from "items"
|
|
where username = ${user} and active = 'true'
|
|
order by stamp desc
|
|
limit ${+eps}
|
|
`;
|
|
|
|
return res.json({
|
|
success: rows.length > 0,
|
|
items: rows.length > 0 ? rows : []
|
|
});
|
|
});
|
|
|
|
// tags lol
|
|
|
|
group.put(/\/admin\/tags\/(?<tagname>.*)/, lib.auth, async (req, res) => {
|
|
if(!req.params.tagname || !req.post.newtag) {
|
|
return res.json({
|
|
success: false,
|
|
msg: 'missing tagname or newtag',
|
|
debug: {
|
|
params: req.params.tagname,
|
|
post: req.post
|
|
}
|
|
}, 400); // bad request
|
|
}
|
|
|
|
const tagname = decodeURIComponent(req.params.tagname);
|
|
const newtag = req.post.newtag;
|
|
|
|
if(['sfw', 'nsfw'].includes(tagname) || ['sfw', 'nsfw'].includes(newtag)) {
|
|
return res.json({
|
|
msg: 'f0ck you'
|
|
}, 405); // method not allowed
|
|
}
|
|
|
|
const tmptag = (await db`
|
|
select *
|
|
from "tags"
|
|
where tag = ${tagname}
|
|
limit 1
|
|
`)[0];
|
|
|
|
if(!tmptag) {
|
|
return res.json({
|
|
success: false,
|
|
msg: 'no tag found'
|
|
}, 404); // not found
|
|
}
|
|
|
|
const q = (await db`
|
|
update "tags" set ${
|
|
db({
|
|
tag: newtag
|
|
}, 'tag')
|
|
}
|
|
where tag = ${tagname}
|
|
returning *
|
|
`)?.[0];
|
|
|
|
return res.json(q, tagname === newtag ? 200 : 201); // created (modified)
|
|
});
|
|
|
|
group.get(/\/admin\/tags\/suggest$/, lib.auth, async (req, res) => {
|
|
const reply = {
|
|
success: false,
|
|
suggestions: {}
|
|
};
|
|
|
|
const searchString = req.url.qs.q;
|
|
|
|
if(searchString?.length <= 1) {
|
|
reply.error = 'too short lol';
|
|
return res.json(reply);
|
|
}
|
|
|
|
try {
|
|
const q = await db`
|
|
select tag, count(tags_assign.tag_id) as tagged
|
|
from "tags"
|
|
left join "tags_assign" on "tags_assign".tag_id = "tags".id
|
|
where normalized like '%' || slugify(${searchString}) || '%'
|
|
group by "tags".id
|
|
order by tagged desc
|
|
limit 15
|
|
`;
|
|
reply.success = true;
|
|
reply.suggestions = search(q, searchString);
|
|
} catch(err) {
|
|
reply.error = err.msg;
|
|
}
|
|
|
|
return res.json(reply);
|
|
});
|
|
|
|
group.post(/\/admin\/deletepost$/, lib.auth, async (req, res) => {
|
|
if(!req.post.postid) {
|
|
return res.json({
|
|
success: false,
|
|
msg: 'no postid'
|
|
});
|
|
}
|
|
const id = +req.post.postid;
|
|
|
|
if(id <= 1) {
|
|
return res.json({
|
|
success: false
|
|
});
|
|
}
|
|
|
|
const f0ck = await db`
|
|
select dest, mime
|
|
from "items"
|
|
where
|
|
id = ${id} and
|
|
active = 'true'
|
|
limit 1
|
|
`;
|
|
|
|
if(f0ck.length === 0) {
|
|
return res.json({
|
|
success: false,
|
|
msg: `f0ck ${id}: f0ck not found`
|
|
});
|
|
}
|
|
|
|
await db`update "items" set active = 'false' where id = ${id}`;
|
|
|
|
await fs.copyFile(`./public/b/${f0ck[0].dest}`, `./deleted/b/${f0ck[0].dest}`).catch(_=>{});
|
|
await fs.copyFile(`./public/t/${id}.webp`, `./deleted/t/${id}.webp`).catch(_=>{});
|
|
await fs.unlink(`./public/b/${f0ck[0].dest}`).catch(_=>{});
|
|
await fs.unlink(`./public/t/${id}.webp`).catch(_=>{});
|
|
|
|
if(f0ck[0].mime.startsWith('audio')) {
|
|
await fs.copyFile(`./public/ca/${id}.webp`, `./deleted/ca/${id}.webp`).catch(_=>{});
|
|
await fs.unlink(`./public/ca/${id}.webp`).catch(_=>{});
|
|
}
|
|
|
|
res.json({
|
|
success: true
|
|
});
|
|
});
|
|
|
|
group.post(/\/admin\/togglefav$/, lib.auth, async (req, res) => {
|
|
const postid = +req.post.postid;
|
|
|
|
let favs = await db`
|
|
select user_id
|
|
from "favorites"
|
|
where item_id = ${+postid}
|
|
`;
|
|
|
|
if(Object.values(favs).filter(u => u.user_id === req.session.id)[0]) {
|
|
// del fav
|
|
await db`
|
|
delete from "favorites"
|
|
where user_id = ${+req.session.id}
|
|
and item_id = ${+postid}
|
|
`;
|
|
}
|
|
else {
|
|
// add fav
|
|
await db`
|
|
insert into "favorites" ${
|
|
db({
|
|
item_id: +postid,
|
|
user_id: +req.session.id
|
|
}, 'item_id', 'user_id')
|
|
}
|
|
`;
|
|
}
|
|
|
|
favs = await db`
|
|
select "user".user, "user_options".avatar
|
|
from "favorites"
|
|
left join "user" on "user".id = "favorites".user_id
|
|
left join "user_options" on "user_options".user_id = "favorites".user_id
|
|
where "favorites".item_id = ${+postid}
|
|
`;
|
|
|
|
return res.json({
|
|
success: true,
|
|
itemid: postid,
|
|
favs
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
return router;
|
|
};
|