Weekend Hack: Building an Unsplash bot for Telegram with Python

Photo by NeONBRAND on Unsplash

The goal of this post is to step-by-step build our first python Telegram bot, which will serve hi-res images from Unsplash.

This post is the beginning of the Weekend Hack series, a series of short development stories focused on the exploration of new concepts. Set-by-step instructions and repository links will be provided for a more fundamental understanding.

The article is divided into three main sections: technology choices, architecture overview, and step-by-step setup.

After hearing about chatbots and getting hyped, I decided to try the poison myself by building a simple bot that integrates with a third party API while documenting the process.

Technology choices

Before we go nee deep into development, there are some points I would tike to cover:

Why a Telegram bot?

These days you can build bots with many platforms and tools: Facebook, Amazon Lex, Clever Bot, Botsify, Mobile Monkey. AI-powered bots, conversational bots, you name it.

That said, I am a big fan of incremental learning, so instead of choosing a platform like AWS and diving deep into their specific bot API, I have decided to start small and build a barebone chatbot for Telegram. Telegram has a vibrant bot community and friendly API with tons of examples, perfect for starting.

Why use Python?

While you can write Telegram bots in pretty much any language, I have decided to give Python a try. It is not my day-to-day language, but this seemed like an excellent opportunity to learn more about it.

Why integrate it with Unsplash?

Being my first bot and all, I wanted to integrate with a third-party API. Since Unsplash provides Source API that allows for simple image querying, I said, why not? Everybody likes hi-res images anyway.

Architecture overview

Alright, now that we have the goal and tools that we want to use defined, let’s talk about the internals of a Telegram bot. I won’t go in extreme detail, but rather give some general idea of how it works.

The general concept is that a chat user sends a message to the bot, the message is processed by the Telegram infrastructure, and forwarded to your bot. Then, the bot will execute logic and perhaps send something back to the user. Depending on the bot use case, audios, pictures, text, or other media may be sent to the user.

There are multiple ways to connect the bot with the Telegram infrastructure, WebHooks being one of the most used ones. WebHooks are user-defined HTTP-callbacks that enable the implementation of push subscription models, rather than pull (read more about long-polling pull subscription model).

In a nutshell, when the Telegram infrastructure receives a message sent by a user to your bot, it will call the Webhook of the bot, which has assigned a set of callbacks. This way, the bot is only active when a new event comes from the Telegram servers to the bot, rather than performing constant requests to the Telegram infrastructure.

Telegram bot using WebHook.

In our case, the user will message the bot with a set of predefined actions (referred to as commands in the Telegram API), and the bot will interact with the Unsplash API.

Step-by-step setup

Let’s start with the fun part!

1. Setup the bot cloud-infrastructure

First, we need to choose an infrastructure provider to host our bot. They are multiple options when it comes to online server hosting. For this project, we will use Glitch, since it provides out of the box domains, WebHook compatibility, easy code sharing, and the best of all, it is free!

Let’s create an account in Glitch and create an hello-webpage project from the right side drop-down menu.

Creation of a new project.

Some files need to be created for this project:

  • env. → Contains the secret keys that out bot needs for connecting the WebHook to the Telegram infrastructure. Modify the project name to yours (seen on the top left of the Glitch project). Mine is weekend-hack-unsplash-bot.
# .envTELEGRAM_TOKEN=
PROJECT_NAME=weekend-hack-unsplash-bot
  • server.py → The code is connecting the bot specific code with the WebHook calls.
# server.py# import the required libraries
import flask, telebot
# import the bot.py file
from bot import bot
# setup the Flask web server
app = flask.Flask(__name__)
# define the WEBHOOK path using the bot token
WEBHOOK_URL_PATH = "/{}".format(bot.token)
# web server webhook route
@app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
update = telebot.types.Update.de_json(json_string)
bot.process_new_updates([update])
return ''
else:
flask.abort(403)
# start the app
if __name__ == "__main__":
app.run()
  • bot.py → The bot logic triggered by the server.py that interacts with the Unsplash API.
# bot.py# import required libraries
import telebot
import requests
from os import environ
# setup bot with Telegram token from .env
bot = telebot.TeleBot(environ['TELEGRAM_TOKEN'])
# Handler triggered with the /start command
@bot.message_handler(commands=['start'])
def send_welcome(message):
bot.reply_to(message, 'hi there')
# configure the webhook for the bot, with the url of the Glitch project
bot.set_webhook("https://{}.glitch.me/{}".format(environ['PROJECT_NAME'], environ['TELEGRAM_TOKEN']))
  • glitch.json → Will make your app to be set up as a custom app by Glitch, allowing to install scripts. In our case, we will install Python3 and spin a process that will re-run when changes are made to the *.py source files.
// glitch.json
{
"install": "pip3 install --user -r requirements.txt",
"start": "PYTHONUNBUFFERED=true python3 server.py",
"watch": {
"ignore": [
"\\.pyc$"
],
"install": {
"include": [
"^requirements\\.txt$",
"^\\.env$"
]
},
"restart": {
"include": [
"\\.py$",
"^start\\.sh"
]
},
"throttle": 5000
}
}
  • requirements.txt → Auxiliary file containing the names of packages that need to be installed.
Flask
PyTelegramBotAPI
How the project will look after creating the required files.

2. Register the bot in telegram

Now that we have our bot setup in Glitch, we need to register in with Telegram so we can subscribe using WebHooks.

Search in Telegram for the BotFather, Telegram’s bot for creating bots (crazy, right?). Type /newbot and follow the steps, giving a name and username to the bot. The BotFather will then give you a token, that you need to put in the .env file, as:

TELEGRAM_TOKEN=XXX-XXX-XXX

3. Test the bot

Search for the bot in Telegram by the name you gave it (weekend-hack-unsplash-bot in my case) and start a conversation.

According to the code in bot.py, our bot will reply “hi there!” to the /start command.

The very first response of our bot!

4. Add more commands

For our example bot, I want to add three commands. Paste them on bot.py. Note that for the third party integration in those commands, we use the Unsplash Source API.

  • /random → returns a random picture from Unsplash.
# send random unsplash picture
@bot.message_handler(commands=['random'])
def send_random_pic(message):
response = requests.get('https://source.unsplash.com/random')
bot.send_photo(message.chat.id, response.content)
  • /4k → returns a random 4K resolution picture from Unsplash and a document with the original file. The document is required, as Telegram compacts the images.
# send random 4k unsplash picture
@bot.message_handler(commands=['4k'])
def send_random_pic(message):
response = requests.get('https://source.unsplash.com/random/4096x2160')
bot.send_photo(message.chat.id, response.content)
bot.send_document(message.chat.id, response.content,caption='rename_to_jpeg')
  • /topic → returns photos from a specific topic. Topics are defined as comma-separated words.
# send picture from topic  
@bot.message_handler(commands=['topic'])
def handle_text(message):
cid = message.chat.id
msgTopics = bot.send_message(cid, 'Type the topic(s), coma separated:')
bot.register_next_step_handler(msgTopics , step_Set_Topics)
def step_Set_Topics(message):
cid = message.chat.id
topics = message.text
response = requests.get("https://source.unsplash.com/random?{0}".format(topics))
bot.send_photo(message.chat.id, response.content)

The running project and code can be found in https://glitch.com/!/weekend-hack-unsplash-bot. Feel free to remix it!

Some snapshots of the bot working on mobile Telegram client:

Bot sending random photo.
Bot sending random 4K photo.
Bot sending photo for topics: sun, car.

Summary

Telegram provides an easy API for starting with bots, while Glitch enables rapid prototyping before moving the bot to a fully-fledged hosting solution. Enough for building simple bots, more advanced platforms (ex. Amazon Lex) is worth looking into depending on the requirements for the bot.

Resources

Summary of useful reading resources, tools, and code repositories mentioned in the article.

Front-End Engineer. Building https://taggr.ai/

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