API host's rate-limit header not read properly - javascript

Here is my code (not the entire code, but I think this is the only really relevant part):
const timer = ms => new Promise(resolve => setTimeout(resolve, ms));
const createThrottler = (limitHeader) => {
let requestTimestamp = 0;
let rateLimit = 0;
return (requestHandler) => {
return async (...params) => {
const currentTimestamp = Number(Date.now());
if (currentTimestamp < requestTimestamp + rateLimit) {
const timeOut = rateLimit - (currentTimestamp - requestTimestamp);
requestTimestamp = Number(Date.now()) + timeOut;
await timer(timeOut)
}
requestTimestamp = Number(Date.now());
const response = await requestHandler(...params);
if (!rateLimit > 0) {
rateLimit = Math.floor((60 / response.headers.get(limitHeader)) * 1000);
}
console.log(limitHeader);
console.log(rateLimit);
return response;
}
}
}
const throttle = createThrottler("X-***-Ratelimit");
const throttleFetch = throttle(fetch);
function getRelease(idFiltered) {
return throttleFetch(`https://api.***.com/releases/${idFiltered}`, {
headers: {
'User-Agent': '***/0.1',
},
}).then(response => response.json())
.then(data => {
if (data.message === 'Release not found.') {
return { error: `Release with ID ${idFiltered} does not exist` };
} else {
const id = data.id;
const delimiter = document.getElementById("delimiter").value || "|";
const artists = data.artists ? data.artists.map(artist => artist.name) : [];
const barcode = data.identifiers.filter(id => id.type === 'Barcode')
.map(barcode => barcode.value);
var formattedBarcode = barcode.join(delimiter);
const country = data.country || 'Unknown';
const genres = data.genres || [];
const formattedGenres = genres.join(delimiter);
const labels = data.labels ? data.labels.map(label => label.name) : [];
const formattedLabels = labels.join(delimiter);
const catno = data.labels ? data.labels.map(catno => catno.catno) : [];
const formattedCatNo = catno.join(delimiter);
const styles = data.styles || [];
const formattedStyles = styles.join(delimiter);
const tracklist = data.tracklist ? data.tracklist
.map(track => track.title) : [];
const formattedTracklist = tracklist.join(delimiter);
const year = data.year || 'Unknown';
const format = data.formats ? data.formats.map(format => format.name) : [];
const qty = data.formats ? data.formats.map(format => format.qty) : [];
const descriptions = data.formats ? data.formats
.map(descriptions => descriptions.descriptions) : [];
const preformattedDescriptions = descriptions.toString()
.replace('"', '""').replace(/,/g, ', ');
const formattedDescriptions = '"' + preformattedDescriptions + '"';
console.log(idFiltered,
artists,
format,
qty,
formattedDescriptions,
formattedLabels,
formattedCatNo,
country,
year,
formattedGenres,
formattedStyles,
formattedBarcode,
formattedTracklist
)
return [idFiltered,
artists,
format,
qty,
formattedDescriptions,
formattedLabels,
formattedCatNo,
country,
year,
formattedGenres,
formattedStyles,
formattedBarcode,
formattedTracklist
];
}
});
}
But the "X-***-Ratelimit" header is clearly not being read correctly, as when I do
console.log(limitHeader);
console.log(rateLimit);
I initially get back
object
and thereafter
X-***-Ratelimit
Infinity
From the host's documentation:
We attach the following headers to responses to help you track your rate limit use:
X-***-Ratelimit: The total number of requests you can make in a one minute window.
X-***-Ratelimit-Used : The number of requests you’ve made in your existing rate limit window.
X-***-Ratelimit-Remaining: The number of remaining requests you are able to make in the existing rate limit window.
Any help please? TIA.
Edit: amazingly, I managed to greatly increase the rate-limit by getting my app authenticated thusly:
headers: {
'User-Agent': '***/0.1',
'Authorization': '*** key=***, secret=***',
},
However, I just took the key and secret from the site documentation, and I now get back this JSON response:
message - "Invalid consumer key/secret. Please register an app before making requests."
Edit2: OK, I worked out how to register my app now. I'm proceeding to further tests.
Edit3: the rate-limit in effect from the host is much better now, but my app is still not reading the header from the response correctly, so limitHeader is still coming back as "Infinity", instead of some meaningful/appropriate value.

Related

Convert iterative function to recursive kind using javascript

I have written a function to pull stream data from the fetch API. I want to convert the function to a recursive one and would like to write it as an async function.
Here is the code which works but not asynchronous:
const productsStream = async () => {
const request = {
searchRange: ['fragrance', 'perfumery', 'cologne'],
exclusionCategory: ['discounted']
}
const response = await fetch('/products/stream', {
method: 'POST',
body: JSON.stringify(request)
});
const decoder = new TextDecoderStream();
const reader = response.body.pipeThrough(decoder).getReader();
let line = "";
while (true) {
const { done, value } = await reader.read();
let chunk = remainder + value;
let products = []
let newlineIndex;
while ((newlineIndex = chunk.indexOf("\n")) != -1) {
let item = chunk.substring(0, newlineIndex);
chunk = chunk.substring(newlineIndex);
if (chunk.length > 1) chunk = chunk.substring(1);
}
line = chunk;
products = []
if ( done ) break;
}
}
I'd welcome any help in converting this.

Incomplete response received from application Error

I am doing a virtual pos integration, in the second part of the step, I have to post the data I received from the user to the specified field, for this I had to get some information from the database, I am pulling data with 2 different intertwined queries, and then I am posting the data, but I am getting an error:
Incomplete response received from application
const reqUrl = 'https://onlineodeme.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx?prmstr='
Server.getAllData('paytr') // get data from paytr collection
.then((result) =>{
var uniqueId = req.body.VerifyEnrollmentRequestId.split(',')[0]
var uniqueId2 = req.body.VerifyEnrollmentRequestId
var newUniqueId = new Date().getTime()
var uyeNumarasi = encryptedData.decrypt(result[0].merchant_id) //merchant
var uyeSifresi = encryptedData.decrypt(result[0].merchant_salt)//merchant
var teminalNo = encryptedData.decrypt(result[0].merchant_key)//merchant
var amountResult = req.body.PurchAmount / 100
const amount = amountResult + '.00'
var resBrandName = '300' // troy
if(req.body.Pan.startsWith('4') ){resBrandName = '100'} //visa
if(req.body.Pan.startsWith('5') ){resBrandName = '200'} // mastercard
var resCreditCardNumber = req.body.Pan
var ResCurrencyCode = req.body.PurchCurrency
var resExpiryData = req.body.Expiry
var clientIp = 'xx.xxx.xx.xx' //req.body.SessionInfo.ipAdress
var CAVV = req.body.Cavv
var eci = req.body.Eci
Server.findPayments(parseInt(uniqueId))// get data by unique id
.then((data) =>{
const CVV = encryptedData.decrypt(data.CVV)
const cardanmeSurname = data.cardNameSurname
var sendUrl = `Cvv=${CVV}&TransactionDeviceSource=0&MpiTransactionId=${uniqueId2}&ECI=${eci}&CAVV=${CAVV}&ClientIp=${clientIp}&CardHoldersName=${cardanmeSurname}&Expiry=${resExpiryData}&TransactionType=Sale&MerchantId=${req.body.MerchantId}&Password=${uyeSifresi}&TransactionId=${newUniqueId}&TerminalNo=${teminalNo}&CurrencyCode=${ResCurrencyCode}&CurrencyAmount=${amount}&BrandName=${resBrandName}&Pan=${resCreditCardNumber}`
axios.post(reqUrl , sendUrl,
{
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then((dataUrl) =>{
console.log(dataUrl)
res.send('veri var usta axios')
})
.catch((err) => {
res.send('hata var usta axios')
console.log(err)
})
})
})
I am making the request on hosting but unfortunately I did not get any results, thanks in advance for your help.

How do I make my mineflayer sprint while he following me?

I'm making mineflayer bot he follow me and try to kill me so when I go far from him he stop from
following me, And he has other problems like while he bridge he fall as stupid so how I can make him sprint while he follow me
My code :
const { versions } = require('minecraft-data')
const MinecraftData = require('minecraft-data')
const mineflayer = require('mineflayer')
const { pathfinder, Movements, goals } = require('mineflayer-pathfinder')
const GoalFollow = goals.GoalFollow
const pvp = require('mineflayer-pvp').plugin
const armorM = require('mineflayer-armor-manager')
const bot = mineflayer.createBot({
host: 'EventWG.aternos.me',
username: 'bot'
})
//Follow the player
function followPlayer() {
bot.on('chat', (namee, msgg)=>{
const player = bot.players[namee]
if (msgg == "attack") {
bot.chat("ok " + namee)
bot.chat("/effect give #p minecraft:resistance 111111 255")
if (!player || !player.entity){
bot.chat("I can't see you " + namee)
return
}
const data = require('minecraft-data')(bot.version)
const movements = new Movements(bot, data)
bot.pathfinder.setMovements(movements)
const goal = new GoalFollow(player.entity, 2)
bot.pathfinder.setGoal(goal, true)
setInterval(() => {
const playerFilter = p => p.type === "player"
const playerr = bot.nearestEntity(playerFilter)
bot.pvp.attack(player.entity)
const sword = bot.inventory.items().find(item => item.name.includes('sword'))
if(sword) bot.equip(sword, "hand")
}, 2000);
}
})
}
bot.on('spawn', lookAtPlayer)
bot.on('spawn', followPlayer)
You can simple just use bot.setControlState just like
bot.setControlState('sprint', true);

Loop over a list of ids and foreach id get data from api

Loop over a list of ids and foreach id get data from api but, i can make only 40 requests per 10 seconds, i'm getting data from tbdb but i'm getting kicked by the api here is my code
Popular.findAll({ limit: 25 }).then((filmes) => {
for (let index = 0; index < filmes.length; index++) {
const element = filmes[index];
const id_filme = element.id_filme;
i get each movie id so i can make requests to the api with this function..
function fetchdata(id_filme) {
setTimeout(function () {
axios
.all([
axios.get(
`https://api.themoviedb.org/3/movie/${id_filme}?api_key=${process.env.API_KEY}&language=pt-BR`
),
axios.get(
`https://api.themoviedb.org/3/movie/${id_filme}/videos?api_key=${process.env.API_KEY}&language=pt-BR`
),
])
.then(
axios.spread(function (detalhes, linksyt) {
var filme = detalhes.data;
var youtube = linksyt.data;
// console.log(filme, youtube);
var filmesLista = new Array();
const title = filme.title;
const filmeid = filme.id;
if (Object.keys(filme.genres).length === 0) {
var genre = filme.genres;
} else {
var genre = filme.genres[0].name;
}
const overview = filme.overview;
const poster_path =
"https://image.tmdb.org/t/p/w500" + filme.poster_path;
const release_date = filme.release_date;
const vote_average = parseFloat(filme.vote_average);
const backdrop_path =
"https://image.tmdb.org/t/p/original" + filme.backdrop_path;
const imdb_id = filme.imdb_id;
const runtime = filme.runtime;
if (Object.keys(youtube.results).length === 0) {
var trailer = "";
} else {
var trailer =
"http://www.youtube.com/watch?v=" + youtube.results[0].key;
}
filmesLista.push([
filmeid,
title,
genre,
overview,
poster_path,
release_date,
vote_average,
backdrop_path,
imdb_id,
runtime,
trailer,
]);
console.log(filmesLista);
filmesLista.forEach((i) => {
const filmeid = i[0];
const title = i[1];
const genre = i[2];
const overview = i[3];
const poster_path = i[4];
const release_date = i[5];
const vote_average = i[6];
const backdrop_path = i[7];
const imdb_id = i[8];
const runtime = i[9];
const trailer = i[10];
Detalhes.create({
id_filme: `${filmeid}`,
title: `${title}`,
genre: `${genre}`,
release_date: `${release_date}`,
vote_average: `${vote_average}`,
imdb_id: `${imdb_id}`,
runtime: `${runtime}`,
overview: `${overview}`,
poster_path: `${poster_path}`,
backdrop_path: `${backdrop_path}`,
trailer: `${trailer}`,
});
});
})
);
o++;
if (o < 25) {
fetchdata(id_filme);
}
}, 10000);
console.log("INSERIDO NO BANCO");
}
fetchdata(id_filme);
the code works but, works so fast and i get kicked every time i run with more than 40 ids.. i'm strugling on just make 40 request every 10 secconds. anyone can help me please?

How to avoid empty object error in a loop using Google Apps Script?

I'm calling an API and getting data going through its pagination. When I get to the last page, though, the obejct giving me the last page is empty and it's throwing the following error: TypeError: Cannot convert undefined or null to object Besides, I don't any data from that last page.
Here's the pagination information I get:
{"count":100,"total":545,"_links":
{
"self":{
"href":"\/candidates?page=0&per_page=100"
},
"next":{
"href":"\/candidates?per_page=100"
},
"last":{
"href":"\/candidates?page=6&per_page=100"
}
},
Here's the code I'm using to get the data:
function allcandidates() {
const url = "https://api.catsone.com/v3/candidates";
const params = {
'muteHttpExceptions': true,
'method': 'GET',
'redirect': 'follow',
'headers': {
'Content-Type': 'application/json',
'Authorization': 'Token ' + API_KEY
}
};
let pageNum = 1;
let lastPgNo;
let data = {}, output = [];
do {
let currentUrl = url + '?' + 'per_page=100' + '&' + 'page=' + pageNum;
//One of their URL parameter is "per_page", which is 25 result/page and it go up to 100. I'm not sure if the fact that the last page doesn't have all 100 results may result in an error, too.
const response = UrlFetchApp.fetch(currentUrl, params);
const respCode = response.getResponseCode();
if (respCode != 200) {
Browser.msgBox('The server seems to be temporarily down. Please try again later.');
return;
}
//Gets the last page number
const getText = response.getContentText();
const lastPageObj = JSON.parse(getText)['_links']['last'];
const lastPgVal = Object.values(lastPageObj); //This is where the error occurs
const lastPgText = lastPgVal.toString();
lastPgNo = Number(lastPgText.split('?page=').pop().split('&')[0])
//Gets current page
const currentPageObj = JSON.parse(getText)['_links']['self'];
const currentPgVal = Object.values(currentPageObj);
const nextPgText = currentPgVal.toString();
var currentPgNo = Number(nextPgText.split('?page=').pop().split('&')[0])
const dataSet = JSON.parse(getText)['_embedded']['candidates'];
for (let i = 0; i < dataSet.length; i++) {
data = dataSet[i];
output.push([data.id]);
}
pageNum = pageNum + 1;
} while (pageNum <= lastPgNo);
}
You might use an if statement and continue. I.E. replace
const lastPgVal = Object.values(lastPageObj);
by
if(lastPageObj){
const lastPgVal = Object.values(lastPageObj);
} else {
continue;
}
Another option is to use try...catch
Resources
https://developer.mozilla.org/en-US/docs/Glossary/Truthy
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch

Categories