patternjavascriptMinor
Another JavaScript Stack Exchange chat bot
Viewed 0 times
chatstackjavascriptexchangebotanother
Problem
I've been inspired by @SirPython's SirAlfred JavaScript chat bot, so I went and made my own. This one is slightly different though, in the fact that it can accept input in a more lenient way. For example, here's a "conversation" with the bot:
Essentially, instead of directly checking the contents of the string, it removes all non-alphanumeric characters, excluding spaces, and then splits on a space. It then checks to see if this split array contains certain words, and then outputs a message based on those words.
`/**
* This is a small utility function used to
* determine if an array contains a certain
* value.
* @param {array} array - The array to check for the element in.
* @param {generic} value - The value to check for.
* @returns {boolean}
*/
function arrayContains(array, value) {
return array.indexOf(value) > -1;
}
/**
* Select a random element from the array.
* @param {array} array - The array to select from.
*/
function randomArrayElement(array) {
return array[Math.floor(Math.random() * array.length)];
}
/**
* This error is thrown when sendMessage
* is called and the message length
* exceeds 400 characters.
* @constructor
* @param {string} message - The error's message.
*/
function InvalidMessageLength(message) {
this.message = message;
this.name = "InvalidMessageLength";
}
/**
* Post a message to the room.
* @param {string} messageString - The string to be posted.
*/
function sendMessage(messageString) {
if(messageString.length - 1
Finally, in order to run this, you need to open up inspect element on your browser. While in a Stack Exchange chat room, copy-paste the above source into the JavaScript console, and then hit enter.
sudo make me a sandwich bot
BOT: It will be done master.
sudo make me a sandwich bot
BOT: Yes sir.
Hello there bot.
BOT: Hello there.
Goodbye bot.
BOT: Goodbye.
Essentially, instead of directly checking the contents of the string, it removes all non-alphanumeric characters, excluding spaces, and then splits on a space. It then checks to see if this split array contains certain words, and then outputs a message based on those words.
`/**
* This is a small utility function used to
* determine if an array contains a certain
* value.
* @param {array} array - The array to check for the element in.
* @param {generic} value - The value to check for.
* @returns {boolean}
*/
function arrayContains(array, value) {
return array.indexOf(value) > -1;
}
/**
* Select a random element from the array.
* @param {array} array - The array to select from.
*/
function randomArrayElement(array) {
return array[Math.floor(Math.random() * array.length)];
}
/**
* This error is thrown when sendMessage
* is called and the message length
* exceeds 400 characters.
* @constructor
* @param {string} message - The error's message.
*/
function InvalidMessageLength(message) {
this.message = message;
this.name = "InvalidMessageLength";
}
/**
* Post a message to the room.
* @param {string} messageString - The string to be posted.
*/
function sendMessage(messageString) {
if(messageString.length - 1
Finally, in order to run this, you need to open up inspect element on your browser. While in a Stack Exchange chat room, copy-paste the above source into the JavaScript console, and then hit enter.
Solution
if(arrayContains(lastMessage, "hello") && arrayContains(lastMessage, "bot")) {
sendMessage(BOT_TEXT + RANDOM_REPLIES.helloGreeting());
}
else if(arrayContains(lastMessage, "goodbye") && arrayContains(lastMessage, "bot")) {
sendMessage(BOT_TEXT + RANDOM_REPLIES.goodbyeGreeting());
}
else if(arrayContains(lastMessage, "sudo") && arrayContains(lastMessage, "bot")) {
sendMessage(BOT_TEXT + RANDOM_REPLIES.sudoCommand());
}What's the difference between these three lines? The keyword being searched for and the method being called.
Just two values? Seems like the perfect job for a map/object!
I'm assuming that you aren't going to only have these three commands for your chat bot; you're probably going to want to add more in the future.
Let's use a map/object (as I stated above) to store these commands and their keywords and functions:
var commands = {
"hello": function() { [hello greeting] },
"goodbye": function() { [goodbye greeting] },
"sudo": function() { [sudo command] }
};Now, going back to the
main function, all we have to do now is iterate through the map/object and check if the key value with the keyword that you were originally passing into arrayContains.Here is what that looks like:
var lastMessage = getLastPostedMessage().toLowerCase().replace(/[^a-zA-Z\d\s:]/g, "").split(" ");
if(arrayContains(lastMessage, "bot")) {
for(var command in commands) {
if(arrayContains(lastMessage, command)) {
sendMessage(BOT_TEXT + commands[command]());
}
}
}Note: I moved the
arrayContains outside of the loop because you don't want to unnecessarily check if the message is a command if it isn't even addressing the bot. Credit to 3Doubloons.I just realized this, but your
RANDOM_REPLIES object could be used instead of creating that new commands map/object that I recommended. The only thing you'd have to change in that object would be the keys; you'd have to change those to the keywords.Code Snippets
if(arrayContains(lastMessage, "hello") && arrayContains(lastMessage, "bot")) {
sendMessage(BOT_TEXT + RANDOM_REPLIES.helloGreeting());
}
else if(arrayContains(lastMessage, "goodbye") && arrayContains(lastMessage, "bot")) {
sendMessage(BOT_TEXT + RANDOM_REPLIES.goodbyeGreeting());
}
else if(arrayContains(lastMessage, "sudo") && arrayContains(lastMessage, "bot")) {
sendMessage(BOT_TEXT + RANDOM_REPLIES.sudoCommand());
}var commands = {
"hello": function() { [hello greeting] },
"goodbye": function() { [goodbye greeting] },
"sudo": function() { [sudo command] }
};var lastMessage = getLastPostedMessage().toLowerCase().replace(/[^a-zA-Z\d\s:]/g, "").split(" ");
if(arrayContains(lastMessage, "bot")) {
for(var command in commands) {
if(arrayContains(lastMessage, command)) {
sendMessage(BOT_TEXT + commands[command]());
}
}
}Context
StackExchange Code Review Q#95792, answer score: 6
Revisions (0)
No revisions yet.