Dialogflow webhook fulfillment parameter not accessible - node.js

I want to get input of a parameter in my webhook fulfillment.
Here is the my code:
const bodyParser = require('body-parser')
var request = require('request-promise-native');
const { dialogflow } = require('actions-on-google');
const assistant = dialogflow({
clientId: "30xxxxx08407-rv9kxxxxxxxxuuq8f9ul2eg.apps.googleusercontent.com"
});
module.exports = (app) => {
const logger = console;
assistant.intent('Sales', conv => {
const pcode = agent.parameters['PCODE'];
console.log(pcode)
const token = '3369708919812376';
const serviceID = '502';
const P_STATE_CD = 'ALL';
const P_FO_CD = 'ALL';
const P_DISTT_CD = 'ALL';
const P_DATE = '16/12/2019';
const P_PRD_GROUP = 'UREA';
const P_PERSONAL_NO = '106296';
var data = {"token" : token,"serviceID" : serviceID,"P_STATE_CD" : P_STATE_CD,"P_FO_CD" : P_FO_CD,"P_DISTT_CD" : P_DISTT_CD,"P_DATE" : P_DATE,"P_PRD_GROUP" : P_PRD_GROUP,"P_PERSONAL_NO" : P_PERSONAL_NO };
var sdata = JSON.stringify(data);
const options = {
method: 'POST',
uri: 'http://Webservice/resources/webservice/service' ,
body: JSON.parse(sdata) ,
json: true
}
return request(options)
.then( body => {
var unit = body
console.log(body)
unit.intent = "Sales"
unit.value1 = unit.saleInfo[0].QMTD
unit.value2 = unit.saleInfo[0].QYTD
unit.value3 = unit.saleInfo[0].O_UOM
unit.value4 = null
unit.value5 = null
delete unit.saleInfo
var unit2 = JSON.stringify(unit)
console.log(unit2)
conv.ask(unit2);
})
.catch( err => {
console.error( err );
conv.ask('Something went wrong. What should I do now?');
});
})
I tried with const pcode = agent.parameters.PCODE but it is not working. Giving me error:
ReferenceError: agent is not defined
at assistant.intent.conv (/home/dbalounge/GoogleDF/service.js:15:16)
at Function. (/home/dbalounge/GoogleDF/node_modules/actions-on-google/dist/service/dialogflow/dialogflow.js:151:27)
at Generator.next ()
at /home/dbalounge/GoogleDF/node_modules/actions-on-google/dist/service/dialogflow/dialogflow.js:22:71
at new Promise ()
at __awaiter (/home/dbalounge/GoogleDF/node_modules/actions-on-google/dist/service/dialogflow/dialogflow.js:18:12)
at Function.handler (/home/dbalounge/GoogleDF/node_modules/actions-on-google/dist/service/dialogflow/dialogflow.js:85:16)
at Object. (/home/dbalounge/GoogleDF/node_modules/actions-on-google/dist/assistant.js:55:32)
at Generator.next ()
at /home/dbalounge/GoogleDF/node_modules/actions-on-google/dist/assistant.js:22:71

agent is not defined anywhere in your code, that's why you're getting:
ReferenceError: agent is not defined
In any case if you use assistant.parameters won't work either. Dialogflow intent parameters can be accessed through the second argument of .intent callback.
assistant.intent('Sales', (conv, params) => {
const pcode = params.PCODE;
/* ... */
})
For more info you can check the docs

Related

How can i get a client side cookie with next.js 13 before rendering from middleware

I am trying to get a cookie from the middleware of Nextjs 13 and I can't find up to date information on this.
My question: is there a way to see the cookie before rendering the html.
window is fined or something?
page.tsx
async function getData() {
const nextCookies = cookies(); // Get cookies object
try {
let cityToken = nextCookies.get('regionCode'); // Find cookie city
return cityToken;
} catch (e) {
console.log(e);
}
}
export default async function Page() {
const nextCookies = cookies(); // Get cookies object
const token = nextCookies.get('new'); // Find cookie for is new user
// const cityToken = await getData();
const cityToken = cookies().get('regionCode')?.value;
console.log(cityToken);
}
middleware.tsx
const myFunction = async () => {
// https://geolocation.onetrust.com/cookieconsentpub/v1/geo/location
// run asynchronous tasks here - ip location
const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace');
const text = await response.text();
const arr = text.split('\n');
const ip = arr.filter((v) => v.includes('ip='))[0].split('=')[1];
// https://stackoverflow.com/questions/65752416/how-can-i-most-easily-parse-this-http-response-into-json-to-then-access-response
// https://stackoverflow.com/questions/64591296/access-to-fetch-at-https-www-cloudflare-com-cdn-cgi-trace-from-origin-http
const ipCity = await fetch(`https://ipapi.co/${ip}/json/`);
const textJson = await ipCity.json();
};
const data = await myFunction();
res.cookies.set('regionCode', 'textJson.region');

Unable to stub an exported function with Sinon

I need to test the following createFacebookAdVideoFromUrl() that consumes a retryAsyncCall that I'd like to stub with Sinon :
async function createFacebookAdVideoFromUrl(accountId, videoUrl, title, facebookToken = FACEBOOK_TOKEN, options = null, businessId = null) {
const method = 'POST';
const url = `${FACEBOOK_URL}${adsSdk.FacebookAdsApi.VERSION}/${accountId}/advideos`;
const formData = {
access_token: businessId ? getFacebookConfig(businessId).token : facebookToken,
title,
name: title,
file_url: videoUrl,
};
const callback = () => requestPromise({ method, url, formData });
const name = 'createFacebookAdVideoFromUrl';
const retryCallParameters = buildRetryCallParameters(name, options);
const adVideo = await retryAsyncCall(callback, retryCallParameters);
logger.info('ADVIDEO', adVideo);
return { id: JSON.parse(adVideo).id, title };
}
This retryAsyncCall function is exported as such:
module.exports.retryAsyncCall = async (callback, retryCallParameters, noRetryFor = [], customRetryCondition = null) => {
// Implementation details ...
}
Here is how I wrote my test so far:
it.only("should create the video calling business's Facebook ids", async () => {
const payload = createPayloadDataBuilder({
businessId: faker.internet.url(),
});
const retryAsyncCallStub = sinon.stub(retryAsyncCallModule, 'retryAsyncCall').resolves('random');
const createdFacebookAd = await FacebookGateway.createFacebookAdVideoFromUrl(
payload.accountId,
payload.videoUrl,
payload.title,
payload.facebookToken,
payload.options,
payload.businessId,
);
assert.strictEqual(retryAsyncCallStub.calledOnce, true);
assert.strictEqual(createdFacebookAd, { id: 'asdf', title: 'asdf' });
});
I don't expect it to work straightaway as I am working in TDD fashion, but I do expect the retryAsyncCall to be stubbed out. Yet, I am still having this TypeError: Cannot read property 'inc' of undefined error from mocha, which refers to an inner function of retryAsyncCall.
How can I make sinon stubbing work?
I fixed it by changing the way to import in my SUT :
// from
const { retryAsyncCall } = require('../../../helpers/retry-async');
// to
const retry = require('../../../helpers/retry-async');
and in my test file :
// from
import * as retryAsyncCallModule from '../../../src/common/helpers/retry-async';
// to
import retryAsyncCallModule from '../../../src/common/helpers/retry-async';
The use of destructuring seemed to make a copy instead of using the same reference, thus, the stub was not applied on the right reference.

DiscordAPIError: Invalid Form Body Code : 50035 , Slash commands

Hello So I was developing my own slash command handler for the Discord.js v13 bot
But I have run into a snag.... When I collect the array of all slash commands and their respective options to register into the commands.set() method I get an error which is :
**> throw new DiscordAPIError(data, res.status, request);
> ^
>
> DiscordAPIError: Invalid Form Body options[2]: Required options must
> be placed before non-required options
> at RequestHandler.execute (C:\Users\Mihir\Desktop\FunMod\node_modules\discord.js\src\rest\RequestHandler.js:350:13)
>
> at processTicksAndRejections (node:internal/process/task_queues:96:5)
> at async RequestHandler.push (C:\Users\Mihir\Desktop\FunMod\node_modules\discord.js\src\rest\RequestHandler.js:51:14)
> at async GuildApplicationCommandManager.set (C:\Users\Mihir\Desktop\FunMod\node_modules\discord.js\src\managers\ApplicationCommandManager.js:146:18)
> at async Object.execute (C:\Users\Mihir\Desktop\FunMod\slashregistering.js:71:13) { method:
> 'put', path:
> '/applications/922152514420363285/guilds/933052184432636014/commands',
> code: 50035, httpStatus: 400,**
This is the complete code of the slashregistering.js ( pls ignore the code typing style... )
**const fs = require('fs')
const db= require('quick.db')
module.exports = {
async execute(client){
const categories = ['MODERATION' , 'FUN' ,'ACTIONS' , 'UTILITY']
const registeredCommandsArray = new Array()
const guildId = '933052184432636014'
const guild = client.guilds.cache.get(guildId)
//console.log(client.guilds.cache);
let commands
var commandsarray = new Array()
if(guild){
commands = guild.commands
}
else{
commands = client.application?.commands
}
//console.log(commands)
let data
data = await db.get('slashcommands')
if(data){
var scommands = new Array()
var unRegisteredCommands
const slashcommands = await guild.commands.fetch()
unRegisteredCommands = slashcommands.filter(a => !data.includes(a.name))
for(var e in unRegisteredCommands){
scommands.push(e.name)
}
for(const category of categories){
for(const file of scommands){
const command = require(`./slashcommands/${category}/${file}.js`)
//console.log(command , category)
commandsarray.push({
name : command.name,
description : command.description,
options : command.options
})
}
}
data.concat(scommands)
//console.log(data)
commands.set(commandsarray)
console.log(`Loaded ${scommands.length} commands.`)
await db.set('slashcommands' , data)
}
else{
for(const category of categories){
const slashCommandFiles = fs.readdirSync(`./slashcommands/${category}`).filter(file => file.endsWith('.js'))
for(const file of slashCommandFiles){
const command = require(`./slashcommands/${category}/${file}`)
//console.log(command , category)
commandsarray.push({
name : command.name,
description : command.description,
options : command.options
})
registeredCommandsArray.push(command.name)
}
}
console.log(`Loaded ${registeredCommandsArray.length} commands.`)
await commands.set(commandsarray)
await db.set('slashcommands' , registeredCommandsArray)
}
}
}**
Its all working fine until I reach the commands.set(commandsarray) ... Please help ! and thanks in advance!

Dialogflow webhook fulfillment parameter is not working in post API

I make a code in webhook were i want invoke POST API and i want to invoke that api for that i have to pass some parameter but whenever i am trying to pass parameter coming from dialogflow its gives error. My code is like that
//Self Hosted Express Server
const bodyParser = require('body-parser')
var request = require('request-promise-native');
const { dialogflow } = require('actions-on-google');
const assistant = dialogflow({
clientId: "305xxxxxx7-rv9kocdq2xxxxouuq8f9ul2eg.apps.googleusercontent.com"
});
module.exports = (app) => {
const logger = console;
assistant.intent('Sales',(conv, params) => {
var pcode = params.myproduct;
// console.log(pcode)
const token = '3369708919812376';
const serviceID = '502';
const P_STATE_CD = 'ALL';
const P_FO_CD = 'ALL';
const P_DISTT_CD = 'ALL';
const P_DATE = '16/12/2019';
const P_PRD_GROUP = pcode;
const P_PERSONAL_NO = '106296';
var data = {"token" : token,"serviceID" : serviceID,"P_STATE_CD" : P_STATE_CD,"P_FO_CD" : P_FO_CD,"P_DISTT_CD" : P_DISTT_CD,"P_DATE" : P_DATE,"P_PRD_GROUP" : P_PRD_GROUP ,"P_PERSONAL_NO" : P_PERSONAL_NO };
var sdata = JSON.stringify(data);
const options = {
method: 'POST',
uri: 'http://chatbotWebservice/resources/webservice/service' ,
body: JSON.parse(sdata) ,
json: true
}
return request(options)
.then( body => {
var unit = body
unit.intent = "Sales"
unit.value1 = unit.saleInfo[0].QMTD
unit.value2 = unit.saleInfo[0].QYTD
unit.value3 = unit.saleInfo[0].O_UOM
unit.value4 = null
unit.value5 = null
delete unit.saleInfo
var unit2 = JSON.stringify(unit)
console.log(unit2)
conv.ask(unit2);
})
.catch( err => {
console.error( err );
conv.ask('Something went wrong. What should I do now?');
});
})
And the error like this
TypeError: Cannot read property '0' of undefined
at request.then.body (/home/dbalounge/GoogleDF/service.js:40:44)
at process._tickCallback (internal/process/next_tick.js:68:7)
Please help me out this. Thank You in Advance
Apparently body is coming as a string, probably because the server is not setting the correct Content-Type to the response, and request is ignoring json: true option. So you should use JSON.parse on it, and then access the saleInfo
return request(options)
.then( body => {
var unit = JSON.parse(body)
unit.intent = "Sales"
unit.value1 = unit.saleInfo[0].QMTD
/* ... */
});
Aside from that body: JSON.parse(sdata) in your call is not needed, you're stringifying data to sdata to parse it back again, just use data directly:
const options = {
method: 'POST',
uri: 'http://chatbotWebservice/resources/webservice/service' ,
body: data,
json: true
}

express router, req.body undefined

I have a post interface that does not submit data correctly.
test shows: req.body undefined
const express = require('express');
const router = express.Router();
const passport = require("passport");
const passportInfo = passport.authenticate('jwt',{ session: false });
const HomeSchema = require('../../../models/AnvizHome');
const homeBannerValidator = require('../../../validation/anviz/homeBanner');
router.post("/banner",passportInfo,(req,res) => {
const {msg,isValid} = homeBannerValidator(req.body);
if(!isValid){
return res.status(400).json(msg);
}
HomeSchema.findOne({handle:req.body.handle}).then(banner => {
console.log('current: ' + req.body);
const newBanner = {
bannerBg:req.body.bannerBg,
bannerName:req.body.bannerName,
bannerSubName:req.body.bannerSubName,
bannerFeather:req.body.bannerFeather,
bannerLink:req.body.bannerLink
};
banner.prodcutBanner = newBanner;
banner.then(home => res.json(home));
})
.catch((err) => res.json(err));
});
module.exports = router;
postman test:
In fact, the terminal can see the returned data.
[Object: null prototype] {
bannerBg: '5555555555555555555555555555555555',
bannerName: 'THE GLOBAL LEADING',
bannerSubName: 'PROVIDER OF INTELLIGENT SECURITY',
bannerLink: 'www.anviz.com',
handle: 'true' }
Seeking one or two!Thank you!
you forgot to import and use body parser
https://www.npmjs.com/package/body-parser
var bodyParser = require('body-parser');
var express = require('express');
express.use(bodyParser.json());
express.use(bodyParser.urlencoded({ extended: false }));
I think I know the reason, because this is based on the user's token to submit data, so must be in the post according to the user id to determine whether the data is successful?
Here is the code that has been successfully saved, but I don't know right and wrong:
router.post("/banner",passportInfo,(req,res) => {
const {msg,isValid} = homeBannerValidator(req.body);
if(!isValid){
return res.status(400).json(msg);
}
const profileFields = {};
profileFields.prodcutBanner = {};
if(req.body.handle) profileFields.handle = req.body.handle;
if(req.body.bannerBg) profileFields.prodcutBanner.bannerBg = req.body.bannerBg;
if(req.body.bannerName) profileFields.prodcutBanner.bannerName = req.body.bannerName;
if(req.body.bannerSubName) profileFields.prodcutBanner.bannerSubName = req.body.bannerSubName;
if(req.body.bannerFeather) profileFields.prodcutBanner.bannerFeather = req.body.bannerFeather;
if(req.body.bannerLink) profileFields.prodcutBanner.bannerLink = req.body.bannerLink;
HomeSchema.findOne({user: req.user.id}).then(profile => {
if(profile){
HomeSchema.findByIdAndUpdate({user: req.user.id},{$set:profileFields},{new:true}).then(profile => res.json(profile));
}else{
HomeSchema.findOne({handle:profileFields.handle}).then(profile => {
if(profile){
msg.handle = "The user's handle personal information already exists, please do not re-create it!";
res.status(400).json(msg);
}
new HomeSchema(profileFields).save().then(profile => res.json(profile));
})
}
})
.catch((err) => res.json(err));});
module.exports = router;

Resources