I am using socket.io for bi-directional communication between client-server side , i have also used web speech api for speech synthesis and recognition in my web app ,though it fulfills default responses and it gives output properly , but during contextual conversation my intents doesn't match with context and results in fallback intent.
It works fine on dialogflow "try" console but doesn't work on my webapp , please can anyone help..!
here's my app.js file :-
const path = require("path");
const express = require("express");
const colors = require("colors");
const dotenv = require("dotenv");
const socketio = require("socket.io");
const dialogflow = require("#google-cloud/dialogflow");
const uuid = require("uuid");
const app = express();
dotenv.config({ path: "./config/config.env" });
app.use(express.static(path.join(__dirname, "views")));
app.use(express.static(path.join(__dirname, "public")));
const PORT = process.env.PORT || 3000;
const server = app.listen(
PORT,
console.log(
`Server is runnig on ${process.env.NODE_ENV} mode at port ${PORT} for ${process.env.PROJECT_ID}`.yellow
.bold
)
);
const io = socketio(server);
io.on("connection", function (socket) {
console.log("a user connected");
socket.on("chat message", (message) => {
console.log(message);
const callapibot = async (projectId = process.env.PROJECT_ID) => {
try {
const sessionId = uuid.v4();
const sessionClient = new dialogflow.SessionsClient({
keyFilename: "/home/abat/Downloads/kiosk-cwbx-8e7bd8645085.json",
});
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId,
);
const request = {
session: sessionPath,
queryInput: {
text: {
text: message,
languageCode: "en-US",
},
},
};
const responses = await sessionClient.detectIntent(request);
console.log("Detected intent");
const result = responses[0].queryResult;
socket.emit("bot reply", result.fulfillmentText);
console.log(result);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`)
}
} catch (error) {
console.log(error);
}
};
callapibot();
});
});
here's my script.js file :-
const btn = document.querySelector("button");
const outputme = document.querySelector(".output-you");
const outputbot = document.querySelector(".output-bot");
const socket = io();
const SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.lang = "en-US";
recognition.interimResults = false;
btn.addEventListener("click", () => {
recognition.start();
});
recognition.onresult = function (event) {
const last = event.results.length - 1;
const text = event.results[last][0].transcript;
console.log(text);
outputme.textContent = text;
socket.emit("chat message", text);
};
const botReply = (text) => {
const synth = window.speechSynthesis;
const voices = synth.getVoices();
const utterance = new SpeechSynthesisUtterance();
utterance.voice = voices[4];
utterance.lang = "hi-IN";
utterance.text = text;
utterance.pitch = 1;
utterance.volume = 1;
synth.speak(utterance);
};
socket.on("bot reply", (text) => {
outputbot.textContent = text;
botReply(text);
});
Does my code need modifications for handling contexts for dialogflow ?
Got the answer , it was because the session id was inside the async function() , i then removed it from there and placed it on the top
const sessionId = uuid.v4();
Don't put this under the async function , that's it.
Related
I have created a socket server as shown below.
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server, {cors:{origin:'*'}})
const mongoose= require("mongoose")
const port = process.env.PORT || 4002;
server.listen(port, ()=>{
console.log(`Listening on port ${port}......`)
})
onlineUsers = [];
const addNewUser = (userId, socketId)=>{
!onlineUsers.some((user)=>user.userId === userId) &&
onlineUsers.push({userId,socketId})
}
const removeUser= (socketId) =>{
onlineUsers = onlineUsers.filter((user)=> user.socketId!==socketId)
}
const getUser = (userId)=>{
return onlineUsers.find(user=>user.userId ===userId)
}
io.on("connection", (socket=> {
console.log("User connected:", socket.id);
socket.on("disconnect",()=>{
removeUser(socket.id)
})
socket.on("newUser",(userId)=>{
addNewUser(userId, socket.id)
})
export function handleMessaging (userId,clientID,messageId )
{
const receiver = getUser(userId);
if(receiver)
{
io.to(receiver.socketId).emit("sendMessage", {data:"working properly"});
return true;
}
else return false
}
}));
I want to export the function handle messaging so that I can use it inside the API like (shown below) to see if a user is online and if yes, send a message.
But as someone new to programming, I can't figure out how to export handle messaging the proper way. I tried to use export but its telling me "Modifiers cannot appear here".
router.post('/:companyId' async (req, res) => {
const {userId,clientId,messageId} = req.body
handleMessaging (userId,clientID,messageId )
{
//do xyz
}
}
Hi I am trying to make a request and receive just the response in realtime using socketIO
and currently I am able to connect to the router but not getting any response as the error shows
Error: io is not defined.
If anyone can please help me to resolve this issue.
Below is the necessary code.
ChatPageProvider.dart
Future<void> addProduct(String message) async {
Map<String, String> headers = {
"Content-Type": "charset=utf-8",
"Content-type": "application/json"
};
const url = 'http://localhost:8080/message/check';
try {
var response = await http.post(url,
headers: headers,
body: json.encode({
"text": message,
}));
socketIO.init();
//Subscribe to an event to listen to
socketIO.subscribe('message', (jsonData) {
//Convert the JSON data received into a Map
Map<String, dynamic> data = json.decode(jsonData);
messages.add(data['message']);
notifyListeners();
});
socketIO.connect();
// final getMessage = Message(
// text: json.decode(response.body)['message'],
// );
print(response.statusCode);
notifyListeners();
} catch (error) {
throw error;
}
}
index.js
const express = require('express');
const app = express();
const notificationdetails = require('../nodePractice/router/notification');
const http = require('http').createServer(app);
const io = require('socket.io')(http);
bodyParser = require('body-parser');
var port = process.env.PORT || 8080;
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit:"50mb",extended:true}));
io.on("connection",(userSocket) => {
console.log('Conntected to port')
io.emit('connected', 80);
})
var server = http.listen(port, ()=> {
console.log('listening on port' + port)
})
app.use(notificationdetails);
notification.js
const express = require('express');
const router = new express.Router()
router.post('/message/check',async(req,res) => {
console.log("Success"); // I am able to get till here but then the error occurs
io.emit("message", req.body)
try {
res.status(201).send();
io.emit("message", req.body)
}catch(e) {
res.status(401);
io.emit("message", req.body)
res.send(e);
}
})
module.exports = router
error
(node:78214) UnhandledPromiseRejectionWarning: ReferenceError: io is not defined
You can create a file like below, give it a name socket-io.js.
var io = require('socket.io')(9999);
module.exports = io;
Then import it first in your index.js like below snippet.
let io = require('./app/utilities/socket-io');
io.on('connection', function (socket) {
...
});
Last, you can import the same file in your notification.js file as well & try below code.
const express = require('express');
const router = new express.Router()
let io = require('./app/utilities/socket-io');
router.post('/message/check',async(req,res) => {
console.log("Success"); // I am able to get till here but then the error occurs
io.emit("message", req.body)
try {
res.status(201).send();
io.emit("message", req.body)
}catch(e) {
res.status(401);
io.emit("message", req.body)
res.send(e);
}
})
module.exports = router
edit: added a bit more code.
const express = require('express');
var bodyParser = require('body-parser');
const app = express();
var urlencodedParser = bodyParser.urlencoded({extended: false})
const {google} = require('googleapis');
const {PubSub} = require('#google-cloud/pubsub');
const iot = require('#google-cloud/iot');
const API_VERSION = 'v1';
const DISCOVERY_API = 'https://cloudiot.googleapis.com/$discovery/rest';
app.get('/', urlencodedParser, (req, res) => {
const projectId = req.query.proyecto;
const cloudRegion = req.query.region;
const registryId = req.query.registro;
const numSerie = req.query.numSerie;
const command = req.query.command;
const client = new iot.v1.DeviceManagerClient();
if (client === undefined) {
console.log('Did not instantiate client.');
} else {
console.log('Did instantiate client.');
sendCom();
}
async function sendCom() {
const formattedName = await client.devicePath(projectId, cloudRegion, registryId, numSerie)
const binaryData = Buffer.from(command);
const request = {
name: formattedName,
binaryData: binaryData,
};
return client.sendCommandToDevice(request).then(responses => res.status(200).send(JSON.stringify({
data: OK
}))).catch(err => res.status(404).send('Could not send command. Is the device connected?'));
}
});
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
console.log('Press Ctrl+C to quit.');
});
module.exports = app;
I have this function, that I call after the client initiate: sendCom();
async function sendCom() {
const formattedName = await client.devicePath(projectId, cloudRegion, registryId, deviceId)
const binaryData = Buffer.from(command);
const request = { name: formattedName, binaryData: binaryData, };
client.sendCommandToDevice(request)
.then(responses => {
res.status(200).send(JSON.stringify({ data: OK })).end();
})
.catch(err => {
res.status(404).send('Could not send command. Is the device connected?').end();
});
}
My problem is that sendCommandToDevice gets executed perfectly, however I get the catch error.
As I understand it, it's because in the .then ends the connection.
I've looked at this and thats's what I tried, however I'm not sure I understand what's going on.
You can not use send with end.
end() is used when you want to end the request and want to respond with no data.
send() is used to end the request and respond with some data.
You can found more about it here.
I want to use Cloud Functions for Firebase to deploy the React application for shopify app.
I am new to both Next and Koa.
Based on this repo the below code is how to host a simple react application in Firebase.
const path = require('path')
const functions = require('firebase-functions')
const next = require('next')
var dev = process.env.NODE_ENV !== 'production'
var app = next({
dev,
conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})
var handle = app.getRequestHandler()
exports.next = functions.https.onRequest((req, res) => {
console.log('File: ' + req.originalUrl) // log the page.js file that is being requested
return app.prepare().then(() => handle(req, res))
})
Which works correctly, no issue.
Then based on this tutorial from shopify I need to integrate koa and other dependencies in server.js, which in my case I believe it should be placed inside the firebase function. so I get to this code
const path = require('path')
const isomorphicFetch = require('isomorphic-fetch');
const Koa = require('koa');
const functions = require('firebase-functions')
const next = require('next');
const ShopifyConfig = require('./shopify.js');
const { default: createShopifyAuth } = require('#shopify/koa-shopify-auth');
const dotenv = require('dotenv');
const { verifyRequest } = require('#shopify/koa-shopify-auth');
const session = require('koa-session');
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 3000;
var dev = process.env.NODE_ENV !== 'production'
var app = next({
dev,
conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})
var handle = app.getRequestHandler()
const server = new Koa();
server.use(session(server));
server.keys = [ShopifyConfig.secretKey];
server.use(
createShopifyAuth({
apiKey: ShopifyConfig.key,
secret: ShopifyConfig.secretKey,
scopes: [],
afterAuth(ctx) {
const { shop, accessToken } = ctx.session;
ctx.redirect('/');
},
}),
);
server.use(verifyRequest());
server.use(async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
});
exports.next = functions.https.onRequest((req, res) => {
console.log('File: ' + req.originalUrl) //
// This is old code
// return app.prepare().then(() => {
// handle(req, res);
// })
// I tried this #1
// server.callback(req, res);
})
// I tried this #2
// exports.next = functions.https.onRequest(server.callback);
// I tried this #3
// exports.next = functions.https.onRequest(server.callback());
// I tried this #4
exports.next = functions.https.onRequest((req, res) => {
console.log('File: ' + req.originalUrl)
return app.prepare().then(() => {
server.callback(req, res);
//handle(req, res);
})
})
My question is now based on Koa what code should be in functions.https.onRequest ? please note there is no code to listen to port since it doesn't make sense for firebase functions.
I tried #1, #2, #3, as well as this post
1 -> I get request timeout
2 -> I get request timeout
3 -> I get "Cannot access middleware of undefined"
4 -> I get request timeout
Thanks to kvindasAB
server.callback is not the callback by itself, rather a function that generates the callback from your configuration I assumed.
so code needs to be changed to
server.callback()(req, res);
const functions = require('firebase-functions');
const app = new Koa();
...
exports['http'] = functions.https.onRequest(app.callback());
This is what I want, server is a file server, when client asks for certain file, it'll stream that file back. Instead of koi-static, I try to do this, but the dest.jpg only contains 'Not found'.
client code:
var Koa = require('koa');
var Router = require('koa-router');
const HttpStatus = require('http-status');
const fs = require('fs');
const koaBody = require('koa-body');
const request = require('request');
const tempSaveFile = fs.createWriteStream('dest.jpg');
const writeStream = request.post('http://localhost:3456/getfile/src.jpg').pipe(tempSaveFile);
writeStream.on('finish', () => {
tempSaveFile.end();
console.log('Upload successful! ');
});
server code:
var Koa = require('koa');
var Router = require('koa-router');
const HttpStatus = require('http-status');
const fs = require('fs');
const koaBody = require('koa-body');
var app = new Koa();
var router = new Router();
const serve = require('koa-static');
router
.post([`/getfile/:fileName`],
(ctx) => {
const { params: { fileName } } = ctx;
console.error(`------- server will return ${fileName} --------`);
const readStream = fs.createReadStream(fileName).pipe(ctx.res);
readStream.on('finish', () => {
console.error('---- server finished stream ----');
ctx.status = HttpStatus.OK;
});
})
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3456);
When I change the server to use koa-static, client can gets the file successfully, did diff, look the same.
I suspect server returns too fast before it finishes, but another post said this is the way to wait for pipe to finish.
callback to handle completion of pipe
Any suggestions ? thanks !
ok, I added async, working now
const multiparty = require('multiparty');
const multer = require('koa-multer');
const request = require('request');
var app = new Koa();
var router = new Router();
const serve = require('koa-static');
const streamEnd = fd => new Promise((resolve, reject) => {
fd.on('end', () => {console.error('-- 51 --'); resolve(51); });
fd.on('finish', () => {console.error('-- 53 --'); resolve(53); });
fd.on('error', reject);
});
router
.get([`/getfile/:fileName`],
async (ctx) => {
const { params: { fileName } } = ctx;
console.error(`------- server will return ${fileName} --------`);
if (fs.existsSync(fileName)) {
const readStream = fs.createReadStream(fileName).pipe(ctx.res);
await streamEnd(readStream);
ctx.status = HttpStatus.OK;
} else {
console.error(`File ${fileName} doesnot exist`);
ctx.status = HttpStatus.INTERNAL_SERVER_ERROR;
}
})
app.use(serve('./customer'));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3456);