streamify-audio 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +430 -0
- package/bin/streamify.js +84 -0
- package/docs/README.md +31 -0
- package/docs/automation.md +186 -0
- package/docs/configuration.md +169 -0
- package/docs/discord/events.md +206 -0
- package/docs/discord/manager.md +180 -0
- package/docs/discord/player.md +180 -0
- package/docs/discord/queue.md +197 -0
- package/docs/examples/advanced-bot.md +391 -0
- package/docs/examples/basic-bot.md +182 -0
- package/docs/examples/lavalink.md +156 -0
- package/docs/filters.md +309 -0
- package/docs/http/endpoints.md +199 -0
- package/docs/http/server.md +172 -0
- package/docs/quick-start.md +92 -0
- package/docs/sources.md +141 -0
- package/docs/sponsorblock.md +95 -0
- package/index.d.ts +350 -0
- package/index.js +252 -0
- package/package.json +57 -0
- package/silence.ogg +0 -0
- package/src/cache/index.js +61 -0
- package/src/config.js +133 -0
- package/src/discord/Manager.js +453 -0
- package/src/discord/Player.js +658 -0
- package/src/discord/Queue.js +129 -0
- package/src/discord/Stream.js +252 -0
- package/src/filters/ffmpeg.js +270 -0
- package/src/providers/soundcloud.js +166 -0
- package/src/providers/spotify.js +216 -0
- package/src/providers/youtube.js +320 -0
- package/src/server.js +318 -0
- package/src/utils/logger.js +139 -0
- package/src/utils/stream.js +108 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Automation
|
|
2
|
+
|
|
3
|
+
Streamify includes built-in automation features for common scenarios.
|
|
4
|
+
|
|
5
|
+
## Auto-Pause
|
|
6
|
+
|
|
7
|
+
Automatically pauses playback when users leave the voice channel and resumes when they return.
|
|
8
|
+
|
|
9
|
+
### Configuration
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
const manager = new Streamify.Manager(client, {
|
|
13
|
+
autoPause: {
|
|
14
|
+
enabled: true,
|
|
15
|
+
minUsers: 1 // Pause when users drop below this
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Behavior
|
|
21
|
+
|
|
22
|
+
1. User count drops below `minUsers`
|
|
23
|
+
2. Playback pauses immediately
|
|
24
|
+
3. Stream is destroyed (saves resources)
|
|
25
|
+
4. Position is saved
|
|
26
|
+
5. When users rejoin and count reaches `minUsers`:
|
|
27
|
+
6. Stream recreates with seek
|
|
28
|
+
7. Playback resumes
|
|
29
|
+
|
|
30
|
+
### Events
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
player.on('autoPause', (userCount) => {
|
|
34
|
+
channel.send(`Paused (${userCount} users in channel)`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
player.on('autoResume', (userCount) => {
|
|
38
|
+
channel.send(`Resumed (${userCount} users now)`);
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Runtime Toggle
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
player.setAutoPause(false); // Disable
|
|
46
|
+
player.setAutoPause(true); // Enable
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Auto-Leave
|
|
50
|
+
|
|
51
|
+
Automatically leaves the voice channel after a period of inactivity.
|
|
52
|
+
|
|
53
|
+
### Configuration
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
const manager = new Streamify.Manager(client, {
|
|
57
|
+
autoLeave: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
emptyDelay: 30000, // Leave 30s after channel empty
|
|
60
|
+
inactivityTimeout: 300000 // Leave after 5min of not playing
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Behavior
|
|
66
|
+
|
|
67
|
+
**Empty Channel:**
|
|
68
|
+
1. All users leave
|
|
69
|
+
2. 30 second countdown starts
|
|
70
|
+
3. If no one rejoins, player destroys
|
|
71
|
+
|
|
72
|
+
**Inactivity:**
|
|
73
|
+
1. Queue ends, nothing playing
|
|
74
|
+
2. 5 minute countdown starts
|
|
75
|
+
3. If nothing plays, player destroys
|
|
76
|
+
|
|
77
|
+
### Events
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
player.on('channelEmpty', () => {
|
|
81
|
+
channel.send('Everyone left. Leaving in 30 seconds...');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
player.on('destroy', () => {
|
|
85
|
+
channel.send('Disconnected due to inactivity.');
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Autoplay
|
|
90
|
+
|
|
91
|
+
Automatically plays related tracks when the queue ends.
|
|
92
|
+
|
|
93
|
+
### Configuration
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
const manager = new Streamify.Manager(client, {
|
|
97
|
+
autoplay: {
|
|
98
|
+
enabled: false, // Off by default
|
|
99
|
+
maxTracks: 5 // How many related tracks to fetch
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Behavior
|
|
105
|
+
|
|
106
|
+
1. Queue ends (last track finishes)
|
|
107
|
+
2. Fetch related tracks from YouTube Mix or Spotify Recommendations
|
|
108
|
+
3. Add to queue and start playing
|
|
109
|
+
4. Repeat when those tracks end
|
|
110
|
+
|
|
111
|
+
### Events
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
player.on('autoplayStart', (lastTrack) => {
|
|
115
|
+
console.log(`Finding tracks like: ${lastTrack.title}`);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
player.on('autoplayAdd', (tracks) => {
|
|
119
|
+
channel.send(`Autoplay added ${tracks.length} tracks`);
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Runtime Toggle
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
player.setAutoplay(true); // Enable
|
|
127
|
+
player.setAutoplay(false); // Disable
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Track Identification
|
|
131
|
+
|
|
132
|
+
Autoplay tracks are marked:
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
player.on('trackStart', (track) => {
|
|
136
|
+
if (track.isAutoplay) {
|
|
137
|
+
channel.send(`Autoplay: **${track.title}**`);
|
|
138
|
+
} else {
|
|
139
|
+
channel.send(`Now playing: **${track.title}**`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Combining Features
|
|
145
|
+
|
|
146
|
+
All automation features work together:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const manager = new Streamify.Manager(client, {
|
|
150
|
+
autoPause: {
|
|
151
|
+
enabled: true,
|
|
152
|
+
minUsers: 1
|
|
153
|
+
},
|
|
154
|
+
autoLeave: {
|
|
155
|
+
enabled: true,
|
|
156
|
+
emptyDelay: 30000,
|
|
157
|
+
inactivityTimeout: 300000
|
|
158
|
+
},
|
|
159
|
+
autoplay: {
|
|
160
|
+
enabled: true,
|
|
161
|
+
maxTracks: 5
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Scenario: User leaves during playback**
|
|
167
|
+
1. `autoPause` triggers → pauses playback
|
|
168
|
+
2. `autoLeave` starts 30s countdown
|
|
169
|
+
3. User rejoins within 30s
|
|
170
|
+
4. `autoResume` triggers → playback continues
|
|
171
|
+
5. Countdown cancelled
|
|
172
|
+
|
|
173
|
+
**Scenario: Queue ends**
|
|
174
|
+
1. `autoplay` fetches related tracks
|
|
175
|
+
2. Playback continues with recommendations
|
|
176
|
+
3. If autoplay disabled, `autoLeave` inactivity timeout starts
|
|
177
|
+
|
|
178
|
+
## Disabling All Automation
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
const manager = new Streamify.Manager(client, {
|
|
182
|
+
autoPause: { enabled: false },
|
|
183
|
+
autoLeave: { enabled: false },
|
|
184
|
+
autoplay: { enabled: false }
|
|
185
|
+
});
|
|
186
|
+
```
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
## Discord Player Mode
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
const manager = new Streamify.Manager(client, {
|
|
7
|
+
// Paths (required)
|
|
8
|
+
ytdlpPath: '/usr/local/bin/yt-dlp',
|
|
9
|
+
ffmpegPath: '/usr/bin/ffmpeg',
|
|
10
|
+
|
|
11
|
+
// YouTube cookies (optional)
|
|
12
|
+
cookiesPath: './cookies.txt',
|
|
13
|
+
|
|
14
|
+
// Providers (optional - all enabled by default)
|
|
15
|
+
providers: {
|
|
16
|
+
youtube: { enabled: true },
|
|
17
|
+
spotify: { enabled: true },
|
|
18
|
+
soundcloud: { enabled: true }
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
// Spotify credentials (optional)
|
|
22
|
+
spotify: {
|
|
23
|
+
clientId: process.env.SPOTIFY_CLIENT_ID,
|
|
24
|
+
clientSecret: process.env.SPOTIFY_CLIENT_SECRET
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// Audio settings
|
|
28
|
+
audio: {
|
|
29
|
+
bitrate: '128k', // Audio bitrate
|
|
30
|
+
format: 'opus' // opus, mp3, aac
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// Defaults
|
|
34
|
+
defaultVolume: 80, // 0-200
|
|
35
|
+
maxPreviousTracks: 25, // History size
|
|
36
|
+
|
|
37
|
+
// Sponsorblock
|
|
38
|
+
sponsorblock: {
|
|
39
|
+
enabled: true,
|
|
40
|
+
categories: ['sponsor', 'selfpromo', 'intro', 'outro']
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// Auto-leave
|
|
44
|
+
autoLeave: {
|
|
45
|
+
enabled: true,
|
|
46
|
+
emptyDelay: 30000, // Leave 30s after channel empty
|
|
47
|
+
inactivityTimeout: 300000 // Leave after 5min idle
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// Auto-pause
|
|
51
|
+
autoPause: {
|
|
52
|
+
enabled: true,
|
|
53
|
+
minUsers: 1 // Pause when users drop below this
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
// Autoplay
|
|
57
|
+
autoplay: {
|
|
58
|
+
enabled: false,
|
|
59
|
+
maxTracks: 5 // Related tracks to fetch
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## HTTP Server Mode
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
const streamify = new Streamify({
|
|
68
|
+
// Server
|
|
69
|
+
port: 8787,
|
|
70
|
+
host: '0.0.0.0',
|
|
71
|
+
|
|
72
|
+
// Paths
|
|
73
|
+
ytdlpPath: '/usr/local/bin/yt-dlp',
|
|
74
|
+
ffmpegPath: '/usr/bin/ffmpeg',
|
|
75
|
+
|
|
76
|
+
// YouTube cookies
|
|
77
|
+
cookiesPath: './cookies.txt',
|
|
78
|
+
// Or direct string:
|
|
79
|
+
cookies: '# Netscape HTTP Cookie File\n...',
|
|
80
|
+
|
|
81
|
+
// Providers (optional - all enabled by default)
|
|
82
|
+
providers: {
|
|
83
|
+
youtube: { enabled: true },
|
|
84
|
+
spotify: { enabled: true },
|
|
85
|
+
soundcloud: { enabled: true }
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// Spotify
|
|
89
|
+
spotify: {
|
|
90
|
+
clientId: 'xxx',
|
|
91
|
+
clientSecret: 'xxx'
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
// Audio
|
|
95
|
+
audio: {
|
|
96
|
+
bitrate: '128k',
|
|
97
|
+
format: 'opus'
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// Logging
|
|
101
|
+
logLevel: 'info', // none, error, warn, info, debug
|
|
102
|
+
silent: false,
|
|
103
|
+
colors: true
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Environment Variables
|
|
108
|
+
|
|
109
|
+
| Variable | Description |
|
|
110
|
+
|----------|-------------|
|
|
111
|
+
| `SPOTIFY_CLIENT_ID` | Spotify API client ID |
|
|
112
|
+
| `SPOTIFY_CLIENT_SECRET` | Spotify API client secret |
|
|
113
|
+
| `YTDLP_PATH` | Path to yt-dlp binary |
|
|
114
|
+
| `FFMPEG_PATH` | Path to ffmpeg binary |
|
|
115
|
+
| `COOKIES_PATH` | Path to YouTube cookies file |
|
|
116
|
+
| `PORT` | HTTP server port |
|
|
117
|
+
|
|
118
|
+
## YouTube Cookies
|
|
119
|
+
|
|
120
|
+
For age-restricted or region-locked videos:
|
|
121
|
+
|
|
122
|
+
1. Install browser extension "Get cookies.txt"
|
|
123
|
+
2. Visit youtube.com while logged in
|
|
124
|
+
3. Export cookies in Netscape format
|
|
125
|
+
4. Save as `cookies.txt`
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
// File path
|
|
129
|
+
cookiesPath: './cookies.txt'
|
|
130
|
+
|
|
131
|
+
// Or direct string
|
|
132
|
+
cookies: `# Netscape HTTP Cookie File
|
|
133
|
+
.youtube.com TRUE / TRUE 0 COOKIE_NAME COOKIE_VALUE`
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Spotify Setup
|
|
137
|
+
|
|
138
|
+
1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
|
|
139
|
+
2. Create an app
|
|
140
|
+
3. Copy Client ID and Client Secret
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
spotify: {
|
|
144
|
+
clientId: process.env.SPOTIFY_CLIENT_ID,
|
|
145
|
+
clientSecret: process.env.SPOTIFY_CLIENT_SECRET
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Spotify tracks are resolved to YouTube for playback.
|
|
150
|
+
|
|
151
|
+
## Providers
|
|
152
|
+
|
|
153
|
+
Enable or disable individual providers:
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
providers: {
|
|
157
|
+
youtube: { enabled: true },
|
|
158
|
+
spotify: { enabled: true },
|
|
159
|
+
soundcloud: { enabled: false } // Disabled
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
All providers are enabled by default. When a disabled provider is accessed, an error is thrown:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Error: SoundCloud provider is disabled
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
This is useful if you only want to support specific platforms.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Events
|
|
2
|
+
|
|
3
|
+
## Manager Events
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
manager.on('playerCreate', (player) => {
|
|
7
|
+
console.log(`Player created for guild ${player.guildId}`);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
manager.on('playerDestroy', (player) => {
|
|
11
|
+
console.log(`Player destroyed for guild ${player.guildId}`);
|
|
12
|
+
});
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Player Events
|
|
16
|
+
|
|
17
|
+
### Track Events
|
|
18
|
+
|
|
19
|
+
#### trackStart
|
|
20
|
+
|
|
21
|
+
Fired when a track starts playing.
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
player.on('trackStart', (track) => {
|
|
25
|
+
channel.send({
|
|
26
|
+
embeds: [{
|
|
27
|
+
title: 'Now Playing',
|
|
28
|
+
description: `**${track.title}**\nby ${track.author}`,
|
|
29
|
+
thumbnail: { url: track.thumbnail }
|
|
30
|
+
}]
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### trackEnd
|
|
36
|
+
|
|
37
|
+
Fired when a track finishes.
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
player.on('trackEnd', (track, reason) => {
|
|
41
|
+
// reason: 'finished' | 'skipped' | 'stopped'
|
|
42
|
+
console.log(`Track ended: ${track.title} (${reason})`);
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### trackError
|
|
47
|
+
|
|
48
|
+
Fired when a track fails to play.
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
player.on('trackError', (track, error) => {
|
|
52
|
+
channel.send(`Failed to play **${track.title}**: ${error.message}`);
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### queueEnd
|
|
57
|
+
|
|
58
|
+
Fired when the queue is empty and playback stops.
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
player.on('queueEnd', () => {
|
|
62
|
+
channel.send('Queue finished. Add more songs or enable autoplay!');
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Voice Events
|
|
67
|
+
|
|
68
|
+
#### userJoin
|
|
69
|
+
|
|
70
|
+
Fired when a user joins the voice channel.
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
player.on('userJoin', (member, count) => {
|
|
74
|
+
console.log(`${member.user.tag} joined (${count} users now)`);
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### userLeave
|
|
79
|
+
|
|
80
|
+
Fired when a user leaves the voice channel.
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
player.on('userLeave', (member, count) => {
|
|
84
|
+
console.log(`${member.user.tag} left (${count} users remaining)`);
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### channelEmpty
|
|
89
|
+
|
|
90
|
+
Fired when all users leave the voice channel.
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
player.on('channelEmpty', () => {
|
|
94
|
+
channel.send('Everyone left. I\'ll leave in 30 seconds...');
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### channelMove
|
|
99
|
+
|
|
100
|
+
Fired when the bot is moved to a different voice channel.
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
player.on('channelMove', (newChannelId) => {
|
|
104
|
+
console.log(`Moved to channel ${newChannelId}`);
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Automation Events
|
|
109
|
+
|
|
110
|
+
#### autoPause
|
|
111
|
+
|
|
112
|
+
Fired when playback is automatically paused.
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
player.on('autoPause', (userCount) => {
|
|
116
|
+
channel.send(`Paused (${userCount} users in channel)`);
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### autoResume
|
|
121
|
+
|
|
122
|
+
Fired when playback is automatically resumed.
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
player.on('autoResume', (userCount) => {
|
|
126
|
+
channel.send(`Resumed (${userCount} users rejoined)`);
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### autoplayStart
|
|
131
|
+
|
|
132
|
+
Fired when autoplay starts fetching related tracks.
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
player.on('autoplayStart', (lastTrack) => {
|
|
136
|
+
console.log(`Finding tracks related to: ${lastTrack.title}`);
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### autoplayAdd
|
|
141
|
+
|
|
142
|
+
Fired when autoplay adds tracks to the queue.
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
player.on('autoplayAdd', (tracks) => {
|
|
146
|
+
channel.send(`Autoplay added ${tracks.length} tracks`);
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Lifecycle Events
|
|
151
|
+
|
|
152
|
+
#### destroy
|
|
153
|
+
|
|
154
|
+
Fired when the player is destroyed.
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
player.on('destroy', () => {
|
|
158
|
+
console.log('Player destroyed');
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Example: Full Event Setup
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
function setupPlayerEvents(player, textChannel) {
|
|
166
|
+
player.on('trackStart', (track) => {
|
|
167
|
+
const embed = {
|
|
168
|
+
color: 0x00ff00,
|
|
169
|
+
title: track.isAutoplay ? 'Autoplay' : 'Now Playing',
|
|
170
|
+
description: `**${track.title}**\nby ${track.author}`,
|
|
171
|
+
thumbnail: { url: track.thumbnail }
|
|
172
|
+
};
|
|
173
|
+
textChannel.send({ embeds: [embed] });
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
player.on('trackError', (track, error) => {
|
|
177
|
+
textChannel.send(`Failed to play **${track.title}**: ${error.message}`);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
player.on('queueEnd', () => {
|
|
181
|
+
if (!player.autoplay.enabled) {
|
|
182
|
+
textChannel.send('Queue ended. Use `!autoplay` to keep the music going!');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
player.on('channelEmpty', () => {
|
|
187
|
+
textChannel.send('Channel empty. Leaving in 30 seconds...');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
player.on('autoPause', () => {
|
|
191
|
+
textChannel.send('Paused - everyone left the channel.');
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
player.on('autoResume', () => {
|
|
195
|
+
textChannel.send('Resumed - welcome back!');
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
player.on('destroy', () => {
|
|
199
|
+
textChannel.send('Disconnected.');
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Usage
|
|
204
|
+
const player = await manager.create(guildId, vcId, tcId);
|
|
205
|
+
setupPlayerEvents(player, textChannel);
|
|
206
|
+
```
|