Dynamically creating multidimensional inline keyboard telegram bot api? - javascript

My Code:
var keyBoardData = [];
var menu = ['Nightclub', 'Parks'];
for (var i = 0; i < menu.length; i++) {
keyBoardData.push([{'text': menu[i], 'callback_data': '{"a":(menu[i]),"b":(menu[i])}' }]);
}
var keyBoard = {"inline_keyboard": keyBoardData};
result is:
{"inline_keyboard":[[{"text":"Nightclub","callback_data":"{\"a\":(menu[i]),\"b\":(menu[i])}"}],
[{"text":"Parks","callback_data":"{\"a\":(menu[i]),\"b\":(menu[i])}"}]]}
but am trying to get:
{"inline_keyboard":[[{"text":"Nightclub","callback_data":'{"a":"Nightclub","b":"Nightclub"}'}],
[{"text":"Parks","callback_data":'{"a":"Parks","b":"Parks"}'}]]}
working with telegram bot api and google sheets app script.
need to display a column data as Buttons in telegram and on selection of button needs to filter sheets data using callback_data and return the result.
am having issue here: '{"a":(menu[i]),"b":(menu[i])}' this fits inline keyboard but menu[i]) treating as text.
if i remove single quotes am able to get data but inline keyboard not works.
any suggestion.

Don't create json by hard-coding strings.
Use JSON.stringify() and URLSearchParams() to format the required data;
An example, using the same data; with the result below;
// Create keyBoard data
var keyBoardData = [];
var menu = ['Nightclub', 'Parks'];
for (var i = 0; i < menu.length; i++) {
keyBoardData.push({
text: menu[i],
callback_data: menu[i]
});
}
// Create fetch options
var requestOptions = new URLSearchParams({
reply_markup: JSON.stringify({ "inline_keyboard": [ keyBoardData ]}),
chat_id: 12345678,
text: 'Test Keyboard'
}).toString();
// Send test
const token = '1134534202?????????????';
fetch("https://api.telegram.org/bot" + token + "/sendMessage?" + requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));

Related

How to render RapidAPI data on another HTML page?

I am new to JavaScript and this is my first question here. I've been trying for week to render my RapidApi data on another HTML page. I made search form on my index page and then put its values as my api call parameters in order to influence my API response. I used fetch to do so. The issue is that my API data keeps rendering on the same index page which is understandable since I don't know how to render it on a separate page. This also means that my CSS styling options are limited since I cannot design API data as I want without messing up my index page. If you have any sort of solution that is not way too complicated I would really appreciate your help.
Here is part of my code:
const input = document.getElementById(`location`);
const guests = document.getElementById(`guests`);
const check = document.querySelectorAll(".date");
let id;
document.getElementById(`submit`).addEventListener(`click`, function (e) {
e.preventDefault();
locationId();
});
async function locationId () {
let hotelId = input.value;
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': '//API key goes here',
'X-RapidAPI-Host': 'tripadvisor16.p.rapidapi.com'
}
};
let response = await fetch(`https://tripadvisor16.p.rapidapi.com/api/v1/hotels/searchLocation?query=${hotelId}`, options);
if (!response.ok) throw new Error(`Woops something went wrong`);
let data = await response.json();
let geoId = await (data.data[0].geoId);
id= parseInt(geoId);
return (fetch(`https://tripadvisor16.p.rapidapi.com/api/v1/hotels/searchHotels?geoId=${id}&checkIn=${check[0].value}&checkOut=${check[1].value}&pageNumber=1&adults=${guests.value}currencyCode=USD`, options))
.then(response => response.json())
.then(data => {
let list = data.data.data;
displayObjectElements(list)
function displayObjectElements (object) {
let display = ``;
let price = ``;
object.forEach(element => {
display+= `<div class = "objectResults">
<ul class="hotel__lists">
<li><h2 class = "title">${element.title}</h2></li>
<li><img class= "hotels--photo "src="${element.cardPhotos[0].sizes.urlTemplate.split("?")[0] + `?w=500&h=500`}" alt=image--photo/></li>
<li><p>Ranking:${element.bubbleRating.rating}&#9734 out of 5&#9734</p></li>`
if(!element.priceForDisplay) {
display+= `<li><p>There is no price to display</p></li>`
display+= `<li><button class="booking-btn">Click to book</button></li>`
} else {
price =element.priceForDisplay.substring(1);
price= parseInt(price);
// console.log(price);
display+= `<li><p>Price: $${price} in total</p></li>`
display+= `<li><button class = "booking-btn">Click to book</button></li>
</ul>
</div>`
// console.log(display);
}});
document.body.innerHTML = display;
}
})
.catch(err => console.error(err));
}
I already tried with localStorage and sessionStorage but as a newbie I am just now sure how to put the whole API data in storage. Also, I desperately tried with window.location object as well but as I assumed that did nothing but open a new tab. Again, thanks in advance for any help!

API Integration - How to extract only values from Object Array using JS?

Need assistance with Javascript - API Integration. I have been trying to pull data off SWAPI (an open API) and fetch the data into our system. I am struggling with something now!
What I am trying to do is get the around 3 country names and get the people's attribute under that country. So fat I was able to get the country names using the following code:
(async () => {
let Name = [];
let Diameter = [];
let Resident = [];
for (i = 1; i < 4; i++) {
const PlanetDetails = await api.makeRequest({
method: 'GET',
url: `https://swapi.dev/api/planets/${[i]}`,
});
Name[i] = PlanetDetails.data.name;
Resident[i] = PlanetDetails.data.residents;
api.setVariable('Name1', Name[1]);
api.setVariable('Name2', Name[2]);
api.setVariable('Name3', Name[3]);
api.setVariable('R1', Resident[1]);
}
})();
But under the countries the residents' attributes are coming up as links like this:
I used POSTMAN here to test. When I click on the links I can see the person's attributes (e.g color, height, name, etc.). But How do I do that in JS?
Thank you
To get the resident's data, you need to make a request to the endpoint and then use the returned data. for example to get the data of the first resident, you can make a request to https://swapi.dev/api/people/1.
This code makes requests for each resident.
(async () => {
let Name = [];
let Diameter = [];
let Resident = [];
for (i = 1; i < 4; i++) {
const PlanetDetails = await api.makeRequest({
method: 'GET',
url: `https://swapi.dev/api/planets/${[i]}`,
});
Name[i] = PlanetDetails.data.name;
Resident[i] = await Promise.all(PlanetDetails.data.residents.map(async(resident) => {
let resident = await api.makeRequest({
method: 'GET',
url: resident,
});
console.log(resident.data); // for visually viewing the result.
return resident.data;
}));
api.setVariable('Name1', Name[1]);
api.setVariable('Name2', Name[2]);
api.setVariable('Name3', Name[3]);
api.setVariable('R1', Resident[1]);
}
})();

sqlite- fetch data from multiple tables together- android and iOS

I have multiple sqlite tables and I want to fetch data from these tables together from Ionic 3 app for android and iOS platform and send it to server
Here's the code I wrote for this functionality
function fetchDataFromSqlite(){
let tableNames = ['table1','table2','table3'];
var dataFromSQLite= {};
for (var i = 0; i < tableNames.length; i++)
{
let tableName = tableNames[i];
let queryParams = [1];
let query = `SELECT * FROM ${tableName} WHERE status= ?`;
this.databaseprovider.SelectQry(query, queryParams).then(data => {
dataFromSQLite[tableName] = data;
});
return dataFromSQLite;
}
}
Above function is what I wrote to perform this action. I call this function in my app component
SelectQry() in databaseprovider looks like this:
SelectQry(sql, params) {
return this.database.executeSql(sql, params).then(
data => {
return data;
},
err => {
console.log("Error: ", JSON.stringify(err));
return [];
}
);
}
When I alert() the data returned from fetchDataFromSqlite() , I get {}
Can anyone tell me what I'm doing wrong or why I'm not getting any output when there's data in SQLite tables?

Write puppeteer json into html table in html and save it without jQuery

Im collecting titles and images from website into a human-readable format.
I use fs.writeFile and options are:
save as html (where its opened locally) or,
have it sent to email by nodemailer.
Either way I need the info in table format in html.
Top row = Title, Price, Image (displayed, not link).
Columns =list of items.
I added in a portion to convert JSON to html table but its messing up. Now the script does not run. Error is document not defined (in table formation).
Separately, if theres any way to auto-send the list to emails daily without maintaining a server, kindly let me know too.
const puppeteer = require('puppeteer');
const fs = require('fs');
/* this gets the json data, all working ok */
async function newCam() {
const browser = await puppeteer.launch({ headless: false });
let page = await browser.newPage();
await page.goto('https://sg.carousell.com/search/products/?query=camera', { waitUntil: 'networkidle2' });
let results = [];
let elements = await page.$$('div.U-U');
for (let element of elements) {
let listTitle = await element.$eval('div.U-m', node => node.innerText.trim());
let listImg = await element.$eval('.U-p img', img => img.src);
let listPrice = await element.$eval('div.U-k :nth-child(1)', node => node.innerText.trim());
results.push({
'Title': listTitle,
'Img': listImg,
'Px': listPrice
});
}
await browser.close();
return results;
/* format json into table and feed into fs below */
// get header keys
var col = [];
for (var i = 0; i < results.length; i++) {
for (var key in results[i]) {
if (col.indexOf(key) === -1) { col.push(key); }
}
}
// create table
var table = document.createElement("table");
var tr = table.insertRow(-1); // insert header row.
for (var k = 0; k < col.length; k++) {
var th = document.createElement("th"); // fill header
th.innerHTML = col[k];
tr.appendChild(th);
}
// add json data as rows
for (var a = 0; a < results.length; a++) {
tr = table.insertRow(-1);
for (var f = 0; f < col.length; f++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = results[a][col[f]];
}
}
/* save to html on local drive with fs */
fs.writeFile('/data.html', table, (err) => {
if (err) throw err;
});
}
newCam();
Why your code is not working
You are trying to use the DOM inside the Node.js environment. Node.js executes JavaScript on the server-side. So there are no DOM variables (like window or document) that you can access. Therefore you are getting the error document is not defined.
For more information regarding that topic you might want to check out the question "Why doesn't Node.js have a native DOM?"
Table creation
If you want to create the markup of an HTML table, you can either use string concatenation and simple merge together the table on your own or use something like jsdom to simulate a DOM on the server-side.
As your case seems to be rather simple, I would go with the first option.
Here some rather simple code to create the HTML markup for the table. You can put it into your code instead of your "create table" code and it will produce a table with one column for each value inside col.
function escapeHtml(str) { // for security reasons escape "<" (you could even improve this)
return str.replace(/</g, '<');
}
const htmlTable = '<table>'
+ `\n <tr>${col.map(c => '<th>' + escapeHtml(c) + '</th>')}</tr>`
+ results // generate rows, use map function to map values to trs/tds
.map(row => ('\n <tr>' +
col.map(c => `\n <td>${escapeHtml(row[c])}</td>`).join('')
+ '\n</tr>')).join('')
+ '\n</table>';
fs.writeFile('/data.html', htmlTable, (err) => {
// ...
});
Of course, this code is a rather simple example to get you started.
Sending the document via mail
Instead of saving the HTML locally, you can also directly send it via mail by using nodemailer. Here is a code sample to get you started, but you might want to check out the nodemailer website for more information.
await transporter.sendMail({
/* ... */
html: 'Full HTML document.... ' + htmlTable + ' ...'
});

Node/Feathers with a database in the back

I am learning about Node and Feathers on a job. Need to make a simple app that would use feathers to load the [nedb] with sample data.
var fake = require('./fake.js');
var feathers = require('feathers-client');
var io = require('socket.io-client');
var socket = io("http://127.0.0.1:8000");
var app = feathers()
.configure(feathers.socketio(socket));
var accountsAPIService = app.service('/api/accounts');
var dummyData = fake();
// import dummy data
for ( var i = 0; i < dummyData.accounts.length; i++) {
// console.log(dummyData.accounts[i]);
var params = { query: {}};
accountsAPIService.create(dummyData.accounts[i], params).then(function(account) {
console.log("inserted: ", account);
});
}
// read back inserted records
accountsAPIService.find(params, function(accounts) {
console.log("accounts: ", accounts);
});
i just need to insert items from the array dummyData.accounts into the server.
When I run the script, it seems that nothing is being imported.
When I read the records back, it returns:
accounts: null
What is the proper way of inserting/creating records with Feathers?
Could not figure out how to use ".then" so used a regular form:
for ( var i = 0; i < dummyData.accounts.length; i++) {
var params = { query: {}};
accountsAPIService.create(dummyData.accounts[i], params, function(error, account) {
// console.log("inserted: ", account);
});
}
That works fine.
To read the data back, I corrected the method signature. Then, it works. :)
accountsAPIService.find(function(error, accounts) {
console.log("accounts: ", accounts);
});

Categories