feat: ✨ display remaining time on ratelimits
This commit is contained in:
parent
8a45d25912
commit
7ca519560f
4 changed files with 30 additions and 7 deletions
17
packages/backend/src/misc/convert-milliseconds.ts
Normal file
17
packages/backend/src/misc/convert-milliseconds.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
export function convertMilliseconds(ms: number) {
|
||||
let seconds = Math.round(ms / 1000);
|
||||
let minutes = Math.round(seconds / 60);
|
||||
let hours = Math.round(minutes / 60);
|
||||
const days = Math.round(hours / 24);
|
||||
seconds %= 60;
|
||||
minutes %= 60;
|
||||
hours %= 24;
|
||||
|
||||
const result = [];
|
||||
if (days > 0) result.push(`${days} day(s)`);
|
||||
if (hours > 0) result.push(`${hours} hour(s)`);
|
||||
if (minutes > 0) result.push(`${minutes} minute(s)`);
|
||||
if (seconds > 0) result.push(`${seconds} second(s)`);
|
||||
|
||||
return result.join(", ");
|
||||
}
|
|
@ -66,8 +66,11 @@ export default async (
|
|||
limit as IEndpointMeta["limit"] & { key: NonNullable<string> },
|
||||
limitActor,
|
||||
).catch((e) => {
|
||||
const remainingTime = e.remainingTime
|
||||
? `Please try again in ${e.remainingTime}.`
|
||||
: "Please try again later.";
|
||||
throw new ApiError({
|
||||
message: "Rate limit exceeded. Please try again later.",
|
||||
message: `Rate limit exceeded. ${remainingTime}`,
|
||||
code: "RATE_LIMIT_EXCEEDED",
|
||||
id: "d5826d14-3982-4d2e-8011-b9e9f02499ef",
|
||||
httpStatusCode: 429,
|
||||
|
@ -94,7 +97,7 @@ export default async (
|
|||
}
|
||||
|
||||
if (ep.meta.requireAdmin && !user!.isAdmin) {
|
||||
throw new ApiError(accessDenied, { reason: "You are not the admin." });
|
||||
throw new ApiError(accessDenied, { reason: "You are not an admin." });
|
||||
}
|
||||
|
||||
if (ep.meta.requireModerator && !isModerator) {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { CacheableLocalUser, User } from "@/models/entities/user.js";
|
|||
import Logger from "@/services/logger.js";
|
||||
import { redisClient } from "../../db/redis.js";
|
||||
import type { IEndpointMeta } from "./endpoints.js";
|
||||
import { convertMilliseconds } from "@/misc/convert-milliseconds.js";
|
||||
|
||||
const logger = new Logger("limiter");
|
||||
|
||||
|
@ -76,7 +77,10 @@ export const limiter = (
|
|||
);
|
||||
|
||||
if (info.remaining === 0) {
|
||||
reject("RATE_LIMIT_EXCEEDED");
|
||||
reject({
|
||||
message: "RATE_LIMIT_EXCEEDED",
|
||||
remainingTime: convertMilliseconds(info.resetMs),
|
||||
});
|
||||
} else {
|
||||
ok();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ export const errors = {
|
|||
INVALID_PARAM: {
|
||||
value: {
|
||||
error: {
|
||||
message: "Invalid param.",
|
||||
message: "Invalid parameter.",
|
||||
code: "INVALID_PARAM",
|
||||
id: "3d81ceae-475f-4600-b2a8-2bc116157532",
|
||||
},
|
||||
|
@ -25,8 +25,7 @@ export const errors = {
|
|||
AUTHENTICATION_FAILED: {
|
||||
value: {
|
||||
error: {
|
||||
message:
|
||||
"Authentication failed. Please ensure your token is correct.",
|
||||
message: "Authentication failed.",
|
||||
code: "AUTHENTICATION_FAILED",
|
||||
id: "b0a7f5f8-dc2f-4171-b91f-de88ad238e14",
|
||||
},
|
||||
|
@ -38,7 +37,7 @@ export const errors = {
|
|||
value: {
|
||||
error: {
|
||||
message:
|
||||
"You sent a request to Calc, Calckey's resident stoner furry, instead of the server.",
|
||||
"You sent a request to Calc instead of the server. How did this happen?",
|
||||
code: "I_AM_CALC",
|
||||
id: "60c46cd1-f23a-46b1-bebe-5d2b73951a84",
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue