bot.on('message', message => {
var str = (message.content.indexOf("swear"))
if (str != -1){
var Pottymouth = message.guild.roles.find('name', 'Pottymouth')
message.channel.send("Woah there, " + message.author + ", you can't use that kind of language here!");
message.member.addRole(Pottymouth);
}
I'm trying to code Jesus as a super cool bot, and one thing he needs to do is make sure that nobody's swearing. So far, this code works for when someone says "swear", but it won't detect them saying "SWEAR" or any other capitalisation. How do I make Jesus not bother with listening to case, and instead focus on the actual content of the message?
Simply lowercase the whole message before checking, or else consider using a case-insensitive regular expression.
Using a regular expression allows you to enforce word boundaries as well, which means you can avoid flagging false positives like "menswear".
if (/\bswear\b/.test(message)) {
// Do things
}
Related
I tried to create a JavaScript program that outputs the binary format of an English letter on input. I had to put the value in the code. How can the value be entered in the console when the program runs?
function returnBinaryLetter(char) {
return ((/^[a-z]$/).test(char)) ? char.charCodeAt(0).toString(2).padStart(8, '0') : 'Sorry, that is not a letter.'
}
// Something like:
// const input = consoleInputFunction('Enter a number.');
// console.log(returnBinaryLetter(input.toLowerCase()));
EDIT 1: This is not for a webpage. This is a JS program which I will run using Node.js. I require a solution with just JS, not with some framework (if that is even possible, mentioning just to be specific).
EDIT 2: I have made the code better after suggestions in Endothermic Dragon's answer.
To directly answer your question, you would use prompt to get a user input in this case.
However, you don't need all of that code. Try this:
function returnBinaryLetter(char) {
if ((/^[a-z]$/).test(char)) {
return char.charCodeAt(0).toString(2).padStart(8, '0')
} else {
return 'Sorry, that is not a letter.'
}
}
var input = prompt('Enter letter to be converted to binary:').toLowerCase();
console.log(returnBinaryLetter(input))
While it may seem a bit intimidating, here's the whole thing broken down:
Ask for an input using prompt, and convert it to lowercase.
Pass the character to the function returnBinaryLetter, and log the output.
Now for the function returnBinaryLetter:
Check if it is a single lowercase letter, using some RegEx.
If it is, return binary. Otherwise, return an error with a description.
Hmm, but how does the binary conversion work?
First, take the character and get its character code.
Next, convert that code to binary.
Finally, pad the start so it is an 8-bit number. If it is not 8 digits, add on 0s at the beginning until it is.
Here, you can see that a more dynamic conversion looks much shorter, and cleaner as well, compared to manually entering about 28 lines of code.
Bonus:
Surprise, surprise! You can further shorten it. Using a ternary operator, you can skip the if-else statement.
function returnBinaryLetter(char) {
return ((/^[a-z]$/).test(char)) ? char.charCodeAt(0).toString(2).padStart(8, '0') : 'Sorry, that is not a letter.'
}
var input = prompt('Enter letter to be converted to binary:').toLowerCase();
console.log(returnBinaryLetter(input))
Now, it's a one-liner!
A ternary operator is usually used within variables when you want to assign its value based on a condition. The ternary operator first checks if the condition inside the brackets is true, and if it is, it returns the first statement (between ? and :), and if not, it returns the second statement (after the :). Pairing this with the return statement of a function, you get a one-liner function!
Feedback:
Since it seems that you are following CamelCase, I thought I would mention that function names should always start with a capital letter, along with each word after that also starting with a capital letter. Variables are different however - for variables, you do make the first letter lowercase, but make all the other words uppercase. In addition, the function name returnBinaryLetter might seem intuitive to you, but not for anyone looking at the code. A more intuitive name that exactly describes its function would be LowercaseLetterToBinary.
For NodeJS, You can use inquirer, which provides different kinds of prompts for the command line (such as text, list, checkbox etc).
Prerequistes:
Install it with npm install inquirer
Example
const { prompt } = require("inquirer");
async main() {
const binaryLetter = await prompt({
type: 'input',
name: 'letter',
message: `What's your name >>`
})
.then(answer => returnBinaryLetter(answer['letter']));
}
main();
I'm really new to Javascript, kinda just learned a little earlier today and been messing around with it, but I'm running into a few issues her and there. I'd appreciate help from some people that know their way around the code.
What's the best way to search a string for multiple words? I'm not completely sure how to explain what I mean, so I'll include my current test code and try to explain. I'm making an attached script to pull text from a text based game online, converting it to lowercase, and defining variables for the use of a money system that changes the input text. Once changes are made, I'm re-inputting the modified text into the game as a return.
let money = 0;
const modifier = (text) => {
let modifiedText = text;
const lowered = text.toLowerCase();
let moneyChange = 0;
// The text passed in is either the user's input or players output to modify.
if(lowered.includes('take their money') || lowered.includes('take ' + 'money')) {
moneyChange = (Math.floor(Math.random() * 500));
if ((moneyChange) > 1) {
console.log(moneyChange);
money += moneyChange;
modifiedText = `You find ${moneyChange} Credits. You now have ${money} Credits`;
} else {
modifiedText = 'You find nothing.';
console.log(modifiedText);
}
}
console.log(modifiedText);
// You must return an object with the text property defined.
return {text: modifiedText};
}
modifier(text);
Currently, as you can see, I have to specifically type "Take their money" or "Take money" as an action before the text pulled is recognized as me taking money from someone or taking some in general. My main issue is that with how the game works, it's somewhat impossible to guess exactly how the input or output is going to come out. The way it works is that the game takes your character's action or speech that you type out, processes it via AI into it's own action or dialogue and generates procedural story to make more sense with the setting so that the player only has to type a vague idea of what's going to happen.
Here's an example:
There's a dead man on the street in front of you.
>loot him
You loot the man, digging through his pockets. You take some money from his wallet, but find nothing else.
The > is my only input and the rest is completely AI generated. My script looks through the AI result and , so I could look for every possible result, from "take his money" to "take her money" and so forth, but that's a little too much to bother with if there's an easier way. If I could have it search the result for specific words that may not be in the normal order and/or with other words in between. Like, it must contain the words "take" and "money" so that if the game says "You find some money, along with a gun. You take both", it recognizes that I'm taking the money. As well as the fact that I still need to write code for every single other time I do anything with money, such as buying things, and if I have to write every possible thing it's going to be a pain.
I know that it would be easier if this code was integrated into the game, but due to AI limitations, that kinda breaks how it works and it goes a little crazy... Any sort of help you can give me will be a help.
If you're looking for a way to search a string which includes multiple sub-phrases, you can use string.includes() in a loop like shown below:
function containsWords(string, words) {
for (let i=0, len=string.length; i<len; i++) {
if (!string.includes(words[i])) {
return false;
}
}
return true;
}
However you also mentioned
search the result for specific words that may not be in the normal order and/or with other words in between
Which immediately brings to mind regex, a text and string matching technology. You can easily find tutorials for regex online, and this live tester is nice too.
I'll quickly build a search string to match "take *** money", where any word can be *** as a quick introduction and example to regex:
/take .+ money/g
Here it matches the specific string take , then .+ matches one or more characters (the middle pronoun eg him/her), then matches money.
I am working on a project that needs to check if the user has written a good condition on a textfield. So I'd like to know if one of you knows the regex of a 'if'. For example, if the user writes if ((k <= 5 && k>0)|| x>8) I will return true.
Keith's reference looks good (pegjs.org). You're not looking for a regex (albeit possible to do with such) by a lexer + yacc combo (see flex and bison). Note that what you are really looking for is the "expression" parser. A "simple calculator" expression.
One way to test would be to use the "eval()" function. However, it is considered to be a dangerous function. Yet, in your case you let the end user enter an expression and then execute that expression. If they write dangerous stuff, they probably know what they are doing and they will be doing it to themselves.
There is documentation about it:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
In your case you would do something like the following with a try/catch to know whether it is valid:
var valid = true;
try
{
// where input.val would reference your if() expression
eval(input.val);
}
catch(e)
{
valid = false;
}
Note that's a poor man solution since it won't tell you whether other code is included in the expression. There are probably some solution to that such as adding some string at the start such as:
eval("ignore = (1 + " + input.val + ")");
Now input.val pretty much has to be an expression. You'll have to test and see whether that's acceptable or not.
I'm sort of building an AI for a Telegram Bot, and currently I'm trying to process the text and respond to the user almost like a human does.
For example;
"I want to register"
As a human we understand that the user wants to register.
So I'd process this text using javascript's indexOf to look for want and register
var user_text = message.text;
if (user_text.indexOf('want') >= 0) {
if (user_text.indexOf('register') >= 0) {
console.log('He wants to register?')
}
}
But what if the text contains not somewhere in the string? Of course I'd have like a zillion of conditions for a zillion of cases. It'd be tiring to write this kind of logic.
My question is — Is there any other elegant way to do this? I don't really know the keyword to Google this...
The concept you're looking for is natural language processing and is a very broad field. Full NLP is very intricate and complicated, with all kinds of issues.
I would suggest starting with a much simpler solution, by splitting your input into words. You can do that using the String.prototype.split method with some tweaks. Filter out tokens you don't care about and don't contribute to the command, like "the", "a", "an". Take the remaining tokens, look for negation ("not", "don't") and keywords. You may need to combine adjacent tokens, if you have some two-word commands.
That could look something like:
var user_text = message.text;
var tokens = user_text.split(' '); // split on spaces, very simple "word boundary"
tokens = tokens.map(function (token) {
return token.toLowerCase();
});
var remove = ['the', 'a', 'an'];
tokens = tokens.filter(function (token) {
return remove.indexOf(token) === -1; // if remove array does *not* contain token
});
if (tokens.indexOf('register') !== -1) {
// User wants to register
} else if (tokens.indexOf('enable') !== -1) {
if (tokens.indexOf('not') !== -1) {
// User does not want to enable
} else {
// User does want to enable
}
}
This is not a full solution: you will eventually want to run the string through a real tokenizer and potentially even a full parser, and may want to employ a rule engine to simplify the logic.
If you can restrict the inputs you need to understand (a limited number of sentence forms and nouns/verbs), you can probably just use a simple parser with a few rules to handle most commands. Enforcing a predictable sentence structure with articles removed will make your life much easier.
You could also take the example above and replace the filter with a whitelist (only include words that are known). That would leave you with a small set of known tokens, but introduces the potential to strip useful words and misinterpret the command, so you should confirm with the user before running anything.
If you really want to parse and understand sentences expressed in natural language, you should look into the topic of natural language processing. This is usually done with some kind of neural network trained to "understand" different variations of sentences (aka machine learning), because specifying all of different syntactic and semantic rules of the language appears to be an overwhelming task.
If however the amount of variations of these sentences is limited, then you could specify some rules in the form of commonly used word combinations, probably even regular expressions would do in the simplest case.
I have written the following regex to catch anything within two parenthesis of a text:
var rule = /[a-zA-Z0-9]*(\(+[a-zA-Z\s0-9]*\))*[a-zA-Z0-9\s]/;
It works in this website: http://regex101.com/ (javascript section)
Look the right side of the window and you see the bottom section shows the matched string which is what I want.
But in firebug when I execute the following code it crashes. Why? how then should I catch the group in parenthesis?
var rule = /^[a-zA-Z0-9\s]*(\(+[a-zA-Z\s0-9]*\))*[a-zA-Z0-9\s\,]*/;
var str = "He left us (with anger), but came back all cool and modest.";
var res = "";
while((res = rule.exec(str)) !== null)
{
console.log("Good");
}
console.log(res);
Or maybe I'm totally wrong and am missing something?
"But in firebug when I execute the following code it crashes. Why?"
To use .exec() in a loop like that, the regex must be global. Otherwise it's just going to keep getting the first match, resulting in an infinite loop.
// make it global ------------------------------------------------v
var rule = /^[a-zA-Z0-9\s]*(\(+[a-zA-Z\s0-9]*\))*[a-zA-Z0-9\s\,]*/g;
When global, the regex object becomes stateful, and each subsequent .exec() will begin from the character after the last match.
When there are finally no matches left, it'll return null, breaking the loop.
As others pointed out in the comments, the leading ^ will guarantee only one match (without the m modifier anyway), so you'll probably want to remove that. It's not the cause of the crash though.