aqualink 2.1.3 → 2.3.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 +31 -35
- package/build/handlers/autoplay.js +45 -15
- package/build/handlers/fetchImage.js +23 -30
- package/build/index.d.ts +255 -1211
- package/build/structures/Aqua.js +68 -70
- package/build/structures/Filters.js +127 -87
- package/build/structures/Node.js +207 -171
- package/build/structures/Player.js +122 -87
- package/build/structures/Rest.js +40 -44
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,50 +22,44 @@ This code is based in riffy, but its an 100% Rewrite made from scratch...
|
|
|
22
22
|
- https://github.com/topi314/LavaLyrics (RECOMMENDED)
|
|
23
23
|
- https://github.com/DRSchlaubi/lyrics.kt (?)
|
|
24
24
|
- https://github.com/DuncteBot/java-timed-lyrics (RECOMMENDED)
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Tralalero Tralala 2.3.0 Released
|
|
27
28
|
---
|
|
29
|
+
|
|
30
|
+
- now is ~21% more lightweight, reduced disk space
|
|
31
|
+
|
|
28
32
|
- Improved the `AQUA` module
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Faster
|
|
33
|
-
|
|
34
|
-
- Remade the `Connection` system
|
|
35
|
-
- Less overheard now.
|
|
36
|
-
- Faster connections
|
|
37
|
-
- Improved the checkings
|
|
38
|
-
- Improved error handling
|
|
39
|
-
- Fixed creating useless Objects and arrays
|
|
40
|
-
|
|
41
|
-
- Fully rewrite the `Node` system
|
|
42
|
-
- Way faster connections
|
|
43
|
-
- More stable (i think so)
|
|
44
|
-
- Faster events / messages / payloads handling
|
|
45
|
-
- Better stats handling (reusing, creating, destroyin)
|
|
46
|
-
- Some more bug fixes and stuff i forgot.
|
|
33
|
+
- 3x better cleanup system
|
|
34
|
+
- Fixed some memory leaks
|
|
35
|
+
- Improved long process support
|
|
36
|
+
- Faster node caching
|
|
47
37
|
|
|
48
38
|
- Remade the `Player` module
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- Rewrite to use direct comparasions
|
|
39
|
+
- Added circular buffer for previousTracks (way more memory efficient)
|
|
40
|
+
- Reorganized the event handlings
|
|
41
|
+
- Way better Memory management
|
|
53
42
|
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
43
|
+
- Rewrite the `Node` system
|
|
44
|
+
- Fixed an memory leak in connections
|
|
45
|
+
- Improved the overal speed
|
|
46
|
+
- Improved code readbility / modules
|
|
47
|
+
- improved cleanup System
|
|
48
|
+
- Better long runtime
|
|
49
|
+
- Rewrite the Filter system
|
|
58
50
|
|
|
59
|
-
- Improved `
|
|
60
|
-
-
|
|
61
|
-
-
|
|
51
|
+
- Improved `Rest` code
|
|
52
|
+
- Fixed lyrics (both search and get)
|
|
53
|
+
- Better chunks system for more performance
|
|
62
54
|
|
|
63
|
-
-
|
|
55
|
+
- Improved `fetchImage` speed and recourses
|
|
64
56
|
|
|
65
57
|
# Docs (Wiki)
|
|
66
|
-
- https://github.
|
|
58
|
+
- https://toddythenoobdud.github.io/aqualink.github.io/
|
|
59
|
+
|
|
60
|
+
- Example bot: https://github.com/ToddyTheNoobDud/Kenium-Music
|
|
67
61
|
|
|
68
|
-
-
|
|
62
|
+
- Discord support: https://discord.com/invite/K4CVv84VBC
|
|
69
63
|
|
|
70
64
|
|
|
71
65
|
# How to install
|
|
@@ -147,7 +141,9 @@ client.on("messageCreate", async (message) => {
|
|
|
147
141
|
|
|
148
142
|
if (resolve.loadType === 'playlist') {
|
|
149
143
|
await message.channel.send(`Added ${resolve.tracks.length} songs from ${resolve.playlistInfo.name} playlist.`);
|
|
150
|
-
|
|
144
|
+
for (const track of result.tracks) {
|
|
145
|
+
player.queue.add(track);
|
|
146
|
+
}
|
|
151
147
|
if (!player.playing && !player.paused) return player.play();
|
|
152
148
|
|
|
153
149
|
} else if (resolve.loadType === 'search' || resolve.loadType === 'track') {
|
|
@@ -3,15 +3,30 @@ const https = require('https');
|
|
|
3
3
|
function fetch(url, options = {}) {
|
|
4
4
|
return new Promise((resolve, reject) => {
|
|
5
5
|
const req = https.get(url, options, (res) => {
|
|
6
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
7
|
+
return fetch(res.headers.location, options).then(resolve).catch(reject);
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
if (res.statusCode !== 200) {
|
|
11
|
+
res.resume();
|
|
7
12
|
reject(new Error(`Request failed. Status code: ${res.statusCode}`));
|
|
8
13
|
return;
|
|
9
14
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
res.on('
|
|
15
|
+
|
|
16
|
+
const chunks = [];
|
|
17
|
+
res.on('data', chunk => chunks.push(chunk));
|
|
18
|
+
res.on('end', () => resolve(Buffer.concat(chunks).toString()));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
req.setTimeout(10000, () => {
|
|
22
|
+
req.destroy();
|
|
23
|
+
reject(new Error('Request timeout'));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
req.on('error', err => {
|
|
27
|
+
reject(err);
|
|
13
28
|
});
|
|
14
|
-
|
|
29
|
+
|
|
15
30
|
req.end();
|
|
16
31
|
});
|
|
17
32
|
}
|
|
@@ -20,15 +35,23 @@ async function scAutoPlay(url) {
|
|
|
20
35
|
try {
|
|
21
36
|
const html = await fetch(`${url}/recommended`);
|
|
22
37
|
|
|
23
|
-
const
|
|
38
|
+
const regex = /<a itemprop="url" href="(\/.*?)"/g;
|
|
39
|
+
const hrefs = new Set();
|
|
40
|
+
let match;
|
|
24
41
|
|
|
25
|
-
|
|
42
|
+
while ((match = regex.exec(html)) !== null) {
|
|
43
|
+
hrefs.add(`https://soundcloud.com${match[1]}`);
|
|
44
|
+
}
|
|
26
45
|
|
|
27
|
-
if (hrefs.
|
|
46
|
+
if (hrefs.size === 0) {
|
|
28
47
|
throw new Error("No recommended tracks found on SoundCloud.");
|
|
29
48
|
}
|
|
30
49
|
|
|
31
|
-
const shuffledHrefs =
|
|
50
|
+
const shuffledHrefs = Array.from(hrefs);
|
|
51
|
+
for (let i = shuffledHrefs.length - 1; i > 0; i--) {
|
|
52
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
53
|
+
[shuffledHrefs[i], shuffledHrefs[j]] = [shuffledHrefs[j], shuffledHrefs[i]];
|
|
54
|
+
}
|
|
32
55
|
|
|
33
56
|
return shuffledHrefs;
|
|
34
57
|
} catch (error) {
|
|
@@ -40,21 +63,28 @@ async function scAutoPlay(url) {
|
|
|
40
63
|
async function spAutoPlay(track_id) {
|
|
41
64
|
try {
|
|
42
65
|
const tokenResponse = await fetch("https://open.spotify.com/get_access_token?reason=transport&productType=embed");
|
|
43
|
-
const
|
|
66
|
+
const tokenData = JSON.parse(tokenResponse);
|
|
67
|
+
const accessToken = tokenData?.accessToken;
|
|
44
68
|
|
|
45
69
|
if (!accessToken) throw new Error("Failed to retrieve Spotify access token");
|
|
46
70
|
|
|
47
|
-
const recommendationsResponse = await fetch(
|
|
48
|
-
|
|
49
|
-
|
|
71
|
+
const recommendationsResponse = await fetch(
|
|
72
|
+
`https://api.spotify.com/v1/recommendations?limit=5&seed_tracks=${track_id}&fields=tracks.id`,
|
|
73
|
+
{
|
|
74
|
+
headers: {
|
|
75
|
+
Authorization: `Bearer ${accessToken}`,
|
|
76
|
+
'Content-Type': 'application/json'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
);
|
|
50
80
|
|
|
51
|
-
const
|
|
81
|
+
const data = JSON.parse(recommendationsResponse);
|
|
82
|
+
const tracks = data?.tracks || [];
|
|
52
83
|
|
|
53
|
-
if (
|
|
84
|
+
if (tracks.length === 0) {
|
|
54
85
|
throw new Error("No recommended tracks found on Spotify.");
|
|
55
86
|
}
|
|
56
87
|
|
|
57
|
-
// Return a random track ID
|
|
58
88
|
return tracks[Math.floor(Math.random() * tracks.length)].id;
|
|
59
89
|
} catch (error) {
|
|
60
90
|
console.error("Error fetching Spotify recommendations:", error);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
const
|
|
1
|
+
const https = require('https');
|
|
2
2
|
const sourceHandlers = new Map([
|
|
3
3
|
['spotify', uri => fetchThumbnail(`https://open.spotify.com/oembed?url=${uri}`)],
|
|
4
4
|
['youtube', identifier => fetchYouTubeThumbnail(identifier)]
|
|
5
5
|
]);
|
|
6
6
|
const YOUTUBE_URL_TEMPLATE = (quality) => (id) => `https://img.youtube.com/vi/${id}/${quality}.jpg`;
|
|
7
7
|
const YOUTUBE_QUALITIES = ['maxresdefault', 'hqdefault', 'mqdefault', 'default'].map(YOUTUBE_URL_TEMPLATE);
|
|
8
|
+
|
|
8
9
|
async function getImageUrl(info) {
|
|
9
10
|
if (!info?.sourceName || !info?.uri) return null;
|
|
10
11
|
const handler = sourceHandlers.get(info.sourceName.toLowerCase());
|
|
@@ -16,42 +17,34 @@ async function getImageUrl(info) {
|
|
|
16
17
|
return null;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
|
|
19
21
|
function fetchThumbnail(url) {
|
|
20
22
|
return new Promise((resolve, reject) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
let data = '';
|
|
26
|
-
|
|
27
|
-
req.on('response', (headers, flags) => {
|
|
28
|
-
if (headers[':status'] !== 200) {
|
|
29
|
-
return reject(`Failed to fetch: ${headers[':status']}`);
|
|
23
|
+
https.get(url, (res) => {
|
|
24
|
+
if (res.statusCode !== 200) {
|
|
25
|
+
res.resume();
|
|
26
|
+
return reject(`Failed to fetch: ${res.statusCode}`);
|
|
30
27
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
client.close();
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
req.on('error', (error) => {
|
|
28
|
+
let data = '';
|
|
29
|
+
res.on('data', chunk => data += chunk);
|
|
30
|
+
res.on('end', () => {
|
|
31
|
+
try {
|
|
32
|
+
const json = JSON.parse(data);
|
|
33
|
+
resolve(json.thumbnail_url || null);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
reject(`JSON parse error: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}).on('error', (error) => {
|
|
46
39
|
reject(`Request error: ${error.message}`);
|
|
47
|
-
client.close();
|
|
48
40
|
});
|
|
49
|
-
req.end();
|
|
50
41
|
});
|
|
51
42
|
}
|
|
43
|
+
|
|
52
44
|
async function fetchYouTubeThumbnail(identifier) {
|
|
53
45
|
const promises = YOUTUBE_QUALITIES.map(urlFunc => fetchThumbnail(urlFunc(identifier)));
|
|
54
|
-
const
|
|
55
|
-
return
|
|
46
|
+
const firstResult = await Promise.race(promises);
|
|
47
|
+
return firstResult || null;
|
|
56
48
|
}
|
|
57
|
-
|
|
49
|
+
|
|
50
|
+
module.exports = { getImageUrl };
|