# DSPlayer
## Описание
`dsplayer` — это библиотека для создания Discord-ботов, которая позволяет подключаться к голосовым каналам, воспроизводить музыкальные треки и управлять очередями воспроизведения. Библиотека также поддерживает плагины, что позволяет расширять количество доступных платформ для воспроизведения.
**Совместимость:** `dsplayer` работает с библиотеками `disnake`, `discord.py` и `nextcord`.
## Установка
Установите библиотеку с помощью `pip` из PyPI:
```bash
pip install dsplayer
```
Или установите последнюю версию с GitHub:
```bash
pip install git+https://github.com/FlacSy/dsplayer
```
> **Примечание:** Установка через PyPI гарантирует стабильную версию, тогда как установка с GitHub предоставляет последние изменения и улучшения.
---
---
## Список изменений
Ниже представлен список изменений для библиотеки, начиная с версии **2.0.0**.
- **2.0.0** | Глобальное обновление:
- Обновлены компоненты: плеер, очередь, система плагинов.
- Оптимизирован код для лучшей производительности.
- **2.0.1** | Исправления и улучшения:
- Исправлены ошибки при инициализации некоторых классов.
- Удалены ненужные части кода.
- Добавлен новый метод в очередь: `get_current_track`.
- **2.1.0** | Новая система плагинов:
- Добавлена поддержка двух типов плагинов: `addon` и `extractor`.
- Частичная обратная совместимость с плагинами старых версий. Для работы старых плагинов необходимо реализовать метод `get_plugin_type`.
- **2.2.0** | Исправления и улучшения:
- Удалены лишние фрагменты кода.
- Обновлен стандарт возвращаемых данных плагинов. В этой версии плагины типа `extractor` совместимы только с версиями выше **1.4.0**!
## Плагины
В `dsplayer` предусмотрены следующие плагины:
- **[Query](dsplayer/plugins/query_plugin.py)** - Плагин для поиска музыки по названию (включен по умолчанию).
- **[Spotify](https://github.com/FlacSy/dsplayer-spotify)** - Плагин для поиска треков, плейлистов и авторов из Spotify.
```bash
pip install dsplayer-spotify
```
- **[YouTube](https://github.com/FlacSy/dsplayer-youtube)** - Плагин для поиска треков из YouTube, YouTube Music и YouTube Shorts.
```bash
pip install dsplayer-youtube
```
- **[SoundCloud](https://github.com/FlacSy/dsplayer-soundcloud)** - Плагин для поиска треков, плейлистов и авторов из SoundCloud.
```bash
pip install dsplayer-soundcloud
```
- **[Apple Music](https://github.com/FlacSy/dsplayer-applemusic)** - Плагин для поиска треков из Apple Music.
```bash
pip install dsplayer-applemusic
```
## Поисковые движки
В `dsplayer` предусмотрены следующие поисковые движки:
- **[YouTube Music](dsplayer/engines_system/ytmusic.py)** - Более быстрая, но менее точная поисковая система.
- **[SoundCloud](dsplayer/engines_system/soundcloud.py)** - Более точный поиск, но время отклика 2-3+ секунды.
- **[Bandcamp](dsplayer/engines_system/bandcamp.py)** - Высокая точность с хорошей производительностью.
> ⚠️ **Важно:** SoundCloud работает на Selenium! Для его использования необходимо установить Chrome и соответствующий Chrome Driver.
## Примеры использования
### Использование `Player` и `Queue`
#### Пример 1: Подключение и воспроизведение трека
```python
import disnake
from disnake.ext import commands
from dsplayer import Player, PluginLoader, YTMusicSearchEngine
intents = disnake.Intents.all()
bot = commands.Bot(command_prefix='!', intents=intents)
players = {}
@bot.command()
async def play(ctx, url):
"""Добавить трек в очередь и воспроизвести его."""
if ctx.guild.id in players:
player = players[ctx.guild.id]
else:
if ctx.author.voice:
voice_channel = ctx.author.voice.channel
player = Player(
voice_channel=voice_channel,
bot=bot,
plugin_loader=PluginLoader(),
engine=YTMusicSearchEngine,
debug=True
)
players[ctx.guild.id] = player
await player.connect()
else:
await ctx.send('Вы не подключены к голосовому каналу.')
return
await player.play(url)
await ctx.send(f'Трек добавлен в очередь: {url}')
bot.run('YOUR_BOT_TOKEN')
```
#### Пример 2: Управление очередью треков
```python
@bot.command()
async def skip(ctx):
"""Пропустить текущий трек."""
if ctx.guild.id in players:
player = players[ctx.guild.id]
await player.skip()
await ctx.send('Играет следующий трек.')
else:
await ctx.send("Нет активного плеера для этого сервера.")
@bot.command()
async def previous(ctx):
"""Вернуться к предыдущему треку."""
if ctx.guild.id in players:
player = players[ctx.guild.id]
await player.previous()
await ctx.send('Играет предыдущий трек.')
else:
await ctx.send("Нет активного плеера для этого сервера.")
@bot.command()
async def queue(ctx):
"""Показать текущую очередь треков."""
if ctx.guild.id in players:
player = players[ctx.guild.id]
queue = player.queue.get_queue()
if queue:
queue_list = "\n".join([f"{idx + 1}. {track['url']}" for idx, track in enumerate(queue)])
await ctx.send(f"Очередь:\n{queue_list}")
else:
await ctx.send("Очередь пуста.")
else:
await ctx.send("Нет активного плеера для этого сервера.")
bot.run('YOUR_BOT_TOKEN')
```
#### Пример 3: Обработка событий
```python
from dsplayer import event
@event("on_play_track")
async def on_play_track(event_data: dict):
"""Отправляет сообщение, когда начинается воспроизведение трека."""
track = event_data['track']
channel_id = event_data['text_id']
channel = bot.get_channel(channel_id)
await channel.send(f"Начинается воспроизведение трека: {track['title']}")
```
## `PluginLoader`
### 1. Загрузка плагинов из директории
```python
from dsplayer import PluginLoader
plugins_list = ["custom_plugins.plugins"]
loader = PluginLoader(plugins_list)
```
### 2. Загрузка плагинов используя класс
```python
from dsplayer import PluginLoader, PluginInterface
loader = PluginLoader()
loader.load_plugins_from_classes(plugins_list)
class MyCustomPlugin1(PluginInterface):
# Реализация плагина
...
class MyCustomPlugin2(PluginInterface):
# Реализация плагина
...
plugins_list = [MyCustomPlugin1, MyCustomPlugin2]
```
> **Пример бота можно найти в [examples/example_bot.py](examples/example_bot.py)**
## Обработка исключений
`dsplayer` предоставляет систему обработки исключений, позволяющую гибко реагировать на ошибки. Для этого рекомендуется использовать исключения из модуля `dsplayer.utils.exceptions.lib_exceptions`.
### Основные исключения
- **VoiceChaneNotConnected**
Возникает, если бот пытается воспроизвести трек, не подключившись к голосовому каналу.
- **TrackNotFound**
Возникает, если указанный трек не найден.
- **TrackError**
Общая ошибка, связанная с воспроизведением трека.
### Пример обработки исключений
```python
from dsplayer.utils.exceptions.lib_exceptions import VoiceChaneNotConnected, TrackNotFound, TrackError
try:
# Ваш код
except VoiceChaneNotConnected as e:
print(f"Ошибка подключения: {e}")
except TrackNotFound as e:
print(f"Трек не найден: {e}")
except TrackError as e:
print(f"Ошибка воспроизведения трека: {e}")
```
### Список доступных исключений
- **VoiceChaneError**
- **VoiceChaneNotConnected**: Бот не подключен к голосовому каналу.
- **VoiceChaneNotFound**: Указанный голосовой канал не найден.
- **VoiceChaneNotPlaying**: Бот не воспроизводит трек.
- **ConnectionError**
- Проблемы с подключением к голосовому каналу.
- **TrackError**
- **TrackNotFound**: Трек не найден.
- **TrackError**: Ошибка воспроизведения трека.
Raw data
{
"_id": null,
"home_page": "https://github.com/FlacSy/dsplayer",
"name": "dsplayer",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10.0",
"maintainer_email": null,
"keywords": null,
"author": "FlacSy",
"author_email": "flacsy.x@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/3d/17/18234a29a607f76e35809cf0cb91932429d0dc2a3480cad3fbabc4fe74b9/dsplayer-2.2.0.tar.gz",
"platform": null,
"description": "# DSPlayer\r\n\r\n## \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\r\n\r\n`dsplayer` \u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Discord-\u0431\u043e\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043a \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u044b\u043c \u043a\u0430\u043d\u0430\u043b\u0430\u043c, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u043a\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u044f\u043c\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043b\u0430\u0433\u0438\u043d\u044b, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.\r\n\r\n**\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c:** `dsplayer` \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 `disnake`, `discord.py` \u0438 `nextcord`.\r\n\r\n## \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\r\n\r\n\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e `pip` \u0438\u0437 PyPI:\r\n\r\n```bash\r\npip install dsplayer\r\n```\r\n\r\n\u0418\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0441 GitHub:\r\n\r\n```bash\r\npip install git+https://github.com/FlacSy/dsplayer\r\n```\r\n\r\n> **\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:** \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0447\u0435\u0440\u0435\u0437 PyPI \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e, \u0442\u043e\u0433\u0434\u0430 \u043a\u0430\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441 GitHub \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f.\r\n\r\n---\r\n\r\n---\r\n\r\n## \u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\r\n\r\n\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 **2.0.0**.\r\n\r\n- **2.0.0** | \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435:\r\n - \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b: \u043f\u043b\u0435\u0435\u0440, \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.\r\n - \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u043e\u0434 \u0434\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.\r\n\r\n- **2.0.1** | \u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f:\r\n - \u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432.\r\n - \u0423\u0434\u0430\u043b\u0435\u043d\u044b \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430.\r\n - \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c: `get_current_track`.\r\n\r\n- **2.1.0** | \u041d\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432:\r\n - \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0432\u0443\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432: `addon` \u0438 `extractor`.\r\n - \u0427\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438 \u0441\u0442\u0430\u0440\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0442\u0430\u0440\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 `get_plugin_type`.\r\n\r\n- **2.2.0** | \u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f:\r\n - \u0423\u0434\u0430\u043b\u0435\u043d\u044b \u043b\u0438\u0448\u043d\u0438\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0434\u0430.\r\n - \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u0412 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0442\u0438\u043f\u0430 `extractor` \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0432\u044b\u0448\u0435 **1.4.0**!\r\n\r\n## \u041f\u043b\u0430\u0433\u0438\u043d\u044b\r\n\r\n\u0412 `dsplayer` \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b:\r\n\r\n- **[Query](dsplayer/plugins/query_plugin.py)** - \u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043c\u0443\u0437\u044b\u043a\u0438 \u043f\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044e (\u0432\u043a\u043b\u044e\u0447\u0435\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e).\r\n- **[Spotify](https://github.com/FlacSy/dsplayer-spotify)** - \u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0442\u0440\u0435\u043a\u043e\u0432, \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442\u043e\u0432 \u0438 \u0430\u0432\u0442\u043e\u0440\u043e\u0432 \u0438\u0437 Spotify.\r\n ```bash\r\n pip install dsplayer-spotify\r\n ```\r\n- **[YouTube](https://github.com/FlacSy/dsplayer-youtube)** - \u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0442\u0440\u0435\u043a\u043e\u0432 \u0438\u0437 YouTube, YouTube Music \u0438 YouTube Shorts.\r\n ```bash\r\n pip install dsplayer-youtube\r\n ```\r\n- **[SoundCloud](https://github.com/FlacSy/dsplayer-soundcloud)** - \u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0442\u0440\u0435\u043a\u043e\u0432, \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442\u043e\u0432 \u0438 \u0430\u0432\u0442\u043e\u0440\u043e\u0432 \u0438\u0437 SoundCloud.\r\n ```bash\r\n pip install dsplayer-soundcloud\r\n ```\r\n- **[Apple Music](https://github.com/FlacSy/dsplayer-applemusic)** - \u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0442\u0440\u0435\u043a\u043e\u0432 \u0438\u0437 Apple Music.\r\n ```bash\r\n pip install dsplayer-applemusic\r\n ```\r\n\r\n## \u041f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0435 \u0434\u0432\u0438\u0436\u043a\u0438\r\n\r\n\u0412 `dsplayer` \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0435 \u0434\u0432\u0438\u0436\u043a\u0438:\r\n\r\n- **[YouTube Music](dsplayer/engines_system/ytmusic.py)** - \u0411\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u0430\u044f, \u043d\u043e \u043c\u0435\u043d\u0435\u0435 \u0442\u043e\u0447\u043d\u0430\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430.\r\n- **[SoundCloud](dsplayer/engines_system/soundcloud.py)** - \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a, \u043d\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u0430 2-3+ \u0441\u0435\u043a\u0443\u043d\u0434\u044b.\r\n- **[Bandcamp](dsplayer/engines_system/bandcamp.py)** - \u0412\u044b\u0441\u043e\u043a\u0430\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0441 \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.\r\n\r\n> \u26a0\ufe0f **\u0412\u0430\u0436\u043d\u043e:** SoundCloud \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 Selenium! \u0414\u043b\u044f \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Chrome \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 Chrome Driver.\r\n\r\n## \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f\r\n\r\n### \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 `Player` \u0438 `Queue`\r\n\r\n#### \u041f\u0440\u0438\u043c\u0435\u0440 1: \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0430\r\n\r\n```python\r\nimport disnake\r\nfrom disnake.ext import commands\r\nfrom dsplayer import Player, PluginLoader, YTMusicSearchEngine\r\n\r\nintents = disnake.Intents.all()\r\nbot = commands.Bot(command_prefix='!', intents=intents)\r\nplayers = {}\r\n\r\n@bot.command()\r\nasync def play(ctx, url):\r\n \"\"\"\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0440\u0435\u043a \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0435\u0433\u043e.\"\"\"\r\n if ctx.guild.id in players:\r\n player = players[ctx.guild.id]\r\n else:\r\n if ctx.author.voice:\r\n voice_channel = ctx.author.voice.channel\r\n player = Player(\r\n voice_channel=voice_channel,\r\n bot=bot,\r\n plugin_loader=PluginLoader(),\r\n engine=YTMusicSearchEngine,\r\n debug=True\r\n )\r\n players[ctx.guild.id] = player\r\n await player.connect()\r\n else:\r\n await ctx.send('\u0412\u044b \u043d\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043a \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443.')\r\n return\r\n\r\n await player.play(url)\r\n await ctx.send(f'\u0422\u0440\u0435\u043a \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c: {url}')\r\n\r\nbot.run('YOUR_BOT_TOKEN')\r\n```\r\n\r\n#### \u041f\u0440\u0438\u043c\u0435\u0440 2: \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u044c\u044e \u0442\u0440\u0435\u043a\u043e\u0432\r\n\r\n```python\r\n@bot.command()\r\nasync def skip(ctx):\r\n \"\"\"\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u0440\u0435\u043a.\"\"\"\r\n if ctx.guild.id in players:\r\n player = players[ctx.guild.id]\r\n await player.skip()\r\n await ctx.send('\u0418\u0433\u0440\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0440\u0435\u043a.')\r\n else:\r\n await ctx.send(\"\u041d\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043b\u0435\u0435\u0440\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\")\r\n\r\n@bot.command()\r\nasync def previous(ctx):\r\n \"\"\"\u0412\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0442\u0440\u0435\u043a\u0443.\"\"\"\r\n if ctx.guild.id in players:\r\n player = players[ctx.guild.id]\r\n await player.previous()\r\n await ctx.send('\u0418\u0433\u0440\u0430\u0435\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0442\u0440\u0435\u043a.')\r\n else:\r\n await ctx.send(\"\u041d\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043b\u0435\u0435\u0440\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\")\r\n\r\n@bot.command()\r\nasync def queue(ctx):\r\n \"\"\"\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0442\u0440\u0435\u043a\u043e\u0432.\"\"\"\r\n if ctx.guild.id in players:\r\n player = players[ctx.guild.id]\r\n queue = player.queue.get_queue()\r\n if queue:\r\n queue_list = \"\\n\".join([f\"{idx + 1}. {track['url']}\" for idx, track in enumerate(queue)])\r\n await ctx.send(f\"\u041e\u0447\u0435\u0440\u0435\u0434\u044c:\\n{queue_list}\")\r\n else:\r\n await ctx.send(\"\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u043f\u0443\u0441\u0442\u0430.\")\r\n else:\r\n await ctx.send(\"\u041d\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043b\u0435\u0435\u0440\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\")\r\n\r\nbot.run('YOUR_BOT_TOKEN')\r\n```\r\n\r\n#### \u041f\u0440\u0438\u043c\u0435\u0440 3: \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439\r\n\r\n```python\r\nfrom dsplayer import event\r\n\r\n@event(\"on_play_track\")\r\nasync def on_play_track(event_data: dict):\r\n \"\"\"\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0430.\"\"\"\r\n track = event_data['track']\r\n channel_id = event_data['text_id']\r\n channel = bot.get_channel(channel_id)\r\n await channel.send(f\"\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0430: {track['title']}\")\r\n```\r\n\r\n## `PluginLoader`\r\n\r\n### 1. \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438\r\n\r\n```python\r\nfrom dsplayer import PluginLoader\r\n\r\nplugins_list = [\"custom_plugins.plugins\"]\r\nloader = PluginLoader(plugins_list)\r\n```\r\n\r\n### 2. \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043b\u0430\u0441\u0441 \r\n\r\n```python\r\nfrom dsplayer import PluginLoader, PluginInterface\r\n\r\nloader = PluginLoader()\r\nloader.load_plugins_from_classes(plugins_list)\r\n\r\nclass MyCustomPlugin1(PluginInterface):\r\n # \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u0430\r\n ...\r\n\r\nclass MyCustomPlugin2(PluginInterface):\r\n # \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u0430\r\n ...\r\n\r\nplugins_list = [MyCustomPlugin1, MyCustomPlugin2]\r\n```\r\n\r\n> **\u041f\u0440\u0438\u043c\u0435\u0440 \u0431\u043e\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 [examples/example_bot.py](examples/example_bot.py)**\r\n\r\n## \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439\r\n\r\n`dsplayer` \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0443\u044e \u0433\u0438\u0431\u043a\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043c\u043e\u0434\u0443\u043b\u044f `dsplayer.utils.exceptions.lib_exceptions`.\r\n\r\n### \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\r\n\r\n- **VoiceChaneNotConnected** \r\n \u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0431\u043e\u0442 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0442\u0440\u0435\u043a, \u043d\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0432\u0448\u0438\u0441\u044c \u043a \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443.\r\n\r\n- **TrackNotFound** \r\n \u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u043a \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.\r\n\r\n- **TrackError** \r\n \u041e\u0431\u0449\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0430\u044f \u0441 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u0442\u0440\u0435\u043a\u0430.\r\n\r\n### \u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439\r\n\r\n```python\r\nfrom dsplayer.utils.exceptions.lib_exceptions import VoiceChaneNotConnected, TrackNotFound, TrackError\r\n\r\ntry:\r\n # \u0412\u0430\u0448 \u043a\u043e\u0434\r\nexcept VoiceChaneNotConnected as e:\r\n print(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f: {e}\")\r\nexcept TrackNotFound as e:\r\n print(f\"\u0422\u0440\u0435\u043a \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d: {e}\")\r\nexcept TrackError as e:\r\n print(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0440\u0435\u043a\u0430: {e}\")\r\n```\r\n\r\n### \u0421\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439\r\n\r\n- **VoiceChaneError** \r\n - **VoiceChaneNotConnected**: \u0411\u043e\u0442 \u043d\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443.\r\n - **VoiceChaneNotFound**: \u0423\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u0439 \u043a\u0430\u043d\u0430\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.\r\n - **VoiceChaneNotPlaying**: \u0411\u043e\u0442 \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u0442\u0440\u0435\u043a.\r\n\r\n- **ConnectionError** \r\n - \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043a \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443.\r\n\r\n- **TrackError** \r\n - **TrackNotFound**: \u0422\u0440\u0435\u043a \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.\r\n - **TrackError**: \u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0440\u0435\u043a\u0430.\r\n",
"bugtrack_url": null,
"license": null,
"summary": "Music player for Discord",
"version": "2.2.0",
"project_urls": {
"Homepage": "https://github.com/FlacSy/dsplayer"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ccec05b96127957d9c26427c00e547725a811253208ff0ef0a0f9b69c898026f",
"md5": "839b4383aad7fc59a9a7bcf6157fad3f",
"sha256": "df70cf6bf05c4b579e244bb56115439f73ba30f9642d074feee8a68ea01c6d09"
},
"downloads": -1,
"filename": "dsplayer-2.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "839b4383aad7fc59a9a7bcf6157fad3f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10.0",
"size": 55996,
"upload_time": "2024-10-15T16:49:55",
"upload_time_iso_8601": "2024-10-15T16:49:55.719268Z",
"url": "https://files.pythonhosted.org/packages/cc/ec/05b96127957d9c26427c00e547725a811253208ff0ef0a0f9b69c898026f/dsplayer-2.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3d1718234a29a607f76e35809cf0cb91932429d0dc2a3480cad3fbabc4fe74b9",
"md5": "c8141a43e256b9ffd0e6c93b40452341",
"sha256": "1239a4f3258e6b81cca0d8deab04f371fc7b9564f020e592cc0f23aa7e611933"
},
"downloads": -1,
"filename": "dsplayer-2.2.0.tar.gz",
"has_sig": false,
"md5_digest": "c8141a43e256b9ffd0e6c93b40452341",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10.0",
"size": 46662,
"upload_time": "2024-10-15T16:49:57",
"upload_time_iso_8601": "2024-10-15T16:49:57.386062Z",
"url": "https://files.pythonhosted.org/packages/3d/17/18234a29a607f76e35809cf0cb91932429d0dc2a3480cad3fbabc4fe74b9/dsplayer-2.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-15 16:49:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "FlacSy",
"github_project": "dsplayer",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "requests",
"specs": []
},
{
"name": "bs4",
"specs": []
},
{
"name": "colorama",
"specs": []
},
{
"name": "selenium",
"specs": []
},
{
"name": "webdriver_manager",
"specs": []
},
{
"name": "yt-dlp",
"specs": []
},
{
"name": "PyNaCl",
"specs": []
}
],
"lcname": "dsplayer"
}