In the previous parts of this tutorial, we built a telegram bot and dockerized it. In this section, we will see how to do something useful with our bot.

This is the third part of a three-part tutorial. Here are the links to other parts of this tutorial.

  1. Part 1
  2. Part 2
  3. Part 3(You are here)

Saving Messages to Database

To save messages to the database, we need to add a model first. Open the models.py in the chat app and add the following code to it.

from django.db import models


class TelegramMessage(models.Model):
    name = models.CharField(max_length=255)
    message = models.TextField()
    chat_id = models.BigIntegerField()

    def __str__(self):
        return self.name

Let us add this model to django admin next. Open the admin.py inside the chat app and add the following.

from django.contrib import admin

from .models import TelegramMessage


@admin.register(TelegramMessage)
class TelegramMessageAdmin(admin.ModelAdmin):
    list_display = ("name", "chat_id")

Now we can create migrations for our new models. Run the following command.

docker-compose run django_server pipenv run python manage.py makemigrations

Then run the migrate command.

docker-compose run django_server pipenv run python manage.py migrate

Let us create a superuser account also. We will need this to log in to the admin site.

docker-compose run django_server pipenv run python manage.py createsuperuser

Go to the admin site and log in with the credentials. You should see the model there.

Now let us update the code to save the messages to the database. Open the tasks.py file in the chat app and update it with the following code.

import requests
from celery import shared_task
from django.conf import settings

from .models import TelegramMessage


@shared_task
def send_telegram_reply(message):
    name = message["message"]["from"]["first_name"]
    text = message["message"]["text"]
    chat_id = message["message"]["chat"]["id"]

    TelegramMessage.objects.create(name=name, message=text, chat_id=chat_id)

    reply = f"Hi {name}! Got your message: {text}"

    reply_url = f"https://api.telegram.org/bot{settings.TELEGRAM_API_TOKEN}/sendMessage"

    data = {"chat_id": chat_id, "text": reply}

    requests.post(reply_url, data=data)

We have imported our model and updated the task function to save the message details to the database.

Restart the docker-compose since we have changes in the celery task. Then open the bot in Telegram and send a message. You should see the message in django admin. Make sure you configure the webhook URL correctly before testing this.

Adding Weather Information

The replies from our bot it not very useful now. It is just sending us the message back. Let’s update the bot to give weather information when a user asks for it.

We will be generating some fake weather information here. When you build a real weather bot, you should be calling some weather information service and returning that data to the user.

Create a new weather.py file inside the chat app and add the following code.

import random


def get_weather(city):
    weather_choices = ["sunny", "cloudy", "rainy", "snowy"]

    weather = random.choice(weather_choices)
    temperature = random.randint(5, 40)

    return f"Weather in {city} is {temperature}c and {weather}"

We are creating a fake weather forecast with some random data. Next, we need to update the celery task to call this function. Open the tasks.py file inside chat app and update it with the following code.

import requests
from celery import shared_task
from django.conf import settings

from .models import TelegramMessage
from .weather import get_weather


@shared_task
def send_telegram_reply(message):
    name = message["message"]["from"]["first_name"]
    text = message["message"]["text"]
    chat_id = message["message"]["chat"]["id"]

    TelegramMessage.objects.create(name=name, message=text, chat_id=chat_id)

    words = text.split(" ")
    command = words[0].lower()

    if len(words) > 1 and command == "weather":
        city = " ".join(words[1:])
        reply = get_weather(city)
    else:
        reply = "Invalid command. Send 'weather <city>' to get the weather information"

    reply_url = f"https://api.telegram.org/bot{settings.TELEGRAM_API_TOKEN}/sendMessage"

    data = {"chat_id": chat_id, "text": reply}

    requests.post(reply_url, data=data)

We are splitting the message into words and take the first word as command. We are also converting it into lowercase for ease of comparison. We then check if the length of words is at least two and the command is weather. If so, we construct the city name from the rest of the words and fetch the weather information. If the command is not weather or if there is no city name, we send a helpful error message. Don’t forget to restart the docker-compose before you test this.

Congratulations! You have reached the end of this tutorial. I hope you learned enough to code your own bot.


Last updated on September 15, 2022
Tags: Python Django Telegram Chatbot