Discord.js command check empty space only once - javascript

when someone inputs a command !add James Bond;Michael B Jordan the argument takes it as "James"arg[0], "Bond;Michale"args[1], "B"args[2], "Jordan"args[3]. Any way i can make it so that it only counts the empty space after the "!add" and then splits using ";" ?. Final answer would be "James Bond"args[0], "Michael B Jordan"args[1].
client.on('message',async(message)=>{
if(!message.content.startsWith(prefix2)||message.author.bot)return;
const args2=message.content.slice(prefix.length).trim().split(/ +/);
const command= args2.shift().toLowerCase();
This is what i tried but it doesnt seem to work
if(!message.content.startsWith(prefix2)||message.author.bot)return;
const args2=message.content.slice(prefix.length).trim().split(/ {1}[;]+/);
const command= args2.shift().toLowerCase();
Thanks

Since we know !add will always takeup 5 characters of the string, we can crop out those 5 using String.prototype.slice().
This will then return 'James Bond;Michael B Jordan', which we can ofcourse split by ; to return each name in it's own array element.
client.on('message', async(message) => {
// message.content = '!add James Bond;Michael B Jordan'
const rawContent = message.content.slice(5);
const celebrityArguments = rawContent.split(';');
console.log(celebrityArguments);
// ["James Bond", "Michael B Jordan"]
})

Related

Issue using .split() to get a username containing many spaces (Discord.js in NodeJS)

I'm working on a feature of my Discord Bot, which returns the League of Legends statistics of a player when you write the following command !lolid [enter_username_here] in a Discord chat room,
I succeeded to do it for a person which has a username in 1 word, but unfortunately for me a League of Legends username can have spaces (example of possible username: I AM A GOD),
When a user types the following command !lolid [enter_username_here], i get it in my JS file as message.content variable, so with message.content.split(" ")[1]; I can get the username he wrote,
But how can I do if the username contains many spaces ? Thanks,
Part of involved code :
if (message.content.startsWith("!lolid")) {
console.log(message.content.split(" ")); => if someone types !lolid 1 2 3, it returns ["lolid", "1", "2", "3"];
const username = message.content.split(" ")[1];
const promise1 = new Promise(async (resolve, reject) => {
resolve(await getSummonerId(username)); => returns id needed to do the request for the stats
});
}
Why not just remove the command part:
const username = message.content.slice(7);
or
const username = message.content.split("!lolid ")[1];
or
const username = message.content.replace(/\!lolid\s/, "");
Thanks to #GACy20 for the first suggestion
Another solution, leveraging on ES6 syntax:
const msg = "!lolid I AM GOD"
const [cmd, ...ids] = msg.split(" ")
const id = ids.join(" ");
console.log(id);
If you are only taking the input of the username in your code, then you can just slice off the first element, and use join the rest of it to work.
So like
const username = message.content.split(" ").slice(1).join(" ");
This removes the first argument, which is your !lolid. That would leave your username only for you to deal with.
I'm not really into discord bots but since you know what is the length of "!lolid ", can't you just use "message.content.slice(7) or something?

Partial String Match - Dynamic Strings

For certain dynamic strings like:
covid-19 testing status upto may 05,2021
covid-19 testing status upto may 04,2021
covid-19 testing status upto may 01,2021
....
covid-19 testing status upto {{date}}
and others like:
Jack and Jones are friends
Jack and JC are friends
Jack and Irani are friends
.....
Jack and {{friend-name}} are friends
I want to match the incoming string like:
covid-19 testing status upto may 01,2021
with
covid-19 testing status upto {{date}}
and if there is a match, I want to extract the value of date.
Similarly, for an incoming string like
Jack and JC are friends
I want to match with
Jack and {{friend-name}} are friends
and extract JC or the friend-name. How could I do this?
I am trying to create a setup where dynamic strings like these, can be merged into one. There could be thousands of incoming strings that I want to match against the existing patterns.
INCOMING_STRINGS -------EXISTING-PATTERNS----->
[
covid-19 testing status upto {{date}},
Jack and {{friend-name}} are friends,
....
] ---> FIND THE PATTERN AND EXTRACT THE DYNAMIC VALUE
EDIT
It is not guaranteed that the pattern will always exist in the incoming strings.
It's very easy to use regex for the second of your examples. If you use a capturing group for the "friend name" part you can extract that with ease:
const re = /Jack and ([a-zA-Z]+) are friends/
const inputs = ["Jack and Jones are friends",
"Jack and JC are friends",
"Jack and Irani are friends",
"Bob and John are friends"] // last one wont match
for(let i=0;i<inputs.length;i++){
const match = inputs[i].match(re);
if(match)
console.log("friend=",match[1]);
else
console.log("No match for the string:", inputs[i])
}
The first example is slightly hardeer, but only because the regex is more difficult to write. Assuming the format is always "short month name 2 digit day comma 4 digit year" it is doable
const re = /covid-19 testing status upto ((jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) (0?[1-9]|[12][0-9]|3[01]),\d{4})/
const inputs = ["covid-19 testing status upto may 05,2021",
"covid-19 testing status upto may 04,2021",
"covid-19 testing status upto may 01,2021",
"covid-19 testing status upto 01/01/2020"] // wrong date format
for(let i=0;i<inputs.length;i++){
const match = inputs[i].match(re);
if(match)
console.log("date=",match[1]);
else
console.log("No match for the string:", inputs[i])
}
It's fairly unclear to me what your actual inputs and outputs should be. Here's an attempt that guesses at that. With inputs like
[{
sample: 'covid-19 testing status upto may 05,2021',
extract: 'may 05,2021',
propName: 'date'
}, {
sample: 'Jack and Jones are friends',
extract: 'Jones',
propName: 'friend-name'
}]
we generate a function which can be used like this:
mySubs ('Jack and William are friends')
//=> {"friend-name": "William"}
or
(mySubs ('covid-19 testing status upto apr 30,2021')
//=> {"date": "apr 30,2021"}
or
mySubs ('Jack and Jessica are friends who dicsussed covid-19 testing status upto apr 27,2021')
//=> {"date": "apr 27,2021", "friend-name": "Jessica"}
and which would yield an empty object if nothing matched.
We do this by dynamically generating regular expressions for our samples, ones which will capture the substitutions made:
const regEscape = (s) =>
s .replace (/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
const makeTester = ({sample, extract, propName}) => ({
regex: new RegExp (
regEscape (sample .slice (0, sample .indexOf (extract))) +
'(.+)' +
regEscape (sample .slice (sample .indexOf (extract) + extract .length))
),
propName
})
const substitutes = (configs, testers = configs .map (makeTester)) => (sentence) =>
Object.assign( ...testers .flatMap (({regex, propName}) => {
const match = sentence .match (regex)
return (match)
? {[propName]: match[1]}
: {}
}))
const configs = [{
sample: 'covid-19 testing status upto may 05,2021',
extract: 'may 05,2021',
propName: 'date'
}, {
sample: 'Jack and Jones are friends',
extract: 'Jones',
propName: 'friend-name'
}]
const mySubs = substitutes (configs)
console .log (mySubs ('Jack and William are friends'))
console .log (mySubs ('covid-19 testing status upto apr 30,2021'))
console .log (mySubs ('Jack and Jessica are friends who dicsussed covid-19 testing status upto apr 27,2021'))
console .log (mySubs ('Some random string that does not match'))
.as-console-wrapper {max-height: 100% !important; top: 0}
If you needed to also report what templates matched, you could add a name to each template, and then carry the results through the two main functions to give results like this:
{"covid": {"date": "apr 27,2021"}, "friends": {"friend-name": "Jessica"}}
It's only slightly more complex:
const regEscape = (s) =>
s .replace (/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
const makeTester = ({name, sample, extract, propName}) => ({
regex: new RegExp (
regEscape (sample .slice (0, sample .indexOf (extract))) +
'(.+)' +
regEscape (sample .slice (sample .indexOf (extract) + extract .length))
),
propName,
name
})
const substitutes = (configs, testers = configs.map(makeTester)) => (sentence) =>
Object.assign( ...testers .flatMap (({name, regex, propName}) => {
const match = sentence .match (regex)
return (match)
? {[name]: {[propName]: match[1]}}
: {}
}))
const configs = [{
name: 'covid',
sample: 'covid-19 testing status upto may 05,2021',
extract: 'may 05,2021',
propName: 'date'
}, {
name: 'friends',
sample: 'Jack and Jones are friends',
extract: 'Jones',
propName: 'friend-name'
}]
const mySubs = substitutes (configs)
console .log (mySubs ('Jack and William are friends'))
console .log (mySubs ('covid-19 testing status upto apr 30,2021'))
console .log (mySubs ('Jack and Jessica are friends who dicsussed covid-19 testing status upto apr 27,2021'))
console .log (mySubs ('Some random string that does not match'))
Either way, this has some limitations. It's hard to figure out what to do if the templates overlap in odd ways, etc. It's also possible that you want to match only complete sentences, and my examples of double-matching won't make sense. If so, you can just prepend a '^' and append a '$' to the string passed to new RegExp.
Again, this is a guess at your requirements. The important thing here is that you might be able to dynamically generate regexes to use.

How to make a discord bot reply what you have said?

I'm new at coding and I want to make a bot that says whatever you say after the !say command. For example - !say hello, bot replies with "hello".
What I tried:
let args = message.content.substring(PREFIX.length).split(" ");
if(message.content.startsWith(PREFIX + 'say')) {
var say = args[1].join(" ");
message.channel.send(say)
}
args is an array of strings, so args[1] is a string and therefore has no function join.
Try this:
const args = message.content.substring(PREFIX.length).split(' ')
if (message.content.startsWith(PREFIX + 'say')) {
const say = args[1]
message.channel.send(say)
}
You might want to take a look at the discord.js guide (which has a section on handling command arguments).

How can I split a message and resend the second part into a text channel?

I am trying to split a message when someone uses this tip command and get the second part of the message.
In other words, after someone types &tip <#607942707620610087> 10 satoshi I want to be able to get the 10 satoshi part and put it into the general.send command.
var general = client.channels.find(channel => channel.id === "605819397524946972");
if(message.content.startsWith("&tip <#607942707620610087>")) {
message.author.send("Thanks for the donation!");
general.send("<#" + message.author.id + "> just donated ")
};
var general = client.channels.find(channel => channel.id === "605819397524946972");
if(message.content.startsWith("&tip <#607942707620610087>")) {
let args = message.content.slice("&").split(' ');
message.author.send("Thanks for the donation!");
general.send(`${message.author} just donated ${args[2]`)
};
message.content.slice("&").split(' ')This will slice the prefix and split the message like that ("&tip <#607942707620610087> 10 satoshi" Where tip will be our (args[0]), <#607942707620610087> (args[1]) and finally 10 satoshi will be ours (args[2]))

How we can ignore some space in JavaScript?

I did this code :
var fs = require('fs');
var str = fs.readFileSync('input.txt', 'utf8');
str.split(/\s+/).forEach(function (s) {
return console.log(
s === 'bob'
? 'boy'
: s === 'alicia'
? 'girl'
: s === 'cookie'
? 'dog'
: 'unknown');
});
But in my input file there are some space, and I don't want my code to take it into account. My input file is :
cat
bob
alicia
shirley
cookie
thomas
rat`
So how can I code, to ignore the space in my input file please ?
First of all if you'd console.log(str.split(/\s+/)) you'll get
[ 'cat', 'bob', 'alicia', 'shirley', 'cookie', 'thomas', 'rat`' ]
so as everyone has already said /\s+/ will in fact remove the spaces
#JuanCaicedo your solution doesn't work well sorry, I tried and between cookie and thomas there are space, and the code write unknown. The result is unknown boy girl unknown dog unknown unknown unknown so after rat the code take care about the space
the output you're seeing is correct, according to your logic
s === 'bob'
? 'boy'
: s === 'alicia'
? 'girl'
: s === 'cookie'
? 'dog'
: 'unknown');
If the string doesn't equal bob or alicia or cookie it will output unknown therefore
cat = unknown
bob = boy
alicia = girl
shirley = unknown
cookie = dog
thomas = unknown
rat` = unknown
Please look at the code below
function removeEmptyLines(str) {
const arrayOfLines = str.split("\n"); // Remove empty lines from the string which leaves "" in the returned array
const filtered = arrayOfLines.filter(line => line !== ""); // filter the array and remove all the empty strings
const joined = filtered.join(" "); // form a single string
return joined; // return filtered array
}

Categories