Yandex Music Bot - это бот, позволяющий проигрывать музыку в Discord, используя возможности Yandex Music.
Так же по боту записано отдельное видео. В нем представлена такая же информация что и в Readme файле, но с комментариями. Если вам удобней потреблять информацию в формате видео - прошу кликать на меня.
На сегодняшний день бот поддерживает следующий функционал:
- Плеер. Функционал плеера:
- Переключаться на следующий трек.
- Переключаться на предыдущий трек.
- Ставить текущий трек на паузу.
- Ставить текущий трек на повтор.
- Отображать очередь следующих треков.
- Сбрасывать всю очередь.
- Команда /play. Команда /play является основной командой, чтобы начать прослушивание музыки или добавить треки в существующую очередь. В качестве параметра команда принимает ссылку на трек/альбом/исполнителя/плейлист/подкаст/книгу или поисковой запрос.
- Недавно прослушанные треки. Каждый запрос бот сохраняет в базу данных и по завершению прослушивания отображает пять последних запросов.
- История. После завершения трек попадает в созданную ветку. Ветка хранит все ранее прослушанные треки.
Прежде чем решиться на развертывание бота у себя на сервере, предлагаю вам ознакомится с ним через CactusBot.
CactusBot - это уже настроенная версия бота, которой вы можете воспользоваться, чтобы проверить функциональность и возможности бота.
Для добавления бота к себе в логово, выполните следующие шаги:
- Перейдите по ссылке.
- В открывшемся окне выберите сервер, в который нужно добавить бота и выдайте боту права администратора.
- После появления на сервере, бот создает текстовый канал с именим "музыка", а так же ветку "история". Важно: на текущий момент бот принимает основные команды только в своем созданном текстовом канале и менять канал нельзя, но можно переименовывать (ветку тоже можно переименовывать).
- Если вы перейдете в канал "музыка", то сможете заметить что бот написал свое первое сообщение. Теперь вы можете воспользоваться ботом.
- Для того чтобы включить музыку, перейдите в любой голосовой канал на сервере и в текстовом канале "музыка", введите интересующий запрос с использованием команды play. Например чтобы включить альбом доры Miss, нужно ввести запрос: /play https://music.yandex.ru/album/22647617
- Если вы слышите музыку, значит бот корректно настроен и работает. Приятного прослушивания!
Note
Прежде чем развернуть бота, убедитесь что у вас установлен docker и git.
- Клонируем репозиторий:
Mac/Linux:
git clone https://github.com/VasiliyNichnikov/yandex-music-bot.git
Windows:
git clone https://github.com/VasiliyNichnikov/yandex-music-bot.git --config core.autocrlf=input
- Переходим в папку проекта:
cd yandex-music-bot
- Окружение. Сначала настроим .env. Для этого продублируйте файл .env.example и переименуйте его в .env:
DISCORD_TOKEN=Discord токен бота, нужно скопировать из discord developer portal
YANDEX_TOKEN=Яндекс токен, нужен для получение треков из Я.Музыка
IS_PRODUCTION=TRUE выбираем True, более детально в главе "Для разработчиков"
OWNER_BOT_ID=id бота, его можно так же найти в discord developer portal (На портале поле называется как APPLICATION ID)
DATABASE_USER=root - оставляем без изменений
DATABASE_PASSWORD=тут надо написать пароль от базы данных
DATABASE_NAME=cactusdiscordbot - можем поменять или оставить без изменений
DATABASE_HOST=localhost - если собираете на локальной машине, то оставляем без изменений,
если собираете в docker, то пишите mysql
DATABASE_PORT=3306 - оставляем без изменений
Note
Для получения YANDEX_TOKEN, можете воспользоваться следующей инструкцией: https://t.me/yandex_music_api/32448
- Теперь по аналогии с .env дублируем файл .env.database.example и называем его env.database. Переходим к заполнению:
MYSQL_ROOT_PASSWORD=вставляем пароль к базе данных из файла .env, поле DATABASE_PASSWORD
MYSQL_DATABASE=cactusdiscordbot - если на предыдущем пункте, не меняли значение DATABASE_NAME - оставляем без изменений,
в противном случае изменяем.
- Собираем проект:
docker compose build
- Запускаем проект:
docker compose up -d
- Убедимся, что бот запущен корректно. Находим в корне проекта, файл cactus_discord_bot.log. При корректной загрузке, вы увидете следующее:
[2024-06-21 10:20:08] [INFO ] core.config: Loading dev keys.
...
[2024-06-21 10:20:13] [INFO ] bot: Bot is ready to work.
- Поздравляю, бот запущен. Последний пункт - добавить бот на сервер и наслаждаться музыкой!
В данном разделе основной упор сделан на описание конфигураций, которые могут помочь при тестирование бота. Так же описаны существующие ошибки и недоработки.
Все основные конфигурации представлены в файле config.py. Сам файл находится в папке core и содержит словари с различными настройками. Основной словарь называется public_keys:
public_keys = {
"prefix": "!", # Префикс для вызова команд
"message_content_name": "Музыка", # Слово, которое будет написано в сообщение с плеером.
"recent_auditions_title": "Вы недавно слушали:",
"channel_with_music_default_name": "музыка", # Название канала по умолчанию для прослушивания трека. (На случай если канал создан заранее)
"history_thread_default_name": "история", # Название ветки по умолчанию для истории треков. (На случай если ветка создана заранее)
"default_icon_url_vk": "https://sun9-56.userapi.com/impg/p6aGXemp7cGozSNzNmTTHtsyTSuDkyo4GVLtnQ/tHFizKgaMDg.jpg?size=1024x1024&quality=95&sign=a063aaa51b89642075129f8fdbbbeef3&type=album", # Иконка бота
"messages": None, # подгружается из json, все сообщения бота
"message_lifetime": 30, # Дефолтное время жизние сообщения, если не удалось посчитать кол-во слов в предложение
"database_url": "mysql+pymysql://{user}:{password}@{host}/{database}?charset=utf8mb4",
"maximum_number_recent_requests_in_message": 5, # Не более 10. Так как дискорд за раз может отправить только 10 Embed.
"max_tracks_in_list": 3, # Сколько максимально будем держать скаченных треков (Для одного канала)
"commands_that_ignore_music_text_channel": ["help", "recreate"], # Команды, которые можно вызывать из любого текстового канала
"number_of_attempts_when_requesting_music_service": 10, # Кол-во попыток при возникновение ошибке при запросе
"delay_in_case_of_error_when_requesting_music_service": 30, # Время ожидания прежде чем выполним следующий запрос к сервису
"loading_tracks_into_ram": False, # Куда загружаем треки, если RAM = false, то грузим на жесткий диск (пока поддерживается только жесткий диск).
"maximum_display_of_tracks_in_queue": 10, # Максимальное кол-во треков, которое показываем в очереди. ВАЖНО: число должно быть меньше 25. Так как мы рисуем с помощью embed
}
Несмотря на комментарии на некоторых настройках хочется остановиться по подробнее:
- message_lifetime - каждое сообщение живет небольшое время жизни, после чего удаляется. Для расчета времени жизни используется среднее значение за которое человек может прочитать N символов. В случае если из сообщения невозможно получить кол-во символов, в качестве времени ожидания выставляется значение в message_lifetime.
- maximum_number_recent_requests_in_message - для включения недавно прослушанных треков используются кнопки под сообщением, кол-во этих кнопок ограничено, поэтому не стоит выставлять в данном поле большие значения.
- max_tracks_in_list - сейчас бот старается всегда держать у себя в "голове" N загруженных треков, таким образом если пользователь передал боту 10 треков, бот загрузит не один трек, а сразу N (Для пример N = 3). И после завершения первого трека, будет пытаться подгрузить четвертый трек, чтобы кол-во загруженных треков всегда было равно N. max_tracks_in_list и есть это число N.
- number_of_attempts_when_requesting_music_service - если во время обращения к Я.Музыка возникнет ошибка, бот будет пытаться повторить запрос еще number_of_attempts_when_requesting_music_service раз.
- delay_in_case_of_error_when_requesting_music_service - после возникновения ошибки при обращение к Я.Музыка, бот прежде чем отправить повторный запрос, будет ожидать заданное время.
- loading_tracks_into_ram - это поле нужно поддержать, на текущий момент загрузка в RAM не поддержана из-за ряда архитектурных сложностей :)
- maximum_display_of_tracks_in_queue - в данном случае подразумевается, что пользователь увидит следующие 10 треков с подробным описанием: что за трек, кто исполнитель и длительность трека. Кроме трека пользователю отобразится и общее количество треков в очереди.
Следом за public_key можно увидеть ключи для продакшена и дебага. Рассмотрим один из словарей, так как ключи в них повторяются.
dev_keys = {
"ignore_number_members_in_voice_chat": True,
"waiting_time_before_disconnection": 10,
"ignore_user_in_voice_channel": True,
"slash_supported": False
}
- ignore_number_members_in_voice_chat - в случае если значение равно True, бот не будет покидать голосовой канал, даже если останется один.
- waiting_time_before_disconnection - после завершения проигрывания музыки, бот ожидает определенное время после чего автоматически покидает голосовой канал, как раз данное поле и отвечает за длительность ожидания.
- ignore_user_in_voice_channel - соглашусь, что название не самое удачное и в каком-то смысле похоже на ignore_number_members_in_voice_chat, но функционал немного отличается. Если выставить данное поле в значение True, бот не будет проверять нахождение пользователя в голосовом канале, таким образом он будет выполнять команды на включение треков, даже если слушателя нет в голосовом канале. Важно отметить: сам бот должен находиться в голосовом канале, иначе он просто не будет знать где именно проигрывать музыку.
- slash_supported - включены/выключены команды через слеш.
Ко всем плюсам, бот так же содержит несколько ошибок и недоработок, на исправление которых у меня не хватает времени.
В качестве ошибок приведу самые критичные, которые могут наблюдаться при работе бота:
- Бот в случайный момент времени может покинуть голосовой канал. По какой-то причине вызывается метод on_voice_state_update и передается новое состояние бота: бот покинул канал. На деле бот находится в голосовом канале. На текущий момент есть предположение, что это либо шалит метод on_ready, либо баги discord.py.
- Если во время работы бота выгнать бота из голосового канала, затем сразу ввести команду по проигрыванию музыки, бот будет писать, что находится в голосовом канале, на деле его в голосовом канале нет. На текущий момент ошибка исправляется автоматически спустя минуту ожидания.
К недоработкам могу отнести следующие вещи:
- Логирование. Бот логирует все данные в один файл из-за чего сложно смотреть логи по конкретному серверу.
- Наличие команд через суффикс. В идеальном мире бот не должен содержать команды через "!" в проде, а поддерживать только слеш. Одна из причин по которой сейчас есть команды через суффикс: кнопки в недавно прослушанном. Дело в том, что кнопки привязываются к именам команд и незаметно их вызывают при нажатии.
- Не асинхронная БД. БД выполняет запросы в однопоточном режиме, при увеличении количества пользователей это может привести к большим проблемам. С другой стороны, честно скажу - это мой первый большой проект с полноценным использованием библиотеки asyncio, поэтому вероятность, что развалится что-то асинхронное на много больше :)
- Бот не удаляет загруженную музыку. На текущий момент при прослушивание треков, бот загружает все аудифайлы на жесткий диск. Как следствие по прошествию времени на диске может накопиться большой набор данных