val-bot
Version:
A bot that does things.
319 lines (262 loc) • 8.04 kB
JavaScript
const Module = require('./Module.js');
const fs = require('fs');
const rollRegex = /^(\d+)?(?:[dD]([0-9][\d]+|[1-9]))(?:[+](\d+))?$/;
const DW_CHANNEL = 'CB391DZQT';
let characters = {};
class DND extends Module {
/**
* ## actAs
*
* performs an action to the dark heracy channel in the voice of your character
*
* @param {String} from originating channel
* @param {String} to originating user
* @param {String} text full message text
* @param {String} textArr full message text split by " "
* @param {String} command trigger word that brought us here
* @param {Object} confObj extra config object that some command modules need
*
* @return {String} success message
*/
actAs(from, to, text, textArr, command, confObj) {
this.loadCharacterList();
characters[DW_CHANNEL] = characters[DW_CHANNEL] || {};
const characterName = characters[DW_CHANNEL][to];
if (characterName) {
this._bot.say(DW_CHANNEL, `_${characterName} ${text}_`);
return 'done';
}
}
/**
* ## constructor
*
* sets the initial "global" variables
*
* @param {Object} _bot instance of _Val with a core attached
* @param {Object} _modules config and instance of all modules
* @param {Object} userConfig available options
* @param {Object} commandModule instance of the applied core
*
* @return {Void} void
*/
constructor(_bot, _modules, userConfig, commandModule) {
super(_bot, _modules, userConfig, commandModule);
this.loadCharacterList();
}
/**
* ## listCharacters
*
* reports the active characters in the current channel
*
* @param {String} from originating channel
* @param {String} to originating user
* @param {String} text full message text
* @param {String} textArr full message text split by " "
* @param {String} command trigger word that brought us here
* @param {Object} confObj extra config object that some command modules need
*
* @return {String} list of activly tracked coins
*/
listCharacters(from, to, text, textArr, command, confObj) {
const channelId = confObj.from;
characters[channelId] = characters[channelId] || {};
if (Object.keys(characters[channelId]).length === 0) {
return 'Sorry, there are no characters in this channel.';
}
let botText = 'Characters currently in this channel:\n';
Object.keys(characters[channelId]).forEach(player => {
botText += `*${characters[channelId][player]}* : _${player}_\n`;
});
return botText;
}
/**
* ## loadCharacterList
*
* loads the json for the master ticker list
*
* @return {Void}
*/
loadCharacterList() {
const botName = this._bot.name;
const url = `json/characters/characters.${botName}.json`;
try {
characters = JSON.parse(fs.readFileSync(url, 'utf8'));
} catch (e) {
characters = {};
this.saveCharacterList();
}
}
/**
* ## responses
*
* @return {Object} responses
*/
responses() {
const { trigger } = this.userConfig;
return {
commands: {
actAs: {
f: this.actAs,
desc: 'acts in the voice of your dark herasy character',
syntax: [`${trigger}actAs <words>`],
},
listCharacters: {
f: this.listCharacters,
desc:
'lists all characters in the channel and their corresponding player',
syntax: [`${trigger}listCharacters`],
},
sayAs: {
f: this.sayAs,
desc: 'speaks in the voice of your dark herasy character',
syntax: [`${trigger}sayAs <words>`],
},
setCharacter: {
f: this.setCharacter,
desc: 'sets your character in the channel',
syntax: [`${trigger}setCharacter <name>`],
},
},
regex: {
[`${rollRegex}`]: {
f: this.roll,
desc: 'roll them bones',
syntax: [`${trigger}d10`, `${trigger}16d6`, `${trigger}9d12+6`],
},
},
};
}
/**
* ## roll
*
* rolls X dice with the Y sides
*
* @param {String} from originating channel
* @param {String} to originating user
* @param {String} text message text
* @param {Array} textArr text broken into an array of words
* @param {String} command text that triggered the bot
* @param {Object} confObj configuration object
*
* @return {Void}
*/
roll(from, to, text, textArr, command, confObj) {
const userConfig = this.userConfig;
const dndRooms = userConfig.dndRooms;
const maxDice = userConfig.dndMaxDice;
let botText = '';
function exectuteRoll(roll) {
function _getDie(_max) {
return Math.floor(Math.random() * _max) + 1;
}
let rolls = parseInt(roll[1]);
const max = parseInt(roll[2]);
const bonus = parseInt(roll[3] || 0);
if (rolls > maxDice) {
botText = `Come on ${to}... do you *really* need that many dice?`;
return false;
} else if (rolls === 0) {
botText = `Really? Fine ${to}... your 0d${max} rolls... 0`;
return false;
}
rolls = rolls || 1;
const multiple = rolls > 1;
let total = 0;
botText = `${to}, your ${rolls}d${max}${
bonus ? '+' + bonus : ''
} rolls: `;
for (let i = 0; i < rolls; i++) {
if (multiple && i === rolls - 1) {
botText += ' &';
}
const result = _getDie(max) + bonus;
total += result;
botText += ` ${result}, `;
}
botText = botText.slice(0, botText.length - 2);
if (multiple) {
botText += ` (total: ${total})`;
}
}
if (
dndRooms.indexOf(from) !== -1 ||
dndRooms === '*' ||
dndRooms[0] === '*'
) {
const roll = rollRegex.exec(command);
if (roll && roll[2]) {
exectuteRoll(roll);
}
}
return botText;
}
/**
* ## saveCharacterList
*
* saves the json to the master ticker list
*
* @return {Void}
*/
saveCharacterList() {
const botName = this._bot.name;
const charactersJSON = JSON.stringify(characters);
fs.writeFileSync(
`./json/characters/characters.${botName}.json`,
charactersJSON,
'utf8'
);
}
/**
* ## sayAs
*
* says somethig to the dark heracy channel in the voice of your character
*
* @param {String} from originating channel
* @param {String} to originating user
* @param {String} text full message text
* @param {String} textArr full message text split by " "
* @param {String} command trigger word that brought us here
* @param {Object} confObj extra config object that some command modules need
*
* @return {String} success message
*/
sayAs(from, to, text, textArr, command, confObj) {
this.loadCharacterList();
characters[DW_CHANNEL] = characters[DW_CHANNEL] || {};
const characterName = characters[DW_CHANNEL][to];
if (characterName) {
this._bot.say(DW_CHANNEL, `*${characterName}* : ${text}`);
return 'done';
}
}
/**
* ## setCharacter
*
* sets a ticker to a room
*
* @param {String} from originating channel
* @param {String} to originating user
* @param {String} text full message text
* @param {String} textArr full message text split by " "
* @param {String} command trigger word that brought us here
* @param {Object} confObj extra config object that some command modules need
*
* @return {String} success message
*/
setCharacter(from, to, text, textArr, command, confObj) {
const name = textArr[0];
if (!name) {
return 'invalid Name';
}
this.loadCharacterList();
const channelId = confObj.from;
characters[channelId] = characters[channelId] || {};
if (name) {
characters[channelId][to] = name;
this.saveCharacterList();
return `You have set your character in this channel to ${name}`;
}
return botText;
}
}
module.exports = DND;