change psql-lib from knex to postgres.js

This commit is contained in:
Flummi
2022-03-31 13:34:51 +02:00
parent f750a9a60f
commit c498a33cbe
20 changed files with 689 additions and 973 deletions

View File

@ -1,6 +1,6 @@
import crypto from "crypto";
import util from "util";
import sql from "./sql.mjs";
import db from "./sql.mjs";
const scrypt = util.promisify(crypto.scrypt);
@ -46,7 +46,7 @@ export default new class {
tmp = "items.id not in (select item_id from tags_assign group by item_id)";
break;
case 3: // all
tmp = "";
tmp = "1 = 1";
break;
default: // sfw
tmp = "items.id in (select item_id from tags_assign where tag_id = 1 group by item_id)";
@ -73,10 +73,26 @@ export default new class {
// async funcs
async countf0cks() {
const tagged = (await sql("items").whereRaw("id in (select item_id from tags_assign group by item_id)").count("* as total"))[0].total;
const untagged = (await sql("items").whereRaw("id not in (select item_id from tags_assign group by item_id)").count("* as total"))[0].total;
const sfw = (await sql("items").whereRaw("id in (select item_id from tags_assign where tag_id = 1 group by item_id)").count("* as total"))[0].total;
const nsfw = (await sql("items").whereRaw("id in (select item_id from tags_assign where tag_id = 2 group by item_id)").count("* as total"))[0].total;
const tagged = (await db`
select count(*) as total
from "items"
where id in (select item_id from tags_assign group by item_id)
`)[0].total;
const untagged = (await db`
select count(*) as total
from "items"
where id not in (select item_id from tags_assign group by item_id)
`)[0].total;
const sfw = (await db`
select count(*) as total
from "items"
where id in (select item_id from tags_assign where tag_id = 1 group by item_id)
`)[0].total;
const nsfw = (await db`
select count(*) as total
from "items"
where id in (select item_id from tags_assign where tag_id = 2 group by item_id)
`)[0].total;
return {
tagged,
untagged,
@ -106,12 +122,14 @@ export default new class {
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)
.orderBy("tags.id", "asc");
const tags = await db`
select "tags".id, "tags".tag, "tags".normalized, "user".user
from "tags_assign"
left join "tags" on "tags".id = "tags_assign".tag_id
left join "user" on "user".id = "tags_assign".user_id
where "tags_assign".item_id = ${+itemid}
order by "tags".id asc
`;
for(let t = 0; t < tags.length; t++) {
if(tags[t].tag.startsWith(">"))
tags[t].badge = "badge-greentext badge-light";

View File

@ -10,6 +10,6 @@ export default new Proxy({}, {
level: prop,
message: msg,
timestamp: timestamp
}) + "\n") &&
console.log(timestamp, prop, msg)
}) + "\n")// &&
//console.log(timestamp, prop, msg)
});

View File

@ -1,4 +1,4 @@
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
import cfg from "../config.mjs";
import fs from "fs";
@ -18,51 +18,54 @@ export default {
let data;
let total;
if(tag) {
if(tag.match(/sfw/) || tag.length <= 2)
return {
success: false,
message: "nope."
};
total = (await sql("items")
.innerJoin(
sql("tags")
.select("tags_assign.item_id", "tags.tag")
.leftJoin("tags_assign", "tags_assign.tag_id", "tags.id")
.where("tags.tag", "ilike", "%"+tag+"%")
.groupBy("tags_assign.item_id", "tags.tag")
.as("st"),
"st.item_id", "items.id"
)
.whereRaw(modequery)
.groupBy('st.tag', 'st.item_id')
.count("* as total")
)?.length;
total = await db`
select count(*) as total
from items
inner join (
select tags_assign.item_id, tags.tag
from tags
left join tags_assign on tags_assign.tag_id = tags.id
where tags.tag ilike ${'%' + (tag ? tag : '') + '%'}
group by tags_assign.item_id, tags.tag
) as st on st.item_id = items.id
where ${db.unsafe(modequery)}
group by st.tag, st.item_id`;
total = total?.length;
}
else {
if(!o.fav) {
total = (await sql("items")
.whereRaw(modequery)
.andWhere("items.mime", "ilike", smime)
.andWhere("items.username", "ilike", user ? user : "%")
.count("* as total")
)[0]?.total;
total = await db`
select count(*) as total
from items
where ${db.unsafe(modequery)}
and items.mime ilike ${smime}
and items.username ilike ${user ? user : '%'}
`;
total = total[0].total;
}
else {
total = (await sql("favorites")
.select('items.id', 'items.mime')
.leftJoin('user', 'user.id', 'favorites.user_id')
.leftJoin('tags_assign', 'tags_assign.item_id', 'favorites.item_id')
.leftJoin('tags', 'tags.id', 'tags_assign.tag_id')
.leftJoin('items', 'items.id', 'favorites.item_id')
.whereRaw(modequery)
.andWhere('items.mime', 'ilike', smime)
.andWhere('user.user', 'ilike', user)
.groupBy('items.id')
.count('* as total')
)[0]?.total;
total = await db`
select count(*) as total
from "favorites"
left join "user" on "user".id = "favorites".user_id
left join "tags_assign" on "tags_assign".item_id = "favorites".item_id
left join "tags" on "tags".id = "tags_assign".tag_id
left join "items" on "items".id = "favorites".item_id
where ${db.unsafe(modequery)}
and "items".mime ilike ${smime}
and "user".user ilike ${user}
group by "items".id
`;
total = total[0].total;
}
}
@ -77,49 +80,70 @@ export default {
const offset = Math.max(0, (act_page - 1) * cfg.websrv.eps);
let rows;
if(!o.fav) {
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", "ilike", smime)
.andWhere("items.username", "ilike", user ? user : "%")
.orderBy("items.id", "desc")
.offset(offset)
.limit(cfg.websrv.eps);
rows = db`
select "items".id, "items".mime, "tags_assign".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)
${tag
? db`
inner join (
select "tags_assign".item_id, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags".tag ilike ${'%' + tag + '%'}
group by "tags_assign".item_id, "tags".tag
) as st on st.item_id = "items".id
`
: db``
}
where ${db.unsafe(modequery)}
and "items".mime ilike ${smime}
and "items".username ilike ${user ? user : '%'}
${tag
? db`group by st.item_id, "items".id, "tags_assign".tag_id`
: db``
}
order by "items".id desc
offset ${offset}
limit ${cfg.websrv.eps}
`;
}
else {
rows = sql("favorites")
.select('items.id', 'items.mime', 'ta.tag_id')
.leftJoin('user', 'user.id', 'favorites.user_id')
.leftJoin('tags_assign', 'tags_assign.item_id', 'favorites.item_id')
.leftJoin('tags', 'tags.id', 'tags_assign.tag_id')
.leftJoin('items', 'items.id', 'favorites.item_id')
.joinRaw("left join tags_assign as ta on ta.item_id = items.id and (ta.tag_id = 1 or ta.tag_id = 2)")
.whereRaw(modequery)
.andWhere('items.mime', 'ilike', smime)
.andWhere('user.user', 'ilike', user)
.orderBy('items.id', 'desc')
.groupBy('items.id', 'ta.tag_id')
.offset(offset)
.limit(cfg.websrv.eps);
rows = db`
select "items".id, "items".mime, ta.tag_id
from "favorites"
left join "user" on "user".id = "favorites".user_id
left join "tags_assign" on "tags_assign".item_id = "favorites".item_id
left join "tags" on "tags".id = "tags_assign".tag_id
left join "items" on "items".id = "favorites".item_id
left join "tags_assign" as ta on ta.item_id = "items".id and (ta.tag_id = 1 or ta.tag_id = 2)
${ tag
? db`
inner join (
select "tags_assign".item_id, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags".tag ilike ${'%' + tag + '%'}
group by "tags_assign".item_id, "tags".tag
) as st on st.item_id = "items".id`
: db``
}
where ${db.unsafe(modequery)}
and "items".mime ilike ${smime}
and "user".user ilike ${user}
${tag
? db`group by st.item_id, "items".id, "tags_assign".tag_id`
: db``
}
group by "items".id, ta.tag_id
order by "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", "ilike", "%"+tag+"%")
.groupBy("tags_assign.item_id", "tags.tag")
.as("st"),
"st.item_id", "items.id"
)
.groupBy('st.item_id', 'items.id', 'tags_assign.tag_id');
}
rows = await rows;
if(rows.length === 0)
@ -177,39 +201,66 @@ export default {
let items;
if(o.fav) {
items = sql('favorites')
.select('items.*')
.leftJoin('items', 'items.id', 'favorites.item_id')
.leftJoin('user', 'user.id', 'favorites.user_id')
.whereRaw(modequery)
.andWhere('user.user', 'ilike', user)
items = db`
select "items".*
from "favorites"
left join "items" on "items".id = "favorites".item_id
left join "user" on "user".id = "favorites".user_id
${ tag
? db`
inner join (
select "tags_assign".item_id, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags".tag ilike ${'%' + tag + '%'}
group by "tags_assign".item_id, "tags".tag
) as st on st.item_id = "items".id`
: db``
}
where ${db.unsafe(modequery)}
and "user".user ilike ${user}
${ mime
? db`and "items".mime ilike ${mime + '/%'}`
: db``
}
${ tag
? db`group by st.tag, st.item_id, "items".id`
: db`group by "items".id, "favorites".user_id, "favorites".item_id, "user".id`
}
`;
}
else {
items = sql("items")
.select("*")
.orderBy("items.id", "desc")
.whereRaw(modequery);
items = db`
select *
from "items"
${tag
? db`
inner join (
select "tags_assign".item_id, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags".tag ilike ${'%' + tag + '%'}
group by "tags_assign".item_id, "tags".tag
) as st on st.item_id = "items".id`
: db``
}
where ${db.unsafe(modequery)}
${ user
? db`and "items".username ilike ${'%' + user + '%'}`
: db``
}
${ mime
? db`and "items".mime ilike ${mime + '/%'}`
: db``
}
${ tag
? db`group by st.item_id, "items".id, "tags_assign".tag_id`
: db`group by "items".id`
}
order by "items".id desc
`;
}
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", "ilike", "%"+tag+"%")
.groupBy("tags.tag", "tags_assign.item_id")
.as("st"),
"st.item_id", "items.id"
)
.groupBy('st.tag', 'st.item_id', 'items.id');
}
else
items = items.groupBy('items.id');
if(user && !o.fav)
items = items.andWhere("items.username", "ilike", "%" + user + "%");
if(mime)
items = items.andWhere("items.mime", "ilike", mime + "/%");
items = await items;
if(tag)
@ -228,11 +279,13 @@ export default {
const tags = await lib.getTags(itemid);
const cheat = [...new Set(items.slice(Math.max(0, item - 3), item + 4).map(i => i.id))];
const link = lib.genLink({ user, tag, mime, type: o.fav ? 'favs' : 'f0cks' });
const favorites = await sql('favorites')
.select('user.user', 'user_options.avatar')
.leftJoin('user', 'user.id', 'favorites.user_id')
.leftJoin('user_options', 'user_options.user_id', 'favorites.user_id')
.where('favorites.item_id', itemid);
const favorites = 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 = ${itemid}
`;
let coverart = true;
try {
@ -286,45 +339,66 @@ export default {
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 modequery = mime == "audio" ? lib.getMode(0) : lib.getMode(o.mode ?? 0);
let item;
if(o.fav) {
item = sql("favorites")
.select('items.*')
.leftJoin('items', 'items.id', 'favorites.item_id')
.leftJoin('user', 'user.id', 'favorites.user_id')
.whereRaw(modequery)
.orderByRaw("random()")
.andWhere('user.user', 'ilike', user);
if(o.fav) { // dood lol
item = db`
select "items".*
from "favorites"
left join "items" on "items".id = "favorites".item_id
left join "user" on "user".id = "favorites".user_id
${ tag
? db`
inner join (
select "tags_assign".item_id, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags".tag ilike ${'%' + tag + '%'}
group by "tags_assign".item_id, "tags".tag
) as st on st.item_id = "items".id`
: db``
}
where ${db.unsafe(modequery)}
and "user".user ilike ${user}
${ mime
? db`and "items".mime ilike ${mime + '/%'}`
: db``
}
order by random()
limit 1
`;
}
else {
item = sql("items")
.select("*")
.orderByRaw("random()")
.whereRaw(modequery);
item = db`
select *
from "items"
${ tag
? db`
inner join (
select "tags_assign".item_id, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags".tag ilike ${'%' + tag + '%'}
group by "tags_assign".item_id, "tags".tag
) as st on st.item_id = "items".id`
: db``
}
where ${db.unsafe(modequery)}
${ user
? db`and "items".username ilike ${'%' + user + '%'}`
: db``
}
${ mime
? db`and "items".mime ilike ${mime + '/%'}`
: db``
}
order by random()
limit 1
`;
}
if(tag) {
item = item.innerJoin(
sql("tags")
.select("tags_assign.item_id", "tags.tag")
.leftJoin("tags_assign", "tags_assign.tag_id", "tags.id")
.where("tags.tag", "ilike", "%"+tag+"%")
.groupBy("tags_assign.item_id", "tags.tag")
.as("st"),
"st.item_id", "items.id"
)
.groupBy('st.item_id', 'st.tag', 'items.id');
}
if(user)
item = item.andWhere("username", "ilike", "%" + user + "%");
if(mime)
item = item.andWhere("mime", "ilike", mime + "/%");
item = await item;
if(item.length === 0) {

View File

@ -1,4 +1,4 @@
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
import { exec } from "child_process";
import search from "../routeinc/search.mjs";
@ -24,20 +24,26 @@ export default (router, tpl) => {
});
router.post(/^\/login(\/)?$/, async (req, res) => {
const user = await sql("user").where("login", req.post.username.toLowerCase()).limit(1);
const user = await db`
select *
from "user"
where "login" = ${req.post.username.toLowerCase()}
limit 1
`;
if(user.length === 0)
return res.reply({ body: "user doesn't exist or wrong password" });
if(!(await lib.verify(req.post.password, user[0].password)))
return res.reply({ body: "user doesn't exist or wrong password" });
const stamp = ~~(Date.now() / 1e3);
await sql("user_sessions") // delete unused sessions
.where('last_action', '<=', (Date.now() - 6048e5))
.andWhere('kmsi', 0)
.del();
await db`
delete from user_sessions
where last_action <= ${(Date.now() - 6048e5)}
and kmsi = 0
`;
const session = lib.md5(lib.createID());
await sql("user_sessions").insert({
const blah = {
user_id: user[0].id,
session: lib.md5(session),
browser: req.headers["user-agent"],
@ -45,7 +51,13 @@ export default (router, tpl) => {
last_used: stamp,
last_action: "/login",
kmsi: typeof req.post.kmsi !== 'undefined' ? 1 : 0
});
};
await db`
insert into "user_sessions" ${
db(blah, 'user_id', 'session', 'browser', 'created_at', 'last_used', 'last_action', 'kmsi')
}
`;
return res.writeHead(301, {
"Cache-Control": "no-cache, public",
@ -55,11 +67,18 @@ export default (router, tpl) => {
});
router.get(/^\/logout$/, auth, async (req, res) => {
const usersession = await sql("user_sessions").where("id", req.session.sess_id);
const usersession = await db`
select *
from "user_sessions"
where id = ${+req.session.sess_id}
`;
if(usersession.length === 0)
return res.reply({ body: "nope 2" });
await sql("user_sessions").where("id", req.session.sess_id).del();
await db`
delete from "user_sessions"
where id = ${+req.session.sess_id}
`;
return res.writeHead(301, {
"Cache-Control": "no-cache, public",
"Set-Cookie": "session=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT",
@ -86,10 +105,12 @@ export default (router, tpl) => {
});
router.get(/^\/admin\/sessions(\/)?$/, auth, async (req, res) => {
const rows = await sql("user_sessions")
.leftJoin("user", "user.id", "user_sessions.user_id")
.select("user_sessions.*", "user.user")
.orderBy("user_sessions.last_used", "desc");
const rows = await db`
select "user_sessions".*, "user".user
from "user_sessions"
left join "user" on "user".id = "user_sessions".user_id
order by "user_sessions".last_used desc
`;
res.reply({
body: tpl.render("admin/sessions", {
@ -108,17 +129,22 @@ export default (router, tpl) => {
if(tag.startsWith('src:')) {
tag = tag.substring(4);
ret = await sql('items')
.where('src', 'ilike', '%'+tag+'%')
.limit(500);
ret = await db`
select *
from "items"
where src ilike ${'%' + tag + '%'}
limit 500
`;
}
else {
rows = await sql("tags")
.select("items.id", "items.username", "tags.tag")
.leftJoin("tags_assign", "tags_assign.tag_id", "tags.id")
.leftJoin("items", "items.id", "tags_assign.item_id")
.where("tags.tag", "like", '%'+tag+'%')
.limit(500);
rows = await db`
select "items".id, "items".username, "tags".tag
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
left join "items" on "items".id = "tags_assign".item_id
where "tags".tag ilike ${'%' + tag + '%'}
limit 500
`;
ret = search(rows, tag);
}
}

View File

@ -1,4 +1,4 @@
import sql from '../../sql.mjs';
import db from '../../sql.mjs';
import lib from '../../lib.mjs';
import search from '../../routeinc/search.mjs';
@ -13,11 +13,14 @@ export default router => {
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 sql("items")
.orderByRaw("rand()")
.limit(1)
.where("mime", "ilike", mime)
.andWhere("username", "ilike", user);
const rows = await db`
select *
from "items"
where mime ilike ${mime}
and username ilike ${user}
order by random()
limit 1
`;
return res.json({
success: rows.length > 0,
@ -29,7 +32,13 @@ export default router => {
let eps = 100;
let id = +req.url.split[3];
const rows = await sql("items").where("id", "<", id).orderBy("id", "desc").limit(eps);
const rows = await db`
select *
from "items"
where id < ${+id}
order by id desc
limit ${+eps}
`;
const items = {
items: rows,
@ -45,9 +54,26 @@ export default router => {
group.get(/\/item\/[0-9]+$/, async (req, res) => {
const id = +req.url.split[3];
const item = await sql("items").where("id", id).limit(1);
const next = await sql("items").select("id").where("id", ">", id).orderBy("id").limit(1);
const prev = await sql("items").select("id").where("id", "<", id).orderBy("id", "desc").limit(1);
const item = await db`
select *
from "items"
where id = ${+id}
limit 1
`;
const next = await db`
select id
from "items"
where id > ${+id}
order by id
limit 1
`;
const prev = await db`
select id
from "items"
where id < ${+id}
order by id desc
limit 1
`;
if(item.length === 0) {
return res.json({
@ -74,11 +100,13 @@ export default router => {
const user = req.url.split[3];
const eps = +req.url.split[4] || 50;
const rows = await sql("items")
.select("id", "mime", "size", "src", "stamp", "userchannel", "username", "usernetwork")
.where("username", user)
.orderBy("stamp", "desc")
.limit(eps);
const rows = db`
select id, mime, size, src, stamp, userchannel, username, usernetwork
from "items"
where username = ${user}
order by stamp desc
limit ${+eps}
`;
return res.json({
success: rows.length > 0,
@ -109,11 +137,12 @@ export default router => {
}, 405); // method not allowed
}
const tmptag = (
await sql('tags')
.where('tag', tagname)
.limit(1)
)[0];
const tmptag = (await db`
select *
from "tags"
where tag = ${tagname}
limit 1
`)[0];
if(!tmptag) {
return res.json({
@ -122,13 +151,15 @@ export default router => {
}, 404); // not found
}
const q = (
await sql('tags')
.update({
tag: newtag
}, [ 'tag', 'normalized' ])
.where('tag', tagname)
)?.[0];
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)
});
@ -147,13 +178,15 @@ export default router => {
}
try {
const q = await sql('tags')
.select('tag', sql.raw('count(tags_assign.tag_id) as tagged'))
.leftJoin('tags_assign', 'tags_assign.tag_id', 'tags.id')
.whereRaw("normalized like '%' || slugify(?) || '%'", [ searchString ])
.groupBy('tags.id')
.orderBy('tagged', 'desc')
.limit(15);
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) {
@ -172,7 +205,10 @@ export default router => {
}
const postid = +req.post.postid;
await sql("items").where("id", postid).del();
await db`
delete from "items"
where id = ${+postid}
`;
res.json({
success: true
@ -182,25 +218,39 @@ export default router => {
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);
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 sql('favorites').where('user_id', req.session.id).andWhere('item_id', postid).del();
await db`
delete from "favorites"
where user_id = ${+req.session.id}
and item_id = ${+postid}
`;
}
else {
// add fav
await sql('favorites').insert({
item_id: postid,
user_id: req.session.id
});
await db`
insert into "favorites" ${
db({
item_id: +postid,
user_id: +req.session.id
}, 'item_id', 'user_id')
}
`;
}
favs = await sql('favorites')
.select('user.user', 'user_options.avatar')
.leftJoin('user', 'user.id', 'favorites.user_id')
.leftJoin('user_options', 'user_options.user_id', 'favorites.user_id')
.where('favorites.item_id', postid);
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,

View File

@ -1,4 +1,4 @@
import sql from '../../sql.mjs';
import db from '../../sql.mjs';
import lib from '../../lib.mjs';
export default router => {
@ -13,11 +13,11 @@ export default router => {
const avatar = +req.post.avatar;
const itemid = (
await sql('items')
.select('id')
.where('id', avatar)
)?.[0]?.id;
const itemid = (await db`
select id
from "items"
where id = ${+avatar}
`)?.[0]?.id;
if(!itemid) {
return res.json({
@ -25,11 +25,14 @@ export default router => {
}, 404); // not found
}
const q = await sql('user_options')
.update({
avatar
})
.where('user_id', req.session.id);
const q = await db`
update "user_options" set ${
db({
avatar
}, 'avatar')
}
where user_id = ${+req.session.id}
`;
return res.json({
msg: q

View File

@ -1,4 +1,4 @@
import sql from '../../sql.mjs';
import db from '../../sql.mjs';
import lib from '../../lib.mjs';
export default router => {
@ -38,22 +38,31 @@ export default router => {
}
try {
let tagid = (
await sql("tags")
.select("id")
.whereRaw("normalized = slugify(?)", [ tagname ])
)?.[0]?.id;
let tagid = (await db`
select id
from "tags"
where normalized = slugify(${tagname})
`)?.[0]?.id;
if(!tagid) { // create new tag
tagid = (await sql("tags").returning("id").insert({
tag: tagname
}))[0];
tagid = (await db`
insert into "tags" ${
db({
tag: tagname
}, 'tag')
}
returning id
`)[0];
}
await sql("tags_assign").insert({
tag_id: tagid,
item_id: postid,
user_id: req.session.id
});
await db`
insert into "tags_assign" ${
db({
tag_id: +tagid,
item_id: +postid,
user_id: +req.session.id
}, 'tag_id', 'item_id', 'user_id')
}
`;
} catch(err) {
return res.json({
success: false,
@ -83,20 +92,27 @@ export default router => {
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
});
await db`
insert into "tags_assign" ${
db({
item_id: +postid,
tag_id: 1,
user_id: +req.session.id
}, 'item_id', 'tag_id', 'user_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);
await db`
update "tags_assign" set ${
db({
tag_id: db`(array[2,1])[tag_id]`
}, tag_id)
}
where tag_id = any(array[1,2])
and item_id = ${+postid}
`;
}
return res.json({
@ -129,10 +145,16 @@ export default router => {
});
}
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);
let q = await db`
delete from "tags_assign"
where tag_id = ${+tagid}
and item_id = ${+postid}
${ req.session.level < 50
? db`and user_id = ${+req.session.id}`
: db``
}
`;
const reply = !!q;
return res.json({
success: reply,

View File

@ -1,5 +1,5 @@
import cfg from "../config.mjs";
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
import f0cklib from "../routeinc/f0cklib.mjs";
@ -49,37 +49,52 @@ export default (router, tpl) => {
referer = referertmp.split("/").slice(3).join("/");
if(cfg.allowedModes[mode]) {
await sql("user_options")
.insert({
user_id: req.session.id,
mode: mode,
theme: req.theme ?? "f0ck"
})
.onConflict("user_id")
.merge();
const blah = {
user_id: req.session.id,
mode: mode,
theme: req.theme ?? "f0ck"
};
await db`
insert into "user_options" ${
db(blah, 'user_id', 'mode', 'theme')
}
on conflict ("user_id") do update set
mode = excluded.mode,
theme = excluded.theme,
user_id = excluded.user_id
`;
}
res.redirect(`/${referer}`);
});
router.get(/^\/ranking$/, async (req, res) => {
try {
const list = await sql('tags_assign')
.select('user.user', sql.raw('coalesce(user_options.avatar, 47319) as avatar'))
.leftJoin('user', 'user.id', 'tags_assign.user_id')
.leftJoin('user_options', 'user_options.user_id', 'user.id')
.groupBy('user.user', 'user_options.avatar')
.orderBy('count', 'desc')
.countDistinct('tag_id', 'item_id', { as: 'count' });
const list = await db`
select
"user".user,
coalesce("user_options".avatar, 47319) as avatar,
count(distinct(tag_id, item_id)) as count
from "tags_assign"
left join "user" on "user".id = "tags_assign".user_id
left join "user_options" on "user_options".user_id = "user".id
group by "user".user, "user_options".avatar
order by count desc
`;
const stats = await lib.countf0cks();
const hoster = await sql.with('t', sql.raw("select split_part(substring(src, position('//' in src)+2), '/', 1) part from items"))
.from('t')
.select('t.part')
.count('t.part as c')
.groupBy('t.part')
.orderBy('c', 'desc')
.limit(20);
const hoster = await db`
with t as (
select
split_part(substring(src, position('//' in src)+2), '/', 1) part
from items
)
select t.part, count(t.part) as c
from t
group by t.part
order by c desc
limit 20
`;
res.reply({
body: tpl.render('ranking', {

View File

@ -1,4 +1,4 @@
import sql from "../../inc/sql.mjs";
import db from "../../inc/sql.mjs";
const auth = async (req, res, next) => {
if(!req.session)
@ -9,9 +9,16 @@ const auth = async (req, res, next) => {
export default (router, tpl) => {
router.group(/^\/settings/, group => {
group.get(/$/, auth, async (req, res) => {
const sessions = await sql("user_sessions")
/*const sessions = await sql("user_sessions")
.where("user_id", req.session.id)
.orderBy("last_used", "desc");
.orderBy("last_used", "desc");*/
const sessions = await db`
select *
from user_sessions
where user_id = ${ +req.session.id }
order by last_used desc
`;
res.reply({
body: tpl.render('settings', {

View File

@ -1,7 +1,11 @@
import knex from "knex";
//import knex from "knex";
import postgres from "postgres";
import cfg from "./config.mjs";
export default knex({
/*export default knex({
client: 'pg',
connection: cfg.sql
});
});*/
//export const db = postgres(cfg.sql);
export default postgres(cfg.sql);

View File

@ -1,7 +1,5 @@
import { getLevel } from "../admin.mjs";
import fetch from "flumm-fetch-cookies";
import sql from "../sql.mjs";
import vm from "vm";
let maxoutput = 750;
@ -9,7 +7,6 @@ let context = vm.createContext({
e: null,
bot: null,
admins: null,
sql: sql,
fetch: fetch,
a: null,

View File

@ -1,5 +1,5 @@
import { promises as fs } from "fs";
import sql from "../sql.mjs";
import db from "../sql.mjs";
export default async bot => {
@ -14,14 +14,22 @@ export default async bot => {
if(id <= 0)
return false;
const f0ck = await sql("items").select("dest").where("id", id).limit(1);
const f0ck = await db`
select dest
from "items"
where id = ${+id}
limit 1
`;
if(f0ck.length === 0)
return false;
await fs.unlink(`./public/b/${f0ck[0].dest}`).catch(_=>{});
await fs.unlink(`./public/t/${id}`).catch(_=>{});
await sql("items").where("id", id).del().limit(1);
await db`
delete from "items"
where id = ${+id}
`;
return id;
}))).filter(d => d);

View File

@ -2,14 +2,17 @@ import fetch from "flumm-fetch-cookies";
import { promises as fs } from "fs";
import { exec } from "child_process";
import cfg from "../config.mjs";
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
const cleanTags = async () => {
const tags = await sql("tags")
.leftJoin("tags_assign", "tags_assign.tag_id", "tags.id")
.whereNull("tags_assign.item_id");
/*const cleanTags = async () => {
const tags = await db`
select *
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
where "tags_assign".item_id is null
`;
if(tags.length === 0)
return 0;
@ -23,7 +26,7 @@ const cleanTags = async () => {
});
await deleteTag.del();
return dtags;
};
};*/
export default async bot => {
@ -49,7 +52,10 @@ export default async bot => {
case "limit":
return e.reply(`up to ${lib.formatSize(cfg.main.maxfilesize)} (${lib.formatSize(cfg.main.maxfilesize * cfg.main.adminmultiplier)} for admins)`);
case "thumb":
const rows = await sql("items").select("id");
const rows = await db`
select id
from "items"
`;
const dir = (await fs.readdir("./public/t")).filter(d => d.endsWith(".png")).map(e => +e.split(".")[0]);
const tmp = [];
for(let row of rows)
@ -69,10 +75,10 @@ export default async bot => {
e.reply("hay hay patron, hemen!");
exec("sudo systemctl restart f0ck");
break;
case "cleanTags":
/*case "cleanTags":
const tags = await cleanTags();
e.reply(tags + " tags removed");
break;
break;*/
case "clearTmp":
await Promise.all((await fs.readdir("./tmp")).filter(d => d !== ".empty").map(async d => fs.unlink(`./tmp/${d}`)));
e.reply("cleared lol");

View File

@ -1,5 +1,5 @@
import cfg from "../config.mjs";
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
const regex = /(https\:\/\/f0ck\.me|http\:\/\/fockmoonsb24iczs7odozzy5uktlzbcgp337nabrgffzxv5ihabgpvyd\.onion)(\/(video|image|audio))?\/(\d+|(?:b\/)(\w{8})\.(jpg|webm|gif|mp4|png|mov|mp3|ogg|flac))/gi;
@ -12,14 +12,15 @@ export default async bot => {
active: true,
f: async e => {
const dat = e.message.match(regex)[0].split(/\//).pop();
let query = sql("items").select("id", "mime", "size", "username", "userchannel", "usernetwork", "stamp");
const rows = await db`
select id, mime, size, username, userchannel, usernetwork, stamp
from "items"
${ dat.includes('.')
? db`where dest ilike ${'%' + dat + '%'}`
: db`where id = ${dat}`
}
`;
if(dat.includes("."))
query = query.where("dest", "like", `%${dat}%`);
else
query = query.where("id", dat);
const rows = await query;
if(rows.length === 0)
return e.reply("no f0cks given! lol D:");

View File

@ -1,4 +1,4 @@
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
import cfg from "../config.mjs";
@ -7,10 +7,10 @@ export default async bot => {
return [{
name: "f0ckrand",
call: /^gib f0ck/i,
active: true,
active: false,
f: async e => {
let args = e.args.slice(1);
let rows = sql("items").select("id", "username", "mime", "size");
/*let rows = sql("items").select("id", "username", "mime", "size");
for(let i = 0; i < args.length; i++) {
if(args[i].charAt(0) === "!")
@ -19,7 +19,7 @@ export default async bot => {
rows = rows.where("username", "ilike", args[i]);
}
rows = await rows.orderByRaw("random()").limit(1);
rows = await rows.orderByRaw("random()").limit(1);*/
if(rows.length === 0)
return e.reply("nothing found, f0cker");

View File

@ -1,5 +1,5 @@
import cfg from "../config.mjs";
import sql from "../sql.mjs";
import db from "../sql.mjs";
import lib from "../lib.mjs";
import { getLevel } from "../admin.mjs";
import fetch from "flumm-fetch-cookies";
@ -45,12 +45,18 @@ export default async bot => {
links.forEach(async link => {
// check repost (link)
const q_repost = await sql("items").select("id").where("src", link);
const q_repost = await db`
select id
from "items"
where src = ${link}
`;
if(q_repost.length > 0)
return e.reply(`repost motherf0cker (link): ${cfg.main.url}/${q_repost[0].id}`);
// generate uuid
const uuid = (await sql.select(sql.raw("gen_random_uuid() as uuid")))[0].uuid.substring(0, 8);
const uuid = (await db`
select gen_random_uuid() as uuid
`)[0].uuid.substring(0, 8);
const maxfilesize = (getLevel(e.user).level > 50 ? cfg.main.maxfilesize * cfg.main.adminmultiplier : cfg.main.maxfilesize) / 1024;
@ -108,26 +114,40 @@ export default async bot => {
}
// check repost (checksum)
const q_repostc = await sql("items").select("id").where("checksum", checksum);
const q_repostc = await db`
select id
from "items"
where checksum = ${checksum}
`;
if(q_repostc.length > 0)
return e.reply(`repost motherf0cker (checksum): ${cfg.main.url}/${q_repostc[0].id}`);
await fs.promises.copyFile(`./tmp/${filename}`, `./public/b/${filename}`);
await fs.promises.unlink(`./tmp/${filename}`).catch(_=>{});
await sql("items").insert({
src: e.photo ? "" : link,
dest: filename,
mime: mime,
size: size,
checksum: checksum,
username: e.user.nick || e.user.username,
userchannel: e.channel,
usernetwork: e.network,
stamp: ~~(new Date() / 1000),
active: 1
});
const itemid = (await sql('items').where('dest', filename).limit(1))[0].id;
await db`
insert into items ${
db({
src: e.photo ? "" : link,
dest: filename,
mime: mime,
size: size,
checksum: checksum,
username: e.user.nick || e.user.username,
userchannel: e.channel,
usernetwork: e.network,
stamp: ~~(new Date() / 1000),
active: 1
}, 'src', 'dest', 'mime', 'size', 'checksum', 'username', 'userchannel', 'usernetwork', 'stamp', 'active')
}
`;
const itemid = (await db`
select *
from "items"
where dest = ${filename}
limit 1
`)[0].id;
// generate thumbnail
try {
@ -184,11 +204,15 @@ export default async bot => {
}
if(tag === 'sfw' || tag === 'nsfw') {
await sql("tags_assign").insert({
tag_id: tag === "sfw" ? 1 : 2,
item_id: itemid,
user_id: 7 // user: autotagger (ID: 7)
});
await db`
insert into "tags_assign" ${
db({
tag_id: tag === "sfw" ? 1 : 2,
item_id: itemid,
user_id: 7 // user: autotagger (ID: 7)
}, 'tag_id', 'item_id', 'user_id')
}
`;
}
} catch(err) {
console.error(err);

View File

@ -1,12 +1,8 @@
import sql from "../sql.mjs";
import db from "../sql.mjs";
import cfg from "../config.mjs";
import lib from "../lib.mjs";
import { getLevel } from "../admin.mjs";
const getTags = async itemid => await sql("tags_assign")
.leftJoin("tags", "tags.id", "tags_assign.tag_id")
.where("tags_assign.item_id", itemid)
.select("tags.id", "tags.tag");
export default async bot => {
return [{
name: "tags show",
@ -17,7 +13,7 @@ export default async bot => {
const id = +e.args[1];
if(!id)
return e.reply("lol no");
const tags = (await getTags(id)).map(t => t.tag);
const tags = (await lib.getTags(id)).map(t => t.tag);
if(tags.length === 0)
return e.reply(`item ${cfg.main.url}/${id} has no tags!`);
return e.reply(`item ${cfg.main.url}/${id} is tagged as: ${tags.join(', ')}`);
@ -32,7 +28,7 @@ export default async bot => {
if(!id)
return e.reply("lol no");
const tags = (await getTags(id)).map(t => t.tag);
const tags = (await lib.getTags(id)).map(t => t.tag);
const newtags = (e.message.includes(",")
? e.args.splice(2).join(" ").trim().split(",")
@ -44,26 +40,38 @@ export default async bot => {
await Promise.all(newtags.map(async ntag => {
try {
let tagid;
const tag_exists = await sql("tags").select("id", "tag").where("tag", ntag);
const tag_exists = await db`
select id, tag
from "tags"
where tag = ${ntag}
`;
if(tag_exists.length === 0) { // create new tag
tagid = (await sql("tags").insert({
tag: ntag
}))[0];
tagid = (await db`
insert into "tags" ${
db({
tag: ntag
}, 'tag')
}
`)[0];
}
else {
tagid = tag_exists[0].id;
}
return await sql("tags_assign").insert({
tag_id: tagid,
item_id: id,
prefix: `${e.user.prefix}${e.channel}`
});
return await db`
insert into "tags_assign" ${
db({
tag_id: tagid,
item_id: id,
prefix: `${e.user.prefix}${e.channel}`
}, 'tag_id', 'item_id', 'prefix')
}
`;
} catch(err) {
console.error(err);
}
}));
const ntags = (await getTags(id)).map(t => t.tag);
const ntags = (await lib.getTags(id)).map(t => t.tag);
if(ntags.length === 0)
return e.reply(`item ${cfg.main.url}/${id} has no tags!`);
return e.reply(`item ${cfg.main.url}/${id} is now tagged as: ${ntags.join(', ')}`);
@ -78,7 +86,7 @@ export default async bot => {
if(!id)
return e.reply("lol no");
const tags = await getTags(id);
const tags = await lib.getTags(id);
const removetags = (e.message.includes(",")
? e.args.splice(2).join(" ").trim().split(",")
@ -96,13 +104,19 @@ export default async bot => {
msg: "tag is not assigned"
};
}
let q = sql("tags_assign").where("tag_id", tagid).andWhere("item_id", id).del();
if(getLevel(e.user).level < 50)
q = q.andWhere("prefix", `${e.user.prefix}${e.channel}`);
const q = await db`
delete from "tags_assign"
where tag_id = ${+tagid}
and item_id = ${+id}
${ getLevel(e.user.level < 50)
? db`and prefix = ${e.user.prefix + e.channel}`
: db``
}
`;
return {
success: !!(await q),
success: !!q,
tag: rtag,
tagid: tagid
};
@ -110,7 +124,7 @@ export default async bot => {
e.reply(JSON.stringify(res));
const ntags = (await getTags(id)).map(t => t.tag);
const ntags = (await lib.getTags(id)).map(t => t.tag);
if(ntags.length === 0)
return e.reply(`item ${cfg.main.url}/${id} has no tags!`);
return e.reply(`item ${cfg.main.url}/${id} is now tagged as: ${ntags.join(', ')}`);

View File

@ -1,5 +1,5 @@
import cfg from "./inc/config.mjs";
import sql from "./inc/sql.mjs";
import db from "./inc/sql.mjs";
import lib from "./inc/lib.mjs";
import cuffeo from "cuffeo";
import { promises as fs } from "fs";
@ -20,35 +20,35 @@ import flummpress from "flummpress";
bot: await new cuffeo(cfg.clients)
};
console.time("loading");
//console.time("loading");
const modules = {
events: (await fs.readdir("./src/inc/events")).filter(f => f.endsWith(".mjs")),
trigger: (await fs.readdir("./src/inc/trigger")).filter(f => f.endsWith(".mjs"))
};
console.timeLog("loading", "directories");
//console.timeLog("loading", "directories");
const blah = (await Promise.all(Object.entries(modules).map(async ([dir, mods]) => ({
[dir]: (await Promise.all(mods.map(async mod => {
const res = await Promise.race([
(await import(`./inc/${dir}/${mod}`)).default(self),
new Promise((_, rej) => setTimeout(() => rej(false), timeout))
]);
console.timeLog("loading", `${dir}/${mod}`);
//console.timeLog("loading", `${dir}/${mod}`);
return res;
}))).flat(2)
})))).reduce((a, b) => ({...a, ...b}));
blah.events.forEach(event => {
console.timeLog("loading", `registering event > ${event.name}`);
//console.timeLog("loading", `registering event > ${event.name}`);
self.bot.on(event.listener, event.f);
});
blah.trigger.forEach(trigger => {
console.timeLog("loading", `registering trigger > ${trigger.name}`);
//console.timeLog("loading", `registering trigger > ${trigger.name}`);
self._trigger.set(trigger.name, new self.trigger(trigger));
});
console.timeEnd("loading");
//console.timeEnd("loading");
// websrv
@ -64,13 +64,15 @@ import flummpress from "flummpress";
req.theme = req.cookies.theme ?? 'f0ck';
if(req.cookies.session) {
const user = await sql("user_sessions") // get user
.select("user.id", "user.login", "user.user", "user.level", "user_sessions.id as sess_id", "user_options.*")
.where("user_sessions.session", lib.md5(req.cookies.session))
.leftJoin("user", "user.id", "user_sessions.user_id")
.leftJoin("user_options", "user_options.user_id", "user_sessions.user_id")
.limit(1);
const user = await db`
select "user".id, "user".login, "user".user, "user".level, "user_sessions".id as sess_id, "user_options".*
from "user_sessions"
left join "user" on "user".id = "user_sessions".user_id
left join "user_options" on "user_options".user_id = "user_sessions".user_id
where "user_sessions".session = ${lib.md5(req.cookies.session)}
limit 1
`;
if(user.length === 0) {
return res.writeHead(307, { // delete session
"Cache-Control": "no-cache, public",
@ -80,21 +82,33 @@ import flummpress from "flummpress";
}
req.session = user[0];
await sql("user_sessions") // log last action
.update("last_used", ~~(Date.now() / 1e3))
.update("last_action", req.url.pathname)
.update("browser", req.headers["user-agent"])
.where("id", user[0].sess_id);
// log last action
await db`
update "user_sessions" set ${
db({
last_used: ~~(Date.now() / 1e3),
last_action: req.url.pathname,
browser: req.headers['user-agent']
}, 'last_used', 'last_action', 'browser')
}
where id = ${+user[0].sess_id}
`;
// update userprofile
await sql("user_options")
.insert({
user_id: user[0].id,
mode: user[0].mode ?? 0,
theme: req.session.theme ?? "f0ck"
})
.onConflict("user_id")
.merge();
await db`
insert into "user_options" ${
db({
user_id: +user[0].id,
mode: user[0].mode ?? 0,
theme: req.session.theme ?? 'f0ck'
}, 'user_id', 'mode', 'theme')
}
on conflict ("user_id") do update set
mode = excluded.mode,
theme = excluded.theme,
user_id = excluded.user_id
`;
}
});