Discord.js | Mentioning someone in an embed - node.js

Hey im trying to make a bot which has hug commands and its meant to say you hugged a user that you mentioned, inside an embed with a random hug image...Code:
if (message.content === '+hug'){
let user = message.mentions.users.first();
let maxImageNumber = 5;
let imageNumber = Math.floor (Math.random() * (maxImageNumber - 1 + 1)) + 1;
let imageName = `${imageNumber}.gif`
let imagePath = `./hug/${imageName}`
let file = new Discord.MessageAttachment(imagePath);
let embed = new Discord.MessageEmbed();
embed.setDescription(message.author.username + ' *just hugged* '+ user.username);
embed.setImage(`attachment://${imageName}`)
embed.setColor(0xffe6f7)
message.channel.send({ files: [file], embed: embed });
}
The Error is every time I do the command nothing shows up
How would I solve this issue?
I already made a question like this but it wasn't clear enough, I hope this is clear

Your current doesn't work, because you check if the content of the message is equal to +hug. So when you send +hug #some-user, the content of the message is not equal to +huganymore. The following code will work:
if (message.content.startsWith('+hug')){
let user = message.mentions.users.first();
let maxImageNumber = 5;
let imageNumber = Math.floor (Math.random() * (maxImageNumber - 1 + 1)) + 1;
let imageName = `${imageNumber}.gif`
let imagePath = `./hug/${imageName}`
let file = new Discord.MessageAttachment(imagePath);
let embed = new Discord.MessageEmbed();
embed.setDescription(message.author.username + ' *just hugged* '+ user.username);
embed.setImage(`attachment://${imageName}`)
embed.setColor(0xffe6f7)
message.channel.send({ files: [file], embed: embed });
}
It doesn't check if the content of the message is equal to something but if it starts with something.

Try this
embed.setDescription(`${message.author.username} *just hugged* ${user.username}`);
If you want to mention the second person you just type user instead of user.username
Hope this helped

Related

Undefined username in leaderboard command [ quick.db / discord.js ]

I've tried making a leaderboard command with quick.db for my Discord.js bot but it isnt working.
It replies with undefined users and stuff like that!
var money = await db.all(`money_${message.guild.id}`, { sort: ".data" });
let resp = "";
for (let i = 0; i < money.length; i++) {
let user = client.users.cache.get(money[i].ID.split("_")[1]);
resp += `${i + 1}. ${user} - ${money[i].data}$\n`;
}
return message.channel.send(
new Discord.MessageEmbed().setAuthor(`Leaderboard`).setDescription(resp)
);
Here is the code ^^^^
Here is the output for the command
It means that money[i].ID.split("_")[1] is not a valid ID. Have you thought about logging these values in the loop to check the validity of the data you store?

TypeError: Cannot read property ' ' error with discord.js

So I have figured out how to set up a simple database with discord.js in a users.json file and my !start cmnd works to create the users database, but when me and my cousin tried the !daily cmnds, the cmnd seems to be fine but I get this error: TypeError: Cannot read property 'a number' of undefined. I believe the number refers to my user number or database number (a number means an actual long number, not "a number").
Also here is the code that goes along with this that is in my index.js file:
var UserJSON = JSON.parse(Fs.readFileSync('./DB/users.json'));
UserJSON[message.author.id] = {
bal: 0,
lastclaim: 0,
}
Fs.writeFileSync('./DB/users.json', JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have joined the economy! type !help to get started");
message.channel.send(SuccessEmbed);
return;
}
if (args[0] == "daily") {
let userJSON = JSON.parse(Fs.readFileSync('./DB/users.json'));
if (Math.floor(new Date().getTime() - UserJSON[message.author.id].lastclaim) / (1000 * 60 * 60 * 24) < 1) {
let WarningEmbed = new Discord.MessageEmbed()
WarningEmbed.setTitle("**ERROR**");
WarningEmbed.setDescription("You have claimed today already");
message.channel.send(WarningEmbed);
return;
}
UserJSON[message.author.id].bal += 500;
UserJSON[message.author.id].lastclaim = new Date().getTime();
Fs.writeFileSync('./DB/users.json', JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have claimed a daily reward of 500 coins!");
message.channel.send(SuccessEmbed);
}
}
})
Also to specify, the ./DB/users.json refers to the folder DB for database and users.json is the file that stores the databases.
Here is what the user.json file looks like:
{"*my database number*":{"bal":0,"lastclaim":0},"*my cousin's database number*":{"bal":0,"lastclaim":0}}
Is there any code I need to add into my index.js file to stop this from happening. If possible, answer as soon as possible so I can get this error worked out. Thank You!
Edit: I somehow figured this out by re-doing it and this is the finished product if anyone wants to start an economy bot:
const Discord = require("discord.js");
const client = new Discord.Client();
const Fs = require("fs");
const prefix = "!";
client.on("ready", () => {
console.log("Ready!");
});
client.on("message", async (message) => {
if(message.content.startsWith(prefix)) {
var args = message.content.substr(prefix.length)
.toLowerCase()
.split(" ");
if (args[0] == "start") {
let UserJSON = JSON.parse(Fs.readFileSync("./DB/users.json"));
UserJSON[message.author.id] = {
bal: 0,
lastclaim: 0,
}
Fs.writeFileSync("./DB/users.json", JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have joined the economy! type !help to get started");
message.channel.send(SuccessEmbed);
return;
}
if (args[0] == "daily") {
let UserJSON = JSON.parse(Fs.readFileSync("./DB/users.json"));
if (Math.floor(new Date().getTime() - UserJSON[message.author.id].lastclaim) / (1000 * 60 * 60 * 24) < 1) {
let WarningEmbed = new Discord.MessageEmbed()
WarningEmbed.setTitle("**ERROR**");
WarningEmbed.setDescription("You have claimed today already");
message.channel.send(WarningEmbed);
return;
}
UserJSON[message.author.id].bal += 500;
UserJSON[message.author.id].lastclaim = new Date().getTime();
Fs.writeFileSync("./DB/users.json", JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have claimed a daily reward of 500 discord coins!");
message.channel.send(SuccessEmbed);
}
}
})
client.login('your token');
also remember to make a DB folder with an users.json file
I realized that the problem with the code is that instead of vars, it needed to be let before the UserJSON, so the line of code should read:
let UserJSON = JSON.parse(Fs.readFileSync("./DB/users.json"));
UserJSON[message.author.id] = {
bal: 0,
lastclaim: 0,
}

How to send values using labels of a field in Protractor

Can anyone please guide me on how can I send values using the labels of the field. I'm aware of the fact that one should not send values using labels as the labels changes but in my case it's not that case, i.e it's not gonna change.
I'm attaching the HTML Code screenshots of that label and the webpage screenshot as well. WebPage Screenshot and the HTML Code Screenshot.
The only code structure I can show is in this image.Code Structure
The codes which I have tried are as below,
The From Date and To Date is one set of code I tried. So, like first From and To Date variable is one way of implementation of code, second set is some other way of implementing the code and so on.
async selectDates(FromDate:string,ToDate:string){
console.log("$$$ From and To Date in selectDates function From: "+FromDate+" To: "+ToDate);
// var fromDate = "From Date";
// await browser.element(by.xpath("//label[. = '" + fromDate + "']/following-sibling::input"));
// await fromInput.sendKeys(FromDate);
// var toDate = "To Date";
// await browser.element(by.xpath("//label[. = '" + toDate + "']/following-sibling::input"));
// await toInput.sendKeys(ToDate);
// var TmpLabelName = "From Date";
// var TmpInput = await element(by.xpath("//label[contains(text(),'" + TmpLabelName + "')]/following-sibling::input"));
// await TmpInput.sendKeys(FromDate);
// var TmpLabelName2 = "To Date";
// var TmpInput2 = await element(by.xpath("//label[contains(text(),'" + TmpLabelName2 + "')]/following-sibling::input"));
// await TmpInput2.sendKeys(ToDate);
// var TmpLabelName = "From Date";
// var TmpInput = await element(by.xpath("//label[.,'" + TmpLabelName + "']/following-sibling::input"));
// await TmpInput.sendKeys(FromDate);
// var TmpLabelName2 = "To Date";
// var TmpInput2 = await element(by.xpath("//label[.,'" + TmpLabelName2 + "']/following-sibling::input"));
// await TmpInput2.sendKeys(ToDate);
// let FlabelName = "From Date";
// var Finput = await element(by.xpath("//label[. = '" + FlabelName + "']/following-sibling::input")).sendKeys(FromDate);
// let TlabelName = "To Date";
// var Tinput = await element(by.xpath("//label[. = '" + TlabelName + "']/following-sibling::input")).sendKeys(ToDate);
}
I have searched for many articles and other answers but neither of them gave the desired answer. can anyone please help me with this, It would be really helpful!!
Edits:
The Code structure (Sorry for identation issues)
function ele(label: string){
return element.all(by.css('td > label.fieldlabel')).filter((ele)=>{
return ele.getText().then((text: string) => {
return text === label;
});
}).get(0);
}
export class Reports extends ReportObjects {
async selectDates(FromDate:string,ToDate:string){
await browser.executeScript("arguments[0].value='" + FromDate + "';", ele('From Date'));
await browser.executeScript("arguments[0].value='" + ToDate + "';", ele('To Date'));
}
async generateReport(testDataRow:number){
let fromDate = excel.getColumnValue('FromDate',testDataRow).toString();
let toDate = excel.getColumnValue('ToDate',testDataRow).toString();
await this.selectDates(fromDate,toDate);
}
}
The Excel Screenshot From/To Date
PS: I cannot use ID because that is dynamic, it's changing for different scenarios
Even we not recommend to use XPATH, but in your case we need it.
cost ele = element(by.xpath('//label[text()="From Date"]/../../input'))
await ele.sendKeys(FromDate)
// if sendKeys() can't work, try as below
await browser.executeScript("arguments[0].value=arguments[1]", ele, FromDate);
Try below solution with java script executer
const FromDate= //your from date
function ele(label: string){
return element.all(by.css('td > label.feildlabel').filter((ele)=>{
return ele.getText().then((text: string) => {
return text === label;
});
}).get(0);
}
await browser.executeScript("arguments[0].value='" + FromDate + "';", ele('From Date'));
Refer https://www.protractortest.org/#/api?view=webdriver.WebDriver.prototype.executeScript

How to avoid having “quota exceeded for 'ReadGroup'” error in google api

I've created a bot which goes in Google Spreadsheet getting some datas before sending them by DM to 50 guild members into Discord.
However, due to high requests of datas, I've got an error message saying that I've exceeded the quota for group 'ReadGroup' and limit 'USER-100s'.
To avoid getting this error, I've created a buffer function however it still doesn't work, does anyone know how to avoid getting this limit error?
Here is the main code which is launched when I type a specific commande in Discord :
const client1 = new google.auth.JWT(keys.client_email, null, keys.private_key, ['https://www.googleapis.com/auth/spreadsheets']);
const client2 = new discord.Client();
.
.
.
let valeur1 = await liste(client1);
await sleep(100000);
console.log("End of first buffering time (100s)");
for (i = 0; i < valeur1.length; i++){
if (valeur1[i] != undefined){
try{
let valeur2 = await envoi(client1, valeur1[i]);
const user = client2.users.get(String(valeur1[i])) || await client2.fetchUser(String(valeur1[i]));
console.log("Ready to send to : " + user.id);
await user.send("The character you need to improve is : " + valeur2[0] + "\n 1. " + valeur2[1] + " = " + valeur2[2] + " >>> " + valeur2[3] + "\n 2. " + valeur2[4] + " = " + valeur2[5] + " >>> " + valeur2[6] + "\n 3. " + valeur2[7] + " = " + valeur2[8] + " >>> " + valeur2[9]);
console.log("Message sent for : " + user.id);
}
catch(err){
console.error(err);
console.log("Error detected for : " + valeur1[i]);
break;
}
}
}
Here is the first function called ("liste") which return the list of the 50 members id :
async function liste(client){
const gsapi = google.sheets({version:'v4',auth: client});
let data1 = new Array();
for (i = 0; i < 50; i++) {
const opt1 = {spreadsheetId: 'XXXXXX', range: 'Serveur!C' + (3+i)};
let data2 = await gsapi.spreadsheets.values.get(opt1);
data1.push(data2.data.values);
}
return data1;
}
And here is the second function called ("envoi") which is supposed to send the DM to the 50 different members of the guild :
async function envoi(client, id){
const gsapi = google.sheets({version:'v4',auth: client});
for (i = 0; i < 50; i++){
const opt1 = {spreadsheetId: 'XXXXXX', range: 'Discord!A' + (3+i)};
let data1 = await gsapi.spreadsheets.values.get(opt1);
if (parseInt(id) === parseInt(data1.data.values)){
const opt2 = {spreadsheetId: 'XXXXXX', range: 'Discord!C' + (3+i)};
let data2 = await gsapi.spreadsheets.values.get(opt2);
const opt3 = {spreadsheetId: 'XXXXXX', range: 'Discord!D' + (3+i)};
let data3 = await gsapi.spreadsheets.values.get(opt3);
.
.
.
const opt10 = {spreadsheetId: 'XXXXXX', range: 'Discord!K' + (3+i)};
let data10 = await gsapi.spreadsheets.values.get(opt10);
const opt11 = {spreadsheetId: 'XXXXXX', range: 'Discord!L' + (3+i)};
let data11 = await gsapi.spreadsheets.values.get(opt11);
var stats = [data2.data.values,data3.data.values,data4.data.values,data5.data.values,data6.data.values,data7.data.values,data8.data.values,data9.data.values,data10.data.values,data11.data.values];
await sleep(10000);
console.log("Extraction done for " + parseInt(id));
return stats;
}
}
console.log("Member not found");
return "erreur";
}
As a result, I would like to get all the members to get their DM. However after the 18th member, an error appear, even though I put some buffering time.
In the console.log, I get :
End of first buffering time (100s)
Extraction done for 408575708424699900
Ready to send to : 408575708424699925
Message sent for : 408575708424699925
.
.
.
Extraction done for 438420776652374000
Ready to send to : 438420776652374036
Message sent for : 438420776652374036
Error: Quota exceeded for quota group 'ReadGroup' and limit 'USER-100s' of service 'sheets.googleapis.com'
.
.
.
Error detected for : 493854774446391296
This is even more strange that the error concerns a member who already have received his DM (he is one the the first 10 members in the list)
Thanks to Tanaike, I updated my code using spreadsheets.values.batchGet() method. In that way instead of extraction values by values, I extracted a batch of values.
And then I made my formula. Now I don't have any issues anymore and even better, my script is way much quicker :)

How to get the reply message without the original message from the Gmail API

I would like to get the reply message in a thread without the original message. However, when I use either Users.messages: GET or Users.threads: GET, I receive the reply (as desired) with the original message (undesired) as well. See screenshot below code.
(This question, as far as I can tell, was also posed here, however I did not find that the proposed solution answers the question and the poster of the proposed solution suggested I start a new question. I tried with Users.threads as Tholle suggests however received the same result.)
I'm a noob, so any and all help is greatly appreciated and I apologize if I'm missing something obvious.
Code
var gapiGETRequest = function (gapiRequestURL)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", gapiRequestURL, false );
xmlHttp.send( null );
return xmlHttp.responseText;
}
var gapiRequestInboxMessagesAndToken = "https://www.googleapis.com/gmail/v1/users/me/messages?q=-label%3ASENT+in%3AINBOX&access_token=" + thisToken
var allMessagesReceived = gapiGETRequest(gapiRequestInboxMessagesAndToken)
var allMessagesObject = JSON.parse(allMessagesReceived)
var messageIdsOfReceivedMessages = [];
var getIdsOfReceivedMessages = function(responseObject){
for(var i=0; i < responseObject.messages.length; i ++) {
messageIdsOfReceivedMessages.push(responseObject.messages[i].id);
}
}
var messageContentsArr = [];
var getMessageContents = function(messageIdList)
{
for(var i=0; i < messageIdList.length; i++)
{
var gapiRequestMessageWithId = "https://www.googleapis.com/gmail/v1/users/me/messages/" + messageIdList[i] + "?access_token=" + thisToken
var currentMessage = JSON.parse(gapiGETRequest(gapiRequestMessageWithId))
var encodedMessageContents = currentMessage.payload.parts[0].body.data
var decodedMessageContents = atob(encodedMessageContents.replace(/-/g, '+').replace(/_/g, '/'));
messageContentsArr.push(decodedMessageContents)
}
}
getIdsOfReceivedMessages(allMessagesObject);
getMessageContents(messageIdsOfReceivedMessages);
Response
You are getting the full reply message. When the report replied, they quoted the original message and this the text of the original is in the reply message. You may just want to do what Gmail and many other modern emails apps do and collapse/hide any reply text which begins with >.
This is my solution. It's a bit long but I tried to document it as detailed as possible.
Handles message returned by Gmail API:
https://developers.google.com/gmail/api/v1/reference/users/messages#resource
Input:
Hello. This is my reply to message.
On Thu, Apr 30, 2020 at 8:29 PM John Doe <john.doe#example.com>
wrote:
> Hey. This is my message.
>
--
John Doe
My Awesome Signature
Output:
Hello. This is my reply to message.
Code: (Unfortunately this has no syntax highlight :P)
const message = await getMessageFromGmailApi();
const text = getGoogleMessageText(message);
console.log(text, '<= AWESOME RESULT');
function getGoogleMessageText(message) {
let text = '';
const fromEmail = getGoogleMessageEmailFromHeader('From', message);
const toEmail = getGoogleMessageEmailFromHeader('To', message);
let part;
if (message.payload.parts) {
part = message.payload.parts.find((part) => part.mimeType === 'text/plain');
}
let encodedText;
if (message.payload.parts && part && part.body.data) {
encodedText = part.body.data;
} else if (message.payload.body.data) {
encodedText = message.payload.body.data;
}
if (encodedText) {
const buff = new Buffer(encodedText, 'base64');
text = buff.toString('ascii');
}
// NOTE: We need to remove history of email.
// History starts with line (example): 'On Thu, Apr 30, 2020 at 8:29 PM John Doe <john.doe#example.com> wrote:'
//
// We also don't know who wrote the last message in history, so we use the email that
// we meet first: 'fromEmail' and 'toEmail'
const fromEmailWithArrows = `<${fromEmail}>`;
const toEmailWithArrows = `<${toEmail}>`;
// NOTE: Check if email has history
const isEmailWithHistory = (!!fromEmail && text.indexOf(fromEmailWithArrows) > -1) || (!!toEmail && text.indexOf(toEmailWithArrows) > -1);
if (isEmailWithHistory) {
// NOTE: First history email with arrows
const historyEmailWithArrows = this.findFirstSubstring(fromEmailWithArrows, toEmailWithArrows, text);
// NOTE: Remove everything after `<${fromEmail}>`
text = text.substring(0, text.indexOf(historyEmailWithArrows) + historyEmailWithArrows.length);
// NOTE: Remove line that contains `<${fromEmail}>`
const fromRegExp = new RegExp(`^.*${historyEmailWithArrows}.*$`, 'mg');
text = text.replace(fromRegExp, '');
}
text = text.trim()
return text;
}
function getGoogleMessageEmailFromHeader(headerName, message) {
const header = message.payload.headers.find((header) => header.name === headerName);
if (!header) {
return null;
}
const headerValue = header.value; // John Doe <john.doe#example.com>
const email = headerValue.substring(
headerValue.lastIndexOf('<') + 1,
headerValue.lastIndexOf('>')
);
return email; // john.doe#example.com
}
function findFirstSubstring(a, b, str) {
if (str.indexOf(a) === -1) return b;
if (str.indexOf(b) === -1) return a;
return (str.indexOf(a) < str.indexOf(b))
? a
: b; // NOTE: (str.indexOf(b) < str.indexOf(a))
}
Substring the reply content alone, based on your Email id position in the full email string.
$str = "VGhhbmtzIGZvciB0aGUgbWFpbC4NCg0KT24gVHVlLCBKdWwgMTIsIDIwMjIgYXQgMjo1OCBQTSA8aW5mb0BhaXJjb25uZWN0aW5kaWEuY29tPiB3cm90ZToNCg0KPiBTLk5vIFZlbmRvciBQcm9kdWN0IEJhbmR3aWR0aCBGcm9tIExvY2F0aW9uIFRvIExvY2F0aW9uDQo-IDEgQWlydGVsIEludGVybmV0IDEwMCAyMS4xNzAyNDAxLDcyLjgzMTA2MDcwMDAwMDAxDQo-IDE5LjA0NjE5NTY4NjA2MjMxMiw3Mi44MjAyNzY0Mzc4MjA0Mw0KPg0K";
$str_raw = strtr($str, array('+' => '-', '/' => '_'));
$full_email = utf8_decode(base64_decode($str_raw));
$split_position = strpos($full_email, "your_mail_id") - 33; //33 - before that some date time available, remove those also
$final_string = substr($full_email, 0, $split_position);
echo $final_string;
Let me save your day
console.log(message.split("On")[0])
output : Hello. This is my reply to message.

Resources