# Music Player Documentation

## Overview
This documentation outlines the functionality and features of the `Player` class, its associated constants, filters, and events. The `Player` class enables advanced audio playback features for Discord bots, such as queue management, audio effects, and looping options.

---

## Classes and Components

### 1. **Player**
The main class responsible for managing audio playback, including queue operations, filters, and connection handling.

#### **Constructor Options**
- **`defaultVolume`** (number)  
  Default playback volume percentage. *(Default: `100`)*
  
- **`leaveAfterEnd`** (boolean)  
  Whether the bot leaves the voice channel after the queue ends. *(Default: `true`)*
  
- **`keepVoiceIfExists`** (boolean)  
  Whether to retain an existing voice connection instead of creating a new one. *(Default: `true`)*
  
- **`client`** (Discord.Client)  
  Instance of a [Discord.js](https://discord.js.org) client.

- **`ytDlpOptions`** (string)
  Your [yt-dlp options](https://github.com/yt-dlp/yt-dlp/blob/master/README.md)

#### **Key Methods**
- **`search(query, trackLimit = 10)`**  
  Searches YouTube for tracks matching a query.  
  - `query` (string): The search term or URL.  
  - `trackLimit` (number): Maximum number of tracks to fetch. *(Default: `10`)*  

- **`connect(channelResolvable, voiceJoinOptions = {})`**  
  Force connect in a voice channel (ignoring `keepVoiceIfExists` option!).  
  - `channelResolvable` (Object or Snowflake): Voice channel to play in.  
  - `voiceJoinOptions` (object): [JoinVoiceChannelOptions](https://discord.js.org/docs/packages/voice/main/JoinVoiceChannelOptions:Interface) && [CreateVoiceConnectionOptions](https://discord.js.org/docs/packages/voice/main/CreateVoiceConnectionOptions:Interface).  

- **`play(channelResolvable, query, voiceJoinOptions = {})`**  
  Plays a track in a voice channel.  
  - `channelResolvable` (Object or Snowflake): Voice channel to play in.  
  - `query` (string): Track URL or search query. 
  - `voiceJoinOptions` (object): [JoinVoiceChannelOptions](https://discord.js.org/docs/packages/voice/main/JoinVoiceChannelOptions:Interface) && [CreateVoiceConnectionOptions](https://discord.js.org/docs/packages/voice/main/CreateVoiceConnectionOptions:Interface). 

- **`pause(guildResolvable)`**  
  Pauses the current track.  
  - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`unpause(guildResolvable)`**  
  Resumes playback.  
    - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`skip(guildResolvable)`**  
  Skips the current track and plays the next one in the queue.
    - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`stop(guildResolvable)`**  
  Stops playback and clears the queue.
    - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`setVolume(guildResolvable, volume)`**  
  Sets playback volume.
    - `guildResolvable` (Object or Snowflake): The guild ID or object.  
    - `volume` (number): Percentage.  

- **`shuffleQueue(guildResolvable)`**  
  Randomizes the playback order in the queue.
    - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`nowPlaying(guildResolvable)`**  
  Fetches information about the currently playing track.  
    - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`addFilter(guildResolvable, ffmpegFilter)`**  
  Adds an FFmpeg audio filter.  
    - `guildResolvable` (Object or Snowflake): The guild ID or object.
    - `ffmpegFilter` FFmpeg filter from `Filters` class or you can using `registerAudioFilter` method from `Filters` class enum for your own filters.

- **`setFilter(guildResolvable, ffmpegFilter)`**  
  Replaces existing filters with a new filter.
      - `guildResolvable` (Object or Snowflake): The guild ID or object.
     - `ffmpegFilter` FFmpeg filter from `Filters` class or you can using `registerAudioFilter` method from `Filters` class enum for your own filters.
     
- **`resetFilters(guildResolvable)`**  
  Removes all applied filters.  
      - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`loopQueue(guildResolvable, status)`**  
  Sets the loop status.
        - `guildResolvable` (Object or Snowflake): The guild ID or object.  
  - `status` (number):  
    `0` = Nothing, `1` = Loop Track, `2` = Loop Queue. (Also you can using `LoopStatuses` class enum).  

- **`restartCurrentTrack(guildResolvable)`**  
  Restarts the currently playing track.
        - `guildResolvable` (Object or Snowflake): The guild ID or object.

- **`setChannelStatus(channelResolvable, status)`**  
  Updates the voice status of a specified channel.  
        - `channelResolvable` (Object or Snowflake): The channel ID or object.  
        - `status` (string): The voice status to set (e.g., `"muted"`, `"unmuted"`). 

---

### 2. **Filters**
Provides static methods for generating various FFmpeg-based audio filters.

#### **Available Filters**
- **`nightcore({ strength: 1.25 })`**  
  Produces a "nightcore" effect by altering pitch and tempo.  

- **`bassboost({ strength: 10 })`**  
  Enhances bass frequencies.  

- **`reverb({ strength: 50 })`**  
  Adds a reverb effect.  

- **`crusher({ bits: 8 })`**  
  Reduces the audio quality for a distorted effect.  

- **`speed({ strength: 1 })`**  
  Alters the playback speed.

#### **Registering Filters**
For creating your own filters on this project, you can use `registerAudioFilter` method from `Filters` class enum. Usage:
```js
const { Filters } = require('@terron/djs-music');

Filters.registerAudioFilter(
    'dynamicBassboost', // name
    'bass=g={strength},dynaudnorm=f={frequency}:g={gain}', // ffmpeg syntax
    { strength: 10, frequency: 150, gain: 15 } // default args
);

Filters.dynamicBassboost();
```
---

### 3. **PlayerEvents**
Events emitted by the `Player` class to track playback, queue changes, and other interactions.

#### **Available Events**
- **`VoiceJoin`**: Emitted when the bot joins a voice channel.  
- **`VoiceLeft`**: Emitted when the bot leaves a voice channel.  
- **`VoiceUpdate`**: Emitted when the bot's voice state is updated.  
- **`TrackAdd`**: Triggered when a track is added to the queue.  
- **`TrackStart`**: Triggered when a track starts playing.  
- **`QueueEnd`**: Triggered when the queue ends.  
- **`UpdateLoopStatus`**: Emitted when the loop status is changed.  
- **`Backward`**: Emitted when playback moves backward.

---

## Examples

```javascript
const { Client, GatewayIntentBits } = require('discord.js');
const { Player, PlayerEvents, Filters } = require('@terron/djs-music');
const client = new Client({
    intents: ['Guilds', 'GuildMessages', 'MessageContent', 'GuildVoiceStates']
});

client.player = new Player({
    client,
    defaultVolume: 75,
    leaveAfterEnd: false
});

client.on('ready', () => console.log('Client is ready!'));

// commands
client.on('messageCreate', async msg => {
    if (!msg.content || !msg.guild) return;
    const args = msg.content.split(' ');
    const cmd = args.shift();

    if (cmd == '!play') {
        await client.player.play(msg.member.voice?.channel, args.join(' '), {
          selfDeaf: false
        });
    }

    if (cmd == '!stop') {
        client.player.stop(msg.guildId);
    }
});

// player events
client.player.on(PlayerEvents.VoiceJoin, channel => console.log(`Client join in ${channel.name}!`));
client.player.on(PlayerEvents.VoiceLeft, channel => console.log(`Client left from ${channel.name}!`));
client.player.on(PlayerEvents.TrackStart, track => {
    console.log(`Started track ${track.title} by ${track.author.name}!`)
});
```