I have a Bot running on botbuilder V3 where I am using a middleware explained here to intercept the messages.
bot.use({
botbuilder: function (session, next) {
myMiddleware.logIncomingMessage(session, next);
},
send: function (event, next) {
myMiddleware.logOutgoingMessage(event, next);
}
})
We are planning to migrate on sdk v4 so looking for similar capabilities in sdk v4. Are there any ?
I didn't find example on this page.
The BotAdapter base class exposes the use method to register middleware. So in your startup logic you'll create a specific implementation of a BotAdapter, typically BotFrameworkAdapter, and then add the middleware to it. Like so:
const botAdapter = new BotFrameworkAdapter( { /* credential stuff here*/ });
// Simple handler based
botAdapter.use(async (turnContext, next) => {
// pre logic
await next();
// post logic
});
// Or class based
botAdapter.use(new MyMiddleware());
Related
I am working on my first full stack application, specifically with the MERN stack, and have run into a bit of an issue. I am trying to implement a leaderboard stored in a db for a unity game on my website. I have everything working wherein the client can post and get scores from my MongoDB Atlas database using my Express api. However, in the case of a leaderboard, I need to insure that the scores can ONLY be sent by the client based on how the game goes. With the current working configuration, anyone can send spoof scores via the api without having to play the game.
I first thought was to try to implement JWT to authenticate that the api call was coming from the site, but in my head any auth token like JWT could still be copied down by a user and sent with spoofed scores easily with Postman.
I am not extensively familiar with databases and suspect that this could possibly be solved if I wasn't using a DBaaS provider like Atlas but I am not entire sure.
Any thoughts or recommendations would be greatly appreciated!
You could define a middleware function and check the method of the incoming request:
const allowOnlyPost = (req, res, next) => {
if (req.method !== 'POST') {
return res.status(401).send(`Method ${req.method} not allowed`)
}
next()
}
module.exports = { allowOnlyPost }
And then apply it to the routes you want to protect:
const { allowOnlyPost } = require('./your/middleware/folder')
app.use('/route/to/protect', allowOnlyPost, (req, res) => { ... })
An improvement to current answer's function could be:
const allowMethods = (...methods) => {
return (req, res, next) => {
if (!methods.map(m => m.toUpperCase()).includes(req.method.toUpperCase())) {
return res.status(401).send(`Method ${req.method} not allowed`)
}
next()
}
}
module.exports = { allowMethods }
So you could use it like this:
const { allowMethods } = require('./your/middleware/folder')
app.use('/route/to/protect', allowMethods('get','post'), (req, res) => { ... })
In my Node.js application I´m using fastify as framework together with some plugins (i18next).
I´m using i18next for translation (is working properly in preHandler and handler hooks) and want to customize all errors by using my translations via i18next in my custom error handler (via fastify setErrorHandler method).
Here is my coding so far (from top to bottom):
import fastify from "fastify";
import routes from "./routes/routes.js";
import i18next from "./config/i18next.js";
import i18nextMiddleware from "i18next-http-middleware";
const app = fastify({
logger: true,
ajv: {
customOptions: {
allErrors: true,
$data: true
}
},
});
app.register(i18nextMiddleware.plugin, { i18next });
app.register(routes, { prefix: '/api/v1' });
app.setErrorHandler((error, request, reply) => {
console.log('request.t: ', request.t);
if (error.validation) {
// other coding ...
reply.send(error);
}
});
(async () => {
try {
await app.listen(process.env.PORT);
console.log(`Server started listening on port ${process.env.PORT}`);
} catch (err) {
app.log.error(err);
}
})();
Inside the setErrorHandler (which is sync) I want to use the initialized t() method from i18next instance passed to request object (this is working for all my routes in the preHandler and handler hooks) but is not working in the setErrorHandler, as I´ll get undefined when an error occours.
I know the setErrorHandler is sync and all plugin registration will be handled async, but didn´t solved it yet.
What I´ve also tried is to do the setErrorHandler call in the after() hook when registering the i18next plugin, but the result is the same. I know I´m missing a small detail, but any tips are appreciated, as I´m spinning my head around this since hours.
This happens because the i18next-http-middleware plugin adds the t method to the request object on a preHandler hook that is executed after the JSON validation step:
export function plugin (instance, options, next) {
const middleware = handle(options.i18next, options)
instance.addHook('preHandler', (request, reply, next) => middleware(request, reply, next))
return next()
}
source
You should be able to write a workaround like this:
import i18nextMiddleware from "i18next-http-middleware";
// ....
const middleware = i18nextMiddleware.handle({})
app.addHook('preValidation', (request, reply, next) => middleware(request, reply, next))
I think that is a bug of the module tho
I'm working with a node app for Azure Mobile Apps.
I have an Easy Table with a read operation that looks something like this:
table.read(function (context) {
context.query.where({ _user_id: context.req.userId });
return context.execute();
});
Now I want to add some middleware before that function runs which adds userId into the req, and so I thought I was supposed to do something like this:
table.use((req,res,next) => {
req.userId = "1234";
next();
}, table.operation);
Now, inside the table.read, if i console.log(context.req.userId) it comes out correct, but for some reason after adding thing .use, context.query becomes undefined. When I take off table.use, context.query.where({ _user_id: "1234" }) works perfectly.
How am I supposed to do this middleware properly within Azure Mobile Apps? Why is defining table.use messing with context.query?
Try adding the middleware at the application level instead:
mobileApp.use((req, res, next) => {
req.userId = "1234";
next();
});
mobileApp.tables.import('./tables');
mobileApp.api.import('./api');
How do i implement watson text to speech while running a chatbot on a local host using nodejs?
My chatbot is already running on a localhost..I want to embed watson text to speech service. I have read that it could be done by websocket interfacing. I don t have any idea on that
Assuming that you have the Conversation Simple example built by IBM Developers using Node.js and Conversation Service, you can simply have your app submit an HTTP REST request by following this tutorial using Websocket or you can leverage a language-specific SDK, I'll paste in the links below.
So, a few months ago the #kane built one example that integrates the conversation simple example with text to speech, you can easily found them in this link.
You can check this commit for saw the changes and follow the logic to implement Text to Speech in your application. You'll see this code above calling the Text to Speech service with the Services credentials in the .env file, like the comments in the code:
const TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
const textToSpeech = new TextToSpeechV1({
// If unspecified here, the TEXT_TO_SPEECH_USERNAME and
// TEXT_TO_SPEECH_PASSWORD env properties will be checked
// After that, the SDK will fall back to the bluemix-provided VCAP_SERVICES environment property
// username: '<username>',
// password: '<password>',
});
app.get('/api/synthesize', (req, res, next) => {
const transcript = textToSpeech.synthesize(req.query);
transcript.on('response', (response) => {
if (req.query.download) {
if (req.query.accept && req.query.accept === 'audio/wav') {
response.headers['content-disposition'] = 'attachment; filename=transcript.wav';
} else {
response.headers['content-disposition'] = 'attachment; filename=transcript.ogg';
}
}
});
transcript.on('error', next);
transcript.pipe(res);
});
// Return the list of voices
app.get('/api/voices', (req, res, next) => {
textToSpeech.voices(null, (error, voices) => {
if (error) {
return next(error);
}
res.json(voices);
});
});
Obs.: I suggest to you see the Commit and follow the same logic to make your changes in your app.
Node SDK for Watson Services.
API Reference for using Text to Speech with Node.js
My question is essentially the same as this github issue, but then for the Node version of the BotBuilder framework.
When the bot is added to a channel with multiple users, it will react to every single message, which is not its purpose. I intend to fix this by intercepting the message, and if it contains a mention of the bot, it will be allowed to flow normally, otherwise cancel the action. However I can not find the right function to override. Any suggestions?
You can intercept messages easily using node SDK. I let you a sample code:
server.post('/api/messages', connector.listen());
var bot = new builder.UniversalBot(connector);
bot.use({
botbuilder: function (session, next) {
myMiddleware.doSthWithIncomingMessage(session, next);
},
send: function (event, next) {
myMiddleware.doSthWithOutgoingMessage(event, next);
}
})
module.exports = {
doSthWithIncomingMessage: function (session, next) {
console.log(session.message.text);
next();
},
doSthWithOutgoingMessage: function (event, next) {
console.log(event.text);
next();
}
}
Now, every inbound message (from user to bot) will trigger doSthWithIncomingMessage, and every outbound message (from bot to user) will trigger doSthWithOutgoingMessage. In this example, the bot simply prints some information about each message, but you can modify the behaviour to filter the messages and check about mentions.