From e38283dd6940ea3ba1f1c2c2e45f536899371114 Mon Sep 17 00:00:00 2001 From: Ruby Date: Sat, 9 Nov 2024 06:39:59 +0100 Subject: [PATCH] feat: fix leap year rules, add year and month to the delay string --- backend/src/humanizeDuration.ts | 34 +++++++++++++++++++ backend/src/humanizeDurationShort.ts | 18 ---------- .../functions/createMessageSpamTrigger.ts | 2 +- .../src/plugins/ContextMenus/actions/mute.ts | 2 +- .../plugins/LocateUser/commands/FollowCmd.ts | 2 +- .../Logs/logFunctions/logMemberJoin.ts | 2 +- .../src/plugins/ModActions/commands/BanCmd.ts | 2 +- .../plugins/ModActions/commands/MassBanCmd.ts | 2 +- .../ModActions/functions/actualMuteUserCmd.ts | 2 +- .../functions/actualUnmuteUserCmd.ts | 2 +- .../plugins/ModActions/functions/banUserId.ts | 2 +- .../ModActions/functions/clearTempban.ts | 2 +- .../src/plugins/Mutes/commands/MutesCmd.ts | 2 +- .../src/plugins/Mutes/functions/muteUser.ts | 2 +- .../src/plugins/Mutes/functions/unmuteUser.ts | 2 +- .../Post/commands/ScheduledPostsListCmd.ts | 2 +- .../src/plugins/Post/util/actualPostCmd.ts | 2 +- .../plugins/Reminders/commands/RemindCmd.ts | 2 +- .../Reminders/commands/RemindersCmd.ts | 2 +- .../Slowmode/commands/SlowmodeGetCmd.ts | 2 +- .../Slowmode/commands/SlowmodeListCmd.ts | 2 +- .../Slowmode/commands/SlowmodeSetCmd.ts | 2 +- backend/src/plugins/Tags/TagsPlugin.ts | 2 +- .../src/plugins/Utility/commands/AboutCmd.ts | 2 +- .../src/plugins/Utility/commands/CleanCmd.ts | 2 +- .../Utility/functions/getChannelInfoEmbed.ts | 2 +- backend/src/utils.ts | 17 +++------- .../src/components/dashboard/GuildAccess.vue | 2 +- 28 files changed, 64 insertions(+), 55 deletions(-) create mode 100644 backend/src/humanizeDuration.ts delete mode 100644 backend/src/humanizeDurationShort.ts diff --git a/backend/src/humanizeDuration.ts b/backend/src/humanizeDuration.ts new file mode 100644 index 000000000..c4cb19740 --- /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), // 365 + 1/4 - 1/100 + 1/400 (leap year rules) = 365.2425 days + mo: 1000 * 60 * 60 * 24 * (365 + 1 / 4 - 1 / 100 + 1 / 400) / 12, // 365.2425 / 12 = 30.436875 days + w: 1000 * 60 * 60 * 24 * 7, + d: 1000 * 60 * 60 * 24, + h: 1000 * 60 * 60, + m: 1000 * 60, + s: 1000, + ms: 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 05b8ad393..000000000 --- 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 366d87468..a5ed35dae 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/mute.ts b/backend/src/plugins/ContextMenus/actions/mute.ts index d7dc60528..9f519f18b 100644 --- a/backend/src/plugins/ContextMenus/actions/mute.ts +++ b/backend/src/plugins/ContextMenus/actions/mute.ts @@ -1,5 +1,5 @@ import { ContextMenuCommandInteraction } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError.js"; import { canActOn } from "../../../pluginUtils.js"; diff --git a/backend/src/plugins/LocateUser/commands/FollowCmd.ts b/backend/src/plugins/LocateUser/commands/FollowCmd.ts index 874cbcfa0..7b908394d 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 b73dcd7a4..5160eb083 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 "humanize-duration"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { LogType } from "../../../data/LogType.js"; diff --git a/backend/src/plugins/ModActions/commands/BanCmd.ts b/backend/src/plugins/ModActions/commands/BanCmd.ts index d3c5c7456..092a23c7b 100644 --- a/backend/src/plugins/ModActions/commands/BanCmd.ts +++ b/backend/src/plugins/ModActions/commands/BanCmd.ts @@ -1,4 +1,4 @@ -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { getMemberLevel } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { CaseTypes } from "../../../data/CaseTypes.js"; diff --git a/backend/src/plugins/ModActions/commands/MassBanCmd.ts b/backend/src/plugins/ModActions/commands/MassBanCmd.ts index 8f4fdccb5..61c1485f7 100644 --- a/backend/src/plugins/ModActions/commands/MassBanCmd.ts +++ b/backend/src/plugins/ModActions/commands/MassBanCmd.ts @@ -4,7 +4,7 @@ import { performance } from "perf_hooks"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { CaseTypes } from "../../../data/CaseTypes.js"; import { LogType } from "../../../data/LogType.js"; -import { humanizeDurationShort } from "../../../humanizeDurationShort.js"; +import { humanizeDurationShort } from "../../../humanizeDuration.js"; import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils.js"; import { CasesPlugin } from "../../../plugins/Cases/CasesPlugin.js"; import { DAYS, MINUTES, SECONDS, noop } from "../../../utils.js"; diff --git a/backend/src/plugins/ModActions/functions/actualMuteUserCmd.ts b/backend/src/plugins/ModActions/functions/actualMuteUserCmd.ts index 2eac70ef3..2f718b0ed 100644 --- a/backend/src/plugins/ModActions/functions/actualMuteUserCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualMuteUserCmd.ts @@ -1,5 +1,5 @@ import { GuildMember, GuildTextBasedChannel, 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/functions/actualUnmuteUserCmd.ts b/backend/src/plugins/ModActions/functions/actualUnmuteUserCmd.ts index d4e931008..021db7f08 100644 --- a/backend/src/plugins/ModActions/functions/actualUnmuteUserCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualUnmuteUserCmd.ts @@ -1,5 +1,5 @@ import { GuildMember, Message, User } from "discord.js"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "../../../humanizeDuration.js"; import { GuildPluginData } from "knub"; import { hasPermission, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils.js"; import { MutesPlugin } from "../../../plugins/Mutes/MutesPlugin.js"; diff --git a/backend/src/plugins/ModActions/functions/banUserId.ts b/backend/src/plugins/ModActions/functions/banUserId.ts index 2ac01af31..1ab76cc22 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 e0962e9ca..340bf1343 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 d599edd44..eda0de18b 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 e57ae7623..d77a2ebde 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 a5624f0a4..c7719354a 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 99f935978..ebc79e773 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 93f7ac5cf..d9d7f170b 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 136a5c30a..202f79440 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 04ef41255..3b8a91d98 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 { sendErrorMessage } from "../../../pluginUtils.js"; import { createChunkedMessage, DBDateFormat, sorter } from "../../../utils.js"; diff --git a/backend/src/plugins/Slowmode/commands/SlowmodeGetCmd.ts b/backend/src/plugins/Slowmode/commands/SlowmodeGetCmd.ts index e98160b49..4ece39e25 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 043d7d5a1..3cc25eb96 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 82ebec82e..ece21411b 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 { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils.js"; import { asSingleLine, DAYS, HOURS, MINUTES } from "../../../utils.js"; diff --git a/backend/src/plugins/Tags/TagsPlugin.ts b/backend/src/plugins/Tags/TagsPlugin.ts index 303a13dc2..750d38686 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 6de194715..bf7d49359 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 683f28f21..7a3e79a1a 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, sendErrorMessage, sendSuccessMessage } 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 5c0cd3347..3b78c3f15 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 214d3f20b..160f5de6e 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -28,7 +28,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" }; @@ -44,21 +44,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"; @@ -407,7 +400,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; diff --git a/dashboard/src/components/dashboard/GuildAccess.vue b/dashboard/src/components/dashboard/GuildAccess.vue index a28ddd1bf..d224d0c79 100644 --- a/dashboard/src/components/dashboard/GuildAccess.vue +++ b/dashboard/src/components/dashboard/GuildAccess.vue @@ -108,7 +108,7 @@ import { GuildState, RootState } from "../../store/types"; -import humanizeDuration from "humanize-duration"; +import { humanizeDuration } from "humanize-duration"; import moment from "moment"; export default {