aqualink 2.9.13 → 2.10.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/README.md +94 -58
- package/build/handlers/autoplay.js +39 -44
- package/build/structures/Aqua.js +437 -468
- package/build/structures/Connection.js +91 -88
- package/build/structures/Filters.js +178 -167
- package/build/structures/Node.js +99 -96
- package/build/structures/Player.js +275 -296
- package/build/structures/Rest.js +265 -146
- package/build/structures/Track.js +51 -126
- package/package.json +17 -2
|
@@ -1,130 +1,133 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const MODERN_ENDPOINT_REGEX = /^([a-z\-]+)-\d+\.discord\.media(?::\d+)?$/i
|
|
3
|
+
const ENDPOINT_REGEX = /^([a-z-]+)(?:-\d+\.discord\.media(?::\d+)?|\d+)/i
|
|
5
4
|
|
|
6
5
|
class Connection {
|
|
7
6
|
constructor(player) {
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.nodes = player.nodes
|
|
7
|
+
this._player = player
|
|
8
|
+
this._aqua = player.aqua
|
|
9
|
+
this._nodes = player.nodes
|
|
10
|
+
this._guildId = player.guildId
|
|
13
11
|
|
|
12
|
+
this.voiceChannel = player.voiceChannel
|
|
14
13
|
this.sessionId = null
|
|
15
14
|
this.endpoint = null
|
|
16
15
|
this.token = null
|
|
17
16
|
this.region = null
|
|
17
|
+
|
|
18
|
+
this.sequence = 0
|
|
19
|
+
this._lastEndpoint = null
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
_extractRegion(endpoint) {
|
|
23
|
+
const match = endpoint?.match(ENDPOINT_REGEX)
|
|
24
|
+
return match?.[1] || null
|
|
25
|
+
}
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
if (
|
|
27
|
+
setServerUpdate(data) {
|
|
28
|
+
if (!data?.endpoint || !data?.token) return
|
|
25
29
|
|
|
26
|
-
const
|
|
27
|
-
|
|
30
|
+
const newEndpoint = data.endpoint.trim()
|
|
31
|
+
const newRegion = this._extractRegion(newEndpoint)
|
|
32
|
+
const regionChanged = this.region !== newRegion
|
|
33
|
+
const endpointChanged = this._lastEndpoint !== newEndpoint
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
if (regionChanged || endpointChanged) {
|
|
36
|
+
if (regionChanged && this._aqua.listenerCount('debug') > 0) {
|
|
37
|
+
this._aqua.emit('debug', `[Player ${this._guildId}] Region: ${this.region || 'none'} → ${newRegion}`)
|
|
38
|
+
}
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
40
|
+
if (endpointChanged) {
|
|
41
|
+
this.sequence = 0
|
|
42
|
+
this._lastEndpoint = newEndpoint
|
|
43
|
+
}
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
this.endpoint = newEndpoint
|
|
46
|
+
this.region = newRegion
|
|
47
|
+
}
|
|
41
48
|
|
|
42
|
-
const oldRegion = this.region
|
|
43
|
-
this.endpoint = fullEndpoint
|
|
44
49
|
this.token = data.token
|
|
45
|
-
this.region = newRegion
|
|
46
50
|
|
|
47
|
-
this.
|
|
51
|
+
if (this._player.paused) {
|
|
52
|
+
this._player.paused = false
|
|
53
|
+
}
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
this._updatePlayerVoiceData()
|
|
55
|
+
this._updateVoiceData()
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
setStateUpdate(data) {
|
|
54
|
-
if (!data || data.user_id !== this.
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
this.voiceChannel =
|
|
65
|
-
|
|
59
|
+
if (!data || data.user_id !== this._aqua.clientId) return
|
|
60
|
+
|
|
61
|
+
const { session_id, channel_id, self_deaf, self_mute } = data
|
|
62
|
+
|
|
63
|
+
if (channel_id) {
|
|
64
|
+
if (this.voiceChannel !== channel_id) {
|
|
65
|
+
if (this._aqua.listenerCount('playerMove') > 0) {
|
|
66
|
+
this._aqua.emit('playerMove', this.voiceChannel, channel_id)
|
|
67
|
+
}
|
|
68
|
+
this.voiceChannel = channel_id
|
|
69
|
+
this._player.voiceChannel = channel_id
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (this.sessionId !== session_id) {
|
|
73
|
+
this.sessionId = session_id
|
|
66
74
|
}
|
|
67
75
|
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
70
|
-
this.
|
|
71
|
-
this.voiceChannel = channelId
|
|
76
|
+
this._player.self_deaf = !!self_deaf
|
|
77
|
+
this._player.self_mute = !!self_mute
|
|
78
|
+
this._player.connected = true
|
|
72
79
|
|
|
73
|
-
this.
|
|
74
|
-
this.player.connected = true
|
|
80
|
+
this._updateVoiceData()
|
|
75
81
|
} else {
|
|
76
|
-
this.
|
|
77
|
-
if (this.player) {
|
|
78
|
-
this._destroyPlayer()
|
|
79
|
-
this.voiceChannel = null;
|
|
80
|
-
this.player.voiceChannel = null;
|
|
81
|
-
this.aqua.emit('playerDestroy', this.player)
|
|
82
|
-
} else {
|
|
83
|
-
this.aqua.destroyPlayer(this.guildId)
|
|
84
|
-
this.voiceChannel = null;
|
|
85
|
-
this.player.voiceChannel = null;
|
|
86
|
-
this.aqua.emit('playerDestroy', this.player)
|
|
87
|
-
}
|
|
82
|
+
this._handleDisconnect()
|
|
88
83
|
}
|
|
89
84
|
}
|
|
90
85
|
|
|
91
|
-
|
|
92
|
-
this.
|
|
93
|
-
|
|
94
|
-
this.
|
|
86
|
+
_handleDisconnect() {
|
|
87
|
+
if (!this._player.connected) return
|
|
88
|
+
|
|
89
|
+
this._aqua.emit('debug', `[Player ${this._guildId}] Disconnected`)
|
|
90
|
+
|
|
91
|
+
this.voiceChannel = null
|
|
92
|
+
this.sessionId = null
|
|
93
|
+
this.sequence = 0
|
|
94
|
+
|
|
95
|
+
this._player.destroy()
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return
|
|
101
|
-
}
|
|
98
|
+
updateSequence(seq) {
|
|
99
|
+
this.sequence = seq > this.sequence ? seq : this.sequence
|
|
100
|
+
}
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
voice: {
|
|
110
|
-
token: this.token,
|
|
111
|
-
endpoint: this.endpoint,
|
|
112
|
-
sessionId: this.sessionId
|
|
113
|
-
},
|
|
114
|
-
volume: this.player.volume
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
} catch (error) {
|
|
118
|
-
this.aqua.emit('debug', 'updatePlayer', {
|
|
119
|
-
error: error.message,
|
|
120
|
-
guildId: this.guildId,
|
|
102
|
+
_updateVoiceData(isResume = false) {
|
|
103
|
+
if (!this.sessionId || !this.endpoint || !this.token) return
|
|
104
|
+
|
|
105
|
+
const payload = {
|
|
106
|
+
guildId: this._guildId,
|
|
107
|
+
data: {
|
|
121
108
|
voice: {
|
|
122
109
|
token: this.token,
|
|
123
110
|
endpoint: this.endpoint,
|
|
124
111
|
sessionId: this.sessionId
|
|
125
|
-
}
|
|
126
|
-
|
|
112
|
+
},
|
|
113
|
+
volume: this._player.volume
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (isResume) {
|
|
118
|
+
payload.data.voice.resume = true
|
|
119
|
+
payload.data.voice.sequence = this.sequence
|
|
127
120
|
}
|
|
121
|
+
|
|
122
|
+
setImmediate(() => {
|
|
123
|
+
try {
|
|
124
|
+
this._nodes.rest.updatePlayer(payload)
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (!error.message.includes('ECONNREFUSED')) {
|
|
127
|
+
this._aqua.emit('debug', `[Player ${this._guildId}] Update failed: ${error.message}`)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
})
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
|
|
@@ -1,171 +1,182 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
class Filters {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
4
|
+
static defaults = {
|
|
5
|
+
karaoke: { level: 1, monoLevel: 1, filterBand: 220, filterWidth: 100 },
|
|
6
|
+
timescale: { speed: 1, pitch: 1, rate: 1 },
|
|
7
|
+
tremolo: { frequency: 2, depth: 0.5 },
|
|
8
|
+
vibrato: { frequency: 2, depth: 0.5 },
|
|
9
|
+
rotation: { rotationHz: 0 },
|
|
10
|
+
distortion: { sinOffset: 0, sinScale: 1, cosOffset: 0, cosScale: 1, tanOffset: 0, tanScale: 1, offset: 0, scale: 1 },
|
|
11
|
+
channelMix: { leftToLeft: 1, leftToRight: 0, rightToLeft: 0, rightToRight: 1 },
|
|
12
|
+
lowPass: { smoothing: 20 }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
constructor(player, options = {}) {
|
|
16
|
+
this.player = player
|
|
17
|
+
this._pendingUpdate = false
|
|
18
|
+
|
|
19
|
+
this.filters = {
|
|
20
|
+
volume: options.volume ?? 1,
|
|
21
|
+
equalizer: options.equalizer ?? [],
|
|
22
|
+
karaoke: options.karaoke ?? null,
|
|
23
|
+
timescale: options.timescale ?? null,
|
|
24
|
+
tremolo: options.tremolo ?? null,
|
|
25
|
+
vibrato: options.vibrato ?? null,
|
|
26
|
+
rotation: options.rotation ?? null,
|
|
27
|
+
distortion: options.distortion ?? null,
|
|
28
|
+
channelMix: options.channelMix ?? null,
|
|
29
|
+
lowPass: options.lowPass ?? null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.presets = {
|
|
33
|
+
bassboost: options.bassboost ?? null,
|
|
34
|
+
slowmode: options.slowmode ?? null,
|
|
35
|
+
nightcore: options.nightcore ?? null,
|
|
36
|
+
vaporwave: options.vaporwave ?? null,
|
|
37
|
+
_8d: options._8d ?? null
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_setFilter(filterName, enabled, options = {}) {
|
|
42
|
+
const filter = enabled ? { ...Filters.defaults[filterName], ...options } : null
|
|
43
|
+
if (this.filters[filterName] === filter) return this
|
|
44
|
+
|
|
45
|
+
this.filters[filterName] = filter
|
|
46
|
+
return this._scheduleUpdate()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_scheduleUpdate() {
|
|
50
|
+
if (this._pendingUpdate) return this
|
|
51
|
+
this._pendingUpdate = true
|
|
52
|
+
|
|
53
|
+
queueMicrotask(() => {
|
|
54
|
+
this._pendingUpdate = false
|
|
55
|
+
this.updateFilters()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
return this
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setEqualizer(bands) {
|
|
62
|
+
if (this.filters.equalizer === bands) return this
|
|
63
|
+
this.filters.equalizer = bands || []
|
|
64
|
+
return this._scheduleUpdate()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
setKaraoke(enabled, options = {}) {
|
|
68
|
+
return this._setFilter('karaoke', enabled, options)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
setTimescale(enabled, options = {}) {
|
|
72
|
+
return this._setFilter('timescale', enabled, options)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setTremolo(enabled, options = {}) {
|
|
76
|
+
return this._setFilter('tremolo', enabled, options)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
setVibrato(enabled, options = {}) {
|
|
80
|
+
return this._setFilter('vibrato', enabled, options)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
setRotation(enabled, options = {}) {
|
|
84
|
+
return this._setFilter('rotation', enabled, options)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
setDistortion(enabled, options = {}) {
|
|
88
|
+
return this._setFilter('distortion', enabled, options)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setChannelMix(enabled, options = {}) {
|
|
92
|
+
return this._setFilter('channelMix', enabled, options)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
setLowPass(enabled, options = {}) {
|
|
96
|
+
return this._setFilter('lowPass', enabled, options)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
setBassboost(enabled, options = {}) {
|
|
100
|
+
if (!enabled) {
|
|
101
|
+
if (this.presets.bassboost === null) return this
|
|
102
|
+
this.presets.bassboost = null
|
|
103
|
+
return this.setEqualizer([])
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const value = options.value ?? 5
|
|
107
|
+
if (value < 0 || value > 5) throw new Error('Bassboost value must be between 0 and 5')
|
|
108
|
+
if (this.presets.bassboost === value) return this
|
|
109
|
+
|
|
110
|
+
this.presets.bassboost = value
|
|
111
|
+
const gain = (value - 1) * (1.25 / 9) - 0.25
|
|
112
|
+
const eq = Array(13).fill().map((_, band) => ({ band, gain }))
|
|
113
|
+
|
|
114
|
+
return this.setEqualizer(eq)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setSlowmode(enabled, options = {}) {
|
|
118
|
+
const rate = enabled ? options.rate ?? 0.8 : 1
|
|
119
|
+
if (this.presets.slowmode === enabled && this.filters.timescale?.rate === rate) return this
|
|
120
|
+
|
|
121
|
+
this.presets.slowmode = enabled
|
|
122
|
+
return this.setTimescale(enabled, { rate })
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
setNightcore(enabled, options = {}) {
|
|
126
|
+
const rate = enabled ? options.rate ?? 1.5 : 1
|
|
127
|
+
if (this.presets.nightcore === enabled && this.filters.timescale?.rate === rate) return this
|
|
128
|
+
|
|
129
|
+
this.presets.nightcore = enabled
|
|
130
|
+
return this.setTimescale(enabled, { rate })
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
setVaporwave(enabled, options = {}) {
|
|
134
|
+
const pitch = enabled ? options.pitch ?? 0.5 : 1
|
|
135
|
+
if (this.presets.vaporwave === enabled && this.filters.timescale?.pitch === pitch) return this
|
|
136
|
+
|
|
137
|
+
this.presets.vaporwave = enabled
|
|
138
|
+
return this.setTimescale(enabled, { pitch })
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
set8D(enabled, options = {}) {
|
|
142
|
+
const rotationHz = enabled ? options.rotationHz ?? 0.2 : 0
|
|
143
|
+
if (this.presets._8d === enabled && this.filters.rotation?.rotationHz === rotationHz) return this
|
|
144
|
+
|
|
145
|
+
this.presets._8d = enabled
|
|
146
|
+
return this.setRotation(enabled, { rotationHz })
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async clearFilters() {
|
|
150
|
+
let needsUpdate = false
|
|
151
|
+
|
|
152
|
+
// Reset filters
|
|
153
|
+
Object.keys(this.filters).forEach(key => {
|
|
154
|
+
const newValue = key === 'volume' ? 1 : key === 'equalizer' ? [] : null
|
|
155
|
+
if (this.filters[key] !== newValue) {
|
|
156
|
+
this.filters[key] = newValue
|
|
157
|
+
needsUpdate = true
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// Reset presets
|
|
162
|
+
Object.keys(this.presets).forEach(key => {
|
|
163
|
+
if (this.presets[key] !== null) {
|
|
164
|
+
this.presets[key] = null
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
if (!needsUpdate) return this
|
|
169
|
+
return this.updateFilters()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async updateFilters() {
|
|
173
|
+
await this.player.nodes.rest.updatePlayer({
|
|
174
|
+
guildId: this.player.guildId,
|
|
175
|
+
data: { filters: this.filters }
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
return this
|
|
179
|
+
}
|
|
169
180
|
}
|
|
170
181
|
|
|
171
|
-
module.exports = Filters
|
|
182
|
+
module.exports = Filters
|