fix(api): improve ratelimits

This commit is contained in:
diced 2022-06-20 10:49:24 -07:00
parent 8fea0cbe77
commit d21e48a1a3
No known key found for this signature in database
GPG key ID: 370BD1BA142842D1
4 changed files with 41 additions and 20 deletions

View file

@ -0,0 +1,9 @@
/*
Warnings:
- You are about to drop the column `ratelimited` on the `User` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "User" DROP COLUMN "ratelimited",
ADD COLUMN "ratelimit" TIMESTAMP(3);

View file

@ -17,7 +17,7 @@ model User {
embedTitle String? embedTitle String?
embedColor String @default("#2f3136") embedColor String @default("#2f3136")
embedSiteName String? @default("{image.file} • {user.name}") embedSiteName String? @default("{image.file} • {user.name}")
ratelimited Boolean @default(false) ratelimit DateTime?
domains String[] domains String[]
images Image[] images Image[]
urls Url[] urls Url[]

View file

@ -37,7 +37,7 @@ export type NextApiRes = NextApiResponse & {
forbid: (message: string, extra?: any) => void; forbid: (message: string, extra?: any) => void;
bad: (message: string) => void; bad: (message: string) => void;
json: (json: any) => void; json: (json: any) => void;
ratelimited: () => void; ratelimited: (remaining: number) => void;
setCookie: (name: string, value: unknown, options: CookieSerializeOptions) => void; setCookie: (name: string, value: unknown, options: CookieSerializeOptions) => void;
} }
@ -69,9 +69,9 @@ export const withZipline = (handler: (req: NextApiRequest, res: NextApiResponse)
}); });
}; };
res.ratelimited = () => { res.ratelimited = (remaining: number) => {
res.status(429); res.status(429);
res.setHeader('X-Ratelimit-Remaining', Math.floor(remaining / 1000));
res.json({ res.json({
error: '429: ratelimited', error: '429: ratelimited',
}); });

View file

@ -22,7 +22,21 @@ async function handler(req: NextApiReq, res: NextApiRes) {
}); });
if (!user) return res.forbid('authorization incorect'); if (!user) return res.forbid('authorization incorect');
if (user.ratelimited) return res.ratelimited(); if (user.ratelimit) {
const remaining = user.ratelimit.getTime() - Date.now();
if (remaining <= 0) {
await prisma.user.update({
where: {
id: user.id,
},
data: {
ratelimit: null,
},
});
} else {
return res.ratelimited(remaining);
}
}
await run(uploader.array('file'))(req, res); await run(uploader.array('file'))(req, res);
@ -85,28 +99,26 @@ async function handler(req: NextApiReq, res: NextApiRes) {
} }
} }
if (user.administrator && zconfig.ratelimit.admin !== 0) { if (user.administrator && zconfig.ratelimit.admin > 0) {
await prisma.user.update({ await prisma.user.update({
where: { where: {
id: user.id, id: user.id,
}, },
data: { data: {
ratelimited: true, ratelimit: new Date(Date.now() + (zconfig.ratelimit.admin * 1000)),
},
});
} else if (!user.administrator && zconfig.ratelimit.user > 0) {
if (user.administrator && zconfig.ratelimit.user > 0) {
await prisma.user.update({
where: {
id: user.id,
},
data: {
ratelimit: new Date(Date.now() + (zconfig.ratelimit.user * 1000)),
}, },
}); });
setTimeout(async () => await prisma.user.update({ where: { id: user.id }, data: { ratelimited: false } }), zconfig.ratelimit.admin * 1000).unref();
} }
if (!user.administrator && zconfig.ratelimit.user !== 0) {
await prisma.user.update({
where: {
id: user.id,
},
data: {
ratelimited: true,
},
});
setTimeout(async () => await prisma.user.update({ where: { id: user.id }, data: { ratelimited: false } }), zconfig.ratelimit.user * 1000).unref();
} }
return res.json({ files }); return res.json({ files });