feat: setter and getter

This commit is contained in:
Siwoo Jeon 2023-01-28 18:10:38 +09:00
parent ba3f5ae0b2
commit c1fab17950
Signed by: migan
GPG key ID: C4151385FFD2082A
9 changed files with 1968 additions and 62 deletions

5
jest.config.js Normal file
View file

@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

View file

@ -3,7 +3,6 @@
"version": "1.0.0", "version": "1.0.0",
"main": "index.js", "main": "index.js",
"license": "MIT", "license": "MIT",
"type": "module",
"dependencies": { "dependencies": {
"discord.js": "^14.7.1", "discord.js": "^14.7.1",
"dokdo": "^0.6.2", "dokdo": "^0.6.2",
@ -12,16 +11,20 @@
}, },
"devDependencies": { "devDependencies": {
"@migan/prettier-config": "^1.0.0", "@migan/prettier-config": "^1.0.0",
"@types/jest": "^29.4.0",
"@types/node": "^18.11.18", "@types/node": "^18.11.18",
"jest": "^29.4.0",
"prettier": "^2.8.3", "prettier": "^2.8.3",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsup": "^6.5.0", "tsup": "^6.5.0",
"typescript": "^4.9.4" "typescript": "^4.9.4"
}, },
"scripts": { "scripts": {
"build": "tsup", "build": "tsup",
"dev": "ts-node-esm src", "dev": "ts-node src",
"start": "node dist" "start": "node dist",
"test": "jest"
}, },
"prettier": "@migan/prettier-config" "prettier": "@migan/prettier-config"
} }

View file

@ -1,22 +1,25 @@
import sqlite3 from 'sqlite3'
import type { Client, Message } from 'discord.js' import type { Client, Message } from 'discord.js'
import { dirname, join } from 'node:path' import { join } from 'node:path'
import { fileURLToPath } from 'node:url' import Database from './Database'
type TrainType = 'muffinOnly' | 'All' type TrainType = 'muffinOnly' | 'All'
export default class ChatBot { export default class ChatBot {
private db = new sqlite3.Database( get trainType(): TrainType {
join(dirname(fileURLToPath(import.meta.url)), '..', 'db', 'db.sqlite3') return this._trainType
) }
private trainType: TrainType = 'All'
set trainType(value: TrainType) {
this._trainType = value
}
private db = new Database(join(__dirname, '..', 'db', 'db.sqlite3'))
private _trainType: TrainType = 'All'
public constructor() {} public constructor() {}
public getResponse(msg: Message, sendMsg?: boolean): ChatBot { public getResponse(msg: Message, sendMsg?: boolean): ChatBot {
this.db.all( this.db
'SELECT text FROM statement;', .get()
(err, rows: Array<{ text: string }>) => { .then(rows => {
if (err) throw err
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
if (!r) r = '살ㄹ려주세요' if (!r) r = '살ㄹ려주세요'
@ -26,22 +29,20 @@ export default class ChatBot {
msg.channel.sendTyping() msg.channel.sendTyping()
setTimeout(() => msg.channel.send(r), 1000) setTimeout(() => msg.channel.send(r), 1000)
} }
} })
) .catch(console.error)
return this return this
} }
public train(client: Client): ChatBot { public train(client: Client): ChatBot {
const sql = `INSERT INTO statement(text, persona) VALUES(?, ?);`
client.on('messageCreate', msg => { client.on('messageCreate', msg => {
if (msg.author.bot) return if (msg.author.bot) return
if (msg.author.id === '1026185545837191238') { if (msg.author.id === '1026185545837191238') {
this.db.run( this.db.run(sql, [msg.content, 'muffin'], err => {
`INSERT INTO statement(text, persona) VALUES('${msg.content}', 'muffin');`,
err => {
if (err) throw err if (err) throw err
this.getResponse(msg) this.getResponse(msg)
} })
)
} else { } else {
if (this.trainType !== 'All') return if (this.trainType !== 'All') return
if (!msg.content.startsWith('머핀아 ')) return if (!msg.content.startsWith('머핀아 ')) return
@ -49,9 +50,8 @@ export default class ChatBot {
.replaceAll("'", '') .replaceAll("'", '')
.slice(0, 50) .slice(0, 50)
.toLowerCase()}` .toLowerCase()}`
const text = msg.content.replace('머핀아 ', '').replaceAll("'", '') const text = msg.content.replace('머핀아 ', '')
const sql = `INSERT INTO statement(text, persona) VALUES('${text}', '${user}');` this.db.run(sql, [text, user], err => {
this.db.run(sql, err => {
if (err) throw err if (err) throw err
}) })
} }
@ -59,18 +59,6 @@ export default class ChatBot {
return this return this
} }
public changeTrainType(): TrainType {
switch (this.trainType) {
case 'muffinOnly':
this.trainType = 'All'
break
case 'All':
this.trainType = 'muffinOnly'
break
}
return this.trainType
}
public destroy(): void { public destroy(): void {
this.db.close() this.db.close()
} }

View file

@ -1,5 +1,5 @@
import { ActivityType, Client, GatewayIntentBits, Message } from 'discord.js' import { ActivityType, Client, GatewayIntentBits, Message } from 'discord.js'
import ChatBot from './ChatBot.js' import ChatBot from './ChatBot'
import Dokdo from 'dokdo' import Dokdo from 'dokdo'
import 'dotenv/config' import 'dotenv/config'
@ -56,8 +56,19 @@ export default class MuffinAI extends Client {
this.destroy() this.destroy()
} else if (msg.content.startsWith('멒힌아 모드변경')) { } else if (msg.content.startsWith('멒힌아 모드변경')) {
if (!isNotOwner(msg)) return if (!isNotOwner(msg)) return
const a = this.chatBot.changeTrainType() switch (this.chatBot.trainType) {
switch (a) { 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('멒힌아 현재모드')) {
if (!isNotOwner(msg)) return
switch (this.chatBot.trainType) {
case 'muffinOnly': case 'muffinOnly':
msg.channel.send('현재 모드: 머핀만 학습') msg.channel.send('현재 모드: 머핀만 학습')
break break

42
src/Database.ts Normal file
View file

@ -0,0 +1,42 @@
import sqlite3 from 'sqlite3'
interface ResponseData {
id: number
text: string
search_text: string
conversation: string
created_at: string
in_response_to: string | null
search_in_response_to: string
persona: string
}
export default class Database {
private db: sqlite3.Database
public constructor(dbPath: string) {
this.db = new sqlite3.Database(dbPath)
}
public get(): Promise<ResponseData[]> {
return new Promise((resolve, reject) => {
this.db.serialize(() => {
this.db.all('SELECT * FROM statement;', (err, rows) => {
if (err) reject(err)
resolve([...rows])
})
})
})
}
public run(
sql: string,
params: any[],
callBack: (err: Error | null) => void
) {
this.db.run(sql, params, callBack)
}
public close() {
this.db.close()
}
}

View file

@ -1 +1 @@
import('./Client.js').then(a => new a.default().login()) import('./Client').then(a => new a.default().login())

43
tests/Database.test.ts Normal file
View file

@ -0,0 +1,43 @@
import Database from '../src/Database'
import sqlite3 from 'sqlite3'
describe('Test Database', () => {
const DBPATH = `${__dirname}/../db/db.sqlite3`
const db = new sqlite3.Database(DBPATH)
const getData = () => {
return new Promise((resolve, reject) => {
db.all('SELECT * FROM statement;', async (err, rows) => {
if (err) reject(err)
resolve(rows)
}).close()
})
}
test('Get rows', () => {
getData().then(async rows =>
expect(await new Database(DBPATH).get()).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 => {
if (err) throw err
})
const data2 = await db.get()
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 => {
db.run('DELETE FROM statement WHERE text=?;', ['TEST'], err => {
if (err) throw err
})
const data2 = await db.get()
expect(data1[data1.length - 1]).not.toEqual(data2[data2.length - 1])
})
})
})

View file

@ -26,10 +26,10 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */ /* Modules */
"module": "Node16", "module": "commonjs",
/* Specify what module code is generated. */ /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */ // "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "Node16" /* Specify how TypeScript looks up a file from a given module specifier. */, // "moduleResolution": "Node16" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */

1850
yarn.lock

File diff suppressed because it is too large Load diff