magmastream 2.6.0-beta.8 → 2.6.1
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 +1 -0
- package/dist/index.d.ts +44 -7
- package/dist/structures/Manager.js +28 -9
- package/dist/structures/Node.js +102 -61
- package/dist/structures/Player.js +29 -23
- package/dist/structures/Queue.js +13 -13
- package/dist/utils/managerCheck.js +27 -17
- package/dist/utils/nodeCheck.js +1 -1
- package/dist/utils/playerCheck.js +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ Also you can join the [Discord Support Server](https://discord.com/invite/HV59Z3
|
|
|
44
44
|
| [Lunio](https://discord.com/api/oauth2/authorize?client_id=945030475779551415&permissions=61991952&scope=bot+applications.commands) | vexi |
|
|
45
45
|
| [JukeDisc](https://discord.com/oauth2/authorize?client_id=1109751797549105176&permissions=968552214080&scope=bot+applications.commands) | Theo |
|
|
46
46
|
| [Cool Music](https://discord.com/oauth2/authorize?client_id=923529398425096193&permissions=12888394808&redirect_uri=https%3A%2F%2Fdiscord.gg%2Fcool-music-support-925619107460698202&response_type=code&scope=bot%20identify%20applications.commands) | Itz Random |
|
|
47
|
+
| [Soundy](https://dsc.gg/sndy) | iaMJ |
|
|
47
48
|
|
|
48
49
|
If you want to add your own bot create a pull request with your bot added. Please add your full name.
|
|
49
50
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { Message, User, ClientUser } from 'discord.js';
|
|
3
2
|
import WebSocket from 'ws';
|
|
4
3
|
import { Collection } from '@discordjs/collection';
|
|
@@ -203,6 +202,8 @@ declare class Player {
|
|
|
203
202
|
manager: Manager;
|
|
204
203
|
/** The autoplay state of the player. */
|
|
205
204
|
isAutoplay: boolean;
|
|
205
|
+
/** The number of times to try autoplay before emitting queueEnd. */
|
|
206
|
+
autoplayTries: number;
|
|
206
207
|
private static _manager;
|
|
207
208
|
private readonly data;
|
|
208
209
|
private dynamicLoopInterval;
|
|
@@ -271,7 +272,7 @@ declare class Player {
|
|
|
271
272
|
* @param autoplayState
|
|
272
273
|
* @param botUser
|
|
273
274
|
*/
|
|
274
|
-
setAutoplay(autoplayState: boolean, botUser: object): this;
|
|
275
|
+
setAutoplay(autoplayState: boolean, botUser: object, tries?: number): this;
|
|
275
276
|
/**
|
|
276
277
|
* Gets recommended tracks and returns an array of tracks.
|
|
277
278
|
* @param track
|
|
@@ -527,7 +528,6 @@ declare class Node {
|
|
|
527
528
|
extractSpotifyTrackID(url: string): string | null;
|
|
528
529
|
extractSpotifyArtistID(url: string): string | null;
|
|
529
530
|
private handleAutoplay;
|
|
530
|
-
private handleSpotifyAutoplay;
|
|
531
531
|
private handleFailedTrack;
|
|
532
532
|
private handleRepeatedTrack;
|
|
533
533
|
private playNextTrack;
|
|
@@ -912,9 +912,9 @@ declare class Manager extends EventEmitter {
|
|
|
912
912
|
constructor(options: ManagerOptions);
|
|
913
913
|
/**
|
|
914
914
|
* Initiates the Manager.
|
|
915
|
-
* @param clientId
|
|
915
|
+
* @param clientId - The Discord client ID (required).
|
|
916
916
|
*/
|
|
917
|
-
init(clientId
|
|
917
|
+
init(clientId: string): this;
|
|
918
918
|
/**
|
|
919
919
|
* Searches the enabled sources based off the URL or the `source` property.
|
|
920
920
|
* @param query
|
|
@@ -997,6 +997,11 @@ interface ManagerOptions {
|
|
|
997
997
|
defaultSearchPlatform?: SearchPlatform;
|
|
998
998
|
/** Whether the YouTube video titles should be replaced if the Author does not exactly match. */
|
|
999
999
|
replaceYouTubeCredentials?: boolean;
|
|
1000
|
+
/** The last.fm API key.
|
|
1001
|
+
* If you need to create one go here: https://www.last.fm/api/account/create.
|
|
1002
|
+
* If you already have one, get it from here: https://www.last.fm/api/accounts.
|
|
1003
|
+
*/
|
|
1004
|
+
lastFmApiKey: string;
|
|
1000
1005
|
/**
|
|
1001
1006
|
* Function to send data to the websocket.
|
|
1002
1007
|
* @param id
|
|
@@ -1004,7 +1009,23 @@ interface ManagerOptions {
|
|
|
1004
1009
|
*/
|
|
1005
1010
|
send(id: string, payload: Payload): void;
|
|
1006
1011
|
}
|
|
1007
|
-
|
|
1012
|
+
declare const UseNodeOptions: {
|
|
1013
|
+
readonly leastLoad: "leastLoad";
|
|
1014
|
+
readonly leastPlayers: "leastPlayers";
|
|
1015
|
+
};
|
|
1016
|
+
type UseNodeOption = keyof typeof UseNodeOptions;
|
|
1017
|
+
declare const SearchPlatforms: {
|
|
1018
|
+
readonly deezer: "deezer";
|
|
1019
|
+
readonly soundcloud: "soundcloud";
|
|
1020
|
+
readonly "youtube music": "youtube music";
|
|
1021
|
+
readonly youtube: "youtube";
|
|
1022
|
+
readonly spotify: "spotify";
|
|
1023
|
+
readonly jiosaavn: "jiosaavn";
|
|
1024
|
+
readonly tidal: "tidal";
|
|
1025
|
+
readonly applemusic: "applemusic";
|
|
1026
|
+
readonly bandcamp: "bandcamp";
|
|
1027
|
+
};
|
|
1028
|
+
type SearchPlatform = keyof typeof SearchPlatforms;
|
|
1008
1029
|
type PlayerStateEventType = "connectionChange" | "playerCreate" | "playerDestroy" | "channelChange" | "volumeChange" | "pauseChange" | "queueChange" | "trackChange" | "repeatChange" | "autoplayChange";
|
|
1009
1030
|
interface SearchQuery {
|
|
1010
1031
|
/** The source to search from. */
|
|
@@ -1034,9 +1055,25 @@ interface PlaylistRawData {
|
|
|
1034
1055
|
/** The tracks of the playlist */
|
|
1035
1056
|
tracks: TrackData[];
|
|
1036
1057
|
}
|
|
1058
|
+
interface PlaylistInfoData {
|
|
1059
|
+
/** Url to playlist. */
|
|
1060
|
+
url: string;
|
|
1061
|
+
/** Type is always playlist in that case. */
|
|
1062
|
+
type: string;
|
|
1063
|
+
/** ArtworkUrl of playlist */
|
|
1064
|
+
artworkUrl: string;
|
|
1065
|
+
/** Number of total tracks in playlist */
|
|
1066
|
+
totalTracks: number;
|
|
1067
|
+
/** Author of playlist */
|
|
1068
|
+
author: string;
|
|
1069
|
+
}
|
|
1037
1070
|
interface PlaylistData {
|
|
1038
1071
|
/** The playlist name. */
|
|
1039
1072
|
name: string;
|
|
1073
|
+
/** Requester of playlist. */
|
|
1074
|
+
requester: User | ClientUser;
|
|
1075
|
+
/** More playlist information. */
|
|
1076
|
+
playlistInfo: PlaylistInfoData[];
|
|
1040
1077
|
/** The length of the playlist. */
|
|
1041
1078
|
duration: number;
|
|
1042
1079
|
/** The songs of the playlist. */
|
|
@@ -1071,4 +1108,4 @@ interface ManagerEvents {
|
|
|
1071
1108
|
chaptersLoaded: [player: Player, track: Track | UnresolvedTrack, payload: SponsorBlockChaptersLoaded];
|
|
1072
1109
|
}
|
|
1073
1110
|
|
|
1074
|
-
export { type CPUStats, type EqualizerBand, type Exception, type Extendable, type FrameStats, type LavalinkInfo, type LavalinkResponse, type LoadType, Manager, type ManagerEvents, type ManagerOptions, type MemoryStats, Node, type NodeMessage, type NodeOptions, type NodeStats, type Payload, type PlayOptions, Player, type PlayerEvent, type PlayerEventType, type PlayerEvents, type PlayerOptions, type PlayerStateEventType, type PlayerUpdate, type PlaylistData, type PlaylistRawData, Plugin, Queue, type SearchPlatform, type SearchQuery, type SearchResult, type Severity, type Sizes, type SponsorBlockChapterStarted, type SponsorBlockChaptersLoaded, type SponsorBlockSegment, type SponsorBlockSegmentEventType, type SponsorBlockSegmentEvents, type SponsorBlockSegmentSkipped, type SponsorBlockSegmentsLoaded, type State, Structure, type Track, type TrackData, type TrackDataInfo, type TrackEndEvent, type TrackEndReason, type TrackExceptionEvent, type TrackPluginInfo, type TrackSourceName, type TrackStartEvent, type TrackStuckEvent, TrackUtils, type UnresolvedQuery, type UnresolvedTrack, type VoicePacket, type VoiceServer, type VoiceState, type WebSocketClosedEvent, validSponsorBlocks };
|
|
1111
|
+
export { type CPUStats, type EqualizerBand, type Exception, type Extendable, type FrameStats, type LavalinkInfo, type LavalinkResponse, type LoadType, Manager, type ManagerEvents, type ManagerOptions, type MemoryStats, Node, type NodeMessage, type NodeOptions, type NodeStats, type Payload, type PlayOptions, Player, type PlayerEvent, type PlayerEventType, type PlayerEvents, type PlayerOptions, type PlayerStateEventType, type PlayerUpdate, type PlaylistData, type PlaylistInfoData, type PlaylistRawData, Plugin, Queue, type SearchPlatform, SearchPlatforms, type SearchQuery, type SearchResult, type Severity, type Sizes, type SponsorBlockChapterStarted, type SponsorBlockChaptersLoaded, type SponsorBlockSegment, type SponsorBlockSegmentEventType, type SponsorBlockSegmentEvents, type SponsorBlockSegmentSkipped, type SponsorBlockSegmentsLoaded, type State, Structure, type Track, type TrackData, type TrackDataInfo, type TrackEndEvent, type TrackEndReason, type TrackExceptionEvent, type TrackPluginInfo, type TrackSourceName, type TrackStartEvent, type TrackStuckEvent, TrackUtils, type UnresolvedQuery, type UnresolvedTrack, type UseNodeOption, UseNodeOptions, type VoicePacket, type VoiceServer, type VoiceState, type WebSocketClosedEvent, validSponsorBlocks };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Manager = void 0;
|
|
3
|
+
exports.SearchPlatforms = exports.UseNodeOptions = exports.Manager = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
/* eslint-disable no-async-promise-executor */
|
|
6
6
|
const Utils_1 = require("./Utils");
|
|
@@ -337,17 +337,19 @@ class Manager extends events_1.EventEmitter {
|
|
|
337
337
|
}
|
|
338
338
|
/**
|
|
339
339
|
* Initiates the Manager.
|
|
340
|
-
* @param clientId
|
|
340
|
+
* @param clientId - The Discord client ID (required).
|
|
341
341
|
*/
|
|
342
342
|
init(clientId) {
|
|
343
|
-
if (this.initiated)
|
|
343
|
+
if (this.initiated) {
|
|
344
344
|
return this;
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (typeof
|
|
348
|
-
throw new Error('"clientId"
|
|
349
|
-
|
|
350
|
-
|
|
345
|
+
}
|
|
346
|
+
// Validate clientId
|
|
347
|
+
if (typeof clientId !== "string" || !/^\d+$/.test(clientId)) {
|
|
348
|
+
throw new Error('"clientId" must be a valid Discord client ID.');
|
|
349
|
+
}
|
|
350
|
+
// Set the validated clientId
|
|
351
|
+
this.options.clientId = clientId;
|
|
352
|
+
// Attempt to connect nodes
|
|
351
353
|
for (const node of this.nodes.values()) {
|
|
352
354
|
try {
|
|
353
355
|
node.connect();
|
|
@@ -400,6 +402,8 @@ class Manager extends events_1.EventEmitter {
|
|
|
400
402
|
if (res.loadType === "playlist") {
|
|
401
403
|
playlist = {
|
|
402
404
|
name: playlistData.info.name,
|
|
405
|
+
playlistInfo: playlistData.pluginInfo,
|
|
406
|
+
requester: requester,
|
|
403
407
|
tracks: playlistData.tracks.map((track) => Utils_1.TrackUtils.build(track, requester)),
|
|
404
408
|
duration: playlistData.tracks.reduce((acc, cur) => acc + (cur.info.length || 0), 0),
|
|
405
409
|
};
|
|
@@ -610,3 +614,18 @@ class Manager extends events_1.EventEmitter {
|
|
|
610
614
|
}
|
|
611
615
|
}
|
|
612
616
|
exports.Manager = Manager;
|
|
617
|
+
exports.UseNodeOptions = {
|
|
618
|
+
leastLoad: "leastLoad",
|
|
619
|
+
leastPlayers: "leastPlayers",
|
|
620
|
+
};
|
|
621
|
+
exports.SearchPlatforms = {
|
|
622
|
+
deezer: "deezer",
|
|
623
|
+
soundcloud: "soundcloud",
|
|
624
|
+
"youtube music": "youtube music",
|
|
625
|
+
youtube: "youtube",
|
|
626
|
+
spotify: "spotify",
|
|
627
|
+
jiosaavn: "jiosaavn",
|
|
628
|
+
tidal: "tidal",
|
|
629
|
+
applemusic: "applemusic",
|
|
630
|
+
bandcamp: "bandcamp",
|
|
631
|
+
};
|
package/dist/structures/Node.js
CHANGED
|
@@ -8,6 +8,7 @@ const nodeCheck_1 = tslib_1.__importDefault(require("../utils/nodeCheck"));
|
|
|
8
8
|
const ws_1 = tslib_1.__importDefault(require("ws"));
|
|
9
9
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
10
10
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
11
|
+
const axios_1 = tslib_1.__importDefault(require("axios"));
|
|
11
12
|
exports.validSponsorBlocks = ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic", "filler"];
|
|
12
13
|
const sessionIdsFilePath = path_1.default.join(process.cwd(), "node_modules", "magmastream", "dist", "sessionData", "sessionIds.json");
|
|
13
14
|
let sessionIdsMap = new Map();
|
|
@@ -367,72 +368,103 @@ class Node {
|
|
|
367
368
|
return match ? match[1] : null;
|
|
368
369
|
}
|
|
369
370
|
// Handle autoplay
|
|
370
|
-
async handleAutoplay(player, track) {
|
|
371
|
+
async handleAutoplay(player, track, attempt = 0) {
|
|
372
|
+
if (!player.isAutoplay || attempt === player.autoplayTries || !player.queue.previous)
|
|
373
|
+
return false;
|
|
371
374
|
const previousTrack = player.queue.previous;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
375
|
+
const apiKey = this.manager.options.lastFmApiKey;
|
|
376
|
+
// If Last.fm API is not available and YouTube is not supported
|
|
377
|
+
if (!apiKey && !this.info.sourceManagers.includes("youtube"))
|
|
378
|
+
return false;
|
|
379
|
+
// Handle YouTube autoplay logic
|
|
380
|
+
if ((!apiKey && this.info.sourceManagers.includes("youtube")) ||
|
|
381
|
+
(attempt === player.autoplayTries - 1 && !(apiKey && player.autoplayTries === 1) && this.info.sourceManagers.includes("youtube"))) {
|
|
382
|
+
const hasYouTubeURL = ["youtube.com", "youtu.be"].some((url) => previousTrack.uri.includes(url));
|
|
383
|
+
const videoID = hasYouTubeURL
|
|
384
|
+
? previousTrack.uri.split("=").pop()
|
|
385
|
+
: (await player.search(`${previousTrack.author} - ${previousTrack.title}`, player.get("Internal_BotUser"))).tracks[0]?.uri.split("=").pop();
|
|
386
|
+
if (!videoID)
|
|
387
|
+
return false;
|
|
388
|
+
let randomIndex;
|
|
389
|
+
let searchURI;
|
|
390
|
+
do {
|
|
391
|
+
randomIndex = Math.floor(Math.random() * 23) + 2;
|
|
392
|
+
searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
|
|
393
|
+
} while (track.uri.includes(searchURI));
|
|
394
|
+
const res = await player.search(searchURI, player.get("Internal_BotUser"));
|
|
395
|
+
if (res.loadType === "empty" || res.loadType === "error")
|
|
396
|
+
return false;
|
|
397
|
+
const foundTrack = res.tracks.find((t) => t.uri !== track.uri && t.author !== track.author && t.title !== track.title);
|
|
398
|
+
if (!foundTrack)
|
|
399
|
+
return false;
|
|
400
|
+
player.queue.add(foundTrack);
|
|
401
|
+
player.play();
|
|
402
|
+
return true;
|
|
379
403
|
}
|
|
380
|
-
|
|
381
|
-
let
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
404
|
+
// Handle Last.fm-based autoplay logic
|
|
405
|
+
let { author: artist } = previousTrack;
|
|
406
|
+
const { title, uri } = previousTrack;
|
|
407
|
+
const enabledSources = this.info.sourceManagers;
|
|
408
|
+
const isSpotifyEnabled = enabledSources.includes("spotify");
|
|
409
|
+
const isSpotifyUri = uri.includes("spotify.com");
|
|
410
|
+
let selectedSource = null;
|
|
411
|
+
if (isSpotifyEnabled && isSpotifyUri) {
|
|
412
|
+
selectedSource = "spotify";
|
|
385
413
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
414
|
+
else {
|
|
415
|
+
selectedSource = this.manager.options.defaultSearchPlatform;
|
|
416
|
+
}
|
|
417
|
+
if (!artist || !title) {
|
|
418
|
+
if (!title) {
|
|
419
|
+
const noTitleUrl = `https://ws.audioscrobbler.com/2.0/?method=artist.getTopTracks&artist=${artist}&autocorrect=1&api_key=${apiKey}&format=json`;
|
|
420
|
+
const response = await axios_1.default.get(noTitleUrl);
|
|
421
|
+
if (response.data.error || !response.data.toptracks?.track?.length)
|
|
422
|
+
return false;
|
|
423
|
+
const randomTrack = response.data.toptracks.track[Math.floor(Math.random() * response.data.toptracks.track.length)];
|
|
424
|
+
const res = await player.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: selectedSource }, player.get("Internal_BotUser"));
|
|
425
|
+
if (res.loadType === "empty" || res.loadType === "error")
|
|
426
|
+
return false;
|
|
427
|
+
const foundTrack = res.tracks.find((t) => t.uri !== track.uri);
|
|
428
|
+
if (!foundTrack)
|
|
429
|
+
return false;
|
|
430
|
+
player.queue.add(foundTrack);
|
|
431
|
+
player.play();
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
else if (!artist) {
|
|
435
|
+
const noArtistUrl = `https://ws.audioscrobbler.com/2.0/?method=track.search&track=${title}&api_key=${apiKey}&format=json`;
|
|
436
|
+
const response = await axios_1.default.get(noArtistUrl);
|
|
437
|
+
artist = response.data.results.trackmatches?.track?.[0]?.artist;
|
|
438
|
+
if (!artist)
|
|
439
|
+
return false;
|
|
408
440
|
}
|
|
409
441
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
442
|
+
const url = `https://ws.audioscrobbler.com/2.0/?method=track.getSimilar&artist=${artist}&track=${title}&limit=10&autocorrect=1&api_key=${apiKey}&format=json`;
|
|
443
|
+
const response = await axios_1.default.get(url);
|
|
444
|
+
if (response.data.error || !response.data.similartracks?.track?.length) {
|
|
445
|
+
const retryUrl = `https://ws.audioscrobbler.com/2.0/?method=artist.getTopTracks&artist=${artist}&autocorrect=1&api_key=${apiKey}&format=json`;
|
|
446
|
+
const retryResponse = await axios_1.default.get(retryUrl);
|
|
447
|
+
if (retryResponse.data.error || !retryResponse.data.toptracks?.track?.length)
|
|
448
|
+
return false;
|
|
449
|
+
const randomTrack = retryResponse.data.toptracks.track[Math.floor(Math.random() * retryResponse.data.toptracks.track.length)];
|
|
450
|
+
const res = await player.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: selectedSource }, player.get("Internal_BotUser"));
|
|
451
|
+
if (res.loadType === "empty" || res.loadType === "error")
|
|
452
|
+
return false;
|
|
453
|
+
const foundTrack = res.tracks.find((t) => t.uri !== track.uri);
|
|
454
|
+
if (!foundTrack)
|
|
455
|
+
return false;
|
|
456
|
+
player.queue.add(foundTrack);
|
|
457
|
+
player.play();
|
|
458
|
+
return true;
|
|
425
459
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
if (recommendedResult.loadType !== "playlist")
|
|
460
|
+
const randomTrack = response.data.similartracks.track[Math.floor(Math.random() * response.data.similartracks.track.length)];
|
|
461
|
+
const res = await player.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: selectedSource }, player.get("Internal_BotUser"));
|
|
462
|
+
if (res.loadType === "empty" || res.loadType === "error")
|
|
430
463
|
return false;
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
if (!recommendedTrack)
|
|
464
|
+
const foundTrack = res.tracks.find((t) => t.uri !== track.uri);
|
|
465
|
+
if (!foundTrack)
|
|
434
466
|
return false;
|
|
435
|
-
player.queue.add(
|
|
467
|
+
player.queue.add(foundTrack);
|
|
436
468
|
player.play();
|
|
437
469
|
return true;
|
|
438
470
|
}
|
|
@@ -480,13 +512,22 @@ class Node {
|
|
|
480
512
|
player.queue.previous = player.queue.current;
|
|
481
513
|
player.queue.current = null;
|
|
482
514
|
if (!player.isAutoplay) {
|
|
483
|
-
player.queue.previous = player.queue.current;
|
|
484
|
-
player.queue.current = null;
|
|
485
515
|
player.playing = false;
|
|
486
516
|
this.manager.emit("queueEnd", player, track, payload);
|
|
487
517
|
return;
|
|
488
518
|
}
|
|
489
|
-
|
|
519
|
+
let attempts = 1;
|
|
520
|
+
let success = false;
|
|
521
|
+
while (attempts <= player.autoplayTries) {
|
|
522
|
+
success = await this.handleAutoplay(player, track, attempts);
|
|
523
|
+
if (success)
|
|
524
|
+
return;
|
|
525
|
+
attempts++;
|
|
526
|
+
}
|
|
527
|
+
// If all attempts fail, reset the player state and emit queueEnd
|
|
528
|
+
player.queue.previous = null;
|
|
529
|
+
player.playing = false;
|
|
530
|
+
this.manager.emit("queueEnd", player, track, payload);
|
|
490
531
|
}
|
|
491
532
|
trackStuck(player, track, payload) {
|
|
492
533
|
player.stop();
|
|
@@ -47,6 +47,8 @@ class Player {
|
|
|
47
47
|
manager;
|
|
48
48
|
/** The autoplay state of the player. */
|
|
49
49
|
isAutoplay = false;
|
|
50
|
+
/** The number of times to try autoplay before emitting queueEnd. */
|
|
51
|
+
autoplayTries = 3;
|
|
50
52
|
static _manager;
|
|
51
53
|
data = {};
|
|
52
54
|
dynamicLoopInterval;
|
|
@@ -116,7 +118,7 @@ class Player {
|
|
|
116
118
|
if (!this.voiceChannel)
|
|
117
119
|
throw new RangeError("No voice channel has been set.");
|
|
118
120
|
this.state = "CONNECTING";
|
|
119
|
-
const oldPlayer = { ...this };
|
|
121
|
+
const oldPlayer = this ? { ...this } : null;
|
|
120
122
|
this.manager.options.send(this.guild, {
|
|
121
123
|
op: 4,
|
|
122
124
|
d: {
|
|
@@ -135,7 +137,7 @@ class Player {
|
|
|
135
137
|
if (this.voiceChannel === null)
|
|
136
138
|
return this;
|
|
137
139
|
this.state = "DISCONNECTING";
|
|
138
|
-
const oldPlayer = { ...this };
|
|
140
|
+
const oldPlayer = this ? { ...this } : null;
|
|
139
141
|
this.pause(true);
|
|
140
142
|
this.manager.options.send(this.guild, {
|
|
141
143
|
op: 4,
|
|
@@ -153,7 +155,7 @@ class Player {
|
|
|
153
155
|
}
|
|
154
156
|
/** Destroys the player. */
|
|
155
157
|
destroy(disconnect = true) {
|
|
156
|
-
const oldPlayer = { ...this };
|
|
158
|
+
const oldPlayer = this ? { ...this } : null;
|
|
157
159
|
this.state = "DESTROYING";
|
|
158
160
|
if (disconnect) {
|
|
159
161
|
this.disconnect();
|
|
@@ -170,10 +172,10 @@ class Player {
|
|
|
170
172
|
setVoiceChannel(channel) {
|
|
171
173
|
if (typeof channel !== "string")
|
|
172
174
|
throw new TypeError("Channel must be a non-empty string.");
|
|
173
|
-
const oldPlayer = { ...this };
|
|
175
|
+
const oldPlayer = this ? { ...this } : null;
|
|
174
176
|
this.voiceChannel = channel;
|
|
175
177
|
this.connect();
|
|
176
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
178
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "voiceChannelChange");
|
|
177
179
|
return this;
|
|
178
180
|
}
|
|
179
181
|
/**
|
|
@@ -183,9 +185,9 @@ class Player {
|
|
|
183
185
|
setTextChannel(channel) {
|
|
184
186
|
if (typeof channel !== "string")
|
|
185
187
|
throw new TypeError("Channel must be a non-empty string.");
|
|
186
|
-
const oldPlayer = { ...this };
|
|
188
|
+
const oldPlayer = this ? { ...this } : null;
|
|
187
189
|
this.textChannel = channel;
|
|
188
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
190
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "textChannelChange");
|
|
189
191
|
return this;
|
|
190
192
|
}
|
|
191
193
|
/** Sets the now playing message. */
|
|
@@ -234,15 +236,19 @@ class Player {
|
|
|
234
236
|
* @param autoplayState
|
|
235
237
|
* @param botUser
|
|
236
238
|
*/
|
|
237
|
-
setAutoplay(autoplayState, botUser) {
|
|
239
|
+
setAutoplay(autoplayState, botUser, tries = 3) {
|
|
238
240
|
if (typeof autoplayState !== "boolean") {
|
|
239
241
|
throw new TypeError("autoplayState must be a boolean.");
|
|
240
242
|
}
|
|
241
243
|
if (typeof botUser !== "object") {
|
|
242
244
|
throw new TypeError("botUser must be a user-object.");
|
|
243
245
|
}
|
|
244
|
-
|
|
246
|
+
if (typeof tries !== "number" || tries < 1) {
|
|
247
|
+
tries = 3; // Default to 3 if invalid
|
|
248
|
+
}
|
|
249
|
+
const oldPlayer = this ? { ...this } : null;
|
|
245
250
|
this.isAutoplay = autoplayState;
|
|
251
|
+
this.autoplayTries = tries;
|
|
246
252
|
this.set("Internal_BotUser", botUser);
|
|
247
253
|
this.manager.emit("playerStateUpdate", oldPlayer, this, "autoplayChange");
|
|
248
254
|
return this;
|
|
@@ -324,7 +330,7 @@ class Player {
|
|
|
324
330
|
setVolume(volume) {
|
|
325
331
|
if (isNaN(volume))
|
|
326
332
|
throw new TypeError("Volume must be a number.");
|
|
327
|
-
const oldPlayer = { ...this };
|
|
333
|
+
const oldPlayer = this ? { ...this } : null;
|
|
328
334
|
this.node.rest.updatePlayer({
|
|
329
335
|
guildId: this.options.guild,
|
|
330
336
|
data: {
|
|
@@ -361,7 +367,7 @@ class Player {
|
|
|
361
367
|
setTrackRepeat(repeat) {
|
|
362
368
|
if (typeof repeat !== "boolean")
|
|
363
369
|
throw new TypeError('Repeat can only be "true" or "false".');
|
|
364
|
-
const oldPlayer = { ...this };
|
|
370
|
+
const oldPlayer = this ? { ...this } : null;
|
|
365
371
|
if (repeat) {
|
|
366
372
|
this.trackRepeat = true;
|
|
367
373
|
this.queueRepeat = false;
|
|
@@ -372,7 +378,7 @@ class Player {
|
|
|
372
378
|
this.queueRepeat = false;
|
|
373
379
|
this.dynamicRepeat = false;
|
|
374
380
|
}
|
|
375
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
381
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "trackRepeatChange");
|
|
376
382
|
return this;
|
|
377
383
|
}
|
|
378
384
|
/**
|
|
@@ -382,7 +388,7 @@ class Player {
|
|
|
382
388
|
setQueueRepeat(repeat) {
|
|
383
389
|
if (typeof repeat !== "boolean")
|
|
384
390
|
throw new TypeError('Repeat can only be "true" or "false".');
|
|
385
|
-
const oldPlayer = { ...this };
|
|
391
|
+
const oldPlayer = this ? { ...this } : null;
|
|
386
392
|
if (repeat) {
|
|
387
393
|
this.trackRepeat = false;
|
|
388
394
|
this.queueRepeat = true;
|
|
@@ -393,7 +399,7 @@ class Player {
|
|
|
393
399
|
this.queueRepeat = false;
|
|
394
400
|
this.dynamicRepeat = false;
|
|
395
401
|
}
|
|
396
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
402
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "queueRepeatChange");
|
|
397
403
|
return this;
|
|
398
404
|
}
|
|
399
405
|
/**
|
|
@@ -408,7 +414,7 @@ class Player {
|
|
|
408
414
|
if (this.queue.size <= 1) {
|
|
409
415
|
throw new RangeError("The queue size must be greater than 1.");
|
|
410
416
|
}
|
|
411
|
-
const oldPlayer = { ...this };
|
|
417
|
+
const oldPlayer = this ? { ...this } : null;
|
|
412
418
|
if (repeat) {
|
|
413
419
|
this.trackRepeat = false;
|
|
414
420
|
this.queueRepeat = false;
|
|
@@ -429,7 +435,7 @@ class Player {
|
|
|
429
435
|
this.queueRepeat = false;
|
|
430
436
|
this.dynamicRepeat = false;
|
|
431
437
|
}
|
|
432
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
438
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "dynamicRepeatChange");
|
|
433
439
|
return this;
|
|
434
440
|
}
|
|
435
441
|
/** Restarts the current track to the start. */
|
|
@@ -449,7 +455,7 @@ class Player {
|
|
|
449
455
|
}
|
|
450
456
|
/** Stops the current track, optionally give an amount to skip to, e.g 5 would play the 5th song. */
|
|
451
457
|
stop(amount) {
|
|
452
|
-
const oldPlayer = { ...this };
|
|
458
|
+
const oldPlayer = this ? { ...this } : null;
|
|
453
459
|
if (typeof amount === "number" && amount > 1) {
|
|
454
460
|
if (amount > this.queue.length)
|
|
455
461
|
throw new RangeError("Cannot skip more than the queue length.");
|
|
@@ -461,7 +467,7 @@ class Player {
|
|
|
461
467
|
encodedTrack: null,
|
|
462
468
|
},
|
|
463
469
|
});
|
|
464
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
470
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "trackChangeStop");
|
|
465
471
|
return this;
|
|
466
472
|
}
|
|
467
473
|
/**
|
|
@@ -473,7 +479,7 @@ class Player {
|
|
|
473
479
|
throw new RangeError('Pause can only be "true" or "false".');
|
|
474
480
|
if (this.paused === pause || !this.queue.totalSize)
|
|
475
481
|
return this;
|
|
476
|
-
const oldPlayer = { ...this };
|
|
482
|
+
const oldPlayer = this ? { ...this } : null;
|
|
477
483
|
this.playing = !pause;
|
|
478
484
|
this.paused = pause;
|
|
479
485
|
this.node.rest.updatePlayer({
|
|
@@ -487,10 +493,10 @@ class Player {
|
|
|
487
493
|
}
|
|
488
494
|
/** Go back to the previous song. */
|
|
489
495
|
previous() {
|
|
490
|
-
const oldPlayer = { ...this };
|
|
496
|
+
const oldPlayer = this ? { ...this } : null;
|
|
491
497
|
this.queue.unshift(this.queue.previous);
|
|
492
498
|
this.stop();
|
|
493
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
499
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "trackChangePrevious");
|
|
494
500
|
return this;
|
|
495
501
|
}
|
|
496
502
|
/**
|
|
@@ -504,7 +510,7 @@ class Player {
|
|
|
504
510
|
if (isNaN(position)) {
|
|
505
511
|
throw new RangeError("Position must be a number.");
|
|
506
512
|
}
|
|
507
|
-
const oldPlayer = { ...this };
|
|
513
|
+
const oldPlayer = this ? { ...this } : null;
|
|
508
514
|
if (position < 0 || position > this.queue.current.duration)
|
|
509
515
|
position = Math.max(Math.min(position, this.queue.current.duration), 0);
|
|
510
516
|
this.position = position;
|
|
@@ -514,7 +520,7 @@ class Player {
|
|
|
514
520
|
position: position,
|
|
515
521
|
},
|
|
516
522
|
});
|
|
517
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this, "
|
|
523
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this, "trackChangeSeek");
|
|
518
524
|
return this;
|
|
519
525
|
}
|
|
520
526
|
}
|
package/dist/structures/Queue.js
CHANGED
|
@@ -40,7 +40,7 @@ class Queue extends Array {
|
|
|
40
40
|
add(track, offset) {
|
|
41
41
|
const trackInfo = Array.isArray(track) ? track.map((t) => JSON.stringify(t, null, 2)).join(", ") : JSON.stringify(track, null, 2);
|
|
42
42
|
this.manager.emit("debug", `[QUEUE] Added ${Array.isArray(track) ? track.length : 1} track(s) to queue: ${trackInfo}`);
|
|
43
|
-
const oldPlayer = { ...this.manager.players.get(this.guild) };
|
|
43
|
+
const oldPlayer = this.manager.players.get(this.guild) ? { ...this.manager.players.get(this.guild) } : null;
|
|
44
44
|
if (!Utils_1.TrackUtils.validate(track)) {
|
|
45
45
|
throw new RangeError('Track must be a "Track" or "Track[]".');
|
|
46
46
|
}
|
|
@@ -77,10 +77,10 @@ class Queue extends Array {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
80
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueTrackAdd");
|
|
81
81
|
}
|
|
82
82
|
remove(startOrPosition = 0, end) {
|
|
83
|
-
const oldPlayer = { ...this.manager.players.get(this.guild) };
|
|
83
|
+
const oldPlayer = this.manager.players.get(this.guild) ? { ...this.manager.players.get(this.guild) } : null;
|
|
84
84
|
if (typeof end !== "undefined") {
|
|
85
85
|
// Validate input for `start` and `end`
|
|
86
86
|
if (isNaN(Number(startOrPosition)) || isNaN(Number(end))) {
|
|
@@ -91,34 +91,34 @@ class Queue extends Array {
|
|
|
91
91
|
}
|
|
92
92
|
const removedTracks = this.splice(startOrPosition, end - startOrPosition);
|
|
93
93
|
this.manager.emit("debug", `[QUEUE] Removed ${removedTracks.length} track(s) from player: ${this.guild} from position ${startOrPosition} to ${end}.`);
|
|
94
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
94
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueTrackRemove");
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
// Single item removal when no end specified
|
|
98
98
|
const removedTrack = this.splice(startOrPosition, 1);
|
|
99
99
|
this.manager.emit("debug", `[QUEUE] Removed 1 track from player: ${this.guild} from position ${startOrPosition}: ${JSON.stringify(removedTrack[0], null, 2)}`);
|
|
100
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
100
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueTrackRemoveSingle");
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
/** Clears the queue. */
|
|
104
104
|
clear() {
|
|
105
|
-
const oldPlayer = { ...this.manager.players.get(this.guild) };
|
|
105
|
+
const oldPlayer = this.manager.players.get(this.guild) ? { ...this.manager.players.get(this.guild) } : null;
|
|
106
106
|
this.splice(0);
|
|
107
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
107
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueClear");
|
|
108
108
|
this.manager.emit("debug", `[QUEUE] Cleared the queue for: ${this.guild}`);
|
|
109
109
|
}
|
|
110
110
|
/** Shuffles the queue. */
|
|
111
111
|
shuffle() {
|
|
112
|
-
const oldPlayer = { ...this.manager.players.get(this.guild) };
|
|
112
|
+
const oldPlayer = this.manager.players.get(this.guild) ? { ...this.manager.players.get(this.guild) } : null;
|
|
113
113
|
for (let i = this.length - 1; i > 0; i--) {
|
|
114
114
|
const j = Math.floor(Math.random() * (i + 1));
|
|
115
115
|
[this[i], this[j]] = [this[j], this[i]];
|
|
116
116
|
}
|
|
117
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
117
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueShuffle");
|
|
118
118
|
this.manager.emit("debug", `[QUEUE] Shuffled the queue for: ${this.guild}`);
|
|
119
119
|
}
|
|
120
120
|
userBlockShuffle() {
|
|
121
|
-
const oldPlayer = { ...this.manager.players.get(this.guild) };
|
|
121
|
+
const oldPlayer = this.manager.players.get(this.guild) ? { ...this.manager.players.get(this.guild) } : null;
|
|
122
122
|
const userTracks = new Map();
|
|
123
123
|
this.forEach((track) => {
|
|
124
124
|
const user = track.requester.id;
|
|
@@ -138,11 +138,11 @@ class Queue extends Array {
|
|
|
138
138
|
}
|
|
139
139
|
this.splice(0);
|
|
140
140
|
this.add(shuffledQueue);
|
|
141
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
141
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueUserBlockShuffle");
|
|
142
142
|
this.manager.emit("debug", `[QUEUE] userBlockShuffled the queue for: ${this.guild}`);
|
|
143
143
|
}
|
|
144
144
|
roundRobinShuffle() {
|
|
145
|
-
const oldPlayer = { ...this.manager.players.get(this.guild) };
|
|
145
|
+
const oldPlayer = this.manager.players.get(this.guild) ? { ...this.manager.players.get(this.guild) } : null;
|
|
146
146
|
const userTracks = new Map();
|
|
147
147
|
this.forEach((track) => {
|
|
148
148
|
const user = track.requester.id;
|
|
@@ -171,7 +171,7 @@ class Queue extends Array {
|
|
|
171
171
|
}
|
|
172
172
|
this.splice(0);
|
|
173
173
|
this.add(shuffledQueue);
|
|
174
|
-
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "
|
|
174
|
+
this.manager.emit("playerStateUpdate", oldPlayer, this.manager.players.get(this.guild), "queueRobinShuffle");
|
|
175
175
|
this.manager.emit("debug", `[QUEUE] roundRobinShuffled the queue for: ${this.guild}`);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = managerCheck;
|
|
4
|
+
const Manager_1 = require("../structures/Manager");
|
|
3
5
|
function managerCheck(options) {
|
|
4
6
|
if (!options)
|
|
5
7
|
throw new TypeError("ManagerOptions must not be empty.");
|
|
6
|
-
const { autoPlay,
|
|
7
|
-
if (typeof autoPlay !== "
|
|
8
|
+
const { autoPlay, clientName, defaultSearchPlatform, nodes, plugins, send, trackPartial, usePriority, useNode, replaceYouTubeCredentials, lastFmApiKey } = options;
|
|
9
|
+
if (typeof autoPlay !== "boolean") {
|
|
8
10
|
throw new TypeError('Manager option "autoPlay" must be a boolean.');
|
|
9
11
|
}
|
|
10
|
-
if (typeof
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
throw new TypeError('Manager option "clientName" must be a string.');
|
|
12
|
+
if (typeof clientName !== "undefined") {
|
|
13
|
+
if (typeof clientName !== "string" || clientName.trim().length === 0) {
|
|
14
|
+
throw new TypeError('Manager option "clientName" must be a non-empty string.');
|
|
15
|
+
}
|
|
15
16
|
}
|
|
16
|
-
if (typeof defaultSearchPlatform !== "undefined"
|
|
17
|
-
|
|
17
|
+
if (typeof defaultSearchPlatform !== "undefined") {
|
|
18
|
+
if (typeof defaultSearchPlatform !== "string" || !Object.values(Manager_1.SearchPlatforms).includes(defaultSearchPlatform)) {
|
|
19
|
+
throw new TypeError(`Manager option "defaultSearchPlatform" must be one of: ${Object.values(Manager_1.SearchPlatforms).join(", ")}.`);
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
|
-
if (typeof nodes
|
|
22
|
+
if (typeof nodes === "undefined" || !Array.isArray(nodes)) {
|
|
20
23
|
throw new TypeError('Manager option "nodes" must be an array.');
|
|
21
24
|
}
|
|
22
25
|
if (typeof plugins !== "undefined" && !Array.isArray(plugins)) {
|
|
@@ -25,16 +28,21 @@ function managerCheck(options) {
|
|
|
25
28
|
if (typeof send !== "function") {
|
|
26
29
|
throw new TypeError('Manager option "send" must be present and a function.');
|
|
27
30
|
}
|
|
28
|
-
if (typeof trackPartial !== "undefined"
|
|
29
|
-
|
|
31
|
+
if (typeof trackPartial !== "undefined") {
|
|
32
|
+
if (!Array.isArray(trackPartial)) {
|
|
33
|
+
throw new TypeError('Manager option "trackPartial" must be an array.');
|
|
34
|
+
}
|
|
35
|
+
if (!trackPartial.every(item => typeof item === "string")) {
|
|
36
|
+
throw new TypeError('Manager option "trackPartial" must be an array of strings.');
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
if (typeof usePriority !== "undefined" && typeof usePriority !== "boolean") {
|
|
32
40
|
throw new TypeError('Manager option "usePriority" must be a boolean.');
|
|
33
41
|
}
|
|
34
42
|
if (usePriority) {
|
|
35
43
|
for (let index = 0; index < nodes.length; index++) {
|
|
36
|
-
if (
|
|
37
|
-
throw new TypeError(`Missing node option "priority" at position ${index}`);
|
|
44
|
+
if (typeof nodes[index].priority !== 'number' || isNaN(nodes[index].priority)) {
|
|
45
|
+
throw new TypeError(`Missing or invalid node option "priority" at position ${index}`);
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
}
|
|
@@ -42,12 +50,14 @@ function managerCheck(options) {
|
|
|
42
50
|
if (typeof useNode !== "string") {
|
|
43
51
|
throw new TypeError('Manager option "useNode" must be a string "leastLoad" or "leastPlayers".');
|
|
44
52
|
}
|
|
45
|
-
if (useNode
|
|
46
|
-
throw new TypeError('Manager option must be either "leastLoad" or "leastPlayers".');
|
|
53
|
+
if (!(useNode in Manager_1.UseNodeOptions)) {
|
|
54
|
+
throw new TypeError('Manager option "useNode" must be either "leastLoad" or "leastPlayers".');
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
if (typeof replaceYouTubeCredentials !== "undefined" && typeof replaceYouTubeCredentials !== "boolean") {
|
|
50
58
|
throw new TypeError('Manager option "replaceYouTubeCredentials" must be a boolean.');
|
|
51
59
|
}
|
|
60
|
+
if (typeof lastFmApiKey !== "undefined" && (typeof lastFmApiKey !== "string" || lastFmApiKey.trim().length === 0)) {
|
|
61
|
+
throw new TypeError('Manager option "lastFmApiKey" must be a non-empty string.');
|
|
62
|
+
}
|
|
52
63
|
}
|
|
53
|
-
exports.default = managerCheck;
|
package/dist/utils/nodeCheck.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = nodeCheck;
|
|
3
4
|
function nodeCheck(options) {
|
|
4
5
|
if (!options)
|
|
5
6
|
throw new TypeError("NodeOptions must not be empty.");
|
|
@@ -38,4 +39,3 @@ function nodeCheck(options) {
|
|
|
38
39
|
throw new TypeError('Node option "priority" must be a number.');
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
exports.default = nodeCheck;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = playerCheck;
|
|
3
4
|
function playerCheck(options) {
|
|
4
5
|
if (!options)
|
|
5
6
|
throw new TypeError("PlayerOptions must not be empty.");
|
|
@@ -26,4 +27,3 @@ function playerCheck(options) {
|
|
|
26
27
|
throw new TypeError('Player option "volume" must be a number.');
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
|
-
exports.default = playerCheck;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magmastream",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "A user-friendly Lavalink client designed for NodeJS.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,23 +15,23 @@
|
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@favware/rollup-type-bundler": "^3.3.0",
|
|
18
|
-
"@types/lodash": "^4.17.
|
|
19
|
-
"@types/node": "^20.
|
|
20
|
-
"@types/ws": "^8.5.
|
|
18
|
+
"@types/lodash": "^4.17.14",
|
|
19
|
+
"@types/node": "^20.17.12",
|
|
20
|
+
"@types/ws": "^8.5.13",
|
|
21
21
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
22
22
|
"@typescript-eslint/parser": "^7.18.0",
|
|
23
23
|
"eslint": "^8.57.1",
|
|
24
24
|
"npm-run-all": "^4.1.5",
|
|
25
|
-
"typedoc": "^0.
|
|
26
|
-
"typedoc-plugin-no-inherit": "^1.
|
|
27
|
-
"typescript": "^5.
|
|
25
|
+
"typedoc": "^0.27.6",
|
|
26
|
+
"typedoc-plugin-no-inherit": "^1.5.0",
|
|
27
|
+
"typescript": "^5.7.3"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@discordjs/collection": "^2.1.1",
|
|
31
|
-
"axios": "^1.7.
|
|
31
|
+
"axios": "^1.7.9",
|
|
32
32
|
"events": "^3.3.0",
|
|
33
33
|
"lodash": "^4.17.21",
|
|
34
|
-
"tslib": "^2.
|
|
34
|
+
"tslib": "^2.8.1",
|
|
35
35
|
"ws": "^8.18.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|