Dialogflow function deployment issues on Node.js/Firebase - javascript

I am trying to send user SMS texts to Dialogflow in a Firebase function, however I'm receiving the following error when I deploy my functions. The code for Dialogflow was copied off the DF Node.js library.
error Move function declaration to function body root
This is referring to async function dialogflowMessage() line. Maybe I don't fully understand async/await yet, but it seems like my function needs to be nested within the original receive SMS function. Below is my complete function code for handling incoming texts, checking if SMS, and sending to DF.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({ origin: true});
const serviceAccount = require('./service-account.json'); //firebase service account
const serviceKey = require('./service-key.json'); //Dialogflow service key
const express = require('express');
const async = require('async');
const http = require('http');
const bodyParser = require('body-parser');
const accountSid = 'REDACTED'; //Twilio acct sid
const authToken = 'REDACTED'; //Twilio auth token
const twilioNumber = '+REDACTED'; //Twilio phone number
const client = require('twilio')(accountSid, authToken);
const MessagingResponse = require('twilio').twiml.MessagingResponse;
const dialogflow = require('dialogflow');
const uuid = require('uuid');
const {Storage} = require('#google-cloud/storage');
exports.processMsg = functions.https.onRequest((request, response) => {
const twiml = new MessagingResponse();
const sid = request.body.MessageSid;
const body = request.body.Body;
if (sid.startsWith('SM', 0)) {
//Start Dialogflow
async function dialogflowMessage(projectId = 'REDACTED-PROJECT-ID') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: body,
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
}
//end Dialogflow
} else if (sid.startsWith('MM', 0)) {
twiml.message(`This is an image!! ${media}`);
} else {
twiml.message(
'No Body param match, Twilio sends this in the request to your server.'
);
}
response.writeHead(200, {'Content-Type': 'text/xml'});
response.end(twiml.toString());
});

exports.processMsg = functions.https.onRequest((request, response) => {
const twiml = new MessagingResponse();
const sid = request.body.MessageSid;
const body = request.body.Body;
if (sid.startsWith('SM', 0)) {
dialogflowMessage('REDACTED-PROJECT-ID')
} else if (sid.startsWith('MM', 0)) {
twiml.message(`This is an image!! ${media}`);
} else {
twiml.message(
'No Body param match, Twilio sends this in the request to your server.'
);
}
async function dialogflowMessage(projectId = 'REDACTED-PROJECT-ID') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: body,
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
}
response.writeHead(200, {'Content-Type': 'text/xml'});
response.end(twiml.toString());
});

Related

Cannot get jwt token from cookies

I am using mern stack to make one website. I am using jwt and trying to store them in cookies. I invoked the res.cookie function with parameters(you can find the code below). But somehow I cannot find the cookie in the browser.
no cookie found(top portion) whereas name of cookie(=jwt) found in network tab in inspect. Please look at this screenshot
But when I check the network tab in the inspect, there is a cookie present in Set-cookie.
Assuming that the cookie has been stored, I try to access the jwt token, but in vain.
I am providing the code below.
This is my file where all the routes are written.
const express = require ("express")
const Resident = require("../models/residentModels");
const bcrypt = require("bcrypt");
// const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const router = express.Router();
router.post("/register", async (req, res) =\> {
try {
const resident = new Resident(req.body);
console.log(req.body);
// password hash
// middleware
const token = await resident.generateAuthToken();
console.log("token: " + token);
res.cookie("jwt", token, {
httpOnly: true,
expires: new Date (Date.now() + 12342)
})
// console.log(cookie);
const newResident = await resident.save();
console.log("hehe" + newResident);
// console.log(newResident._id);
// console.log(newResident._id.toString());
res.status(200).send("Record Added Successfully");
} catch (error) {
console.log(error);
res.status(200).send("Record Creation Unsuccessfull");
}
})
router.post("/login", async (req, res) =\> {
try {
let blockNumber = req.body.blockNumber;
let flatNumber = req.body.flatNumber;
let password = req.body.password;
console.log(blockNumber)
console.log(flatNumber)
console.log(password)
const response = await Resident.findOne({blockNumber: blockNumber, flatNumber:flatNumber});
console.log(response);
const isMatch = await bcrypt.compare(password, response.password);
console.log("isMatch: " + isMatch);
const token = await response.generateAuthToken();
console.log("token part: " + token);
let cookie = res.cookie("jwt", token, {
httpOnly: true,
expires: new Date (Date.now() + 10000)
})
// console.log(cookie)
// console.log(`this is the cookie awesome !! + ${req.cookies.jwt}`);
let jwtToken = req.cookies;
console.log("req.cookies.jwt: " + jwtToken);
if(isMatch){
res.status(200).send("Successful Login");
}
else{
res.status(200).send("Invalid Login Details");
}
} catch (error) {
res.status(200).send("Invalid Login Details");
}
});
module.exports = router;
This is my index.js file :
const express = require("express");
require('./db/conn');
const Resident = require("./routes/residentRoutes");
var cors = require("cors");
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cors());
app.use(express.json());
app.use(Resident);
app.use(cookieParser());
const port = process.env.PORT || 8000;
const bcrypt = require("bcrypt");
const securePassword = async (password) =\> {
const passwordHash = await bcrypt.hash(password, 10);
console.log(passwordHash);
const passwordMatch = await bcrypt.compare(password, passwordHash)
console.log(passwordMatch);
}
securePassword("thapa#123");
const createToken = async () =\> {
const token = await jwt.sign({\_id: "63e677a57d45b06c8557441a"}, "thisisnotformyresumebutmyideology!!!",{
expiresIn: "20 seconds"
})
console.log(token);
const userVerify = await jwt.verify(token, "thisisnotformyresumebutmyideology!!!");
console.log(userVerify); // returns an object
}
createToken();
app.listen(port, () =\> {
console.log(`connection successful at port ${port}`);
})
In the file where all the routes are written, the variable jwtToken returns "undefined".
As a result, it is evident that the cookie was not stored.
So now the question arises how do I store the cookies and where am I doing wrong?
P.S.: I am using React.js in the frontend.
My Login.jsx file looks like this:
import axios from 'axios';
import React from 'react'
import { NavLink, useNavigate } from 'react-router-dom'
const Login = () => {
let navigate = useNavigate();
const loginButton = async (event) => {
event.preventDefault();
// console.log(event.target[0].value); // block number
let blockNumber = event.target[0].value;
let flatNumber = event.target[1].value;
let password = event.target[2].value;
const response = await axios.post('http://localhost:8000/login', {
blockNumber: blockNumber,
flatNumber: flatNumber,
password: password
})
// console.log("response :" + response.data);
console.log(response);
if(response.status === 200){
navigate("/dashboard");
}
else{
alert("Invalid Login Details");
}
}
return (
<>
<h1> Login </h1>
<form onSubmit={loginButton}>
<input type="number" placeholder='Block Number *' />
<input type="number" placeholder='Flat Number *' />
<input type="password" placeholder='Password *' />
<button type="submit">Login</button>
<NavLink to='/register'>or Click to Register</NavLink>
</form>
</>
)
}
export default Login
In your index.js file
Swap these two from:
app.use(Resident);
app.use(cookieParser());
to:
app.use(cookieParser());
app.use(Resident);
You need to parse the request first before accessing the routes
The sequence matter how you place your code
can you see the cookies in the application tab of browser developer tools?
If you can, are you using axios? If so, it might be because of that, you need to add withCredentials: true in the axios constructor.
axios("http://someurl", {
method: "post",
data: someJsonData,
withCredentials: true
})

Rest API, take request fields. handle

I stood in a stupor. And I need help.
I do rest full api on express
I want to do this if a request comes in type: reset_password -> I sent an email to reset my password.(it can be both registration and auth)
But I don't know how to pass it into a query. And that is, how to do it.
I trimmed the code.
const send = async (req, res) => {
const key = req.query.apiKey;
const type = req.query.type;
const to = req.query.to;
if (err) {
console.log(err);
} else if (rows.length == 0) {
res.status(401).json({"apiKey":"error"})
} else {
if (email.validate(to)) {
sendmail(type, to)
} else {
res.status(422)
}
}
}
sendmail:
const nodemailer = require("nodemailer");
const ejs = require('ejs')
const path = require('path')
const sendmail = async (type, to, url) => {
try {
const reset_password = path.join(__dirname, "../template/resetpassword.ejs")
const signup_auth = path.join(__dirname, "../template/signupauth.ejs")
const sign_in_auth = path.join(__dirname, "../template/signinauth.ejs")
const data = await ejs.renderFile(reset_password,signup_auth,sign_in_auth, { to, url } )
let testAccount = await nodemailer.createTestAccount();
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: testAccount.user, // generated ethereal user
pass: testAccount.pass, // generated ethereal password
},
});
const send = await transporter.sendMail({
from: 'dev#test.io',
to: to,
text: "Hello world?",
subject: "test",
html: ???
})
console.log("Success send: %s", nodemailer.getTestMessageUrl(send));
}catch (err) {
console.log('Error send: ' + err.message);
}
}
module.exports = sendmail;
Now I have a question. How do I send a request: reset_password,signup_auth,sign_in_auth
That is, how do I pass it on to the type: reset_password,signup_auth,sign_in_auth
http://localhost:3000/api?apiKey=key&type=reset_password,signup_auth,sign_in_auth
How do I take it and process it?
I need to accept type=auth signup reset to api rest
I'm sorry, maybe I didn't make my point correctly.

Uncaught TypeError TypeError: Cannot read property 'cache' of undefined Discord.js

I have a problem with 'cache'. I had an error before with 'guilds' that I fixed but now it's the 'cache' that has a problem.
I have this error in the console when I click on the web page
Uncaught TypeError TypeError: Cannot read property 'cache' of undefined
at <anonymous> (c:\Users\elelo\OneDrive\Bureau\bot discord serv NFT\website\public\getUserGuilds.js:29:31)
at run (c:\Users\elelo\OneDrive\Bureau\bot discord serv NFT\website\public\getUserGuilds.js:27:20)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Here is the link to the old question asked Old question guilds
Code file getUserGuilds.js
const { Permissions } = require('discord.js');
const client = require('../../index');
const schema = require('../../model/dashboard');
const jwt = require('jsonwebtoken');
const { jwt_secret } = require('../../config.json');
module.exports = {
name: "/getUserGuilds/",
run: async (req, res) => {
delete require.cache[require.resolve("../html/getUserGuilds.ejs")];
if (!req.cookies.token) return res.redirect('/login')
let decoded;
try {
decoded = jwt.verify(req.cookies.token, jwt_secret);
} catch (e) { }
if (!decoded) res.redirect('/login');
let data = await schema.findOne({
_id: decoded.uuid,
userID: decoded.userID
});
if (!data) res.redirect('/login');
let guildArray = await process.oauth.getUserGuilds(data.access_token);
let mutualArray = [];
guildArray.forEach(g => {
g.avatar = `https://cdn.discordapp.com/avatars/${g.id}/${g.icon}.png`;
if (client.guilds.cache.get(g.id)) {
const bitPermissions = new Permissions(g.permissions_new);
if (bitPermissions.has(Permissions.FLAGS.MANAGE_GUILD) || bitPermissions.has(Permissions.FLAGS.ADMINISTRATOR) || client.guilds.cache.get(g.id).ownerID == data.userID) g.hasPerm = true
mutualArray.push(g);
} else g.hasPerm = false;
});
let args = {
avatar: `https://cdn.discordapp.com/avatars/${data.userID}/${data.user.avatar}.png`,
username: data.user.username,
discriminator: data.user.discriminator,
id: data.user.userID,
loggedIN: true,
guilds: guildArray,
adminGuilds: mutualArray
};
res.render('./website/html/getUserGuilds.ejs', args);
}
}
Code file index.js
const Discord = require('discord.js');
const { Intents } = Discord;
const axios = require('axios');
const express = require("express");
const app = express()
const fs = require("fs");
const DiscordOauth2 = require('discord-oauth2');
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
const { token, clientId, clientSecret } = require('./config.json');
const client = new Discord.Client({
intents:
[
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MEMBERS
]
});
require('dotenv').config();
const prefix = "k!";
mongoose.connect(process.env.DATABASE_URI, {
autoIndex: false,
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
family: 4
}).then(() => { console.log('[Database] - La base de donnée est connectée') })
.catch(err => {console.log(err)})
app.enable("Trust proxy") // if this ip is ::1 it means localhost
app.set("etag", false) // disable cache
app.use(express.static(__dirname + "/website"))
app.set("views", __dirname)
app.set("view engine", "ejs")
app.use(cookieParser());
process.oauth = new DiscordOauth2({
clientId: clientId,
clientSecret: clientSecret,
redirectUrl: "http://localhost:90/callback"
})
client.on("ready", () => {
console.log("[BOT] - Le Bot est opérationnel");
getGas();
});
How do I fix this?
with things like this i find using client.guilds.fetch() to work better and more smoothly.
// async the forEach function param
guildArray.forEach(async g => {
g.avatar = `https://cdn.discordapp.com/avatars/${g.id}/${g.icon}.png`;
// awaits the fetching a the guild, for discord's sake
await client.guilds.fetch(g.id)
.catch(err => err) // caution of error
.then(guild => {
// bool based on if client was able to fetch guild
if (guild !== undefined) {
// if yes
const bitPermissions = new Permissions(g.permissions_new)
if (bitPermissions.has(Permissions.FLAGS.MANAGE_GUILD) ||
bitPermissions.has(Permissions.FLAGS.ADMINISTRATOR) ||
client.guilds.cache.get(g.id).ownerID == data.userID) g.hasPerm = true
mutualArray.push(g)
} else g.hasPerm = false; // if no
})
});
Why fetch and not get?
The Fetch function allows you to asynchronously request for a resource. If the request fails due to some network problems, the promise is rejected. async/await syntax fits great with fetch() because it simplifies the work with promises. Meaning, we wait on discord's time. But with a lesser chance of error.

Not able to send or receive messages on slack for a bot build using Microsoft Bot Framework

I am trying to build a slack bot using the Microsoft Bot framework. I have created a bot using bot channels registration and also running a local node.js server. I tested my bot in web chat and it works fine but not working in slack. As soon as a user adds the bot to his apps list he needs to get a message welcome, the welcome message appears in web chat but not in slack app.
//importing npm packages
const express = require('express')
const {
BotFrameworkAdapter,
MemoryStorage,
UserState
} = require('botbuilder')
const path = require("Path")
const {
WelcomeBot
} = require("./WelcomeBot")
const {
SlackAdapter
} = require('botbuilder-adapter-slack')
//environmental path variables file config
const ENV_FILE = path.join(__dirname, '.env')
require('dotenv').config({
path: ENV_FILE
})
//object creation
const app = express()
//An adapter object for botframeworkadapter
const adapter = new BotFrameworkAdapter({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword
})
// const adapter = new SlackAdapter({
// clientSigningSecret: process.env.SLACK_SECRET,
// botToken: process.env.SLACK_TOKEN
// })
adapter.onTurnError = async(context, error) => {
console.error(`\n [onTurnError] unhandled error: ${error}`)
await context.sendTraceActivity('OnTurnError Trace', `${error}`, 'https://www.botframework.com/schemas/error', 'TurnError');
await context.sendActivity('The bot encountered an error or bug')
await context.sendActivity('To continue to run this bot, please fix the bot source code')
}
const memoryStorage = new MemoryStorage()
const userState = new UserState(memoryStorage)
const bot = new WelcomeBot(userState)
app.listen(process.env.port || process.env.PORT || 3000, function() {
console.log("listening....")
})
app.get("/api/messages", (req, res) => {
res.send("Connected")
})
app.post('/', (req, res) => {
console.log(req)
const {
challenge
} = req.body;
res.send({
challenge
});
})
app.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async(context) => {
await bot.run(context)
})
})
The above is my main server file and the next is a welcome function to welcome the user:
const {
ActionTypes,
ActivityHandler,
CardFactory,
MessageFactory
} = require('botbuilder')
const WELCOMED_USER = 'welcomedUserProperty'
const quick_reply1 = require("./User-inputs/Quick_replies")
const cardActions = [{
type: ActionTypes.PostBack,
title: 'List all the tasks',
value: 'List all the tasks',
imageAltText: 'R'
}]
myvalues = ['in progress', 'in review', 'blocked', 'Done']
class WelcomeBot extends ActivityHandler {
constructor(userState) {
super()
this.welcomedUserProperty = userState.createProperty(WELCOMED_USER)
this.userState = userState
this.onMessage(async(context, next) => {
const text = context.activity.text.toLowerCase()
switch (text) {
case "list all the tasks":
await context.sendActivity("Hello")
}
await next()
})
this.onMembersAdded(async(context, next) => {
var reply = MessageFactory.suggestedActions(cardActions, 'What can I do for you today?');
for (const idx in context.activity.membersAdded) {
if (context.activity.membersAdded[idx].id != context.activity.recipient.id) {
await context.sendActivity("Welcome to Jaas Slackbot")
await context.sendActivity(reply);
}
}
})
}
async run(context) {
await super.run(context)
await this.userState.saveChanges(context)
}
}
exports.WelcomeBot = WelcomeBot;
The bot gets added to the workspace and have also created a channel on bot registration channel azure but yet not working.

Can a POST request be made server side?

I am designing a middleware between the client and the GraphQL API. The idea is to create a route that all client requests go to first /filament. This route then decides whether it can send data back from the cache or to proceed on to /graphql to access the resolvers there to get data from the database. I am using Axios to make my requests but it isn't firing server side. I wanted to ask if this was just an improper way to use Axios or if I am doing it incorrectly.
Server.js
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const fetch = require("node-fetch");
const redis = require("redis");
const PORT = process.env.PORT || 4000;
// const REDIS_PORT = process.env.REDIS_PORT || 6379;
//Create Redis client on Redis port (optional)
const client = redis.createClient();
const schema = require('./schema');
const bluebird = require('bluebird')
const app = express()
// bluebird.promisifyAll(redis.RedisClient.prototype);
// bluebird.promisifyAll(redis.Multi.prototype);
app.use(express.json())
client.on("error", err => {
console.log("Error " + err);
});
client.on('connect', () => {
console.log('Redis client connected');
});
// pass redis as context so our schema can use Redis methods
const wrapper = require('./filamentMiddleware')
app.use('/filament',
wrapper(client), // filamentMiddleware with access to client
)
app.use(
'/graphql',
graphqlHTTP((req) => ({
schema,
graphiql: true,
context: {
client,
req: req
}
})),
// addToCacheWrapper(res.data)
);
app.listen(PORT, () =>
console.log(`GraphQL server is running on port: ${PORT}`)
);
Middleware
const axios = require('axios')
const serverFilamentQuery = require('./serverFilamentQuery')
const mergeDataFromCacheAndServer = require('./mergeDataFromCacheAndServer')
const wrapper = (client) => (req, res, next) => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
client.get(ip, (err, cacheData) => {
const { query } = req.body
// ip not found in cache
if (!cacheData) {
console.log('cacheData:', cacheData)
axios.post('/graphql', { query }).then(res => {
console.log('have we made the post ????')
// set redis cache
// set the new data in Redis
client.set(ip, JSON.stringify({
todos: res.data.data['todos']
}), (err, result) => {
console.log(result)
})
const { data } = res.data
// return combinedData to client
return res.status(200).json({ data })
})
}
// console.log('ip found in cache')
const [newQuery, data, isMatched] = serverFilamentQuery(query, cacheData)
if (isMatched) {
return res.status(200).json({ data })
} else {
axios.post('/graphql', { newquery }).then(res => {
const merged = mergeDataFromCacheAndServer(data['todos'], res.data.data['todos']);
// set the new data in Redis
console.log(merged)
client.set(ip, JSON.stringify({
todos: merged
}), (err, result) => {
console.log(result)
})
// return combinedData to client
return res.status(200).json({ merged })
})
}
})
}
module.exports = wrapper
Yes, there is no problem making a post request server-side with Axios.
As per the Axios GitHub page
Promise based HTTP client for the browser and node.js (ie. server-side)
Note that the server-side call/usage is slightly different though, as per the docs here
versus client-side call here

Categories