Alexa is unable to connect - javascript

I am trying to connect alexa with my website. I created an Alexa skill (following the guide) that works in connecting with a website like "numbersapi" it asks the user for a number and reads the answer given by the site. This is the code:
function httpGet(query) {
return new Promise((resolve, reject) => {
var options = {
host: 'numbersapi.com',
path: '/' + encodeURIComponent(query),
method: 'GET',
};
var req = http.request(options, res => {
res.setEncoding('utf8');
var responseString = "";
//accept incoming data asynchronously
res.on('data', (chunk) => {
responseString = responseString + chunk;
});
//return the data when streaming is complete
res.on('end', () => {
resolve(responseString);
});
res.on('error',(error) => {
reject(error);
});
});
req.end();
});
}
And the Intent:
const questionIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'questionIntent';
},
handle(handlerInput) {
const theNumber = handlerInput.requestEnvelope.request.intent.slots.info.value;
var query = parseInt(theNumber);
return new Promise((resolve,reject) => {
httpGet(query).then((response) => {
resolve(handlerInput.responseBuilder
.speak(response)
.withShouldEndSession(false)
.getResponse());
}).catch ((error) => {
resolve(handlerInput.responseBuilder.speak('Request error').getResponse());
});
});
},
};
It works perfectly.Now I'm trying to use it for my very simple website but I can't get it to work. I created a simple form in a jsp that sends a number and opens another jsp page where a string is displayed based on the number. Changing the number to display in the url works, but when I try to apply the number through alexa it doesn't work. I think I have problems with the options.
var options = {
host: 'localhost',
path: '/SearchFact?info=' + encodeURIComponent(query),
method: 'GET',
};
Can someone help me?

Related

My weather app is throwing type error of temp.. It was console logging the data when I checked but as I enter city Lat and Log it shows type error [duplicate]

I'm trying to get my function to return the http get request, however, whatever I do it seems to get lost in the ?scope?. I'm quit new to Node.js so any help would be appreciated
function getData(){
var http = require('http');
var str = '';
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
//return str;
}
var req = http.request(options, callback).end();
// These just return undefined and empty
console.log(req.data);
console.log(str);
}
Of course your logs return undefined : you log before the request is done. The problem isn't scope but asynchronicity.
http.request is asynchronous, that's why it takes a callback as parameter. Do what you have to do in the callback (the one you pass to response.end):
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(req.data);
console.log(str);
// your code here if you want to use the results !
});
}
var req = http.request(options, callback).end();
Simple Working Example of Http request using node.
const http = require('https')
httprequest().then((data) => {
const response = {
statusCode: 200,
body: JSON.stringify(data),
};
return response;
});
function httprequest() {
return new Promise((resolve, reject) => {
const options = {
host: 'jsonplaceholder.typicode.com',
path: '/todos',
port: 443,
method: 'GET'
};
const req = http.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
} catch(e) {
reject(e);
}
resolve(body);
});
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.end();
});
}
Shorter example using http.get:
require('http').get('http://httpbin.org/ip', (res) => {
res.setEncoding('utf8');
res.on('data', function (body) {
console.log(body);
});
});
from learnyounode:
var http = require('http')
http.get(options, function (response) {
response.setEncoding('utf8')
response.on('data', console.log)
response.on('error', console.error)
})
'options' is the host/path variable
from learnyounode:
var http = require('http')
var bl = require('bl')
http.get(process.argv[2], function (response) {
response.pipe(bl(function (err, data) {
if (err)
return console.error(err)
data = data.toString()
console.log(data)
}))
})
I think it's too late to answer this question but I faced the same problem recently my use case was to call the paginated JSON API and get all the data from each pagination and append it to a single array.
const https = require('https');
const apiUrl = "https://example.com/api/movies/search/?Title=";
let finaldata = [];
let someCallBack = function(data){
finaldata.push(...data);
console.log(finaldata);
};
const getData = function (substr, pageNo=1, someCallBack) {
let actualUrl = apiUrl + `${substr}&page=${pageNo}`;
let mydata = []
https.get(actualUrl, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', async () => {
if (JSON.parse(data).total_pages!==null){
pageNo+=1;
somCallBack(JSON.parse(data).data);
await getData(substr, pageNo, someCallBack);
}
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
getData("spiderman", pageNo=1, someCallBack);
Like #ackuser mentioned we can use other module but In my use case I had to use the node https. Hoping this will help others.
This is my solution, although for sure you can use a lot of modules that give you the object as a promise or similar. Anyway, you were missing another callback
function getData(callbackData){
var http = require('http');
var str = '';
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
callbackData(str);
});
//return str;
}
var req = http.request(options, callback).end();
// These just return undefined and empty
console.log(req.data);
console.log(str);
}
somewhere else
getData(function(data){
// YOUR CODE HERE!!!
})

API GET request returns undefined in Node JS

I'm new to Node JS and still figuring out how API GET requests are working. I'm trying to call API GET request using Node Js, function is supposed to get data from the servers and url will be "url/books?name=" where "name" will be passed to the function from input field. So far I have this function
async function getBooksInfo(name) {
const url = `https://test/books?name=${name}`;
return new Promise(function (resolve, reject) {
https.get(url, res => {
res.setEncoding("utf8");
let body = "";
res.on("data", data => {
body += data;
});
res.on("end", () => {
body = JSON.parse(body);
resolve(body)
});
res.on("error", (e) => {
reject(e);
});
});
})
}
and another function will create stream of inputs,
async function storeInfo() {
const date = readLine().trim();
const result = await getBooksInfo(date);
const isEmpty = !Object.keys(result).length;
if (isEmpty) {
ws.write('We don't have this book in our database');
} else {
ws.write(`Book Name: ${result.bookName}`);
ws.write(`Year: ${result.year}\n`)
}
}
but for some reason stream of inputs return undefined, I don't seems to understand what could be the issue. Any help and suggestion is greatly appreciated.
Updated: this is what console.log shows
{
page: 1,
per_page: 100,
total_pages: 20,
data: [
{
bookName: 'test',
year: 1975,
author: "test,
}
]
}

this.title returning as Undefined

I'm trying to get my bot to "dynamically" get the name of a command.
title is defined in module.exports as the name of the command that will show up in the Embed; however in 1 specific command where I get a joke from an API, this.title returns as Undefined instead of the command's name.
It only happens in this command.
I've tried using just title however that just returns "node".
What did I do wrong? 
Code:
const Discord = require("discord.js");
const { title } = require("process");
const config = require("../data.json");
module.exports = {
name: "dadjoke",
title: "Dad Joke",
description: "A (not so) very funny dadjoke.",
execute(client, message, args) {
const https = require('https');
const url = "icanhazdadjoke.com";
var options = {
host: url,
port: 443,
path: "/",
headers: {"Accept":"application/json", "User-Agent":"crazyBot (https://github.com/acrazytown/crazybot)"}
}
function getData(options) {
https.get(options, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
const embed = new Discord.MessageEmbed()
.setColor(config.crazyBot.settings.accent_color)
.setAuthor("crazyBot", config.crazyBot.settings.icon_url)
.setTitle(this.title)
.setDescription(JSON.parse(data).joke)
.setFooter(`Powered by ${url}`);
message.channel.send(embed);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
getData(options)
}
}
Because the function getData() doesn't have an object reference, the value of this within the function is undefined whereas the value of this within execute() is defined as the object being exported. One simple solution to this is to use Function.bind() to set the this keyword of getData() to the object reference.
This is how that would look in your execute() function:
execute(client, message, args) {
const https = require('https');
const url = "icanhazdadjoke.com";
var options = {
host: url,
port: 443,
path: "/",
headers: {"Accept":"application/json", "User-Agent":"crazyBot (https://github.com/acrazytown/crazybot)"}
}
var getData = function(options) {
https.get(options, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
const embed = new Discord.MessageEmbed()
.setColor(config.crazyBot.settings.accent_color)
.setAuthor("crazyBot", config.crazyBot.settings.icon_url)
.setTitle(this.title)
.setDescription(JSON.parse(data).joke)
.setFooter(`Powered by ${url}`);
message.channel.send(embed);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}.bind(this);
getData(options)
}
Relevant resources:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

When creating files using Google Drive API the file content is empty

I'm working on node js app that is creating pdf by user id (using pdfkit), fills with user data and then uploads to Google Drive using Google Drive API. Client is getting back URL of this file. My problem is that when I upload it once, it works perfectly. But when I'm trying to do it again, the file uploads but it's empty. If I restart server it works again.
Pdf creation is also fine on the second attempt, the only problem is second create/upload. I have tried making the name of the file dynamic but that did not help. Only server restart works. Thank you.
Function for creating pdf
const createPdf = async (req, res, missions) => {
try {
const { _id } = req.user;
const pdfPath = path.join('data', 'pdf', _id + '.pdf');
let doc = new PDFDocument({ margin: 50 });
doc.pipe(fs.createWriteStream(pdfPath));
generateInnerPdf(doc, missions);
doc.end();
return { success: true };
} catch (err) {
return { success: false };
}
};
Function for upload on google drive and retrieve url
exports.uploads = (_id) => {
return new Promise((resolve) => {
const auth = new google.auth.JWT(
credentials.client_email,
null,
credentials.private_key,
scopes
);
const drive = google.drive({ version: 'v3', auth });
var folderId = 'xxxxxxxxxxx';
const pdfPath = path.join('data', 'pdf', _id + '.pdf');
var fileMetadata = {
name: `${_id}.pdf`,
parents: [folderId],
};
var media = {
mimeType: 'application/pdf',
body: fs.createReadStream(pdfPath),
};
drive.files.create(
{
resource: fileMetadata,
media: media,
fields: 'id',
},
(error, result) => {
resolve({
fileUrl: `https://drive.google.com/file/d/${result.data.id}/view?usp=sharing`,
});
}
);
});
};
My pdf controller
exports.create = async (req, res) => {
try {
const { missions } = await getMissions(req.user._id);
const { success } = await createPdf(req, res, missions);
if (success) {
googleApi.uploads(req.user._id).then((result) => {
res.status(200).send(result);
});
} else {
res.status(422).send(err);
}
} catch (err) {
console.log(err);
res.status(422).send(err.message);
}
};
EDIT: Should be a problem when I'm resolving promise again?
Fixed when setting timeout
if (success) {
setTimeout(function () {
googleApi.uploads(req.user._id).then((result) => {
res.status(200).send(result);
});
}, 500);

In azure functions (js) POST request after async/await call does not work

I am currently working with azure functions in javascript. In my function, I am first getting a specific element from my CosmoDB (this is the async/await part). I get a result and then I want to do an https POST request. However, my problem is, that it never finished the HTTPs request and I don't really know why. What am I doing wrong?
(As you can see I tried 2 different ways of doing the request, once with the standard https function and the commented out the part with npm request package. However, both ways won't work).
Here is my code:
const CosmosClient = require('#azure/cosmos').CosmosClient;
var https = require('https');
var http = require('http');
var request = require('request');
const endpoint = "someEndpoint";
const masterKey = "anymasterkey";
const database = {
"id": "Database"
};
const container = {
"id": "Container1"
};
const databaseId = database.id;
const containerId = container.id;
const client = new CosmosClient({
endpoint: endpoint,
auth: {
masterKey: masterKey
}
});
module.exports = function (context, req) {
const country = "de";
const bban = 12345678;
const querySpec = {
query: "SELECT * FROM Container1 f WHERE f.country = #country AND f.bban = #bban",
parameters: [{
name: "#country",
value: country
},
{
name: "#bban",
value: bban
}
]
};
getContainers(querySpec).then((results) => {
const result = results[0];
context.log('here before request');
var options = {
host: 'example.com',
port: '80',
path: '/test',
method: 'POST'
};
// Set up the request
var req = http.request(options, (res) => {
var body = "";
context.log('request');
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
context.res = body;
context.done();
});
}).on("error", (error) => {
context.log('error');
context.res = {
status: 500,
body: error
};
context.done();
});
req.end();
// request({
// baseUrl: 'someURL',
// port: 443,
// uri: 'someuri',
// method: 'POST',
// headers: {
// 'Content-Type': 'text/xml;charset=UTF-8',
// 'SOAPAction': 'someaction'
// },
// function (error, response, body) {
// context.log('inside request')
// if (error) {
// context.log('error', error);
// } else {
// context.log('response');
// }
// }
// })
})
};
async function getContainers(querySpec) {
const {container, database} = await init();
return new Promise(async (resolve, reject) => {
const {
result: results
} = await container.items.query(querySpec).toArray();
resolve(results);
})
}
async function init() {
const {
database
} = await client.databases.createIfNotExists({
id: databaseId
});
const {
container
} = await database.containers.createIfNotExists({
id: containerId
});
return {
database,
container
};
}
The last thing that happens is the print of "here before request". After that the function just does nothing until it timesout. So what am I doing wrong? Can't I just this combination of await/async and requests?
As commented you are not sending any data to the POST call. You need to have a req.write before the req.end
req.write(data);
req.end();
That is why the POST call is failing for you. After this fix, it should work

Categories