Google Apps Script phone numbers from AD - javascript

I’m trying to create a script in Google Apps Script that gets users' phone numbers from AD and copies them into Google Sheets.
try {
if(user.phones[0].type = 'home'){
prop.push(user.phones[0].value);
}
if (user.phones[1].type = 'mobile'){
prop.push(user.phones[1].value );
}
if(user.phones[2].type = 'work'){
prop.push(user.phones[2].value);
}
else{
prop.push('');
}
}
catch(err){
prop.push('');
}
Now that does work, but it puts numbers in unwanted cell order. It seems to type: ‘work’ ‘home’ ‘mobile’. Also, if the user does not have 3 of those numbers, so f.e. Only ‘mobile’, this script puts it first where ‘work’ should be. I was hoping this code would put them in a specific cell order: ‘home’, ‘mobile’, ‘work’. Any ideas?

Instead of = use ===
The first two if hasn't and else. If you don't want misplaced data, then you should add else{ prop.push(''); } after each of them.
Regarding the order, you might have to create an Array of empty strings and replace the one that corresponds to each phone type by the corresponding value.
The following example uses Array.prototype.forEach and switch instead of several if
const prop = new Array(4).fill('');
user.phones.forEach(phone => {
switch(phone.type){
case 'home':
prop[0] = phone.value;
break;
case 'work':
prop[1] = phone.value;
break;
case 'mobile':
prop[2] = phone.value;
break;
default: // This will manage other phone types
prop[3] = prop[3].length === 0 ? phone.value : [prop[3], phone.value].join(',');
}

Related

Is there a way for my manual special case if statement look more pretty and cleaner?

I have a website where some of the Titles have been translated to my country's language.
Because of that, when I match with worldwide data API, it'll not match (just some cases) due to API title is using in English name, so I tried the if statement to translate some "specific case" back into English, but it looks really long and doesn't feel organized well, I think I should put it into 1 other .JS file and just add more special case to that file only for the scalable purpose. But how can I do that and make sure to classify all the cases correctly?
Pardon me if this is an already answered question somewhere, but I don't know the keyword of it.
This is an example of my code:
static async titleInfo() {
//- Some codes here
//- ...
//- Make URL slug becomes a Title
let slugMod = animeSlug.replace(/-/g, " ").toString()
// Special case that doesn't correct due to country language, have to do manually.
if (slugMod == "vua hai tac") {
slugMod = "One Piece"
}
if (slugMod == "su mang than chet") {
slugMod = "Bleach"
}
if (slugMod == "nanatsu no taizai that dai toi") {
slugMod = "Nanatsu no Taizai"
}
if (slugMod == "hoi phap su") {
slugMod = "Fairy Tail"
}
if (slugMod == "vua phap thuat 2021") {
slugMod = "SHAMAN KING (2021)"
}
if (slugMod == "hunter x hunter") {
slugMod = "HUNTER×HUNTER (2011)"
}
//
//- Ending code
}
An object indexed by search string whose values are the string to replace it with would work.
const titles = {
'vua hai tac': 'One Piece',
'su mang than chet': 'Bleach',
'nanatsu no taizai that dai toi': 'Nanatsu no Taizai',
// etc
};
const slugWithSpaces = animeSlug.replace(/-/g, " ");
const correctedTitle = titles[slugWithSpaces] || slugWithSpaces;
If you have a lot of these, yes, consider a separate file.
If you have a lot and you see the need to add even more exceptions quite frequently, and manually editing the source code seems too error-prone, you could make yourself a little app (like with Electron) that would let you copy-paste titles into a page, which then updates the data that your script uses with a button.
You could try something similar to Jump table , It can be implemented like this
const handleSpecialCase =
{
'vua hai tac' : 'One Piece',
'su mang than chet' : 'Bleach',
'nanatsu no taizai that dai toi' : 'Nanatsu no Taizai'
}
handleSpecialCase[specialCase]();
You could also store this in an another file and then import it, will make your code cleaner! Hope it helps

cli input parsing for node.js

i am trying to make a CLIish server in node.js.
but I need a way to parse a string and run a function from an object.
what I mean is... I don't want to nest a million switch statements just to have the commands I need.
using 2 other StackOverflow answers, I got 1 part done. inputs.
now i just need to figure out how to figure ou where the command stops and the input begins.
example:
inputting do say user:Yimmee msg:"well hello" "something random":yes
I need to separate do say and the inputs.
this is what i started with, but I do not know how to finish it.
function command(command, usable){
//usable is the object holding the commands that can be used.
//here I set commandMain to the part of command that is the command
/*and where commandInput is too. and I'm not forcing you,
but is preferably to be converted to an object.*/
var commandSplit = [];
do{
var match = (/[^ "]+|"([^"]*)"/gim).exec(commandMain);
if(match != null){
commandSplit.push(match[1] ? match[1] : match[0]);
}
}while (match != null);
var reach = `usable`;
commandSplit.forEach((to, nu)=>{
if(nu === commandSplit.length - 1){
reach += `["_${to}"]`;
}else{
reach += `["${to}"]`;
}
});
console.log(reach);
try{
return eval(reach)(commandInputs);
}catch(error){
return false;
}
}
Note I gave up a little, there will be some ridiculous errors.
big fat edit::::::::::::::::::::::L:::::::
idk how in the world process.argv works, and looking in one of the answers, i know how to set it.
but i am using a live websocket for this.
Unless this is an exercise, I'd strongly recommend not to implement your own command and argument parser. Use one of the existing libraries. A quick web search for "node cli library" yields a lot of results, including comparisons.
The libraries range from tiny and simple like minimist, very popular ones like yargs or commander, to heavier ones like oclif.
I'd also recommend checking the Command-line utilities section of Sindre Sorhus' Awesome Node.js list.
What you are doing is passing options and arguments to a program. You can use process.argv to get these.
It's always good to have useful error messages and command line documentation. Hence, if you're distributing to users, a more robust library for this purpose is worth an extra dependency. Widely used is yargs, see their website at https://www.npmjs.com/package/yargs for some examples.
If you want to do it using the basic process.argv, here's a solution:
This is your command in a format most people are used to: node some.js --user Yimmee --msg "well hello" --random
And the implementation
let arguments = process.argv.slice(2); // this removes `node` and the filename from arguments list
console.log(arguments)
switch (arguments[0]) { // check that `say` is the first "command"
case 'say':
let options = process.argv.slice(3); // get the stuff after `say`
let optionsObject = {} // key-value representation
if (options.indexOf("--user") != -1) { // if it exists
optionsObject.user = options[options.indexOf("--user")+1]
}
else {
// you can throw an error here
}
if (options.indexOf("--msg") != -1) { // if it exists
optionsObject.msg = options[options.indexOf("--msg")+1]
}
if (options.indexOf("--random") != -1) { // if it exists
optionsObject.random = true
}
console.log(optionsObject) // you can use optionsObject for your program
break;
default:
console.log("Invalid command");
}
EDIT: If this is happening inside the code as a function call, you can adapt above code:
function test(argsString) {
let arguments = argsString.split(/ (?=(?:(?:[^"]*"){2})*[^"]*$)/); // split the string into an array at the spaces
// ^ regex from https://stackoverflow.com/questions/23582276/
console.log(arguments)
switch (arguments[0]) { // check that `say` is the first "command"
case 'say':
let options = arguments.slice(1); // get the stuff after `say`
let optionsObject = {} // key-value representation
if (options.indexOf("--user") != -1) { // if it exists
optionsObject.user = options[options.indexOf("--user") + 1]
}
else {
// you can throw an error here
}
if (options.indexOf("--msg") != -1) { // if it exists
optionsObject.msg = options[options.indexOf("--msg") + 1]
}
if (options.indexOf("--random") != -1) { // if it exists
optionsObject.random = true
}
console.log(optionsObject) // you can use optionsObject for your program
break;
default:
console.log("Invalid command");
}
}

how to check: if array includes specific text properly?

I am struggling with doing an array search that includes a piece of text that must include back slashes in it. I have tried includes(''); negating includes(''); and also trying similar using indexOf('').
I have a simple array, with at maximum four values; typically it has two, here is how it typically looks:
{tks: Array(2)}
tks: Array(2)
0: "https://mycoolwebsite.net/arcgis/rest/services"
1: "https://mycoolwebsite.com/arcgis/rest/services"
length: 2
__proto__: Array(0)
__proto__: Object
Here are the simple checks I'm trying to do: My second check with *includes* 'wdt' text seems to be working so I assume it's something with the backslashes. Anyway I can handle this? I'm perplexed why my if and else both get hit with the first check below using back slashes... I added the negating on the else to double check.. with and without that in the else, else is always hit.
// right before doing the search I am building the array, just to add more context
for (let i = 0; i < coolObj.length; i++) {
if (coolObj[i].url){
tr = coolObj[i].url;
tks.push(tr);
console.log({tks});
}
}
console.log({tks}); // consoles as I have included above ^
if (tks.includes('/arcgis/rest/services')) {
console.log({tks});
} else if (!tks.includes('/arcgis/rest/services')) {
console.log({tks});
console.log('does not include correct url');
aT = '/arcgis/rest/services';
lP = false;
filterAt(aT);
}
if (tks.includes('wdt')) {
console.log({tks});
}else {
console.log({tks});
wT = 'wdt';
filterWt(wT);
}
From the MDN docs: The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.
You have to test the strings using String.prototype.includes within the array elements thus:
const arr = ["https://mycoolwebsite.net/arcgis/rest/services", "https://mycoolwebsite.com/arcgis/rest/services"];
arr.forEach(el => {
if (el.includes('/arcgis/rest/services')) {
console.log(el, ': includes url');
}
else {
console.log('does not include correct url');
}
if (el.includes('wdt')) {
console.log(el, ': includes wdt');
} else {
console.log('does not include correct wdt');
}
});

Making a Discord Bot in JavaScript: Attempting to make a game of wordchain between two players

The user that uses a particular command 'shiritori' and tags another user will be player1. The tagged user will be player2. I have already downloaded a JSON file with most dictionary words so firstly and I have tested it here and it appeared to be successful:
let usedWords = []
let points = 0
function shiritoriCommand(arguments, receivedMessage) {
let word = receivedMessage.content.substr(11)
fs.readFile('./words_dictionary.json', 'utf8', (err, jsonString) => {
if (err) {
console.log("Error reading file from disk:", err)
return
}
try {
const dictionary = JSON.parse(jsonString)
if (word in dictionary && !(usedWords.includes(word)) && word.length >= 4) {
points = points + word.length
receivedMessage.channel.send('The word is in the dictionary! You have a total of ' + points + ' points!')
usedWords.push(word)
} else {
receivedMessage.channel.send('Either the word is not in the dictionary, it is too short or it has already been used. You gain no points.')
}
} catch(err) {
console.log('Error parsing JSON string:', err)
}
})
}
The current program takes in the received message and separates the word with the substr(). Then it reads the dictionary to see if the word is found in there. If it is, it pushes the word into the array of used words so it cannot be used again to gain points. The points are the word length (which has to be 4 or more otherwise it will be disregarded.) The total is shown when a valid word is used.
However, I am finding it challenging to incorporate 2 players into it. I was inspired by the Pokecord duel, how does one differentiate between the two players' words and what exactly must be done? I initially arranged it like this:
let player1 = receivedMessage.author
let player2 = receivedMessage.mentions.members.first()
On top of that, I want each player to have a 15 second timeslot. The game stops when either player has 200 points. Now I can manage that with a while loop:
points1 = 0
points2 = 0
while (points1 <= 200 || points2 <= 200) {
/* Do I use set interval and duplicate the first function for each player
and assign their respective points */
}
If they do not answer by then, then the turn goes to the next player. I have no clue how to combine all of this to make a valid game.
You'll need to figure out a way to keep track of which player's turn it is. In this case you could use a boolean, as there are only two players. If you want the game to be more extensible, you'll obviously need to use a different logical check.
In this case, if
(player1Turn === true) {
// do some stuff
}
Of course this is just one way to handle it

Overwriting a key, if it exists, in a key/value array

I'm allowing users to highlight rows in a table by clicking them.
When they click them, HighToggle() is called.
HighToggle() checks to to see if the bgcolor of the td matches the highlighter color and either highlights or un-highlights.
function HighToggle(cObj,vid,vColor,hColor) {
if ((vColor == hColor)) {
$(cObj).css('background-color','#FFFFFF'); // un-highlight
vx.push({'id' : vid, 'status' : 'off'});
} else {
$(cObj).css('background-color','#' + Highlighter.Hex); // highlight
vx.push({'id' : vid, 'status' : 'on'});
}
}
It is important that I store these in an array, because I have recordset navigation that deletes the rows (from view) and loads in new rows via JSON. Otherwise, when I wanted to submit the data to the server, I could just loop through table rows and build the array pre-submit.
So, that works fine, except that it adds duplicate id's in the case of each time something is highlighted or un-highlighted, so it might look like:
1: on, 7: on, 7: off, 2: on, 4: on, 1: off, 3: on, 1: on, 2: off.
Which is just a mess.
Following the same click process that results in that array above, what I'd like to end up with is..
1: on, 7: off, 2: off, 4: on, 3: on
Rows never interacted with (5, 6, 8, 9, 10 if the result set only had 10 rows), need not have an entry in the array at all.
I'm looking for a fast way to search my array and override rows if they exist.
I have thought of one solution that I haven't tried to implement yet because I feel like there might be something better.
I could make a separate array, let's say it's called vindexes. Vindexes could use the ID passed as the vid variable like so..
vindexes[vid] = vx.length;
HighToggle could check to see if vindexes[vid] exists, and if so, use that id to override rather than vx.push.
It would work (wouldn't it?) but is it reinventing the wheel? Is there a faster way? This function will be used a lot on each page.
I've found the grep function, since I'm using jQuery, but I don't think grep is applicable to me here since I want to know the index of where the ID was found.
Thank you for any advice.
Edit: Here's what I devised myself, though I think that the answer is a more elegant and sensible solution.
function HighToggle(cObj,vid,vColor,hColor) {
vid = Number(vid);
if (!(vid in vi)) {
inIndex = vx.length;
} else {
inIndex = vi[vid];
}
if ((vColor == hColor)) {
$(cObj).css('background-color','#FFFFFF');
vi[vid] = inIndex;
vx[inIndex] = {'id' : vid, 'status' : 'off'};
} else {
vi[vid] = inIndex;
$(cObj).css('background-color','#' + Highlighter.Hex);
vx[inIndex] = {'id' : vid, 'status' : 'on'};
}
}
My solution, and the answer are both effective for my use, but perhaps someone else will run into this situation and benefit from the code I've provided.
You could use an object:
var vx = {};
function HighToggle(cObj,vid,vColor,hColor) {
if ((vColor == hColor)) {
$(cObj).css('background-color','#FFFFFF'); // un-highlight
vx[vid] = "off";
} else {
$(cObj).css('background-color','#' + Highlighter.Hex); // highlight
vx[vid] = "on";
}
}
Then if you need an array later (for submitting to server, etc):
var vxArray = [];
for (var key in vx) {
vxArray.push({id: key, status: vx[key]});
}

Categories

Resources