diff --git a/backend/src/humanizeDuration.ts b/backend/src/humanizeDuration.ts new file mode 100644 index 00000000..937f2f40 --- /dev/null +++ b/backend/src/humanizeDuration.ts @@ -0,0 +1,34 @@ +import humanizeduration from "humanize-duration"; + +export const delayStringMultipliers = { + y: 1000 * 60 * 60 * 24 * (365 + 1 / 4 - 1 / 100 + 1 / 400), + mo: 1000 * 60 * 60* 24 * (365 + 1 / 4 - 1 / 100 + 1 / 400) / 12, + w: 1000 * 60 * 60 * 24 * 7, + d: 1000 * 60 * 60 * 24, + h: 1000 * 60 * 60, + m: 1000 * 60, + s: 1000, + x: 1, +}; + +export const humanizeDurationShort = humanizeduration.humanizer({ + language: "shortEn", + languages: { + shortEn: { + y: () => "y", + mo: () => "mo", + w: () => "w", + d: () => "d", + h: () => "h", + m: () => "m", + s: () => "s", + ms: () => "ms", + }, + }, + spacer: "", + unitMeasures: delayStringMultipliers +}); + +export const humanizeDuration = humanizeduration.humanizer({ + unitMeasures: delayStringMultipliers +}); \ No newline at end of file diff --git a/backend/src/humanizeDurationShort.ts b/backend/src/humanizeDurationShort.ts deleted file mode 100644 index 05b8ad39..00000000 --- a/backend/src/humanizeDurationShort.ts +++ /dev/null @@ -1,18 +0,0 @@ -import humanizeDuration from "humanize-duration"; - -export const humanizeDurationShort = humanizeDuration.humanizer({ - language: "shortEn", - languages: { - shortEn: { - y: () => "y", - mo: () => "mo", - w: () => "w", - d: () => "d", - h: () => "h", - m: () => "m", - s: () => "s", - ms: () => "ms", - }, - }, - spacer: "", -}); diff --git a/backend/src/plugins/Automod/functions/createMessageSpamTrigger.ts b/backend/src/plugins/Automod/functions/createMessageSpamTrigger.ts index 366d8746..a5ed35da 100644 --- a/backend/src/plugins/Automod/functions/createMessageSpamTrigger.ts +++ b/backend/src/plugins/Automod/functions/createMessageSpamTrigger.ts @@ -1,6 +1,6 @@ import z from "zod"; import { SavedMessage } from "../../../data/entities/SavedMessage.js"; -import { humanizeDurationShort } from "../../../humanizeDurationShort.js"; +import { humanizeDurationShort } from "../../../humanizeDuration.js"; import { getBaseUrl } from "../../../pluginUtils.js"; import { convertDelayStringToMS, sorter, zDelayString } from "../../../utils.js"; import { RecentActionType } from "../constants.js"; diff --git a/backend/src/plugins/ContextMenus/actions/ban.ts b/backend/src/plugins/ContextMenus/actions/ban.ts index 644a293b..268eef62 100644 --- a/backend/src/plugins/ContextMenus/actions/ban.ts +++ b/backend/src/plugins/ContextMenus/actions/ban.ts @@ -7,7 +7,7 @@ import { TextInputBuilder, TextInputStyle, } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { logger } from "../../../logger.js"; import { canActOn } from "../../../pluginUtils.js"; diff --git a/backend/src/plugins/ContextMenus/actions/mute.ts b/backend/src/plugins/ContextMenus/actions/mute.ts index 380f5e3a..534ac117 100644 --- a/backend/src/plugins/ContextMenus/actions/mute.ts +++ b/backend/src/plugins/ContextMenus/actions/mute.ts @@ -7,7 +7,7 @@ import { TextInputBuilder, TextInputStyle, } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError.js"; import { logger } from "../../../logger.js"; diff --git a/backend/src/plugins/LocateUser/commands/FollowCmd.ts b/backend/src/plugins/LocateUser/commands/FollowCmd.ts index ff18dabc..eefa0ccd 100644 --- a/backend/src/plugins/LocateUser/commands/FollowCmd.ts +++ b/backend/src/plugins/LocateUser/commands/FollowCmd.ts @@ -1,4 +1,4 @@ -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { registerExpiringVCAlert } from "../../../data/loops/expiringVCAlertsLoop.js"; diff --git a/backend/src/plugins/Logs/logFunctions/logMemberJoin.ts b/backend/src/plugins/Logs/logFunctions/logMemberJoin.ts index b73dcd7a..b84d3613 100644 --- a/backend/src/plugins/Logs/logFunctions/logMemberJoin.ts +++ b/backend/src/plugins/Logs/logFunctions/logMemberJoin.ts @@ -1,5 +1,5 @@ import { GuildMember } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { LogType } from "../../../data/LogType.js"; diff --git a/backend/src/plugins/ModActions/commands/ban/actualBanCmd.ts b/backend/src/plugins/ModActions/commands/ban/actualBanCmd.ts index 60903e44..eff9adff 100644 --- a/backend/src/plugins/ModActions/commands/ban/actualBanCmd.ts +++ b/backend/src/plugins/ModActions/commands/ban/actualBanCmd.ts @@ -1,5 +1,5 @@ import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { getMemberLevel } from "knub/helpers"; import { CaseTypes } from "../../../../data/CaseTypes.js"; diff --git a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts index 8ced00c4..2ec33308 100644 --- a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts +++ b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts @@ -2,7 +2,7 @@ import { Attachment, ChatInputCommandInteraction, GuildMember, Message, Snowflak import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes.js"; import { LogType } from "../../../../data/LogType.js"; -import { humanizeDurationShort } from "../../../../humanizeDurationShort.js"; +import { humanizeDurationShort } from "../../../../humanizeDuration.js"; import { canActOn, getContextChannel, isContextInteraction, sendContextResponse } from "../../../../pluginUtils.js"; import { DAYS, MINUTES, SECONDS, noop } from "../../../../utils.js"; import { CasesPlugin } from "../../../Cases/CasesPlugin.js"; diff --git a/backend/src/plugins/ModActions/commands/mute/actualMuteCmd.ts b/backend/src/plugins/ModActions/commands/mute/actualMuteCmd.ts index 2b30ecd9..a27bcefc 100644 --- a/backend/src/plugins/ModActions/commands/mute/actualMuteCmd.ts +++ b/backend/src/plugins/ModActions/commands/mute/actualMuteCmd.ts @@ -1,5 +1,5 @@ import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { ERRORS, RecoverablePluginError } from "../../../../RecoverablePluginError.js"; import { logger } from "../../../../logger.js"; diff --git a/backend/src/plugins/ModActions/commands/unmute/actualUnmuteCmd.ts b/backend/src/plugins/ModActions/commands/unmute/actualUnmuteCmd.ts index a6fc768a..df272c00 100644 --- a/backend/src/plugins/ModActions/commands/unmute/actualUnmuteCmd.ts +++ b/backend/src/plugins/ModActions/commands/unmute/actualUnmuteCmd.ts @@ -1,5 +1,5 @@ import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { UnknownUser, asSingleLine, renderUsername } from "../../../../utils.js"; import { MutesPlugin } from "../../../Mutes/MutesPlugin.js"; diff --git a/backend/src/plugins/ModActions/functions/banUserId.ts b/backend/src/plugins/ModActions/functions/banUserId.ts index d432de23..806a0e74 100644 --- a/backend/src/plugins/ModActions/functions/banUserId.ts +++ b/backend/src/plugins/ModActions/functions/banUserId.ts @@ -1,5 +1,5 @@ import { DiscordAPIError, Snowflake } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../data/CaseTypes.js"; import { LogType } from "../../../data/LogType.js"; diff --git a/backend/src/plugins/ModActions/functions/clearTempban.ts b/backend/src/plugins/ModActions/functions/clearTempban.ts index b2f80d83..07b3b062 100644 --- a/backend/src/plugins/ModActions/functions/clearTempban.ts +++ b/backend/src/plugins/ModActions/functions/clearTempban.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { CaseTypes } from "../../../data/CaseTypes.js"; diff --git a/backend/src/plugins/Mutes/commands/MutesCmd.ts b/backend/src/plugins/Mutes/commands/MutesCmd.ts index d599edd4..eda0de18 100644 --- a/backend/src/plugins/Mutes/commands/MutesCmd.ts +++ b/backend/src/plugins/Mutes/commands/MutesCmd.ts @@ -8,7 +8,7 @@ import { } from "discord.js"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; -import { humanizeDurationShort } from "../../../humanizeDurationShort.js"; +import { humanizeDurationShort } from "../../../humanizeDuration.js"; import { getBaseUrl } from "../../../pluginUtils.js"; import { DBDateFormat, MINUTES, renderUsername, resolveMember } from "../../../utils.js"; import { IMuteWithDetails, mutesCmd } from "../types.js"; diff --git a/backend/src/plugins/Mutes/functions/muteUser.ts b/backend/src/plugins/Mutes/functions/muteUser.ts index bb2b60ef..3e13f466 100644 --- a/backend/src/plugins/Mutes/functions/muteUser.ts +++ b/backend/src/plugins/Mutes/functions/muteUser.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError.js"; import { CaseTypes } from "../../../data/CaseTypes.js"; diff --git a/backend/src/plugins/Mutes/functions/unmuteUser.ts b/backend/src/plugins/Mutes/functions/unmuteUser.ts index a5624f0a..c7719354 100644 --- a/backend/src/plugins/Mutes/functions/unmuteUser.ts +++ b/backend/src/plugins/Mutes/functions/unmuteUser.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../data/CaseTypes.js"; import { AddMuteParams } from "../../../data/GuildMutes.js"; diff --git a/backend/src/plugins/Post/commands/ScheduledPostsListCmd.ts b/backend/src/plugins/Post/commands/ScheduledPostsListCmd.ts index 99f93597..ebc79e77 100644 --- a/backend/src/plugins/Post/commands/ScheduledPostsListCmd.ts +++ b/backend/src/plugins/Post/commands/ScheduledPostsListCmd.ts @@ -1,5 +1,5 @@ import { escapeCodeBlock } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import moment from "moment-timezone"; import { createChunkedMessage, DBDateFormat, deactivateMentions, sorter, trimLines } from "../../../utils.js"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin.js"; diff --git a/backend/src/plugins/Post/util/actualPostCmd.ts b/backend/src/plugins/Post/util/actualPostCmd.ts index d1265b02..32fb74d1 100644 --- a/backend/src/plugins/Post/util/actualPostCmd.ts +++ b/backend/src/plugins/Post/util/actualPostCmd.ts @@ -1,5 +1,5 @@ import { GuildTextBasedChannel, Message } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { registerUpcomingScheduledPost } from "../../../data/loops/upcomingScheduledPostsLoop.js"; diff --git a/backend/src/plugins/Reminders/commands/RemindCmd.ts b/backend/src/plugins/Reminders/commands/RemindCmd.ts index eaa66746..d8765127 100644 --- a/backend/src/plugins/Reminders/commands/RemindCmd.ts +++ b/backend/src/plugins/Reminders/commands/RemindCmd.ts @@ -1,4 +1,4 @@ -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { registerUpcomingReminder } from "../../../data/loops/upcomingRemindersLoop.js"; diff --git a/backend/src/plugins/Reminders/commands/RemindersCmd.ts b/backend/src/plugins/Reminders/commands/RemindersCmd.ts index 585557ab..846c7e1e 100644 --- a/backend/src/plugins/Reminders/commands/RemindersCmd.ts +++ b/backend/src/plugins/Reminders/commands/RemindersCmd.ts @@ -1,4 +1,4 @@ -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import moment from "moment-timezone"; import { createChunkedMessage, DBDateFormat, sorter } from "../../../utils.js"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin.js"; diff --git a/backend/src/plugins/Slowmode/commands/SlowmodeGetCmd.ts b/backend/src/plugins/Slowmode/commands/SlowmodeGetCmd.ts index e98160b4..4ece39e2 100644 --- a/backend/src/plugins/Slowmode/commands/SlowmodeGetCmd.ts +++ b/backend/src/plugins/Slowmode/commands/SlowmodeGetCmd.ts @@ -1,4 +1,4 @@ -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { slowmodeCmd } from "../types.js"; diff --git a/backend/src/plugins/Slowmode/commands/SlowmodeListCmd.ts b/backend/src/plugins/Slowmode/commands/SlowmodeListCmd.ts index 043d7d5a..3cc25eb9 100644 --- a/backend/src/plugins/Slowmode/commands/SlowmodeListCmd.ts +++ b/backend/src/plugins/Slowmode/commands/SlowmodeListCmd.ts @@ -1,5 +1,5 @@ import { GuildChannel, TextChannel } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { createChunkedMessage } from "knub/helpers"; import { errorMessage } from "../../../utils.js"; import { slowmodeCmd } from "../types.js"; diff --git a/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts b/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts index 52a5713e..666b1cb8 100644 --- a/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts +++ b/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts @@ -1,5 +1,5 @@ import { escapeInlineCode, PermissionsBitField } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { asSingleLine, DAYS, HOURS, MINUTES } from "../../../utils.js"; import { getMissingPermissions } from "../../../utils/getMissingPermissions.js"; diff --git a/backend/src/plugins/Tags/TagsPlugin.ts b/backend/src/plugins/Tags/TagsPlugin.ts index f1ded1d3..3fa07569 100644 --- a/backend/src/plugins/Tags/TagsPlugin.ts +++ b/backend/src/plugins/Tags/TagsPlugin.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../humanizeDuration.js"; import { PluginOptions, guildPlugin } from "knub"; import moment from "moment-timezone"; import { GuildArchives } from "../../data/GuildArchives.js"; diff --git a/backend/src/plugins/Utility/commands/AboutCmd.ts b/backend/src/plugins/Utility/commands/AboutCmd.ts index 6de19471..bf7d4935 100644 --- a/backend/src/plugins/Utility/commands/AboutCmd.ts +++ b/backend/src/plugins/Utility/commands/AboutCmd.ts @@ -1,5 +1,5 @@ import { APIEmbed, GuildChannel } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import LCL from "last-commit-log"; import shuffle from "lodash/shuffle.js"; import moment from "moment-timezone"; diff --git a/backend/src/plugins/Utility/commands/CleanCmd.ts b/backend/src/plugins/Utility/commands/CleanCmd.ts index db8553d3..9515394c 100644 --- a/backend/src/plugins/Utility/commands/CleanCmd.ts +++ b/backend/src/plugins/Utility/commands/CleanCmd.ts @@ -4,7 +4,7 @@ import { allowTimeout } from "../../../RegExpRunner.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { LogType } from "../../../data/LogType.js"; import { SavedMessage } from "../../../data/entities/SavedMessage.js"; -import { humanizeDurationShort } from "../../../humanizeDurationShort.js"; +import { humanizeDurationShort } from "../../../humanizeDuration.js"; import { getBaseUrl } from "../../../pluginUtils.js"; import { ModActionsPlugin } from "../../../plugins/ModActions/ModActionsPlugin.js"; import { DAYS, SECONDS, chunkArray, getInviteCodesInString, noop } from "../../../utils.js"; diff --git a/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts b/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts index 5c0cd334..3b78c3f1 100644 --- a/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts @@ -1,5 +1,5 @@ import { APIEmbed, ChannelType, Snowflake, StageChannel, VoiceChannel } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { EmbedWith, MINUTES, formatNumber, preEmbedPadding, trimLines, verboseUserMention } from "../../../utils.js"; import { UtilityPluginType } from "../types.js"; diff --git a/backend/src/utils.ts b/backend/src/utils.ts index 9a35ea73..8ae02e3c 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -29,7 +29,7 @@ import { import emojiRegex from "emoji-regex"; import fs from "fs"; import https from "https"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration, delayStringMultipliers } from "./humanizeDuration.js"; import isEqual from "lodash/isEqual.js"; import { performance } from "perf_hooks"; import tlds from "tlds" assert { type: "json" }; @@ -45,21 +45,14 @@ import { waitForButtonConfirm } from "./utils/waitForInteraction.js"; const fsp = fs.promises; -const delayStringMultipliers = { - w: 1000 * 60 * 60 * 24 * 7, - d: 1000 * 60 * 60 * 24, - h: 1000 * 60 * 60, - m: 1000 * 60, - s: 1000, - x: 1, -}; - export const MS = 1; export const SECONDS = 1000 * MS; export const MINUTES = 60 * SECONDS; export const HOURS = 60 * MINUTES; export const DAYS = 24 * HOURS; -export const WEEKS = 7 * 24 * HOURS; +export const WEEKS = 7 * DAYS; +export const YEARS = (365 + 1/4 - 1/100 + 1/400) * DAYS; +export const MONTHS = YEARS / 12 export const EMPTY_CHAR = "\u200b"; @@ -408,7 +401,7 @@ const MAX_DELAY_STRING_AMOUNT = 100 * 365 * DAYS; * Turns a "delay string" such as "1h30m" to milliseconds */ export function convertDelayStringToMS(str, defaultUnit = "m"): number | null { - const regex = /^([0-9]+)\s*([wdhms])?[a-z]*\s*/; + const regex = /^([0-9]+)\s*((?:mo?)|[ywdhs])?[a-z]*\s*/; let match; let ms = 0;