@persian-caesar/discord-player
A lightweight, type-safe music player for Discord bots, built with TypeScript and integrated with discord.js
. This package provides a robust MusicPlayer
class for streaming audio from platforms like YouTube, SoundCloud, Spotify, and Deezer, with optional Lavalink support via Erela.js for enhanced performance and playlist handling. Without Lavalink, it falls back to direct streaming using libraries like play-dl
, soundcloud-downloader
, and yt-dlp-exec
.
Table of Contents
- @persian-caesar/discord-player
- Table of Contents
- Introduction
- Features
- Installation
- Dependencies
- Usage Examples
- API Reference
- MusicPlayer Class
- MusicPlayerEvent Enum
- Method Usage and Examples
isPlaylist(url: string): Promise<boolean>
searchPlaylists(query: string, platform?: SearchPlatform, limit?: number): Promise<PlaylistMetadata[]>
search(query: string, platform?: SearchPlatform, limit?: number): Promise<TrackMetadata[]>
play(input: string | TrackMetadata | TrackMetadata[], radio?: boolean): Promise<void>
pause(): void
resume(): void
setVolume(percent: number): number
skip(): void
previous(): Promise<void>
shuffle(): void
undoShuffle(): void
toggleLoopQueue(): boolean
toggleLoopTrack(): boolean
startRadio(urls: string[]): Promise<void>
stop(noLeave?: boolean): void
disconnect(): void
join(): VoiceConnection
getQueue(): TrackMetadata[]
getVolume(): number
isPlaying(): boolean
isPaused(): boolean
isShuffiled(): boolean
isConnected(guildId?: string): boolean
searchLyrics(title: string, artist?: string): Promise<string | null>
- Support and Contributions
- License
- Contact
Introduction
@persian-caesar/discord-player
is designed to simplify audio playback in Discord bots. It leverages the @discordjs/voice
library for voice channel interactions and supports streaming from multiple platforms. Lavalink integration (via Erela.js) is optional for better scalability, playlist support, and performance. Without Lavalink, the player uses direct streaming for flexibility in smaller setups. The package is fully typed, making it ideal for TypeScript projects, and includes JSDoc annotations for JavaScript users. The MusicPlayer
class handles all aspects of music playback, including multi-platform search, queue management, history tracking, and event-driven notifications.
Developed by Sobhan-SRZA for Persian Caesar, this package is licensed under MIT and actively maintained.
Features
- Optional Lavalink Support: Use Erela.js for advanced features like playlist loading and better audio handling, or fallback to direct streaming without it.
- Multi-Platform Search and Streaming: Supports YouTube, SoundCloud, Spotify, and Deezer. Search prioritizes platforms in order (configurable), returns a list of results.
- Direct Stream Handling: Streams non-platform URLs (e.g., radio stations) directly without searching.
- Playlist Support: Detect, search, and load playlists from all supported platforms, automatically enqueues tracks.
- Queue Management: Add tracks (single or multiple), shuffle, or revert to the original order.
- Looping Options: Toggle looping for a single track or the entire queue.
- Volume Control: Adjust playback volume (0–200%).
- Lyrics Retrieval: Fetch song lyrics from Google search results using
html-to-text
. - Radio Mode: Play a shuffled list of URLs in a continuous loop.
- Event System: Strongly-typed events for playback status, queue changes, errors, and more.
- Auto-Disconnect: Configurable options to leave voice channels when the queue is empty or after idle time.
- Type Safety: Full TypeScript support with defined interfaces and enums in
types.ts
. - Lightweight: Minimal dependencies with no external framework requirements beyond
discord.js
.
Installation
Install the package:
npm install @persian-caesar/discord-player
Ensure you have Node.js version 16 or higher, as specified in package.json
.
Dependencies
The following dependencies are required for the package to function correctly:
Package | Version | Purpose |
---|---|---|
@discordjs/voice |
^0.18.0 | Handles voice channel connections and audio playback in Discord. |
@discordjs/opus |
^0.10.0 | Provides Opus audio encoding/decoding for high-quality audio streaming. |
erela.js |
^2.4.0 | Optional: Access to Lavalink for enhanced audio and playlist support. |
play-dl |
^1.9.7 | Streams audio from Spotify, YouTube, and Deezer with search capabilities (fallback mode). |
soundcloud-downloader |
^1.0.0 | Downloads and streams audio from SoundCloud URLs (fallback mode). |
html-to-text |
^9.0.5 | Converts HTML (from Google lyrics searches) to plain text. |
libsodium-wrappers |
^0.7.15 | Required for secure audio encryption in @discordjs/voice . |
ffmpeg-static |
(peer) | Provides FFmpeg for audio processing and stream conversion. |
Why these dependencies?
@discordjs/voice
and@discordjs/opus
are core to Discord voice functionality, enabling the bot to join channels and stream audio.erela.js
enables optional Lavalink integration for better scalability.play-dl
andsoundcloud-downloader
provide fallback streaming without Lavalink.html-to-text
is used for scraping and cleaning lyrics from Google search results.libsodium-wrappers
andffmpeg-static
are required for secure and efficient audio processing.
Usage Examples
Below are examples demonstrating how to integrate @persian-caesar/discord-player
with discord.js
in both TypeScript and JavaScript. These examples assume you have a Discord bot set up with discord.js
.
TypeScript Example with Lavalink
This example uses Lavalink for playlist support and better performance.
import { Client, GatewayIntentBits, TextChannel, VoiceChannel } from 'discord.js';
import { MusicPlayer, MusicPlayerEvent, LavalinkManager } from '@persian-caesar/discord-player';
// Initialize Discord client with necessary intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
// Initialize Erela.js Manager for Lavalink
const manager = new LavalinkManager(client, {
nodes: [
{
host: "lava-v4.ajieblogs.eu.org",
port: 443,
password: "https://dsc.gg/ajidevserver",
secure: true
}
]
});
// Bot configuration
const PREFIX = '!';
const TOKEN = 'YOUR_BOT_TOKEN'; // Replace with your bot token
client.on('ready', () => {
console.log(`Logged in as ${client.user?.tag}`);
});
client.on('messageCreate', async (message) => {
if (!message.content.startsWith(PREFIX) || message.author.bot) return;
const args = message.content.slice(PREFIX.length).trim().split(/ +/);
const command = args.shift()?.toLowerCase();
if (!message.guild || !message.member?.voice.channel) return;
const voiceChannel = message.member.voice.channel as VoiceChannel;
const player = new MusicPlayer(voiceChannel, message.channel as TextChannel, manager, {
autoLeaveOnEmptyQueue: true,
autoLeaveOnIdleMs: 300_000 // 5 minutes
});
// Event listeners for music player
player.on(MusicPlayerEvent.Start, ({ metadata }) => {
message.channel.send(`▶️ Now playing: ${metadata.title || metadata.url}`);
});
player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
const added = metadatas ? metadatas.length + ' tracks' : metadata?.title || metadata?.url;
message.channel.send(`➕ Added: ${added} (${queue.length} in queue)`);
});
player.on(MusicPlayerEvent.Error, (error) => {
message.channel.send(`❌ Error: ${error.message}`);
});
player.on(MusicPlayerEvent.Finish, () => {
message.channel.send('⏹️ Playback finished.');
});
// Command handling
if (command === 'play') {
const query = args.join(' ');
if (!query) {
message.channel.send('Please provide a URL or search query.');
return;
}
await player.play(query);
}
else if (command === 'search') {
const query = args.join(' ');
const results = await player.search(query, 'youtube');
const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url}`).join('\n');
message.channel.send(resultList || 'No results.');
}
else if (command === 'playlists') {
const query = args.join(' ');
const playlists = await player.searchPlaylists(query, 'spotify');
const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} tracks): ${p.url}`).join('\n');
message.channel.send(list || 'No playlists found.');
}
else if (command === 'isplaylist') {
const url = args[0];
const isPlaylist = await player.isPlaylist(url);
message.channel.send(isPlaylist ? 'Yes, this is a playlist.' : 'No, this is not a playlist.');
} // Add other commands as needed
});
client.login(TOKEN);
TypeScript Example without Lavalink
This example uses fallback streaming without Lavalink.
import { Client, GatewayIntentBits, TextChannel, VoiceChannel } from 'discord.js';
import { MusicPlayer, MusicPlayerEvent } from '@persian-caesar/discord-player';
// Initialize Discord client with necessary intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
// Bot configuration
const PREFIX = '!';
const TOKEN = 'YOUR_BOT_TOKEN'; // Replace with your bot token
client.on('ready', () => {
console.log(`Logged in as ${client.user?.tag}`);
});
client.on('messageCreate', async (message) => {
if (!message.content.startsWith(PREFIX) || message.author.bot) return;
const args = message.content.slice(PREFIX.length).trim().split(/ +/);
const command = args.shift()?.toLowerCase();
if (!message.guild || !message.member?.voice.channel) return;
const voiceChannel = message.member.voice.channel as VoiceChannel;
const player = new MusicPlayer(voiceChannel, message.channel as TextChannel, undefined, {
autoLeaveOnEmptyQueue: true,
autoLeaveOnIdleMs: 300_000, // 5 minutes
youtubeCookie: 'YOUR_YOUTUBE_COOKIE', // Optional for age-restricted content
});
// Event listeners for music player
player.on(MusicPlayerEvent.Start, ({ metadata }) => {
message.channel.send(`▶️ Now playing: ${metadata.title || metadata.url}`);
});
player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
const added = metadatas ? metadatas.length + ' tracks' : metadata?.title || metadata?.url;
message.channel.send(`➕ Added: ${added} (${queue.length} in queue)`);
});
player.on(MusicPlayerEvent.Error, (error) => {
message.channel.send(`❌ Error: ${error.message}`);
});
player.on(MusicPlayerEvent.Finish, () => {
message.channel.send('⏹️ Playback finished.');
});
// Command handling
if (command === 'play') {
const query = args.join(' ');
if (!query) {
message.channel.send('Please provide a URL or search query.');
return;
}
await player.play(query);
}
else if (command === 'search') {
const query = args.join(' ');
const results = await player.search(query, 'spotify'); // Optional platform
const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url}`).join('\n');
message.channel.send(resultList || 'No results.');
}
else if (command === 'playlists') {
const query = args.join(' ');
const playlists = await player.searchPlaylists(query, 'deezer');
const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} tracks): ${p.url}`).join('\n');
message.channel.send(list || 'No playlists found.');
}
else if (command === 'isplaylist') {
const url = args[0];
const isPlaylist = await player.isPlaylist(url);
message.channel.send(isPlaylist ? 'Yes, this is a playlist.' : 'No, this is not a playlist.');
} // Add other commands as needed
});
client.login(TOKEN);
JavaScript Example
This example uses plain JavaScript with optional Lavalink.
const { Client, GatewayIntentBits } = require('discord.js');
const { MusicPlayer, MusicPlayerEvent, LavalinkManager } = require('@persian-caesar/discord-player');
// Initialize Discord client with necessary intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
// Optional Lavalink Manager
const manager = new LavalinkManager(client, {
nodes: [
{
host: "lava-v4.ajieblogs.eu.org",
port: 443,
password: "https://dsc.gg/ajidevserver",
secure: true
}
]
});
// Bot configuration
const PREFIX = '!';
const TOKEN = 'YOUR_BOT_TOKEN'; // Replace with your bot token
client.on('ready', () => {
console.log(`Logged in as ${client.user?.tag}`);
});
client.on('messageCreate', async (message) => {
if (!message.content.startsWith(PREFIX) || message.author.bot) return;
const args = message.content.slice(PREFIX.length).trim().split(/ +/);
const command = args.shift()?.toLowerCase();
if (!message.guild || !message.member?.voice.channel) return;
/** @type {import('@persian-caesar/discord-player').VoiceChannel} */
const voiceChannel = message.member.voice.channel;
const player = new MusicPlayer(voiceChannel, message.channel, manager, { // Pass manager if using Lavalink
autoLeaveOnEmptyQueue: true,
autoLeaveOnIdleMs: 300_000 // 5 minutes
});
// Event listeners for music player
player.on(MusicPlayerEvent.Start, ({ metadata }) => {
message.channel.send(`▶️ Now playing: ${metadata.title || metadata.url}`);
});
player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
const added = metadatas ? metadatas.length + ' tracks' : metadata?.title || metadata?.url;
message.channel.send(`➕ Added: ${added} (${queue.length} in queue)`);
});
player.on(MusicPlayerEvent.Error, (error) => {
message.channel.send(`❌ Error: ${error.message}`);
});
player.on(MusicPlayerEvent.Finish, () => {
message.channel.send('⏹️ Playback finished.');
});
// Command handling
if (command === 'play') {
const query = args.join(' ');
if (!query) {
message.channel.send('Please provide a URL or search query.');
return;
}
await player.play(query);
}
else if (command === 'search') {
const query = args.join(' ');
const results = await player.search(query);
const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url}`).join('\n');
message.channel.send(resultList || 'No results.');
}
else if (command === 'playlists') {
const query = args.join(' ');
const playlists = await player.searchPlaylists(query);
const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} tracks): ${p.url}`).join('\n');
message.channel.send(list || 'No playlists found.');
}
else if (command === 'isplaylist') {
const url = args[0];
const isPlaylist = await player.isPlaylist(url);
message.channel.send(isPlaylist ? 'Yes, this is a playlist.' : 'No, this is not a playlist.');
} // Add other commands as needed
});
client.login(TOKEN);
API Reference
MusicPlayer Class
Constructor:
new MusicPlayer(
channel: VoiceChannel,
textChannel: TextChannel,
lavaLinkManager?: Manager, // Optional Erela.js Manager for Lavalink
options?: MusicPlayerOptions // { initialVolume?: number, autoLeaveOnEmptyQueue?: boolean, autoLeaveOnIdleMs?: number, youtubeCookie?: string, logError?: boolean }
)
Methods:
| Method | Description |
| -------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| isPlaylist(url: string): Promise<boolean>
| Checks if the given URL is a playlist. |
| searchPlaylists(query: string, platform?: SearchPlatform, limit?: number): Promise<PlaylistMetadata[]>
| Searches for playlists across platforms. |
| search(query: string, platform?: SearchPlatform, limit?: number): Promise<TrackMetadata[]>
| Searches for tracks across platforms. |
| play(input: string | TrackMetadata | TrackMetadata[], radio?: boolean): Promise<void>
| Plays input (string searches first result or loads playlist, metadata/array direct). Supports playlists. |
| pause(): void
| Pauses the current track. |
| resume(): void
| Resumes playback. |
| setVolume(percent: number): number
| Sets volume (0–200%), returns new volume. |
| skip(): void
| Skips to the next track in the queue. |
| previous(): Promise<void>
| Plays the previous track from history. |
| shuffle(): void
| Shuffles the queue, saving the original order. |
| undoShuffle(): void
| Restores the queue to its pre-shuffle order. |
| toggleLoopQueue(): boolean
| Toggles queue looping, returns new state. |
| toggleLoopTrack(): boolean
| Toggles single-track looping, returns new state. |
| startRadio(urls: string[]): Promise<void>
| Starts radio mode with shuffled URLs. |
| stop(noLeave?: boolean): void
| Stops playback, optionally disconnects. |
| disconnect(): void
| Disconnects from the voice channel. |
| join(): VoiceConnection
| Joins the voice channel without subscribing player. |
| getQueue(): TrackMetadata[]
| Returns a copy of the current queue. |
| getVolume(): number
| Returns the current volume (0–200%). |
| isPlaying(): boolean
| Checks if a track is playing. |
| isPaused(): boolean
| Checks if playback is paused. |
| isShuffiled(): boolean
| Checks if the queue is shuffled. |
| isConnected(guildId?: string): boolean
| Checks if connected to a voice channel. |
| searchLyrics(title: string, artist?: string): Promise<string | null>
| Fetches song lyrics from Google. |
MusicPlayerEvent Enum
export enum MusicPlayerEvent {
Start = "start",
QueueAdd = "queueAdd",
Pause = "pause",
Resume = "resume",
Stop = "stop",
Skip = "skip",
Previous = "previous",
Shuffle = "shuffle",
LoopQueue = "loopQueue",
LoopTrack = "loopTrack",
VolumeChange = "volumeChange",
Finish = "finish",
Disconnect = "disconnect",
Error = "error"
}
Event Payloads:
Start
:{ metadata: TrackMetadata, queue: TrackMetadata[] }
QueueAdd
:{ metadata?: TrackMetadata, metadatas?: TrackMetadata[], queue: TrackMetadata[] }
VolumeChange
:{ volume: number }
Skip
:{ queue: TrackMetadata[], history: string[] }
Previous
:{ metadata: TrackMetadata, queue: TrackMetadata[], history: string[] }
Shuffle
:{ queue: TrackMetadata[] }
LoopQueue
:{ enabled: boolean }
LoopTrack
:{ enabled: boolean }
Finish
:{ queue: TrackMetadata[], history: string[] }
Error
:Error
- Others: No payload
See types.ts
for full type definitions.
Method Usage and Examples
This section provides detailed explanations and code snippets for each MusicPlayer
method, demonstrating their usage within a Discord bot context using discord.js
. The examples assume a MusicPlayer
instance is created as shown in the Usage Examples section.
isPlaylist(url: string): Promise<boolean>
Checks if the given URL is a playlist.
Example:
if (command === 'isplaylist') {
const url = args[0];
const isPlaylist = await player.isPlaylist(url);
message.channel.send(isPlaylist ? 'Yes, this is a playlist.' : 'No, this is not a playlist.');
}
searchPlaylists(query: string, platform?: SearchPlatform, limit?: number): Promise<PlaylistMetadata[]>
Searches for playlists across platforms.
Example:
if (command === 'playlists') {
const query = args.join(' ');
const playlists = await player.searchPlaylists(query, 'spotify', 5);
if (playlists.length === 0) {
message.channel.send('No playlists found.');
return;
}
const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} tracks): ${p.url}`).join('\n');
message.channel.send(`Playlists:\n${list}`);
}
search(query: string, platform?: SearchPlatform, limit?: number): Promise<TrackMetadata[]>
Searches for tracks across platforms.
Example:
if (command === 'search') {
const query = args.join(' ');
const results = await player.search(query, 'youtube', 5);
if (results.length === 0) {
message.channel.send('No results found.');
return;
}
const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url} (${r.source})`).join('\n');
message.channel.send(`Results:\n${resultList}`);
}
play(input: string | TrackMetadata | TrackMetadata[], radio?: boolean): Promise<void>
Plays input. If string, searches and plays first result or loads playlist. If TrackMetadata or array, plays directly.
Example:
if (command === 'play') {
const query = args.join(' ');
if (!query) {
message.channel.send('Please provide a URL or search query.');
return;
}
await player.play(query);
}
player.on(MusicPlayerEvent.Start, ({ metadata }) => {
message.channel.send(`▶️ Now playing: ${metadata.title || metadata.url}`);
});
player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
const added = metadatas ? metadatas.length + ' tracks' : metadata?.title || metadata?.url;
message.channel.send(`➕ Added: ${added} (${queue.length} in queue)`);
});
pause(): void
Pauses the current track.
Example:
if (command === 'pause') {
player.pause();
message.channel.send('⏸️ Playback paused.');
}
resume(): void
Resumes playback.
Example:
if (command === 'resume') {
player.resume();
message.channel.send('▶️ Playback resumed.');
}
setVolume(percent: number): number
Sets volume (0–200%), returns new volume.
Example:
if (command === 'volume') {
const volume = parseInt(args[0]);
if (isNaN(volume)) {
message.channel.send('Please provide a valid volume (0–200).');
return;
}
const newVolume = player.setVolume(volume);
message.channel.send(`🔊 Volume set to ${newVolume}%`);
}
player.on(MusicPlayerEvent.VolumeChange, ({ volume }) => {
message.channel.send(`🔊 Volume changed to ${volume}%`);
});
skip(): void
Skips to the next track.
Example:
if (command === 'skip') {
player.skip();
message.channel.send('⏭️ Skipped to next track.');
}
player.on(MusicPlayerEvent.Skip, ({ queue }) => {
message.channel.send(`⏭️ Skipped. ${queue.length} tracks remaining.`);
});
previous(): Promise<void>
Plays the previous track.
Example:
if (command === 'previous') {
await player.previous();
}
player.on(MusicPlayerEvent.Previous, ({ metadata }) => {
message.channel.send(`⏮️ Playing previous: ${metadata.title || metadata.url}`);
});
shuffle(): void
Shuffles the queue.
Example:
if (command === 'shuffle') {
player.shuffle();
message.channel.send('🔀 Queue shuffled.');
}
player.on(MusicPlayerEvent.Shuffle, ({ queue }) => {
message.channel.send(`🔀 Shuffled. ${queue.length} tracks in new order.`);
});
undoShuffle(): void
Restores pre-shuffle order.
Example:
if (command === 'unshuffle') {
player.undoShuffle();
message.channel.send('🔄 Queue restored.');
}
toggleLoopQueue(): boolean
Toggles queue loop, returns state.
Example:
if (command === 'loopqueue') {
const enabled = player.toggleLoopQueue();
message.channel.send(`🔁 Queue loop ${enabled ? 'enabled' : 'disabled'}.`);
}
player.on(MusicPlayerEvent.LoopQueue, ({ enabled }) => {
message.channel.send(`🔁 Queue loop ${enabled ? 'enabled' : 'disabled'}.`);
});
toggleLoopTrack(): boolean
Toggles track loop, returns state.
Example:
if (command === 'looptrack') {
const enabled = player.toggleLoopTrack();
message.channel.send(`🔂 Track loop ${enabled ? 'enabled' : 'disabled'}.`);
}
player.on(MusicPlayerEvent.LoopTrack, ({ enabled }) => {
message.channel.send(`🔂 Track loop ${enabled ? 'enabled' : 'disabled'}.`);
});
startRadio(urls: string[]): Promise<void>
Starts radio mode.
Example:
if (command === 'radio') {
const urls = args; // Array of URLs
await player.startRadio(urls);
message.channel.send('📻 Radio mode started.');
}
stop(noLeave?: boolean): void
Stops playback.
Example:
if (command === 'stop') {
player.stop(true); // Stay connected
message.channel.send('⏹️ Stopped.');
}
player.on(MusicPlayerEvent.Stop, () => {
message.channel.send('⏹️ Stopped.');
});
disconnect(): void
Disconnects from voice.
Example:
if (command === 'leave') {
player.disconnect();
message.channel.send('🔌 Disconnected.');
}
player.on(MusicPlayerEvent.Disconnect, () => {
message.channel.send('🔌 Disconnected.');
});
join(): VoiceConnection
Joins voice channel without player subscribe.
Example:
if (command === 'join') {
const connection = player.join();
message.channel.send('🔗 Joined voice channel.');
}
getQueue(): TrackMetadata[]
Gets queue copy.
Example:
if (command === 'queue') {
const queue = player.getQueue();
const list = queue.map((t, i) => `${i + 1}. ${t.title || t.url}`).join('\n');
message.channel.send(`📃 Queue:\n${list || 'Empty'}`);
}
getVolume(): number
Gets volume.
Example:
if (command === 'volume') {
message.channel.send(`🔊 Volume: ${player.getVolume()}%`);
}
isPlaying(): boolean
Checks playing.
Example:
if (command === 'status') {
message.channel.send(`🎵 ${player.isPlaying() ? 'Playing' : 'Not playing'}.`);
}
isPaused(): boolean
Checks paused.
Example:
if (command === 'status') {
message.channel.send(`⏯️ ${player.isPaused() ? 'Paused' : 'Not paused'}.`);
}
isShuffiled(): boolean
Checks shuffled.
Example:
if (command === 'status') {
message.channel.send(`🔀 Queue is ${player.isShuffiled() ? 'shuffled' : 'not shuffled'}.`);
}
isConnected(guildId?: string): boolean
Checks connected.
Example:
if (command === 'status') {
message.channel.send(`🔗 ${player.isConnected() ? 'Connected' : 'Not connected'}.`);
}
searchLyrics(title: string, artist?: string): Promise<string | null>
Fetches lyrics.
Example:
if (command === 'lyrics') {
const title = args.join(' ');
const lyrics = await player.searchLyrics(title, 'artist');
message.channel.send(lyrics ? `🎵 Lyrics:\n${lyrics}` : 'No lyrics found.');
}
Support and Contributions
- Repository: https://github.com/Persian-Caesar/discord-player
- Issues: https://github.com/Persian-Caesar/discord-player/issues
- Community: Join the Persian Caesar Discord for support.
- Contributions: Pull requests are welcome! Please follow the contribution guidelines in the repository.
License
This project is licensed under the MIT License. See the LICENSE
file or the repository for details.
⌨️ Built with ❤️ by Sobhan-SRZA for Persian Caesar. Star the repo if you find it useful!