Is there any benefit to using an object instead of several variables? - node.js

I am writing an application in nodeJS - a Facebook messenger app.
My application contains a module called strings.js, which is basically used to store common strings. Any time I need to print a greeting or whatever I pull it from the strings.js file. Strings.js looks like this:
/*
* This module exports common strings.
* */
'use strict';
module.exports = {
// Quick replies for user to choose age range
ageReplies:[
{
//Option 1 CODE
},
{
//Option 2 CODE
},
{
//Option 3 CODE
}],
// Quick replies for user to choose gender
genderReplies:[
{
//Option 1 CODE
},
{
//Option 2 CODE
},
{
//Option 3 CODE
}],
// 'greetingButtons' is used to create the buttons sent to a registered
// user during the greeting
greetingButtons: [
{
//BUTTON 1 CODE
},
{
//BUTTON 2 CODE
},
{
//BUTTON 3 CODE
}],
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
};
The first two"objects" (if that's what we can call them), "ageReplies" and "GenderReplies" are used for generating quick replies in Facebook messenger when asking user for gender and age (during user profile creation).
The next is "greetingButtons", which is used for creating buttons, which are sent to a previously registered user with a "What would you like to do next?" message.
Finally I have a number of strings for greeting the user, prompting them to enter gender and age, and so on. There will be more of these as I add them.
I have been considering putting these individual strings in an object, for example as follows:
stringData: {
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
},
Is there any benefit to doing this? Is there any point?
Another question is, if I DID use an object like this, is it possible to put my buttons and quick replies into the same object, for example as below:
stringData: {
ageReplies:[ /* Age reply code */ ],
genderReplies: [ /* Gender reply code */ ],
greetingButtons: [ /* Button code */ ],
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
},
Would this work?
EDIT: Just to clarify, I'm not talking about having an object within my main code. The object I'm talking about would be within strings.js

Generally when writing a program that involves displaying text of some sort, I store all of my copy (text eventually sent to a user) in it's own file. These blocks of text have a variable name like you've made, and that allows me to refer to them around the system.
Why do I do this? Internationalisation (commonly shortened to i18n).
It's quite common practice to pull apart text displayed to uses from the rest of your application so that you can easily create multiple files for text and load from the correct one depending on the users language settings (or locale).
In that instance, you'd have a strings file per spoken language, where variable names are all the same. You then select from the specific file depending on settings / locale.
For this reason alone, I keep all my text separate from the rest of the application. This doesn't quite work when it's HTML based projects and such, but with things like nodejs server side error messages, it works perfectly.
Personally when I've built bots, the number of options (buttons) does not relate to the text I use in anyway. So my code to create varying options happens elsewhere, but will use the strings provided by my i18n module. This way text and buttons are decoupled nicely. Often button creation happens in a function that takes some sort of array of objects which represents the options for each button, I'll then pull in the text, when creating the final button markup, from my i18n files.
On a side note: I also don't label things like a "string" prefix or suffix, referring to something as i18n.welcomeGreeting or just welcomeGreeting and I find that's more than explicit enough for this stuff.
Tl;dr
It won't make a huge difference either way right now, but decoupling your text from your button creation can render useful benefits if your application is likely to grow in the future. It can also often make it easier to work with, and separates buttons from text. After all, you don't always use the two together in chat bots, so they should probably be separate concerns.

Related

Processing \Animation in NetSuite

I have this client script which copies the line number entered in Copy line# and creates new lines from number of lines entered in Copy #Times.
This thing takes time when you increase the number of lines you require to copy. So can we give any processing animation till all the lines are set so user dont have to worry?
I have tried giving dialog.create but it didnt work. I want the animation to stay until script is executing and after that stop.
var options = {
title: 'Alert',
message: 'Processing. Please wait.',
buttons: [{
label: 'OKK...',
value: 1
},
]
};
dialog.create(options).then(success)
return (true);
success is a function I am calling.
The N/ui/dialog module is intended for showing dismissable messages, and won't really work for progress bars as you cannot hide the buttons, nor close it via code. I would recommend looking at a third party library. A very popular one is SweetAlert2, and there is some sample code on the NetSuite Professionals site for using it with NetSuite.
If you just want a quick hack, you could just used the Ext.js library that NetSuite includes by default on all pages. However I would highly recommend not doing so for any production code because NetSuite could update or remove it at any time in a future upgrade.
var messageBox = Ext.MessageBox.show({
title: 'Lines are being copied...',
msg: 'This may take a couple minutes',
wait: true,
width: 250
});
// your work here
messageBox.hide()

How should I do using multiple different two languages in NodeJs?

Can someone help me and can explain about this matter?
Currently, I'm just building a blog which I used which nodejs. In my projects, I want to use and display the two different languages which my local language and English.
As I showed up above like that website when I click change languages without showing like this example.com/mm. I'm just want to display like example.com without /mm or /en.
Example url: https://www.mmbusticket.com/
I'm not familiar with PHP. I'm the big fun of Nodejs.
How I have to do so for this case and which packages should I use for nodejs?
Thanks.
An option for you is the i18n module, and you can find similar options in many frontend frameworks as well. (You'll see this concept in app development too.)
The idea is that you have a directory with "locales" (the languages), each in a JSON file. The keys are the same in all locales. Like:
locales/en.json
{
"hello": "hello",
"greeting": "hey there, {{name}}"
}
locales/mm.json (used google translate, forgive me : )
{
"hello": "ဟယ်လို",
"greeting": "ဟေ့ဒီမှာ {{name}}"
}
In your app you'd do something like i18n.localize("hello") and depending on your current language setting (maybe passed in a cookie to the server if server-rendering, or set on the frontend page for client-side) you'll get the response.
Variables can be done above like i18n.localize(['greeting', {name: "clay"}]) and that will fill in the passed parameter name into the string defined at greeting. You can typically do nesting and other cool things, depending on the library used.
Just note that you end up using these special "key strings" everywhere, so the code is a little messier to read. Name those keys wisely : ) And if you want to translate the entire contents of your blog, that's a different service entirely.

message filter for bot's messages undefined node.js

I am having a bot set up the beginnings of a game. A human inputs the command of /startbrawl to initiate the setup of the game (creating the deck objects). But the two players need to be identified first. I have a message sent from another command that says "Player A is #[username A]. Player B is #[username B]." in the channel this game is happening in. I want the bot from this new command to look at the first message sent in the channel, which is always the "Player A is etc..." message (and is always sent by the bot) and pull both usernames from it in order to specify for this new command who is player A and who is player B. The code I have most recently (after trying multiple things) is this:
if (userInput.startsWith("!startbrawl") === true) {
message.channel.fetchMessages().then(messages => {
const botMessages = messages.filter(message => message.author.bot);
console.log(botMessages.mentions.members.first()) //this will be Player A. I'd repeat same for Player B with .last instead.
}
}
This gives me an error:
(node:15368) UnhandledPromiseRejectionWarning: TypeError: Cannot read
property 'first' of undefined.
I have made the last line be console.log(botMessages) to get all the info about the messages the filter finds. But trying to extract only part of it gives issues about not being defined, or just a result of undefined with no errors. Either way, something isn't working how I think I need it to.
The only other thing I've debated trying is exporting variables from the command prior to this new command. Player A and Player B are defined in the command used to make the channel that this new command is then used in. However, I've never had luck with exporting variables when I've used it in other instances. I use a command handler, so I'm not sure if that affects how exporting variables works... Which method would work best to set up the card game? I'm a novice in general just figuring things out as I go, so some advice (beyond take a course, look up basics, etc) is greatly appreciated. I've taken an online course for javascript and I work best figuring things out first hand.
Thanks for the help in advance!
As botMessages is a collection you wanna get a Message object out of it by doing
botMessages.first()
So try logging something like
botMessages.first().mentions.members.first()

What could cause L20N to not process the Entity variables and inclusions?

L20N is setup in my ReactJS project and I am calling getSync on the context after its ready event has fired (so things should be good to go). However, rather than my expected string including other Entity values and variable expansion, I get the raw Entity string.
The string I get looks like this:
{{$user.name}} - {{appName}}
But of course, I'm expecting something like this:
Ben Taylor - My Cool App
I have tried to recreate the problem in this plunker. Unfortunately, it works fine! When you run it, the alert box shows the expected L20N expanded string.
What could cause the Entity value to be returned raw? I have a valid context and there are no errors in inspector, so it appears all is configured fine. I'm wondering if there is some interaction with something else I'm doing that is breaking L20N. Any ideas appreciated!
I am unable to include the app I'm working on, but needless to say it has more moving parts. It is a React app based on this template.
If there is some sort of error in your .l20n file (the extension formerly known as .lol) then the getSync call will return the raw string value. In my case the error was to quote the keys in an L20n dictionary.
If you have context data like { user: { type: "Awesome" } } then the following does not work and calling getSync for useTheShout will return the unprocessed string value (including the text {{shout}}):
<shout[$user.type] {
"Awesome": "HEY AWESOME USER!",
"Loser": "i can't be bothered to shout at you loser..."
}>
<useTheShout "I'm gonna shout the following: {{shout}}">
Removing the quote marks from the dictionary key names will make this work, as follows:
<shout[$user.type] {
Awesome: "HEY AWESOME USER!",
Loser: "i can't be bothered to shout at you loser..."
}>
<useTheShout "I'm gonna shout the following: {{shout}}">
Update: You can avoid the pain by logging using the error and warning event emitters.

How can I disable javascript for the page that's being opened?

I was up till 1 am last night trying to find an example of how to do this. My theory is that I'd write a function that would comment out all javascript.
The second option would be to add the url to the list of javascript settings.
Right now my extension is very simple:
function linkOnClick(info, tab) {
window.open(info.linkUrl)
}
chrome.contextMenus.create(
{title: "Load with no Javascript", contexts:["link"], onclick: linkOnClick});
This is my first extension and I'm kind of lost.
edit: let me know if I should also post the manifest.json.
edit: I can't mark this as solved for 2 days (why? who knows.), so I'll probably not remember to mark this as solved. So accept this as the official making: SOLVED.
chrome.contentSettings.javascript.set is the thing that disables javascript.
Here's the part that disables javascript.
(Google, here's what an actual example should look like):
chrome.contentSettings.javascript.set(
{'primaryPattern':AnyDomainName, /*this is a string with the domain*/
'setting': "block", /* block the domain. Can be switched to "allow" */
'scope':'regular'}, /*it's either regular or incognito*/
function(){
/*optional action you want to
take place AFTER something's been blocked'*/
});
Here's the script I used to import into my json script for my chrome extension.
var link=""
var pattern=""
function linkOnClick(info, tab) {
r = /:\/\/(.[^/]+)/;
link=info.linkUrl
pattern="http://"+link.match(r)[1]+"/*"
chrome.contentSettings.javascript.set(
{'primaryPattern':pattern,
'setting': "block",
'scope':'regular'},
function(){
window.open(link)
});
}
chrome.contextMenus.create({title: "Load with no Javascript", contexts:["link"], onclick: linkOnClick});
I couldn't tell how any of this worked by reading the developer.chrome.com page! They really need add complete working examples or allow a way for users to add examples. I can't even use it. The git hub link is what saved me.

Resources