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) { set trainType(value: TrainType) {
this._trainType = value 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' private _trainType: TrainType = 'All'
public constructor() {} public constructor() {}
public getResponse(msg: Message, sendMsg?: boolean): ChatBot { public getResponse(msg: Message, sendMsg?: boolean): ChatBot {
this.db this.db
.get() .all()
.then(rows => { .then(rows => {
const a = msg.content.replace('머핀아', '') const a = msg.content.replace('머핀아', '')
let r = rows[Math.floor(Math.random() * rows.length)].text 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 ChatBot from './ChatBot'
import Dokdo from 'dokdo' 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' import 'dotenv/config'
function noPerm(msg: Message) { const prefix = '멒힌아 '
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
}
export default class MuffinAI extends Client { export default class MuffinAI extends Client {
private chatBot = new ChatBot() public chatBot = new ChatBot()
private modules: Collection<string, Command> = new Collection()
public constructor() { public constructor() {
super({ super({
intents: [ intents: [
@ -36,47 +24,40 @@ export default class MuffinAI extends Client {
public override login(): Promise<string> { public override login(): Promise<string> {
this.chatBot.train(this) 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 => { this.once('ready', client => {
client.user!.setActivity({ client.user!.setActivity({
type: ActivityType.Playing, type: ActivityType.Playing,
name: 'ㅅ살려주세요..!', name: 'ㅅ살려주세요..!',
}) })
console.log(`먹힐 준비 완료`) console.log(`먹힐 준비 완료`)
}).on('messageCreate', msg => { }).on('messageCreate', async msg => {
if (msg.author.bot) return if (msg.author.bot) return
new Dokdo(this, { await new Dokdo(this, {
prefix: '멒힌아 ', prefix,
noPerm, noPerm,
aliases: ['테스트'], aliases: ['테스트'],
owners: ['415135882006495242'], owners: ['415135882006495242'],
}).run(msg) }).run(msg)
if (msg.content.startsWith('머핀아 ')) this.chatBot.getResponse(msg, true) if (msg.content.startsWith('머핀아 ')) this.chatBot.getResponse(msg, true)
else if (msg.content.startsWith('멒힌아 봇꺼')) { else if (msg.content.startsWith(prefix)) {
if (!isNotOwner(msg)) return const args: string[] = msg.content
this.destroy() .slice(prefix.length)
} else if (msg.content.startsWith('멒힌아 모드변경')) { .trim()
if (!isNotOwner(msg)) return .split('/ +/g')
switch (this.chatBot.trainType) {
case 'muffinOnly': const command = this.modules.get(args.join(' '))
this.chatBot.trainType = 'All' if (!command) return
msg.channel.send('다음 모드로 변경: 전체 학습') if (command.noPerm && msg.author.id !== '415135882006495242')
break return await noPerm(msg)
case 'All': command.execute(msg, args)
this.chatBot.trainType = 'muffinOnly' }
msg.channel.send('다음 모드로 변경: 머핀만 학습')
break
}
} 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() return super.login()
} }
@ -86,3 +67,9 @@ export default class MuffinAI extends Client {
super.destroy() 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 { export default class Database {
private db: sqlite3.Database private sqliteDB: sqlite3.Database
public constructor(dbPath: string) { 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) => { return new Promise((resolve, reject) => {
this.db.serialize(() => { this.sqliteDB.serialize(() => {
this.db.all('SELECT * FROM statement;', (err, rows) => { this.sqliteDB.all('SELECT * FROM statement;', (err, rows) => {
if (err) reject(err) if (err) reject(err)
resolve([...rows]) resolve([...rows])
}) })
@ -33,10 +33,10 @@ export default class Database {
params: any[], params: any[],
callBack: (err: Error | null) => void callBack: (err: Error | null) => void
) { ) {
this.db.run(sql, params, callBack) this.sqliteDB.run(sql, params, callBack)
} }
public close() { 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', () => { test('Get rows', () => {
getData().then(async rows => getData().then(async rows =>
expect(await new Database(DBPATH).get()).toEqual(rows) expect(await new Database(DBPATH).all()).toEqual(rows)
) )
}) })
test('Insert row', () => { test('Insert row', () => {
const db = new Database(DBPATH) const db = new Database(DBPATH)
return db.get().then(async data1 => { return db.all().then(async data1 => {
db.run('INSERT INTO statement(text) VALUES(?)', ['TEST'], err => { db.run(
if (err) throw err 'INSERT INTO statement(id, text) VALUES(?, ?)',
}) [++data1[data1.length - 1].id, 'TEST'],
const data2 = await db.get() err => {
if (err) throw err
}
)
const data2 = await db.all()
expect(data1[data1.length - 1]).not.toEqual(data2[data2.length - 1]) expect(data1[data1.length - 1]).not.toEqual(data2[data2.length - 1])
}) })
}) })
test('Delete row', () => { test('Delete row', () => {
const db = new Database(DBPATH) 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 => { db.run('DELETE FROM statement WHERE text=?;', ['TEST'], err => {
if (err) throw 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]) expect(data1[data1.length - 1]).not.toEqual(data2[data2.length - 1])
}) })
}) })