This repository has been archived by the owner on Oct 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Int-CI-Moderation: Add warn, mute, kick, and ban commands
- Loading branch information
1 parent
36a48da
commit 054aacd
Showing
8 changed files
with
687 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
// https://github.com/vercel/ms | ||
// https://github.com/Abdelrahmanwalidhassan/ms | ||
|
||
// Helpers. | ||
const s = 1000; | ||
const m = s * 60; | ||
const h = m * 60; | ||
const d = h * 24; | ||
const w = d * 7; | ||
const mo = d * 30.4375; | ||
const y = d * 365.25; | ||
|
||
type Unit = | ||
| "Years" | ||
| "Year" | ||
| "Yrs" | ||
| "Yr" | ||
| "Y" | ||
| "Months" | ||
| "Month" | ||
| "Mo" | ||
| "Weeks" | ||
| "Week" | ||
| "W" | ||
| "Days" | ||
| "Day" | ||
| "D" | ||
| "Hours" | ||
| "Hour" | ||
| "Hrs" | ||
| "Hr" | ||
| "H" | ||
| "Minutes" | ||
| "Minute" | ||
| "Mins" | ||
| "Min" | ||
| "M" | ||
| "Seconds" | ||
| "Second" | ||
| "Secs" | ||
| "Sec" | ||
| "s" | ||
| "Milliseconds" | ||
| "Millisecond" | ||
| "Msecs" | ||
| "Msec" | ||
| "Ms"; | ||
|
||
type UnitAnyCase = Unit | Uppercase<Unit> | Lowercase<Unit>; | ||
|
||
export type StringValue = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}` | string; | ||
|
||
interface Options { | ||
/** | ||
* Set to `true` to use verbose formatting. Defaults to `false`. | ||
*/ | ||
long?: boolean; | ||
} | ||
|
||
/** | ||
* Parse or format the given value. | ||
* | ||
* @param value - The string or number to convert | ||
* @param options - Options for the conversion | ||
* @throws Error if `value` is not a non-empty string or a number | ||
*/ | ||
function msFn(value: StringValue, options?: Options): number; | ||
function msFn(value: number, options?: Options): string; | ||
function msFn(value: StringValue | number, options?: Options): number | string { | ||
try { | ||
if (typeof value === "string" && value.length > 0) { | ||
return parse(value); | ||
} else if (typeof value === "number" && isFinite(value)) { | ||
return options?.long ? fmtLong(value) : fmtShort(value); | ||
} | ||
throw new Error("Value is not a string or number."); | ||
} catch (error) { | ||
const message = isError(error) | ||
? `${error.message}. value=${JSON.stringify(value)}` | ||
: "An unknown error has occurred."; | ||
throw new Error(message); | ||
} | ||
} | ||
|
||
/** | ||
* Parse the given string and return milliseconds. | ||
* | ||
* @param str - A string to parse to milliseconds | ||
* @returns The parsed value in milliseconds, or `NaN` if the string can't be | ||
* parsed | ||
*/ | ||
function parse(str: string): number { | ||
if (str.length > 100) { | ||
throw new Error("Value exceeds the maximum length of 100 characters."); | ||
} | ||
const match = | ||
/^(?<value>-?(?:\d+)?\.?\d+) *(?<type>milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|months?|mo?|years?|yrs?|y)?$/i.exec( | ||
str, | ||
); | ||
// Named capture groups need to be manually typed today. | ||
// https://github.com/microsoft/TypeScript/issues/32098 | ||
const groups = match?.groups as { value: string; type?: string } | undefined; | ||
if (!groups) { | ||
return NaN; | ||
} | ||
const n = parseFloat(groups.value); | ||
const type = (groups.type || "ms").toLowerCase() as Lowercase<Unit>; | ||
switch (type) { | ||
case "years": | ||
case "year": | ||
case "yrs": | ||
case "yr": | ||
case "y": | ||
return n * y; | ||
case "months": | ||
case "month": | ||
case "mo": | ||
return n * mo; | ||
case "weeks": | ||
case "week": | ||
case "w": | ||
return n * w; | ||
case "days": | ||
case "day": | ||
case "d": | ||
return n * d; | ||
case "hours": | ||
case "hour": | ||
case "hrs": | ||
case "hr": | ||
case "h": | ||
return n * h; | ||
case "minutes": | ||
case "minute": | ||
case "mins": | ||
case "min": | ||
case "m": | ||
return n * m; | ||
case "seconds": | ||
case "second": | ||
case "secs": | ||
case "sec": | ||
case "s": | ||
return n * s; | ||
case "milliseconds": | ||
case "millisecond": | ||
case "msecs": | ||
case "msec": | ||
case "ms": | ||
return n; | ||
default: | ||
// This should never occur. | ||
throw new Error(`The unit ${type as string} was matched, but no matching case exists.`); | ||
} | ||
} | ||
|
||
/** | ||
* Parse the given StringValue and return milliseconds. | ||
* | ||
* @param value - A typesafe StringValue to parse to milliseconds | ||
* @returns The parsed value in milliseconds, or `NaN` if the string can't be | ||
* parsed | ||
*/ | ||
export function parseStrict(value: StringValue): number { | ||
return parse(value); | ||
} | ||
|
||
// eslint-disable-next-line import/no-default-export | ||
export default msFn; | ||
|
||
/** | ||
* Short format for `ms`. | ||
*/ | ||
function fmtShort(ms: number): StringValue { | ||
const msAbs = Math.abs(ms); | ||
if (msAbs >= d) { | ||
return `${Math.round(ms / d)}d`; | ||
} | ||
if (msAbs >= h) { | ||
return `${Math.round(ms / h)}h`; | ||
} | ||
if (msAbs >= m) { | ||
return `${Math.round(ms / m)}m`; | ||
} | ||
if (msAbs >= s) { | ||
return `${Math.round(ms / s)}s`; | ||
} | ||
return `${ms}ms`; | ||
} | ||
|
||
/** | ||
* Long format for `ms`. | ||
*/ | ||
function fmtLong(ms: number): StringValue { | ||
const msAbs = Math.abs(ms); | ||
if (msAbs >= d) { | ||
return plural(ms, msAbs, d, "day"); | ||
} | ||
if (msAbs >= h) { | ||
return plural(ms, msAbs, h, "hour"); | ||
} | ||
if (msAbs >= m) { | ||
return plural(ms, msAbs, m, "minute"); | ||
} | ||
if (msAbs >= s) { | ||
return plural(ms, msAbs, s, "second"); | ||
} | ||
return `${ms} ms`; | ||
} | ||
|
||
/** | ||
* Format the given integer as a string. | ||
* | ||
* @param ms - milliseconds | ||
* @param options - Options for the conversion | ||
* @returns The formatted string | ||
*/ | ||
export function format(ms: number, options?: Options): string { | ||
if (typeof ms !== "number" || !isFinite(ms)) { | ||
throw new Error("Value provided to ms.format() must be of type number."); | ||
} | ||
return options?.long ? fmtLong(ms) : fmtShort(ms); | ||
} | ||
|
||
/** | ||
* Pluralization helper. | ||
*/ | ||
function plural(ms: number, msAbs: number, n: number, name: string): StringValue { | ||
const isPlural = msAbs >= n * 1.5; | ||
return `${Math.round(ms / n)} ${name}${isPlural ? "s" : ""}` as StringValue; | ||
} | ||
|
||
/** | ||
* A type guard for errors. | ||
* | ||
* @param value - The value to test | ||
* @returns A boolean `true` if the provided value is an Error-like object | ||
*/ | ||
function isError(value: unknown): value is Error { | ||
return typeof value === "object" && value !== null && "message" in value; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.