Airtable - How to change Api link Onclick JS? - javascript

I have this JS script, who call an Airtable API
var type = "Coupons"
var api_key = "?api_key=123456"
var maxRecords = "&maxRecords=10"
var filterByFormula = "&filterByFormula=%7Bvip_ou_50%7D%3D%2250%222"
var offset = "";
var url = "https://api.airtable.com/v0/app123456/" + type + api_key + maxRecords + "&offset=" + offset + "&sort%5B0%5D%5Bfield%5D=coupons_id";
async function catchJson() {
const response = await fetch(url);
const data = await response.json();....
as you see next, I created a function to change the value of the offset
var next_page = function () {
console.log(offset);
offset = data.offset;
console.log(offset);
}
page_suivante.onclick = next_page;
so I want to create a next page bouton Onclick that change the offset value
How can I do that !
Thanks for your help !
This is my result page for now : https://web.pinkmarket.co
Edit : this is my full JS with correction
var type = "Coupons"
var api_key = "?api_key=1234"
var maxRecords = "&maxRecords=10"
var filterByFormula = "&filterByFormula=%7Bvip_ou_50%7D%3D%2250%222"
var offset = "&offset"
var url = "https://api.airtable.com/v0/app1234/" + type + api_key + offset + "&sort%5B0%5D%5Bfield%5D=coupons_id";
const app = document.getElementById('root')
const card = document.createElement('div');
card.setAttribute('class', 'rightcontainer w-container')
app.appendChild(card)
async function catchJson() {
const response = await fetch(url);
const data = await response.json();
if (response.status >= 200 && response.status < 400) {
data.records.forEach(records => {
const records_length = document.getElementById('number')
records_length.innerHTML = 'Liste de coupons <br> <span class="text-span-2">Ouvrir la Map</span>'
const property_card = document.createElement('a')
property_card.setAttribute('class', 'property-card left w-inline-block w-clearfix')
property_card.style.background = "-webkit-gradient(linear, left top, left bottom, color-stop(29%, hsla(0, 0%, 100%, 0)), color-stop(68%, rgba(0, 0, 0, 0.5))), url('" + records.fields.image_url + "');";
property_card.style.background = "linear - gradient(180deg, hsla(0, 0 %, 100 %, 0) 29 %, rgba(0, 0, 0, 0.5) 68 %), url('" + records.fields.image_url + "');"
const image_quantity_div = document.createElement('div')
image_quantity_div.setAttribute('class', 'image-quantity-div')
const price_text = document.createElement('h1')
price_text.setAttribute('class', 'price-text')
price_text.innerText = records.fields.titre
const div_lower_info = document.createElement('div')
div_lower_info.setAttribute('class', 'div-lower-info w-clearfix')
const info_text = document.createElement('div')
info_text.setAttribute('class', 'info-text')
info_text.innerText = records.fields.compagny_name + ' - ' + records.fields.description_sub.substring(0, 100) + '...'
const view_button = document.createElement('div')
view_button.setAttribute('class', 'view-button')
view_button.textContent = 'Plus'
root.appendChild(card);
card.appendChild(property_card);
property_card.appendChild(image_quantity_div);
property_card.appendChild(price_text);
div_lower_info.appendChild(info_text);
div_lower_info.appendChild(view_button);
property_card.appendChild(div_lower_info);
})
const offset_page = document.createElement('a');
offset_page.setAttribute('class', 'button-2 left-aligned w-button')
offset_page.setAttribute('id', 'next')
offset_page.setAttribute('href', data.offset)
offset_page.innerHTML = "Page Suivante"
card.appendChild(offset_page);
});
}
else {
const errorMessage = document.createElement('a')
errorMessage.textContent = `Bah, ça ne marche pas !`
app.appendChild(errorMessage)
}
}
document.addEventListener('DOMContentLoaded', function () {
catchJson()
});
<div class="premium-properties-div" id="root">
</div>

If I got your question right you want to run the next_page() function on button click. If so this code does that:
EDIT: As discussed in the comments the below code will update your offset variable without restarting.
var type = "Coupons"
var api_key = "?api_key=123456"
var maxRecords = "&maxRecords=10"
var filterByFormula = "&filterByFormula=%7Bvip_ou_50%7D%3D%2250%222"
//I assume you set the ofset to "" because as discussed in the comments you get the offset value after calling the api the first time
var offset = "";
var url = "https://api.airtable.com/v0/app123456/" + type + api_key + maxRecords + "&offset=" + offset + "&sort%5B0%5D%5Bfield%5D=coupons_id";
var dynamicOffset = []
//your finalData
var finalData = []
//on click of button the api starts running.
document.getElementById("nextPageBtn").addEventListener('click', function() {
getNewOffset()
});
function getNewOffset() {
async function catchJson() {
const response = await fetch(url);
const data = await response.json();
//as disscussed in the comments ```data``` is the offset value you get back so now insert the offset value to the URL and run it again and again untill no ofset value is returned
//so first check if data is not empty then if not lets push every new offset data returned to an array called ```dynamic Offset``` but also empty the array before pushing then call the second fetch method.
if (data != "" && data != null) {
dynamicOffset = []
dynamicOffset.push(data)
secondFetch()
} else {
console.log('not more new offset')
//Log your final data
console.log(finalData)
}
}
}
function secondFetch() {
//insert the new Offset Value
const modifiedURL = "https://api.airtable.com/v0/app123456/" + type + api_key + maxRecords + "&offset=" + dynamicOffset[0] + "&sort%5B0%5D%5Bfield%5D=coupons_id";
//call fetch
async function catchJson() {
const response = await fetch(modifiedURL);
const data = await response.json();
//we didn't discuss how you want your final data to be saved but assuming your data are strings lets push them all to ```finalDataArray``` but you can save them in your desierd way. Note we are not clearing array here becuase we are appending not writing.
//just a precaution statment
if (data != "" && data != null) {
finalData.push(data)
//lets setTimeout of 1 second to avoid memory overload
setTimeout(() => {
//call getNewOffset() again
getNewOffset()
}, 1000)
}
}
}
<button id="nextPageBtn">Next Page</button>

Related

Delay for messages in node-telegram-bot-api

I am working on a telegram bot with the node-telegram-bot-api library. I made 2 buttons using keyboard. But when you click on them a lot, the bot will spam and sooner or later it will freeze. Is it possible to somehow put a delay for the user on messages.
if (text === '/start') {
return bot.sendMessage(chatId, 'hello', keyboardMain);
}
export const keyboardMain = {
reply_markup: JSON.stringify({
keyboard: [
[{
text: '/start',
},
],
resize_keyboard: true
})
};
You can create a user throttler using Javascript Map
/*
* #param {number} waitTime Seconds to wait
*/
function throttler(waitTime) {
const users = new Map()
return (chatId) => {
const now = parseInt(Date.now()/1000)
const hitTime = users.get(chatId)
if (hitTime) {
const diff = now - hitTime
if (diff < waitTime) {
return false
}
users.set(chatId, now)
return true
}
users.set(chatId, now)
return true
}
}
How to use:
You'll get the user's chatId from telegram api. You can use that id as an identifier and stop the user for given specific time.
For instance I'm gonna stop the user for 10seconds once the user requests.
// global 10 second throttler
const throttle = throttler(10) // 10 seconds
// in your code
const allowReply = throttle(chatId) // chatId obtained from telegram
if (allowReply) {
// reply to user
} else {
// dont reply
}
I tried using this code, put the function code in my function file, connected everything to the required file, and I don’t understand what to do next and where to insert the last code and what to do with it. I'm new to JavaScript and just learning.
import {
bot
} from '../token.js';
import {
throttler
} from '../functions/functions.js';
import {
keyboardMain
} from '../keyboards/keyboardsMain.js';
export function commands() {
bot.on('message', msg => {
const text = msg.text;
const chatId = msg.chat.id;
const throttle = throttler(10);
if (text === '/start') {
const allowReply = throttle(chatId) // chatId obtained from telegram
if (allowReply) {
return bot.sendMessage(chatId, 'hello', keyboardMain);
} else {
// dont reply
}
}
return bot.sendMessage(chatId, 'error');
});
}
Get the time when he pressed the button
Get the time of the next click
Take away the difference and set the condition (if, for example, more than 3 seconds have passed between clicks, then the user will not be frozen).
var token = ""; // FILL IN YOUR OWN TOKEN
var telegramUrl = "https://api.telegram.org/bot" + token;
var webAppUrl = ""; // FILLINYOUR GOOGLEWEBAPPADDRESS
var ssId = ""; // FILL IN THE ID OF YOUR SPREADSHEET
function getMe() {
var url = telegramUrl + "/getMe";
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function setWebhook() {
var url = telegramUrl + "/setWebhook?url=" + webAppUrl;
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function sendText(id,text) {
var url = telegramUrl + "/sendMessage?chat_id=" + id + "&text=" + text;
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function doGet(e) {
return HtmlService.createHtmlOutput("Hi there");
}
function doPost(e){
var data = JSON.parse(e.postData.contents);
var text = data.message.text;
var id = data.message.chat.id;
var msgbegan = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A7").getValue();
var msginfo = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A9").getValue();
var answer = "%0A" + msgbegan + "%0A" ;
///////////////////////
/*
* #param {number} waitTime Seconds to wait
*/
function throttler(waitTime) {
const users = new Map()
return (chatId) => {
const now = parseInt(Date.now()/1000)
const hitTime = users.get(chatId)
if (hitTime) {
const diff = now - hitTime
if (diff < waitTime) {
return false
}
users.set(chatId, now)
return true
}
users.set(chatId, now)
return true
}
}
// global 10 second throttler
const throttle = throttler(500) // 10 seconds
// in your code
const allowReply = throttle(chatId) // chatId obtained from telegram
if (allowReply) {
// reply to user
} else {
// dont reply
}
///////////////////////////////////////
if(text == "/start"){
sendText(id, answer);
} else if (text == "/info"){
sendText(id, msginfo);
}else{
if (text.length == 10){
var found = false;
var total_rows = SpreadsheetApp.openById(ssId).getSheets()[0].getMaxRows();
for(i=1; i<=total_rows; i++){
var loop_id = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(i,2).getValue();
if(text == loop_id){
found = true;
found_at = i; // employee row
break;
}
}
if(found){
sendText(id, work_message);
}else{
var msgerrror = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A6").getValue();
var not_found = "%0A" + msgerrror+ "%0A" ;
sendText(id, not_found);
}
} else {
sendText(id, "eroor");
}
}
/////////////
var emp_name = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,1).getValue();
var emp_work = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,3).getValue();
var homeloc = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,4).getValue();
var emp_location = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,8).getValue();
var emp_data = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,5).getValue();
var emp_day = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,6).getValue();
var emp_clock = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,7).getValue();
var emp_location = SpreadsheetApp.openById(ssId).getSheets()[0].getRange(found_at,8).getValue();
var welcome = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A2").getValue();
var msgemp = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A3").getValue();
var msgloc = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A4").getValue();
var msgbay = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A5").getValue();
var msghome = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A8").getValue();
var msmobil = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A11").getValue();
var mstoday = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A13").getValue();
var msdata = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A14").getValue();
var msclock = SpreadsheetApp.openById(ssId).getSheets()[1].getRange("A15").getValue();
var work_message = welcome + emp_name +
"%0A" + msgemp + emp_work +
"%0A" + mstoday + emp_day +
"%0A" + msdata + emp_data +
"%0A" + msclock + emp_clock +
"%0A" + msghome + homeloc +
"%0A" + msgloc+ emp_location +
"%0A" + msgbay +
"%0A" + msmobil ;
}
Excuse me . I am a beginner
Is this the correct way

Fetch data from API on setInterval without creating another HTML elements

My code basically fetches API data, creates HTML elements for each and update the innerHTML elements with API data.
How can I possibly refresh the data from API and update it without creating another HTML elements?
This is my actual code:
let divCrypto = document.getElementById("divCrypto");
let temp, p1, p2, p3, imgz;
let data = [];
const getData = async () => {
for (i = 0; i < 2; i++){
coinName = await fetch("https://api.coinlore.net/api/tickers/")
.then((res) => res.json());
data.push(coinName.data[i]);
p1 = document.createElement("p");
p2 = document.createElement("p");
p3 = document.createElement("p");
p1.innerHTML = "Coin:" + " " + data[i].name;
p2.innerHTML = "Coin:" + " " + data[i].price_usd;
p3.innerHTML = data[i].percent_change_7d + "%";
divCrypto.appendChild(p1);
divCrypto.appendChild(p2);
divCrypto.appendChild(p3);
}
console.log(data);
};
getData();
console.log(data);
I tried with : setInterval (getData, 1000); but after each second, it recreates the HTML elements again and again.
I also tried to make 2 different functions but I don't know how to access the data outside the getData() function.
If I console log it outside, after the function is called and the data is updated, I get [] and I cannot understand why.
You can add to the html object the coins you want to display and the function will generate the html for them if it doesn't exist or just update the values if they do exists
let divCrypto = document.getElementById("divCrypto");
let html = { BTC: 1, ETH: 1, ADA: 1 };
let data = [];
let temp, p1, p2, p3, container;
const getData = async () => {
coinName = await fetch("https://api.coinlore.net/api/tickers/").then((res) =>
res.json()
);
for (i = 0; i < 3; i++) {
data.push(coinName.data[i]);
container = document.getElementById(data[i].symbol);
if (html[data[i].symbol] && !container) {
// if this is the first time we read this coin we generate the html
container = document.createElement("div");
container.id = data[i].symbol;
p1 = document.createElement("p");
p2 = document.createElement("p");
p3 = document.createElement("p");
container.appendChild(p1);
container.appendChild(p2);
container.appendChild(p3);
divCrypto.appendChild(container);
}
if (html[data[i].symbol]) {
container.children[0].innerHTML = "Coin:" + " " + data[i].name;
container.children[1].innerHTML = "Coin:" + " " + data[i].price_usd;
container.children[2].innerHTML = data[i].percent_change_7d + "%";
}
}
console.log(data);
};
getData();
setInterval(getData, 1000);
//console.log(data);
<div id="divCrypto"></div>

Editing PDFs with Hummus.js problem with certain pages

i am currently trying to edit a pdf with hummus.js to replace certain placeholder characters in the pdf with others.
This works perfectly fine for almost every page, but for certain pages I get the following error:
TypeError:
pageObject.getDictionary(...).toJSObject(...).Contents.getObjectID is
not a function for:
const textObjectID = pageObject.getDictionary().toJSObject().Contents.getObjectID();
Whenever that error happens and it doesnt work,
pageObject.getDictionary().toJSObject().Contents returns a PDFArray {}, while, when it works, it returns an PDFIndirectObjectReference {}
Does anybody know how I could solve this issue or any other way to edit a pdf that way (replacing certain placeholder characters with others)
UPDATE 1: I can now differentiate between IndirectObjectReferences and arrays containing IndirectObjectReferences, but for some reason it removes all text but keeps the images from pdf pages which i access through these arrays, the rest of the pdf pages still work perfectly fine
async function replacetext(filePath, callback) {
var pageCount = 0;
const modPdfWriter = hummus.createWriterToModify(filePath+'.pdf', { modifiedFilePath: `${filePath}-modified.pdf`, compress: false })
const numPages = modPdfWriter.createPDFCopyingContextForModifiedFile().getSourceDocumentParser().getPagesCount()
var log="";
for (let page = 0; page < numPages; page++) {
const copyingContext = modPdfWriter.createPDFCopyingContextForModifiedFile()
const objectsContext = modPdfWriter.getObjectsContext()
const pageObject = copyingContext.getSourceDocumentParser().parsePage(page)
pageCount = pageCount + 1;
try
{
var replaceTextRight = " " + pageCount.toString();
if(pageCount > 9 && pageCount < 100)
{
replaceTextRight = " " + pageCount.toString();
}
else if(pageCount > 99)
{
replaceTextRight = " " + pageCount.toString();
}
const textStream = copyingContext.getSourceDocumentParser().queryDictionaryObject(pageObject.getDictionary(), 'Contents')
console.log(textStream);
if(textStream.toString() == 'Array')
{
let data = []
streamArray = textStream.toJSArray();
for(var i = 0; i<streamArray.length; i++)
{
var streamo = copyingContext.getSourceDocumentParser().queryArrayObject(textStream, i);
const readStream = copyingContext.getSourceDocumentParser().startReadingFromStream(streamo)
while (readStream.notEnded()) {
const readData = readStream.read(10000)
data = data.concat(readData)
}
var redactedPdfPageAsString = new Buffer.from(data).toString();
var replacedBuffer = replace(redactedPdfPageAsString, "12345", pageCount.toString());
log = log+" \n Replaced " +page +" with " + pageCount.toString();
var replacedBuffer = replace(replacedBuffer, "67890", replaceTextRight);
log = log+" \n Replaced " +page +" with " + replaceTextRight;
var textObjectID = streamArray[i].getObjectID();
objectsContext.startModifiedIndirectObject(textObjectID)
var stream = objectsContext.startUnfilteredPDFStream();
stream.getWriteStream().write(strToByteArray(replacedBuffer));
objectsContext.endPDFStream(stream);
objectsContext.endIndirectObject();
}
}
else
{
let data = []
const readStream = copyingContext.getSourceDocumentParser().startReadingFromStream(textStream)
while (readStream.notEnded()) {
const readData = readStream.read(10000)
data = data.concat(readData)
}
var redactedPdfPageAsString = new Buffer.from(data).toString();
var replacedBuffer = replace(redactedPdfPageAsString, "12345", pageCount.toString());
log = log+" \n Replaced " +page +" with " + pageCount.toString();
var replacedBuffer = replace(replacedBuffer, "67890", replaceTextRight);
log = log+" \n Replaced " +page +" with " + replaceTextRight;
const textObjectID = pageObject.getDictionary().toJSObject().Contents.getObjectID();
var content = pageObject.getDictionary().toJSObject().Contents;
objectsContext.startModifiedIndirectObject(textObjectID)
const stream = objectsContext.startUnfilteredPDFStream();
stream.getWriteStream().write(strToByteArray(replacedBuffer));
objectsContext.endPDFStream(stream);
objectsContext.endIndirectObject();
}
}
catch(e){
console.log(e);
}
}
fs.writeFile('C:\\Users\\Administrator\\Downloads\\PDFModifyDebugging\\PDFWRITELOG.txt', log, function (err) {
if (err) return console.log(err);
console.log('written in file');
});
modPdfWriter.end()
hummus.recrypt(`${filePath}-modified.pdf`, filePath)
callback();
}

Nodejs Scraper isn't moving to next page(s)

Hey guys this is a follow on from my other question, i have created a Nodejs Scraper that doesnt seem to want to go through the pages, it stays on the first. my source code is below
const rp = require('request-promise');
const request = require('request');
const otcsv = require('objects-to-csv');
const cheerio = require('cheerio');
//URL To scrape
const baseURL = 'xxx';
const searchURL = 'xxxx';
//scrape info
const getCompanies = async () => {
// Pagination test
for (let index = 1; index <= 20; index = index + 1) {
const html = await rp.get(baseURL + searchURL + index);
const $ = await cheerio.load(html);
console.log("Loading Pages....");
console.log("At page number " + index);
// end pagination test
//const htmls = await rp(baseURL + searchURL);
const businessMap = cheerio('a.business-name', html).map(async (i, e) => {
const link = baseURL + e.attribs.href;
const innerHtml = await rp(link);
const emailAddress = cheerio('a.email-business', innerHtml).prop('href');
const name = e.children[0].data || cheerio('h1', innerHtml).text();
const phone = cheerio('p.phone', innerHtml).text();
return {
// link,
name,
emailAddress: emailAddress ? emailAddress.replace('mailto:', '') : '',
phone,
}
}).get();
return Promise.all(businessMap);
}
};
console.log("Finished Scraping.... Now Saving!")
//save to CSV
getCompanies()
.then(result => {
const transformed = new otcsv(result);
return transformed.toDisk('./output.csv');
})
.then(() => console.log('Scrape Complete :D '));
As you can see I have tried a few different ways to make this happen so any help will be gratefully appreciated.

cant pass data from textbox inside a loop

so im getting my data from Darksky api, i have elements generated with loops, and i update the text content of those via loop of the api data array. whenever i search, everthing else static changes values, not the one inside the loop
function search(ele) {
if(event.key === 'Enter') {
var url3 = 'https://geocode.xyz/' + ele.value +'?json=1' //this is where i convert the long,lat to city name
fetch(url3)
.then(z => z.json())
.then(z => {
locres = (z.latt+','+z.longt)
render()
renderLoop()
})
}
}
function renderLoop(){
var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
var url1 = 'https://api.darksky.net/forecast/c34e122a56ae30a3090687878bce72c3/' + locres + '?units=auto' //i have to use proxy because of CORS
fetch(proxyUrl + url1)
.then(x => x.json())
.then(x => {
var skycons = new Skycons({"color": "white"});
skycons.set("icon0", Skycons = x.currently.icon);
skycons.play();
console.log(x.daily.data)
for(i=0;i<8;i++){
console.log(x.daily.data[i].time)
console.log(x.daily.data[i].summary)
const divs = document.createElement('div')
divs.className = ('week-day-container')
const divsholdr = document.querySelector('.week-stage')
const canv = document.createElement('canvas')
canv.id = ('icons'+(i+1))
canv.height = 100
canv.width = 70
divs.appendChild(canv)
divsholdr.appendChild(divs)
const dates = document.createElement('p')
dates.textContent = x.daily.data[i].time
divs.appendChild(dates)
const temp = document.createElement('p')
temp.textContent = 'High: '+ x.daily.data[i].temperatureHigh + 'Low: ' + x.daily.data[i].temperatureLow
divs.appendChild(temp)
const summ = document.createElement('p')
summ.textContent = x.daily.data[i].summary
divs.appendChild(summ)
}
for(y=0;y<8;y++){
skycons.set('icons'+(y+1), Skycons = x.daily.data[y].icon)
}
})
}

Categories

Resources