From 4fc51e9b07c8c22697b2cee8f2a26a42564278ab Mon Sep 17 00:00:00 2001 From: Charlie Laabs Date: Sat, 11 Jan 2020 20:46:27 -0600 Subject: [PATCH] Update 0.7.1: Various config fixes, response quality fixes. --- .vscode/launch.json | 20 ++++++++ README.md | 116 ++++++++++++++++++++++++++++++++------------ index.ts | 67 +++++++++++++------------ package-lock.json | 4 +- package.json | 6 +-- 5 files changed, 142 insertions(+), 71 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c7255c1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "runtimeArgs": [ + "-r", + "ts-node/register" + ], + "args": [ + "${workspaceFolder}/index.ts" + ] + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 21bc824..f7dc519 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,48 @@ # MarkBot for Discord + A Markov chain bot using markov-strings. -# Setup -First, create a [Discord bot application](https://discordapp.com/developers/applications/). -## Windows -### Requirements -* [Node.js 8.0+ (Current)](https://nodejs.org/en/download/current/) +## Usage -### Setup -1. Install Node.js 8.0 or newer. +1. Train the bot in a lengthy text channel: + * User: `!mark train` + * Markbot: `@User, Finished training from past 76394 messages.` +1. Ask the bot to say something: + * User: `!mark` + * Markbot: `This Shopko has a Linux release` + +## Setup + +First, create a [Discord bot application](https://discordapp.com/developers/applications/). + +### Windows + +#### Requirements + +* [Node.js 12.0+ (Current)](https://nodejs.org/en/download/) + * Installing with build tools is recommended + +#### Setup + +1. Install Node.js 12.0 or newer. 1. Download this repository using git in a command prompt + ```cmd 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. + ```sh - # Install Windows build tools + # Install Windows build tools (if you didn't install build tools with Node) npm install --global --production windows-build-tools # NPM install non-development packages npm install --production ``` + 1. Create a file called `config.json` in the project directory with the contents: + ```json { "prefix":"!mark", @@ -29,28 +50,34 @@ First, create a [Discord bot application](https://discordapp.com/developers/appl "token":"k5NzE2NDg1MTIwMjc0ODQ0Nj.DSnXwg.ttNotARealToken5p3WfDoUxhiH" } ``` + Feel free to change the command prefix, game display. Add your bot token. 1. Run the bot: + ```sh npm start ``` +### Debian Linux -## Debian Linux -### Requirements -* Node.js 8.0+ +#### Requirements + +* Node.js 12.0+ * Python 2.7 (for erlpack) * C++ build tools (for erlpack) -### Download +#### Download + ```sh # Clone this repository git clone https://github.com/charlocharlie/markov-discord.git cd markov-discord ``` -### Configure +#### Configure + Create a file called `config.json` in the project directory with the contents: + ```json { "prefix":"!mark", @@ -58,9 +85,11 @@ Create a file called `config.json` in the project directory with the contents: "token":"k5NzE2NDg1MTIwMjc0ODQ0Nj.DSnXwg.ttNotARealToken5p3WfDoUxhiH" } ``` + Feel free to change the command prefix, game display. Add your bot token. -### Install and Run +#### Install and Run + ```sh # Install Node.js if you haven't already wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash @@ -77,43 +106,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 - ``` +### Docker + +#### Setup with Docker Hub image -### Setup with Docker Hub image 1. Install Docker for your OS. 1. Open a command prompts and run: + ```sh docker pull charlocharlie/markov-discord docker run --rm -d charlocharlie/markov-discord:latest ``` +#### 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 + ``` + +## Changelog + +### 0.7.1 + +* Readme updates +* Config loading fix +* Fix min score +* Add generator options to config +* Document Node 12 update -# Changelog ### 0.7.0 + * Convert project to Typescript * Optimize Docker build (smaller image) * Load corpus from filesystem to reduce memory load ### 0.6.2 + * Fix MarkovDB not loading on boot ### 0.6.1 + * Fix bot crashing on scheduled regen ### 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. @@ -121,6 +168,7 @@ npm start * 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. @@ -131,19 +179,23 @@ npm start * Simpler config loading. ### 0.4.0 -* Huge refactor. + +* 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. +* 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. ### 0.2.0 + * 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. \ No newline at end of file + +Thanks to [BotMaker-for-Discord](https://github.com/CorySanin/BotMaker-for-Discord) which I used as a reference when during development. diff --git a/index.ts b/index.ts index f67ac92..93b3cb7 100644 --- a/index.ts +++ b/index.ts @@ -4,7 +4,11 @@ import * as Discord from 'discord.js'; // https://discord.js.org/#/docs/main/stable/general/welcome import * as fs from 'fs'; -import Markov, { MarkovGenerateOptions, MarkovResult } from 'markov-strings'; +import Markov, { + MarkovGenerateOptions, + MarkovResult, + MarkovConstructorOptions, +} from 'markov-strings'; import * as schedule from 'node-schedule'; @@ -23,8 +27,11 @@ interface MessagesDB { } interface MarkbotConfig { - prefix: string; - game: string; + stateSize?: number; + minScore?: number; + maxTries?: number; + prefix?: string; + game?: string; token?: string; } @@ -37,8 +44,11 @@ const client = new Discord.Client(); const PAGE_SIZE = 100; // let guilds = []; // let connected = -1; -let GAME = 'GAME'; -let PREFIX = '! '; +let GAME = '!mark help'; +let PREFIX = '!mark'; +let STATE_SIZE = 2; // Value of 1 to 3, based on corpus quality +let MAX_TRIES = 1000; +let MIN_SCORE = 10; const inviteCmd = 'invite'; const errors: string[] = []; @@ -49,14 +59,8 @@ let fileObj: MessagesDB = { let markovDB: MessageRecord[] = []; let messageCache: MessageRecord[] = []; let deletionCache: string[] = []; -const markovOpts = { - stateSize: 2, - maxLength: 2000, - minWords: 3, - maxWords: 0, - minScore: 10, - minScorePerWord: 0, - maxTries: 10000, +let markovOpts: MarkovConstructorOptions = { + stateSize: STATE_SIZE, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -139,15 +143,21 @@ function loadConfig(): void { PREFIX = cfg.prefix || '!mark'; GAME = cfg.game || '!mark help'; token = cfg.token || process.env.TOKEN || token; + STATE_SIZE = cfg.stateSize || STATE_SIZE; + MIN_SCORE = cfg.minScore || MIN_SCORE; + MAX_TRIES = cfg.maxTries || MAX_TRIES; } catch (e) { - console.error('Failed to read config.json.'); - throw e; + console.warn('Failed to read config.json.'); + token = process.env.TOKEN || token; } try { client.login(token); } catch (e) { console.error('Failed to login with token:', token); } + markovOpts = { + stateSize: STATE_SIZE, + }; } /** @@ -245,27 +255,16 @@ async function fetchMessages(message: Discord.Message): Promise { * @param {Boolean} debug Sends debug info as a message if true. * @param {Boolean} tts If the message should be sent as TTS. Defaults to the TTS setting of the * invoking message. - * @param {Array} filterWords Array of words that the message generated will be filtered on. */ -function generateResponse( - message: Discord.Message, - debug = false, - tts = message.tts, - filterWords?: string[] -): void { +function generateResponse(message: Discord.Message, debug = false, tts = message.tts): void { console.log('Responding...'); - const options: MarkovGenerateOptions = {}; - if (filterWords) { - options.filter = (result): boolean => { - for (let i = 0; i < filterWords.length; i += 1) { - if (result.string.includes(filterWords[i])) { - return true; - } - } - return false; - }; - options.maxTries = 5000; - } + const options: MarkovGenerateOptions = { + filter: (result): boolean => { + return result.score >= MIN_SCORE; + }, + maxTries: MAX_TRIES, + }; + const fsMarkov = new Markov([''], markovOpts); const markovFile = JSON.parse(fs.readFileSync('config/markov.json', 'utf-8')) as Markov; fsMarkov.corpus = markovFile.corpus; diff --git a/package-lock.json b/package-lock.json index 9da785a..6316c94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "markbot", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2039,4 +2039,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 249eb67..f9de28f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "markbot", - "version": "0.7.0", + "version": "0.7.1", "description": "A conversational Markov chain bot for Discord", "main": "index.js", "scripts": { @@ -34,7 +34,7 @@ "zlib-sync": "^0.1.6" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" }, "devDependencies": { "@types/node": "^12.12.21", @@ -53,4 +53,4 @@ "eslintIgnore": [ "**/*.js" ] -} +} \ No newline at end of file