I am trying to create a leaderboard command for my Discord bot and having some trouble getting the data to display, my current code only displays the top user, you can see in the image there are 4 lines, this is because there are 4 entries in the database, so it's getting the information but not displaying all the data. Could someone point out what I am doing wrong/what I would need to change to fix this. (The blocked out bits in the photos is my username)
Code:
const top10 = db
.prepare(
'SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10;',
)
.all(message.guild.id);
if (!top10) {
return;
}
for (const data of top10) {
let userNames = '';
for (let i = 0; i < top10.length; i++) {
const user = bot.users.cache.get(data.user).tag;
userNames += `\`${i + 1}\` ${user}\n`;
}
const level = `\`${data.level}\`\n`;
const xp = `\`${data.points.toLocaleString('en')}\`\n`;
const embed = new MessageEmbed()
.setAuthor(`Leaderboard for ${message.guild.name}`, message.guild.iconURL({ dynamic: true }))
.setColor(0x51267)
.addFields({ name: 'Top 10', value: userNames, inline: true },
{ name: 'Level', value: level, inline: true },
{ name: 'XP', value: xp, inline: true });
message.channel.send(embed);
return;
}
Current Output:
Desired Output:
From reading your code, I believe you made a mistake in the structuring of your code. From what it seems, your code gets the first item in top10, then adds that to the string as many times as the length of the top10 array. It then gets the level and xp for the first user, adds it to a string, then constructs this into an embed.
Here is the code revised so it should work as you intended:
let userNames = '';
let levels = '';
let xp = '';
for (let i = 0; i < top10.length; i++) {
const data = top10[i];
const user = (await bot.users.fetch(data.user)).tag;
userNames += `\`${i + 1}\` ${user}\n`;
levels += `\`${data.level}\`\n`;
xp += `\`${data.points.toLocaleString('en')}\`\n`;
}
const embed = new MessageEmbed()
.setAuthor(`Leaderboard for ${message.guild.name}`, message.guild.iconURL({ dynamic: true }))
.setColor(0x51267)
.addFields({ name: 'Top 10', value: userNames, inline: true },
{ name: 'Level', value: levels, inline: true },
{ name: 'XP', value: xp, inline: true });
message.channel.send(embed);
return;
You problem is, you just add \n to js object, so its no work.
As varian you can create 3 arrs with data, then, map db result push information to data.
And better use message.guild.members.chache.get for check if user on server, because, bot.users.cache.get(data.user).tag will return undined, after bot restart, if user don`t send any messages in handled bot channels.
const top10 = db.prepare('SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10;').all(message.guild.id);
if (!top10) {
return;
}
let usersArr = [];
let levelArr = [];
let xpArr = [];
top10.forEach(dataUser, index => {
let findUser = message.guild.members.cache.get(dataUser.user);
if (findUser) {
usersArr.push(`\`${index + 1}\` ${user.tag}`);
levelArr.push(dataUser.level);
xpArr.push(dataUser.points.toLocaleString('en'));
}
});
const embed = new MessageEmbed()
.setAuthor(`Leaderboard for ${message.guild.name}`, message.guild.iconURL({ dynamic: true }))
.setColor(0x51267)
.addFields({ name: 'Top 10', value: usersArr.join('\n'), inline: true }, { name: 'Level', value: levelArr.join('\n'), inline: true }, { name: 'XP', value: xpArr.join('\n'), inline: true });
message.channel.send(embed);
Related
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } = require('discord.js');
const fetch = require('node-fetch');
module.exports = {
data: new SlashCommandBuilder()
.setName('quiz')
.setDescription('Starts a Quiz!')
.addStringOption(option =>
option.setName('category')
.setDescription('Category of questions.')
.setRequired(true)
.addChoices(
{ name: 'History', value: '23' },
{ name: 'Arts', value: '25' },
{ name: 'Comics', value: '29' },
{ name: 'Computer', value: '18' },
{ name: 'Animals', value: '27' },
{ name: 'Films', value: '11' },
))
.addStringOption(option =>
option.setName('difficulty')
.setDescription('The difficulty of questions.')
.setRequired(true)
.addChoices(
{ name: 'Easy', value: 'easy' },
{ name: 'Medium', value: 'medium' },
{ name: 'Hard', value: 'hard' },
))
.addStringOption(option =>
option.setName('type')
.setDescription('Type of questions.')
.setRequired(true)
.addChoices(
{ name: 'Multiple Choice', value: 'multiple' },
{ name: 'True / False', value: 'boolean' },
)),
async execute(interaction) {
const category = interaction.options.getString('category');
const difficulty = interaction.options.getString('difficulty');
const type = interaction.options.getString('type');
const response = await fetch(`https://opentdb.com/api.php?amount=12&category=${category}&difficulty=${difficulty}&type=${type}`);
const data = await response.json()
var length = data.results.length;
var random = Math.floor(Math.random() * length);
let randomQuestion = data.results[random];
console.log(randomQuestion);
let question = randomQuestion.question;
const correctAnswer = randomQuestion.correct_answer;
const questionEmbed = new EmbedBuilder()
.setDescription(question)
const multipleAnswersRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('first')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('second')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('third')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('fourth')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('last')
.setLabel('Stop')
.setStyle(ButtonStyle.Danger),
);
const booleanAnswersRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('first')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('second')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('third')
.setLabel('Click me!')
.setStyle(ButtonStyle.Danger)
);
if(type == 'multiple'){
interaction.reply({embeds: [questionEmbed], components: [multipleAnswersRow]});
}
else if(type == 'boolean'){
interaction.reply({embeds: [questionEmbed], components: [booleanAnswersRow]});
}
},
};
Error -
undefined
Error executing quiz
TypeError: Cannot read properties of undefined (reading 'question')
at Object.execute (C:\Projects\Work Projects\Programmers Bot\commands\quiz.js:53:39)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Object.execute (C:\Projects\Work Projects\Programmers Bot\events\interactionCreate.js:16:4)
I as trying to make a quiz command and it had an option to choose if you want to get questions as true/false or multiple choice based, when running the commands if i run the multiple choice question, it's working perfectly and when i try true/false it gives me this error,
i have used same question variable for both type of questions.
I hope someone can help me resolve this issue.
OpenTDB categories start from 9 (General Knowledge). Supplying a category of 8 or less may lead to the following response:
{ response_code: 1, results: [] }
Where response code 1 means:
Code 1: No Results Could not return results. The API doesn't have enough questions for your query. (Ex. Asking for 50 Questions in a Category that only has 20.)
Ensure you supply a category id of 9 or higher and check for the response code
// Change category accordingly
const response = await fetch(`https://opentdb.com/api.php?amount=12&category=9&difficulty=easy`);
const data = await response.json()
if (data.response_code !== 0) throw `Error Code: ${data.response_code}`;
if (!data.results.length) throw "No Questions!";
const random = Math.floor(Math.random() * data.results.length);
const randomQuestion = data.results[random];
const { question } = randomQuestion;
const correctAnswer = randomQuestion.correct_answer;
Consider using my package "open-trivia-db" to make working with OpenTDB alot faster:
import { Category, getQuestions } from 'open-trivia-db';
const questions = await getQuestions({
amount: 50, // 1 - 50
difficulty: 'easy', // or 'medium' or 'hard'
type: 'multiple', // or 'boolean (true/false)
category: Category.allNames.SCIENCE_COMPUTERS
});
// questions[0].value and questions[0].correctAnswer
If you want to make an entire trivia game with points and leaderboards, I've also written discord-trivia
import { TriviaCommandBuilder, TriviaManager } from 'discord-trivia';
const cmd = new TriviaCommandBuilder();
const trivia = new TriviaManager({
theme: 'Red'
});
module.exports = {
data: cmd.toBuilder(),
async execute(interaction) {
const game = trivia.createGame(interaction, cmd.getOptions(interaction));
game
.start()
.catch(console.error);
},
};
For both libraries, you may need to swap the import/export syntax for require() depending on your environment setup
Other than the 3 attributes hf.EnrollmentId, hf.type and hf.Affiliation, I've created a custom attribute named email and added it as attrs:[{name: 'email', value: rahul18#gmail.com, ecert: true}] and it was successfully added to the attribute list.
In my chaincode, i'm able to get the enrollmentId by using the following command : cid.GetAttributeValue(ctx.GetStub(), "hf.EnrollmentID") but i'm not able to get the email using the same method cid.GetAttributeValue(ctx.GetStub(), "email")
Any help would be appreciated regarding why the first one is working and the second isn't
Does getAttributeValue not support custom made attributes?
Here is an example that may be helpful. A previous stackoverflow contribution helped me with a similar situation. I don't have the link for it right now, but thanks anyway.
First of all, you state that you have added attributes successfully. Here is some code as an example which I had placed in the code file for registering users.
//create user attr array
let registerAttrs = [];
let registerAttribute = {
name: "recycler",
value: config.recycler,
ecert: true,
};
registerAttrs.push(registerAttribute);
const secret = await ca.register({
affiliation: config.affiliation,
enrollmentID: config.recycler,
role: "client",
attrs: registerAttrs,
},
adminUser
);
The contract code is able to find the value of "recycler" using the following code. Of particular importance is the getCurrentUserId() function.
async getCurrentUserId(ctx) {
let id = [];
id.push(ctx.clientIdentity.getID());
var begin = id[0].indexOf("/CN=");
var end = id[0].lastIndexOf("::/C=");
let userid = id[0].substring(begin + 4, end);
return userid;}
async getCurrentUserType(ctx) {
let userid = await this.getCurrentUserId(ctx);
// check user id; if admin, return type = admin;
// else return value set for attribute "type" in certificate;
if (userid == "admin") {
return userid;
}
return ctx.clientIdentity.getAttributeValue(userid);}
The user type returned from the getCurrentUserType function is subsequently examined further up in the contract code, as shown in the following example.
async readTheAsset(ctx, id) {
let userType = await this.getCurrentUserType(ctx);
const buffer = await ctx.stub.getState(id);
const asset = JSON.parse(buffer.toString());
asset.userType = userType;
asset.userID = ctx.clientIdentity.getID();
if (asset.userType === "recycler") {
throw new Error(`The record cannot be read by ${asset.userType} `);
}
return asset;}
I feel sure that this code should solve your issue, as there is a lot of similarity.
const updateObj = {
enrollmentID : userName,
type:'client',
affiliation:'' ,
attrs: [{name: 'email', value: email, ecert: true}, {name: 'orgId', value: orgId, ecert: true}, {name: 'userId', value: userName, ecert: true}] ,
}
const response = await identityService.update(userName, updateObj ,adminUser)
const clientUser = await provider.getUserContext(userIdentity, userName);
const reenrollment = await caClient.reenroll(clientUser,
[{
name: 'email',
optional: false
},
{
name: 'orgId',
optional: false
},
{
name: 'userId',
optional: false
}
]);
I have a script that is triggering a search when a field is changed. The goal is that if the search finds a result to alter the user that this may be a possible duplicate. The issue I am having is that if there are more than 1 result it will show the alert as many times as there are results. How can I have it show the result only once?
/**
*#NApiVersion 2.0
*#NScriptType ClientScript
*/
define(['N/record', 'N/search', 'N/ui/dialog'], function(r, search, u) {
function fieldChanged(context) {
var recCurrent = context.currentRecord;
var show = recCurrent.getValue({
fieldId: 'custrecord_eym_er_show'
});
var client = recCurrent.getValue({
fieldId: 'custrecord_eym_er_customer'
});
if ((context.fieldId == 'custrecord_eym_er_customer')) {
var client = recCurrent.getValue({
fieldId: 'custrecord_eym_er_customer'
});
console.log(client);
var sv = search.create({
type: "customrecord_eym_exhibit_reg",
columns: [
search.createColumn({
name: "internalid",
label: "Internal ID"
})
],
filters: [
["custrecord_eym_er_show", "anyof", show],
"AND",
["custrecord_eym_er_customer", "anyof", client]
]
});
var pagedData = sv.runPaged({
pageSize: 1000
});
// iterate the pages
for (var i = 0; i < pagedData.pageRanges.length; i++) {
// fetch the current page data
var currentPage = pagedData.fetch(i);
// and forEach() thru all results
currentPage.data.forEach(function(result) {
// you have the result row. use it like this....
var duplicate = result.getValue('internalid');
console.log(duplicate);
if (duplicate) {
alert('There is more than 1 entry for this client')
}
});
}
}
}
return {
fieldChanged: fieldChanged
};
});
You can change:
var pagedData = sv.runPaged({
pageSize: 1000
});
To
var pagedData = sv.run().getRanged({
start: 0,
end:1
});
The variable pagedData is an array contains the result, if you have many duplication you will have only the First result.
Also another way you can simply introduce a variable to print it once like this:
var printOnce = 0;
for (var i = 0; i < pagedData.pageRanges.length; i++) {
// fetch the current page data
var currentPage = pagedData.fetch(i);
// and forEach() thru all results
currentPage.data.forEach(function(result) {
// you have the result row. use it like this....
var duplicate = result.getValue('internalid');
console.log(duplicate);
if (duplicate && printOnce==0) {
printOnce++;
alert('There is more than 1 entry for this client')
}
});
}
I think the first approach is better since you don't need to retrieve all the data.
Try using a summary level grouping on the saved search results. Ex: If you're getting multiple internal ids, where 0 mean no duplicates, and 1+ means duplicates try changing
columns: [
search.createColumn({
name: "internalid",
label: "Internal ID"
})
],
to
columns: [
search.createColumn({
name: "internalid",
label: "Internal ID",
summary: 'GROUP'
})
],
And change
var duplicate = result.getValue('internalid');
to
var duplicate = result.getValue(name: 'internalid', summary: 'GROUP');
If I assumed incorrectly about the use of internal ids, add "Customer" or the desired grouped value as a column and use the summary grouping on that field.
There is a way to get the number of results returned by a search, in your case it seems you just want to show an alert of the search return at least one result so, you can use this code:
/**
*#NApiVersion 2.0
*#NScriptType ClientScript
*/
define(['N/record', 'N/search', 'N/ui/dialog'], function(r, search, u) {
function fieldChanged(context) {
var recCurrent = context.currentRecord;
var show = recCurrent.getValue({
fieldId: 'custrecord_eym_er_show'
});
var client = recCurrent.getValue({
fieldId: 'custrecord_eym_er_customer'
});
if ((context.fieldId == 'custrecord_eym_er_customer')) {
var client = recCurrent.getValue({
fieldId: 'custrecord_eym_er_customer'
});
console.log(client);
var sv = search.create({
type: "customrecord_eym_exhibit_reg",
columns: [
search.createColumn({
name: "internalid",
label: "Internal ID"
})
],
filters: [
["custrecord_eym_er_show", "anyof", show],
"AND",
["custrecord_eym_er_customer", "anyof", client]
]
});
if(sv.runPaged().count >= 1) {
alert('There is more than 1 entry for this client');
}
}
}
return {
fieldChanged: fieldChanged
};
});
For some reason this code below is not sending a embed to the reports channel tried what i could to fix it it will not send tried client.channels.cache.get(Channel).send(embed); that gave me a error tried it multipole ways and it still won't send
const Discord = require("discord.js");
module.exports = {
name: 'report',
usage: '%report <reason>',
description: 'reports a person',
async execute(client, message, args) {
let user = message.mentions.users.first() || await message.guild.members.cache.get(args[0])
if (!user) return message.reply(`Please mention a user to report`)
let reason = args.slice(1).join(" ")
if (!reason) return message.reply(`Please enter a reason`)
let Avatar = user.displayAvatarURL();
let Channel = client.channels.cache.find(c => c.name == 'reports')
if (!Channel) return message.reply(`Thier is no Valid channel to send a report please contact a staff member`)
const embed = new Discord.MessageEmbed()
.setTitle('New Report')
.setDescription(`The member ${message.author.tag} has reported ${user.tag}`)
.setColor("RED")
.setThumbnail(Avatar)
.addFields({
name: "Member ID,",
value: `${message.author.id}`,
inline: true
}, {
name: "Member Tag,",
value: `${message.author.tag}`,
inline: true
}, {
name: "Reported ID,",
value: `${user.id}`,
inline: true
}, {
name: "Reported Tag,",
value: `${user.tag}`,
inline: true
}, {
name: "Reason,",
value: `${reason}`,
inline: true
})
client.channels.cache.get(Channel);
message.channel.send(`Successfully sent the report!`)
}
}
function findChannel(client, channelName) {
var channelId = client.channels.cache.find(c => c.name.toLowerCase().includes(channelName.toLowerCase())).id;
}
Try
let Channel = message.guild.channels.cache.find(c => c.name == 'reports')
if (!Channel) return message.reply(`Thier is no Valid channel to send a report please contact a staff member`)
Channel.send(embed)
message.channel.send(`Successfully sent the report!`)
I'm struggling with a script that is supposed to:
Search for a list of Customer's
Get a couple of Field Values, one of which is used in the next Search, the other is the ID
Search for a list of Custom Records, the criteria being one of the fields I just fetched
Get a field value
And use the Customer ID fetched earlier to assign the Custom Record field value to a Custom field on the Customer.
But it is dropping out on the second search, saying that it is returning "undefined" due to invalid Search Criteria. I'm assuming that the field I get from the first search is not working in the Criteria of the second search?
My code is below - is it an obvious one (as usual), or is it literally the wrong way to go about this?
/**
*#NApiVersion 2.x
*#NScriptType ScheduledScript
*/
define(['N/search'],
function getShipSuburbId(search) {
function execute() {
var customerSearchObj = search.create({
type: "customer",
filters:
[
["custentity_store_shipping_suburb","isnotempty",""]
],
columns:
[
search.createColumn({
name: "entityid"
}),
search.createColumn({name: "custentity_store_shipping_suburb"})
]
});
var custSearchResult = customerSearchObj.runPaged({pageSize: 1000});
log.debug({title: "customerSearchObj result count", details: custSearchResult.count});
var custNumPages = custSearchResult.pageRanges.length;
var custAllResults = [];
var i = 0;
while (i < custNumPages) {
custAllResults = custAllResults.concat(custSearchResult.fetch(i).data);
i++;
}
return custAllResults;
for (var j = 0; j < custAllResults.length; j++) {
var currentRecord = custAllResults[j].getValue({
name: "entityid"
});
var shipSub = custAllResults[j].getValue({
name: "custentity_store_shipping_suburb"
});
};
var shipSubIdSearch = search.create({
type: "customrecord_suburb",
filters:
[
["name","is",shipSub]
],
columns:
[
search.createColumn({
name: "internalid",
summary: "MAX",
label: "Internal ID"
})
]
});
var allSubIdResults = shipSubIdSearch.runPaged({pageSize: 1});
log.debug({title: "shipSubIdSearch result count", details: allSubIdResults.count});
var subNumPages = custSearchResult.pageRanges.length;
var subAllResults = [];
var m = 0;
while (m < subNumPages) {
subAllResults = subAllResults.concat(allSubIdResults.fetch(m).data);
m++;
}
return subAllResults;
for (var k = 0; k < subAllResults.length; k++) {
var shipSubId = subAllResults[k].getValue({
name: "internalid"
});
};
var setSuburbId = currentRecord.setValue({
fieldId: 'custentity_shipping_suburb_id',
value: shipSubId
});
return setSuburbId;
}
return {
execute : execute
};
});
NEW CODE BELOW
/**
*#NApiVersion 2.x
*#NScriptType ScheduledScript
*/
define(['N/search', 'N/record'],
function getShipSuburbId(search, record) {
function execute() {
var customerSearchObj = search.create({
type: "customer",
filters:
[
["custentity_store_shipping_suburb", "isnotempty", ""]
],
columns:
[
search.createColumn({
name: "entityid"
}),
search.createColumn({name: "custentity_store_shipping_suburb"})
]
}); // The first search, which draws a list of Customers
var custSearchResult = customerSearchObj.runPaged({pageSize: 1000}); // Run paged
log.debug({title: "customerSearchObj result count", details: custSearchResult.count});
var custNumPages = custSearchResult.pageRanges.length;
var custAllResults = [];
var i = 0;
while (i < custNumPages) {
custAllResults = custAllResults.concat(custSearchResult.fetch(i).data);
i++;
}
for (var j = 0; j < custAllResults.length; j++) {
var currentRecord = custAllResults[j].getValue({
name: "entityid"
});
var shipSub = custAllResults[j].getValue({
name: "custentity_store_shipping_suburb"
});
log.debug({title: "currentRecord", details: currentRecord});
log.debug({title: "shipSub", details: shipSub});
// I've left this "for" operation open for the next search - possible issue?
var shipSubIdSearch = search.create({
type: "customrecord_suburb",
filters:
[
["name", "is", shipSub]
],
columns:
[
search.createColumn({
name: "internalid",
summary: "MAX",
label: "Internal ID"
})
]
}); // Second search. This should only return one result each time it is run
var subIdRun = shipSubIdSearch.run();
log.debug({title: "subIdRun result count", details: subIdRun.count});
var shipSubId = subIdRun.each(
function (result) {
log.debug({
title: "Fetch ID",
details: result.getValue({name: "internalid"})
})
return true;
});
log.debug({title: "shipSubId result", details: shipSubId});
var myRecord = record.load({
type: 'customer',
id: currentRecord
}); // Load the Customer record, based on the id fetched in the first search
log.debug({title: "myRecord", details: myRecord});
myRecord.setValue({
fieldId: 'custentity_shipping_suburb_id',
value: shipSubId
}); // And set the value of the Custom field, based on value from second search
}
}
return {
execute : execute
};
});
And screenshot of Execution Log on New Script:
I tried to edit some of your code to get your closer to the answer. I've left comments explaining steps you'll need to take.
Try this and let me know how it goes!
/**
*#NApiVersion 2.1
*#NScriptType ScheduledScript
*/
define(['N/search', "N/record"], function (search, record) {
function execute() {
let customers = [];
let storeShippingSuburbIds = [];
let storeShippingSuburbId;
let searchCustomers = search.create({
type: "customer",
filters:
[
["custentity_store_shipping_suburb", "isnotempty", ""]
],
columns:
[
search.createColumn({name: "entityid"}),
search.createColumn({name: "custentity_store_shipping_suburb"})
]
});
var pagedData = searchCustomers.runPaged({pageSize: 1000});
pagedData.pageRanges.forEach(function (pageRange) {
let page = pagedData.fetch({index: pageRange.index});
page.data.forEach(function (result) {
customers.push([
result.getValue({name: "entityid"}),
result.getValue({name: "custentity_store_shipping_suburb"})
])
storeShippingSuburbIds.push(result.getValue({name: "custentity_store_shipping_suburb"}));
return true;
});
});
/*
* I think you want the search operator of anyof here.
*/
search.create({
type: "customrecord_suburb",
filters:
[
["name", "anyof", storeShippingSuburbIds]
],
columns:
[
search.createColumn({
name: "internalid",
summary: "MAX",
label: "Internal ID"
})
]
}).run().each(function (result) {
storeShippingSuburbId = result.getValue(result.columns[0]);
});
/*
* You'll need to use record.load() here or record.submitFields(), depending on a few things.
* But, it won't work as it is because it doesn't know what the "current record" is.
*/
let myRecord = record.load();
myRecord.setValue({
fieldId: 'custentity_shipping_suburb_id',
value: storeShippingSuburbId
});
myRecord.save();
}
return {
execute: execute
};
});
I have found the best way to approach multiple levels of searching, is to gather the results of each search into an array.
Once I have finished dealing with the results of one search, then process each element of the array one by one, whether that be searching, querying, editing, etc.
The advantages of this include:
If a scheduled script, this allows me to check the governance usage after the first search, and reschedule with the array of results as a parameter if necessary.
Handling other logic like sorting or formulas on the array elements, before continuing with other operations.
Potentially faster processing, particularly if you don't need to process any further operations on some results of the first search.
This is just personal preference, but it makes it easier to split elements of the script into separate functions and maintain readability and logical sequence.