diff --git a/src/Player.ts b/src/Player.ts index 90b11a4..8f28503 100644 --- a/src/Player.ts +++ b/src/Player.ts @@ -2,7 +2,7 @@ import { Client, Collection, GuildResolvable, Snowflake, User, VoiceState, Inten import { TypedEmitter as EventEmitter } from "tiny-typed-emitter"; import { Queue } from "./Structures/Queue"; import { VoiceUtils } from "./VoiceInterface/VoiceUtils"; -import { PlayerEvents, PlayerOptions, QueryType, SearchOptions, PlayerInitOptions } from "./types/types"; +import { PlayerEvents, PlayerOptions, QueryType, SearchOptions, PlayerInitOptions, PlayerSearchResult } from "./types/types"; import Track from "./Structures/Track"; import { QueryResolver } from "./utils/QueryResolver"; import YouTube from "youtube-sr"; @@ -198,13 +198,40 @@ class Player extends EventEmitter { * Search tracks * @param {string|Track} query The search query * @param {SearchOptions} options The search options - * @returns {Promise} + * @returns {Promise} */ - async search(query: string | Track, options: SearchOptions) { - if (query instanceof Track) return { playlist: null, tracks: [query] }; + async search(query: string | Track, options: SearchOptions): Promise { + if (query instanceof Track) return { playlist: query.playlist || null, tracks: [query] }; if (!options) throw new PlayerError("DiscordPlayer#search needs search options!", ErrorStatusCode.INVALID_ARG_TYPE); options.requestedBy = this.client.users.resolve(options.requestedBy); if (!("searchEngine" in options)) options.searchEngine = QueryType.AUTO; + if (this.extractors.has(options.searchEngine)) { + const extractor = this.extractors.get(options.searchEngine); + if (!extractor.validate(query)) return { playlist: null, tracks: [] }; + const data = await extractor.handle(query); + if (data && data.data.length) { + const playlist = !data.playlist + ? null + : new Playlist(this, { + ...data.playlist, + tracks: [] + }); + + const tracks = data.data.map( + (m) => + new Track(this, { + ...m, + requestedBy: options.requestedBy as User, + duration: Util.buildTimeCode(Util.parseMS(m.duration)), + playlist: playlist + }) + ); + + if (playlist) playlist.tracks = tracks; + + return { playlist: playlist, tracks: tracks }; + } + } // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const [_, extractor] of this.extractors) { diff --git a/src/types/EventEmitter.d.ts b/src/types/EventEmitter.d.ts deleted file mode 100644 index 7ad36c0..0000000 --- a/src/types/EventEmitter.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -declare module "tiny-typed-emitter" { - export type ListenerSignature = { - [E in keyof L]: (...args: any[]) => any; - }; - - export type DefaultListener = { - [k: string]: (...args: any[]) => any; - }; - - export class TypedEmitter = DefaultListener> { - static defaultMaxListeners: number; - addListener(event: U, listener: L[U]): this; - prependListener(event: U, listener: L[U]): this; - prependOnceListener(event: U, listener: L[U]): this; - removeListener(event: U, listener: L[U]): this; - removeAllListeners(event?: keyof L): this; - once(event: U, listener: L[U]): this; - on(event: U, listener: L[U]): this; - off(event: U, listener: L[U]): this; - emit(event: U, ...args: Parameters): boolean; - eventNames(): U[]; - listenerCount(type: keyof L): number; - listeners(type: U): L[U][]; - rawListeners(type: U): L[U][]; - getMaxListeners(): number; - setMaxListeners(n: number): this; - } -} diff --git a/src/types/types.ts b/src/types/types.ts index 1715260..e1d3578 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -8,6 +8,11 @@ import { downloadOptions } from "ytdl-core"; export type FiltersName = keyof QueueFilters; +export interface PlayerSearchResult { + playlist: Playlist | null; + tracks: Track[]; +} + /** * @typedef {AudioFilters} QueueFilters */