Telegram chat platform is in an early stage but amazing chatbot architecture. Please read offical documentation for an introduction:
Telegram Bots are special accounts that do not require an additional phone number to set up. These accounts serve as an interface for code running somewhere on your server. See: https://core.telegram.org/bots
The Bot API is an HTTP-based interface created for developers keen on building bots for Telegram. See: https://core.telegram.org/bots/api
In the sketch here below:
- User Giorgio chat with HelloWorldbot Telegram chatbot.
- HelloWorldbot is just a Hello World /echo server application
- User communicate with Telegram.org networking through the Telegram client app installed on a smartphone/tablet/pc
- Telegram Bot API server forward messages updates to a third party backend app HellowWorldbot via HTTPS
+---------------------+ +--------------+ +-------------------------------+
| Giorgio chat with | | | | HelloWorldbot |
| HelloWorldbot | | | | application server |
| using Telegram app | | | | |
| +---+ | | | | https | |
| | +------------------->----------|----------->-------------------+ |
| | | Hello! | | | | | | |
| | | | | | | | +-------------v-------------+ |
| | | | | Bot API | | | input message: "Hello!" | |
| | | | | Server | | | output message: "World!" | |
| | | | | | | | +-------------+-------------+ |
| | | World! | | | | https | | |
| | <-------------------<----------|-----------<-------------------+ |
| +---+ | | | | | |
| | | | | |
+---------------------+ +--------------+ +-------------------------------+
User device Telegram Network Bot Owner Server
There are two mutually exclusive ways of receiving updates for your bot — the getUpdates method on one hand and Webhooks on the other. See: https://core.telegram.org/bots/api#getting-updates
-
Long Polling
Application Bot talk with Telegram server opening an HTTPS persistent connection to send requests and receive updates (HTTP long polling mode). This is the simplest scenario, good for develop environments. You can set up a bot very quickly.
Note: Alexander Tipugin's telegram-bot-ruby Ruby gem, an excellent Telegram Bot APIs wrapper that implement long polling mode. Here below the example code hello world using long polling technique under the woods:
require 'telegram/bot'
token = 'INSERT_HERE_YOUR_REAL_BOT_TOKEN'
#
# echo-server useless bot
# just to test long-polling = 1 bot, 1 process mode
#
Telegram::Bot::Client.run(token) do |client|
client.listen do |message|
# print message sent by user
puts "received message by: #{message.from.first_name}, text: #{message.text}"
# echo-server, just for test purpose
case message.text
when /.+/
text = "#{message.from.first_name}:#{message.text}"
chat_id = message.chat.id
# send echo tu user
client.api.send_message(chat_id: chat_id, text: text)
puts "#{update_id}:#{message_id}:#{text}"
end
end
end
-
Webhooks
Application Bot send requests on a HTTPS client connection, as in the previous case, but receive updates as webhooks (certificated HTTPS POSTs). In this scenario the application Bot is behind a web server that have to manage incoming webhooks calls. This solution is good for a production environment because webhooks als for performance reasons. The webhooks approach is perfect to manage MULTIPLE Bots in a single third party server.
+----+
| device +---------+
| | +-------+ | device +-----+
| | | device | | device |
+--+-+ | | | | +-------------+ | |
| +---+---+ +----+----+ | | | |
| | | device | +--+--+
| | | +------+------+ |
| | | | |
+--------+-----------+--------------+---------------+-------------+------------------+
| T E L E G R A M . O R G N E T W O R K |
+--+----------------------------------------+-----+-------------------------------+--+
| Telegram Bot Webhooks API | | Telegram Bot Long Polling API |
+-+-+-+---------------------------+-+-+--+ +--+------------+--+------+-+---+
v v v ^ ^ ^ v v ^ ^
| | | HTTPS webhooks https | many HTTPS | | |
+--| | |--+ | | | | persistent | | |
| | | | +---------------+ | | | | conn. | | |
| | | +--> Bot 1 |--------+ | | | | | |
| | | +---------------+ | | v v ^ ^
| | | | | | | | | |
| | | +---------------------+ | | | | | |
| | +----> Bot 2 |----+ | +-----v------+ | | |
| | +---------------------+ | | Bot 1 |---------------+ |
| | | | +------------+ | |
| | +--------+ | | |
| +------> Bot N |-------------------+ | |
| +--------+ +--------v-----+ |
| | | Bot N |-----+
+---------+ Webhooks BOTServer +--------------+
Interesting article Bot Revolution. Know your API or die hard. by Miguel Garcia Lafuente! I quote here his conclusion:
That depends to you and what you want, if you are going to have many requests, you should use the webhook, it can handle better many messages, and it’s faster. The webhook are real PUSH data.
If you are not going to have 50 requests/second, you can use getUpdates if you prefer.
Also, if you don’t have a web server with domain and verified SSL, you will have to use the getUpdates. My suggestion are: If you have domain and SSL, use webhook, if don’t, use getUpdates. When you are testing, use getUpdates :)
What kind of application needs a very large number of bots to be managed at once!? Let consider as example, a sort of e-commerce marketplace, where your backend bot "marletplace" server must manage multiple bots, and where each bot implement a shop chatterbot that manage online orders!
Still Confused ? I'm working around some bots innovative usage examples for humans-to-humans service mediation by bots, see: Innovative Chatbot Services with Telegram.
By example consider a "Pizza maker in-store shop" scenario, where a buyer makes an online order chatting with a virtual shop bot, that helps buyer filling order and sending order to seller! So, for this shops marketplace it make sense to manage a multitude of bots (1 bot = 1 shop) with an efficient server architecture. For this specific business reason I created BOTServer: a sort of webhooks handler microframework to serve "a lot of bots".
What's the problem to handle a large number bots updates ? Ok, you have to handle an HTTPS POST webhook for each bot (lets consider bot and app as a synonymous of a specific bit application logic). Let me show two possible approaches in following paragraphs.
The "hard-coded" way is to build-up a rack routing that in Sinatra pseudocode could be something like this:
app_1 = create_instance('APP_TOKEN_1')
app_2 = create_instance('APP_TOKEN_2')
app_N = create_instance('APP_TOKEN_N')
post '/APP_TOKEN_1' do | token |
app_1.update(data_from_request_body(token))
end
post '/APP_TOKEN_2' do | token |
app_2.update(data_from_request_body(token))
end
post '/APP_TOKEN_N' do | token |
app_N.update(data_from_request_body(token))
end
That's a possible way, but every time you have to add a new app, a Telegram bot (a new shop), you have to modify the router source code :( pretty awful in a production system, isn't it ?
BOTServer run-time engine is very simple dynamic router: it's a rack server (now implemented with Sinatra, but I'll soon substitute it with flat fast rack app), that dispatch dinamically incoming token webhooks, calling update method of an instance of a class generated with a template sckeleton, that define the bot.
Yes, I used a bit "Ruby on Rails" metaprogramming for the routing-game.
Here below the router (rackup/router.rb
) code extract:
# load bots in memory. return a lookup table
set lookup: Loader.lookup(Config.tokens_config_file)
# HTTPS POST webhook endpoint(s)
post '/:token' do | token |
# retrieve name, method object pair from lookup table
bot = settings.lookup[token.to_sym]
if bot
# get webhook update
update = json_load request.body
# route update to corresponding app
bot[:method].call update
end
end
My idea is to generate, for each bot, an app template, to be filled with your own logic.
The generated app implement an echo-server trivial logic, it's just an example to be used as skeleton for your REAL BOT application (to be coded inside the
update
method!).
To generate the skeleton app for token YOUR_BOT_TOKEN
corresponding to Telegram bot Yourbot
:
$ rake app:new[YOUR_BOT_TOKEN]
create the app skeleton file: app/yourbot.rb
:
#
# file: yourbot.rb
#
require 'telegram/bot'
class Yourbot
attr_reader :token, :client
def initialize
@token = 'YOUR_BOT_TOKEN'
@client = Telegram::Bot::Client.new(@token)
end
#
# message(s) updates from telegram server.
# put ALL your Telegram Bot logic here.
#
def update(data)
update_id = data.update_id
message = data.message
message_id = message.message_id
# #######################
# PUT HERE YOUR BOT LOGIC
# #######################
# echo-server, just for test purpose
case message.text
when /.+/
text = "#{message.from.first_name}:#{message.text}"
chat_id = message.chat.id
# send echo tu user
client.api.send_message(chat_id: chat_id, text: text)
puts "#{update_id}:#{message_id}:#{text}"
end
end
end