Building a Telegram Chatbot using Python

Image for post
Image for post

This article provides a very brief introduction to creating chatbots using Python. We will be using Flask to set up the backend to our chatbot. So a brief idea about both Python and Flask would be helpful in understanding this tutorial.

Creating a bot using BotFather

BotFather is a bot provided by telegram that will help us create a bot. Search for Botfather on telegram and follow the instructions given. Once you have completed it, they will give you a token that needs to copied down. Make sure that you keep your token a secret.

Structure of a Flask app

Before you proceed, you need to make sure that you have Flask installed. You also need to install Requests library.

from flask import Flask,request
import requests
app = Flask(__name__)
key = "your-bot-token"
@app.route('/')
def index():
return 'Hello World’

if __name__ == '__main__':
app.run()

The above piece of code is the basic structure of a Flask code. If you are unfamiliar, when you run this code you will see that it will display “Hello World” in your browser. The decorator (@) is used for routing. So whenever you visit localhost:5000/ the hello_world() function will be executed. Do not forget to assign your token to a variable called key.

Setting Up Webhooks

Telegram allows for two methods to receive messages from users. The first one is through getUpdates methodology and the second one is through webhooks. The latter is often considered to be the most efficient one. In webhooks, when a user sends a message, Telegram will send a POST request to the URL we have specified. We will then write code to extract the message and other details from the request which will help us form our reply. In order to set up a webhook, we need to make our localhost globally accessible. For that, we use a tool called ngrok. Once you have installed it, we need to run it by typing the following into our command line

$ngrok http 5000

Make sure that you have the flask app running simultaneously. It is important to specify the same port that you used to run our flask app. By default, Flask runs on port 5000, so I have given the same to ngrok. Once you run the above command, you will get something like this:

Image for post
Image for post

Copy the URL starting with https and paste it on a browser. You can see that it returns Hello World on the browser which is the same you got when you ran flask app locally. This will be the URL that you will use to set up the webhook.

In order to set up the webhook, we need to send a GET request to a url provided by telegram. This URL is of the format:

https://api.telegram.org/bot{token}/setWebhook?url={url}

The token is the token provided by the BotFather that we saved earlier, and the url is the URL provided by the ngrok.

@app.route("/setwebhook/")
def setwebhook():
url = "https://your-ngrok-URL.ngrok.io/"
s = requests.get("https://api.telegram.org/bot{}/setWebhook?url={}".format(key,url))

if s:
return "Success"
else:
return "fail"

In the above code, we will send a GET request using the requests library that we had imported and this will contain the URL to set up the webhook. Once we have done this, go to the browser and navigate to https://your-ngrok-URL.ngrok.io/setwebhook/ and you will see that it will return “Success” if everything has gone correctly.

Handling Messages

Once we have set up the webhooks, when we type in a message on telegram, they would send a POST request to the URL specified while setting up webhooks. Hence, we need to have a piece of code that could handle the POST request and then extract out the useful information.

@app.route("/",methods=["POST","GET"])
def index():
if(request.method == "POST"):

resp = request.get_json()
msgtext = resp["message"]["text"]
sendername = resp["message"]["from"]["first_name"]
chatid = resp["message"]["chat"]["id"]
sendmessage(chatid)
return "Done"

Instead of the “Hello world” that we returned initially (Basic structure of flask), we will use the get_json() method of the request library to get the details in a JSON format. The JSON format will look similar to this:

Image for post
Image for post

This is somewhat similar to the dictionary in python. Hence we will use the normal dictionary accession syntax of python to extract chat ID and message text. Once we have got the necessary information we will pass these into a function called sendmessage.

def sendmessage(chatid):
url = "https://api.telegram.org/bot{}/sendMessage".format(key)
payload = {
"text":"heyy",
"chat_id":chatid
}

resp = requests.get(url,params=payload)

Sending messages in telegram is facilitated by sending a request to https://api.telegram.org/bot{}/sendMessage. Along with this URL, we will pass on the argument which is the reply text and the chatid(which we extracted previously). In the above code, the reply text will be “heyy”. So when we run our bot, we will see that for every message we send, we will get a “heyy” back as reply. I agree that this is pretty rudimentary but this tutorial is just to provide a foundation. Once you have perfected it, you can use your own bot logic to provide intriguing replies.

Deploying

So far we were using ngrok to build our project. But this is only a temporary solution as ngrok will expire after 7 hours. So in order to have our bot available all the time, we need to deploy this. One way is to use Heroku to deploy. More on Heroku coming soon.

Here is the complete code of our app:

from flask import Flask,request
import requests
import syskey = "Your token"app = Flask(__name__)def sendmessage(chatid):
url = "https://api.telegram.org/bot{}/sendMessage".format(key)
payload = {
"text":"heyy",
"chat_id":chatid
}

resp = requests.get(url,params=payload)
@app.route("/",methods=["POST","GET"])
def index():
if(request.method == "POST"):

resp = request.get_json()
msgtext = resp["message"]["text"]
sendername = resp["message"]["from"]["first_name"]
chatid = resp["message"]["chat"]["id"]
sendmessage(chatid)
return "Done"@app.route("/setwebhook/")
def setwebhook():
url = "https://ngrok-url.ngrok.io/"
s = requests.get("https://api.telegram.org/bot{}/setWebhook?url={}".format(key,url))
if s:
return "yes"
else:
return "fail"
if __name__ == "__main__":
app.run(debug=True)

Written by

Get busy living or get busy dying

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store