From a14ad37c6d090abebdc59cbd032f391cb462661a Mon Sep 17 00:00:00 2001 From: Kp Adeyinka <65085595+exiify@users.noreply.github.com> Date: Sat, 10 Apr 2021 13:27:49 -0400 Subject: [PATCH 1/3] Update Utils.ts --- src/structures/Utils.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/structures/Utils.ts b/src/structures/Utils.ts index 1b3711a..b208bb8 100644 --- a/src/structures/Utils.ts +++ b/src/structures/Utils.ts @@ -185,8 +185,11 @@ export abstract class TrackUtils { new RegExp(`^${escapeRegExp(unresolvedTrack.title)}$`, "i").test(track.title) ); }); - - if (originalAudio) return originalAudio; + + if (originalAudio) { + if(unresolvedTrack.spotifyUri) originalAudio.spotifyUri = unresolvedTrack.spotifyUri + return originalAudio; + } } if (unresolvedTrack.duration) { @@ -194,10 +197,13 @@ export abstract class TrackUtils { (track.duration >= (unresolvedTrack.duration - 1500)) && (track.duration <= (unresolvedTrack.duration + 1500)) ); - - if (sameDuration) return sameDuration; + + if (sameDuration) { + if(unresolvedTrack.spotifyUri) sameDuration.spotifyUri = unresolvedTrack.spotifyUri; + return sameDuration; + } } - + if(unresolvedTrack.spotifyUri) res.tracks[0].spotifyUri = unresolvedTrack.spotifyUri return res.tracks[0]; } } @@ -397,4 +403,4 @@ export interface PlayerUpdate { time: number; }; guildId: string; -} \ No newline at end of file +} From 7af435f9e093f615b3489bd5453418efc6614885 Mon Sep 17 00:00:00 2001 From: Kp Adeyinka <65085595+exiify@users.noreply.github.com> Date: Sat, 10 Apr 2021 13:51:33 -0400 Subject: [PATCH 2/3] Added spotify links support --- src/structures/Utils.ts | 106 ++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/src/structures/Utils.ts b/src/structures/Utils.ts index b208bb8..fe1ec15 100644 --- a/src/structures/Utils.ts +++ b/src/structures/Utils.ts @@ -20,7 +20,8 @@ const TRACK_SYMBOL = Symbol("track"), ]; /** @hidden */ -const escapeRegExp = (str: string): string => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +const escapeRegExp = (str: string): string => + str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); export abstract class TrackUtils { static trackPartial: string[] | null = null; @@ -32,8 +33,13 @@ export abstract class TrackUtils { } static setTrackPartial(partial: string[]): void { - if (!Array.isArray(partial) || !partial.every(str => typeof str === "string")) - throw new Error("Provided partial is not an array or not a string array."); + if ( + !Array.isArray(partial) || + !partial.every((str) => typeof str === "string") + ) + throw new Error( + "Provided partial is not an array or not a string array." + ); if (!partial.includes("track")) partial.unshift("track"); this.trackPartial = partial; @@ -49,15 +55,16 @@ export abstract class TrackUtils { if (Array.isArray(trackOrTracks) && trackOrTracks.length) { for (const track of trackOrTracks) { - if (!(track[TRACK_SYMBOL] || track[UNRESOLVED_TRACK_SYMBOL])) return false + if (!(track[TRACK_SYMBOL] || track[UNRESOLVED_TRACK_SYMBOL])) + return false; } return true; } return ( - trackOrTracks[TRACK_SYMBOL] || - trackOrTracks[UNRESOLVED_TRACK_SYMBOL] - ) === true; + (trackOrTracks[TRACK_SYMBOL] || + trackOrTracks[UNRESOLVED_TRACK_SYMBOL]) === true + ); } /** @@ -99,6 +106,7 @@ export abstract class TrackUtils { isSeekable: data.info.isSeekable, isStream: data.info.isStream, uri: data.info.uri, + spotifyUri: null, thumbnail: data.info.uri.includes("youtube") ? `https://img.youtube.com/vi/${data.info.identifier}/default.jpg` : null, @@ -122,12 +130,14 @@ export abstract class TrackUtils { Object.defineProperty(track, TRACK_SYMBOL, { configurable: true, - value: true + value: true, }); return track; } catch (error) { - throw new RangeError(`Argument "data" is not a valid track: ${error.message}`); + throw new RangeError( + `Argument "data" is not a valid track: ${error.message}` + ); } } @@ -136,25 +146,28 @@ export abstract class TrackUtils { * @param query * @param requester */ - static buildUnresolved(query: string | UnresolvedQuery, requester?: unknown): UnresolvedTrack { + static buildUnresolved( + query: string | UnresolvedQuery, + requester?: unknown + ): UnresolvedTrack { if (typeof query === "undefined") throw new RangeError('Argument "query" must be present.'); let unresolvedTrack: Partial = { requester, async resolve(): Promise { - const resolved = await TrackUtils.getClosestTrack(this) - Object.getOwnPropertyNames(this).forEach(prop => delete this[prop]); + const resolved = await TrackUtils.getClosestTrack(this); + Object.getOwnPropertyNames(this).forEach((prop) => delete this[prop]); Object.assign(this, resolved); - } + }, }; if (typeof query === "string") unresolvedTrack.title = query; - else unresolvedTrack = { ...unresolvedTrack, ...query } + else unresolvedTrack = { ...unresolvedTrack, ...query }; Object.defineProperty(unresolvedTrack, UNRESOLVED_TRACK_SYMBOL, { configurable: true, - value: true + value: true, }); return unresolvedTrack as UnresolvedTrack; @@ -163,47 +176,67 @@ export abstract class TrackUtils { static async getClosestTrack( unresolvedTrack: UnresolvedTrack ): Promise { - if (!TrackUtils.manager) throw new RangeError("Manager has not been initiated."); + if (!TrackUtils.manager) + throw new RangeError("Manager has not been initiated."); if (!TrackUtils.isUnresolvedTrack(unresolvedTrack)) throw new RangeError("Provided track is not a UnresolvedTrack."); - const query = [unresolvedTrack.author, unresolvedTrack.title].filter(str => !!str).join(" - "); - const res = await TrackUtils.manager.search(query, unresolvedTrack.requester); - - if (res.loadType !== "SEARCH_RESULT") throw res.exception ?? { - message: "No tracks found.", - severity: "COMMON", - }; + const query = [unresolvedTrack.author, unresolvedTrack.title] + .filter((str) => !!str) + .join(" - "); + const res = await TrackUtils.manager.search( + query, + unresolvedTrack.requester + ); + + if (res.loadType !== "SEARCH_RESULT") + throw ( + res.exception ?? { + message: "No tracks found.", + severity: "COMMON", + } + ); if (unresolvedTrack.author) { - const channelNames = [unresolvedTrack.author, `${unresolvedTrack.author} - Topic`]; + const channelNames = [ + unresolvedTrack.author, + `${unresolvedTrack.author} - Topic`, + ]; - const originalAudio = res.tracks.find(track => { + const originalAudio = res.tracks.find((track) => { return ( - channelNames.some(name => new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.author)) || - new RegExp(`^${escapeRegExp(unresolvedTrack.title)}$`, "i").test(track.title) + channelNames.some((name) => + new RegExp(`^${escapeRegExp(name)}$`, "i").test(track.author) + ) || + new RegExp(`^${escapeRegExp(unresolvedTrack.title)}$`, "i").test( + track.title + ) ); }); - + if (originalAudio) { - if(unresolvedTrack.spotifyUri) originalAudio.spotifyUri = unresolvedTrack.spotifyUri + if (unresolvedTrack.spotifyUri) + originalAudio.spotifyUri = unresolvedTrack.spotifyUri; return originalAudio; } } if (unresolvedTrack.duration) { - const sameDuration = res.tracks.find(track => - (track.duration >= (unresolvedTrack.duration - 1500)) && - (track.duration <= (unresolvedTrack.duration + 1500)) + const sameDuration = res.tracks.find( + (track) => + track.duration >= unresolvedTrack.duration - 1500 && + track.duration <= unresolvedTrack.duration + 1500 ); - + if (sameDuration) { - if(unresolvedTrack.spotifyUri) sameDuration.spotifyUri = unresolvedTrack.spotifyUri; + if (unresolvedTrack.spotifyUri) + sameDuration.spotifyUri = unresolvedTrack.spotifyUri; return sameDuration; } } - if(unresolvedTrack.spotifyUri) res.tracks[0].spotifyUri = unresolvedTrack.spotifyUri + if (unresolvedTrack.spotifyUri) + res.tracks[0].spotifyUri = unresolvedTrack.spotifyUri; return res.tracks[0]; } } @@ -219,7 +252,8 @@ export abstract class Structure { name: K, extender: (target: Extendable[K]) => T ): T { - if (!structures[name]) throw new TypeError(`"${name} is not a valid structure`); + if (!structures[name]) + throw new TypeError(`"${name} is not a valid structure`); const extended = extender(structures[name]); structures[name] = extended; return extended; From 7ec2121852f9083e9f4748d7924bb36f85a9c0f8 Mon Sep 17 00:00:00 2001 From: Kp Adeyinka <65085595+exiify@users.noreply.github.com> Date: Sat, 10 Apr 2021 13:51:59 -0400 Subject: [PATCH 3/3] Update Player.ts --- src/structures/Player.ts | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/structures/Player.ts b/src/structures/Player.ts index 0bdf381..ba56661 100644 --- a/src/structures/Player.ts +++ b/src/structures/Player.ts @@ -72,6 +72,7 @@ export class Player { public bands = new Array(15).fill(0.0); /** The voice state object from Discord. */ public voiceState: VoiceState = Object.assign({}); + public spotifyUri: string; /** The Manager. */ public manager: Manager; private static _manager: Manager; @@ -146,13 +147,18 @@ export class Player { */ public setEQ(...bands: EqualizerBand[]): this { // Hacky support for providing an array - if (Array.isArray(bands[0])) bands = bands[0] as unknown as EqualizerBand[] + if (Array.isArray(bands[0])) + bands = (bands[0] as unknown) as EqualizerBand[]; - if (!bands.length || !bands.every( + if ( + !bands.length || + !bands.every( (band) => JSON.stringify(Object.keys(band).sort()) === '["band","gain"]' ) ) - throw new TypeError("Bands must be a non-empty object array containing 'band' and 'gain' properties."); + throw new TypeError( + "Bands must be a non-empty object array containing 'band' and 'gain' properties." + ); for (const { band, gain } of bands) this.bands[band] = gain; @@ -278,7 +284,10 @@ export class Player { * @param track * @param options */ - public async play(track: Track | UnresolvedTrack, options: PlayOptions): Promise; + public async play( + track: Track | UnresolvedTrack, + options: PlayOptions + ): Promise; public async play( optionsOrTrack?: PlayOptions | Track | UnresolvedTrack, playOptions?: PlayOptions @@ -303,7 +312,9 @@ export class Player { if (TrackUtils.isUnresolvedTrack(this.queue.current)) { try { - this.queue.current = await TrackUtils.getClosestTrack(this.queue.current as UnresolvedTrack); + this.queue.current = await TrackUtils.getClosestTrack( + this.queue.current as UnresolvedTrack + ); } catch (error) { this.manager.emit("trackError", this, this.queue.current, error); if (this.queue[0]) return this.play(this.queue[0]); @@ -385,7 +396,8 @@ export class Player { /** Stops the current track, optionally give an amount to skip to, e.g 5 would play the 5th song. */ public stop(amount?: number): this { if (typeof amount === "number" && amount > 1) { - if (amount > this.queue.length) throw new RangeError("Cannot skip more than the queue length."); + if (amount > this.queue.length) + throw new RangeError("Cannot skip more than the queue length."); this.queue.splice(0, amount - 1); } @@ -464,6 +476,8 @@ export interface PlayerOptions { /** If track partials are set some of these will be `undefined` as they were removed. */ export interface Track { + /** T encoded track. */ + spotifyUri: string | null; /** The base64 encoded track. */ readonly track: string; /** The title of the track. */