Update 0.6.0: Docker support

This commit is contained in:
Charlie Laabs
2019-05-25 15:05:37 -05:00
parent 6f3268dc07
commit 3459dd7413
8 changed files with 533 additions and 532 deletions

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
# Ignore everything
**/*
# Allow files and directories
!*.js
!*.json

18
Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
FROM keymetrics/pm2:latest-stretch
# Create app directory
WORKDIR /usr/src/markbot
# Install app dependencies
COPY package*.json ./
# If you are building your code for production
ENV NPM_CONFIG_LOGLEVEL warn
RUN npm ci --only=production
# Bundle app source
COPY . .
RUN mkdir config
RUN ls -al
CMD [ "pm2-runtime", "start", "ecosystem.config.js" ]

View File

@@ -77,33 +77,61 @@ sudo apt-get install build-essential -y
npm start
```
## Docker
### Setup with source
1. Install Docker for your OS.
1. Download this repository using git in a command prompt
```sh
git clone https://github.com/charlocharlie/markov-discord.git
```
or by just downloading and extracting the [project zip](https://github.com/charlocharlie/markov-discord/archive/master.zip) from GitHub.
1. Open a command prompt in the markov-discord folder and run this one-liner:
```sh
docker run --rm -e TOKEN=YOUR.BOT.TOKEN -v config:/usr/src/markbot/config -it $(docker build -q .)
# Be patient as the build output is suppressed
```
### Setup with Docker Hub image
1. Install Docker for your OS.
1. Open a command prompts and run this one-liner:
```sh
docker build https://github.com/charlocharlie/markov-discord.git
```
# Changelog
### 0.6.0
* Added Docker deploy functionality.
* Moved config and database to `./config` directory. Existing configs will be migrated.
* Config-less support via bot token located in an environment variable.
* Update dependencies.
* Change corpus regen time to 4 AM.
### 0.5.0
Fixed bug where `!mark help` didn't work.
Only admins can train.
The bot responds when mentioned.
The bot cannot mention @everyone.
Added version number to help.
Added `!mark tts` for a quieter TTS response.
Readme overhaul.
Simpler config loading.
* Fixed bug where `!mark help` didn't work.
* Only admins can train.
* The bot responds when mentioned.
* The bot cannot mention @everyone.
* Added version number to help.
* Added `!mark tts` for a quieter TTS response.
* Readme overhaul.
* Simpler config loading.
### 0.4.0
Huge refactor.
Added `!mark debug` which sends debug info alongside the message.
Converted the fetchMessages function to async/await (updating the requirement to Node.js 8).
Updated module versions.
Added faster unique-array-by-property function
Added linting and linted the project.
* Huge refactor.
* Added `!mark debug` which sends debug info alongside the message.
* Converted the fetchMessages function to async/await (updating the requirement to Node.js 8).
* Updated module versions.
* Added faster unique-array-by-property function
* Added linting and linted the project.
### 0.3.0
Added TTS support and random message attachments.
Deleted messages no longer persist in the database longer than 24 hours.
* 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.
* Updated training algorithm and data structure.
# Thanks
Thanks to [BotMaker-for-Discord](https://github.com/CorySanin/BotMaker-for-Discord) which I used as a reference when during development.

4
config/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

12
ecosystem.config.js Normal file
View File

@@ -0,0 +1,12 @@
module.exports = {
apps: [{
name: 'markbot',
script: './index.js',
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
},
}],
};

View File

@@ -3,7 +3,6 @@ const fs = require('fs');
const Markov = require('markov-strings');
const schedule = require('node-schedule');
const { version } = require('./package.json');
const cfg = require('./config');
const client = new Discord.Client();
// const ZEROWIDTH_SPACE = String.fromCharCode(parseInt('200B', 16));
@@ -56,9 +55,17 @@ function uniqueBy(arr, propertyName) {
function regenMarkov() {
console.log('Regenerating Markov corpus...');
try {
fileObj = JSON.parse(fs.readFileSync('markovDB.json', 'utf8'));
fileObj = JSON.parse(fs.readFileSync('config/markovDB.json', 'utf8'));
} catch (err) {
console.log(err);
console.log('No markovDB.json, starting with initial values');
fileObj = {
messages: [
{
id: '0',
string: '',
},
],
};
}
// console.log("MessageCache", messageCache)
markovDB = fileObj.messages;
@@ -69,15 +76,12 @@ function regenMarkov() {
markovDB.splice(removeIndex, 1);
});
deletionCache = [];
if (markovDB.length === 0) {
markovDB.push({ string: 'hello', id: null });
}
markov = new Markov(markovDB, markovOpts);
markov.buildCorpusSync();
fileObj.messages = markovDB;
// console.log("WRITING THE FOLLOWING DATA:")
// console.log(fileObj)
fs.writeFileSync('markovDB.json', JSON.stringify(fileObj), 'utf-8');
fs.writeFileSync('config/markovDB.json', JSON.stringify(fileObj), 'utf-8');
fileObj = null;
messageCache = [];
console.log('Done regenerating Markov corpus.');
@@ -87,10 +91,30 @@ function regenMarkov() {
* Loads the config settings from disk
*/
function loadConfig() {
PREFIX = cfg.prefix;
GAME = cfg.game;
// regenMarkov()
client.login(cfg.token);
// Move config if in legacy location
if (fs.existsSync('./config.json')) {
console.log('Copying config.json to new location in ./config');
fs.renameSync('./config.json', './config/config.json');
}
if (fs.existsSync('./markovDB.json')) {
console.log('Copying markovDB.json to new location in ./config');
fs.renameSync('./markovDB.json', './config/markovDB.json');
}
try {
// eslint-disable-next-line global-require
const cfg = require('./config/config.json');
PREFIX = cfg.prefix;
GAME = cfg.game;
client.login(cfg.token);
} catch (e) {
console.warn('Failed to use config.json. using default configuration with token environment variable');
PREFIX = '!mark';
GAME = '"!mark help" for help';
client.login(process.env.TOKEN);
}
}
/**
@@ -235,7 +259,7 @@ client.on('error', (err) => {
const errText = `ERROR: ${err.name} - ${err.message}`;
console.log(errText);
errors.push(errText);
fs.writeFile('error.json', JSON.stringify(errors), (fsErr) => {
fs.writeFile('./config/error.json', JSON.stringify(errors), (fsErr) => {
if (fsErr) {
console.log(`error writing to error file: ${fsErr.message}`);
}
@@ -270,7 +294,7 @@ client.on('message', (message) => {
fileObj = {
messages: [],
};
fs.writeFileSync('markovDB.json', JSON.stringify(fileObj), 'utf-8');
fs.writeFileSync('config/markovDB.json', JSON.stringify(fileObj), 'utf-8');
fetchMessages(message);
}
}
@@ -284,7 +308,6 @@ client.on('message', (message) => {
generateResponse(message, true);
}
if (command === 'regen') {
console.log('Regenerating...');
regenMarkov();
}
if (command === null) {
@@ -324,4 +347,4 @@ client.on('messageDelete', (message) => {
});
loadConfig();
schedule.scheduleJob('0 0 * * *', regenMarkov());
schedule.scheduleJob('0 4 * * *', regenMarkov());

888
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,41 @@
{
"name": "markbot",
"version": "0.5.0",
"version": "0.6.0",
"description": "A conversational Markov chain bot for Discord",
"main": "index.js",
"scripts": {
"start": "node index.js"
"start": "node index.js",
"docker-up": "docker run --rm -e TOKEN=Mjc4MzU0MTU0NTYzNTY3NjM2.XLtWYQ.1pF0BMNDM0PO4kwPSEPelabRTEw -it $(docker build -q .)"
},
"repository": "https://github.com/charlocharlie/markov-discord.git",
"keywords": [
"discord",
"markov",
"chain",
"bot"
"markov-chain",
"bot",
"discord-js",
"discord-bot",
"markov-chain-bot",
"docker"
],
"author": "Charlie Laabs <charlielaabs@gmail.com>",
"license": "MIT",
"dependencies": {
"bufferutil": "^4.0.0",
"bufferutil": "^4.0.1",
"discord.js": "^11.4.2",
"erlpack": "github:discordapp/erlpack",
"markov-strings": "^1.5.0",
"node-schedule": "^1.3.0",
"markov-strings": "^1.5.2",
"node-schedule": "^1.3.2",
"zlib-sync": "^0.1.4"
},
"engines": {
"node": ">=8.0.0"
},
"devDependencies": {
"eslint": "^5.4.0",
"eslint": "^5.16.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.14.0"
"eslint-plugin-import": "^2.17.2"
},
"eslintConfig": {
"parserOptions": {