Creating a Discord Bot to Monitor Product Prices

Imagine this situation: you are closely monitoring a certain product on Yandex.Market and want to receive an instant notification as soon as its price changes in the desired direction. Or, perhaps, you are the owner of an online store and want to constantly monitor the dynamics of competitors' prices in order to quickly respond and remain competitive in the market. In both of these cases, as well as in many other scenarios, a Discord price monitoring bot will become your indispensable digital assistant, working 24/7. In this detailed article, we will analyze in detail the process of creating such a multifunctional bot.

Let's take a closer look at the key areas of application of our bot and how it can make life much easier for users:

  • Find great deals on electronics: Imagine you want to buy a new TV, but the current price does not suit you. Instead of wasting time on constant monitoring of various online stores, you can add the product you are interested in to the watch list. Our bot will automatically check for price changes and instantly notify you when the price becomes suitable. This will allow you to purchase the product at a bargain price without any extra effort.

  • Analysis of competitive offers for online aggregators: If you work with a platform that collects and compares offers from different sellers, our bot will become an important tool for tracking and analyzing prices. It will automatically monitor price changes from your suppliers, compare them with competitors' offers and promptly inform you about the need to adjust your pricing policy. This will allow you to offer better conditions to customers and maintain the competitiveness of your platform.

What are we going to do? Detailed action plan

  • Preparation of the technical base
    In this section, we will look at the process of installing Python, creating an isolated development environment, and integrating the necessary libraries to implement the project.

  • Discord app configuration
    This step involves registering a new bot in the Discord system, obtaining an authorization token, and setting up key parameters for the bot to function.

  • Developing the main functionality of the Discord bot
    Here we'll focus on writing the basic code that enables you to connect to Discord and implement basic interaction commands.

  • Implementation of a price monitoring system
    At this stage, we integrate into our bot mechanisms for collecting and analyzing information about product prices from various web resources, using specialized libraries for processing HTTP requests and extracting data from HTML structures.

  • Launching our bot in the cloud for 24/7 work

    This will help us Amvera Cloudwhere you can deploy a project using git push or simply drag and drop files in the interface. In addition, there are other benefits to using Amvera:

    • Convenient delivery of code updates via git. Updating a project on production is done with just three commands in your IDE. It's easier than setting up a VPS.

    • You don't need to do any additional settings, the application can be deployed in literally 5 minutes. Fill in a couple of fields in the configuration, upload files, and everything is configured and launched by itself.

    • Free balance upon registration – 111 rubles.

    • If you stop the project, no money is written off and no data is lost. You only pay for running application.

But enough advertising, let's get down to the most important thing – developing a bot.

Preparing the environment

1. Installing Python and required libraries

First, let's make sure we have Python version 3.8 or higher installed. If Python isn't installed yet, download it from official website.
After installation, open the terminal and run the command:

python --version

Further, for convenience and isolation of the project, it is recommended to use a virtual environment. It allows you to create a separate area where the necessary libraries will be installed, which prevents conflicts between dependencies of different projects.

Let's create and activate a virtual environment:

# Создаём виртуальное окружение 
python -m venv venv 
# Активация виртуального окружения 
# На Windows: 
	.\venv\Scripts\activate  
# На macOS и Linux: 
	source venv/bin/activate

After activating the virtual environment, you will see the prefix (venv) at the beginning of the command line.

Now let's install the necessary libraries:

pip install discord.py requests beautifulsoup4 python-dotenv

Parsing installed libraries

discord.py: This asynchronous Python library is designed to interact with the Discord API. It allows you to create Discord bots that can connect to servers, send and receive messages, respond to user commands, and do many other tasks.

requests: A simple and powerful library for making HTTP requests. It is used to send requests to web pages to get the HTML code of product price pages.

beautifulsoup4: Library for parsing HTML and XML documents. It allows you to extract the necessary data from the HTML code of pages, which is necessary for obtaining product prices.

python-dotenv: This library loads environment variables from a file .envwhich is especially useful for securely storing sensitive information such as API tokens, passwords, and other data.

Creating and Setting Up a Discord Bot

Creating a project structure

Let's start by creating a folder for the project and organizing the files:

# Создаём папку проекта 
mkdir PriceMonitorBot cd PriceMonitorBot  
# Создаём основной файл проекта 
touch main.py  
# Создаём файл для хранения конфиденциальной информации 
touch .env

Creating an App on Discord

  1. Go to Discord developer portal.

  2. Log in to your Discord account if you haven't already.

  3. On the portal page, click the button “New Application” .

  4. In the window that opens, enter the name of your application and click “Create”.

Creating a bot in the application

  1. After creating the application, you will be redirected to the management page. In the menu on the left, select the tab “Bot”.

  2. Click the button “Add Bot” (Add bot).

  3. Confirm the creation of the bot by clicking “Yes, do it!”.

Getting a token

  1. On the bot page under the heading “TOKEN” press the button “Copy” (Copy).

  2. This is your token – a long string of characters. Handle it carefully, as it is the “key” to access your bot.

Important: Do not give your token to anyone. If the token falls into the wrong hands, the attackers will be able to control your bot. If you accidentally reveal the token, you can reset it by clicking the button “Regenerate” (Regeneration).

To add a bot to your server:

  • In the section “OAuth2” select “URL Generator”.

  • Check the box “bot” in the section “SCOPES”.

  • In the section “BOT PERMISSIONS” select the desired permissions (eg “Send Messages”).

  • Copy the generated link and open it in your browser. Select the server you want to invite the bot to.

Setting up the .env file

File .env will contain environment variables that are used to configure your bot. These variables will be loaded in the code from the file using the library python-dotenv. Open the file .env in any text editor and add the following lines to it:

DISCORD_TOKEN=YOUR_DISCORD_BOT_TOKEN

Replace YOUR_DISCORD_BOT_TOKEN to your bot's actual token, which we got earlier in the Discord developer panel.

Organizing and protecting your .env file

Because .env contains sensitive data, it is important to ensure that this file does not become publicly available, especially if you use version control systems such as Git. To do this, add the file .env V .gitignoreso that it doesn't get accidentally committed to the repository.

Create a file .gitignore in the root of the project and add the line to it:

.env

Now that we have a general understanding of the structure and functionality of our Discord bot, it's time to start coding. In this section, we'll walk through each component step-by-step, starting with importing the necessary libraries.

The first part of our code is importing all the necessary libraries. This uses libraries that will help us interact with Discord, send HTTP requests and parse HTML, and manage environment variables:

import discord 
import requests 
from bs4 import BeautifulSoup 
from discord.ext import commands, tasks 
from dotenv import load_dotenv import os
  1. discord: This library is required to work with the Discord API. It provides classes and methods for managing the Discord server, bots, channels, messages, and other entities. We will use it to create and manage our bot.

  2. requests: Used to send HTTP requests. This library will help us to get HTML pages from websites to extract price information.

  3. BeautifulSoup: A library for parsing HTML and XML. In our project, it is used to search and extract price data from the HTML code of product pages.

  4. discord.ext.commands And discord.ext.tasks: These modules are from discord.ext help expand opportunities discord.py. Module commands allows you to create commands for our bot, and tasks – run recurring tasks.

  5. dotenv: load_dotenv from this library allows you to load environment variables from a file .env. This is a convenient and secure way to store sensitive information, such as our bot token, without having to include it directly in the code.

  6. os: Module for interacting with the operating system. We will use it to get the values ​​of environment variables.

Loading environment variables

Using environment variables allows us to store sensitive data such as the bot token in a secure way.

load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN')
  • load_dotenv(): This function loads all environment variables defined in the file .envinto the current Python session. This allows us to use them in code without revealing the actual values.

  • TOKEN: We get the value of our bot's token from the environment variable DISCORD_TOKEN. This value will need to be defined in the file .env before running the code. Using environment variables instead of hard-coding tokens or other sensitive data makes the code more secure.

Setting up the bot and declaring global variables

In this step, we create an instance of our bot, set up its intents, and define global variables for tracking products and the notification channel.

intents = discord.Intents.default() 
intents.message_content = True 
bot = commands.Bot(command_prefix='!', intents=intents)  

tracked_items = {} 
notification_channel = None
  1. intentions: Intents are a way to control what events your bot will receive from Discord. Using intents can reduce the load on your bot and improve security. Here we use Intents.default() to create an object with basic settings. Installation intents.message_content = True Allows the bot to receive the contents of messages, which is necessary for processing commands.

  2. bot:Here we create an instance of the bot using the class commands.Bot. Parameter command_prefix='!' specifies that all bot commands will begin with the symbol !. Parameter intents=intents sets the intentions for the bot.

  3. tracked_items: This is a dictionary where we will store the URLs of the products we are tracking and their current prices. A dictionary is a convenient data structure for this task, as it allows you to easily add, remove, and update items.

  4. notification_channel: Variable that will store a link to the channel to which the bot will send price change notifications. Initially, it is set to Noneand it will need to be configured using a special command.

Function to get the price of a product

To extract prices, we need a function that will send requests to sites and analyze the resulting HTML pages.

def get_price(url): 
	headers = { 
			"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}
	response = requests.get(url, headers=headers) 
	soup = BeautifulSoup(response.text, 'html.parser')
	
	price_tag = soup.find('span', {'class': 'price'}) 
	if price_tag: 
		price = 
		float(price_tag.text.replace('\u2009', '').replace('₽', '').replace(' ', '').strip()) 
		return price 
	return None
  1. headers: Setting headers including User-Agentmakes requests more similar to requests from a regular web browser. This helps to avoid blocking or restrictions from sites.

  2. requests.get(url, headers=headers): Performs an HTTP request to the specified URL with the specified headers. If the site is accessible, we get the HTML code of the page.

  3. BeautifulSoup: We use BeautifulSoup to parse the received HTML. It helps us easily find the tags we need and extract information from them.

  4. price_tag: We are looking for the first element with the tag <span> and attribute class="price". This is a simplified assumption that the price on the page is displayed in this format. In a real project, the HTML format may differ, and you may have to adapt this code for a specific site.

  5. price: Once we have found the tag with the price, we extract the text, remove unnecessary characters (such as the currency symbol and spaces) and convert it to a floating point number. If the tag is not found, the function returns None.

Implementing Bot Commands

Now we will add commands that users can use to control the bot and track prices.

  1. Adding a product to tracking

@bot.command() 
async def track(ctx, url: str):     
	price = get_price(url)     
	if price:         
		tracked_items[url] = price        
			await ctx.send(f"Товар добавлен в отслеживание.Цена:{price}₽")
	else:         
		await ctx.send("Не удалось получить цену для этого товара.")
- **@bot.command()**: Декоратор, который регистрирует функцию как команду бота. Название функции (`track`) будет использоваться как команда, которую нужно отправить боту.
- **track(ctx, url: str)**: Эта команда принимает URL товара и добавляет его в список отслеживаемых товаров, если удаётся получить его цену. `ctx` — это контекст команды, он предоставляет информацию о вызове команды, включая канал, пользователя и т.д.
  1. Removing an item from tracking

@bot.command() 
async def untrack(ctx, url: str):     
  if url in tracked_items:         
  	del tracked_items[url]         
  	await ctx.send(f"Товар удален из отслеживания.")     
  else:         
  	await ctx.send("Этот товар не отслеживается.")`
- **untrack(ctx, url: str)**: Команда для удаления товара из списка отслеживаемых. Она проверяет, есть ли указанный URL в `tracked_items` и удаляет его, если он там есть.
  1. View a list of watched products

  @bot.command() 
  async def list(ctx):     
      if tracked_items:         
  	    message = "Отслеживаемые товары:\n"         
  		for url, price in tracked_items.items():             
  			message += f"{url} - Текущая цена: {price} ₽\n"        
  		await ctx.send(message)     
  	else:         
  		await ctx.send("Список отслеживаемых товаров пуст.")`
- **list(ctx)**: Команда для отображения всех товаров, которые бот отслеживает, вместе с их текущими ценами. Если список пуст, бот сообщает об этом.
  1. Setting up a channel for notifications

@bot.command() 
async def setchannel(ctx):     
	global notification_channel     
	notification_channel = ctx.channel    
	await ctx.send(f"Уведомления о изменении цен будут отправляться в канал: {ctx.channel.name}")`
c- **setchannel(ctx)**: Команда для установки текущего канала в качестве канала для отправки уведомлений о изменении цен. Эта команда запоминает канал, из которого была вызвана, и сохраняет его в глобальной переменной `notification_channel`.
  1. Manually updating prices

@bot.command()
async def update(ctx):
await ctx.send(“Updating prices…”)
await price_check()

  
    - **update(ctx)**: Команда для ручного запуска проверки цен. Полезно для случаев, когда нужно немедленно узнать о изменениях цен.

### Задача для регулярной проверки цен

Для автоматизации проверки цен мы создаём задачу, которая будет запускаться каждые 60 минут.

```python
@tasks.loop(minutes=60) 
async def price_check():     
	for url, old_price in tracked_items.items():         
		new_price = get_price(url)         
		if new_price and new_price != old_price:             
			tracked_items[url] = new_price             
			if notification_channel:                 
				await notification_channel.send(f"Цена на товар изменилась! Новая цена: {new_price} ₽ (Старая цена: {old_price} ₽)\n{url}")             
			else:                 
				print("Канал для уведомлений не установлен.")
  • @tasks.loop(minutes=60): A decorator that specifies that a function price_check must be performed every 60 minutes.

  • price_check(): This function goes through all the products you are tracking and checks their current prices. If the price changes, the bot updates it in the dictionary. tracked_items and sends a notification to the specified channel.

Launching the bot

The last step is to launch the bot using the token.

`@bot.event async def on_ready():     
	print(f'Logged in as {bot.user}')     
	price_check.start()  

bot.run(TOKEN)`
  • on_ready(): Event that is called when the bot successfully connects to the Discord server. Here we print a message to the console and run the task price_check.

  • bot.run(TOKEN): Launches the bot with the specified token. The token must be defined in the file .env.

Now that we have configured and tested our Telegram bot on our local machine, it is time to launch it in the cloud so that it is available 24/7. In this step, we will deploy the bot to the platform Amverawhich provides convenient tools for hosting applications.

Registration in the service

  1. Create an account:

    • Go to the website Amvera and click on the “Registration” button.

    • Fill in all required fields, including your phone number, and click the “Send code” button.

    • Enter the code received in SMS, confirm that you are not a robot, and click “Register”.

    • After that, confirm your email address by clicking on the link in the email.

    • Get 111 rubles on your balance for tests)

Creating a project and placing a bot

  1. Creating a new project:

    https://habrastorage.org/r/w1560/getpro/habr/upload_files/90a/00c/aa0/90a00caa0d20e5d56d26f898a5eb9fe2.png
  2. Project setup:

    • Give your project a name (preferably in English).

    • Select a tariff plan. The most basic tariff will be enough to deploy the bot.

    • The initial balance is enough for the bot to work for free and continuously for several weeks.

    https://habrastorage.org/r/w1560/getpro/habr/upload_files/3d0/1e7/14c/3d01e714ca77535ca452f7afa0ced4a2.png
  3. Preparing code for deployment:

  • Amvera uses git to deliver code to the cloud. You will need to create a configuration file amvera.ymlwhich will tell the cloud how to run your project.

  • To make it easier to create this file, use graphic generation tool.
    Selecting environment and dependencies:

    • Specify the Python version and path to the file requirements.txtwhich contains all the necessary packages.

    • Specify the path to the main file of your project, for example main.py.

  • Data storage:

    • If the bot saves data to disk, it should be placed in a folder datato avoid losing them when restarting.

  • Generating and loading a file:

Configuration file amvera.yml serves to ensure that the Amvera platform knows how to properly build and run your project. This file contains key information about the environment, dependencies, and instructions for running the application.

File structure amvera.yml:

meta:
  environment: python  # Указывает, что проект использует Python в качестве окружения.
  toolchain:
    name: pip          # Определяет менеджер пакетов для установки зависимостей.
    version: "3.8"     # Задает версию Python для окружения проекта.

build:
  requirementsPath: requirements.txt  # Путь к файлу, где указаны все необходимые зависимости.

run:
  scriptName: app.py  # Основной файл вашего проекта, который будет запущен после сборки.
  persistenceMount: /data  # Директория для хранения постоянных данных.
  containerPort: 80    # Порт, на котором будет доступен ваш проект в контейнере.

In order for our project to work correctly in the Amvera environment, it is important to specify all the necessary packages in the file requirements.txt. This file defines all Python dependencies that are needed to run the code.

This is what our file looks like requirements.txt :

discord.py==2.2.3
requests==2.31.0
beautifulsoup4==4.12.2
python-dotenv==1.0.0

Initializing and sending the project to the repository:

  • Initialize a git repository at the root of your project if you haven't already:

    git init
  • Link your local repository to the remote one on Amvera:

    git remote add amvera <https://git.amvera.ru/ваш_юзернейм/ваш_проект>
  • Add and commit the changes:

    git add .
    git commit -m "Initial commit"
  • Send your project to the cloud:

    git push amvera master

Building and deploying the project:

https://habrastorage.org/r/w1560/getpro/habr/upload_files/ebb/8d7/7e3/ebb8d77e3a4c581c15a03843df3386d2.png

The build status will appear after all files are downloaded and committed.

Once the build is complete, the project will move to the “Deploying in Progress” stage and then to the “Successfully Deployed” status.

https://habrastorage.org/r/w1560/getpro/habr/upload_files/c75/56c/5f7/c7556c5f70e0992280694a346ba3f070.png

Average build and launch time is 5-10 minutes. At the moment of launch the status may be red – this is normal. The main thing is to look at the errors in the log

Successful launch

Successful launch

If the project does not deploy, check the build logs and application logs for debugging.

If the project is stuck at the “Build” stage, make sure the file is correct amvera.yml.

Conclusion

In this article, we looked at the process of creating and deploying a Discord bot for monitoring prices on Yandex.Market. We went from writing the bot code in Python to hosting it in the cloud on the platform Amvera.

Key points we covered:

  • Development of bot functionality for price monitoring

  • Setting up commands and handling events in Discord

  • Implementation of automatic price checking at a given interval

  • The process of registration and creation of a project on the platform Amvera

  • Preparing a project for deployment in the cloud

  • Setting up and pushing code to the Amvera repository

Author: Alexey Ponomarev


Relevant articles

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *