--- title: Голосовые функции weight: 3 --- **Цель:** реализовать голосовое взаимодействие с изоляцией ресурсов по серверам (гильдиям) и корректным управлением аудиосессиями. ## 1. Изоляция ресурсов Голосовые функции бота **обязательно** изолируются на уровне отдельного сервера (гильдии): - **Архитектурный шаблон:** контроллер хранит соответствие `Map`. - **Поведение:** - **Подключение (Join):** создать `Player` для сервера A, если он ещё не существует. - **Отключение (Leave):** удалить `Player` и освободить соединение. - **Изоляция:** команды на сервере B никак не влияют на сервер A. ## 2. Маршрутизация команд Голосовые функции опираются на набор команд, работу которых координирует контроллер: | Команда | Действие | Логика контроллера | | :--- | :--- | :--- | | `/join` | Подключиться к голосовому каналу | `createPlayer(guildId, channelId)` | | `/play` | Добавить трек в очередь | `getPlayer(guildId).enqueue(track)` | | `/stop` | Отключиться от канала | `destroyPlayer(guildId)` | ## 3. Управление состоянием Аудиосессии по своей природе эфемерны: - **Временное состояние:** активный аудиопоток (сбрасывается при отключении). - **Долговременное состояние:** очередь воспроизведения или плейлист (хранится в контроллере до перезапуска бота). > [!TIP] > **Надёжность:** разделяйте логику очереди воспроизведения и логику голосового соединения. Тогда бот сможет переподключиться без потери пользовательского плейлиста. ## 4. Пример реализации ```typescript // lib/MusicController.ts class MusicController { private players = new Map(); getPlayer(guildId: string): AudioPlayer { if (!this.players.has(guildId)) { this.players.set(guildId, new AudioPlayer()); } return this.players.get(guildId); } destroyPlayer(guildId: string) { this.players.get(guildId)?.disconnect(); this.players.delete(guildId); } } ``` --- **См. также:** - [Руководство Discord.js по голосовым функциям](https://discordjs.guide/voice/)