ninebot
Ninebot is a simple Promise-based JavaScript library with a built-in dialog manager. This library allows you to
build your own Telegram bot faster and easier.
Getting started
To build complicated ramified dialog you should to design all dialog branches and nodes.
Example
For example, we need to send user different messages depending on his languages. Let's write a simple algorithm on
pseudocode
language = %language%
if language = 'Human'
send 'Hello'
ask %name%
send 'Hello %name%'
// Some instructions here
if language = 'Martian'
send 'Sorry, we do not want to communicate with aliens'
This is a simple dialog which we can realize by N nested if ... else ...
, but what about declaratively description
of every dialog node? Let's transform previous algorithm
// Start node (entry point)
name: 'start'
message: 'Select language'
content:
'Human'
'Martian'
conditions:
'Human' => 'proceed'
'Martian' => 'exit'
// Proceed node
name: 'proceed'
message: 'What is your name?'
conditions:
%name is text% => 'next'
// Exit node
name: 'exit'
message: 'Sorry, we do not want to communicate with aliens'
In result, we have an array of nodes, and can easily switch between them depending on the current conditions.
Simple project
Note: This guide implies that you have already created a bot and received a token.
Create a blank project and install a package via npm
or yarn
:
npm install --save ninebot
yarn install ninebot
Then create a index.js
file and connect dependencies
const Ninebot = require('ninebot');
Then create a class which extends a Ninebot
class
class MyBot extends Ninebot {
}
In constructor()
you can initialize your global class entities. Don't forget super()
!
class MyBot extends Ninebot {
constructor() {
super();
}
}
In state
of your class you can store your data and update them to control dialog nodes data.
Dialog nodes are declaratively defined in update
function in JSON-like format:
{
name: 'node_name',
conditions: [
type: 'text',
'text'
regExp: /.+/,
next: 'next_node_name',
callback: callback_fn
],
reply: {
text: 'Here\'s a text which bot sends at the moment of transition to this node'
options: {
}
}
}
Now we can realize previous algorithm
const token = '{Your Telegram bot token}';
class MyBot extends Ninebot {
constructor(_token = token) {
super(_token);
}
update() {
return ([
{
name: 'before',
conditions: [
{
type: 'text',
regExp: /\/start/,
next: 'start'
}
],
reply: { text: 'Enter /start' }
},
{
name: 'start',
conditions: [
{
type: 'text',
regExp: /Human/,
next: 'proceed'
},
{
type: 'text',
regExp: /Martian/,
next: 'exit'
}
],
reply: {
text: 'Select language',
options: {
reply_markup: {
keyboard: [
['Human', 'Martian']
],
resize_keyboard: true,
one_time_keyboard: true
}
}
}
},
{
name: 'proceed',
conditions: [
{
type: 'text',
regExp: /./,
next: 'next'
}
],
reply: { text: 'What is your name?' }
},
{
name: 'next',
conditions: [{ regExp: /./, next: 'before' }],
reply: { text: 'Print any string' }
},
{
name: 'exit',
conditions: [
{
type: 'text',
regExp: /./,
next: 'start'
}
],
reply: { text: 'Sorry, we do not want to communicate with aliens' }
}
]);
}
}
Now that we have a simple bot logic, we can go to start a simple server to serve this bot.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const ADDRESS = '127.0.0.1';
const PORT = 33459;
const BOT_PATH = '/bot';
const server = app.listen(process.env.PORT, ADDRESS, () => {
const host = server.address().address;
const port = server.address().port;
console.log('Web server started at http://%s:%s', host, port);
});
app.post(BOT_PATH, (req, res) => {
});
To identify the user, just use req.body.chat_id
- this is a unique chat ID of every Telegram user. To get data from
message to bot, we can use req.body.nessage
.
app.post(BOT_PATH, (req, res) => {
res.sendStatus(200);
const chat_id = req.body.message.chat.id;
const message = req.body.message;
});
Now initizlize our bot MyBot
const myBot = new MyBot(token);
A couple more lines and we can receive messages
app.post(BOT_PATH, (req, res) => {
res.sendStatus(200);
const chat_id = req.body.message.chat.id;
const message = req.body.message;
if (!myBot.state.chat_id) {
myBot.setState({ chat_id: chat_id });
}
myBot.runDialog(message);
});
If you want to start your bot locally, you should add some manipulations.
- Set SSH tunnel to localhost
- In
onReady()
function set the tunnel
const localtunnel = require('localtunnel');
class MyBot extends Ninebot {
onReady() {
this.dialogManager.setNode('before');
console.log('Setting local tunnel');
localtunnel(PORT, {}, (error, tunnel) => {
if (error) {
throw error;
}
console.log(`Url: ${tunnel.url}`);
this.bot.setWebhook(`${tunnel.url}${BOT_PATH}`).then(() => {
console.log('Webhook was set - bot is ready');
}).catch((error) => {
console.error(error);
});
});
}
}
Note: onReady()
function is similar to componentDidMount()
in React.js
Great! Your first ninebot app is ready!