"invalid authentication credentials" when using SetInterval with google API - javascript

I have a discord bot taking every message on a specific channel (you can type only once on it).
For each message, I put the message on a spreadsheet.
To minimize google API calls on my spreadsheet, I've implemented this :
I'm checking how many users wrote per minute.
If 10 or less : I'm calling my updatesheet function = working perfectly.
If 11 or more : I'm delaying the call with a setInterval (I took care to delay not more than 10per minute in the future aswell) = not working
I get this error message :
message: 'Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.
which I do not understand since I'm using the exact same updatesheet function :
async function update(placeId,authorId,adressId,pointsNumber,tokensWon) {
await doc.useServiceAccountAuth({
client_email: creds.client_email,
private_key: creds.private_key,
});
await doc.loadInfo(); // loads document properties and worksheets
let sheetdailyPoints = doc.sheetsByIndex[1];
var date = new Date();
const year = date.getFullYear()
const month = `${date.getMonth() + 1}`.padStart(2, "0")
const day = `${date.getDate()}`.padStart(2, "0")
const stringDate = [day, month, year].join("/")
const rowPointsAdded = await sheetdailyPoints.addRow({
Date: stringDate,
AuthorId: authorId,
Place: placeId,
Adress: adressId,
Points: pointsNumber
});
let sheetTokensXP = doc.sheetsByIndex[3];
const rows2 = await sheetTokensXP.getRows();
var addedTokensXP = false;
let = length = rows2.length;
for(let i = 0; i < length; i++){
if(rows2[i].Adress == adressId) {
if(rows2[i].Points!='')
rows2[i].Points = parseInt(rows2[i].Points)+parseInt(pointsNumber);
else
rows2[i].Points = parseInt(pointsNumber);
rows2[i].XP = parseInt(rows2[i].XP)+200;
rows2[i].Tokens = parseInt(rows2[i].Tokens)+parseInt(tokensWon);
await rows2[i].save();
addedTokensXP=true;
return rows2[i].Tokens;
}
}
if (addedTokensXP == false) {
const rowAdded3 = await sheetTokensXP.addRow({
Adress: adressId,
Points: pointsNumber,
Tokens: tokensWon,
XP: 200
});
await rowAdded3.save();
return tokensWon;
}
}
The main function:
const prevMap = new Map();
for (i=0; i<61; i++) {
prevMap.set(i,0);
}
async function updateSheets(message,currentMin,ladderNumber,placeId,authorId,adressId,pointsNumber,tokensWon) {
if(currentMin === prevMin) {
nbUpdateAtMin = prevMap.get(currentMin);
nbUpdateAtMin++;
if(nbUpdateAtMin>10) {
let nbMinAdded = 0;
let foundPlaceAtMin;
let foundPlace = false;
for (i=currentMin+1; foundPlace; i++) {
if (prevMap.get(i) < 11 ) {
foundPlaceAtMin = i;
foundPlace = true;
}
}
nbMinAdded = foundPlaceAtMin-currentMin;
setInterval(function() {riddle.update(placeId,authorId,adressId,pointsNumber,tokensWon)},nbMinAdded*60000);
let value = prevMap.get(currentMin+nbMinAdded);
prevMap.set(currentMin+nbMinAdded,value+1);
}
else {
let value = prevMap.get(currentMin);
prevMap.set(currentMin,value+1);
riddle.update(placeId,authorId,adressId,pointsNumber,tokensWon);
}
}
else {
prevMap.set(prevMin,0);
let value = prevMap.get(currentMin);
prevMap.set(currentMin,value+1);
prevMin = currentMin;
riddle.update(placeId,authorId,adressId,pointsNumber,tokensWon)
}
}

Related

how to use trim in fetch url

how to retrieve the verif code, here I try to do the next regex using trim but an error message appears "TypeError: Cannot read properties of undefined (reading 'trim')"
and I just want to fetch the verification code, like in the image
my code
const checkInboxUrl = 'https://getnada.com/api/v1/inboxes/';
const getMessageUrl = 'https://getnada.com/api/v1/messages/html/';
const refreshMailboxUrl = 'https://getnada.com/api/v1/u/';
/* eslint-disable no-unused-vars */
class Getnada {
constructor() {
this.email = '';
this.verificationCode = '';
}
async getEmail(email = 'urmxhbwrz#getnada.com') {
this.email = email;
return this;
}
async getMailbox(pattern, sleepTime = 5000) {
await sleep(sleepTime);
const timestamp = Math.floor(new Date().getTime() / 1000);
const refreshMailboxResponse = await fetch(refreshMailboxUrl + this.email + '/' + timestamp);
const checkInboxResponse = await fetch(checkInboxUrl + this.email);
const checkInboxJson = await checkInboxResponse.json();
const getMessageResponse = await fetch(getMessageUrl + checkInboxJson.msgs[0].uid);
const readInbox = await getMessageResponse.text();
const regex = new RegExp(pattern);
const verificationCodeMatch = regex.exec(readInbox);
this.verificationCode = verificationCodeMatch[1].trim();
console.log(verificationCodeMatch)
return this;
}
}
const getnada = new Getnada();
async function main() {
console.log((await getnada.getEmail()))
console.log((await getnada.getMailbox()))
}
main();
https://getnada.com/api/v1/messages/html/8lra5CwOQcHvja3mpQZgO7G5RPTS3W
To retrieve the verification code, you can try to change this lines :
const regex = new RegExp(pattern);
const verificationCodeMatch = regex.exec(readInbox);
this.verificationCode = verificationCodeMatch[1].trim();
to :
const verificationCodeMatch = pattern.exec(readInbox);
this.verificationCode = verificationCodeMatch[0].trim();
And change this line too :
console.log((await getnada.getMailbox()))
to :
console.log((await getnada.getMailbox(/\b\d{6,6}\b/)));
This regex /\b\d{6,6}\b/ will filter out strings containing exactly 6 digits of numbers which is the verification code.

How to get xmlhttprequest results in a for loop

Good day all,
Please i'm trying to get the latency values of a ping using xmlhttprequest in a for loop for five consecutive latencies that will be stored in an global array in a react native application, after which when the for loop finishes, other codes can now execute, but it seems that the whole code just runs through without getting the array values from the initial for loop and the final result comes out as 0, then later, I start getting the array values due to the result of the xmlhttprequest. How can I ensure that I get the latency results first before now executing the remaining code. My code is below:
let latencies = [];
class App extends Component {
startScan = () => {
this.setState({
scanning: true,
});
this.getJitter();
}
getPing = () => {
var request = new XMLHttpRequest();
var startTime = new Date();
request.open(
'GET',
'http://dummy.restapiexample.com/api/v1/employees',
true,
);
request.send();
request.onreadystatechange = (e) => {
if (request.readyState == 4 && request.status == 200) {
var endTime = new Date();
var ping = endTime.getTime() - startTime.getTime();
this.setState({ping: ping});
latencies.push(ping);
console.log('ping:', ping);
console.log(latencies);
return ping;
}
};
};
getJitter = () => {
for(var i=0; i<5; i++){
this.getPing();
}
//Get each latency difference
var total1 = 0;
for (var i = 0; i < latencies.lenght; i++) {
if (typeof latencies[i] === 'number') {
console.log(latencies[i]);
total1 += latencies[i + 1] - latencies[i];
console.log(total1);
}
}
var jitter = total1 / (latencies.length - 1);
console.log(jitter); //this comes out as 0
latencies = [];
};
render() {
return (
...
<Button title="Scan" onPress={this.startScan} />
)
};
}
Thanks
Tim
The problem is that the XMLHttpRequest is asynchronous and will allow other code to run while it is trying to fetch the resource. The solution to this is to await each request and then move on to the next block.
I've switched the XMLHttpRequest for the Fetch API. fetch returns a Promise which you can await and wait for it to finish.
class App extends Component {
startScan = () => {
this.setState({
scanning: true,
});
this.getJitter().then(() => {
this.setState({
scanning: false,
});
});
}
getPing = async () => {
const startTime = new Date();
await fetch('http://dummy.restapiexample.com/api/v1/employees');
const endTime = new Date();
const ping = endTime.getTime() - startTime.getTime();
this.setState({ ping });
return ping;
}
getJitter = async () => {
const latencies = [];
for (let i = 0; i < 5; i++){
const ping = await this.getPing();
latencies.push(ping);
}
//Get each latency difference
let total1 = 0;
for (let i = 0; i < latencies.length; i++) {
if (typeof latencies[i] === 'number') {
console.log(latencies[i]);
total1 += latencies[i + 1] - latencies[i];
console.log(total1);
}
}
const jitter = total1 / (latencies.length - 1);
console.log(jitter); //this comes out as 0
};
render() {
return (
<Button title="Scan" onPress={this.startScan} />
)
}
}

How do I make it such that the user gets xp only once per minute, instead of once per message?

I am working on the leveling system of my discord bot. I want to make it such that the user gets xp only once per minute, no matter how many messages are sent. I can't figure it out and need some help. I tried adding a cooldown but nothing works.
This is the xp code:
bot.on("message", async message => {
if (!message.guild) return;
if (message.author.bot) return;
const args = message.content.slice(PREFIX.length).split(" ");
const cmd = args.shift().toLowerCase();
let randomXp = Math.floor(Math.random() * 9) + 1;
const hasLeveledUp = await Levels.appendXp(message.author.id, message.guild.id, randomXp);
if (hasLeveledUp)
{
const user = await Levels.fetch(message.author.id, message.guild.id);
message.channel.send(`You leveled up to level ${user.level}!`);
}
if(cmd === "rank")
{
const user = await Levels.fetch(message.author.id, message.guild.id);
message.channel.send(`You are currently level **${user.level}**!`)
}
if(cmd === "lb")
{
const rawLeaderboard = await Levels.fetchLeaderboard(message.guild.id, 5);
if (rawLeaderboard.length < 1) return reply(" Nobody's in the leaderboard yet..");
const leaderboard = Levels.computeLeaderboard(bot, rawLeaderboard);
const lb = leaderboard.map(e => `${e.position}. ${e.username}#${e.discriminator}\nLevel: ${e.level}\nXP: ${e.xp.toLocaleString()}`);
message.channel.send(`${lb.join("\n\n")}`)
}
})
I use that but it needs jsonfile and random
var stats = {};
if(fs.existsSync('stats.json')) {
stats = jsonfile.readFileSync('stats.json');
}
if(message.author.bot) return;
if(!message.guild) return;
if(message.guild.id in stats === false){
stats[message.guild.id] = {};
}
const guildstats = stats[message.guild.id];
if(message.author.id in guildstats === false){
guildstats[message.author.id] = {
xp: 0,
level: 0,
last_message: 0,
};
}
const userstats = guildstats[message.author.id];
if(Date.now() - userstats.last_message > 60000) {
userstats.xp += Random.int(15, 25);
userstats.last_message = Date.now();
jsonfile.writeFileSync('stats.json', stats);
const xptonextlevel = 5 * Math.pow(userstats.level, 2) + 50 * userstats.level + 100;
if(userstats.xp >= xptonextlevel) {
userstats.level++;
userstats.xp - userstats.xp - xptonextlevel;
message.reply('Has reached level ' + userstats.level)
}
}

Issues with request, and cheerio when web-scraping

I'm trying to write a code that makes a request to a website, for webscraping
So this are the steps:
Here First part of Code STARTS
The program makes the request to the mainURL
The program selects some objects from the html of the mainURL, and store them in an array of objects(advert), on of the properties of the object, is it's link, which we'll call numberURL, that the code automatically selects using a css selector, the amount of objects is something like 80-90;
The program makes requests to every numberURL(80-90 requests),
and for each of them it does set another properties to the same object, and selects another link, that we'll call accountURL
The program creates an CSV file where it writes every object in different rows
Here First part of Code ENDS
So actually the first part works pretty good, it doesn't have any issues, but the second part does
Here Second part of Code STARTS
The program makes requests to every accountURL from the previous object
The program selects some objects from the html of the accountURL, and stores them in an another array of another objects(account), also using CSS selectors
The program should console.log() all the account objects
Here Second part of Code ENDS
But the second part does have some bugs, because when console.logging the objects we see that the objects properties doesn't changed their default value.
So in debugging purposes I took one advert object and putted it's value manually from the code
post[0].link = 'https://999.md/ru/profile/denisserj'
Finally when running the code for this object it actually works correctly, so it shows the changed properties, but for the rest of them it doesn't.
I tried to set some Timeouts, thinking that the code tries to read the link, before the second request finished, but no effects
I also tried to console.log the link, to see if it exists in the array, so it actually exists there, but also no effect.
Finally here is the code:
// CLASSES
class advert {
constructor() {
this.id = 0;
this.tile = new String();
this.link = new String();
this.phone = new String();
this.account = new String();
this.accountLink = new String();
this.text = new String();
this.operator = new String();
}
show() {
console.log(this.id, this.title, this.link, this.phone, this.account, this.accountLink, this.text, this.operator);
}
}
class account {
constructor() {
this.name = 0;
this.createdAt = 0;
this.phone = [];
this.ads = [];
this.adsNumber = 0;
}
show() {
console.log(this.name, this.createdAt, this.phone, this.ads, this.adsNumber);
}
}
// HEADERS
const mainRequest = require('request');
const auxRequest = require('request');
const cheerio1 = require('cheerio');
const cheerio2 = require('cheerio');
const fs = require('fs');
const fs2 = require('fs');
const adFile = fs.createWriteStream('anunturi.csv');
const accFile = fs2.createWriteStream('conturi.csv');
// SETTINGS
const host = 'https://999.md'
const category = 'https://999.md/ru/list/transport/cars'
const timeLimit = 60; //seconds
// VARIABLES
let post = [];
let postNumber = 0;
let acc = [];
// FUNCTIONS
function deleteFromArray(j) {
post.splice(j, 1);
}
function number(i) {
let category = post[i].link;
auxRequest(category, (error, response, html) => {
if (!error && response.statusCode == 200) {
const $ = cheerio1.load(html);
let phone;
const siteTitle = $('strong').each((id, el) => {
phone = $(el).text();
});
const txt = $('.adPage__content__description').html();
const person = $('.adPage__header__stats').find('.adPage__header__stats__owner').text();
const linkToPerson = host + $('.adPage__header__stats').find('.adPage__header__stats__owner').find('a').attr('href');
post[i].phone = phone;
post[i].account = person;
post[i].accountLink = linkToPerson;
post[i].text = txt;
if (i == postNumber) {
console.log('1. Number Putting done')
writeToFileAd(accountPutter, writeToFileAccount);
}
}
});
}
function writeToFileAd() {
adFile.write('ID, Titlu, Link, Text, Cont, LinkCont, Operator\n')
for (let i = 0; i <= postNumber; i++) {
adFile.write(`${post[i].id}, ${post[i].title}, ${post[i].link}, ${post[i].phone}, ${post[i].account}, ${post[i].accountLink}, ${post[i].operator}\n`);
}
console.log('2. Write To File Ad done')
accountPutter();
}
function accountAnalyzis(i) {
let category = post[i].link;
const mainRequest = require('request');
category = category.replace('/ru/', '/ro/');
mainRequest(category, (error, response, html) => {
if (!error && response.statusCode == 200) {
const $ = cheerio2.load(html);
const name = $('.user-profile__sidebar-info__main-wrapper').find('.login-wrapper').text();
let createdAt = $('.date-registration').text();
createdAt = createdAt.replace('Pe site din ', '');
const phones = $('.user-profile__info__data').find('dd').each((id, el) => {
let phone = $(el).text();
acc[i].phone.push(phone);
});
const ads = $('.profile-ads-list-photo-item-title').find('a').each((id, el) => {
let ad = host + $(el).attr('href');
acc[i].ads.push(ad);
acc[i].adsNumber++;
});
acc[i].name = name;
acc[i].createdAt = createdAt;
console.log(name)
if (i == postNumber) {
console.log('3. Account Putting done')
writeToFileAccount();
}
}
});
}
function writeToFileAccount() {
for (let i = 0; i <= postNumber; i++) {
accFile.write(`${acc[i].name}, ${acc[i].createdAt}, ${acc[i].phone}, ${acc[i].ads}, ${acc[i].adsNumber}\n`);
}
console.log('4. Write to file Account done');
}
function numberPutter() {
for (let i = 0; i <= postNumber; i++) {
number(i);
}
}
function accountPutter() {
for (let i = 0; i <= postNumber; i++) {
accountAnalyzis(i);
}
}
// MAIN
mainRequest(category, (error, response, html) => {
let links = [];
for (let i = 0; i < 1000; i++) {
post[i] = new advert();
}
for (let i = 0; i < 1000; i++) {
acc[i] = new account();
}
if (!error && response.statusCode == 200) {
const $ = cheerio2.load(html);
const siteTitle = $('.ads-list-photo-item-title').each((id, el) => {
const ref = host + $(el).children().attr('href');
const title = $(el).text();
post[id].id = id + 1;
post[id].title = title;
post[id].link = ref;
links[id] = ref;
postNumber = id;
});
post[0].link = 'https://999.md/ru/profile/denisserj'
numberPutter()
}
});
You have an error in line
const siteTitle = $('.ads-list-photo-item-title').each((id, el) => {
What you actually want is .find('a').each...

Node is not returning the correct JSON response

I have an object here which I want to return as a response but before that I want to add a couple of fields to it. When I add fields and print the object, it prints the new object but when I send the response, I still get old object before editing.
let applications = await ApplicationHandler.getApplicationOverview(application_id); //I want to edit this one
if (applications == null) {
applications = [];
}
for (let i = 0; i < applications.length; i++) {
let cube_application_id = applications[i].id;
let application_ratings = await Application_Rating.findAll({where: {cube_application_id: cube_application_id}});
let application_ratings_personal = await Application_Rating.findAll({
where: {
cube_application_id: cube_application_id,
user_id: req.user.id
}
});
let total_user_rating = 0;
for (let rating of application_ratings) {
let average_user_rating = (rating.personality_rating + rating.qualification_rating + rating.motivation_rating) / 3;
total_user_rating = total_user_rating + average_user_rating;
}
applications[i].average_rating = total_user_rating / application_ratings.length;
applications[i].recommended = application_ratings_personal.recommended;
if (i == applications.length - 1) {
console.log(applications); // this prints with those 2 fields.
let successRes = {
status: 200,
data: applications
};
return successRes; //however, this returns the one which I had in the first line.
}
}

Categories

Resources