feat: display remaining time on ratelimits

This commit is contained in:
ThatOneCalculator 2023-06-22 17:14:27 -07:00
parent 8a45d25912
commit 7ca519560f
No known key found for this signature in database
GPG Key ID: 8703CACD01000000
4 changed files with 30 additions and 7 deletions

View 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(", ");
}

View File

@ -66,8 +66,11 @@ export default async (
limit as IEndpointMeta["limit"] & { key: NonNullable<string> }, limit as IEndpointMeta["limit"] & { key: NonNullable<string> },
limitActor, limitActor,
).catch((e) => { ).catch((e) => {
const remainingTime = e.remainingTime
? `Please try again in ${e.remainingTime}.`
: "Please try again later.";
throw new ApiError({ throw new ApiError({
message: "Rate limit exceeded. Please try again later.", message: `Rate limit exceeded. ${remainingTime}`,
code: "RATE_LIMIT_EXCEEDED", code: "RATE_LIMIT_EXCEEDED",
id: "d5826d14-3982-4d2e-8011-b9e9f02499ef", id: "d5826d14-3982-4d2e-8011-b9e9f02499ef",
httpStatusCode: 429, httpStatusCode: 429,
@ -94,7 +97,7 @@ export default async (
} }
if (ep.meta.requireAdmin && !user!.isAdmin) { 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) { if (ep.meta.requireModerator && !isModerator) {

View File

@ -3,6 +3,7 @@ import { CacheableLocalUser, User } from "@/models/entities/user.js";
import Logger from "@/services/logger.js"; import Logger from "@/services/logger.js";
import { redisClient } from "../../db/redis.js"; import { redisClient } from "../../db/redis.js";
import type { IEndpointMeta } from "./endpoints.js"; import type { IEndpointMeta } from "./endpoints.js";
import { convertMilliseconds } from "@/misc/convert-milliseconds.js";
const logger = new Logger("limiter"); const logger = new Logger("limiter");
@ -76,7 +77,10 @@ export const limiter = (
); );
if (info.remaining === 0) { if (info.remaining === 0) {
reject("RATE_LIMIT_EXCEEDED"); reject({
message: "RATE_LIMIT_EXCEEDED",
remainingTime: convertMilliseconds(info.resetMs),
});
} else { } else {
ok(); ok();
} }

View File

@ -3,7 +3,7 @@ export const errors = {
INVALID_PARAM: { INVALID_PARAM: {
value: { value: {
error: { error: {
message: "Invalid param.", message: "Invalid parameter.",
code: "INVALID_PARAM", code: "INVALID_PARAM",
id: "3d81ceae-475f-4600-b2a8-2bc116157532", id: "3d81ceae-475f-4600-b2a8-2bc116157532",
}, },
@ -25,8 +25,7 @@ export const errors = {
AUTHENTICATION_FAILED: { AUTHENTICATION_FAILED: {
value: { value: {
error: { error: {
message: message: "Authentication failed.",
"Authentication failed. Please ensure your token is correct.",
code: "AUTHENTICATION_FAILED", code: "AUTHENTICATION_FAILED",
id: "b0a7f5f8-dc2f-4171-b91f-de88ad238e14", id: "b0a7f5f8-dc2f-4171-b91f-de88ad238e14",
}, },
@ -38,7 +37,7 @@ export const errors = {
value: { value: {
error: { error: {
message: 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", code: "I_AM_CALC",
id: "60c46cd1-f23a-46b1-bebe-5d2b73951a84", id: "60c46cd1-f23a-46b1-bebe-5d2b73951a84",
}, },