📜 ⬆️ ⬇️

Pavel 2.0: Reptiloid consultant on JS, node.js with sockets and telephony

So our INTERCOM'18 has died down, with preference and business cases. As usual, the entrance to the conference was paid: anyone could buy tickets for the TimePad at full price, or ... get a discount from a reptilian consultant directly on the site . Last year it worked like a usual callback: you leave the phone in a special form, Pavel calls you in a minute and asks questions; the more correct answers, the higher the discount. This time we decided to change the mechanics, making it more difficult both technically and in terms of issues. Under the cut - Pavlik 2.0 guts, with the current node and web sockets, do not forget to wear workwear before opening.


Competition mechanics


You enter intercomconf.com from a desktop browser, in the lower right corner Pavlik “wakes up” in the form of a chat and offers to play the game. Enter the number, click "Here is my number" - after that Pavel raises the session between your browser and our backend.


')
If everything has successfully risen and your number has not yet participated in the drawing, then Pavel will offer to call 8-800. Here the Voximplant cloud is already entering and the quiz starts:


Answer: deadline / deadline. Based on the meme This is fine .

Yes, the puzzles were like this. Three attempts were made for each question: first there was a “complex” picture, then simpler and at the end the simplest one. The first attempts gave the most points; after 5 puzzles, Pavel counted up his points and either gave a free ticket or a 10% -30% discount.

At the same time, our reptiloid is smart enough: it showed error messages (if you entered the phone number incorrectly, for example), determined that the number was already participating in the drawing (“I see the familiar number on the screen of my non-existing mobile phone. One attempt in one hand - these are the rules. ") And, most importantly, correlated the browser and the cloud. How did this bold IVR work?

In the mouth madness reptiloid



Answer: call center. Nuff said.

Speaking dryly, Paul 2.0 is an IVR running in our cloud. Therefore, all reptiloid logic should be spelled out in a JS script, right? Yes, but no.

The second version of Pavel is synchronized with the client’s browser: Pavel shows the rebuses on the website, and he hears your answers on the phone, depending on which pictures are replaced and the result is displayed. At first glance, this interaction could be implemented using our HTTP API :


But how to "catch" a custom browser? After all, in the httpRequestAsync, you must pass a unique URL. And yes, pictures - they also need to be stored somewhere.

Therefore, in addition to the cloud-based JS script, we used our backend on express.js paired with socket.io : when the visitor entered the number, the browser gave this number to the backend via http, after which the http session turned into a session on web sockets. As a result, the script constantly communicated with the backend via http, and already the backend used web sockets to quickly transfer images and points to the browser.

In part of the web sockets, the backend looked like this:
'use strict';
const express = require('express');
const request = require('request');
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io')(http).listen(server);
var session = require('express-session')({
secret: 'secret',
resave: true,
saveUninitialized: true
});
var sharedsession = require('express-socket.io-session');
var sockets = {};
var PORT = process.env.PORT || 3001;
app.use(session);
io.use(sharedsession(session));
io.on('connection', function (socket) {
if (socket[socket.handshake.session.caller_id] === undefined &&
socket.handshake.session.caller_id !== undefined) {
sockets[socket.handshake.session.caller_id] = socket
}
});
app.use((req, res, next) => {
let allowedOrigins = [
// allowed hosts
];
let origin = req.headers.origin;
if (allowedOrigins.indexOf(origin) > -1) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
})
view raw pavel-backend.js hosted with ❤ by GitHub

But still, most of the logic was stored in the script. Consider a reptiloid from this side ...

We go on the script



Answer: machine learning / machine learning. Taken from the Instagram of Arnie himself .

From the obvious: be sure to connect the ASR recognition module.

require(Modules.ASR); 

From the interesting:


The overall listing of the script approaches 300 lines, the most voluminous piece is the processing of the recognition result, onRecognitionResult .

Speaking fossil



Answer: Firefox. We have everything.

Although Paul and the dinosaur, but still keeps up with the times: it develops from year to year and still loves to joke. We hope you appreciate the second version of our reptiloid and "live", and from the point of view of implementation. Share your views in the comments, be healthy and remember - Paul loves you!

Source: https://habr.com/ru/post/426417/


All Articles