aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2022-08-05 23:24:51 -0400
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2022-08-05 23:24:51 -0400
commit1feb515882cfbbf33dc98d75a54898c1735cf5cb (patch)
tree20386e9d6ca6b5cb978283d672528c03647ec32f /src
parente68a0193b9f5888455f631d72c8783fc50e35faf (diff)
parent060349fcabe9e073eca9f6fd334e3355a9756096 (diff)
downloadtanzanite-1feb515882cfbbf33dc98d75a54898c1735cf5cb.tar.gz
tanzanite-1feb515882cfbbf33dc98d75a54898c1735cf5cb.tar.bz2
tanzanite-1feb515882cfbbf33dc98d75a54898c1735cf5cb.zip
Merge branch 'wip'
Diffstat (limited to 'src')
-rw-r--r--src/arguments/abbreviatedNumber.ts2
-rw-r--r--src/arguments/tinyColor.ts2
-rw-r--r--src/bot.ts10
-rw-r--r--src/commands/admin/channelPermissions.ts2
-rw-r--r--src/commands/admin/roleAll.ts2
-rw-r--r--src/commands/config/blacklist.ts2
-rw-r--r--src/commands/config/config.ts2
-rw-r--r--src/commands/config/disable.ts2
-rw-r--r--src/commands/config/features.ts2
-rw-r--r--src/commands/config/log.ts2
-rw-r--r--src/commands/dev/eval.ts2
-rw-r--r--src/commands/dev/javascript.ts2
-rw-r--r--src/commands/dev/sh.ts2
-rw-r--r--src/commands/fun/minesweeper.ts2
-rw-r--r--src/commands/info/botInfo.ts2
-rw-r--r--src/commands/info/color.ts2
-rw-r--r--src/commands/info/guildInfo.ts2
-rw-r--r--src/commands/info/help.ts2
-rw-r--r--src/commands/info/icon.ts2
-rw-r--r--src/commands/info/inviteInfo.ts43
-rw-r--r--src/commands/info/links.ts2
-rw-r--r--src/commands/info/userInfo.ts6
-rw-r--r--src/commands/leveling/leaderboard.ts2
-rw-r--r--src/commands/leveling/level.ts2
-rw-r--r--src/commands/leveling/levelRoles.ts2
-rw-r--r--src/commands/leveling/setLevel.ts2
-rw-r--r--src/commands/leveling/setXp.ts2
-rw-r--r--src/commands/moderation/ban.ts2
-rw-r--r--src/commands/moderation/block.ts2
-rw-r--r--src/commands/moderation/evidence.ts2
-rw-r--r--src/commands/moderation/hideCase.ts2
-rw-r--r--src/commands/moderation/kick.ts2
-rw-r--r--src/commands/moderation/lockdown.ts2
-rw-r--r--src/commands/moderation/massBan.ts2
-rw-r--r--src/commands/moderation/massEvidence.ts2
-rw-r--r--src/commands/moderation/modlog.ts2
-rw-r--r--src/commands/moderation/mute.ts2
-rw-r--r--src/commands/moderation/purge.ts2
-rw-r--r--src/commands/moderation/removeReactionEmoji.ts2
-rw-r--r--src/commands/moderation/role.ts2
-rw-r--r--src/commands/moderation/slowmode.ts2
-rw-r--r--src/commands/moderation/timeout.ts2
-rw-r--r--src/commands/moderation/unban.ts2
-rw-r--r--src/commands/moderation/unblock.ts2
-rw-r--r--src/commands/moderation/unmute.ts2
-rw-r--r--src/commands/moderation/untimeout.ts2
-rw-r--r--src/commands/moderation/warn.ts2
-rw-r--r--src/commands/moulberry-bush/capes.ts2
-rw-r--r--src/commands/moulberry-bush/giveawayPing.ts8
-rw-r--r--src/commands/moulberry-bush/moulHammer.ts16
-rw-r--r--src/commands/moulberry-bush/neuRepo.ts193
-rw-r--r--src/commands/moulberry-bush/report.ts6
-rw-r--r--src/commands/moulberry-bush/rule.ts5
-rw-r--r--src/commands/moulberry-bush/serverStatus.ts2
-rw-r--r--src/commands/moulberry-bush/solved.ts44
-rw-r--r--src/commands/tickets/ticket-!.ts65
-rw-r--r--src/commands/tickets/ticket-create.ts0
-rw-r--r--src/commands/utilities/calculator.ts2
-rw-r--r--src/commands/utilities/hash.ts2
-rw-r--r--src/commands/utilities/highlight-!.ts5
-rw-r--r--src/commands/utilities/highlight-add.ts2
-rw-r--r--src/commands/utilities/highlight-block.ts2
-rw-r--r--src/commands/utilities/highlight-clear.ts2
-rw-r--r--src/commands/utilities/highlight-matches.ts2
-rw-r--r--src/commands/utilities/highlight-remove.ts2
-rw-r--r--src/commands/utilities/highlight-show.ts2
-rw-r--r--src/commands/utilities/highlight-unblock.ts2
-rw-r--r--src/commands/utilities/price.ts2
-rw-r--r--src/commands/utilities/reminders.ts2
-rw-r--r--src/commands/utilities/steal.ts2
-rw-r--r--src/commands/utilities/viewRaw.ts2
-rw-r--r--src/commands/utilities/whoHasRole.ts2
-rw-r--r--src/commands/utilities/wolframAlpha.ts2
-rw-r--r--src/lib/common/AutoMod.ts2
-rw-r--r--src/lib/common/HighlightManager.ts2
-rw-r--r--src/lib/common/util/Minecraft.ts349
-rw-r--r--src/lib/common/util/Minecraft_Test.ts86
-rw-r--r--src/lib/common/util/Moderation.ts2
-rw-r--r--src/lib/extensions/discord.js/ExtendedGuild.ts28
-rw-r--r--src/lib/utils/BushClientUtils.ts2
-rw-r--r--src/lib/utils/BushConstants.ts21
-rw-r--r--src/lib/utils/BushLogger.ts58
-rw-r--r--src/lib/utils/BushUtils.ts2
-rw-r--r--src/listeners/bush/appealListener.ts4
-rw-r--r--src/listeners/bush/joinAutoBan.ts2
-rw-r--r--src/listeners/bush/supportThread.ts8
-rw-r--r--src/listeners/bush/userUpdateAutoBan.ts2
-rw-r--r--src/listeners/member-custom/bushLevelUpdate.ts2
-rw-r--r--src/listeners/message/quoteCreate.ts4
-rw-r--r--src/listeners/ws/INTERACTION_CREATE.ts2
-rw-r--r--src/tasks/cache/updateNeuItemCache.ts12
-rw-r--r--src/tasks/feature/memberCount.ts2
-rw-r--r--src/tasks/feature/removeExpiredPunishements.ts2
93 files changed, 971 insertions, 144 deletions
diff --git a/src/arguments/abbreviatedNumber.ts b/src/arguments/abbreviatedNumber.ts
index eba9214..a7d8ce5 100644
--- a/src/arguments/abbreviatedNumber.ts
+++ b/src/arguments/abbreviatedNumber.ts
@@ -1,5 +1,5 @@
import type { BushArgumentTypeCaster } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import numeral from 'numeral';
assert(typeof numeral === 'function');
diff --git a/src/arguments/tinyColor.ts b/src/arguments/tinyColor.ts
index 8d01928..148c078 100644
--- a/src/arguments/tinyColor.ts
+++ b/src/arguments/tinyColor.ts
@@ -1,5 +1,5 @@
import type { BushArgumentTypeCaster } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import tinycolorModule from 'tinycolor2';
assert(tinycolorModule);
diff --git a/src/bot.ts b/src/bot.ts
index d7b5ad9..038fbbb 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -3,11 +3,11 @@ import { init } from './lib/utils/BushLogger.js';
// also starts a REPL session
init();
-const { dirname } = await import('path');
-const { fileURLToPath } = await import('url');
-const { default: config } = await import('../config/options.js');
-const { Sentry } = await import('./lib/common/Sentry.js');
-const { BushClient } = await import('./lib/index.js');
+import { dirname } from 'path';
+import { fileURLToPath } from 'url';
+import { default as config } from '../config/options.js';
+import { Sentry } from './lib/common/Sentry.js';
+import { BushClient } from './lib/index.js';
const isDry = process.argv.includes('dry');
if (!isDry && config.credentials.sentryDsn !== null) new Sentry(dirname(fileURLToPath(import.meta.url)) || process.cwd(), config);
diff --git a/src/commands/admin/channelPermissions.ts b/src/commands/admin/channelPermissions.ts
index 15a1128..0b09e54 100644
--- a/src/commands/admin/channelPermissions.ts
+++ b/src/commands/admin/channelPermissions.ts
@@ -9,7 +9,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class ChannelPermissionsCommand extends BushCommand {
diff --git a/src/commands/admin/roleAll.ts b/src/commands/admin/roleAll.ts
index c731f08..a48bd6b 100644
--- a/src/commands/admin/roleAll.ts
+++ b/src/commands/admin/roleAll.ts
@@ -8,7 +8,7 @@ import {
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class RoleAllCommand extends BushCommand {
diff --git a/src/commands/config/blacklist.ts b/src/commands/config/blacklist.ts
index 6768a1c..a098f9d 100644
--- a/src/commands/config/blacklist.ts
+++ b/src/commands/config/blacklist.ts
@@ -10,7 +10,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, GuildMember, PermissionFlagsBits, User } from 'discord.js';
export default class BlacklistCommand extends BushCommand {
diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts
index c562add..cbfc5f7 100644
--- a/src/commands/config/config.ts
+++ b/src/commands/config/config.ts
@@ -14,7 +14,7 @@ import {
type GuildSettingType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo';
import {
diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts
index e9866d5..00dea76 100644
--- a/src/commands/config/disable.ts
+++ b/src/commands/config/disable.ts
@@ -9,7 +9,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, AutocompleteInteraction, PermissionFlagsBits } from 'discord.js';
import Fuse from 'fuse.js';
diff --git a/src/commands/config/features.ts b/src/commands/config/features.ts
index 5eafb0c..625086a 100644
--- a/src/commands/config/features.ts
+++ b/src/commands/config/features.ts
@@ -9,7 +9,7 @@ import {
type GuildFeatures,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
ActionRowBuilder,
ComponentType,
diff --git a/src/commands/config/log.ts b/src/commands/config/log.ts
index 3726105..f79f60e 100644
--- a/src/commands/config/log.ts
+++ b/src/commands/config/log.ts
@@ -9,7 +9,7 @@ import {
type GuildLogType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ArgumentGeneratorReturn } from 'discord-akairo';
import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js';
diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts
index ab7787d..a4a52b5 100644
--- a/src/commands/dev/eval.ts
+++ b/src/commands/dev/eval.ts
@@ -20,7 +20,7 @@ import {
type SlashMessage
} from '#lib';
import { Snowflake as Snowflake_ } from '@sapphire/snowflake';
-import assert from 'assert';
+import assert from 'assert/strict';
import { Canvas } from 'canvas';
import { exec } from 'child_process';
import {
diff --git a/src/commands/dev/javascript.ts b/src/commands/dev/javascript.ts
index 6b6c7e1..12ad6f7 100644
--- a/src/commands/dev/javascript.ts
+++ b/src/commands/dev/javascript.ts
@@ -8,7 +8,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js';
import { VM } from 'vm2';
assert(VM);
diff --git a/src/commands/dev/sh.ts b/src/commands/dev/sh.ts
index 1b9ce22..609129d 100644
--- a/src/commands/dev/sh.ts
+++ b/src/commands/dev/sh.ts
@@ -8,7 +8,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import chalk from 'chalk';
import { exec } from 'child_process';
import { ApplicationCommandOptionType, cleanCodeBlockContent, EmbedBuilder } from 'discord.js';
diff --git a/src/commands/fun/minesweeper.ts b/src/commands/fun/minesweeper.ts
index c2fdccf..f2db6ee 100644
--- a/src/commands/fun/minesweeper.ts
+++ b/src/commands/fun/minesweeper.ts
@@ -8,7 +8,7 @@ import {
type SlashMessage
} from '#lib';
import { Minesweeper } from '@notenoughupdates/discord.js-minesweeper';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType } from 'discord.js';
assert(Minesweeper);
diff --git a/src/commands/info/botInfo.ts b/src/commands/info/botInfo.ts
index f284e0f..d84fd4e 100644
--- a/src/commands/info/botInfo.ts
+++ b/src/commands/info/botInfo.ts
@@ -7,7 +7,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { EmbedBuilder, PermissionFlagsBits, version as discordJSVersion } from 'discord.js';
import * as os from 'os';
const { default: prettyBytes } = await import('pretty-bytes');
diff --git a/src/commands/info/color.ts b/src/commands/info/color.ts
index 7286c5c..7601562 100644
--- a/src/commands/info/color.ts
+++ b/src/commands/info/color.ts
@@ -8,7 +8,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, PermissionFlagsBits, Role } from 'discord.js';
import tinycolor from 'tinycolor2';
assert(tinycolor);
diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts
index dd5704f..e67cdf4 100644
--- a/src/commands/info/guildInfo.ts
+++ b/src/commands/info/guildInfo.ts
@@ -12,7 +12,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
ApplicationCommandOptionType,
ChannelType,
diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts
index 1a8eae5..492f25d 100644
--- a/src/commands/info/help.ts
+++ b/src/commands/info/help.ts
@@ -9,7 +9,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
ActionRowBuilder,
ApplicationCommandOptionType,
diff --git a/src/commands/info/icon.ts b/src/commands/info/icon.ts
index e66f900..b3434ec 100644
--- a/src/commands/info/icon.ts
+++ b/src/commands/info/icon.ts
@@ -1,5 +1,5 @@
import { BushCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { EmbedBuilder, escapeMarkdown, PermissionFlagsBits } from 'discord.js';
export default class IconCommand extends BushCommand {
diff --git a/src/commands/info/inviteInfo.ts b/src/commands/info/inviteInfo.ts
new file mode 100644
index 0000000..5df86ad
--- /dev/null
+++ b/src/commands/info/inviteInfo.ts
@@ -0,0 +1,43 @@
+import { Arg, ArgType, BushCommand, clientSendAndPermCheck, colors, type CommandMessage, type SlashMessage } from '#lib';
+import { ApplicationCommandOptionType, EmbedBuilder, Invite, PermissionFlagsBits } from 'discord.js';
+
+export default class InviteInfoCommand extends BushCommand {
+ public constructor() {
+ super('inviteInfo', {
+ aliases: ['invite-info', 'ii'],
+ category: 'info',
+ description: 'Get info about an invite.',
+ usage: ['invite-info [invite]'],
+ examples: ['invite-info discord.gg/moulberry'],
+ args: [
+ {
+ id: 'invite',
+ description: 'The guild to find information about.',
+ type: 'invite',
+ prompt: 'What invite would you like to find information about?',
+ retry: '{error} Choose a valid invite to find information about.',
+ slashType: ApplicationCommandOptionType.String
+ }
+ ],
+ slash: true,
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ userPermissions: []
+ });
+ }
+
+ public override async exec(message: CommandMessage | SlashMessage, args: { invite: ArgType<'invite' | 'string'> }) {
+ const invite = message.util.isSlashMessage(message)
+ ? ((await Arg.cast('invite', message, args.invite as string)) as ArgType<'invite'>)
+ : (args.invite as Invite);
+
+ const inviteInfoEmbed = new EmbedBuilder().setTitle(`Invite to ${invite.guild!.name}`).setColor(colors.default);
+
+ this.generateAboutField(inviteInfoEmbed, invite);
+ }
+
+ private generateAboutField(embed: EmbedBuilder, invite: Invite) {
+ const about = [`**code:** ${invite.code}`, `**channel:** ${invite.channel!.name}`];
+
+ embed.addFields({ name: '» About', value: about.join('\n') });
+ }
+}
diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts
index 3c7add2..3dbdbef 100644
--- a/src/commands/info/links.ts
+++ b/src/commands/info/links.ts
@@ -1,5 +1,5 @@
import { BushCommand, clientSendAndPermCheck, invite, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
import packageDotJSON from '../../../package.json' assert { type: 'json' };
diff --git a/src/commands/info/userInfo.ts b/src/commands/info/userInfo.ts
index 3479ea3..7b67816 100644
--- a/src/commands/info/userInfo.ts
+++ b/src/commands/info/userInfo.ts
@@ -162,11 +162,11 @@ export default class UserInfoCommand extends BushCommand {
);
if (member.premiumSince) serverUserInfo.push(`**Booster Since:** ${timestampAndDelta(member.premiumSince, 'd')}`);
if (member.displayHexColor) serverUserInfo.push(`**Display Color:** ${member.displayHexColor}`);
- if (member.user.id == '322862723090219008' && member.guild?.id == mappings.guilds.bush)
+ if (member.user.id == mappings.users['IRONM00N'] && member.guild?.id == mappings.guilds["Moulberry's Bush"])
serverUserInfo.push(`**General Deletions:** 1⅓`);
if (
- (['384620942577369088', '496409778822709251'] as const).includes(member.user.id) &&
- member.guild.id == mappings.guilds.bush
+ ([mappings.users['nopo'], mappings.users['Bestower']] as const).includes(member.user.id) &&
+ member.guild.id == mappings.guilds["Moulberry's Bush"]
)
serverUserInfo.push(`**General Deletions:** ⅓`);
if (member?.nickname) serverUserInfo.push(`**Nickname:** ${escapeMarkdown(member?.nickname)}`);
diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts
index 7eef990..bb41a12 100644
--- a/src/commands/leveling/leaderboard.ts
+++ b/src/commands/leveling/leaderboard.ts
@@ -9,7 +9,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class LeaderboardCommand extends BushCommand {
diff --git a/src/commands/leveling/level.ts b/src/commands/leveling/level.ts
index 7888695..eda43f2 100644
--- a/src/commands/leveling/level.ts
+++ b/src/commands/leveling/level.ts
@@ -10,7 +10,7 @@ import {
type SlashMessage
} from '#lib';
import { SimplifyNumber } from '@notenoughupdates/simplify-number';
-import assert from 'assert';
+import assert from 'assert/strict';
import canvas from 'canvas';
import { ApplicationCommandOptionType, AttachmentBuilder, Guild, PermissionFlagsBits, User } from 'discord.js';
import got from 'got';
diff --git a/src/commands/leveling/levelRoles.ts b/src/commands/leveling/levelRoles.ts
index 470cf58..312623c 100644
--- a/src/commands/leveling/levelRoles.ts
+++ b/src/commands/leveling/levelRoles.ts
@@ -8,7 +8,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class LevelRolesCommand extends BushCommand {
diff --git a/src/commands/leveling/setLevel.ts b/src/commands/leveling/setLevel.ts
index b1d9516..8dc1cdf 100644
--- a/src/commands/leveling/setLevel.ts
+++ b/src/commands/leveling/setLevel.ts
@@ -9,7 +9,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class SetLevelCommand extends BushCommand {
diff --git a/src/commands/leveling/setXp.ts b/src/commands/leveling/setXp.ts
index 96b3ad7..5cd3a61 100644
--- a/src/commands/leveling/setXp.ts
+++ b/src/commands/leveling/setXp.ts
@@ -9,7 +9,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class SetXpCommand extends BushCommand {
diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts
index 1b045aa..00fde01 100644
--- a/src/commands/moderation/ban.ts
+++ b/src/commands/moderation/ban.ts
@@ -13,7 +13,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type User } from 'discord.js';
export default class BanCommand extends BushCommand {
diff --git a/src/commands/moderation/block.ts b/src/commands/moderation/block.ts
index 48436eb..00a1996 100644
--- a/src/commands/moderation/block.ts
+++ b/src/commands/moderation/block.ts
@@ -14,7 +14,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class BlockCommand extends BushCommand {
diff --git a/src/commands/moderation/evidence.ts b/src/commands/moderation/evidence.ts
index f480844..d36000f 100644
--- a/src/commands/moderation/evidence.ts
+++ b/src/commands/moderation/evidence.ts
@@ -11,7 +11,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { Argument, ArgumentGeneratorReturn } from 'discord-akairo';
import { ApplicationCommandOptionType, PermissionFlagsBits, type Message } from 'discord.js';
diff --git a/src/commands/moderation/hideCase.ts b/src/commands/moderation/hideCase.ts
index 6724d3c..9bd1d24 100644
--- a/src/commands/moderation/hideCase.ts
+++ b/src/commands/moderation/hideCase.ts
@@ -8,7 +8,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
export default class HideCaseCommand extends BushCommand {
diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts
index df14271..7807166 100644
--- a/src/commands/moderation/kick.ts
+++ b/src/commands/moderation/kick.ts
@@ -12,7 +12,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class KickCommand extends BushCommand {
diff --git a/src/commands/moderation/lockdown.ts b/src/commands/moderation/lockdown.ts
index 1224763..0561767 100644
--- a/src/commands/moderation/lockdown.ts
+++ b/src/commands/moderation/lockdown.ts
@@ -11,7 +11,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
ApplicationCommandOptionType,
Collection,
diff --git a/src/commands/moderation/massBan.ts b/src/commands/moderation/massBan.ts
index 0db5263..db50c44 100644
--- a/src/commands/moderation/massBan.ts
+++ b/src/commands/moderation/massBan.ts
@@ -13,7 +13,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, Collection, PermissionFlagsBits } from 'discord.js';
export default class MassBanCommand extends BushCommand {
diff --git a/src/commands/moderation/massEvidence.ts b/src/commands/moderation/massEvidence.ts
index 6547203..62f4825 100644
--- a/src/commands/moderation/massEvidence.ts
+++ b/src/commands/moderation/massEvidence.ts
@@ -11,7 +11,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits } from 'discord.js';
import { EvidenceCommand } from '../index.js';
diff --git a/src/commands/moderation/modlog.ts b/src/commands/moderation/modlog.ts
index 2bcc54d..4671f58 100644
--- a/src/commands/moderation/modlog.ts
+++ b/src/commands/moderation/modlog.ts
@@ -14,7 +14,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, escapeMarkdown, PermissionFlagsBits, User } from 'discord.js';
export default class ModlogCommand extends BushCommand {
diff --git a/src/commands/moderation/mute.ts b/src/commands/moderation/mute.ts
index 5502a84..4627f2c 100644
--- a/src/commands/moderation/mute.ts
+++ b/src/commands/moderation/mute.ts
@@ -14,7 +14,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class MuteCommand extends BushCommand {
diff --git a/src/commands/moderation/purge.ts b/src/commands/moderation/purge.ts
index ed5d49d..383c439 100644
--- a/src/commands/moderation/purge.ts
+++ b/src/commands/moderation/purge.ts
@@ -8,7 +8,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, Collection, PermissionFlagsBits, type Message } from 'discord.js';
export default class PurgeCommand extends BushCommand {
diff --git a/src/commands/moderation/removeReactionEmoji.ts b/src/commands/moderation/removeReactionEmoji.ts
index a088287..cc3713c 100644
--- a/src/commands/moderation/removeReactionEmoji.ts
+++ b/src/commands/moderation/removeReactionEmoji.ts
@@ -8,7 +8,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, Message, PermissionFlagsBits } from 'discord.js';
export default class RemoveReactionEmojiCommand extends BushCommand {
diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts
index 6febaa6..5251be7 100644
--- a/src/commands/moderation/role.ts
+++ b/src/commands/moderation/role.ts
@@ -13,7 +13,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { type ArgumentGeneratorReturn } from 'discord-akairo';
import { ApplicationCommandOptionType, PermissionFlagsBits, type Snowflake } from 'discord.js';
diff --git a/src/commands/moderation/slowmode.ts b/src/commands/moderation/slowmode.ts
index 641f88e..44ed84f 100644
--- a/src/commands/moderation/slowmode.ts
+++ b/src/commands/moderation/slowmode.ts
@@ -10,7 +10,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { Argument } from 'discord-akairo';
import { ApplicationCommandOptionType, ChannelType, PermissionFlagsBits } from 'discord.js';
diff --git a/src/commands/moderation/timeout.ts b/src/commands/moderation/timeout.ts
index 1ceedf9..3e2b10d 100644
--- a/src/commands/moderation/timeout.ts
+++ b/src/commands/moderation/timeout.ts
@@ -12,7 +12,7 @@ import {
type SlashMessage,
type TimeoutResponse
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class TimeoutCommand extends BushCommand {
diff --git a/src/commands/moderation/unban.ts b/src/commands/moderation/unban.ts
index c102434..3a6221a 100644
--- a/src/commands/moderation/unban.ts
+++ b/src/commands/moderation/unban.ts
@@ -11,7 +11,7 @@ import {
type SlashMessage,
type UnbanResponse
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type User } from 'discord.js';
export default class UnbanCommand extends BushCommand {
diff --git a/src/commands/moderation/unblock.ts b/src/commands/moderation/unblock.ts
index f8a57f8..6533da0 100644
--- a/src/commands/moderation/unblock.ts
+++ b/src/commands/moderation/unblock.ts
@@ -13,7 +13,7 @@ import {
type SlashMessage,
type UnblockResponse
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class UnblockCommand extends BushCommand {
diff --git a/src/commands/moderation/unmute.ts b/src/commands/moderation/unmute.ts
index 31944fc..648a178 100644
--- a/src/commands/moderation/unmute.ts
+++ b/src/commands/moderation/unmute.ts
@@ -12,7 +12,7 @@ import {
type SlashMessage,
type UnmuteResponse
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
import { BushCommand } from '../../lib/extensions/discord-akairo/BushCommand.js';
diff --git a/src/commands/moderation/untimeout.ts b/src/commands/moderation/untimeout.ts
index aa6665d..6ca28f4 100644
--- a/src/commands/moderation/untimeout.ts
+++ b/src/commands/moderation/untimeout.ts
@@ -12,7 +12,7 @@ import {
type RemoveTimeoutResponse,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class UntimeoutCommand extends BushCommand {
diff --git a/src/commands/moderation/warn.ts b/src/commands/moderation/warn.ts
index 442cddc..e1d1e90 100644
--- a/src/commands/moderation/warn.ts
+++ b/src/commands/moderation/warn.ts
@@ -14,7 +14,7 @@ import {
type SlashMessage,
type WarnResponse
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type GuildMember } from 'discord.js';
export default class WarnCommand extends BushCommand {
diff --git a/src/commands/moulberry-bush/capes.ts b/src/commands/moulberry-bush/capes.ts
index 1db2f72..8693dba 100644
--- a/src/commands/moulberry-bush/capes.ts
+++ b/src/commands/moulberry-bush/capes.ts
@@ -12,7 +12,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, PermissionFlagsBits, type APIEmbed, type AutocompleteInteraction } from 'discord.js';
import Fuse from 'fuse.js';
import got from 'got';
diff --git a/src/commands/moulberry-bush/giveawayPing.ts b/src/commands/moulberry-bush/giveawayPing.ts
index d93e0c9..8f8941f 100644
--- a/src/commands/moulberry-bush/giveawayPing.ts
+++ b/src/commands/moulberry-bush/giveawayPing.ts
@@ -1,5 +1,5 @@
-import { AllowedMentions, BushCommand, clientSendAndPermCheck, emojis, type CommandMessage } from '#lib';
-import assert from 'assert';
+import { AllowedMentions, BushCommand, clientSendAndPermCheck, emojis, mappings, type CommandMessage } from '#lib';
+import assert from 'assert/strict';
import { PermissionFlagsBits } from 'discord.js';
export default class GiveawayPingCommand extends BushCommand {
@@ -24,8 +24,8 @@ export default class GiveawayPingCommand extends BushCommand {
cooldown: 1.44e7, //4 hours
ratelimit: 1,
editable: false,
- restrictedGuilds: ['516977525906341928'],
- restrictedChannels: ['767782084981817344', '833855738501267456']
+ restrictedGuilds: [mappings.guilds["Moulberry's Bush"]],
+ restrictedChannels: [mappings.channels['giveaways']]
});
}
diff --git a/src/commands/moulberry-bush/moulHammer.ts b/src/commands/moulberry-bush/moulHammer.ts
index 0eeb769..7bb514e 100644
--- a/src/commands/moulberry-bush/moulHammer.ts
+++ b/src/commands/moulberry-bush/moulHammer.ts
@@ -1,5 +1,13 @@
-import { BushCommand, clientSendAndPermCheck, colors, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import {
+ BushCommand,
+ clientSendAndPermCheck,
+ colors,
+ mappings,
+ type ArgType,
+ type CommandMessage,
+ type SlashMessage
+} from '#lib';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class MoulHammerCommand extends BushCommand {
@@ -22,8 +30,8 @@ export default class MoulHammerCommand extends BushCommand {
],
slash: true,
channel: 'guild',
- slashGuilds: ['516977525906341928'],
- restrictedGuilds: ['516977525906341928'],
+ slashGuilds: [mappings.guilds["Moulberry's Bush"]],
+ restrictedGuilds: [mappings.guilds["Moulberry's Bush"]],
clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: []
});
diff --git a/src/commands/moulberry-bush/neuRepo.ts b/src/commands/moulberry-bush/neuRepo.ts
new file mode 100644
index 0000000..d07ba53
--- /dev/null
+++ b/src/commands/moulberry-bush/neuRepo.ts
@@ -0,0 +1,193 @@
+import { BushCommand, clientSendAndPermCheck, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
+import canvas from 'canvas';
+import {
+ ApplicationCommandOptionType,
+ AttachmentBuilder,
+ AutocompleteInteraction,
+ CacheType,
+ PermissionFlagsBits
+} from 'discord.js';
+import { dirname, join } from 'path';
+import tinycolor from 'tinycolor2';
+import { fileURLToPath } from 'url';
+import { formattingInfo, RawNeuItem } from '../../lib/common/util/Minecraft.js';
+
+export default class NeuRepoCommand extends BushCommand {
+ public static items: { name: string; id: string }[] = [];
+
+ public constructor() {
+ super('neuRepo', {
+ aliases: ['neu-repo', 'repo-item', 'neu-item', 'item-repo'],
+ category: "Moulberry's Bush",
+ description: 'Get information about an item from the NEU item repo.',
+ usage: ['neu-repo <item>'],
+ examples: ['neu-repo BARRIER'],
+ args: [
+ {
+ id: 'item',
+ description: 'The item id that you would like to find neu item information about.',
+ type: 'string',
+ prompt: 'What SkyBlock item would you like to get information about?',
+ retry: '{error} Pick a valid SkyBlock item ID. Try using the slash command for a better experience.',
+ slashType: ApplicationCommandOptionType.String,
+ autocomplete: true
+ }
+ /* {
+ id: 'dangerous',
+ description: 'Whether or not to use the dangerous branch.',
+ prompt: 'Would you like to use the dangerous branch instead of the master branch?',
+ match: 'flag',
+ flag: ['--dangerous', '-d'],
+ default: false,
+ optional: true,
+ slashType: ApplicationCommandOptionType.Boolean
+ } */
+ ],
+ slash: false,
+ clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
+ userPermissions: [],
+ ownerOnly: true,
+ hidden: true
+ });
+ }
+
+ public override async exec(
+ message: CommandMessage | SlashMessage,
+ args: { item: ArgType<'string'> /* dangerous: ArgType<'flag'> */ }
+ ) {
+ const itemPath = join(import.meta.url, '..', '..', '..', '..', '..', 'neu-item-repo-dangerous', 'items', `${args.item}.json`);
+ const item = (await import(itemPath, { assert: { type: 'json' } })).default as RawNeuItem;
+
+ const toolTip = this.toolTip(item);
+
+ return message.util.reply({
+ files: [new AttachmentBuilder(toolTip, { name: `${item.internalname}.png`, description: item.displayname })]
+ });
+ }
+
+ public toolTip(item: RawNeuItem): Buffer {
+ canvas.registerFont(join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..', 'assets', 'Faithful.ttf'), {
+ family: 'Faithful'
+ });
+
+ const background = '#100010';
+
+ const width = 250;
+ const height = 250;
+ const scale = 10;
+
+ const itemRender = canvas.createCanvas(width, height),
+ ctx = itemRender.getContext('2d');
+
+ ctx.globalAlpha = 0.94;
+ ctx.fillStyle = background;
+
+ // top outside
+ ctx.fillRect(scale, 0, width - 2 * scale, scale);
+
+ // bottom outside
+ ctx.fillRect(scale, height - scale, width - 2 * scale, scale);
+
+ // left outside
+ ctx.fillRect(0, scale, scale, height - 2 * scale);
+
+ // right outside
+ ctx.fillRect(width - scale, scale, scale, height - 2 * scale);
+
+ // middle
+ ctx.fillRect(2 * scale, 2 * scale, width - 4 * scale, height - 4 * scale);
+
+ ctx.globalAlpha = 0.78;
+
+ const borderColorStart = parseInt(new tinycolor(this.getPrimaryColour(item.displayname)).toHex(), 16);
+ const borderColorEnd = ((borderColorStart & 0xfefefe) >> 1) | (borderColorStart & 0xff000000);
+
+ const borderColorStartStr = `#${borderColorStart.toString(16)}`;
+ const borderColorEndStr = `#${borderColorEnd.toString(16)}`;
+
+ ctx.fillStyle = borderColorStartStr;
+
+ // top highlight
+ ctx.fillRect(scale, scale, width - 2 * scale, scale);
+
+ // left highlight
+ ctx.fillRect(scale, 2 * scale, scale, height - 3 * scale);
+
+ // bottom highlight
+ {
+ const x = 2 * scale,
+ y = height - 2 * scale,
+ w = width - 3 * scale,
+ h = scale;
+ const gradient = ctx.createLinearGradient(x, y, x + w, y + h);
+ gradient.addColorStop(0, borderColorStartStr);
+ gradient.addColorStop(1, borderColorEndStr);
+ ctx.fillStyle = gradient;
+
+ ctx.fillRect(x, y, w, h);
+ }
+
+ // right highlight
+ {
+ const x = width - 2 * scale,
+ y = 2 * scale,
+ w = scale,
+ h = height - 4 * scale;
+ const gradient = ctx.createLinearGradient(x, y, x + w, y + h);
+ gradient.addColorStop(0, borderColorStartStr);
+ gradient.addColorStop(1, borderColorEndStr);
+ ctx.fillStyle = gradient;
+
+ ctx.fillRect(x, y, w, h);
+ }
+
+ item.displayname.split('');
+
+ return itemRender.toBuffer();
+ }
+
+ // stolen from NEU and modified
+ public getPrimaryColourCode(displayname: string): code {
+ let lastColourCode = -99;
+ let currentColour = 0;
+ const mostCommon = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ for (let i = 0; i < displayname.length; i++) {
+ const c = displayname.charAt(i);
+ if (c === '\u00A7') {
+ lastColourCode = i;
+ } else if (lastColourCode === i - 1) {
+ const colIndex = '0123456789abcdef'.indexOf(c);
+ if (colIndex >= 0) {
+ currentColour = colIndex;
+ } else {
+ currentColour = 0;
+ }
+ } else if ('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.indexOf(c) >= 0) {
+ if (currentColour > 0) {
+ mostCommon[currentColour] = mostCommon[currentColour]++;
+ }
+ }
+ }
+ let mostCommonCount = 0;
+ for (let index = 0; index < mostCommon.length; index++) {
+ if (mostCommon[index] > mostCommonCount) {
+ mostCommonCount = mostCommon[index];
+ currentColour = index;
+ }
+ }
+
+ return <code>'0123456789abcdef'.charAt(currentColour);
+ }
+
+ // stolen from NEU and modified
+ public getPrimaryColour(displayname: string) {
+ const code = this.getPrimaryColourCode(displayname);
+ return formattingInfo[`§${code}`].foregroundDarker;
+ }
+
+ public override async autocomplete(interaction: AutocompleteInteraction<CacheType>) {
+ return interaction.respond([{ name: 'Blazetekk™ Ham Radio', value: 'BLAZETEKK_HAM_RADIO' }]);
+ }
+}
+
+type code = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';
diff --git a/src/commands/moulberry-bush/report.ts b/src/commands/moulberry-bush/report.ts
index 13ef2b6..d0c4f33 100644
--- a/src/commands/moulberry-bush/report.ts
+++ b/src/commands/moulberry-bush/report.ts
@@ -4,12 +4,13 @@ import {
clientSendAndPermCheck,
colors,
emojis,
+ mappings,
timestampAndDelta,
type ArgType,
type CommandMessage
} from '#lib';
import { stripIndent } from '#tags';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
export default class ReportCommand extends BushCommand {
@@ -54,11 +55,12 @@ export default class ReportCommand extends BushCommand {
return await message.util.reply(`${emojis.error} This command can only be used in servers where reporting is enabled.`);
if (!member) return await message.util.reply(`${emojis.error} Choose someone to report`);
- if (member.user.id === '322862723090219008')
+ if (member.user.id === mappings.users['IRONM00N'])
return await message.util.reply({
content: `Thank you for your report! We take these allegations very seriously and have reported <@${member.user.id}> to the FBI!`,
allowedMentions: AllowedMentions.none()
});
+
if (member.user.bot)
return await message.util.reply(`${emojis.error} You cannot report a bot <:WeirdChamp:756283321301860382>.`);
diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts
index d58b78e..25a3ef0 100644
--- a/src/commands/moulberry-bush/rule.ts
+++ b/src/commands/moulberry-bush/rule.ts
@@ -3,6 +3,7 @@ import {
Arg,
BushCommand,
clientSendAndPermCheck,
+ mappings,
type CommandMessage,
type OptArgType,
type SlashMessage
@@ -98,11 +99,11 @@ export default class RuleCommand extends BushCommand {
}
],
slash: true,
- slashGuilds: ['516977525906341928'],
+ slashGuilds: [mappings.guilds["Moulberry's Bush"]],
channel: 'guild',
clientPermissions: (m) => clientSendAndPermCheck(m, [PermissionFlagsBits.EmbedLinks], true),
userPermissions: [],
- restrictedGuilds: ['516977525906341928']
+ restrictedGuilds: [mappings.guilds["Moulberry's Bush"]]
});
}
diff --git a/src/commands/moulberry-bush/serverStatus.ts b/src/commands/moulberry-bush/serverStatus.ts
index a4d5e45..1237b3f 100644
--- a/src/commands/moulberry-bush/serverStatus.ts
+++ b/src/commands/moulberry-bush/serverStatus.ts
@@ -1,5 +1,5 @@
import { BushCommand, clientSendAndPermCheck, colors, emojis, type CommandMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { EmbedBuilder, PermissionFlagsBits } from 'discord.js';
import got from 'got';
diff --git a/src/commands/moulberry-bush/solved.ts b/src/commands/moulberry-bush/solved.ts
new file mode 100644
index 0000000..8e123c4
--- /dev/null
+++ b/src/commands/moulberry-bush/solved.ts
@@ -0,0 +1,44 @@
+import { BushCommand, clientSendAndPermCheck, emojis, mappings, type CommandMessage, type SlashMessage } from '#lib';
+import assert from 'assert/strict';
+
+export default class Solved extends BushCommand {
+ public constructor() {
+ super('solved', {
+ aliases: ['solved'],
+ category: "Moulberry's Bush",
+ description: 'A command to mark a support threads as solved.',
+ usage: ['solved'],
+ examples: ['solved'],
+ slash: true,
+ channel: 'guild',
+ clientPermissions: (m) => clientSendAndPermCheck(m),
+ userPermissions: [],
+ slashGuilds: [mappings.guilds["Moulberry's Bush"]],
+ restrictedGuilds: [mappings.guilds["Moulberry's Bush"]]
+ });
+ }
+
+ public override async exec(message: CommandMessage | SlashMessage) {
+ assert(message.inGuild());
+ assert(message.channel);
+
+ if (!message.channel.isThread()) return message.util.reply(`${emojis.error} This command can only be used in threads.`);
+
+ if (message.channel.parentId !== mappings.channels['neu-support'])
+ return message.util.reply(
+ `${emojis.error} This command can only be used in thread that are created in <#${mappings.channels['neu-support']}>.`
+ );
+
+ if (message.channel.name.startsWith('[Solved]')) return message.util.reply(`${emojis.error} This thread is already solved.`);
+
+ if (!message.channel.name.startsWith('Support'))
+ return message.util.reply(`${emojis.error} This thread is not a support thread.`);
+
+ const newName = `[Solved] ${message.channel.name}`;
+
+ await message.channel.setName(newName);
+ await message.util.reply(`${emojis.success} This thread has been marked as solved.`);
+
+ await message.channel.setArchived(true, `${message.author.tag} (${message.author.id}) marked this support thread as solved.`);
+ }
+}
diff --git a/src/commands/tickets/ticket-!.ts b/src/commands/tickets/ticket-!.ts
new file mode 100644
index 0000000..6ec4093
--- /dev/null
+++ b/src/commands/tickets/ticket-!.ts
@@ -0,0 +1,65 @@
+import { BushCommand, clientSendAndPermCheck, deepWriteable, type SlashMessage } from '#lib';
+import { Flag, type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo';
+import { ApplicationCommandOptionType } from 'discord.js';
+
+export const ticketSubcommands = deepWriteable({
+ create: {
+ description: 'Create a ticket.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'word',
+ description: 'What word do you want to highlight?',
+ retry: '{error} Enter a valid word.',
+ type: ApplicationCommandOptionType.String,
+ required: true
+ }
+ ]
+ }
+} as const);
+
+export default class TicketCommand extends BushCommand {
+ public constructor() {
+ super('ticket', {
+ aliases: ['ticket'],
+ category: 'ticket',
+ description: 'Manage tickets.',
+ usage: ['ticket create <reason>'],
+ examples: ['ticket creates very cool ticket'],
+ slashOptions: Object.entries(ticketSubcommands).map(
+ ([subcommand, options]) => ({ name: subcommand, ...options } as SlashOption)
+ ),
+ slash: false,
+ channel: 'guild',
+ clientPermissions: (m) => clientSendAndPermCheck(m),
+ userPermissions: [],
+ ownerOnly: true,
+ hidden: true
+ });
+ }
+
+ public override *args(): ArgumentGeneratorReturn {
+ const subcommand: keyof typeof ticketSubcommands = yield {
+ id: 'subcommand',
+ type: Object.keys(ticketSubcommands),
+ prompt: {
+ start: 'What sub command would you like to use?',
+ retry: `{error} Valid subcommands are: ${Object.keys(ticketSubcommands)
+ .map((s) => `\`${s}\``)
+ .join()}.`
+ }
+ };
+
+ return Flag.continue(`ticket-${subcommand}`);
+ }
+
+ public override async exec() {
+ throw new Error('This command is not meant to be executed directly.');
+ }
+
+ public override async execSlash(message: SlashMessage, args: { subcommand: string; subcommandGroup?: string }) {
+ // manual `Flag.continue`
+ const subcommand = this.handler.modules.get(`ticket-${args.subcommandGroup ?? args.subcommand}`)!;
+ return subcommand.exec(message, args);
+ }
+}
diff --git a/src/commands/tickets/ticket-create.ts b/src/commands/tickets/ticket-create.ts
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/commands/tickets/ticket-create.ts
diff --git a/src/commands/utilities/calculator.ts b/src/commands/utilities/calculator.ts
index f0db916..c9dbbf2 100644
--- a/src/commands/utilities/calculator.ts
+++ b/src/commands/utilities/calculator.ts
@@ -7,7 +7,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js';
import { evaluate } from 'mathjs';
diff --git a/src/commands/utilities/hash.ts b/src/commands/utilities/hash.ts
index 6e8c37f..6817f04 100644
--- a/src/commands/utilities/hash.ts
+++ b/src/commands/utilities/hash.ts
@@ -1,5 +1,5 @@
import { BushCommand, clientSendAndPermCheck, type CommandMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import crypto from 'crypto';
import { ApplicationCommandOptionType } from 'discord.js';
import got from 'got';
diff --git a/src/commands/utilities/highlight-!.ts b/src/commands/utilities/highlight-!.ts
index b93f59a..f2ee259 100644
--- a/src/commands/utilities/highlight-!.ts
+++ b/src/commands/utilities/highlight-!.ts
@@ -186,10 +186,7 @@ export default class HighlightCommand extends BushCommand {
throw new Error('This command is not meant to be executed directly.');
}
- public override async execSlash(
- message: SlashMessage,
- args: { subcommand: keyof typeof highlightSubcommands; subcommandGroup?: string }
- ) {
+ public override async execSlash(message: SlashMessage, args: { subcommand: string; subcommandGroup?: string }) {
// manual `Flag.continue`
const subcommand = this.handler.modules.get(`highlight-${args.subcommandGroup ?? args.subcommand}`)!;
return subcommand.exec(message, args);
diff --git a/src/commands/utilities/highlight-add.ts b/src/commands/utilities/highlight-add.ts
index facee2c..e7d3ec6 100644
--- a/src/commands/utilities/highlight-add.ts
+++ b/src/commands/utilities/highlight-add.ts
@@ -1,5 +1,5 @@
import { AllowedMentions, BushCommand, emojis, format, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { highlightSubcommands } from './highlight-!.js';
export default class HighlightAddCommand extends BushCommand {
diff --git a/src/commands/utilities/highlight-block.ts b/src/commands/utilities/highlight-block.ts
index 9ee8a5a..7843836 100644
--- a/src/commands/utilities/highlight-block.ts
+++ b/src/commands/utilities/highlight-block.ts
@@ -1,5 +1,5 @@
import { AllowedMentions, BushCommand, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { Argument, ArgumentGeneratorReturn } from 'discord-akairo';
import { Channel, GuildMember, User } from 'discord.js';
import { BlockResult } from '../../lib/common/HighlightManager.js';
diff --git a/src/commands/utilities/highlight-clear.ts b/src/commands/utilities/highlight-clear.ts
index a5ff19e..5451e4e 100644
--- a/src/commands/utilities/highlight-clear.ts
+++ b/src/commands/utilities/highlight-clear.ts
@@ -1,5 +1,5 @@
import { BushCommand, ConfirmationPrompt, emojis, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { highlightSubcommands } from './highlight-!.js';
export default class HighlightClearCommand extends BushCommand {
diff --git a/src/commands/utilities/highlight-matches.ts b/src/commands/utilities/highlight-matches.ts
index 8964af8..863445e 100644
--- a/src/commands/utilities/highlight-matches.ts
+++ b/src/commands/utilities/highlight-matches.ts
@@ -1,5 +1,5 @@
import { BushCommand, ButtonPaginator, chunk, colors, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { type ArgumentGeneratorReturn } from 'discord-akairo';
import { type APIEmbed } from 'discord.js';
import { highlightSubcommands } from './highlight-!.js';
diff --git a/src/commands/utilities/highlight-remove.ts b/src/commands/utilities/highlight-remove.ts
index 67cf029..fd2fa90 100644
--- a/src/commands/utilities/highlight-remove.ts
+++ b/src/commands/utilities/highlight-remove.ts
@@ -1,5 +1,5 @@
import { AllowedMentions, BushCommand, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { highlightSubcommands } from './highlight-!.js';
export default class HighlightRemoveCommand extends BushCommand {
diff --git a/src/commands/utilities/highlight-show.ts b/src/commands/utilities/highlight-show.ts
index 301d719..bed8f19 100644
--- a/src/commands/utilities/highlight-show.ts
+++ b/src/commands/utilities/highlight-show.ts
@@ -1,5 +1,5 @@
import { AllowedMentions, BushCommand, colors, emojis, Highlight, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { EmbedBuilder } from 'discord.js';
import { highlightSubcommands } from './highlight-!.js';
diff --git a/src/commands/utilities/highlight-unblock.ts b/src/commands/utilities/highlight-unblock.ts
index d70fb28..d731205 100644
--- a/src/commands/utilities/highlight-unblock.ts
+++ b/src/commands/utilities/highlight-unblock.ts
@@ -1,5 +1,5 @@
import { AllowedMentions, BushCommand, emojis, type ArgType, type CommandMessage, type SlashMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { Argument, ArgumentGeneratorReturn } from 'discord-akairo';
import { Channel, GuildMember, User } from 'discord.js';
import { UnblockResult } from '../../lib/common/HighlightManager.js';
diff --git a/src/commands/utilities/price.ts b/src/commands/utilities/price.ts
index 3973844..8a3b5c6 100644
--- a/src/commands/utilities/price.ts
+++ b/src/commands/utilities/price.ts
@@ -1,5 +1,5 @@
import { ArgType, BushCommand, clientSendAndPermCheck, colors, emojis, format, oxford, type CommandMessage } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, AutocompleteInteraction, EmbedBuilder, PermissionFlagsBits } from 'discord.js';
import Fuse from 'fuse.js';
import got from 'got';
diff --git a/src/commands/utilities/reminders.ts b/src/commands/utilities/reminders.ts
index 18243fe..fdce981 100644
--- a/src/commands/utilities/reminders.ts
+++ b/src/commands/utilities/reminders.ts
@@ -10,7 +10,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { PermissionFlagsBits, type APIEmbed } from 'discord.js';
import { Op } from 'sequelize';
diff --git a/src/commands/utilities/steal.ts b/src/commands/utilities/steal.ts
index 3741d27..b07338f 100644
--- a/src/commands/utilities/steal.ts
+++ b/src/commands/utilities/steal.ts
@@ -9,7 +9,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { type ArgumentGeneratorReturn, type ArgumentType, type ArgumentTypeCaster } from 'discord-akairo';
import { ApplicationCommandOptionType, Attachment, PermissionFlagsBits } from 'discord.js';
import _ from 'lodash';
diff --git a/src/commands/utilities/viewRaw.ts b/src/commands/utilities/viewRaw.ts
index d2aef0d..a7d8b25 100644
--- a/src/commands/utilities/viewRaw.ts
+++ b/src/commands/utilities/viewRaw.ts
@@ -10,7 +10,7 @@ import {
type OptArgType,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, Constants, EmbedBuilder, Message, PermissionFlagsBits } from 'discord.js';
export default class ViewRawCommand extends BushCommand {
diff --git a/src/commands/utilities/whoHasRole.ts b/src/commands/utilities/whoHasRole.ts
index 851411a..789701c 100644
--- a/src/commands/utilities/whoHasRole.ts
+++ b/src/commands/utilities/whoHasRole.ts
@@ -10,7 +10,7 @@ import {
type CommandMessage,
type SlashMessage
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, escapeMarkdown, type CommandInteraction, type Role } from 'discord.js';
export default class WhoHasRoleCommand extends BushCommand {
diff --git a/src/commands/utilities/wolframAlpha.ts b/src/commands/utilities/wolframAlpha.ts
index bac9f58..b35e14f 100644
--- a/src/commands/utilities/wolframAlpha.ts
+++ b/src/commands/utilities/wolframAlpha.ts
@@ -9,7 +9,7 @@ import {
type SlashMessage
} from '#lib';
import { initializeClass as WolframAlphaAPI } from '@notenoughupdates/wolfram-alpha-api';
-import assert from 'assert';
+import assert from 'assert/strict';
import { ApplicationCommandOptionType, EmbedBuilder, type MessageOptions } from 'discord.js';
assert(WolframAlphaAPI);
diff --git a/src/lib/common/AutoMod.ts b/src/lib/common/AutoMod.ts
index 21bcb00..093f8af 100644
--- a/src/lib/common/AutoMod.ts
+++ b/src/lib/common/AutoMod.ts
@@ -1,5 +1,5 @@
import { colors, emojis, format, formatError, Moderation, unmuteResponse } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import chalk from 'chalk';
import {
ActionRowBuilder,
diff --git a/src/lib/common/HighlightManager.ts b/src/lib/common/HighlightManager.ts
index 4346007..8784b35 100644
--- a/src/lib/common/HighlightManager.ts
+++ b/src/lib/common/HighlightManager.ts
@@ -1,5 +1,5 @@
import { addToArray, format, Highlight, removeFromArray, timestamp, type HighlightWord } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
Collection,
GuildMember,
diff --git a/src/lib/common/util/Minecraft.ts b/src/lib/common/util/Minecraft.ts
new file mode 100644
index 0000000..a12ebf2
--- /dev/null
+++ b/src/lib/common/util/Minecraft.ts
@@ -0,0 +1,349 @@
+import { Byte, Int, parse } from '@ironm00n/nbt-ts';
+import { BitField } from 'discord.js';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+export enum FormattingCodes {
+ Black = '§0',
+ DarkBlue = '§1',
+ DarkGreen = '§2',
+ DarkAqua = '§3',
+ DarkRed = '§4',
+ DarkPurple = '§5',
+ Gold = '§6',
+ Gray = '§7',
+ DarkGray = '§8',
+ Blue = '§9',
+ Green = '§a',
+ Aqua = '§b',
+ Red = '§c',
+ LightPurple = '§d',
+ Yellow = '§e',
+ White = '§f',
+
+ Obfuscated = '§k',
+ Bold = '§l',
+ Strikethrough = '§m',
+ Underline = '§n',
+ Italic = '§o',
+ Reset = '§r'
+}
+
+// https://minecraft.fandom.com/wiki/Formatting_codes
+export const formattingInfo = {
+ [FormattingCodes.Black]: {
+ foreground: 'rgb(0, 0, 0)',
+ foregroundDarker: 'rgb(0, 0, 0)',
+ background: 'rgb(0, 0, 0)',
+ backgroundDarker: 'rgb(0, 0, 0)',
+ ansi: '\u001b[0;30m'
+ },
+ [FormattingCodes.DarkBlue]: {
+ foreground: 'rgb(0, 0, 170)',
+ foregroundDarker: 'rgb(0, 0, 118)',
+ background: 'rgb(0, 0, 42)',
+ backgroundDarker: 'rgb(0, 0, 29)',
+ ansi: '\u001b[0;34m'
+ },
+ [FormattingCodes.DarkGreen]: {
+ foreground: 'rgb(0, 170, 0)',
+ foregroundDarker: 'rgb(0, 118, 0)',
+ background: 'rgb(0, 42, 0)',
+ backgroundDarker: 'rgb(0, 29, 0)',
+ ansi: '\u001b[0;32m'
+ },
+ [FormattingCodes.DarkAqua]: {
+ foreground: 'rgb(0, 170, 170)',
+ foregroundDarker: 'rgb(0, 118, 118)',
+ background: 'rgb(0, 42, 42)',
+ backgroundDarker: 'rgb(0, 29, 29)',
+ ansi: '\u001b[0;36m'
+ },
+ [FormattingCodes.DarkRed]: {
+ foreground: 'rgb(170, 0, 0)',
+ foregroundDarker: 'rgb(118, 0, 0)',
+ background: 'rgb(42, 0, 0)',
+ backgroundDarker: 'rgb(29, 0, 0)',
+ ansi: '\u001b[0;31m'
+ },
+ [FormattingCodes.DarkPurple]: {
+ foreground: 'rgb(170, 0, 170)',
+ foregroundDarker: 'rgb(118, 0, 118)',
+ background: 'rgb(42, 0, 42)',
+ backgroundDarker: 'rgb(29, 0, 29)',
+ ansi: '\u001b[0;35m'
+ },
+ [FormattingCodes.Gold]: {
+ foreground: 'rgb(255, 170, 0)',
+ foregroundDarker: 'rgb(178, 118, 0)',
+ background: 'rgb(42, 42, 0)',
+ backgroundDarker: 'rgb(29, 29, 0)',
+ ansi: '\u001b[0;33m'
+ },
+ [FormattingCodes.Gray]: {
+ foreground: 'rgb(170, 170, 170)',
+ foregroundDarker: 'rgb(118, 118, 118)',
+ background: 'rgb(42, 42, 42)',
+ backgroundDarker: 'rgb(29, 29, 29)',
+ ansi: '\u001b[0;37m'
+ },
+ [FormattingCodes.DarkGray]: {
+ foreground: 'rgb(85, 85, 85)',
+ foregroundDarker: 'rgb(59, 59, 59)',
+ background: 'rgb(21, 21, 21)',
+ backgroundDarker: 'rgb(14, 14, 14)',
+ ansi: '\u001b[0;90m'
+ },
+ [FormattingCodes.Blue]: {
+ foreground: 'rgb(85, 85, 255)',
+ foregroundDarker: 'rgb(59, 59, 178)',
+ background: 'rgb(21, 21, 63)',
+ backgroundDarker: 'rgb(14, 14, 44)',
+ ansi: '\u001b[0;94m'
+ },
+ [FormattingCodes.Green]: {
+ foreground: 'rgb(85, 255, 85)',
+ foregroundDarker: 'rgb(59, 178, 59)',
+ background: 'rgb(21, 63, 21)',
+ backgroundDarker: 'rgb(14, 44, 14)',
+ ansi: '\u001b[0;92m'
+ },
+ [FormattingCodes.Aqua]: {
+ foreground: 'rgb(85, 255, 255)',
+ foregroundDarker: 'rgb(59, 178, 178)',
+ background: 'rgb(21, 63, 63)',
+ backgroundDarker: 'rgb(14, 44, 44)',
+ ansi: '\u001b[0;96m'
+ },
+ [FormattingCodes.Red]: {
+ foreground: 'rgb(255, 85, 85)',
+ foregroundDarker: 'rgb(178, 59, 59)',
+ background: 'rgb(63, 21, 21)',
+ backgroundDarker: 'rgb(44, 14, 14)',
+ ansi: '\u001b[0;91m'
+ },
+ [FormattingCodes.LightPurple]: {
+ foreground: 'rgb(255, 85, 255)',
+ foregroundDarker: 'rgb(178, 59, 178)',
+ background: 'rgb(63, 21, 63)',
+ backgroundDarker: 'rgb(44, 14, 44)',
+ ansi: '\u001b[0;95m'
+ },
+ [FormattingCodes.Yellow]: {
+ foreground: 'rgb(255, 255, 85)',
+ foregroundDarker: 'rgb(178, 178, 59)',
+ background: 'rgb(63, 63, 21)',
+ backgroundDarker: 'rgb(44, 44, 14)',
+ ansi: '\u001b[0;93m'
+ },
+ [FormattingCodes.White]: {
+ foreground: 'rgb(255, 255, 255)',
+ foregroundDarker: 'rgb(178, 178, 178)',
+ background: 'rgb(63, 63, 63)',
+ backgroundDarker: 'rgb(44, 44, 44)',
+ ansi: '\u001b[0;97m'
+ },
+
+ [FormattingCodes.Obfuscated]: { ansi: '\u001b[8m' },
+ [FormattingCodes.Bold]: { ansi: '\u001b[1m' },
+ [FormattingCodes.Strikethrough]: { ansi: '\u001b[9m' },
+ [FormattingCodes.Underline]: { ansi: '\u001b[4m' },
+ [FormattingCodes.Italic]: { ansi: '\u001b[3m' },
+ [FormattingCodes.Reset]: { ansi: '\u001b[0m' }
+} as const;
+
+export type McItemId = Lowercase<string>;
+export type SbItemId = Uppercase<string>;
+export type MojangJson = string;
+export type SbRecipeItem = `${SbItemId}:${number}` | '';
+export type SbRecipe = {
+ [Location in `${'A' | 'B' | 'C'}${1 | 2 | 3}`]: SbRecipeItem;
+};
+export type InfoType = 'WIKI_URL' | '';
+
+export type Slayer = `${'WOLF' | 'BLAZE' | 'EMAN'}_${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`;
+
+export interface RawNeuItem {
+ itemid: McItemId;
+ displayname: string;
+ nbttag: MojangJson;
+ damage: number;
+ lore: string[];
+ recipe?: SbRecipe;
+ internalname: SbItemId;
+ modver: string;
+ infoType: InfoType;
+ info?: string[];
+ crafttext: string;
+ vanilla?: boolean;
+ useneucraft?: boolean;
+ slayer_req?: Slayer;
+ clickcommand?: string;
+ x?: number;
+ y?: number;
+ z?: number;
+ island?: string;
+ recipes?: { type: string; cost: any[]; result: SbItemId }[];
+ /** @deprecated */
+ parent?: SbItemId;
+ noseal?: boolean;
+}
+
+export enum HideFlagsBits {
+ Enchantments = 1,
+ AttributeModifiers = 2,
+ Unbreakable = 4,
+ CanDestroy = 8,
+ CanPlaceOn = 16,
+ /**
+ * potion effects, shield pattern info, "StoredEnchantments", written book
+ * "generation" and "author", "Explosion", "Fireworks", and map tooltips
+ */
+ OtherInformation = 32,
+ Dyed = 64
+}
+
+export type HideFlagsString = keyof typeof HideFlagsBits;
+
+export class HideFlags extends BitField<HideFlagsString> {
+ public static override Flags = HideFlagsBits;
+}
+
+export const formattingCode = new RegExp(
+ `§[${Object.values(FormattingCodes)
+ .filter((v) => v.startsWith('§'))
+ .map((v) => v.substring(1))
+ .join('')}]`
+);
+
+export function removeMCFormatting(str: string) {
+ return str.replaceAll(formattingCode, '');
+}
+
+const repo = path.join(__dirname, '..', '..', '..', '..', '..', 'neu-item-repo-dangerous');
+
+export interface NbtTag {
+ overrideMeta?: Byte;
+ Unbreakable?: Int;
+ ench?: string[];
+ HideFlags?: HideFlags;
+ SkullOwner?: SkullOwner;
+ display?: NbtTagDisplay;
+ ExtraAttributes?: ExtraAttributes;
+}
+
+export interface SkullOwner {
+ Id?: string;
+ Properties?: {
+ textures?: { Value?: string }[];
+ };
+}
+
+export interface NbtTagDisplay {
+ Lore?: string[];
+ color?: Int;
+ Name?: string;
+}
+
+export type RuneId = string;
+
+export interface ExtraAttributes {
+ originTag?: Origin;
+ id?: string;
+ generator_tier?: Int;
+ boss_tier?: Int;
+ enchantments?: { hardened_mana?: Int };
+ dungeon_item_level?: Int;
+ runes?: { [key: RuneId]: Int };
+ petInfo?: PetInfo;
+}
+
+export interface PetInfo {
+ type: 'ZOMBIE';
+ active: boolean;
+ exp: number;
+ tier: 'COMMON' | 'UNCOMMON' | 'RARE' | 'EPIC' | 'LEGENDARY';
+ hideInfo: boolean;
+ candyUsed: number;
+}
+
+export type Origin = 'SHOP_PURCHASE';
+
+const neuConstantsPath = path.join(repo, 'constants');
+const neuPetsPath = path.join(neuConstantsPath, 'pets.json');
+const neuPets = (await import(neuPetsPath, { assert: { type: 'json' } })) as PetsConstants;
+const neuPetNumsPath = path.join(neuConstantsPath, 'petnums.json');
+const neuPetNums = (await import(neuPetNumsPath, { assert: { type: 'json' } })) as PetNums;
+
+export interface PetsConstants {
+ pet_rarity_offset: Record<string, number>;
+ pet_levels: number[];
+ custom_pet_leveling: Record<string, { type: number; pet_levels: number[]; max_level: number }>;
+ pet_types: Record<string, string>;
+}
+
+export interface PetNums {
+ [key: string]: {
+ [key: string]: {
+ '1': {
+ otherNums: number[];
+ statNums: Record<string, number>;
+ };
+ '100': {
+ otherNums: number[];
+ statNums: Record<string, number>;
+ };
+ 'stats_levelling_curve'?: `${number};${number};${number}`;
+ };
+ };
+}
+
+export class NeuItem {
+ public itemId: McItemId;
+ public displayName: string;
+ public nbtTag: NbtTag;
+ public internalName: SbItemId;
+ public lore: string[];
+
+ public constructor(raw: RawNeuItem) {
+ this.itemId = raw.itemid;
+ this.nbtTag = <NbtTag>parse(raw.nbttag);
+ this.displayName = raw.displayname;
+ this.internalName = raw.internalname;
+ this.lore = raw.lore;
+
+ this.petLoreReplacements();
+ }
+
+ private petLoreReplacements(level = -1) {
+ if (/.*?;[0-5]$/.test(this.internalName) && this.displayName.includes('LVL')) {
+ const maxLevel = neuPets?.custom_pet_leveling?.[this.internalName]?.max_level ?? 100;
+ this.displayName = this.displayName.replace('LVL', `1➡${maxLevel}`);
+
+ const nums = neuPetNums[this.internalName];
+ if (!nums) throw new Error(`Pet (${this.internalName}) has no pet nums.`);
+
+ const teir = ['COMMON', 'UNCOMMON', 'RARE', 'EPIC', 'LEGENDARY', 'MYTHIC'][+this.internalName.at(-1)!];
+ const petInfoTier = nums[teir];
+ if (!petInfoTier) throw new Error(`Pet (${this.internalName}) has no pet nums for ${teir} rarity.`);
+
+ const curve = petInfoTier?.stats_levelling_curve?.split(';');
+
+ // todo: finish copying from neu
+
+ const minStatsLevel = parseInt(curve?.[0] ?? '0');
+ const maxStatsLevel = parseInt(curve?.[0] ?? '100');
+
+ const lore = '';
+ }
+ }
+}
+
+export function mcToAnsi(str: string) {
+ for (const format in formattingInfo) {
+ str = str.replaceAll(format, formattingInfo[format as keyof typeof formattingInfo].ansi);
+ }
+ return `${str}\u001b[0m`;
+}
diff --git a/src/lib/common/util/Minecraft_Test.ts b/src/lib/common/util/Minecraft_Test.ts
new file mode 100644
index 0000000..26ca648
--- /dev/null
+++ b/src/lib/common/util/Minecraft_Test.ts
@@ -0,0 +1,86 @@
+import fs from 'fs/promises';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { mcToAnsi, RawNeuItem } from './Minecraft.js';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const repo = path.join(__dirname, '..', '..', '..', '..', '..', 'neu-item-repo-dangerous');
+const itemPath = path.join(repo, 'items');
+const items = await fs.readdir(itemPath);
+
+// for (let i = 0; i < 5; i++) {
+for (const path_ of items) {
+ // const randomItem = items[Math.floor(Math.random() * items.length)];
+ // console.log(randomItem);
+ const item = (await import(path.join(itemPath, /* randomItem */ path_), { assert: { type: 'json' } })).default as RawNeuItem;
+ if (/.*?((_MONSTER)|(_NPC)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$/.test(item.internalname)) continue;
+ if (!/.*?;[0-5]$/.test(item.internalname)) continue;
+ /* console.log(path_);
+ console.dir(item, { depth: Infinity }); */
+
+ /* console.log('==========='); */
+ // const nbt = parse(item.nbttag) as NbtTag;
+
+ // if (nbt?.SkullOwner?.Properties?.textures?.[0]?.Value) {
+ // nbt.SkullOwner.Properties.textures[0].Value = parse(
+ // Buffer.from(nbt.SkullOwner.Properties.textures[0].Value, 'base64').toString('utf-8')
+ // ) as string;
+ // }
+
+ // if (nbt.ExtraAttributes?.petInfo) {
+ // nbt.ExtraAttributes.petInfo = JSON.parse(nbt.ExtraAttributes.petInfo as any as string);
+ // }
+
+ // delete nbt.display?.Lore;
+
+ // console.dir(nbt, { depth: Infinity });
+ // console.log('===========');
+
+ /* if (nbt?.display && nbt.display.Name !== item.displayname)
+ console.log(`${path_} display name mismatch: ${mcToAnsi(nbt.display.Name)} != ${mcToAnsi(item.displayname)}`);
+
+ if (nbt?.ExtraAttributes && nbt?.ExtraAttributes.id !== item.internalname)
+ console.log(`${path_} internal name mismatch: ${mcToAnsi(nbt?.ExtraAttributes.id)} != ${mcToAnsi(item.internalname)}`); */
+
+ // console.log('===========');
+
+ console.log(mcToAnsi(item.displayname));
+ console.log(item.lore.map((l) => mcToAnsi(l)).join('\n'));
+
+ /* const keys = [
+ 'itemid',
+ 'displayname',
+ 'nbttag',
+ 'damage',
+ 'lore',
+ 'recipe',
+ 'internalname',
+ 'modver',
+ 'infoType',
+ 'info',
+ 'crafttext',
+ 'vanilla',
+ 'useneucraft',
+ 'slayer_req',
+ 'clickcommand',
+ 'x',
+ 'y',
+ 'z',
+ 'island',
+ 'recipes',
+ 'parent',
+ 'noseal'
+ ];
+
+ Object.keys(item).forEach((k) => {
+ if (!keys.includes(k)) throw new Error(`Unknown key: ${k}`);
+ });
+
+ if (
+ 'slayer_req' in item &&
+ !new Array(10).flatMap((_, i) => ['WOLF', 'BLAZE', 'EMAN'].map((e) => e + (i + 1)).includes(item.slayer_req!))
+ )
+ throw new Error(`Unknown slayer req: ${item.slayer_req!}`); */
+
+ /* console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-'); */
+}
diff --git a/src/lib/common/util/Moderation.ts b/src/lib/common/util/Moderation.ts
index fc01602..60e32c0 100644
--- a/src/lib/common/util/Moderation.ts
+++ b/src/lib/common/util/Moderation.ts
@@ -12,7 +12,7 @@ import {
type ModLogType,
type ValueOf
} from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
ActionRowBuilder,
ButtonBuilder,
diff --git a/src/lib/extensions/discord.js/ExtendedGuild.ts b/src/lib/extensions/discord.js/ExtendedGuild.ts
index c58916c..88bf5f1 100644
--- a/src/lib/extensions/discord.js/ExtendedGuild.ts
+++ b/src/lib/extensions/discord.js/ExtendedGuild.ts
@@ -11,6 +11,7 @@ import {
type GuildLogType,
type GuildModel
} from '#lib';
+import assert from 'assert/strict';
import {
AttachmentBuilder,
AttachmentPayload,
@@ -735,10 +736,33 @@ export class ExtendedGuild extends Guild {
sendOptions.content = 'Wondering who to invite? Start by inviting anyone who can help you build the server!';
break;
+ // todo: use enum for this
+ case 24 as MessageType: {
+ const embed = quote.embeds[0];
+ assert.equal(embed.data.type, 'auto_moderation_message');
+ const ruleName = embed.fields!.find((f) => f.name === 'rule_name')!.value;
+ const channelId = embed.fields!.find((f) => f.name === 'channel_id')!.value;
+ const keyword = embed.fields!.find((f) => f.name === 'keyword')!.value;
+
+ sendOptions.username = `AutoMod (${quote.member?.displayName ?? quote.author.username})`;
+ sendOptions.content = `Automod has blocked a message in <#${channelId}>`;
+ sendOptions.embeds = [
+ {
+ title: quote.member?.displayName ?? quote.author.username,
+ description: embed.description ?? 'There is no content???',
+ footer: {
+ text: `Keyword: ${keyword} • Rule: ${ruleName}`
+ },
+ color: 0x36393f
+ }
+ ];
+
+ break;
+ }
case MessageType.ChannelIconChange:
case MessageType.Call:
default:
- sendOptions.content = `${emojis.error} I cannot quote **${
+ sendOptions.content = `${emojis.error} I cannot quote messages of type **${
MessageType[quote.type] || quote.type
}** messages, please report this to my developers.`;
@@ -746,7 +770,7 @@ export class ExtendedGuild extends Guild {
}
sendOptions.allowedMentions = AllowedMentions.none();
- sendOptions.username = quote.member?.displayName ?? quote.author.username;
+ sendOptions.username ??= quote.member?.displayName ?? quote.author.username;
sendOptions.avatarURL = quote.member?.displayAvatarURL({ size: 2048 }) ?? quote.author.displayAvatarURL({ size: 2048 });
return await webhook.send(sendOptions); /* .catch((e: any) => e); */
diff --git a/src/lib/utils/BushClientUtils.ts b/src/lib/utils/BushClientUtils.ts
index af49803..920ff40 100644
--- a/src/lib/utils/BushClientUtils.ts
+++ b/src/lib/utils/BushClientUtils.ts
@@ -1,4 +1,4 @@
-import assert from 'assert';
+import assert from 'assert/strict';
import {
cleanCodeBlockContent,
DMChannel,
diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts
index 67723e3..8a7bf03 100644
--- a/src/lib/utils/BushConstants.ts
+++ b/src/lib/utils/BushConstants.ts
@@ -200,11 +200,22 @@ export const pronounMapping = Object.freeze({
*/
export const mappings = deepLock({
guilds: {
- bush: '516977525906341928',
- tree: '767448775450820639',
- staff: '784597260465995796',
- space_ship: '717176538717749358',
- sbr: '839287012409999391'
+ "Moulberry's Bush": '516977525906341928',
+ "Moulberry's Tree": '767448775450820639',
+ 'MB Staff': '784597260465995796',
+ "IRONM00N's Space Ship": '717176538717749358'
+ },
+
+ channels: {
+ 'neu-support': '714332750156660756',
+ 'giveaways': '767782084981817344'
+ },
+
+ users: {
+ IRONM00N: '322862723090219008',
+ Moulberry: '211288288055525376',
+ nopo: '384620942577369088',
+ Bestower: '496409778822709251'
},
permissions: {
diff --git a/src/lib/utils/BushLogger.ts b/src/lib/utils/BushLogger.ts
index 5c98760..995dd82 100644
--- a/src/lib/utils/BushLogger.ts
+++ b/src/lib/utils/BushLogger.ts
@@ -1,6 +1,7 @@
import chalk from 'chalk';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { Client, EmbedBuilder, escapeMarkdown, PartialTextBasedChannelFields, type Message } from 'discord.js';
+import { Client, EmbedBuilder, escapeMarkdown, Formatters, PartialTextBasedChannelFields, type Message } from 'discord.js';
+import { stripVTControlCharacters as stripColor } from 'node:util';
import repl, { REPLServer, REPL_MODE_STRICT } from 'repl';
import { WriteStream } from 'tty';
import { type SendMessageType } from '../extensions/discord-akairo/BushClient.js';
@@ -72,16 +73,16 @@ function parseFormatting(
discordFormat = false
): string | typeof content {
if (typeof content !== 'string') return content;
- const newContent: Array<string> = content.split(/<<|>>/);
- const tempParsedArray: Array<string> = [];
- newContent.forEach((value, index) => {
- if (index % 2 !== 0) {
- tempParsedArray.push(discordFormat ? `**${escapeMarkdown(value)}**` : color ? chalk[color](value) : value);
- } else {
- tempParsedArray.push(discordFormat ? escapeMarkdown(value) : value);
- }
- });
- return tempParsedArray.join('');
+ return content
+ .split(/<<|>>/)
+ .map((value, index) => {
+ if (discordFormat) {
+ return index % 2 === 0 ? escapeMarkdown(value) : Formatters.bold(escapeMarkdown(value));
+ } else {
+ return index % 2 === 0 || !color ? value : chalk[color](value);
+ }
+ })
+ .join('');
}
/**
@@ -99,33 +100,24 @@ function inspectContent(content: any, depth = 2, colors = true): string {
}
/**
- * Strips ANSI color codes from a string.
- * @param text The string to strip color codes from.
- * @returns A string without ANSI color codes.
- */
-function stripColor(text: string): string {
- return text.replace(
- // eslint-disable-next-line no-control-regex
- /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
- ''
- );
-}
-
-/**
* Generates a formatted timestamp for logging.
* @returns The formatted timestamp.
*/
function getTimeStamp(): string {
const now = new Date();
- const hours = now.getHours();
- const minute = now.getMinutes();
- let hour = hours;
- let amOrPm: 'AM' | 'PM' = 'AM';
- if (hour > 12) {
- amOrPm = 'PM';
- hour = hour - 12;
- }
- return `${hour >= 10 ? hour : `0${hour}`}:${minute >= 10 ? minute : `0${minute}`} ${amOrPm}`;
+ const minute = pad(now.getMinutes());
+ const hour = pad(now.getHours() % 12);
+ const meridiem = now.getHours() > 12 ? 'PM' : 'AM';
+ const year = now.getFullYear().toString().slice(2).padStart(2, '0');
+ const date = `${pad(now.getMonth() + 1)}/${pad(now.getDay())}/${year}`;
+ return `${date} ${hour}:${minute} ${meridiem}`;
+}
+
+/**
+ * Pad a two-digit number.
+ */
+function pad(num: number) {
+ return num.toString().padStart(2, '0');
}
/**
diff --git a/src/lib/utils/BushUtils.ts b/src/lib/utils/BushUtils.ts
index 19260c8..af173f9 100644
--- a/src/lib/utils/BushUtils.ts
+++ b/src/lib/utils/BushUtils.ts
@@ -10,7 +10,7 @@ import {
type SlashMessage
} from '#lib';
import { humanizeDuration as humanizeDurationMod } from '@notenoughupdates/humanize-duration';
-import assert from 'assert';
+import assert from 'assert/strict';
import cp from 'child_process';
import deepLock from 'deep-lock';
import { Util as AkairoUtil } from 'discord-akairo';
diff --git a/src/listeners/bush/appealListener.ts b/src/listeners/bush/appealListener.ts
index 424ee48..cbe62a8 100644
--- a/src/listeners/bush/appealListener.ts
+++ b/src/listeners/bush/appealListener.ts
@@ -1,5 +1,5 @@
import { BushListener, colors, mappings, ModLog, type BushClientEvents } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { EmbedBuilder } from 'discord.js';
import UserInfoCommand from '../../commands/info/userInfo.js';
import ModlogCommand from '../../commands/moderation/modlog.js';
@@ -14,7 +14,7 @@ export default class AppealListener extends BushListener {
}
public async exec(...[message]: BushClientEvents['messageCreate']): Promise<any> {
- if (!this.client.config.isProduction || !message.inGuild() || message.guildId !== mappings.guilds.bush) return;
+ if (!this.client.config.isProduction || !message.inGuild() || message.guildId !== mappings.guilds["Moulberry's Bush"]) return;
if (message.author.id !== '855446927688335370' || message.embeds.length < 1) return;
const userId = message.embeds[0].fields?.find?.((f) => f.name === 'What is your discord ID?')?.value;
diff --git a/src/listeners/bush/joinAutoBan.ts b/src/listeners/bush/joinAutoBan.ts
index 082a925..4370e86 100644
--- a/src/listeners/bush/joinAutoBan.ts
+++ b/src/listeners/bush/joinAutoBan.ts
@@ -12,7 +12,7 @@ export default class JoinAutoBanListener extends BushListener {
public async exec(...[member]: BushClientEvents['guildMemberAdd']): Promise<void> {
if (!this.client.config.isProduction) return;
- if (member.guild.id !== mappings.guilds.bush) return;
+ if (member.guild.id !== mappings.guilds["Moulberry's Bush"]) return;
const guild = member.guild;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
diff --git a/src/listeners/bush/supportThread.ts b/src/listeners/bush/supportThread.ts
index 1dadecb..5145ff2 100644
--- a/src/listeners/bush/supportThread.ts
+++ b/src/listeners/bush/supportThread.ts
@@ -1,6 +1,6 @@
-import { BushListener, colors, type BushClientEvents } from '#lib';
+import { BushListener, colors, mappings, type BushClientEvents } from '#lib';
import { stripIndent } from '#tags';
-import assert from 'assert';
+import assert from 'assert/strict';
import { EmbedBuilder, MessageType, PermissionFlagsBits, TextChannel } from 'discord.js';
export default class SupportThreadListener extends BushListener {
@@ -19,8 +19,8 @@ export default class SupportThreadListener extends BushListener {
if (message.author.bot && (message.author.id !== '444871677176709141' || !message.content.includes('uploaded a log,')))
return;
- if (message.guild.id !== '516977525906341928') return; // mb
- if (message.channel.id !== '714332750156660756') return; // neu-support
+ if (message.guild.id !== mappings.guilds["Moulberry's Bush"]) return; // mb
+ if (message.channel.id !== mappings.channels['neu-support']) return;
if (
[await message.guild.getSetting('prefix'), `<@!${this.client.user!.id}>`, `<@${this.client.user!.id}>`].some((v) =>
diff --git a/src/listeners/bush/userUpdateAutoBan.ts b/src/listeners/bush/userUpdateAutoBan.ts
index 54051b2..adfb80c 100644
--- a/src/listeners/bush/userUpdateAutoBan.ts
+++ b/src/listeners/bush/userUpdateAutoBan.ts
@@ -19,7 +19,7 @@ export default class UserUpdateAutoBanListener extends BushListener {
if (!code) return;
if (eval(code)) {
const member = await this.client.guilds.cache
- .get(mappings.guilds.bush)
+ .get(mappings.guilds["Moulberry's Bush"])
?.members.fetch(newUser.id)
.catch(() => undefined);
if (!member || !(member instanceof GuildMember)) return;
diff --git a/src/listeners/member-custom/bushLevelUpdate.ts b/src/listeners/member-custom/bushLevelUpdate.ts
index a9c0820..0281288 100644
--- a/src/listeners/member-custom/bushLevelUpdate.ts
+++ b/src/listeners/member-custom/bushLevelUpdate.ts
@@ -1,5 +1,5 @@
import { BushListener, format, type BushClientEvents } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import { type TextChannel } from 'discord.js';
type Args = BushClientEvents['bushLevelUpdate'];
diff --git a/src/listeners/message/quoteCreate.ts b/src/listeners/message/quoteCreate.ts
index 0478bcf..166bbb7 100644
--- a/src/listeners/message/quoteCreate.ts
+++ b/src/listeners/message/quoteCreate.ts
@@ -1,4 +1,4 @@
-import { BushListener, type BushClientEvents } from '#lib';
+import { BushListener, mappings, type BushClientEvents } from '#lib';
export default class QuoteCreateListener extends BushListener {
public constructor() {
@@ -10,7 +10,7 @@ export default class QuoteCreateListener extends BushListener {
}
public async exec(...[message]: BushClientEvents['messageCreate']) {
- if (message.author.id !== '322862723090219008' || !this.client.config.isProduction) return;
+ if (message.author.id !== mappings.users['IRONM00N'] || !this.client.config.isProduction) return;
if (!message.inGuild()) return;
const messages = await this.client.utils.resolveMessagesFromLinks(message.content);
diff --git a/src/listeners/ws/INTERACTION_CREATE.ts b/src/listeners/ws/INTERACTION_CREATE.ts
index 20c2b3e..67fe56b 100644
--- a/src/listeners/ws/INTERACTION_CREATE.ts
+++ b/src/listeners/ws/INTERACTION_CREATE.ts
@@ -1,5 +1,5 @@
import { BushListener, capitalize, colors, emojis, Moderation, PunishmentTypePresent } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
import {
ActionRowBuilder,
ButtonBuilder,
diff --git a/src/tasks/cache/updateNeuItemCache.ts b/src/tasks/cache/updateNeuItemCache.ts
new file mode 100644
index 0000000..14c107b
--- /dev/null
+++ b/src/tasks/cache/updateNeuItemCache.ts
@@ -0,0 +1,12 @@
+import { BushTask, Time } from '#lib';
+
+export default class UpdateNeuItemCache extends BushTask {
+ public constructor() {
+ super('updateNeuItemCache', {
+ delay: 1 * Time.Hour,
+ runOnStart: true
+ });
+ }
+
+ public async exec() {}
+}
diff --git a/src/tasks/feature/memberCount.ts b/src/tasks/feature/memberCount.ts
index ea422fa..9c31c5b 100644
--- a/src/tasks/feature/memberCount.ts
+++ b/src/tasks/feature/memberCount.ts
@@ -1,5 +1,5 @@
import { BushTask, MemberCount, Time } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
export default class MemberCountTask extends BushTask {
public constructor() {
diff --git a/src/tasks/feature/removeExpiredPunishements.ts b/src/tasks/feature/removeExpiredPunishements.ts
index 0b20a27..c21454b 100644
--- a/src/tasks/feature/removeExpiredPunishements.ts
+++ b/src/tasks/feature/removeExpiredPunishements.ts
@@ -1,5 +1,5 @@
import { ActivePunishment, ActivePunishmentType, BushTask, Time } from '#lib';
-import assert from 'assert';
+import assert from 'assert/strict';
const { Op } = (await import('sequelize')).default;
export default class RemoveExpiredPunishmentsTask extends BushTask {