diff --git a/.env.example b/.env.example index 7edd7d8..a0a28fe 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,11 @@ DISCORD_TOKEN= # Configuration DEFAULT_PREFIX= + +# the id of the owner +OWNER_ID= + +# database shit +POSTGRES_USER= +POSTGRES_PASSWORD= +POSTGRES_DB= \ No newline at end of file diff --git a/src/commands/eval.ts b/src/commands/eval.ts new file mode 100644 index 0000000..d1f2a07 --- /dev/null +++ b/src/commands/eval.ts @@ -0,0 +1,30 @@ +import { ApplyOptions } from '@sapphire/decorators'; +import { Command } from '@sapphire/framework'; +import type { Message } from 'discord.js'; + +@ApplyOptions({ + description: 'runs some code', + preconditions: ['OwnerOnly'], + aliases: ['ev'] +}) +export class UserCommand extends Command { + public async messageRun(message: Message) { + let splitCode = message.content.split(' '); + splitCode.shift(); + const code = splitCode.join(' '); + + let output; + try { + output = await eval(code); + } catch (err) { + output = err; + } + + output = `${output}`.replaceAll(process.env.DISCORD_TOKEN as string, '') + output = `${output}`.replaceAll(process.env.POSTGRES_USER as string, '') + output = `${output}`.replaceAll(process.env.POSTGRES_PASSWORD as string, '') + output = `${output}`.replaceAll(process.env.POSTGRES_DB as string, '') + + await message.channel.send(`${output}`); + } +} diff --git a/src/commands/test-slash.ts b/src/commands/test-slash.ts index 2b68071..f57bb2b 100644 --- a/src/commands/test-slash.ts +++ b/src/commands/test-slash.ts @@ -1,6 +1,7 @@ import { ApplyOptions } from '@sapphire/decorators'; import { Command } from '@sapphire/framework'; import { ComponentType } from 'discord.js'; +import { RolesMessage } from '../lib/types'; @ApplyOptions({ description: 'A basic slash command' @@ -34,5 +35,7 @@ export class UserCommand extends Command { } ]}] }); + + console.log(await RolesMessage.findAll()) } } diff --git a/src/commands/test.ts b/src/commands/test.ts index df7bbca..b592887 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -1,30 +1,13 @@ import { ApplyOptions } from '@sapphire/decorators'; import { Command } from '@sapphire/framework'; -import { ButtonStyle, ComponentType, Message } from 'discord.js'; +import type { Message } from 'discord.js'; +import { RolesMessage } from '../lib/types'; @ApplyOptions({ description: 'A basic command' }) export class UserCommand extends Command { public async messageRun(message: Message) { - await message.channel.send({ - content: 'This button lets you select pronoun roles. You can select multiple.', - allowedMentions: { parse: [] }, - components: [ - { - type: ComponentType.ActionRow, - components: [ - { - type: ComponentType.Button, - style: ButtonStyle.Primary, - label: 'Click me!', - customId: 'showRolesButton' - } - ] - } - ] - }); - // await message.guild?.commands.fetch() // console.log('message.guild.commands.cache, after fetching:', message.guild?.commands.cache) @@ -34,6 +17,8 @@ export class UserCommand extends Command { // await this.container.client.application?.commands.delete('1073818778254717019').then(console.log).catch(console.error) - console.log(this.container.db) + console.log(await RolesMessage.findAll()) + await message.reply('yeah yeah fuck you djs'); + console.log(await RolesMessage.create({guildId: message.guild?.id, roles: ['1074464133371674624']})) } } diff --git a/src/lib/types.ts b/src/lib/types.ts index 1b46c19..7d40159 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,39 +1,39 @@ -import { container, LogLevel, SapphireClient } from "@sapphire/framework"; -import { GatewayIntentBits, Partials } from "discord.js"; -import { Sequelize } from "sequelize"; +import { container, LogLevel, SapphireClient } from '@sapphire/framework'; +import { GatewayIntentBits, Partials } from 'discord.js'; +import { Model, Sequelize } from 'sequelize'; export class SaplingClient extends SapphireClient { - public constructor() { - super({ - defaultPrefix: process.env.DEFAULT_PREFIX, - regexPrefix: /^(hey +)?bot[,! ]/i, - caseInsensitiveCommands: true, - logger: { - level: LogLevel.Info - }, - shards: 'auto', - intents: [ - GatewayIntentBits.DirectMessageReactions, - GatewayIntentBits.DirectMessages, - GatewayIntentBits.GuildModeration, - GatewayIntentBits.GuildEmojisAndStickers, - GatewayIntentBits.GuildMessageReactions, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildVoiceStates, - - GatewayIntentBits.MessageContent - ], - partials: [Partials.Channel], - loadMessageCommandListeners: true - }) - } + public constructor() { + super({ + defaultPrefix: process.env.DEFAULT_PREFIX, + regexPrefix: /^(hey +)?bot[,! ]/i, + caseInsensitiveCommands: true, + logger: { + level: LogLevel.Info + }, + shards: 'auto', + intents: [ + GatewayIntentBits.DirectMessageReactions, + GatewayIntentBits.DirectMessages, + GatewayIntentBits.GuildModeration, + GatewayIntentBits.GuildEmojisAndStickers, + GatewayIntentBits.GuildMessageReactions, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildVoiceStates, - public override async login(token?: string) { - const sequelize = new Sequelize(process.env.POSTGRES_DB as string, process.env.POSTGRES_USER as string, process.env.POSTGRES_PASSWORD, { + GatewayIntentBits.MessageContent + ], + partials: [Partials.Channel], + loadMessageCommandListeners: true + }); + } + + public override async login(token?: string) { + const sequelize = new Sequelize(process.env.POSTGRES_DB as string, process.env.POSTGRES_USER as string, process.env.POSTGRES_PASSWORD, { host: 'bot-db', dialect: 'postgres', - logging: container.logger.debug + logging: false }); try { @@ -43,19 +43,21 @@ export class SaplingClient extends SapphireClient { container.logger.fatal('Unable to connect to the database:', error); } - container.db = sequelize; + container.db = sequelize; - return super.login(token) - } + return super.login(token); + } - public override async destroy() { - await container.db.close(); - return super.destroy(); - } + public override async destroy() { + await container.db.close(); + return super.destroy(); + } } declare module '@sapphire/pieces' { interface Container { - db: Sequelize; + db: Sequelize; } - } \ No newline at end of file +} + +export class RolesMessage extends Model {} diff --git a/src/listeners/commands/messageCommandDenied.ts b/src/listeners/commands/messageCommandDenied.ts new file mode 100644 index 0000000..2345b0c --- /dev/null +++ b/src/listeners/commands/messageCommandDenied.ts @@ -0,0 +1,9 @@ +import { ApplyOptions } from '@sapphire/decorators'; +import { Listener, ListenerOptions, MessageCommandDeniedPayload, UserError } from '@sapphire/framework'; + +@ApplyOptions({}) +export class MessageCommandDenied extends Listener { + public async run(error: UserError, payload: MessageCommandDeniedPayload) { + await payload.message.reply(error.message) + } +} diff --git a/src/listeners/ready.ts b/src/listeners/ready.ts index eea1b45..bd6a279 100644 --- a/src/listeners/ready.ts +++ b/src/listeners/ready.ts @@ -1,6 +1,8 @@ import { ApplyOptions } from '@sapphire/decorators'; import { Listener, Store } from '@sapphire/framework'; import { blue, gray, green, magenta, magentaBright, white, yellow } from 'colorette'; +import { DataTypes } from 'sequelize'; +import { RolesMessage } from '../lib/types'; const dev = process.env.NODE_ENV !== 'production'; @@ -8,10 +10,11 @@ const dev = process.env.NODE_ENV !== 'production'; export class UserEvent extends Listener { private readonly style = dev ? yellow : blue; - public run() { + public async run() { this.printBanner(); this.printStoreDebugInformation(); this.printMiscInformation(); + await this.initDatabase(); } private printBanner() { @@ -50,6 +53,43 @@ ${line03}${dev ? ` ${pad}${blc('<')}${llc('/')}${blc('>')} ${llc('DEVELOPMENT MO } private printMiscInformation() { - console.log("Ready!") + console.log('Ready!'); + } + + private async initDatabase() { + RolesMessage.init({ + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, + guildId: { + type: DataTypes.STRING, + allowNull: false + }, + embedTitle: { + type: DataTypes.STRING + }, + embedDescription: { + type: DataTypes.STRING + }, + embedColor: { + type: DataTypes.STRING + }, + roles: { + type: DataTypes.ARRAY(DataTypes.STRING), + allowNull: false + }, + style: { + type: DataTypes.STRING, + defaultValue: 'buttons' + } + }, { + sequelize: this.container.db, + modelName: 'RolesMessage' + }); + + + await RolesMessage.sync({ alter: true }); } } diff --git a/src/preconditions/OwnerOnly.ts b/src/preconditions/OwnerOnly.ts new file mode 100644 index 0000000..d95d6a4 --- /dev/null +++ b/src/preconditions/OwnerOnly.ts @@ -0,0 +1,26 @@ +import { Precondition } from '@sapphire/framework'; +import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Message } from 'discord.js'; + +export class OwnerOnlyPrecondition extends Precondition { + public override messageRun(message: Message) { + return this.checkOwner(message.author.id); } + + public override chatInputRun(interaction: ChatInputCommandInteraction) { + return this.checkOwner(interaction.user.id); + } + + public override contextMenuRun(interaction: ContextMenuCommandInteraction) { + return this.checkOwner(interaction.user.id); } + + private async checkOwner(userId: string) { + return process.env.OWNER_ID == userId + ? this.ok() + : this.error({ message: 'Only the bot owner can use this command!' }); + } +} + +declare module '@sapphire/framework' { + interface Preconditions { + OwnerOnly: never; + } +}