Discord

https://habr.com/ru/articles/715552/

Руководство по созданию экономического бота для Discord, а также установка необходимых компонентов и ресурсов

Начнём с самого начала. Если у вас всё ещё не установлен Discord, то вы можете это сделать на официальном сайте discord.com, тут же вы можете открыть Discord в браузере если вы не хотите его устанавливать. После входа в Discord вам потребуется создать свой сервер, или же использовать любой уже существующий сервер, где вы имеете права администрации.

Когда вы определитесь с сервером вам понадобится подготовиться к созданию самого бота. Для этого вам нужно установить язык программирования Python. Переходим на официальный сайт python.org, далее в вкладке Downloads в соответствии с вашей операционной системой переходим на нужную страницу и устанавливаем Python версии 3.9.x, так как модуль discord который потребуется нам для написания бота не поддерживает более новые версии.

Как только вы откроете установочный файл Python, вы должны отметить галочку, подписанную как: “Add python.exe to PATH”. После этого можете нажимать install now. Спустя некоторое время вы увидите надпись Setup was successful, это означает что Python был успешно установлен.

Далее нам следует установить среду разработки. Вы можете программировать на Python как в стандартном IDLE, который устанавливается вместе с Python, так и в среде разработки собственного выбора. Но я бы порекомендовал PyCharm, ведь он наиболее распространённый и удобный, и создан специально Python. Для его установки переходим на официальный сайт jetbrains.com на страницу с PyCharm, и нажимаем на кнопку Download.

Далее выбираем в соответствие с вашей операционной системой, вы можете заплатить и использовать версию Professional, или же установить бесплатную версию Community.

Во время установки вам предложат изменить путь установки программы, чтобы избежать неожиданных проблем изменять путь не стоить. На следующей странице установки вы можете нажать на первый пункт что бы создать ярлык на рабочем столе, более ни чего трогать не стоит. После установки запускаем PyCharm и нажимаем New Project. Далее пере называем папку проекта как хотим, расположение проекта трогать не стоит. Выбираем пункт Previously configured interpreter и нажимаем Add Interpreter, заходим в System Interpreter, и видим путь к Python, или же вводим его вручную, нажимаем OK.

Для удобства ставим галочку в нижнем пункте, который создаст main.py, в котором мы и будем писать главный код бота.

Нажимаем кнопку Create, после создания проекта мы видим рабочею среду PyCharm, и открытый файл main.py. Ждём, когда PyCharm всё настроит и стираем содержимое main.py. Теперь нам осталось установить нужные модули для Python и приступить к созданию бота. Для установки библиотек вы можете воспользоваться настройками в PyCharm, или же ввести в терминал PyCharm команды, описанные далее. Для начала на всякий случай обновим pip, для этого нужно ввести в терминал:

python -m pip install --upgrade pip

Теперь установим библиотеку discord введя в терминал:

pip install discord

Следующие модули установим тогда, когда они понадобятся.

Теперь приступим к созданию бота. Для этого сперва перейдём сайт Discord Developer Portal, и удостоверившись что это официальный сайт, входим в учётную запись Discord. В свободное время вы можете почитать документацию, а для создания бота перейдите во вкладку Applications, здесь вы можете увидеть список своих приложений.

Нажимаем New Application, даём желаемое название нашему приложению, и жмём Create. После вы появитесь во вкладке General Information, где вы можете добавить описание, изменить название, добавить аватар и т.п. для вашего приложения. Теперь нам понадобиться перейти во вкладку Bot, где мы и создадим самого бота нажав на Add Bot. В этой же вкладке можно изменить имя и аватар бота. Всё что нам понадобиться на этой странице это токен бота. Сразу стоит оговорить что его не стоит никому присылать и показывать токен, а также публиковать где либо, так как с его помощью люди смогут делать что захотят от лица бота, если всё-таки такое произошло, сразу же нажимайте Reset Token на странице настройки вашего бота, это пересоздаст токен, и вы сможете заменить старый на новый, не переживая за вашего бота. Токен вашего бота находиться под именем бота всё на той же странице во вкладке Bot, если токен не отображается просто нажмите Reset Token, а после можете его скопировать кнопкой Copy.

Пришло время добавить бота на сервер, для этого разверните вкладку OAuth2, и перейдите в подвкладку URL Generator, в блоке scopes прожмите галочку Bot, после в появившемся блоке bot permissions для полного функционала бота на сервере поставьте галочку в пункте Administrator, это нужно для того, чтобы ваш бот мог делать всё что вы пожелаете на сервере, где он находиться. Попрошу не обманывать людей предлагая им добавить вашего бота, и при этом затевая что-то плохое, и также не попадайтесь сами, не добавляйте незнакомых и не верифицированных ботов, имеющих права администратора на свой сервер. После выбора этих пунктов в самом низу в блоке generated url вы можете увидеть ссылку для добавления бота на сервер. Перейдя по ссылке, выберете сервер куда вы хотите добавить бота и оставьте галочку Администратор. После нажатия кнопки Авторизовать, ваш бот присоединится к выбранному серверу и будет иметь права администратора.

Теперь всё что нам осталось это написать код. Переходим в PyCharm и открываем файл main.py. Если же вы не создали main.py при создании проекта, то создайте его сейчас с помощью нажатия правой кнопки мыши на папку проекта в левой панели PyCharm с директорией проекта, наведитесь на New, выберете пункт Python File и введите название файла. Таким образом мы будем создавать и другие файлы проекта, если же вы называете файлы по-своему, то не забудьте, как назван аналогичный файл в этом руководстве что бы не было путаницы. Для начала я предлагаю создать файл config.py, куда мы будем записывать все константы и т.п. В главном файле main.py импортируем модуль discord, пару его частей и наш файл конфига:

import discord
from discord.ext import commands
from discord.utils import get
from config import *

Далее добавим в конфиг константы TOKEN и PREFIX:

TOKEN = "ВАШ ТОКЕН"
PREFIX = "!"

В константе TOKEN будет храниться токен вашего бота, где найти токен описано выше. В константе PREFIX будет храниться префикс ваших команд, например “!”.

Теперь в главном файле после импортов, создаём переменную client, с помощью которой будут работать наши команды и не только:

client = commands.Bot(command_prefix=PREFIX, intents=discord.Intents.all())

При создании переменной мы создаём класс commands.Bot в который мы должны указать префикс наших команд, используя константу, которую мы импортируем из нашего файла config.py. Вы можете не задавать переменную intents, если после создания бота при его запуске вас не потребуют это сделать, если же всё-таки у вас потребовали добавить intents в переменную client, вам понадобиться включить все пункты блока Privileged Gateway Intents, который можно найти на той же странице, где и токен вашего бота.

Что бы узнать работу команд посмотрим на форму префикс команды:

@client.command()
async def <название команды>(ctx, <прочие переменные если они должны быть>):
    <код который исполняется при вызове команды>

Как вы заметили, команда, это просто асинхронная функция, а асинхронная она для того, чтобы различные команды можно было использовать не зависимо от друг друга. Разберём каждую строчку. В первой строчке мы добавляем нашей функции декоратор, который делает из этой функции полноценную команду, далее в название команды (функции) вы должны записать то, что нужно будет ввести в самом Discord после префикса для вызова команды, название может быть на любом языке, т.е. вы можете ввести название этой функции даже на русском. В полученных переменных мы обязательно должны получить ctx, вкратце с его помощью мы получаем информацию о вызове команды: само сообщение в Discord, автора сообщение, канал и так далее. Если же вам нужно получить ещё какую-либо информацию от того, кто вызвал команду, то вы можете создать дополнительные переменные, чтобы при вызове команды заполнить их, после команды через пробел нужно ввести столько информации сколько нужно. Каждый пробел разделяет то, что вы написали на разные переменные, то есть у вас не выйдет написать предложение в одну дополнительную переменную, например если ваша команда получает две переменные, а вы ввели: “<команда> <слово> <слово> <слово>”, то это будет ошибка. Так же стоит уточнить что если вам нужно получить число, то переменную придётся перевести из строки в число в коде команды. И последнее, как вы, наверное, поняли, это сам код команды, который будет работать при вызове команды.

Рассмотрим пример стандартной тестовой команды “ping”, с небольшими дополнениями:

@client.command()
async def ping(ctx):
    await ctx.send("pong!")
    await ctx.send(ctx.author.name)

Первое что делает наша команда, с помощью функции await ctx.send() отправляет сообщение “pong!”, в чат в котором была вызвана команда. Далее с помощью ctx.author мы получаем класс пользователя, который вызвал команду, а потом его имя также отправляем в чат.

После записи этой команды в код для тестирования, нам осталось самое главное. В самом конце кода нам нужно написать функцию, которая с помощью токена вашего бота будет его запускать в самом Discord:

client.run(token=TOKEN)

После всех действий код должен выглядеть так:

import discord
from discord.ext import commands
from discord.utils import get
from config import *

client = commands.Bot(command_prefix=PREFIX, intents=discord.Intents.all())

@client.command()
async def ping(ctx):
    await ctx.send("pong!")
    await ctx.send(ctx.author.name)

client.run(token=TOKEN)

Запускаем код, и переходим в Discord. После отправки команды вы должны будете увидеть следующее: см. картинку ниже.

Готово! Какой никакой бот уже есть, и он работает.

Продолжим, и приступим к написанию команд для экономики, а также созданию json файла, где будут храниться балансы пользователей сервера в Discord. Перед работой с json, импортируем стандартный модуль для работы с ним:

import json

Создаём базу данных в виде файла wallets.json, который будет хранить данные о кошельках пользователей, а также в него нужно написать {} что бы создать пустые данные. Далее создадим функцию, которая будет извлекать всю информацию о кошельке нужного пользователя из базы данных, или записывать если его там нет. Но перед этим добавим новую константу с параметрами кошелька по умолчанию в наш config.py:

WALLET_DEFAULT = {"balance": 0}

Теперь и сама функция:

async def get_user_wallet(user_id):
    user_id = str(user_id)

    with open("wallets.json", "r") as file:
        users_wallets = json.load(file)

    if user_id not in users_wallets.keys():
        users_wallets[user_id] = WALLET_DEFAULT

    with open("wallets.json", "w") as file:
        json.dump(users_wallets, file)

    return users_wallets[user_id]

Данная функция открывает наш json файл где хранятся кошельки пользователей, далее она проверяет наличие данного id пользователя в базе данных, если его нет, то функция добавляет его в базу данных, и добавляет ему константу в которой находится словарь с его стартовым балансом и прочей информацией которую вы пожелаете записать, потом записывает это в файл json, далее функция просто возвращает словарь с данными пользователя чей id был получен. Для того что бы изменять параметры того или иного кошелька, создадим ещё одну функцию:

async def set_user_wallet(user_id, parameter, new_value):
    user_id = str(user_id)

    with open("wallets.json", "r") as file:
        users_wallets = json.load(file)

    if user_id not in users_wallets.keys():
        users_wallets[user_id] = WALLET_DEFAULT

    users_wallets[user_id][parameter] = new_value

    with open("wallets.json", "w") as file:
        json.dump(users_wallets, file)

Эта функция всё так же открывает базу данных и проверяет наличие полученного пользователя в ней, но в добавок записывает в полученный параметр новое полученное значение.

Систему записи и получения информации из базы данных мы реализовали, теперь её нужно задействовать. Создадим команду для просмотра баланса:

@client.command()
async def balance(ctx):
    user_wallet = await get_user_wallet(ctx.author.id)
    await ctx.send(f"**Ваш баланс**: {user_wallet['balance']}")

Тут всё просто, мы создаём стандартную префикс команду с названием “balance”, далее при вызове команды с помощью функции, описанной выше, мы получаем кошелёк пользователя, который вызвал команду, и пишем в чат его баланс.

Пора протестировать работу бота. Но перед этим, добавим ещё одну, на этот раз не обязательную, функцию, а именно, событие, которое будет вызываться при включении бота:

@client.event
async def on_ready():
    print("Бот запустился!")

Нам она понадобится чтобы чётко видеть, когда бот включился. Замете что декоратор немного изменился, так как это не команда, а событие, и в зависимости от названия функции будет меняться событие, при котором функция будет срабатывать, чтобы узнать какие ещё события существуют ознакомьтесь с документацией модуля discord.py.

Теперь запускаем нашего бота и при тестирование его работы, мы должны увидеть следующее: см. картинку ниже.

А также если посмотреть в наш json файл, то увидим, что бот записал нас туда.

Я полагаю, что вы уже определились каким образом, участники вашего сервера будут зарабатывать монеты, поэтому вы можете реализовать это как пожелаете, но поскольку я не знаю, как вы хотите это сделать, расскажу об универсальном способе. Сделаем команду для администрации вашего сервера, которая будет прибавлять или убавлять указанное при вызове команды количество монет:

@client.command()
async def change_balance(ctx, user_mention=None, amount=None):
    if not ctx.author.guild_permissions.administrator:
    	  await ctx.send("**Недостаточно прав!**")
    	  return

    if user_mention is None or amount is None:
        await ctx.send(f"**Вы не указали тот или иной параметр!**")

    user = get(ctx.guild.members, id=int(user_mention[2:-1]))
    user_wallet = await get_user_wallet(user.id)
    user_wallet["balance"] += int(amount)
    await set_user_wallet(user.id, "balance", user_wallet['balance'])

    await ctx.send(f"Баланс {user.name} был успешно изменён!\n" \
                   f"**Баланс {user.name}**: {user_wallet['balance']}")

В этой функции мы должны получить упоминание пользователя, которому мы изменим баланс, и число монет, в количестве монет мы сможем указать как отрицательное число что бы убавить баланс, так и положительное. Далее в коде функции мы проверяем является ли пользователь вызывающий команду администратором и ввёл ли он нужные параметры при написании команды, потом получаем класс пользователя с помощью его id, который мы получаем путём преобразования упоминания, получаем его кошелём с помощью выше созданной функции, изменяем его баланс, также с помощью выше созданной функции изменяем баланс указанного пользователя, и, выводим сообщение об успешном выполнении команды.

Как обычно протестируем работу:

Базовые вещи для экономического бота мы реализовали, далее посмотрим на некоторые дополнения. Например, имеет смысл создать команду также для администрации, которая будет выключать бота, это может пригодиться при зависании бота и подобных случаях:

@client.command()
async def kill(ctx):
    if not ctx.author.guild_permissions.administrator:
        await ctx.send("**Недостаточно прав!**")
        return
    sys.exit()

Для этой команды ещё понадобиться импортировать модуль sys:

import sys

Теперь посмотрим на такую интересную вещь в оформлении сообщений как “embed”. Вкратце это табличка, с помощью которой можно оформить текст. Рассмотрим создание embed на примере команды баланса:

embed = discord.Embed(title=f"💰 БАЛАНС {ctx.author.name}: {user_wallet['balance']}",
                      color="#FFD700")

В title мы записываем главный заголовок embed, в нашем случае он и будет представлять весть текст, далее в color мы можем указать любой код цвета, чтобы изменить цвет левой полоски embed. Также стоит рассмотреть добавление полей с текстом в embed:

embed.add_field(
    name=<заголовок поля>,
    value=<содержание текста>,
    inline=<если указано False то каждое поле будет с новой строки>
)

В нашем случае это не понадобиться. По итогу, чтобы отправить в сообщении embed, нужно использовать всё тот же await ctx.send(), только на этот раз в следующем виде:

await ctx.send(embed=embed)

И вновь протестируем всё выше созданное:

Как видим после команды kill, бот перестаёт работать.

Теперь баланс выглядит намного лучше.

Вот и все базовые аспекты экономического бота. На конец отмечу что для того, чтобы больше узнать о том или ином модуле, изучайте их официальные документации.

Last updated