Skip to content

VasiliyNichnikov/yandex-music-bot

Repository files navigation

Yandex Music Bot

Yandex Music Bot - это бот, позволяющий проигрывать музыку в Discord, используя возможности Yandex Music.

Static Badge GitHub top language GitHub GitHub Repo stars GitHub issues

Видео документация

Так же по боту записано отдельное видео. В нем представлена такая же информация что и в Readme файле, но с комментариями. Если вам удобней потреблять информацию в формате видео - прошу кликать на меня.

Функционал бота

На сегодняшний день бот поддерживает следующий функционал:

  1. Плеер. Функционал плеера:
    1. Переключаться на следующий трек.
    2. Переключаться на предыдущий трек.
    3. Ставить текущий трек на паузу.
    4. Ставить текущий трек на повтор.
    5. Отображать очередь следующих треков.
    6. Сбрасывать всю очередь.

Player.png

  1. Команда /play. Команда /play является основной командой, чтобы начать прослушивание музыки или добавить треки в существующую очередь. В качестве параметра команда принимает ссылку на трек/альбом/исполнителя/плейлист/подкаст/книгу или поисковой запрос.

CommandPlay.png

  1. Недавно прослушанные треки. Каждый запрос бот сохраняет в базу данных и по завершению прослушивания отображает пять последних запросов.

RecentlyListened.png

  1. История. После завершения трек попадает в созданную ветку. Ветка хранит все ранее прослушанные треки.

History.png

Использование бота

Прежде чем решиться на развертывание бота у себя на сервере, предлагаю вам ознакомится с ним через CactusBot.

CactusBot - это уже настроенная версия бота, которой вы можете воспользоваться, чтобы проверить функциональность и возможности бота.

Добавление бота на сервер

Для добавления бота к себе в логово, выполните следующие шаги:

  1. Перейдите по ссылке.
  2. В открывшемся окне выберите сервер, в который нужно добавить бота и выдайте боту права администратора.
  3. После появления на сервере, бот создает текстовый канал с именим "музыка", а так же ветку "история". Важно: на текущий момент бот принимает основные команды только в своем созданном текстовом канале и менять канал нельзя, но можно переименовывать (ветку тоже можно переименовывать).
  4. Если вы перейдете в канал "музыка", то сможете заметить что бот написал свое первое сообщение. Теперь вы можете воспользоваться ботом.
  5. Для того чтобы включить музыку, перейдите в любой голосовой канал на сервере и в текстовом канале "музыка", введите интересующий запрос с использованием команды play. Например чтобы включить альбом доры Miss, нужно ввести запрос: /play https://music.yandex.ru/album/22647617
  6. Если вы слышите музыку, значит бот корректно настроен и работает. Приятного прослушивания!

Упаковка проекта в Docker

Note

Прежде чем развернуть бота, убедитесь что у вас установлен docker и git.

  1. Клонируем репозиторий:

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
  1. Переходим в папку проекта:
cd yandex-music-bot
  1. Окружение. Сначала настроим .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

  1. Теперь по аналогии с .env дублируем файл .env.database.example и называем его env.database. Переходим к заполнению:
MYSQL_ROOT_PASSWORD=вставляем пароль к базе данных из файла .env, поле DATABASE_PASSWORD
MYSQL_DATABASE=cactusdiscordbot - если на предыдущем пункте, не меняли значение DATABASE_NAME - оставляем без изменений,
в противном случае изменяем.
  1. Собираем проект:
docker compose build
  1. Запускаем проект:
docker compose up -d
  1. Убедимся, что бот запущен корректно. Находим в корне проекта, файл 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.
  1. Поздравляю, бот запущен. Последний пункт - добавить бот на сервер и наслаждаться музыкой!

Для разработчиков

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

Описание конфигураций

Все основные конфигурации представлены в файле 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
}

Несмотря на комментарии на некоторых настройках хочется остановиться по подробнее:

  1. message_lifetime - каждое сообщение живет небольшое время жизни, после чего удаляется. Для расчета времени жизни используется среднее значение за которое человек может прочитать N символов. В случае если из сообщения невозможно получить кол-во символов, в качестве времени ожидания выставляется значение в message_lifetime.
  2. maximum_number_recent_requests_in_message - для включения недавно прослушанных треков используются кнопки под сообщением, кол-во этих кнопок ограничено, поэтому не стоит выставлять в данном поле большие значения.
  3. max_tracks_in_list - сейчас бот старается всегда держать у себя в "голове" N загруженных треков, таким образом если пользователь передал боту 10 треков, бот загрузит не один трек, а сразу N (Для пример N = 3). И после завершения первого трека, будет пытаться подгрузить четвертый трек, чтобы кол-во загруженных треков всегда было равно N. max_tracks_in_list и есть это число N.
  4. number_of_attempts_when_requesting_music_service - если во время обращения к Я.Музыка возникнет ошибка, бот будет пытаться повторить запрос еще number_of_attempts_when_requesting_music_service раз.
  5. delay_in_case_of_error_when_requesting_music_service - после возникновения ошибки при обращение к Я.Музыка, бот прежде чем отправить повторный запрос, будет ожидать заданное время.
  6. loading_tracks_into_ram - это поле нужно поддержать, на текущий момент загрузка в RAM не поддержана из-за ряда архитектурных сложностей :)
  7. 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
}
  1. ignore_number_members_in_voice_chat - в случае если значение равно True, бот не будет покидать голосовой канал, даже если останется один.
  2. waiting_time_before_disconnection - после завершения проигрывания музыки, бот ожидает определенное время после чего автоматически покидает голосовой канал, как раз данное поле и отвечает за длительность ожидания.
  3. ignore_user_in_voice_channel - соглашусь, что название не самое удачное и в каком-то смысле похоже на ignore_number_members_in_voice_chat, но функционал немного отличается. Если выставить данное поле в значение True, бот не будет проверять нахождение пользователя в голосовом канале, таким образом он будет выполнять команды на включение треков, даже если слушателя нет в голосовом канале. Важно отметить: сам бот должен находиться в голосовом канале, иначе он просто не будет знать где именно проигрывать музыку.
  4. slash_supported - включены/выключены команды через слеш.

Ошибки и недоработки

Ко всем плюсам, бот так же содержит несколько ошибок и недоработок, на исправление которых у меня не хватает времени.

Ошибки

В качестве ошибок приведу самые критичные, которые могут наблюдаться при работе бота:

  1. Бот в случайный момент времени может покинуть голосовой канал. По какой-то причине вызывается метод on_voice_state_update и передается новое состояние бота: бот покинул канал. На деле бот находится в голосовом канале. На текущий момент есть предположение, что это либо шалит метод on_ready, либо баги discord.py.
  2. Если во время работы бота выгнать бота из голосового канала, затем сразу ввести команду по проигрыванию музыки, бот будет писать, что находится в голосовом канале, на деле его в голосовом канале нет. На текущий момент ошибка исправляется автоматически спустя минуту ожидания.

Недоработки

К недоработкам могу отнести следующие вещи:

  1. Логирование. Бот логирует все данные в один файл из-за чего сложно смотреть логи по конкретному серверу.
  2. Наличие команд через суффикс. В идеальном мире бот не должен содержать команды через "!" в проде, а поддерживать только слеш. Одна из причин по которой сейчас есть команды через суффикс: кнопки в недавно прослушанном. Дело в том, что кнопки привязываются к именам команд и незаметно их вызывают при нажатии.
  3. Не асинхронная БД. БД выполняет запросы в однопоточном режиме, при увеличении количества пользователей это может привести к большим проблемам. С другой стороны, честно скажу - это мой первый большой проект с полноценным использованием библиотеки asyncio, поэтому вероятность, что развалится что-то асинхронное на много больше :)
  4. Бот не удаляет загруженную музыку. На текущий момент при прослушивание треков, бот загружает все аудифайлы на жесткий диск. Как следствие по прошествию времени на диске может накопиться большой набор данных

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages