How to make context request in dialogoflow via nodejs sdk? - node.js

I would like to know how to create a context dialog, but I don't think anything about how to make this request... can anyone help me?
i'm using a lib sdk dialogflow
I searched how to do this, but I don't find anything, I don't know how to implement this..
me code
class DialogFlowController {
public dialogID: string
public sessionID: string
public sessionClient: SessionsClient
constructor () {
this.dialogID = 'chatbot-asxj'
this.sessionID = v4()
this.sessionClient = new dialogflow.SessionsClient({
credentials: {
type: config.gooogleType,
client_id: config.googleClientId,
private_key: config.googlePrivateKey,
client_email: config.googleCLientEmail,
token_url: config.googleTokenUrl
}
})
}
public async interactor (req: Request, res: Response): Promise<Response> {
console.log(teste)
const messagem = req.body.goMessage
try {
// Create a new session
const sessionPath = this.sessionClient.projectAgentSessionPath(this.dialogID, this.sessionID)
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: messagem,
// The language used by the client (en-US)
languageCode: 'en-US'
}
}
}
const response = await this.sessionClient.detectIntent(request)
Socket.io.emit('returnMessage', response[0].queryResult?.fulfillmentText)
return res.status(200).json()
} catch (err) {
return res.status(500).json(err)
}
}
}

Related

ApolloServer (NodeJS): Return string response

I have an ApolloServer with default settings such as:
class AuditRemoteGraphQLDataSource extends RemoteGraphQLDataSource {
...
}
const gateway = new ApolloGateway({
serviceList,
buildService: ({url}) => new AuditRemoteGraphQLDataSource({url})
});
const server = new ApolloServer({
debug: false,
gateway,
context: async ({req}) => {
.........
}
Upon making a request (query/mutation), we expect:
{
"data": {
"something": "somevalue"
}
}
This works fine. The challenge I am having is that for a specific GET request, I want to return a string as is. I tried to extend:
async didReceiveResponse(response, req, context) {
const body = await super.didReceiveResponse(response, req, context);
body.data = "someString";
return body;
}
But it did not help.

"Can't Buy With This Account" POST Request Error When Using The Buys Endpoint To Buy Bitcoin

My goal is to try and get a Node app (written in Typescript) to buy bitcoin using my "GBP Wallet" (fiat account). I am currently trying this via using the Axios library, rather than any unofficial Coinbase client libraries out there. I am successfully able to get data that I need from the GET endpoints of the Coinbase API. However, with the following POST endpoint I get an error:
POST https://api.coinbase.com/v2/accounts/:account_id/buys
The error:
[ { id: 'invalid_request', message: "Can't buy with this account" } ]
Here is a simplified example of the code I am trying to run at the moment:
import * as crypto from 'crypto';
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse, Method } from 'axios';
import * as dotenv from 'dotenv';
dotenv.config();
const timer = (ms: number) => new Promise(res => setTimeout(res, ms));
function isNumeric(str: string): boolean {
const noSpacesStr = str.replace(/\s/g, '');
return !isNaN(Number(noSpacesStr)) && noSpacesStr.length !== 0;
}
async function coinbaseApiRequest(url: string, method: Method, data?: any): Promise<AxiosResponse> {
if (process.env.COINBASE_API_KEY === undefined || process.env.COINBASE_API_SECRET === undefined) {
throw new Error('Missing credentials');
}
const stringData = JSON.stringify(data);
const timestamp = Math.floor(Date.now() / 1000);
const message = data === undefined ? timestamp.toString() + method + url : timestamp.toString() + method + url + stringData;
const signature = crypto.createHmac("sha256", process.env.COINBASE_API_SECRET).update(message).digest("hex");
const config: AxiosRequestConfig = {
method,
url: `https://api.coinbase.com${url}`,
headers: {
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': process.env.COINBASE_API_KEY,
'CB-VERSION': '2021-05-19',
'Content-Type': 'application/json'
},
data
};
return axios(config);
}
async function getBuyPrice(): Promise<AxiosResponse> {
return coinbaseApiRequest('/v2/prices/BTC-GBP/buy', 'GET');
}
async function getSellPrice(): Promise<AxiosResponse> {
return coinbaseApiRequest('/v2/prices/BTC-GBP/sell', 'GET');
}
async function getGBPAccount(): Promise<AxiosResponse> {
return coinbaseApiRequest('/v2/accounts/GBP', 'GET');
}
async function getBitcoinAccount(): Promise<AxiosResponse> {
return coinbaseApiRequest('/v2/accounts/BTC', 'GET');
}
async function getGBPWalletPaymentMethodID(): Promise<string> {
const paymentMethods = await coinbaseApiRequest('/v2/payment-methods', 'GET');
for (let i = 0; i < paymentMethods.data.data.length; i++) {
const paymentMethod = paymentMethods.data.data[i];
if (paymentMethod.name === 'GBP Wallet' && paymentMethod.type === 'fiat_account') {
return paymentMethod.id;
}
}
throw new Error('GBP wallet has not been found');
}
async function postBuyBitcoin(accountId: string, amount: string, paymentMethod: string): Promise<AxiosResponse> {
if (!isNumeric(amount)) { throw new Error('amount arg is not a valid number'); }
const body = { amount, currency: 'BTC', payment_method: paymentMethod };
return coinbaseApiRequest(`/v2/accounts/${accountId}/buys`, 'POST', body);
}
async function run(): Promise<void> {
try {
const oldGBPAccRes = await getGBPAccount();
const oldBTCAccRes = await getBitcoinAccount();
const paymentMethodID = await getGBPWalletPaymentMethodID();
const buyRes = await postBuyBitcoin(oldGBPAccRes.data.data.id, '0.00001', paymentMethodID);
const newGBPAccRes = await getGBPAccount();
const newBTCAccRes = await getBitcoinAccount();
console.log(`old GBP account response:`);
console.log(oldGBPAccRes.data);
console.log(`old BTC account response:`);
console.log(oldBTCAccRes.data);
console.log(`bitcoin buy response:`);
console.log(buyRes);
console.log(`new GBP account response:`);
console.log(newGBPAccRes.data);
console.log(`new BTC account response:`);
console.log(newBTCAccRes.data);
console.log('Finished payment');
} catch (error: any | AxiosError) {
if (axios.isAxiosError(error)) {
console.log(error.response?.data.errors);
}
}
}
run();
All the GET request functions seem to work fine and return the responses correctly when I run them individually. The only issue I have is with the POST request function. I get the following error logged when running the code above:
[ { id: 'invalid_request', message: "Can't buy with this account" } ]
Not sure why this is happening, and there does not seem to be much on this online relevant to node based implementations, but this seems to be somewhat related. would appreciate some guidance. Thanks in advance.

Unable to get input contexts through to dialogflow using node js

I have been trying to get input contexts to flow into dialogflow via node.js but i cant seem to get it working in any way. Here is what I have so far and sorry I am not at node so any pointers would be a massive help.
It doesnt fail or say there is an error I just never see the input contexts hit the back end.
Thanks for you time
Steve
async function createContext(sessionId, contextId, parameters, lifespanCount = 1) {
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
const contextsClient = new dialogflow.ContextsClient();
const contextPath = contextsClient.contextPath(
projectId,
sessionId,
contextId
);
const request = {
parent: sessionPath,
context: {
name: contextPath,
parameters: struct.encode(parameters),
lifespanCount: lifespanCount
}
};
const [context] = await contextsClient.createContext(request);
return context;
}
// hook it up to the question and answer through the chatbot api
async function detectIntent(
projectId,
sessionId,
query,
contexts,
languageCode
) {
// The path to identify the agent that owns the created intent.
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
queryParams: {
contexts: [contexts],
}
};
const responses = await sessionClient.detectIntent(request);
return responses[0];
}
async function requestChatBot(textdata) {
let intentResponse;
let context = "";
const parameters = {
welcome: true
};
context = await createContext(callId, 'welcome-context', parameters);
intentResponse = await detectIntent(
projectId,
callId,
textdata,
context,
languageCode
);
}
modify your "request" to
const request = {
session: sessionPath,
queryParams: {
contexts: [{
name: 'projects/' + projectId + '/agent/sessions/' + sessionId + '/contexts/' + "Name of the context you want to pass",
lifespanCount: provide life span of your context (Integer Value),
}]
},
queryInput: {
text: {
// The query to send to the dialogflow agent
text: userQuery,
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
This works.

User is not available in request with NestJS passport strategy (other than documentation exemples)

I'm trying to implement a passport strategy (passport-headerapikey), I was able to make it work and I can secure my routes.
But the request is empty and cannot access the logged in user ?
import { HeaderAPIKeyStrategy } from "passport-headerapikey";
import { PassportStrategy } from "#nestjs/passport";
import { Injectable, NotFoundException } from "#nestjs/common";
import { CompanyService } from "../../companies/companies.service";
#Injectable()
export class ApiKeyStrategy extends PassportStrategy(HeaderAPIKeyStrategy, "api-key") {
constructor(private readonly companyService: CompanyService) {
super(
{
header: "Authorization",
prefix: "Api-Key "
},
true,
async (apiKey, done) => {
return this.validate(apiKey, done);
}
);
}
public async validate(apiKey: string, done: (error: Error, data) => {}) {
const company = await this.companyService.findByApiKey(apiKey);
if (company === null) {
throw new NotFoundException("Company not found");
}
return company;
}
}
#UseGuards(AuthGuard("api-key"))
export class CompaniesController {
constructor(private companyService: CompanyService) {}
#Get()
#ApiOperation({ title: "Get company information" })
public getCompany(#Request() req) {
// here request is empty, so i cannot access the user..
console.log("request", req);
return [];
}
}
Thanks for your help !
To access the logged user, you can inject the object in the request. To do that, in your ApiKeyStrategy constructor, change the third parameter to something like this:
async (apiKey, verified, req) => {
const user = await this.findUser(apiKey);
// inject the user in the request
req.user = user || null;
return verified(null, user || false);
}
Now, you can access the logged user:
getCompany(#Request() req) {
console.log(req.user);
}
I hope that could help you.
As show in the documentation you should do some works to get the current user : here the documetation
First of all in the app.module make sure that the context is set :
context: ({ req }) => ({ req })
Then you can add this in the controller/resolver, this example use the Gql (GraphQL):
export const CurrentUser = createParamDecorator(
(data: unknown, context: ExecutionContext) => {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req.user;
},
);
if this one doesnt work for you try this one instead :
export const CurrentUser = createParamDecorator(
(data: unknown, context: ExecutionContext) => {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext();
request.body = ctx.getArgs();
return request.user;
},
);
Modify your validate method like so:
public async validate(apiKey: string, done: (error: Error, data) => {}) {
const company = await this.companyService.findByApiKey(apiKey);
if (company === null) {
return done(new NotFoundException("Company not found"), null);
}
return done(null, company);
}

how to call a event in the dialogflow v2 :nodejs

I'm using dialogflow v2 using npm. I just want call a welcome event in dialogflow. How can I do it in the nodejs. I'm pretty new to it.
This is my code
const projectId = "xxxxxx";
const LANGUAGE_CODE = 'en-US';
const sessionId = req.body.sessionId;
var query = req.body.query;
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId,sessionId);
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: LANGUAGE_CODE,
},
},
};
sessionClient.detectIntent(request).then(response => {
console.log('intent detected');
const result = response[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if(result.fulfillmentText) {
console.log(result.fulfillmentText);
return res.json({reply: result.fulfillmentText})
}
// if(result.intent) {
// console.log(` Intent: ${result.intent.displayName}`)
// }
else {
console.log('no intent found');
}
}).catch(err => {
console.log('error '+err);
})
As I open the chat page I just want to throw a welcome message. In order to do that, i read that i have to call the event. How can I do that? I have taken the reference from here
The Request body should be like this:
let eventName='WELCOME'; //name of the event
let request = {
session: sessionPath,
queryInput: {
event: {
name: eventName,
languageCode: 'en-US'
},
},
};
checkout- https://github.com/googleapis/nodejs-dialogflow/blob/master/samples/detect.js#L96
let me know if you find any difficulties :)
I would suggest using actions-on-google as it is much easier to build nodejs backend for dialogflow link : actions on google
And for sample project refer Number genie project
Hope this would help you.

Resources