Validate array command - arrays

As I put in the question I have these commands that work correctly but are not validated, which means that if I enter a name it simply makes the record not validating if this name already exists inside the array.
It sounds simple but I've tried to validate using array.find and then compare with the value before inserting but it does not work: for example in the command track I'm trying to validate if the name you are trying to insert already exists. In the command untrack if the name does not exist send a message, because that is another problem: if the name does not exist the command deletes the last inserted record.
If someone has the knowledge on how to make such validations, I would appreciate a little help.
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === "track") {
let [playerName, playerType] = args;
list.push({
name: playerName,
type: playerType
}) var logger = fs.createWriteStream('./realmtrack-config.json')
logger.write(JSON.stringify(config)) message.reply(`Player being tracked!`);
}
if (command === "untrack") {
let [playerName, playerType] = args;
let entry_to_delete = list.find((e: any) => e.name === playerName);
list.splice(list.indexOf(entry_to_delete), 1);
var logger = fs.createWriteStream('./realmtrack-config.json');
logger.write(JSON.stringify(config));
message.reply(`${playerName} stopped being tracked!`);
}

You have an array of objects
let list = [
{ name: "Joe", type: "Cool" },
{ name: "Sally", type: "Cool"}
]
You could create the below function to check if "Sally" is the name of one of the objects.
function(obj) {
return obj.name === "Sally"
}
We can make this shorter with ES6 arrow functions
obj => obj.name === "Sally"
Next, we can scour list for an argument which will return true when passed to that function.
list.some(obj => obj.name === "Sally")
.some will return false only if all of the elements in an array will return false when passed to the callback function. Otherwise, it returns true.
We can add the below line near the start of your message handler, then.
const isBeingTracked = list.some(obj => obj.name === args[0])
For the track command, you could add if(!isBeingTracked) { /* ... */ } (the ! means "not"). For the untrack command, you could add if(isBeingTracked) { /* ... */ }. /* ... */ is what you would replace for actual code.

Related

react check array values based on specific keys returning true/false if values found

I am trying to figure out how to do this but can't seem to wrap my head around it..
I have an address object
const obj = {
"address_type":"Home",
"country":"US",
"addressLine1":"123 Any Street",
"addressLine2":"",
"city":"Any Town",
"state":"Indiana",
"state_code":"IN",
"zip":"46220-4466",
"phone":"6715551313",
"mobile_number":"",
"extn":"",
"fax":"",
"county_name":"MyCounty"
}
I want to check for any key that has a value but only specific keys
const objProps = ["addressLine1","addressLine2","city","state_code","zip","county_name"];
I want to check all keys in objProps against my address object and if any one of them contains a value return true (doesn't matter if its 1 or all 6).. If all keys don't contain a value then return false (Sometimes I will get an address object that has all null values)
I've tried various ways to accomplish this but have failed in each one.
The variation I am working on now is using reduce. While it doesn't meet my needs I thought I could check the resulting array and if length was greater than 0 than I have my answer..
Work-in-progress:
function hasAddressData(obj: any) {
const objProps = ["addressLine1","addressLine2","city","state_code","zip","county_name"];
const keysWithData = objProps.reduce((accumulator, key) => {
const propExistsOnObj = obj.hasOwnProperty(key);
let keyHasData = [];
if (obj[key].length > 0 ) {
keyHasData = obj[key]
}
if (!propExistsOnObj) {
accumulator.push(key);
} else if (keyHasData) {
const equalValueKeyIndex = accumulator.indexOf(key);
accumulator.splice(equalValueKeyIndex, 1);
}
return accumulator;
});
return keysWithData;
}
The above is messed up I know and doesn't work.. Just learning this stuff.. anyone have a suggestion or comment?
Check that .some of the objProps, when looked up on the obj, contain a value. (Either with Boolean or by comparing against '')
const obj = {
"address_type":"Home",
"country":"US",
"addressLine1":"123 Any Street",
"addressLine2":"",
"city":"Any Town",
"state":"Indiana",
"state_code":"IN",
"zip":"46220-4466",
"phone":"6715551313",
"mobile_number":"",
"extn":"",
"fax":"",
"county_name":"MyCounty"
}
const objProps = ["addressLine1","addressLine2","city","state_code","zip","county_name"];
const somePopulated = objProps.some(prop => obj[prop]);
// or prop => obj[prop] !== ''
console.log(somePopulated);
const obj = {
"address_type":"Home",
"country":"US",
"addressLine1":"",
"addressLine2":"",
"city":"",
"state":"Indiana",
"state_code":"",
"zip":"",
"phone":"6715551313",
"mobile_number":"",
"extn":"",
"fax":"",
"county_name":""
}
const objProps = ["addressLine1","addressLine2","city","state_code","zip","county_name"];
const somePopulated = objProps.some(prop => obj[prop]);
// or prop => obj[prop] !== ''
console.log(somePopulated);
function checkKeys(target, props) {
return props.some((prop) => {
return target.hasOwnProperty(prop) && target[prop];
});
}
Explanation: some iterates through the props you want to check, returning true immediately when one is found (i.e. the callback returns true). If no props are found (i.e. no callback returns true), some returns false.
hasOwnProperty ensures that you are only checking properties on target, and not looking up the prototype chain. target[prop] checks for a truthy value. You may need to modify this last check if you're going to be handling values other than strings.

How do I select multiple args in a command and assign it to a variable? Discord.js

I want to do so that when I use !pm (user) (some message), my bot will send a private message to the user, although I have no idea how to select everything after the (user) and assign it to a variable, to send it to the user.
My current code looks like this:
module.exports = {
name: 'pm',
description: 'Sends a personal message!',
execute(message, args, client) {
const pmMessage = args[1];
client.users.cache.get('464839066781745167').send(pmMessage);
}
}
Since you know the array index of the pmMessage, with the help of that index, you can use the slice method which returns the array from specified stating to end index.
Eg:
let pmMessage = args.slice(2); //returns array.
Note: If the end index is not specified, then it considers till the last index of the array.
Now, using the join method, you can join all the indexes with whatever specified character. Eg:
let MessageContent = pmMessage.join(' '); //joined by space.
let args = ["UserID","This","represents","the","message","content","to","be","sent"];
console.log(args.slice(1));
console.log(args.slice(1).join(' '));
Try this, I think this should work:
let pm_args = args.slice(1).join(' ')
if(args[0]){
let user = getUserFromMention(args[0])
if(!user){
return message.reply('please mention a user.');
}
return client.users.cache.get(user.id).send(pm_args);
}
return message.reply('please mention a user.');
(This is what I used for mention thingie:)
function getUserFromMention(mention){
if(!mention) return;
if(mention.startsWith('<#') && mention.endsWith('>')){
mention = mention.slice(2, -1);
if(mention.startsWith('!')){
mention = mention.slice(1);
}
return bot.users.cache.get(mention);
}
};
client.on("message", message => {
if(!message.content.startsWith(config.prefix)) return;
const withoutPrefix = message.content.slice(config.prefix.length);
const split = withoutPrefix.split(/ +/);
const command = split[0];
const args = split.slice(1);
// Code...
});

condition assign to const variable

I am doing a regex where I am checking for the condition with certain names.
const nameMatch = () => {
return ( !this.state.name.match("^Jen.*") || !this.state.name.endsWith("ez") );
}
In this, I get the values of nameMatch as () => { return ( !this.state.name.match("^Jen.*") || this.state.name.endsWith("ez") ); } rather than true or not
I am doing if(nameMatch) {...}
but rather I would need the ones that match.
What am I doing wrong?
A breakdown of the regex "^Jen.*":
^ asserts the position the start of a line, where lines are delimited by \n.
Jen is a case sensitive match for the characters "Jen".
.* matches any character except for line terminators (\n) between zero and unlimited times.
Therefore as I understand your question, you're asking how to find and return every name which does not start with "Jen" or end with "ez".
If this.state.name is an Array of names, then you can return all of the names that do not start with "Jen" or end with "ez" using the following example:
var names = ['menez', 'asJenas', 'benez', 'destruction', 'present', 'Jenosus', 'ezJen'];
const nameMatch = names.filter((word) => {
return !(word.startsWith("Jen") || word.endsWith("ez"));
});
console.log(nameMatch);
// expected output: Array ["asJenas", "destruction", "present", "ezJen"]
If this.state.name is a String containing multiple names with new line (\n) delimiters in it, then you can first extract an array of names from the string and then use the above code, for example:
var names = "menez\nasJenas\nbenez\ndestruction\npresent\nJenosus\nezJen"
const namesArray = names.split("\n");
const nameMatch = namesArray.filter((word) => {
return !(word.startsWith("Jen") || word.endsWith("ez"));
});
console.log(nameMatch);
// expected output: Array ["asJenas", "destruction", "present", "ezJen"]
If this.state.name is a String containing a single name, then you can use the following function, which will return true if the name does not start with "Jen" or end with "ez":
const nameMatch = (name) => {
return !(name.startsWith("Jen") || name.endsWith("ez"));
};
You can use it like so:
const nameMatch = (name) => {
return !(name.startsWith("Jen") || name.endsWith("ez"));
};
var names = "Ben";
if (nameMatch(names)) {
console.log("This name matched");
}
// expected output: "This name matched"
Please keep in mind that where I have used names, you will need to swap it to this.state.name.
You are assigning a function to the const nameMatch.
These types of functions are called fat arrow functions.
If you wanted to get the value in the nameMatch variable, you can try:
const nameMatch = (!this.state.name.match("^Jen.*") || !this.state.name.endsWith("ez"))
A simpler way of expressing the logic is:
const nameMatch = !(this.state.name.match("^Jen.*") && this.state.name.endsWith("ez"))
nameMatch is a function, so you need execute it to get the result, just call nameMatch() instead nameMatch

Firestore - Simple full text search solution

I know that firestore doesn't support full text search and it giving us solution to use third party services. However I found a simple solution to simple "full text search" and I think this might help others who doesn't want to use third party services as me for such a simple task.
I'm trying to search for company name which is saved in firestore collection under my companyName which can be in any format for example "My Awesome Company". When adding new company with companyName or updating a value in companyName I'm also saving searchName with it which is the same value as company name but in lower case without spaces
searchName: removeSpace(companyName).toLowerCase()
removeSpace is my simple custom function which remove all spaces from a text
export const removeSpace = (string) => {
return string.replace(/\s/g, '');
}
That turns our company name to myawesomecompany which is saved in searchName
Now I've got a firestore function to search for company which indexing through searchName and returning companyName. Minumum search value is a searched value without last character and maximum search value is a searched value with added "zzzzzzzzzzzzzzzzzzzzzzzz" transformed to lower case. That means if you search for My Aw then min value will be mya and max value will be myawzzzzzzzzzzzzzzzzzzzzzzz
exports.handler = ((data) => {
const searchValue = data.value.replace(/\s/g, '').toLowerCase()
const minName = searchValue.substr(0, searchName.length-1)
const maxName = searchValue + "zzzzzzzzzzzzzzzzzzzzzzzz"
let list = []
const newRef = db.collection("user").where("profile.searchName", ">=", minName).where("profile.searchName", "<=", maxName)
return newRef.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
list.push({ name: doc.data().profile.companyName})
})
return list
})
})
I didn't have time to fully test it but so far it works without any problems. Please let me know if you spot anything wrong with it. Now the question is
Is "z" character the highest value character in firestore or is there any other more decent way to add into the search value maximum amount without adding "zzzzzzzzzzzzz"?
I like your decision to preprocess the text so that it can be queried, but you could provide for a more flexible search by storing lowercase keywords with the users and searching those. In other words, transform:
"My Awesome Company"
to...
{ my: true, awesome: true, company: true }
...and test against that.
When adding/updating the property:
// save keywords on the user
let keywords = {}
companyName.split(' ').forEach(word => keywords[word.toLowerCase()] = true)
When querying:
let searchKeywords = userInputString.split(' ').map(word => word.toLowerCase())
let collection = db.collection("user")
searchKeywords.forEach(keyword => {
collection = collection.where(`keywords.${keyword}` , '==' , true);
});
With a little modification of previous answer I have made another simple text search. I'm saving keyword to an array instead of saving it in object like this
nameIndex: textIndexToArray(companyName)
where textIndexToArray is my custom function
export const textIndexToArray = (str) => {
const string = str.trim().replace(/ +(?= )/g,'')
let arr = []
for (let i = 0; i < string.trim().length; i++) {
arr.push(string.substr(0,i+1).toLowerCase());
}
return arr
}
which transfer a text into array. For example
"My Company"
will return
[m, my, my , my c, my co, my com, my comp, my compa, my compan, my company]
with nameIndex saved in firestore we can simply query the data thorough nameIndex and return companyName
exports.handler = ((data) => {
const searchValue = data.value.toLowerCase()
let list = []
const newRef = db.collection("user").where("nameIndex", "array-contains", searchValue)
return newRef.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
list.push({ name: doc.data().companyName, })
})
return list
})
})

How to validate if my list consist of same name and alert already exist?

I want to validate the name if it's already exit or not.
if Exist there should be a pop up to change the name
Here is my list of object before saving.
input change
handleStoryboardTitleChange = (e) => {
this.setState({ storyboardTitle: e.target.value });
};
save function
handleSaveButton = () => {
};
How to check if boardTitle is already exit , if exit need popup,later it should not execute flow
I usually use this
var index = boardTitlesList.findIndex((item) => {
return item.boardTitle === SEARCHED_TITLE
});
if (index === -1) {
/* NOT FOUND */
} else {
/* FOUND */
}
Here you may found polyfill for findIndex

Resources