diff options
| author | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-10-03 22:57:40 -0400 |
|---|---|---|
| committer | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-10-03 22:57:40 -0400 |
| commit | 612ed820a0600ec11ed642005377cd7f5a8a8b77 (patch) | |
| tree | 6bca4e7268fd0063ff53cf64fa44df62a23dba50 /src | |
| parent | ed98ff7e2679f362f2657e77a6cf8dd3ce9b3d43 (diff) | |
| download | tanzanite-612ed820a0600ec11ed642005377cd7f5a8a8b77.tar.gz tanzanite-612ed820a0600ec11ed642005377cd7f5a8a8b77.tar.bz2 tanzanite-612ed820a0600ec11ed642005377cd7f5a8a8b77.zip | |
wip
Diffstat (limited to 'src')
69 files changed, 779 insertions, 687 deletions
@@ -1,26 +1,38 @@ +import { performance } from 'node:perf_hooks'; +performance.mark('processStart'); + console.log('Tanzanite is Starting'); -import { init } from '../lib/utils/Logger.js'; +import { init } from '#lib/utils/Logger.js'; // creates proxies on console.log and console.warn // also starts a REPL session init(); import { config } from '#config'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; -import { Sentry } from '../lib/common/Sentry.js'; -import { TanzaniteClient } from '../lib/extensions/discord-akairo/TanzaniteClient.js'; +import { Sentry } from '#lib/common/Sentry.js'; +import { TanzaniteClient } from '#lib/extensions/discord-akairo/TanzaniteClient.js'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; const isDry = process.argv.includes('dry'); -if (!isDry && config.credentials.sentryDsn !== null) new Sentry(dirname(fileURLToPath(import.meta.url)) || process.cwd(), config); + +if (!isDry && config.credentials.sentryDsn !== null) { + new Sentry(dirname(fileURLToPath(import.meta.url)) || process.cwd(), config); +} + TanzaniteClient.extendStructures(); + const client = new TanzaniteClient(config); -// @ts-ignore: for debugging purposes +// @ts-ignore: I don't want to add this to the global typings, this is only for debugging purposes global.client = client; -if (!isDry) await client.dbPreInit(); +if (!isDry) { + await client.dbPreInit(); +} + await client.init(); + if (isDry) { process.exit(0); } else { diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts index adc41d8..4d38c54 100644 --- a/src/commands/config/config.ts +++ b/src/commands/config/config.ts @@ -13,8 +13,8 @@ import { type GuildSettingType, type SlashMessage } from '#lib'; +import { ExtSub, type ArgumentGeneratorReturn, type SlashOption } from '@notenoughupdates/discord-akairo'; import assert from 'assert/strict'; -import { type ArgumentGeneratorReturn, type SlashOption } from 'discord-akairo'; import { ActionRowBuilder, ApplicationCommandOptionType, @@ -32,10 +32,9 @@ import { User, type Message, type MessageComponentInteraction, - type MessageOptions + type MessageCreateOptions } from 'discord.js'; -import _ from 'lodash'; -const { camelCase, snakeCase } = _; +import { camelCase, snakeCase } from 'lodash-es'; export const arrayActions = ['view' as const, 'add' as const, 'remove' as const, 'clear' as const]; export type ArrayActions = typeof arrayActions[number]; @@ -79,7 +78,7 @@ export default class ConfigCommand extends BotCommand { description: `Manage the server's ${loweredName}`, type: ApplicationCommandOptionType.SubcommandGroup, options: isArray - ? [ + ? ([ { name: 'view', description: `View the server's ${loweredName}.`, @@ -118,8 +117,8 @@ export default class ConfigCommand extends BotCommand { description: `Remove all values from a server's ${loweredName}.`, type: ApplicationCommandOptionType.Subcommand } - ] - : [ + ] as ExtSub[]) + : ([ { name: 'view', description: `View the server's ${loweredName}.`, @@ -144,7 +143,7 @@ export default class ConfigCommand extends BotCommand { description: `Delete the server's ${loweredName}.`, type: ApplicationCommandOptionType.Subcommand } - ] + ] as ExtSub[]) }; }), channel: 'guild', @@ -309,7 +308,7 @@ export default class ConfigCommand extends BotCommand { public async generateMessageOptions( message: CommandMessage | SlashMessage, setting?: undefined | keyof typeof guildSettingsObj - ): Promise<MessageOptions & InteractionUpdateOptions> { + ): Promise<MessageCreateOptions & InteractionUpdateOptions> { assert(message.inGuild()); const settingsEmbed = new EmbedBuilder().setColor(colors.default); diff --git a/src/commands/config/disable.ts b/src/commands/config/disable.ts index 6dd94a6..776ecf0 100644 --- a/src/commands/config/disable.ts +++ b/src/commands/config/disable.ts @@ -10,9 +10,9 @@ import { } from '#lib'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, AutocompleteInteraction } from 'discord.js'; -import { default as Fuse } from 'fuse.js'; -assert(Fuse); +// todo: remove this bullshit once typescript gets its shit together +const Fuse = (await import('fuse.js')).default as unknown as typeof import('fuse.js').default; export default class DisableCommand extends BotCommand { private static blacklistedCommands = ['eval', 'disable']; diff --git a/src/commands/config/log.ts b/src/commands/config/log.ts index 0c74ce7..6d0f594 100644 --- a/src/commands/config/log.ts +++ b/src/commands/config/log.ts @@ -8,8 +8,8 @@ import { type GuildLogType, type SlashMessage } from '#lib'; +import { ArgumentGeneratorReturn } from '@notenoughupdates/discord-akairo'; import assert from 'assert/strict'; -import { ArgumentGeneratorReturn } from 'discord-akairo'; import { ApplicationCommandOptionType, ChannelType } from 'discord.js'; export default class LogCommand extends BotCommand { @@ -38,10 +38,10 @@ export default class LogCommand extends BotCommand { slashType: ApplicationCommandOptionType.Channel, channelTypes: [ ChannelType.GuildText, - ChannelType.GuildNews, - ChannelType.GuildNewsThread, - ChannelType.GuildPublicThread, - ChannelType.GuildPrivateThread + ChannelType.GuildAnnouncement, + ChannelType.AnnouncementThread, + ChannelType.PublicThread, + ChannelType.PrivateThread ], only: 'slash' } diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 83168e0..5fe21c0 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -283,7 +283,7 @@ export default class EvalCommand extends BotCommand { if (!err && proto) embed.addFields({ name: ':gear: Proto', value: proto }); if (!silent || message.util.isSlashMessage(message)) { - await message.util.reply({ content: null, embeds: [embed] }); + await message.util.reply({ content: '', embeds: [embed] }); } else { const success = await message.author.send({ embeds: [embed] }).catch(() => false); if (!deleteMsg) await message.react(success ? emojis.successFull : emojis.errorFull).catch(() => {}); diff --git a/src/commands/dev/superUser.ts b/src/commands/dev/superUser.ts index fc7fcbf..54332d6 100644 --- a/src/commands/dev/superUser.ts +++ b/src/commands/dev/superUser.ts @@ -1,5 +1,5 @@ import { BotCommand, emojis, format, type ArgType, type CommandMessage } from '#lib'; -import { type ArgumentGeneratorReturn, type ArgumentTypeCasterReturn } from 'discord-akairo'; +import { type ArgumentGeneratorReturn, type ArgumentTypeCasterReturn } from '@notenoughupdates/discord-akairo'; export default class SuperUserCommand extends BotCommand { public constructor() { diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts index e1f3b73..994b76f 100644 --- a/src/commands/dev/test.ts +++ b/src/commands/dev/test.ts @@ -1,13 +1,14 @@ -import { BotCommand, ButtonPaginator, colors, emojis, OptArgType, Shared, type CommandMessage } from '#lib'; +import { BotCommand, ButtonPaginator, chunk, colors, emojis, OptArgType, Shared, type CommandMessage } from '#lib'; import { ActionRowBuilder, + APIEmbed, ButtonBuilder, ButtonStyle, + Collection, EmbedBuilder, - GatewayDispatchEvents, + Message, Routes, - type ApplicationCommand, - type Collection + type ApplicationCommand } from 'discord.js'; import badLinksSecretArray from '../../../lib/badlinks-secret.js'; import badLinksArray from '../../../lib/badlinks.js'; @@ -52,15 +53,38 @@ export default class TestCommand extends BotCommand { return await message.util.reply(responses[Math.floor(Math.random() * responses.length)]); } + console.dir(args); + if (args.feature) { if (['button', 'buttons'].includes(args.feature?.toLowerCase())) { const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents( - new ButtonBuilder({ style: ButtonStyle.Primary, customId: 'primaryButton', label: 'Primary' }), - new ButtonBuilder({ style: ButtonStyle.Secondary, customId: 'secondaryButton', label: 'Secondary' }), - new ButtonBuilder({ style: ButtonStyle.Success, customId: 'successButton', label: 'Success' }), - new ButtonBuilder({ style: ButtonStyle.Danger, customId: 'dangerButton', label: 'Danger' }), - new ButtonBuilder({ style: ButtonStyle.Link, label: 'Link', url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' }) + new ButtonBuilder({ + style: ButtonStyle.Primary, + customId: 'test;button;primary', + label: 'Primary' + }), + new ButtonBuilder({ + style: ButtonStyle.Secondary, + customId: 'test;button;secondary', + label: 'Secondary' + }), + new ButtonBuilder({ + style: ButtonStyle.Success, + customId: 'test;button;success', + label: 'Success' + }), + new ButtonBuilder({ + style: ButtonStyle.Danger, + customId: 'test;button;danger', + label: 'Danger' + }), + new ButtonBuilder({ + style: ButtonStyle.Link, + label: 'Link', + url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + }) ); + return await message.util.reply({ content: 'buttons', components: [buttonRow] }); } else if (['embed', 'button embed'].includes(args.feature?.toLowerCase())) { const embed = new EmbedBuilder() @@ -80,18 +104,23 @@ export default class TestCommand extends BotCommand { const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents( new ButtonBuilder({ style: ButtonStyle.Link, label: 'Link', url: 'https://google.com/' }) ); + return await message.util.reply({ content: 'Test', embeds: [embed], components: [buttonRow] }); } else if (['lots of buttons'].includes(args.feature?.toLowerCase())) { const buttonRows: ActionRowBuilder<ButtonBuilder>[] = []; + for (let a = 1; a <= 5; a++) { const row = new ActionRowBuilder<ButtonBuilder>(); + for (let b = 1; b <= 5; b++) { - const id = (a + 5 * (b - 1)).toString(); + const id = `test;lots;${a + 5 * (b - 1)}`; const button = new ButtonBuilder({ style: ButtonStyle.Primary, customId: id, label: id }); row.addComponents(button); } + buttonRows.push(row); } + return await message.util.reply({ content: 'buttons', components: buttonRows }); } else if (['paginate'].includes(args.feature?.toLowerCase())) { const embeds = []; @@ -142,13 +171,16 @@ export default class TestCommand extends BotCommand { return message.util.reply(`${emojis.error} no`); } else if (['sync automod'].includes(args.feature?.toLowerCase())) { const row = (await Shared.findByPk(0))!; + row.badLinks = badLinksArray; row.badLinksSecret = badLinksSecretArray; row.badWords = badWords; + await row.save(); + return await message.util.reply(`${emojis.success} Synced automod.`); } else if (['modal'].includes(args.feature?.toLowerCase())) { - const m = await message.util.reply({ + return await message.util.reply({ content: 'Click for modal', components: [ new ActionRowBuilder<ButtonBuilder>().addComponents( @@ -156,63 +188,57 @@ export default class TestCommand extends BotCommand { ) ] }); + } else if (args.feature.includes('backlog experiments')) { + this.client.logger.debug('backlog experiments'); + + if (message.channelId !== '1019830755658055691') { + return await message.util.reply(`${emojis.error} This only works in <#1019830755658055691>.`); + } - // eslint-disable-next-line @typescript-eslint/no-misused-promises - this.client.ws.on(GatewayDispatchEvents.InteractionCreate, async (i: any) => { - if (i?.data?.custom_id !== 'test;modal' || i?.data?.component_type !== 2) return; - if (i?.message?.id !== m.id) return; - - const text = { type: 4, style: 1, min_length: 1, max_length: 4000, required: true }; - - await this.client.rest.post(Routes.interactionCallback(i.id, i.token), { - body: { - type: 9, - data: { - custom_id: 'test;login', - title: 'Login (real)', - components: [ - { - type: 1, - components: [ - { - ...text, - custom_id: 'test;login;email', - label: 'Email', - placeholder: 'Email' - } - ] - }, - { - type: 1, - components: [ - { - ...text, - custom_id: 'test;login;password', - label: 'Password', - placeholder: 'Password' - } - ] - }, - { - type: 1, - components: [ - { - ...text, - custom_id: 'test;login;2fa', - label: 'Enter Discord Auth Code', - min_length: 6, - max_length: 6, - placeholder: '6-digit authentication code' - } - ] - } - ] - } - } + let messages = new Collection<string, Message>(); + let lastID: string | undefined; + + // eslint-disable-next-line no-constant-condition + while (true) { + const fetchedMessages = await message.channel.messages.fetch({ + limit: 100, + ...(lastID && { before: lastID }) }); - }); - return; + if (fetchedMessages.size === 0) { + break; + } + + messages = messages.concat(fetchedMessages); + lastID = fetchedMessages.lastKey(); + + this.client.logger.debug(messages.size); + this.client.logger.debug(lastID); + } + + const embeds = messages + .sort((a, b) => a.createdTimestamp - b.createdTimestamp) + .filter((m) => m.embeds.length > 0 && (m.embeds[0].title?.includes('Guild Experiment') ?? false)) + .map( + (m): APIEmbed => ({ + ...m.embeds[0]!.toJSON(), + timestamp: new Date(m.createdTimestamp).toISOString() + }) + ); + + const chunked = chunk(embeds, 10); + + let i = 0; + for (const chunk of chunked) { + this.client.logger.debug(i); + this.client.logger.debug(chunk, 1); + await this.client.rest.post(Routes.channelMessages('795356494261911553'), { + body: { embeds: chunk } + }); + i++; + } + + return await message.util.reply(`${emojis.success} Done.`); } } return await message.util.reply(responses[Math.floor(Math.random() * responses.length)]); diff --git a/src/commands/fun/minesweeper.ts b/src/commands/fun/minesweeper.ts index 85945c7..b0528ac 100644 --- a/src/commands/fun/minesweeper.ts +++ b/src/commands/fun/minesweeper.ts @@ -1,8 +1,6 @@ import { BotCommand, emojis, OptArgType, type ArgType, type CommandMessage, type SlashMessage } from '#lib'; -import { Minesweeper } from '@notenoughupdates/discord.js-minesweeper'; -import assert from 'assert/strict'; +import { Minesweeper } from '@tanzanite/discord.js-minesweeper'; import { ApplicationCommandOptionType } from 'discord.js'; -assert(Minesweeper); export default class MinesweeperCommand extends BotCommand { public constructor() { diff --git a/src/commands/info/guildInfo.ts b/src/commands/info/guildInfo.ts index e364a89..acd5b86 100644 --- a/src/commands/info/guildInfo.ts +++ b/src/commands/info/guildInfo.ts @@ -11,6 +11,7 @@ import { type OptArgType, type SlashMessage } from '#lib'; +import { embedField } from '#lib/common/tags.js'; import assert from 'assert/strict'; import { ApplicationCommandOptionType, @@ -26,7 +27,6 @@ import { PermissionFlagsBits, type BaseGuildVoiceChannel, type GuildPreview, - type Snowflake, type Vanity } from 'discord.js'; @@ -66,9 +66,13 @@ export default class GuildInfoCommand extends BotCommand { let guild: ArgType<'guild' | 'snowflake'> | GuildPreview = args.guild ?? message.guild!; if (typeof guild === 'string') { - const preview = await this.client.fetchGuildPreview(`${args.guild}` as Snowflake).catch(() => undefined); - if (preview) guild = preview; - else return await message.util.reply(`${emojis.error} That guild is not discoverable or does not exist.`); + const preview = await this.client.fetchGuildPreview(`${args.guild}`).catch(() => {}); + + if (preview) { + guild = preview; + } else { + return await message.util.reply(`${emojis.error} That guild is not discoverable or does not exist.`); + } } assert(guild); |
