magmastream 2.9.3-dev.3 → 2.9.3-dev.30

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.
Files changed (42) hide show
  1. package/dist/config/blockedWords.d.ts +1 -0
  2. package/dist/index.d.ts +19 -3687
  3. package/dist/index.js +1 -1
  4. package/dist/statestorage/JsonQueue.d.ts +173 -0
  5. package/dist/statestorage/JsonQueue.js +32 -4
  6. package/dist/statestorage/MemoryQueue.d.ts +154 -0
  7. package/dist/statestorage/MemoryQueue.js +56 -36
  8. package/dist/statestorage/RedisQueue.d.ts +178 -0
  9. package/dist/statestorage/RedisQueue.js +29 -7
  10. package/dist/structures/Enums.d.ts +310 -0
  11. package/dist/structures/Enums.js +6 -0
  12. package/dist/structures/Filters.d.ts +352 -0
  13. package/dist/structures/Filters.js +5 -4
  14. package/dist/structures/MagmastreamError.d.ts +14 -0
  15. package/dist/structures/Manager.d.ts +259 -0
  16. package/dist/structures/Manager.js +297 -555
  17. package/dist/structures/Node.d.ts +390 -0
  18. package/dist/structures/Node.js +98 -143
  19. package/dist/structures/Player.d.ts +347 -0
  20. package/dist/structures/Player.js +53 -127
  21. package/dist/structures/Plugin.d.ts +23 -0
  22. package/dist/structures/Rest.d.ts +93 -0
  23. package/dist/structures/Rest.js +41 -21
  24. package/dist/structures/Types.d.ts +1315 -0
  25. package/dist/structures/Utils.d.ts +169 -0
  26. package/dist/structures/Utils.js +145 -71
  27. package/dist/utils/filtersEqualizers.d.ts +16 -0
  28. package/dist/utils/managerCheck.d.ts +7 -0
  29. package/dist/utils/nodeCheck.d.ts +7 -0
  30. package/dist/utils/playerCheck.d.ts +7 -0
  31. package/dist/wrappers/discord.js.d.ts +15 -0
  32. package/dist/wrappers/discord.js.js +19 -4
  33. package/dist/wrappers/discordeno.d.ts +19 -0
  34. package/dist/wrappers/discordeno.js +77 -0
  35. package/dist/wrappers/eris.d.ts +15 -0
  36. package/dist/wrappers/eris.js +20 -3
  37. package/dist/wrappers/oceanic.d.ts +15 -0
  38. package/dist/wrappers/oceanic.js +22 -4
  39. package/dist/wrappers/seyfert.d.ts +37 -0
  40. package/dist/wrappers/seyfert.js +25 -1
  41. package/package.json +106 -98
  42. package/dist/wrappers/detritus.js +0 -52
@@ -0,0 +1,169 @@
1
+ import { AutoPlayPlatform, TrackPartial } from "./Enums";
2
+ import { Manager } from "./Manager";
3
+ import { AnyUser, ErrorOrEmptySearchResult, Extendable, LavalinkResponse, SearchResult, SerializedPlayerState, Track, TrackData } from "./Types";
4
+ import { Player } from "./Player";
5
+ export declare abstract class TrackUtils {
6
+ static trackPartial: TrackPartial[] | null;
7
+ private static manager;
8
+ /**
9
+ * Initializes the TrackUtils class with the given manager.
10
+ * @param manager The manager instance to use.
11
+ * @hidden
12
+ */
13
+ static init(manager: Manager): void;
14
+ /**
15
+ * Sets the partial properties for the Track class. If a Track has some of its properties removed by the partial,
16
+ * it will be considered a partial Track.
17
+ * @param {TrackPartial} partial The array of string property names to remove from the Track class.
18
+ */
19
+ static setTrackPartial(partial: TrackPartial[]): void;
20
+ /**
21
+ * Checks if the provided argument is a valid Track.
22
+ * @param value The value to check.
23
+ * @returns {boolean} Whether the provided argument is a valid Track.
24
+ */
25
+ static isTrack(track: unknown): track is Track;
26
+ /**
27
+ * Checks if the provided argument is a valid Track array.
28
+ * @param value The value to check.
29
+ * @returns {boolean} Whether the provided argument is a valid Track array.
30
+ */
31
+ static isTrackArray(value: unknown): value is Track[];
32
+ /**
33
+ * Checks if the provided argument is a valid Track or Track array.
34
+ * @param value The value to check.
35
+ * @returns {boolean} Whether the provided argument is a valid Track or Track array.
36
+ */
37
+ static validate(value: unknown): value is Track | Track[];
38
+ /**
39
+ * Builds a Track from the raw data from Lavalink and a optional requester.
40
+ * @param data The raw data from Lavalink to build the Track from.
41
+ * @param requester The user who requested the track, if any.
42
+ * @param isAutoPlay Whether the track is autoplayed. Defaults to false.
43
+ * @returns The built Track.
44
+ */
45
+ static build<T = AnyUser>(data: TrackData, requester?: T, isAutoplay?: boolean): Track;
46
+ /**
47
+ * Validates a search result.
48
+ * @param result The search result to validate.
49
+ * @returns Whether the search result is valid.
50
+ */
51
+ static isErrorOrEmptySearchResult(result: SearchResult): result is ErrorOrEmptySearchResult;
52
+ /**
53
+ * Revives a track.
54
+ * @param track The track to revive.
55
+ * @returns The revived track.
56
+ */
57
+ static revive(track: Track): Track;
58
+ }
59
+ export declare abstract class AutoPlayUtils {
60
+ private static manager;
61
+ /**
62
+ * Initializes the AutoPlayUtils class with the given manager.
63
+ * @param manager The manager instance to use.
64
+ * @hidden
65
+ */
66
+ static init(manager: Manager): Promise<void>;
67
+ /**
68
+ * Gets recommended tracks for the given track.
69
+ * @param track The track to get recommended tracks for.
70
+ * @returns An array of recommended tracks.
71
+ */
72
+ static getRecommendedTracks(track: Track): Promise<Track[]>;
73
+ /**
74
+ * Gets recommended tracks from Last.fm for the given track.
75
+ * @param track The track to get recommended tracks for.
76
+ * @param apiKey The API key for Last.fm.
77
+ * @returns An array of recommended tracks.
78
+ */
79
+ static getRecommendedTracksFromLastFm(track: Track, apiKey: string): Promise<Track[]>;
80
+ /**
81
+ * Gets recommended tracks from the given source.
82
+ * @param track The track to get recommended tracks for.
83
+ * @param platform The source to get recommended tracks from.
84
+ * @returns An array of recommended tracks.
85
+ */
86
+ static getRecommendedTracksFromSource(track: Track, platform: AutoPlayPlatform): Promise<Track[]>;
87
+ /**
88
+ * Searches for a track using the manager and returns resolved tracks.
89
+ * @param query The search query (artist - title).
90
+ * @param requester The requester who initiated the search.
91
+ * @returns An array of resolved tracks, or an empty array if not found or error occurred.
92
+ */
93
+ private static resolveTracksFromQuery;
94
+ /**
95
+ * Resolves the first available track from a search query using the specified source.
96
+ * Useful for normalizing tracks that lack platform-specific metadata or URIs.
97
+ *
98
+ * @param query - The search query string (usually "Artist - Title").
99
+ * @param source - The search platform to use (e.g., Spotify, Deezer, YouTube).
100
+ * @param requester - The requester object, used for context or attribution.
101
+ * @returns A single resolved {@link Track} object if found, or `null` if the search fails or returns no results.
102
+ */
103
+ private static resolveFirstTrackFromQuery;
104
+ private static isPlaylistRawData;
105
+ private static isTrackData;
106
+ private static isTrackDataArray;
107
+ static buildTracksFromResponse<T>(recommendedResult: LavalinkResponse, requester?: T): Track[];
108
+ }
109
+ export declare abstract class PlayerUtils {
110
+ private static manager;
111
+ /**
112
+ * Initializes the PlayerUtils class with the given manager.
113
+ * @param manager The manager instance to use.
114
+ * @hidden
115
+ */
116
+ static init(manager: Manager): void;
117
+ /**
118
+ * Serializes a Player instance to avoid circular references.
119
+ * @param player The Player instance to serialize
120
+ * @returns The serialized Player instance
121
+ */
122
+ static serializePlayer(player: Player): Promise<SerializedPlayerState> | null;
123
+ /**
124
+ * Gets the base directory for player data.
125
+ */
126
+ static getPlayersBaseDir(): string;
127
+ /**
128
+ * Gets the path to the player's directory.
129
+ */
130
+ static getGuildDir(guildId: string): string;
131
+ /**
132
+ * Gets the path to the player's state file.
133
+ */
134
+ static getPlayerStatePath(guildId: string): string;
135
+ /**
136
+ * Gets the path to the player's current track file.
137
+ */
138
+ static getPlayerCurrentPath(guildId: string): string;
139
+ /**
140
+ * Gets the path to the player's queue file.
141
+ */
142
+ static getPlayerQueuePath(guildId: string): string;
143
+ /**
144
+ * Gets the path to the player's previous tracks file.
145
+ */
146
+ static getPlayerPreviousPath(guildId: string): string;
147
+ /**
148
+ * Gets the Redis key for player storage.
149
+ */
150
+ static getRedisKey(): string;
151
+ }
152
+ /** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
153
+ export declare abstract class Structure {
154
+ /**
155
+ * Extends a class.
156
+ * @param name
157
+ * @param extender
158
+ */
159
+ static extend<K extends keyof Extendable, T extends Extendable[K]>(name: K, extender: (target: Extendable[K]) => T): T;
160
+ /**
161
+ * Get a structure from available structures by name.
162
+ * @param name
163
+ */
164
+ static get<K extends keyof Extendable>(name: K): Extendable[K];
165
+ }
166
+ export declare abstract class JSONUtils {
167
+ static safe<T>(obj: T, space?: number): string;
168
+ static serializeTrack(track: Track): string;
169
+ }
@@ -9,9 +9,11 @@ const Enums_1 = require("./Enums");
9
9
  const path_1 = tslib_1.__importDefault(require("path"));
10
10
  const safe_stable_stringify_1 = tslib_1.__importDefault(require("safe-stable-stringify"));
11
11
  const MagmastreamError_1 = require("./MagmastreamError");
12
+ // import { isPlainObject } from "lodash";
12
13
  // import playwright from "playwright";
13
14
  /** @hidden */
14
15
  const SIZES = ["0", "1", "2", "3", "default", "mqdefault", "hqdefault", "maxresdefault"];
16
+ const REQUIRED_TRACK_KEYS = ["track", "title", "uri"];
15
17
  class TrackUtils {
16
18
  static trackPartial = null;
17
19
  static manager;
@@ -39,19 +41,12 @@ class TrackUtils {
39
41
  const defaultProperties = [
40
42
  Enums_1.TrackPartial.Track,
41
43
  Enums_1.TrackPartial.Title,
42
- Enums_1.TrackPartial.Identifier,
43
44
  Enums_1.TrackPartial.Author,
44
45
  Enums_1.TrackPartial.Duration,
45
- Enums_1.TrackPartial.Isrc,
46
- Enums_1.TrackPartial.IsSeekable,
47
- Enums_1.TrackPartial.IsStream,
48
46
  Enums_1.TrackPartial.Uri,
49
- Enums_1.TrackPartial.ArtworkUrl,
50
47
  Enums_1.TrackPartial.SourceName,
51
- Enums_1.TrackPartial.ThumbNail,
48
+ Enums_1.TrackPartial.ArtworkUrl,
52
49
  Enums_1.TrackPartial.Requester,
53
- Enums_1.TrackPartial.PluginInfo,
54
- Enums_1.TrackPartial.CustomData,
55
50
  ];
56
51
  /** The array of property names that will be removed from the Track class */
57
52
  this.trackPartial = Array.from(new Set([...defaultProperties, ...partial]));
@@ -61,25 +56,30 @@ class TrackUtils {
61
56
  }
62
57
  /**
63
58
  * Checks if the provided argument is a valid Track.
64
- * If provided an array then every element will be checked.
65
- * @param trackOrTracks The Track or array of Tracks to check.
59
+ * @param value The value to check.
66
60
  * @returns {boolean} Whether the provided argument is a valid Track.
67
61
  */
68
- static validate(trackOrTracks) {
69
- if (typeof trackOrTracks !== "object" || trackOrTracks === null) {
62
+ static isTrack(track) {
63
+ if (typeof track !== "object" || track === null)
70
64
  return false;
71
- }
72
- const isValidTrack = (track) => {
73
- if (typeof track !== "object" || track === null) {
74
- return false;
75
- }
76
- const t = track;
77
- return (typeof t.track === "string" && typeof t.title === "string" && typeof t.identifier === "string" && typeof t.isrc === "string" && typeof t.uri === "string");
78
- };
79
- if (Array.isArray(trackOrTracks)) {
80
- return trackOrTracks.every(isValidTrack);
81
- }
82
- return isValidTrack(trackOrTracks);
65
+ const t = track;
66
+ return REQUIRED_TRACK_KEYS.every((key) => typeof t[key] === "string");
67
+ }
68
+ /**
69
+ * Checks if the provided argument is a valid Track array.
70
+ * @param value The value to check.
71
+ * @returns {boolean} Whether the provided argument is a valid Track array.
72
+ */
73
+ static isTrackArray(value) {
74
+ return Array.isArray(value) && value.every(this.isTrack);
75
+ }
76
+ /**
77
+ * Checks if the provided argument is a valid Track or Track array.
78
+ * @param value The value to check.
79
+ * @returns {boolean} Whether the provided argument is a valid Track or Track array.
80
+ */
81
+ static validate(value) {
82
+ return this.isTrack(value) || this.isTrackArray(value);
83
83
  }
84
84
  /**
85
85
  * Builds a Track from the raw data from Lavalink and a optional requester.
@@ -544,8 +544,7 @@ class AutoPlayUtils {
544
544
  return typeof data === "object" && data !== null && "encoded" in data && "info" in data;
545
545
  }
546
546
  static isTrackDataArray(data) {
547
- return (Array.isArray(data) &&
548
- data.every((track) => typeof track === "object" && track !== null && "encoded" in track && "info" in track && typeof track.encoded === "string"));
547
+ return (Array.isArray(data) && data.every((track) => typeof track === "object" && track !== null && "encoded" in track && "info" in track && typeof track.encoded === "string"));
549
548
  }
550
549
  static buildTracksFromResponse(recommendedResult, requester) {
551
550
  if (!recommendedResult)
@@ -624,64 +623,129 @@ class PlayerUtils {
624
623
  * @returns The serialized Player instance
625
624
  */
626
625
  static async serializePlayer(player) {
626
+ const isNonSerializable = (value) => {
627
+ if (typeof value === "function" || typeof value === "symbol")
628
+ return true;
629
+ if (typeof value === "object" && value !== null) {
630
+ const ctorName = value.constructor?.name ?? "";
631
+ return (value instanceof Map ||
632
+ value instanceof Set ||
633
+ value instanceof WeakMap ||
634
+ value instanceof WeakSet ||
635
+ ctorName === "Timeout" ||
636
+ ctorName === "Socket" ||
637
+ ctorName === "TLSSocket" ||
638
+ ctorName === "EventEmitter");
639
+ }
640
+ return false;
641
+ };
642
+ const safeSerialize = (obj) => {
643
+ if (!obj || typeof obj !== "object")
644
+ return obj;
645
+ const result = {};
646
+ for (const [k, v] of Object.entries(obj)) {
647
+ if (!isNonSerializable(v)) {
648
+ result[k] = v;
649
+ }
650
+ }
651
+ return result;
652
+ };
627
653
  try {
628
- const current = await player.queue.getCurrent();
629
- const tracks = await player.queue.getTracks();
630
- const previous = await player.queue.getPrevious();
631
- const serializeTrack = (track) => ({
632
- ...track,
633
- requester: track.requester ? { id: track.requester.id, username: track.requester.username } : null,
634
- });
635
- const safeNode = player.node
636
- ? JSON.parse(JSON.stringify(player.node, (key, value) => {
637
- if (key === "rest" || key === "players" || key === "shards" || key === "manager")
638
- return undefined;
639
- return value;
640
- }))
641
- : null;
642
- return JSON.parse(JSON.stringify(player, (key, value) => {
643
- if (key === "manager")
654
+ const [current, tracks, previous] = await Promise.all([player.queue.getCurrent(), player.queue.getTracks(), player.queue.getPrevious()]);
655
+ const serializeTrack = (track) => {
656
+ if (!track || !track.identifier)
644
657
  return null;
645
- if (key === "node")
646
- return safeNode;
647
- if (key === "filters") {
658
+ try {
648
659
  return {
649
- distortion: value?.distortion ?? null,
650
- equalizer: value?.equalizer ?? [],
651
- karaoke: value?.karaoke ?? null,
652
- rotation: value?.rotation ?? null,
653
- timescale: value?.timescale ?? null,
654
- vibrato: value?.vibrato ?? null,
655
- reverb: value?.reverb ?? null,
656
- volume: value?.volume ?? 1.0,
657
- bassBoostlevel: value?.bassBoostlevel ?? null,
658
- filterStatus: value?.filtersStatus ? { ...value.filtersStatus } : {},
660
+ ...track,
661
+ requester: track.requester ? { id: track.requester.id, username: track.requester.username } : null,
662
+ displayThumbnail: undefined,
659
663
  };
660
664
  }
661
- if (key === "queue") {
662
- return {
663
- current: current ? serializeTrack(current) : null,
664
- tracks: tracks.map(serializeTrack),
665
- previous: previous.map(serializeTrack),
666
- };
665
+ catch {
666
+ return null;
667
667
  }
668
- if (key === "data") {
669
- return {
670
- clientUser: value?.Internal_AutoplayUser ?? null,
671
- nowPlayingMessage: value?.nowPlayingMessage ?? null,
672
- };
668
+ };
669
+ const safeCurrent = current ? serializeTrack(current) : null;
670
+ const safeTracks = tracks.map(serializeTrack).filter((t) => t !== null);
671
+ const safePrevious = previous.map(serializeTrack).filter((t) => t !== null);
672
+ let safeNode = null;
673
+ if (player.node) {
674
+ try {
675
+ safeNode = JSON.parse(JSON.stringify(player.node, (key, value) => {
676
+ if (["rest", "players", "shards", "manager"].includes(key))
677
+ return undefined;
678
+ if (isNonSerializable(value))
679
+ return undefined;
680
+ return value;
681
+ }));
682
+ }
683
+ catch {
684
+ safeNode = null;
673
685
  }
674
- return value;
675
- }));
686
+ }
687
+ const serializableData = player.getSerializableData();
688
+ const nowPlayingMessage = serializableData.nowPlayingMessage;
689
+ delete serializableData.nowPlayingMessage;
690
+ const snapshot = {
691
+ clusterId: player.clusterId,
692
+ options: player.options,
693
+ voiceState: player.voiceState,
694
+ guildId: player.guildId,
695
+ voiceChannelId: player.voiceChannelId ?? null,
696
+ textChannelId: player.textChannelId ?? null,
697
+ volume: player.volume,
698
+ paused: player.paused,
699
+ playing: player.playing,
700
+ position: player.position,
701
+ trackRepeat: player.trackRepeat,
702
+ queueRepeat: player.queueRepeat,
703
+ dynamicRepeat: player.dynamicRepeat,
704
+ node: safeNode,
705
+ queue: {
706
+ current: safeCurrent,
707
+ tracks: safeTracks,
708
+ previous: safePrevious,
709
+ },
710
+ filters: player.filters
711
+ ? {
712
+ distortion: player.filters.distortion ?? null,
713
+ equalizer: player.filters.equalizer ?? [],
714
+ karaoke: player.filters.karaoke ?? null,
715
+ rotation: player.filters.rotation ?? null,
716
+ timescale: player.filters.timescale ?? null,
717
+ vibrato: player.filters.vibrato ?? null,
718
+ reverb: player.filters.reverb ?? null,
719
+ volume: player.filters.volume ?? 1.0,
720
+ bassBoostlevel: player.filters.bassBoostlevel ?? null,
721
+ filterStatus: { ...player.filters.filtersStatus },
722
+ }
723
+ : null,
724
+ data: {
725
+ ...safeSerialize(serializableData),
726
+ nowPlayingMessage: nowPlayingMessage
727
+ ? {
728
+ id: String(nowPlayingMessage.id),
729
+ channelId: nowPlayingMessage.channelId,
730
+ guildId: nowPlayingMessage.guildId,
731
+ }
732
+ : null,
733
+ },
734
+ };
735
+ // Sanity check
736
+ JSON.stringify(snapshot);
737
+ return snapshot;
676
738
  }
677
739
  catch (err) {
678
- throw err instanceof MagmastreamError_1.MagmaStreamError
740
+ const error = err instanceof MagmastreamError_1.MagmaStreamError
679
741
  ? err
680
742
  : new MagmastreamError_1.MagmaStreamError({
681
- code: Enums_1.MagmaStreamErrorCode.MANAGER_SEARCH_FAILED,
682
- message: `An error occurred while searching: ${err instanceof Error ? err.message : String(err)}`,
743
+ code: Enums_1.MagmaStreamErrorCode.UTILS_PLAYER_SERIALIZE_FAILED,
744
+ message: `An error occurred while serializing player: ${err instanceof Error ? err.message : String(err)}`,
683
745
  cause: err instanceof Error ? err : undefined,
684
746
  });
747
+ console.error(error);
748
+ return null;
685
749
  }
686
750
  }
687
751
  /**
@@ -720,6 +784,16 @@ class PlayerUtils {
720
784
  static getPlayerPreviousPath(guildId) {
721
785
  return path_1.default.join(this.getGuildDir(guildId), "previous.json");
722
786
  }
787
+ /**
788
+ * Gets the Redis key for player storage.
789
+ */
790
+ static getRedisKey() {
791
+ const cfg = this.manager.options.stateStorage.redisConfig;
792
+ // Default prefix
793
+ let prefix = (cfg.prefix ?? "magmastream:").trim();
794
+ prefix = prefix.replace(/:+$/g, "") + ":";
795
+ return prefix;
796
+ }
723
797
  }
724
798
  exports.PlayerUtils = PlayerUtils;
725
799
  /** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
@@ -0,0 +1,16 @@
1
+ /** Represents an equalizer band. */
2
+ export interface Band {
3
+ /** The index of the equalizer band (0-12). */
4
+ band: number;
5
+ /** The gain value of the equalizer band (in decibels). */
6
+ gain: number;
7
+ }
8
+ export declare const bassBoostEqualizer: Band[];
9
+ export declare const softEqualizer: Band[];
10
+ export declare const tvEqualizer: Band[];
11
+ export declare const trebleBassEqualizer: Band[];
12
+ export declare const vaporwaveEqualizer: Band[];
13
+ export declare const popEqualizer: Band[];
14
+ export declare const electronicEqualizer: Band[];
15
+ export declare const radioEqualizer: Band[];
16
+ export declare const demonEqualizer: Band[];
@@ -0,0 +1,7 @@
1
+ import { ManagerOptions } from "../structures/Types";
2
+ /**
3
+ * Validates the provided ManagerOptions object.
4
+ * @param options - The options to validate.
5
+ * @throws {MagmaStreamError} Throws if any required option is missing or invalid.
6
+ */
7
+ export default function managerCheck(options: ManagerOptions): void;
@@ -0,0 +1,7 @@
1
+ import { NodeOptions } from "../structures/Types";
2
+ /**
3
+ * Validates the provided NodeOptions object.
4
+ * @param options - The options to validate.
5
+ * @throws {MagmaStreamError} Throws if any required option is missing or invalid.
6
+ */
7
+ export default function nodeCheck(options: NodeOptions): void;
@@ -0,0 +1,7 @@
1
+ import { PlayerOptions } from "../structures/Types";
2
+ /**
3
+ * Validates the provided PlayerOptions object.
4
+ * @param options - The options to validate.
5
+ * @throws {MagmaStreamError} Throws if any required option is missing or invalid.
6
+ */
7
+ export default function playerCheck(options: PlayerOptions): void;
@@ -0,0 +1,15 @@
1
+ import { Manager as BaseManager } from "../structures/Manager";
2
+ import type { GatewayVoiceStateUpdate } from "discord-api-types/v10";
3
+ import { Client, Guild, User } from "discord.js";
4
+ import { AnyUser, ManagerOptions } from "../structures/Types";
5
+ export * from "../index";
6
+ /**
7
+ * Discord.js wrapper for Magmastream.
8
+ */
9
+ export declare class DiscordJSManager extends BaseManager {
10
+ readonly client: Client;
11
+ constructor(client: Client, options?: ManagerOptions);
12
+ protected send(packet: GatewayVoiceStateUpdate): void;
13
+ resolveUser(user: AnyUser | string): Promise<User | AnyUser>;
14
+ resolveGuild(guildId: string): Guild | null;
15
+ }
@@ -4,7 +4,10 @@ exports.DiscordJSManager = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const Manager_1 = require("../structures/Manager");
6
6
  const discord_js_1 = require("discord.js");
7
- const [major, minor] = discord_js_1.version.split(".").map(Number);
7
+ const discord_js_2 = require("discord.js");
8
+ const MagmastreamError_1 = require("../structures/MagmastreamError");
9
+ const Enums_1 = require("../structures/Enums");
10
+ const [major, minor] = discord_js_2.version.split(".").map(Number);
8
11
  tslib_1.__exportStar(require("../index"), exports);
9
12
  /**
10
13
  * Discord.js wrapper for Magmastream.
@@ -14,6 +17,12 @@ class DiscordJSManager extends Manager_1.Manager {
14
17
  constructor(client, options) {
15
18
  super(options);
16
19
  this.client = client;
20
+ if (!this.client.options.intents.has(discord_js_1.GatewayIntentBits.GuildVoiceStates)) {
21
+ throw new MagmastreamError_1.MagmaStreamError({
22
+ code: Enums_1.MagmaStreamErrorCode.INTENT_MISSING,
23
+ message: "[Custom Wrapper] Your Discord.js client must have the GuildVoiceStates intent enabled.",
24
+ });
25
+ }
17
26
  const attachReadyHandler = () => {
18
27
  const handler = () => {
19
28
  if (!this.options.clientId)
@@ -21,11 +30,11 @@ class DiscordJSManager extends Manager_1.Manager {
21
30
  };
22
31
  // Only attach clientReady if Discord.js >= 14.22.0
23
32
  if (major > 14 || (major === 14 && minor >= 22)) {
24
- client.once("clientReady", handler);
33
+ this.client.once("clientReady", handler);
25
34
  }
26
35
  // Only attach ready if Discord.js < 14.22.0
27
36
  if (major < 14 || (major === 14 && minor < 22)) {
28
- client.once("ready", handler);
37
+ this.client.once("ready", handler);
29
38
  }
30
39
  };
31
40
  attachReadyHandler();
@@ -39,7 +48,7 @@ class DiscordJSManager extends Manager_1.Manager {
39
48
  guild.shard.send(packet);
40
49
  }
41
50
  async resolveUser(user) {
42
- const id = typeof user === "string" ? user : user.id;
51
+ const id = typeof user === "string" ? user : String(user.id);
43
52
  const cached = this.client.users.cache.get(id);
44
53
  if (cached)
45
54
  return cached;
@@ -51,5 +60,11 @@ class DiscordJSManager extends Manager_1.Manager {
51
60
  return { id, username: typeof user === "string" ? undefined : user.username };
52
61
  }
53
62
  }
63
+ resolveGuild(guildId) {
64
+ const cached = this.client.guilds.cache.get(guildId);
65
+ if (cached)
66
+ return cached;
67
+ return null;
68
+ }
54
69
  }
55
70
  exports.DiscordJSManager = DiscordJSManager;
@@ -0,0 +1,19 @@
1
+ import { GatewayVoiceStateUpdate } from "discord-api-types/v10";
2
+ import { Manager as BaseManager } from "../structures/Manager";
3
+ import { Bot, User } from "@discordeno/bot";
4
+ import { AnyGuild, AnyUser, ManagerOptions } from "../structures/Types";
5
+ export * from "../index";
6
+ /**
7
+ * Discordeno wrapper for Magmastream.
8
+ */
9
+ export declare class DiscordenoManager extends BaseManager {
10
+ readonly client: Bot;
11
+ constructor(client: Bot, options?: ManagerOptions);
12
+ protected send(packet: GatewayVoiceStateUpdate): void;
13
+ /**
14
+ * Resolve a user by ID or partial info.
15
+ * Uses user-provided cache getter if available, otherwise falls back to minimal info.
16
+ */
17
+ resolveUser(user: AnyUser | string): Promise<User | AnyUser>;
18
+ resolveGuild(guildId: string): AnyGuild;
19
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DiscordenoManager = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const Manager_1 = require("../structures/Manager");
6
+ const bot_1 = require("@discordeno/bot");
7
+ const Enums_1 = require("../structures/Enums");
8
+ const MagmastreamError_1 = require("../structures/MagmastreamError");
9
+ tslib_1.__exportStar(require("../index"), exports);
10
+ /**
11
+ * Discordeno wrapper for Magmastream.
12
+ */
13
+ class DiscordenoManager extends Manager_1.Manager {
14
+ client;
15
+ constructor(client, options) {
16
+ super(options);
17
+ this.client = client;
18
+ // Ensure GuildVoiceStates intent is enabled
19
+ const intents = this.client.gateway.intents;
20
+ if (!(intents & bot_1.GatewayIntents.GuildVoiceStates)) {
21
+ throw new MagmastreamError_1.MagmaStreamError({
22
+ code: Enums_1.MagmaStreamErrorCode.INTENT_MISSING,
23
+ message: "[Custom Wrapper] Your Discordeno client must have the GuildVoiceStates intent enabled.",
24
+ });
25
+ }
26
+ // Chain READY event
27
+ const oldReady = this.client.handlers.READY;
28
+ this.client.handlers.READY = (bot, payload, shardId) => {
29
+ if (oldReady)
30
+ oldReady(bot, payload, shardId);
31
+ if (!this.options?.clientId)
32
+ this.options.clientId = this.client.applicationId.toString();
33
+ };
34
+ // Chain VOICE_STATE_UPDATE event
35
+ const oldVoiceState = this.client.handlers.VOICE_STATE_UPDATE;
36
+ this.client.handlers.VOICE_STATE_UPDATE = (bot, payload, shardId) => {
37
+ if (oldVoiceState)
38
+ oldVoiceState(bot, payload, shardId);
39
+ this.updateVoiceState(payload);
40
+ };
41
+ // Chain VOICE_SERVER_UPDATE event
42
+ const oldVoiceServer = this.client.handlers.VOICE_SERVER_UPDATE;
43
+ this.client.handlers.VOICE_SERVER_UPDATE = (bot, payload, shardId) => {
44
+ if (oldVoiceServer)
45
+ oldVoiceServer(bot, payload, shardId);
46
+ this.updateVoiceState(payload);
47
+ };
48
+ }
49
+ // Send voice state updates to the guild shard
50
+ send(packet) {
51
+ this.client.gateway.sendPayload(this.client.gateway.calculateShardId(packet.d.guild_id), {
52
+ op: bot_1.GatewayOpcodes.VoiceStateUpdate,
53
+ d: packet.d,
54
+ });
55
+ }
56
+ /**
57
+ * Resolve a user by ID or partial info.
58
+ * Uses user-provided cache getter if available, otherwise falls back to minimal info.
59
+ */
60
+ async resolveUser(user) {
61
+ const id = typeof user === "string" ? user : String(user.id);
62
+ // Try user-provided cache getter
63
+ const cached = this.getUserFromCache(id);
64
+ if (cached)
65
+ return cached;
66
+ // Fallback: return minimal info
67
+ return {
68
+ id,
69
+ username: typeof user === "string" ? undefined : user.username,
70
+ };
71
+ }
72
+ resolveGuild(guildId) {
73
+ // Try user-provided cache getter
74
+ return this.getGuildFromCache(guildId);
75
+ }
76
+ }
77
+ exports.DiscordenoManager = DiscordenoManager;