feat: @sapphire/framework

This commit is contained in:
Siwoo Jeon 2024-06-22 12:30:54 +09:00
parent a3c15d470a
commit 9c897a266d
Signed by: migan
GPG key ID: C4151385FFD2082A
26 changed files with 5922 additions and 7470 deletions

10407
.pnp.cjs generated

File diff suppressed because one or more lines are too long

2560
.pnp.loader.mjs generated

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,9 +1,15 @@
{
"name": "muffinbot",
"version": "3.0.0-cake.d240619b",
"version": "3.0.0-cake.d240622a",
"main": "dist/index.js",
"private": true,
"dependencies": {
"@sapphire/decorators": "^6.1.0",
"@sapphire/discord.js-utilities": "^7.3.0",
"@sapphire/framework": "^5.2.1",
"@sapphire/pieces": "^4.2.2",
"@sapphire/utilities": "^3.16.2",
"discord-api-types": "^0.37.90",
"discord.js": "^14.15.2",
"dokdo": "^0.6.2",
"mysql2": "^3.9.9"
@ -19,7 +25,7 @@
},
"scripts": {
"build": "tsup",
"dev": "cross-env NODE_ENV=development ts-node src",
"dev": "yarn build && cross-env NODE_ENV=development node dist",
"start": "cross-env NODE_ENV=production node dist"
},
"packageManager": "yarn@4.2.2"

View file

@ -1,22 +1,23 @@
import { ActivityType, Client, Collection, GatewayIntentBits } from 'discord.js'
import { type Command, noPerm, ChatBot, NODE_ENV, MaaDatabase } from './modules'
import { readdirSync } from 'node:fs'
import { noPerm, ChatBot, NODE_ENV, MaaDatabase } from './modules'
import { SapphireClient, container } from '@sapphire/framework'
import { ActivityType, GatewayIntentBits, Snowflake } from 'discord.js'
import config from '../config.json'
import { join } from 'node:path'
import Dokdo from 'dokdo'
const prefix = '머핀아 '
container.prefix = '머핀아 '
container.database = new MaaDatabase()
container.chatBot = new ChatBot(container.database)
container.config = config
export default class MuffinBot extends Client {
public modules: Collection<string, Command> = new Collection()
public database = new MaaDatabase()
public chatBot = new ChatBot(this.database)
public prefix = prefix
export default class MuffinBot extends SapphireClient {
public database = container.database
public chatBot = container.chatBot
public prefix = container.prefix
public dokdo: Dokdo = new Dokdo(this, {
aliases: ['dokdo', 'dok'],
owners: [config.bot.owner_ID],
noPerm,
prefix,
prefix: container.prefix,
})
public constructor() {
@ -26,19 +27,14 @@ export default class MuffinBot extends Client {
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
loadMessageCommandListeners: true,
defaultPrefix: container.prefix,
})
}
public override login(): Promise<string> {
public override async login(): Promise<string> {
if (NODE_ENV === 'development') this.on('debug', console.info)
this.chatBot.train(this)
readdirSync(join(__dirname, 'Commands')).forEach(file => {
const a = require(join(__dirname, 'Commands', file))
const b: Command = new a.default()
this.modules.set(b.name, b)
if (NODE_ENV === 'development') console.log(`${b.name}가 로ㄷ드됨`)
})
await this.chatBot.train(this)
this.once('ready', client => {
function setStatus() {
@ -53,26 +49,15 @@ export default class MuffinBot extends Client {
console.log(`먹힐 준ㅂ비 완료`)
}).on('messageCreate', async msg => {
const args: string[] = msg.content
.slice(prefix.length)
.trim()
.split(/ +/g)
if (NODE_ENV === 'development') console.log(args)
if (msg.author.bot) return
if (msg.content.startsWith(prefix)) {
if (msg.content.startsWith(this.prefix)) {
const args = msg.content.slice(this.prefix.length).trim().split(/ +/g)
if (args[0].startsWith('dokdo') || args[0].startsWith('dok')) {
await this.dokdo.run(msg)
} else {
await msg.channel.sendTyping()
const command = this.modules.get(args.shift()!.toLowerCase())
if (command) {
if (command.noPerm && msg.author.id !== config.bot.owner_ID)
return await noPerm(msg)
await command.execute(msg, args)
} else {
if (!this.stores.get('commands').get(args[0])) {
await msg.channel.sendTyping()
const response = await this.chatBot.getResponse(msg)
await msg.reply(response)
}
@ -86,8 +71,31 @@ export default class MuffinBot extends Client {
declare module 'discord.js' {
interface Client {
chatBot: ChatBot
modules: Collection<string, Command>
dokdo: Dokdo
prefix: string
dokdo: Dokdo
}
}
declare module '@sapphire/pieces' {
interface Container {
database: MaaDatabase
chatBot: ChatBot
prefix: string
config: {
bot: {
owner_ID: Snowflake
token: string
}
train: {
user_ID: Snowflake
}
mysql: {
user: string
host: string
password: string
database: string
port: number
}
}
}
}

View file

@ -1,38 +1,41 @@
import { Message } from 'discord.js'
import { Command, type LearnData } from '../modules'
import { ApplyOptions } from '@sapphire/decorators'
import { Args, Command } from '@sapphire/framework'
import { type LearnData } from '../modules'
import { type Message } from 'discord.js'
@ApplyOptions<Command.Options>({
name: '삭제',
aliases: ['지워', '잊어'],
description: '배운 단어를 삭ㅈ제해요.'
})
export default class extends Command {
public constructor() {
super('삭제')
}
public async execute(msg: Message, args: string[]) {
if (!args[0]) {
return await msg.channel.send('사용법: \n```머핀아 삭제 (지울 단어)```')
}
public async messageRun(msg: Message, args: Args) {
// if (!args[0]) {
// return await msg.channel.send('사용법: \n```머핀아 삭제 (지울 단어)```')
// }
const command = args[0]
const db = msg.client.chatBot.db
const [data] = await db.execute<LearnData[]>(
'SELECT * FROM learn WHERE command = ? AND user_id = ?;',
[command, msg.author.id],
)
// const command = args[0]
// const db = msg.client.chatBot.db
// const [data] = await db.execute<LearnData[]>(
// 'SELECT * FROM learn WHERE command = ? AND user_id = ?;',
// [command, msg.author.id],
// )
console.log(data)
// console.log(data)
if (!data[0]) {
return await msg.channel.send('해당하는 걸 찾ㅈ을 수 없어요.')
}
// if (!data[0]) {
// return await msg.channel.send('해당하는 걸 찾ㅈ을 수 없어요.')
// }
console.log(data.length)
if (data.length > 1) {
console.log('a')
} else {
// await db.learn.delete(command)
// await msg.reply('어라 이제 그ㄱ게 기억이 안나요. 그게 뭐ㅇ였죠?')
console.log('b')
}
// console.log(data.length)
// if (data.length > 1) {
// console.log('a')
// } else {
// // await db.learn.delete(command)
// // await msg.reply('어라 이제 그ㄱ게 기억이 안나요. 그게 뭐ㅇ였죠?')
// console.log('b')
// }
await msg.reply('현재 이 기능은 재작성 중입니다.')
// if (!data[0]) {

View file

@ -1,16 +1,18 @@
import { Command } from '../modules'
import { codeBlock, type Message } from 'discord.js'
import { ApplyOptions } from '@sapphire/decorators'
import { Command } from '@sapphire/framework'
import { version } from '../../package.json'
@ApplyOptions<Command.Options>({
name: '도움말',
aliases: ['명령어', '도움', 'help'],
description: '기본적인 사용ㅂ법이에요.',
})
export default class extends Command {
public constructor() {
super('도움말')
}
public async execute(msg: Message, args: string[]) {
public async messageRun(msg: Message) {
const commandList: string[] = []
msg.client.modules.forEach(module => {
this.container.stores.get('commands').forEach(module => {
commandList.push(module.name)
})

View file

@ -1,72 +1,57 @@
import { Command } from '../modules'
import { Message } from 'discord.js'
import config from '../../config.json'
import { Args, Command } from '@sapphire/framework'
import { ApplyOptions } from '@sapphire/decorators'
import { type Message } from 'discord.js'
@ApplyOptions<Command.Options>({
name: '배워',
aliases: ['공부'],
description: '단어를 가르치는 명령ㅇ어에요.',
})
export default class extends Command {
public constructor() {
super('배워')
}
public async execute(msg: Message, args: string[]) {
if (!args[0] || !args[1]) {
public async messageRun(msg: Message, args: Args) {
const config = this.container.config
const command = (await args.pick('string').catch(() => null))?.replaceAll(
'_',
' ',
)
const result = (await args.pick('string').catch(() => null))?.replaceAll(
'_',
' ',
)
if (!command || !result) {
return await msg.reply(
'```\n멒힌아 배워 (등록할 단어) (대답)\n```\n `_`를 대답에 쓰면 공백으로 바뀌ㅇ어요.',
'```\n사용법: 머핀아 배워 (등록할 단어) (대답)\n예시:\n머핀아 배워 안녕 안녕!\n머핀아 배워 "야 죽을래?" "아니요 ㅠㅠㅠ"\n머핀아 배워 미간은_누구야? 이봇의_개발자요\n```',
)
}
const command = args[0].replaceAll('_', ' ')
const result = args[1].replaceAll('_', ' ')
const ignore = [
'학습데이터량',
'봇꺼',
'테스트',
'미간',
'Migan',
'migan',
'간미',
'삭제',
'삭제',
]
const commands: string[] = []
const aliases: string[] = []
this.container.stores.get('commands').forEach(module => {
commands.push(module.name)
module.aliases.forEach(alias => {
aliases.push(alias)
})
})
const ignore = [...commands, ...aliases, '미간', 'Migan', 'migan', '간미']
const disallowed = ['@everyone', '@here', `<@${config.bot.owner_ID}>`]
const db = msg.client.chatBot.db
const data = await db.learn.findOne(command)
// if (data[0]) {
// if (msg.author.id !== data[0].user_id) {
// return msg.channel.send(
// `해ㄷ당 단어는 이미 ${
// (await msg.client.users.fetch(data[0].user_id)).username
// }님에게서 배웠어요.`,
// )
// }
// }
const db = this.container.database
for (const ig of ignore) {
if (command.includes(ig)) {
return msg.channel.send('해ㄷ당 단어는 배울ㄹ 수 없어요.')
return msg.reply('해ㄷ당 단어는 배울ㄹ 수 없어요.')
}
}
for (const di of disallowed) {
if (result.includes(di)) {
return msg.channel.send(
'해당 단ㅇ어는 개발자님이 특별히 금지하였ㅇ어요.',
)
return msg.reply('해당 단ㅇ어는 개발자님이 특별히 금지하였ㅇ어요.')
}
}
if (data[0] && msg.author.id === data[0].user_id) {
await db.learn.update({
command,
result,
})
await msg.channel.send(`${command}을/를 다시 배ㅂ웠어요.`)
} else {
await db.learn.insert({
command,
result,
user_id: msg.author.id,
})
await msg.channel.send(`${command}을/를 배웠ㅇ어요.`)
}
await db.learn.insert({
command,
result,
user_id: msg.author.id,
})
await msg.reply(`${command}을/를 배웠ㅇ어요.`)
}
}

View file

@ -1,12 +1,16 @@
import { Command, type ResponseData } from '../modules'
import { ApplyOptions } from '@sapphire/decorators'
import { type ResponseData } from '../modules'
import { Command } from '@sapphire/framework'
import { type Message } from 'discord.js'
@ApplyOptions<Command.Options>({
name: '데이터학습량',
aliases: ['학습데이터량', '데이터량'],
description: '봇이 학습한 데ㅇ이터량을 보여줘요.',
})
export default class extends Command {
public constructor() {
super('학습데이터량')
}
public async execute(msg: Message<true>, args: string[]) {
const db = msg.client.chatBot.db
public async messageRun(msg: Message<true>) {
const db = this.container.database
const data = await db.statement.all()
const nsfwData = await db.nsfwContent.all()
const learnData = await db.learn.all()

View file

@ -1,13 +1,15 @@
import { ApplyOptions } from '@sapphire/decorators'
import { Message, codeBlock } from 'discord.js'
import { Command } from '../modules'
import { Command } from '@sapphire/framework'
@ApplyOptions<Command.Options>({
name: '리스트',
aliases: ['list', '목록'],
description: '당신이 가ㄹ르쳐준 단어를 나열해요.',
})
export default class extends Command {
public constructor() {
super('리스트')
}
public async execute(msg: Message<boolean>, args: string[]) {
const db = msg.client.chatBot.db
public async messageRun(msg: Message<boolean>) {
const db = this.container.database
const data = await db.learn.findOneAnotherKey('user_id', msg.author.id)
const list: string[] = []

View file

@ -1,7 +1,7 @@
import type { Client, Message, TextChannel } from 'discord.js'
import { MaaDatabase } from './database'
import type { MaaDatabase } from './database'
import config from '../../config.json'
import { NODE_ENV } from '.'
import { NODE_ENV } from './env'
export default class ChatBot {
public constructor(public db: MaaDatabase) {

View file

@ -1,6 +0,0 @@
import { Message } from 'discord.js'
export default abstract class Command {
protected constructor(public name: string, public noPerm: boolean = false) {}
public abstract execute(msg: Message, args: string[]): any
}

View file

@ -1,11 +1,9 @@
import ChatBot from './ChatBot'
import Command from './Command'
import { ResponseData, NSFWData, LearnData, MaaDatabase } from './database'
import noPerm from './noPerm'
import { NODE_ENV } from './env'
export {
ChatBot,
Command,
noPerm,
ResponseData,
NODE_ENV,

View file

@ -15,7 +15,7 @@
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
"experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */

119
yarn.lock
View file

@ -29,7 +29,7 @@ __metadata:
languageName: node
linkType: hard
"@discordjs/collection@npm:1.5.3":
"@discordjs/collection@npm:1.5.3, @discordjs/collection@npm:^1.5.3":
version: 1.5.3
resolution: "@discordjs/collection@npm:1.5.3"
checksum: 10/770d0576612555c848858ead2a6c6242252f51ae3a7a6fdcc4986ceeb330ed8cffb81bcd1819e1ef11cce946cb9e707791926e757985cc2e081e984012c08dad
@ -511,6 +511,94 @@ __metadata:
languageName: node
linkType: hard
"@sapphire/decorators@npm:^6.1.0":
version: 6.1.0
resolution: "@sapphire/decorators@npm:6.1.0"
dependencies:
tslib: "npm:^2.6.2"
checksum: 10/f7afb5f50bba588cc87863860eb3d862636e70665c189a9fb0e68731ecb4b86aaeb38bf6709e9593b4b1386ef02b55cc74a047c410300d40477120543fe9c841
languageName: node
linkType: hard
"@sapphire/discord-utilities@npm:^3.2.3, @sapphire/discord-utilities@npm:^3.3.0":
version: 3.3.0
resolution: "@sapphire/discord-utilities@npm:3.3.0"
dependencies:
discord-api-types: "npm:^0.37.84"
checksum: 10/52019cb9ce8724357f639a6f65dffa14d79ebfb7b7eabf3ee75c58d66abd83988124d08dbd25fe8b0d7b953d466b50695318ce458131532d5bde04ba0d8d4180
languageName: node
linkType: hard
"@sapphire/discord.js-utilities@npm:^7.2.0, @sapphire/discord.js-utilities@npm:^7.3.0":
version: 7.3.0
resolution: "@sapphire/discord.js-utilities@npm:7.3.0"
dependencies:
"@sapphire/discord-utilities": "npm:^3.3.0"
"@sapphire/duration": "npm:^1.1.2"
"@sapphire/utilities": "npm:^3.16.2"
tslib: "npm:^2.6.2"
checksum: 10/865436d7a8d689403bdd6c92dbd344bb2018eb029c5a2d3922bec7a0f1f00fb4cd97a28e7c6350daf9973caa0047a3bafb461e620381ef5fe5b1bc00e3a6be98
languageName: node
linkType: hard
"@sapphire/duration@npm:^1.1.2":
version: 1.1.2
resolution: "@sapphire/duration@npm:1.1.2"
checksum: 10/680634b17c2bb1594a408cd5de7bd270a716a3445d52a95cb3d34392858d219a8c73daa151658076b324cd87304d731638d2af8065ac76953907c7a5e4be3d18
languageName: node
linkType: hard
"@sapphire/framework@npm:^5.2.1":
version: 5.2.1
resolution: "@sapphire/framework@npm:5.2.1"
dependencies:
"@discordjs/builders": "npm:^1.8.1"
"@sapphire/discord-utilities": "npm:^3.2.3"
"@sapphire/discord.js-utilities": "npm:^7.2.0"
"@sapphire/lexure": "npm:^1.1.7"
"@sapphire/pieces": "npm:^4.2.2"
"@sapphire/ratelimits": "npm:^2.4.9"
"@sapphire/result": "npm:^2.6.6"
"@sapphire/stopwatch": "npm:^1.5.2"
"@sapphire/utilities": "npm:^3.15.3"
checksum: 10/51c98ac089581de1396c94626126ab0134499dcb5cef0747fb8c4cf920ef54cd0686b5e930d5eba1df41031fd459a80eab7563b291189304d28ea98768cf1833
languageName: node
linkType: hard
"@sapphire/lexure@npm:^1.1.7":
version: 1.1.7
resolution: "@sapphire/lexure@npm:1.1.7"
dependencies:
"@sapphire/result": "npm:^2.6.6"
checksum: 10/9a9642df355e063a013f65dc83458272207223744a3d19aaf68f8feea1cc15c1674a2e87f9db65608a3b65b13a191512e72893824ba12e3fd56937bb8f2b2a15
languageName: node
linkType: hard
"@sapphire/pieces@npm:^4.2.2":
version: 4.2.2
resolution: "@sapphire/pieces@npm:4.2.2"
dependencies:
"@discordjs/collection": "npm:^1.5.3"
"@sapphire/utilities": "npm:^3.15.3"
tslib: "npm:^2.6.2"
checksum: 10/4553358a677aef4bb7062e8be4cd021dd993a96b3c9fad7e91ab423feb733e4cd56f57400b06b3e13e724d90009eb9b1c79ea5b14c0ac062fea68f7dc2dbfd53
languageName: node
linkType: hard
"@sapphire/ratelimits@npm:^2.4.9":
version: 2.4.9
resolution: "@sapphire/ratelimits@npm:2.4.9"
checksum: 10/591c3ab89dd40aab22e9fd5c439dd785001b7ec1a504235c1c05654f7a59c73cc2ef0a61e0eb1ea90cf81f59f22d2fda1727290acf79ead4a7796982db25a8a0
languageName: node
linkType: hard
"@sapphire/result@npm:^2.6.6":
version: 2.6.6
resolution: "@sapphire/result@npm:2.6.6"
checksum: 10/1847a4c911b0dcaa2d037548e06b4a206bb1f31f9cdb6d84c2e054979a6ac4a0b8348402d118aa4a8b841f9518cb6e10575224f96cbf0b68410bcb8eae7ab014
languageName: node
linkType: hard
"@sapphire/shapeshift@npm:^3.9.7":
version: 3.9.7
resolution: "@sapphire/shapeshift@npm:3.9.7"
@ -528,6 +616,22 @@ __metadata:
languageName: node
linkType: hard
"@sapphire/stopwatch@npm:^1.5.2":
version: 1.5.2
resolution: "@sapphire/stopwatch@npm:1.5.2"
dependencies:
tslib: "npm:^2.6.2"
checksum: 10/2ef17d0a9067827407d72fdbcd974a3a6b8fb9e9ccc4ff2e138c8a563fcee7f8b3b251abd61392ec90410750fda4bcba4898089d7e93d84778810df48236c0b5
languageName: node
linkType: hard
"@sapphire/utilities@npm:^3.15.3, @sapphire/utilities@npm:^3.16.2":
version: 3.16.2
resolution: "@sapphire/utilities@npm:3.16.2"
checksum: 10/9801f26cc7c37f1c4d56231d2e3967e7ac072d037dbc11b577d1ecf09fe7c6e4141bd1d1a10490f3c51eeeaf81eac0373502d41366dc68627b490597ea6d1ebe
languageName: node
linkType: hard
"@tsconfig/node10@npm:^1.0.7":
version: 1.0.9
resolution: "@tsconfig/node10@npm:1.0.9"
@ -896,6 +1000,13 @@ __metadata:
languageName: node
linkType: hard
"discord-api-types@npm:^0.37.84, discord-api-types@npm:^0.37.90":
version: 0.37.90
resolution: "discord-api-types@npm:0.37.90"
checksum: 10/bfd85a2ca3bb2df65bd783eae4daf93754f34a744b487e549a38606262761aee0cb719bdef1917736512011561b0d574b8e399a458ad8e04ddcf549dde4911af
languageName: node
linkType: hard
"discord.js@npm:^14.15.2":
version: 14.15.2
resolution: "discord.js@npm:14.15.2"
@ -1645,8 +1756,14 @@ __metadata:
resolution: "muffinbot@workspace:."
dependencies:
"@migan/prettier-config": "npm:^1.0.0"
"@sapphire/decorators": "npm:^6.1.0"
"@sapphire/discord.js-utilities": "npm:^7.3.0"
"@sapphire/framework": "npm:^5.2.1"
"@sapphire/pieces": "npm:^4.2.2"
"@sapphire/utilities": "npm:^3.16.2"
"@types/node": "npm:^20.12.13"
cross-env: "npm:^7.0.3"
discord-api-types: "npm:^0.37.90"
discord.js: "npm:^14.15.2"
dokdo: "npm:^0.6.2"
mysql2: "npm:^3.9.9"