Build a re-usable error message convertor - javascript

I work on a project where we receive error messages from the backend. Sometimes the error messages are not frontend friendly. We are doing some work to tidy these up, but in the meantime I created a function that takes the error message and replaces any values.
I want to make the function re-usable for other error messages and wondered if anyone has any advice.
Here is the function with 1 error message currently.
Error message entered: 'Minimum payment_amount is $10.'
Error message being returned: 'Minimum payment amount is $10.'
const errorMessageConvertor = (errorMessage) => {
if (errorMessage !== undefined) {
const convertedErrorMessage = errorMessage.toString();
return convertedErrorMessage.replace("payment_amount", "payment amount");
}
};

Maybe something like that
const errorMessageConvertor = (errorMessage, keyToReplace, valueToReplace) => {
if (errorMessage !== undefined) {
const convertedErrorMessage = errorMessage.toString();
return convertedErrorMessage.replace(keyToReplace, valueToReplace);
}
};
// usage
errorMessageConvertor('Minimum payment_amount is $10.','payment_amount','payment amount')

If you only want to get rid of underscores then this should solve the problem, it will replace all the underscores with spaces.
const errorMessageConvertor = (errorMessage) => {
if (errorMessage !== undefined) {
const convertedErrorMessage = errorMessage.toString();
return convertedErrorMessage.replaceAll('_', ' ');
}
};

Related

Basic comparison statement in javascript

So I'm trying to run a comparison statement with the firebase SDK.
I've got a function which checks if the phone number or email has a valid invite value / document exists within the database.
I want to add a comparison that says if the invitationData is valid and the claimedDate value is not equal to the data type null or the invitationData is valid and the string value is not equal to null then alert invitation not confirmed. The problem I'm having is with the || or operator I can only seem to get this comparison to work if I'm just doing one argument when I add the or it stops working.
async function checkInvitation(email = '', phone = '') {
try {
let snapshot = firebase.firestore().collection(COLLECTIONS.INVITATIONS);
if (email) {
snapshot = snapshot.where('email', '==', email);
} else if (phone) {
snapshot = snapshot.where('phone', '==', phone);
}
let invitationData = await snapshot.get();
if (!invitationData || invitationData.docs.length === 0) {
Alert.alert(
'Invitation not confirmed',
'Please try again or join our waiting list.',
);
return false;
}
if ((invitationData && invitationData.docs[0].data().claimedDate !== null) || (invitationData && invitationData.docs[0].data().claimedDate != "somestring")) {
Alert.alert(
'Invitation not confirmed',
'This invitation has already been used',
);
return false;
}
return invitationData.docs[0].id;
} catch (error) {
console.log(error);
throw new Error(error);
}
}
If you shorten it (excuse the pseudo nature) it looks as follows :
if (claimedDate !== null || claimedDate != "somestring")
I'm pretty sure that's not what you are meaning. Perhaps you are intending an AND?

condense if, else JS with similar condition rules

trying to find a way to condense this. wasnt sure of the best way to do it. basically if criteria is met i display an alert with a parameter that is the message. i was thinking of maybe trying it in function. this is part of a larger function react component. i was also thinking if i could find a way to condense the else if's i could use a ternary. thanks in advance for the assistance.
const handleUpdatePassword = () => {
const allFilled = !reject(passwords).length;
const passwordsMatch = newPassword === conPassword;
const isDifferent = curPassword !== newPassword;
const meetsPasswordRequirements = validatePassword();
const usesName = isUsingName();
const usesUserID = isPartOfUserID();
const isValidPassword = meetsPasswordRequirements && isDifferent;
if (allFilled) {
if (!isDifferent) {
Alert.alert(difPassWord);
} else if (!passwordsMatch) {
Alert.alert(noMatch);
} else if (!meetsPasswordRequirements) {
Alert.alert(pasReqs);
} else if (usesName || usesUserID) {
Alert.alert(pasName);
}
} else {
Alert.alert(fieldNotComplete);
}
if (isValidPassword) {
changePasswordPost(
{
userId,
curPassword,
newPassword
},
partyId
);
}
};
You can create an array of objects for your validation rules, each containing a function which returns a boolean indicating whether that validation passes, and a string with the error message to display.
Then loop over the rules array and alert the message for the first rule that returns false. If they all return true, do the post.
You can split each if statement into a function, then chain them. For example
// here we make a closure to validate, and return a Promise
// condition can be a function
const validate = (condition, error) => ()=> new Promise((res, rej)=>{
if(condition()){
res();
}else{
rej(error);
}
});
const handleUpdatePassword = () => {
const validateFieldsComplete = validate(
()=>!reject(passwords).length,
fieldNotComplete
);
const validateDifPassword = validate(
()=> curPassword !== newPassword,
difPassWord
);
// ...
validateFieldsComplete()
.then(validateDifPassword)
.then(...)
.catch(Alert.alert)
}
It would be much cleaner with pipe. You can take a look at ramda. Or if you are intrested in functional way, you might consider using Monad.
I'd recommend DRYing up the Alert.alert part since all branches have that in common, and just come up with an expression that evaluates to the alert message. Compactness isn't always everything, but if you want it, then nested conditional operators can fit the bill. I'm also rearranging your conditions so that it can be a flat chain of if/elses:
const message
= reject(passwords).length ? fieldNotComplete
: curPassword === newPassword ? difPassWord
: newPassword !== conPassword ? noMatch
: !validatePassword() ? pasReqs
: (isUsingName() || isPartOfUserID()) ? pasName
: null;
const isValid = !message;
if (!isValid) {
Alert.alert(message);
}
(feel free to use any other sort of code formatting pattern; nested conditionals always look awkward no matter which pattern you use, IMO.)
Edit:
Also inlined conditionals which will short-circuit evaluation and make it even more compact.
I'd setup a validations object that has the tests and error messages and then loop over it. If validation fails, it'll throw the last validation error message. Using this method, you only have to maintain your tests in one place and not mess with a block of conditional statements.
const handleUpdatePassword = () => {
const validations = {
allFilled: {
test() {
return newPass && oldPass
},
error: 'Must fill out all fields'
},
correct: {
test() {
return curPass === oldPass
},
error: 'Incorrect password'
},
[...]
}
const invalid = () => {
let flag = false
for (let validation in validations) {
if (!validations[validation].test()) {
flag = validations[validation].error
}
}
return flag
}
if (invalid()) {
Alert.alert(invalid())
} else {
changePasswordPost(
{
userId,
curPass,
newPass
},
partyId
)
}
}
hi everyone this was the method i used for a solution
const messages = [
{
alertMessage: difPassWord,
displayRule: different()
},
{
alertMessage: noMatch,
displayRule: match()
},
{
alertMessage: pasReqs,
displayRule: validatePassword()
},
{
alertMessage: pasName,
displayRule: !isUsingName() || !isPartOfUserID()
}
];
if (allFilled) {
const arrayLength = messages.length;
for (let i = 0; i < arrayLength; i++) {
if (messages[i].displayRule === false) {
Alert.alert(messages[i].alertMessage);
}
}

How to fix ReferenceError

After some modification, instead of message is not defined, it is receivedMessage.channel.bulkdelete(args[0].then (() => {
ReferenceError: receivedmessage is not defined. I am not really sure myself what does that mean because im new to node.js and javascript. If there is any mistakes I made please tell me!
client.on('message', (receivedMessage) => {
if (receivedMessage.author == client.user) { // Prevent bot from responding to its own messages
return
}
if (receivedMessage.content.startsWith("?")) {
processCommand(receivedMessage)
}
})
function processCommand(receivedMessage) {
let fullCommand = receivedMessage.content.substr(1) // Remove the leading exclamation mark
let splitCommand = fullCommand.split(" ") // Split the message up in to pieces for each space
let primaryCommand = splitCommand[0] // The first word directly after the exclamation is the command
let arguments = splitCommand.slice(1) // All other words are arguments/parameters/options for the command
console.log("Command received: " + primaryCommand)
console.log("Arguments: " + arguments) // There may not be any arguments
if (primaryCommand == "help") {
helpCommand(arguments, receivedMessage)
} else if (primaryCommand == "multiply") {
multiplyCommand(arguments, receivedMessage)
} else if(primaryCommand == "clear") {
clearCommand(arguments, receivedMessage)
} else {
receivedMessage.channel.send("I don't understand the command. Try `?help`, `?multiply` or '?clear'")
}
function helpCommand(arguments, receivedMessage) {
if (arguments.length > 0) {
receivedMessage.channel.send("It looks like you might need help with " + arguments + ".Try `!multiply 2 4 10` or `!multiply 5.2 7`")
} else {
receivedMessage.channel.send("I'm not sure what you need help with. Try `?help [topic]`")
}
}
function multiplyCommand(arguments, receivedMessage) {
if (arguments.length < 2) {
receivedMessage.channel.send("Not enough values to multiply. Try `!multiply 2 4 10` or `!multiply 5.2 7`")
return
}
let product = 1
arguments.forEach((value) => {
product = product * parseFloat(value)
})
receivedMessage.channel.send("The product of " + arguments + " multiplied together is: " + product.toString())
}
}
function clearCommand (arguments, receivedMessage) {
if (!recievedMessage.member.hasPermission("MANAGE_MESSAGES"))
return receivedmessage.reply("You have no permission to use this command.Sad.");
if (!args[0])
return receivedMessage.channel.send("Please specify a number.")
}
receivedmessage.channel.bulkDelete(args[0]).then(() => {
receivedMessage.channel.send(`Cleared ${args[0]} messages.`).then(msg => msg.delete(5000));
}
,)
You need to use receivedMessasge instead of message, as thats the name you choose in that function.
It kinda seems like you dont really have much experience and I would recommend you to read the offical discord.js guide: https://discordjs.guide . It will teach you how to write Discord Bots without needing to copy a lot of weired stuff into your Code!
1) You have defined receivedMessage instead of messsage
2) The code for clear command is not in any function and it executes once, before any messages.
You need to use receivedMessage instead of message and insert the code in the processCommand function
if (primaryCommand == "help") {
helpCommand(arguments, receivedMessage)
} else if (primaryCommand == "multiply") {
multiplyCommand(arguments, receivedMessage)
} else if(primaryCommand == "clear") {
if (!message.member.hasPermission("MANAGE_MESSAGES")) return message.reply("You have no permission to use this command.Sad.");
if (!args[0]) return message.channel.send("Please specify a number.")
message.channel.bulkDelete(args[0]).then(() => {
message.channel.send(`Cleared ${args[0]} messages.`).then(msg => msg.delete(5000));
});
// or create a function for this command
} else {
receivedMessage.channel.send("I don't understand the command. Try `?help` or `?multiply`")
}

Error: Unexpected Identifier When using an eval command

Ok, so I follow a youtube video on how to make an Eval command (source code: https://github.com/MenuDocs/Discord.JS-Tutorial/blob/Episode-21/commands/owner/eval.js )and in their video they can just do eval message.author.id and bam it works. Whereas in my bot it appears with an error in chat: Error while evaluating: Unexpected identifier ( https://imgur.com/a/1NWuWEy *note i use 2 'a's to keep it separate from my the bot online, reducing duplicate messages).
case 'evaal':
const args = message.content.substring(PREFIX.length).trim().split(" ");
const ownerID = '285198963722944514';
if(message.author.id == ownerID) {
try {
let toEval = args.join(" ")
let evaluated = inspect(eval(toEval, { depth: 0 }));
if (!toEval) {
return message.channel.send("Error while evaluating: \`cannot evaluate air\`!");
} else {
let hrStart = process.hrtime()
let hrDiff;
hrDiff = process.hrtime(hrStart);
return message.channel.send(`*Executed in ${hrDiff[0] > 0 ? `${hrDiff[0]}s ` : ''}${hrDiff[1] / 1000000}ms.*\n\`\`\`javascript\n${evaluated}\n\`\`\``, { maxLength: 1900 })
}
} catch (e) {
return message.channel.send(`Error while evaluating: \`${e.message}\``)
}
} else {
return message.reply('You are not allowed to use this command. (Owner Only)').then(m => m.delete(5000))
}
break;
As linked above in the imgur image, the bot responds but only with the error message. I expect it to tell me the author's id of the message (me).

Javascript, why would "this" be undefined in a bound node callback?

I'm encountering this error for the first time and I'm at a loss of what could cause it.
AccountController.create = function () {
var password = this.param('password'),
confirmPassword = this.param('confirmPassword'),
account = new Account(),
errorMessage = "",
errors = "",
error,
errorCount;
if (password !== confirmPassword) {
this.req.flash('warning', 'passwords do not match');
return this.redirect(this.urlFor({action: 'index'}));
}
account.email = this.param('email');
account.set('password', password);
account.name.first = this.param('name.first');
account.name.last = this.param('name.last');
account.access = this.param('access');
account.save(function (err, account, numberAffected) {
if (err) {
console.log("THIS: " + this);
errorMessage = "";
errors = err.errors;
if (!errors) {
errors = [{message: "There is already an account with this email address."}];
}
errorCount = errors.length;
for (error = 0; error < errorCount; error = error + 1) {
if (typeof errors[error] === "string") {
errorMessage += errors[error].message + " ";
}
}
this.req.flash('warning', errorMessage);
return this.redirect(this.urlFor({action: 'index'}));
}
return this.redirect(this.urlFor({controller: "profile", action: 'login'}));
}).bind(this);
};
I'm hoping that there's no additional code required to make the example work.
Console output (running via nodemon) looks like this:
THIS: undefined
/Users/crispensmith/Documents/cinchedStore/Site/app/controllers/account_controller.js:68
this.req.flash('warning', errorMessage);
^
TypeError: Cannot read property 'req' of undefined
You're doing .bind(this) on the return value of account.save, not the function you're passing into it. Just move the bind inside the bracket;
account.save((function // ... possibly also use an extra parenthesis
// ...
}).bind(this)); // to make the bind target more obvious?

Categories

Resources