feat: Command handler.

This commit is contained in:
Siwoo Jeon 2023-01-30 17:54:08 +09:00
parent 70cb8b84ee
commit 38ad751644
Signed by: migan
GPG key ID: C4151385FFD2082A
10 changed files with 148 additions and 66 deletions

View file

@ -12,13 +12,13 @@ export default class ChatBot {
set trainType(value: TrainType) {
this._trainType = value
}
private db = new Database(join(__dirname, '..', 'db', 'db.sqlite3'))
public db = new Database(join(__dirname, '..', 'db', 'db.sqlite3'))
private _trainType: TrainType = 'All'
public constructor() {}
public getResponse(msg: Message, sendMsg?: boolean): ChatBot {
this.db
.get()
.all()
.then(rows => {
const a = msg.content.replace('머핀아', '')
let r = rows[Math.floor(Math.random() * rows.length)].text

View file

@ -1,29 +1,17 @@
import { ActivityType, Client, GatewayIntentBits, Message } from 'discord.js'
import { ActivityType, Client, Collection, GatewayIntentBits } from 'discord.js'
import ChatBot from './ChatBot'
import Dokdo from 'dokdo'
import { readdirSync } from 'node:fs'
import { join } from 'node:path'
import Command from './Command'
import noPerm from './noPerm'
import 'dotenv/config'
function noPerm(msg: Message) {
msg.reply({
content: '당신은 내 남자친구가 아니야!',
allowedMentions: {
repliedUser: false,
parse: [],
users: [],
roles: [],
},
})
}
function isNotOwner(msg: Message): boolean {
if (msg.author.id !== '415135882006495242') {
noPerm(msg)
return false
} else return true
}
const prefix = '멒힌아 '
export default class MuffinAI extends Client {
private chatBot = new ChatBot()
public chatBot = new ChatBot()
private modules: Collection<string, Command> = new Collection()
public constructor() {
super({
intents: [
@ -36,47 +24,40 @@ export default class MuffinAI extends Client {
public override login(): Promise<string> {
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)
})
this.once('ready', client => {
client.user!.setActivity({
type: ActivityType.Playing,
name: 'ㅅ살려주세요..!',
})
console.log(`먹힐 준비 완료`)
}).on('messageCreate', msg => {
}).on('messageCreate', async msg => {
if (msg.author.bot) return
new Dokdo(this, {
prefix: '멒힌아 ',
await new Dokdo(this, {
prefix,
noPerm,
aliases: ['테스트'],
owners: ['415135882006495242'],
}).run(msg)
if (msg.content.startsWith('머핀아 ')) this.chatBot.getResponse(msg, true)
else if (msg.content.startsWith('멒힌아 봇꺼')) {
if (!isNotOwner(msg)) return
this.destroy()
} else if (msg.content.startsWith('멒힌아 모드변경')) {
if (!isNotOwner(msg)) return
switch (this.chatBot.trainType) {
case 'muffinOnly':
this.chatBot.trainType = 'All'
msg.channel.send('다음 모드로 변경: 전체 학습')
break
case 'All':
this.chatBot.trainType = 'muffinOnly'
msg.channel.send('다음 모드로 변경: 머핀만 학습')
break
else if (msg.content.startsWith(prefix)) {
const args: string[] = msg.content
.slice(prefix.length)
.trim()
.split('/ +/g')
const command = this.modules.get(args.join(' '))
if (!command) return
if (command.noPerm && msg.author.id !== '415135882006495242')
return await noPerm(msg)
command.execute(msg, args)
}
} else if (msg.content.startsWith('멒힌아 현재모드')) {
if (!isNotOwner(msg)) return
switch (this.chatBot.trainType) {
case 'muffinOnly':
msg.channel.send('현재 모드: 머핀만 학습')
break
case 'All':
msg.channel.send('현재 모드: 전체 학습')
break
}
} else return
})
return super.login()
}
@ -86,3 +67,9 @@ export default class MuffinAI extends Client {
super.destroy()
}
}
declare module 'discord.js' {
interface Client {
chatBot: ChatBot
}
}

6
src/Command.ts Normal file
View file

@ -0,0 +1,6 @@
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

@ -0,0 +1,20 @@
import Command from '../Command'
import { type Message } from 'discord.js'
export default class extends Command {
public constructor() {
super('모드변경', true)
}
public async execute(msg: Message, args: string[]) {
switch (msg.client.chatBot.trainType) {
case 'muffinOnly':
msg.client.chatBot.trainType = 'All'
msg.channel.send('다음 모드로 변경: 전체 학습')
break
case 'All':
msg.client.chatBot.trainType = 'muffinOnly'
msg.channel.send('다음 모드로 변경: 머핀만 학습')
break
}
}
}

13
src/Commands/봇꺼.ts Normal file
View file

@ -0,0 +1,13 @@
import Command from '../Command'
import { type Message } from 'discord.js'
export default class extends Command {
public constructor() {
super('봇꺼', true)
}
public execute(msg: Message, args: string[]) {
msg.channel.send('ㅇㅇ').finally(() => {
msg.client.destroy()
})
}
}

View file

@ -0,0 +1,21 @@
import Command from '../Command'
import { type Message } from 'discord.js'
export default class extends Command {
public constructor() {
super('학습데이터량')
}
public execute(msg: Message, args: string[]) {
msg.client.chatBot.db.all().then(rows => {
const user: any[] = []
const muffin: any[] = []
rows.forEach(row => {
if (row.persona === 'muffin') muffin.push(row)
else user.push(row)
})
msg.channel.send(
`머핀 데이터: ${muffin.length}\n유저 데이터: ${user.length}`
)
})
}
}

View file

@ -0,0 +1,18 @@
import { type Message } from 'discord.js'
import Command from '../Command'
export default class extends Command {
public constructor() {
super('현재모드')
}
public execute(msg: Message, args: string[]) {
switch (msg.client.chatBot.trainType) {
case 'muffinOnly':
msg.channel.send('현재 모드: 머핀만 학습')
break
case 'All':
msg.channel.send('현재 모드: 전체 학습')
break
}
}
}

View file

@ -12,15 +12,15 @@ interface ResponseData {
}
export default class Database {
private db: sqlite3.Database
private sqliteDB: sqlite3.Database
public constructor(dbPath: string) {
this.db = new sqlite3.Database(dbPath)
this.sqliteDB = new sqlite3.Database(dbPath)
}
public get(): Promise<ResponseData[]> {
public all(): Promise<ResponseData[]> {
return new Promise((resolve, reject) => {
this.db.serialize(() => {
this.db.all('SELECT * FROM statement;', (err, rows) => {
this.sqliteDB.serialize(() => {
this.sqliteDB.all('SELECT * FROM statement;', (err, rows) => {
if (err) reject(err)
resolve([...rows])
})
@ -33,10 +33,10 @@ export default class Database {
params: any[],
callBack: (err: Error | null) => void
) {
this.db.run(sql, params, callBack)
this.sqliteDB.run(sql, params, callBack)
}
public close() {
this.db.close()
this.sqliteDB.close()
}
}

13
src/noPerm.ts Normal file
View file

@ -0,0 +1,13 @@
import { type Message } from 'discord.js'
export default async function noPerm(msg: Message) {
await msg.reply({
content: '당신은 내 남자친구가 아니야!',
allowedMentions: {
repliedUser: false,
parse: [],
users: [],
roles: [],
},
})
}

View file

@ -15,28 +15,32 @@ describe('Test Database', () => {
test('Get rows', () => {
getData().then(async rows =>
expect(await new Database(DBPATH).get()).toEqual(rows)
expect(await new Database(DBPATH).all()).toEqual(rows)
)
})
test('Insert row', () => {
const db = new Database(DBPATH)
return db.get().then(async data1 => {
db.run('INSERT INTO statement(text) VALUES(?)', ['TEST'], err => {
return db.all().then(async data1 => {
db.run(
'INSERT INTO statement(id, text) VALUES(?, ?)',
[++data1[data1.length - 1].id, 'TEST'],
err => {
if (err) throw err
})
const data2 = await db.get()
}
)
const data2 = await db.all()
expect(data1[data1.length - 1]).not.toEqual(data2[data2.length - 1])
})
})
test('Delete row', () => {
const db = new Database(DBPATH)
return db.get().then(async data1 => {
return db.all().then(async data1 => {
db.run('DELETE FROM statement WHERE text=?;', ['TEST'], err => {
if (err) throw err
})
const data2 = await db.get()
const data2 = await db.all()
expect(data1[data1.length - 1]).not.toEqual(data2[data2.length - 1])
})
})