magmastream 2.10.2-dev.1 → 2.10.2-dev.2

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.
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Rest = void 0;
4
- const tslib_1 = require("tslib");
5
- const axios_1 = tslib_1.__importDefault(require("axios"));
4
+ const undici_1 = require("undici");
6
5
  const Enums_1 = require("./Enums");
7
6
  const Utils_1 = require("./Utils");
8
7
  const MagmastreamError_1 = require("./MagmastreamError");
@@ -105,43 +104,43 @@ class Rest {
105
104
  */
106
105
  async request(method, endpoint, body) {
107
106
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] ${method} request to ${endpoint} with body: ${Utils_1.JSONUtils.safe(body, 2)}`);
108
- const config = {
109
- method,
110
- url: this.url + endpoint,
111
- headers: {
112
- "Content-Type": "application/json",
113
- Authorization: this.password,
114
- },
115
- data: body,
116
- timeout: this.node.options.apiRequestTimeoutMs,
117
- validateStatus: () => true,
118
- };
107
+ const controller = new AbortController();
108
+ const timeoutHandle = setTimeout(() => controller.abort(), this.node.options.apiRequestTimeoutMs);
119
109
  let response = null;
120
110
  try {
121
- response = await (0, axios_1.default)(config);
111
+ response = await (0, undici_1.fetch)(this.url + endpoint, {
112
+ method,
113
+ headers: {
114
+ "Content-Type": "application/json",
115
+ Authorization: this.password,
116
+ },
117
+ body: body !== undefined ? JSON.stringify(body) : undefined,
118
+ signal: controller.signal,
119
+ });
122
120
  }
123
121
  catch (e) {
124
- const isTimeout = axios_1.default.isAxiosError(e) && e.code === "ECONNABORTED";
122
+ const isTimeout = e instanceof Error && e.name === "AbortError";
125
123
  const message = e instanceof Error ? e.message : "Unknown error";
126
124
  const error = new MagmastreamError_1.MagmaStreamError({
127
125
  code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
128
126
  message: `${isTimeout ? "Timeout" : "Network error"} on ${method} ${endpoint}: ${message}`,
129
127
  });
130
- // Emit so the node manager can react (e.g. trigger reconnection logic)
131
128
  this.manager.emit(Enums_1.ManagerEventTypes.NodeError, this.node, error);
132
129
  return null;
133
130
  }
134
- const { status, data } = response;
131
+ finally {
132
+ clearTimeout(timeoutHandle);
133
+ }
134
+ const { status } = response;
135
+ const data = status !== 204 ? await response.json() : null;
135
136
  if (status >= 200 && status < 300) {
136
137
  return data;
137
138
  }
138
139
  if (status === 404) {
139
140
  if (data?.message === "Guild not found") {
140
- // Lavalink sometimes returns "Guild not found" for inactive players
141
141
  return [];
142
142
  }
143
143
  if (data?.message === "Session not found") {
144
- // Session expired — trigger reconnection instead of crashing
145
144
  this.manager.emit(Enums_1.ManagerEventTypes.NodeError, this.node, new MagmastreamError_1.MagmaStreamError({ code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED, message: "Session not found" }));
146
145
  return [];
147
146
  }
@@ -1237,6 +1237,32 @@ export interface ReverbOptions {
1237
1237
  roomSize?: number;
1238
1238
  damping?: number;
1239
1239
  }
1240
+ export interface LastFmResponse {
1241
+ error?: number;
1242
+ toptracks?: {
1243
+ track: Array<{
1244
+ name: string;
1245
+ artist: {
1246
+ name: string;
1247
+ };
1248
+ }>;
1249
+ };
1250
+ similartracks?: {
1251
+ track: Array<{
1252
+ name: string;
1253
+ artist: {
1254
+ name: string;
1255
+ };
1256
+ }>;
1257
+ };
1258
+ results?: {
1259
+ trackmatches?: {
1260
+ track: Array<{
1261
+ artist: string;
1262
+ }>;
1263
+ };
1264
+ };
1265
+ }
1240
1266
  /**
1241
1267
  * Queue interface
1242
1268
  */
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.JSONUtils = exports.Structure = exports.PlayerUtils = exports.AutoPlayUtils = exports.TrackUtils = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  /* eslint-disable @typescript-eslint/no-require-imports */
6
- const axios_1 = require("axios");
6
+ const undici_1 = require("undici");
7
7
  const jsdom_1 = require("jsdom");
8
8
  const Enums_1 = require("./Enums");
9
9
  const path_1 = tslib_1.__importDefault(require("path"));
@@ -250,11 +250,12 @@ class AutoPlayUtils {
250
250
  if (!title) {
251
251
  // No title provided, search for the artist's top tracks
252
252
  const noTitleUrl = `https://ws.audioscrobbler.com/2.0/?method=artist.getTopTracks&artist=${artist}&autocorrect=1&api_key=${apiKey}&format=json`;
253
- const response = await (0, axios_1.get)(noTitleUrl);
254
- if (response.data.error || !response.data.toptracks?.track?.length) {
253
+ const response = await (0, undici_1.fetch)(noTitleUrl);
254
+ const data = (await response.json());
255
+ if (data.error || !data.toptracks?.track?.length) {
255
256
  return [];
256
257
  }
257
- const randomTrack = response.data.toptracks.track[Math.floor(Math.random() * response.data.toptracks.track.length)];
258
+ const randomTrack = data.toptracks.track[Math.floor(Math.random() * data.toptracks.track.length)];
258
259
  const resolvedTracks = await this.resolveTracksFromQuery(`${randomTrack.artist.name} - ${randomTrack.name}`, this.manager.options.defaultSearchPlatform, track.requester);
259
260
  if (!resolvedTracks.length)
260
261
  return [];
@@ -263,8 +264,9 @@ class AutoPlayUtils {
263
264
  if (!artist) {
264
265
  // No artist provided, search for the track title
265
266
  const noArtistUrl = `https://ws.audioscrobbler.com/2.0/?method=track.search&track=${title}&api_key=${apiKey}&format=json`;
266
- const response = await (0, axios_1.get)(noArtistUrl);
267
- artist = response.data.results.trackmatches?.track?.[0]?.artist;
267
+ const response = await (0, undici_1.fetch)(noArtistUrl);
268
+ const noArtistData = (await response.json());
269
+ artist = noArtistData.results?.trackmatches?.track?.[0]?.artist;
268
270
  if (!artist) {
269
271
  return [];
270
272
  }
@@ -272,22 +274,24 @@ class AutoPlayUtils {
272
274
  }
273
275
  // Search for similar tracks to the current track
274
276
  const url = `https://ws.audioscrobbler.com/2.0/?method=track.getSimilar&artist=${artist}&track=${title}&limit=10&autocorrect=1&api_key=${apiKey}&format=json`;
275
- let response;
277
+ let similarData;
276
278
  try {
277
- response = await (0, axios_1.get)(url);
279
+ const response = await (0, undici_1.fetch)(url);
280
+ similarData = (await response.json());
278
281
  }
279
282
  catch (error) {
280
283
  console.error("[AutoPlay] Error fetching similar tracks from Last.fm:", error);
281
284
  return [];
282
285
  }
283
- if (response.data.error || !response.data.similartracks?.track?.length) {
286
+ if (similarData.error || !similarData.similartracks?.track?.length) {
284
287
  // Retry the request if the first attempt fails
285
288
  const retryUrl = `https://ws.audioscrobbler.com/2.0/?method=artist.getTopTracks&artist=${artist}&autocorrect=1&api_key=${apiKey}&format=json`;
286
- const retryResponse = await (0, axios_1.get)(retryUrl);
287
- if (retryResponse.data.error || !retryResponse.data.toptracks?.track?.length) {
289
+ const retryResponse = await (0, undici_1.fetch)(retryUrl);
290
+ const retryData = (await retryResponse.json());
291
+ if (retryData.error || !retryData.toptracks?.track?.length) {
288
292
  return [];
289
293
  }
290
- const randomTrack = retryResponse.data.toptracks.track[Math.floor(Math.random() * retryResponse.data.toptracks.track.length)];
294
+ const randomTrack = retryData.toptracks.track[Math.floor(Math.random() * retryData.toptracks.track.length)];
291
295
  const resolvedTracks = await this.resolveTracksFromQuery(`${randomTrack.artist.name} - ${randomTrack.name}`, this.manager.options.defaultSearchPlatform, track.requester);
292
296
  if (!resolvedTracks.length)
293
297
  return [];
@@ -297,7 +301,7 @@ class AutoPlayUtils {
297
301
  }
298
302
  return filteredTracks;
299
303
  }
300
- const randomTrack = response.data.similartracks.track.sort(() => Math.random() - 0.5).shift();
304
+ const randomTrack = similarData.similartracks.track.sort(() => Math.random() - 0.5).shift();
301
305
  if (!randomTrack) {
302
306
  return [];
303
307
  }
@@ -356,15 +360,21 @@ class AutoPlayUtils {
356
360
  return [];
357
361
  track = resolvedTrack;
358
362
  }
363
+ let html;
359
364
  try {
360
- const recommendedRes = await (0, axios_1.get)(`${track.uri}/recommended`).catch((err) => {
361
- console.error(`[AutoPlay] Failed to fetch SoundCloud recommendations. Status: ${err.response?.status || "Unknown"}`, err.message);
362
- return null;
363
- });
364
- if (!recommendedRes) {
365
+ let recommendedRes = null;
366
+ try {
367
+ recommendedRes = await (0, undici_1.fetch)(`${track.uri}/recommended`);
368
+ }
369
+ catch (err) {
370
+ console.error(`[AutoPlay] Failed to fetch SoundCloud recommendations.`, err);
371
+ return [];
372
+ }
373
+ if (!recommendedRes.ok) {
374
+ console.error(`[AutoPlay] Failed to fetch SoundCloud recommendations. Status: ${recommendedRes.status}`);
365
375
  return [];
366
376
  }
367
- const html = recommendedRes.data;
377
+ html = await recommendedRes.text();
368
378
  const dom = new jsdom_1.JSDOM(html);
369
379
  const window = dom.window;
370
380
  // Narrow the element types using instanceof
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magmastream",
3
- "version": "2.10.2-dev.1",
3
+ "version": "2.10.2-dev.2",
4
4
  "description": "A user-friendly Lavalink client designed for NodeJS.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -36,13 +36,13 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@discordjs/collection": "^2.1.1",
39
- "axios": "^1.13.6",
40
39
  "events": "^3.3.0",
41
40
  "ioredis": "^5.10.0",
42
41
  "jsdom": "^28.1.0",
43
42
  "lodash": "^4.17.23",
44
43
  "safe-stable-stringify": "^2.5.0",
45
44
  "tslib": "^2.8.1",
45
+ "undici": "7.24.6",
46
46
  "ws": "^8.19.0"
47
47
  },
48
48
  "optionalDependencies": {
@@ -53,9 +53,6 @@
53
53
  "oceanic.js": "1.14.x",
54
54
  "seyfert": "4.x"
55
55
  },
56
- "overrides": {
57
- "undici": "^7.0.0"
58
- },
59
56
  "engines": {
60
57
  "node": ">=20.19.0"
61
58
  },