mirror of
https://github.com/pacnpal/markov-discord.git
synced 2025-12-20 11:01:04 -05:00
Update 0.3: Added attachments, TTS, and message deletion support.
This commit is contained in:
@@ -1,2 +1,10 @@
|
|||||||
# MarkBot for Discord
|
# MarkBot for Discord
|
||||||
This is a super rough prototype. A Markov chain bot using markov-strings. Just uploading here so it can run and generate training data.
|
This is a super rough prototype. A Markov chain bot using markov-strings. Just uploading here so it can run and generate training data.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
### 0.3.0
|
||||||
|
Added TTS support and random message attachments.
|
||||||
|
Deleted messages no longer persist in the database longer than 24 hours.
|
||||||
|
|
||||||
|
### 0.2.0
|
||||||
|
Updated training algorithm and data structure.
|
||||||
60
index.js
60
index.js
@@ -26,12 +26,14 @@ let fileObj = {
|
|||||||
|
|
||||||
let markovDB = []
|
let markovDB = []
|
||||||
let messageCache = []
|
let messageCache = []
|
||||||
|
let deletionCache = []
|
||||||
const markovOpts = {
|
const markovOpts = {
|
||||||
maxLength: 400,
|
maxLength: 400,
|
||||||
minWords: 3,
|
minWords: 3,
|
||||||
minScore: 10
|
minScore: 10
|
||||||
}
|
}
|
||||||
let markov = new Markov(markovDB, markovOpts);
|
let markov
|
||||||
|
// let markov = new Markov(markovDB, markovOpts);
|
||||||
|
|
||||||
function regenMarkov() {
|
function regenMarkov() {
|
||||||
console.log("Regenerating Markov corpus...")
|
console.log("Regenerating Markov corpus...")
|
||||||
@@ -41,11 +43,15 @@ function regenMarkov() {
|
|||||||
catch (err) { console.log(err) }
|
catch (err) { console.log(err) }
|
||||||
// console.log("MessageCache", messageCache)
|
// console.log("MessageCache", messageCache)
|
||||||
markovDB = fileObj.messages
|
markovDB = fileObj.messages
|
||||||
|
markovDB = uniqueBy(markovDB.concat(messageCache), 'id')
|
||||||
|
deletionCache.forEach(id => {
|
||||||
|
let removeIndex = markovDB.map(function (item) { return item.id; }).indexOf(id)
|
||||||
|
// console.log('Remove Index:', removeIndex)
|
||||||
|
markovDB.splice(removeIndex, 1)
|
||||||
|
})
|
||||||
|
deletionCache = []
|
||||||
if (markovDB.length == 0)
|
if (markovDB.length == 0)
|
||||||
markovDB.push({ string: 'hello', id: null })
|
markovDB.push({ string: 'hello', id: null })
|
||||||
//markovDB = uniqueArray(markovDB.concat(messageCache), 'id')
|
|
||||||
markovDB = uniqueBy(markovDB.concat(messageCache), 'id')
|
|
||||||
//markovDB = markovDB.concat(messageCache)
|
|
||||||
markov = new Markov(markovDB, markovOpts);
|
markov = new Markov(markovDB, markovOpts);
|
||||||
markov.buildCorpusSync()
|
markov.buildCorpusSync()
|
||||||
fileObj.messages = markovDB
|
fileObj.messages = markovDB
|
||||||
@@ -53,7 +59,7 @@ function regenMarkov() {
|
|||||||
// console.log(fileObj)
|
// console.log(fileObj)
|
||||||
fs.writeFileSync('markovDB.json', JSON.stringify(fileObj), 'utf-8')
|
fs.writeFileSync('markovDB.json', JSON.stringify(fileObj), 'utf-8')
|
||||||
fileObj = null;
|
fileObj = null;
|
||||||
markovDB = []
|
// markovDB = []
|
||||||
messageCache = []
|
messageCache = []
|
||||||
console.log("Done regenerating Markov corpus.")
|
console.log("Done regenerating Markov corpus.")
|
||||||
}
|
}
|
||||||
@@ -97,7 +103,7 @@ client.on('message', message => {
|
|||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
.setAuthor(client.user.username, client.user.avatarURL)
|
||||||
.setThumbnail(client.user.avatarURL)
|
.setThumbnail(client.user.avatarURL)
|
||||||
.setDescription('A Markov chain chatbot that speaks based on previous chat input.')
|
.setDescription('A Markov chain chatbot that speaks based on previous chat input.')
|
||||||
.addField('!mark', 'Generates a sentence to say based on the chat database')
|
.addField('!mark', 'Generates a sentence to say based on the chat database. Send your message as TTS to recieve it as TTS.')
|
||||||
.addField('!mark train', 'Fetches the maximum amount of previous messages in the current text channel, adds it to the database, and regenerates the corpus. Takes about 2 minutes.')
|
.addField('!mark train', 'Fetches the maximum amount of previous messages in the current text channel, adds it to the database, and regenerates the corpus. Takes about 2 minutes.')
|
||||||
.addField('!mark regen', 'Manually regenerates the corpus to add recent chat info. Run this before shutting down to avoid any data loss. This automatically runs at midnight.')
|
.addField('!mark regen', 'Manually regenerates the corpus to add recent chat info. Run this before shutting down to avoid any data loss. This automatically runs at midnight.')
|
||||||
.addField('!mark invite', 'Don\'t invite this bot to other servers. The database is shared between all servers and text channels.')
|
.addField('!mark invite', 'Don\'t invite this bot to other servers. The database is shared between all servers and text channels.')
|
||||||
@@ -108,13 +114,27 @@ client.on('message', message => {
|
|||||||
}
|
}
|
||||||
if (command === 'train') {
|
if (command === 'train') {
|
||||||
console.log("Training...")
|
console.log("Training...")
|
||||||
|
fileObj = {
|
||||||
|
messages: []
|
||||||
|
}
|
||||||
|
fs.writeFileSync('markovDB.json', JSON.stringify(fileObj), 'utf-8')
|
||||||
fetchMessageChunk(message, null, [])
|
fetchMessageChunk(message, null, [])
|
||||||
}
|
}
|
||||||
if (command === 'respond') {
|
if (command === 'respond') {
|
||||||
console.log("Responding...")
|
console.log("Responding...")
|
||||||
markov.generateSentence().then(result => {
|
markov.generateSentence().then(result => {
|
||||||
console.log(result)
|
console.log('Generated Result:', result)
|
||||||
message.channel.send(result.string)
|
let messageOpts = {
|
||||||
|
tts: message.tts
|
||||||
|
}
|
||||||
|
let randomMessage = markovDB[Math.floor(Math.random() * markovDB.length)]
|
||||||
|
console.log('Random Message:', randomMessage)
|
||||||
|
if (randomMessage.hasOwnProperty('attachment')) {
|
||||||
|
messageOpts.files = [{
|
||||||
|
attachment: randomMessage.attachment
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
message.channel.send(result.string, messageOpts)
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
if (err.message == 'Cannot build sentence with current corpus and options')
|
if (err.message == 'Cannot build sentence with current corpus and options')
|
||||||
@@ -129,7 +149,14 @@ client.on('message', message => {
|
|||||||
if (command === null) {
|
if (command === null) {
|
||||||
console.log("Listening...")
|
console.log("Listening...")
|
||||||
if (!message.author.bot) {
|
if (!message.author.bot) {
|
||||||
messageCache.push({ string: message.content, id: message.id })
|
let dbObj = {
|
||||||
|
string: message.content,
|
||||||
|
id: message.id
|
||||||
|
}
|
||||||
|
if (message.attachments.size > 0) {
|
||||||
|
dbObj.attachment = message.attachments.values().next().value.url
|
||||||
|
}
|
||||||
|
messageCache.push(dbObj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (command === inviteCmd) {
|
if (command === inviteCmd) {
|
||||||
@@ -146,6 +173,12 @@ client.on('message', message => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
client.on('messageDelete', message => {
|
||||||
|
// console.log('Adding message ' + message.id + ' to deletion cache.')
|
||||||
|
deletionCache.push(message.id)
|
||||||
|
console.log('deletionCache:', deletionCache)
|
||||||
|
})
|
||||||
|
|
||||||
function validateMessage(message) {
|
function validateMessage(message) {
|
||||||
let messageText = message.content.toLowerCase()
|
let messageText = message.content.toLowerCase()
|
||||||
let command = null;
|
let command = null;
|
||||||
@@ -170,7 +203,14 @@ function fetchMessageChunk(message, oldestMessageID, historyCache) {
|
|||||||
message.channel.fetchMessages({ before: oldestMessageID, limit: 100 })
|
message.channel.fetchMessages({ before: oldestMessageID, limit: 100 })
|
||||||
.then(messages => {
|
.then(messages => {
|
||||||
historyCache = historyCache.concat(messages.filter(elem => !elem.author.bot).map(elem => {
|
historyCache = historyCache.concat(messages.filter(elem => !elem.author.bot).map(elem => {
|
||||||
return { string: elem.content, id: elem.id }
|
let dbObj = {
|
||||||
|
string: elem.content,
|
||||||
|
id: elem.id
|
||||||
|
}
|
||||||
|
if (elem.attachments.size > 0) {
|
||||||
|
dbObj.attachment = elem.attachments.values().next().value.url
|
||||||
|
}
|
||||||
|
return dbObj
|
||||||
}));
|
}));
|
||||||
oldestMessageID = messages.last().id
|
oldestMessageID = messages.last().id
|
||||||
return historyCache.concat(fetchMessageChunk(message, oldestMessageID, historyCache))
|
return historyCache.concat(fetchMessageChunk(message, oldestMessageID, historyCache))
|
||||||
|
|||||||
80
package-lock.json
generated
80
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "markbot",
|
"name": "markbot",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -41,27 +41,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"discord.js": {
|
"discord.js": {
|
||||||
"version": "11.3.0",
|
"version": "11.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.3.2.tgz",
|
||||||
"integrity": "sha512-xM3ydvb4urHjCP3N+Mgpw53a7ZGtmPwllwVgwPqdF2SHNPvTDr4So/+55VVx76s5eO9IMrOWpczsEuIr0/MAgQ==",
|
"integrity": "sha512-Abw9CTMX3Jb47IeRffqx2VNSnXl/OsTdQzhvbw/JnqCyqc2imAocc7pX2HoRmgKd8CgSqsjBFBneusz/E16e6A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"long": "3.2.0",
|
"long": "4.0.0",
|
||||||
"prism-media": "0.0.1",
|
"prism-media": "0.0.2",
|
||||||
"snekfetch": "3.6.1",
|
"snekfetch": "3.6.4",
|
||||||
"tweetnacl": "1.0.0",
|
"tweetnacl": "1.0.0",
|
||||||
"ws": "4.0.0"
|
"ws": "4.1.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ws": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-QYslsH44bH8O7/W2815u5DpnCpXWpEK44FmaHffNwgJI4JMaSZONgPBTOfrxJ29mXKbXak+LsJ2uAkDTYq2ptQ==",
|
|
||||||
"requires": {
|
|
||||||
"async-limiter": "1.0.0",
|
|
||||||
"safe-buffer": "5.1.1",
|
|
||||||
"ultron": "1.1.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"erlpack": {
|
"erlpack": {
|
||||||
@@ -85,14 +73,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.4",
|
"version": "4.17.10",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||||
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
|
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||||
},
|
},
|
||||||
"long": {
|
"long": {
|
||||||
"version": "3.2.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s="
|
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||||
},
|
},
|
||||||
"long-timeout": {
|
"long-timeout": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
@@ -100,12 +88,12 @@
|
|||||||
"integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ="
|
"integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ="
|
||||||
},
|
},
|
||||||
"markov-strings": {
|
"markov-strings": {
|
||||||
"version": "1.3.5",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/markov-strings/-/markov-strings-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/markov-strings/-/markov-strings-1.5.0.tgz",
|
||||||
"integrity": "sha512-cGe7DSh1RrkgCxu33xeI6RAhC0KCExGvS7enHkMyieNs0MrSGm9Gu5AYmVCFcWPM/+0SN34t38OdT+/YKrjxjQ==",
|
"integrity": "sha512-fHrnpXvR2p3mkxZEGeQaipus+2Z+DnewLmxn1BosNRajwWza0dHX1NO3reYGsPB5BGtzDyR6lh3owFZyICs2mg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "3.1.0",
|
"debug": "3.1.0",
|
||||||
"lodash": "4.17.4"
|
"lodash": "4.17.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
@@ -147,19 +135,19 @@
|
|||||||
"integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0="
|
"integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0="
|
||||||
},
|
},
|
||||||
"prism-media": {
|
"prism-media": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.2.tgz",
|
||||||
"integrity": "sha1-o0JcnKvVDRxsAuVDlBoRiVZnvRA="
|
"integrity": "sha512-L6yc8P5NVG35ivzvfI7bcTYzqFV+K8gTfX9YaJbmIFfMXTs71RMnAupvTQPTCteGsiOy9QcNLkQyWjAafY/hCQ=="
|
||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
},
|
},
|
||||||
"snekfetch": {
|
"snekfetch": {
|
||||||
"version": "3.6.1",
|
"version": "3.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz",
|
||||||
"integrity": "sha512-aLEvf1YR440pINb0LEo/SL2Q2s/A26+YEqPlx09A0XpGH7qWp8iqIFFolVILHn2yudWXJne9QWyQu+lzDp+ksQ=="
|
"integrity": "sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw=="
|
||||||
},
|
},
|
||||||
"sorted-array-functions": {
|
"sorted-array-functions": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@@ -171,16 +159,20 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz",
|
||||||
"integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins="
|
"integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins="
|
||||||
},
|
},
|
||||||
"ultron": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
|
|
||||||
},
|
|
||||||
"unique-by": {
|
"unique-by": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unique-by/-/unique-by-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unique-by/-/unique-by-1.0.0.tgz",
|
||||||
"integrity": "sha1-UiDIa6e8Vy+3E610ZRRwy2RCEr0="
|
"integrity": "sha1-UiDIa6e8Vy+3E610ZRRwy2RCEr0="
|
||||||
},
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==",
|
||||||
|
"requires": {
|
||||||
|
"async-limiter": "1.0.0",
|
||||||
|
"safe-buffer": "5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"zlib-sync": {
|
"zlib-sync": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/zlib-sync/-/zlib-sync-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/zlib-sync/-/zlib-sync-0.1.4.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "markbot",
|
"name": "markbot",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"description": "A conversational Markov chain bot for Discord",
|
"description": "A conversational Markov chain bot for Discord",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
"author": "Charlie Laabs <charlielaabs@gmail.com>",
|
"author": "Charlie Laabs <charlielaabs@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"discord.js": "^11.3.0",
|
"discord.js": "^11.3.2",
|
||||||
"erlpack": "github:discordapp/erlpack",
|
"erlpack": "github:discordapp/erlpack",
|
||||||
"markov-strings": "^1.3.5",
|
"markov-strings": "^1.3.5",
|
||||||
"node-schedule": "^1.3.0",
|
"node-schedule": "^1.3.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user