diff --git a/neko/index.js b/neko/index.js index d50aa6385..59cd61d08 100644 --- a/neko/index.js +++ b/neko/index.js @@ -268,6 +268,7 @@ if (!nativeBinding) { const { stringToAcct, acctToString, + formatMilliseconds, genString, IdConvertType, convertId, @@ -278,6 +279,7 @@ const { module.exports.stringToAcct = stringToAcct; module.exports.acctToString = acctToString; +module.exports.formatMilliseconds = formatMilliseconds; module.exports.genString = genString; module.exports.IdConvertType = IdConvertType; module.exports.convertId = convertId; diff --git a/packages/backend/native-utils/src/util/format_milliseconds.rs b/packages/backend/native-utils/src/util/format_milliseconds.rs new file mode 100644 index 000000000..b5fbb1e84 --- /dev/null +++ b/packages/backend/native-utils/src/util/format_milliseconds.rs @@ -0,0 +1,52 @@ +/// Convert milliseconds to human readable string +#[cfg_attr(feature = "napi", napi_derive::napi)] +pub fn format_milliseconds(milliseconds: i32) -> String { + let mut seconds = milliseconds / 1000; + let mut minutes = seconds / 60; + let mut hours = minutes / 60; + let days = hours / 24; + + seconds %= 60; + minutes %= 60; + hours %= 24; + + let mut buf = Vec::::new(); + + if days > 0 { + buf.push(format!("{} day(s)", days)); + } + if hours > 0 { + buf.push(format!("{} hour(s)", hours)); + } + if minutes > 0 { + buf.push(format!("{} minute(s)", minutes)); + } + if seconds > 0 { + buf.push(format!("{} second(s)", seconds)); + } + + buf.join(", ") +} + +#[cfg(test)] +mod unit_test { + use super::format_milliseconds; + use pretty_assertions::assert_eq; + + #[test] + fn format_milliseconds_test() { + assert_eq!(format_milliseconds(1000), "1 second(s)".to_string()); + assert_eq!( + format_milliseconds(1387938), + "23 minute(s), 7 second(s)".to_string() + ); + assert_eq!( + format_milliseconds(34200457), + "9 hour(s), 30 minute(s)".to_string() + ); + assert_eq!( + format_milliseconds(998244353), + "11 day(s), 13 hour(s), 17 minute(s), 24 second(s)".to_string() + ); + } +} diff --git a/packages/backend/native-utils/src/util/mod.rs b/packages/backend/native-utils/src/util/mod.rs index 6f286a479..3a5461101 100644 --- a/packages/backend/native-utils/src/util/mod.rs +++ b/packages/backend/native-utils/src/util/mod.rs @@ -1,3 +1,4 @@ pub mod acct; +pub mod format_milliseconds; pub mod id; pub mod random; diff --git a/packages/backend/src/misc/convert-milliseconds.ts b/packages/backend/src/misc/convert-milliseconds.ts deleted file mode 100644 index d8c163ffd..000000000 --- a/packages/backend/src/misc/convert-milliseconds.ts +++ /dev/null @@ -1,17 +0,0 @@ -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(", "); -} diff --git a/packages/backend/src/server/api/limiter.ts b/packages/backend/src/server/api/limiter.ts index f03f8754c..d9bd5f486 100644 --- a/packages/backend/src/server/api/limiter.ts +++ b/packages/backend/src/server/api/limiter.ts @@ -2,7 +2,7 @@ import Limiter from "ratelimiter"; 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"; +import { formatMilliseconds } from "native-utils/built/index.js"; const logger = new Logger("limiter"); @@ -78,7 +78,7 @@ export const limiter = ( if (info.remaining === 0) { reject({ message: "RATE_LIMIT_EXCEEDED", - remainingTime: convertMilliseconds(info.resetMs - Date.now()), + remainingTime: formatMilliseconds(info.resetMs - Date.now()), }); } else { ok();