UNPKG

damonjs

Version:

A modified Shoukaku wrapper with enhanced queue support.

194 lines (193 loc) 8.31 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DamonJsTrack = void 0; const Interfaces_1 = require("../../Modules/Interfaces"); class DamonJsTrack { constructor(raw, requester) { this.raw = raw; this.resolvedBySource = false; this.damonjs = undefined; this.data = new Map(); this.encoded = raw.encoded; this.sourceName = raw.info.sourceName; this.title = raw.info.title; this.uri = raw.info.uri; this.identifier = raw.info.identifier; this.isSeekable = raw.info.isSeekable; this.isStream = raw.info.isStream; this.author = raw.info.author; this.length = raw.info.length; this.position = raw.info.position; this.artworkUrl = raw.info.artworkUrl; this.isrc = raw.info.isrc; this.realUri = Interfaces_1.SupportedSources.includes(this.sourceName) && this.uri ? this.uri : null; this.pluginInfo = raw.pluginInfo; this.requester = requester; } /** * Get json of this track * @returns {RawTrack} */ getRaw() { return { encoded: this.encoded, info: { identifier: this.identifier, isSeekable: this.isSeekable, author: this.author, length: this.length, isStream: this.isStream, position: this.position, title: this.title, uri: this.uri, isrc: this.isrc, artworkUrl: this.artworkUrl, sourceName: this.sourceName, }, pluginInfo: this.pluginInfo, _raw: this.raw, }; } /** * Set damonjs instance * @param damonjs DamonJs instance * @returns DamonJsTrack */ setDamonJs(damonjs) { var _a; this.damonjs = damonjs; if (this.sourceName === 'youtube' && this.identifier) this.artworkUrl = `https://img.youtube.com/vi/${this.identifier}/${(_a = damonjs.DamonJsOptions.defaultYoutubeThumbnail) !== null && _a !== void 0 ? _a : 'hqdefault'}.jpg`; return this; } /** * Whether the track is ready to play or need to be solved */ get readyToPlay() { return (this.damonjs !== undefined && !!this.encoded && !!this.sourceName && !!this.identifier && !!this.author && !!this.length && !!this.title && !!this.uri && !!this.realUri); } /** * Resolve the track * @param options Resolve options * @returns Promise<DamonJsTrack> */ resolve(options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { if (!this.damonjs) throw new Interfaces_1.DamonJsError(1, 'DamonJs is not set'); if (this.damonjs.DamonJsOptions.trackResolver && typeof this.damonjs.DamonJsOptions.trackResolver === 'function' && (yield this.damonjs.DamonJsOptions.trackResolver.bind(this)(options))) return this; const resolveSource = (_b = (_a = this.damonjs.DamonJsOptions) === null || _a === void 0 ? void 0 : _a.sourceForceResolve) === null || _b === void 0 ? void 0 : _b.includes(this.sourceName); const { forceResolve, overwrite } = options ? options : { forceResolve: false, overwrite: false }; if (!forceResolve && this.readyToPlay) return this; if (resolveSource && this.resolvedBySource) return this; if (resolveSource) { this.resolvedBySource = true; return this; } this.damonjs.emit(Interfaces_1.Events.Debug, options.player, `Resolving ${this.sourceName} track ${this.title}; Source: ${this.sourceName}`); const result = (yield this.getTrack(options.player, Interfaces_1.SourceIDs[this.damonjs.DamonJsOptions.defaultSearchEngine || 'youtube'] || 'yt').catch(() => null)) || (yield this.getTrack(options.player, 'youtube').catch(() => null)); if (!result) throw new Interfaces_1.DamonJsError(2, 'No results found'); this.encoded = result.encoded; this.realUri = result.info.uri || null; this.length = result.info.length; if (overwrite || resolveSource) { this.title = result.info.title; this.identifier = result.info.identifier; this.isSeekable = result.info.isSeekable; this.author = result.info.author; this.length = result.info.length; this.isStream = result.info.isStream; this.uri = result.info.uri; } return this; }); } getTrackScore(track) { let score = 0; const title = track.info.title.toLowerCase(); const author = track.info.author.toLowerCase(); if (track.info.sourceName === 'youtube') { // Prefer "Topic" channels if (author.includes('- topic')) score += 3; // Lower score for music videos if (title.includes('official video') || title.includes('music video') || title.includes('official mv') || title.includes('(video)') || title.includes('[video]')) { score -= 2; } // Prefer "audio" tracks if (title.includes('audio') || title.includes('lyric')) score += 1; } else if (track.info.sourceName === 'soundcloud') { // Prefer "audio" tracks if (author.includes('official')) score += 2; if (title.includes('original mix')) score += 3; if (title.includes('remix')) score -= 1; if (title.includes('repost')) score -= 2; if (title.includes('cover')) score -= 1; } return score; } filterPlayableTrack(track) { if (track.info.sourceName === 'soundcloud' && track.info.identifier.includes('/preview/')) { return false; } return true; } getTrack(player, source) { return __awaiter(this, void 0, void 0, function* () { if (!this.damonjs) throw new Interfaces_1.DamonJsError(1, 'DamonJs is not set'); const query = [this.author, this.title].filter((x) => !!x).join(' - '); const result = yield player.search(`${query}`, { requester: this.requester, engine: source }); if (!result || !result.tracks.length) throw new Interfaces_1.DamonJsError(2, 'No results found'); const rawTracks = result.tracks.map((x) => x.getRaw()._raw); // Filter out preview tracks const filteredTracks = rawTracks.filter((track) => this.filterPlayableTrack(track)); if (!filteredTracks.length) throw new Interfaces_1.DamonJsError(2, 'No non-preview tracks found'); const sortedTracks = filteredTracks.sort((a, b) => { // Prioritize "Topic" channels and tracks without "Official Video" in title const aScore = this.getTrackScore(a); const bScore = this.getTrackScore(b); return bScore - aScore; }); return sortedTracks[0]; }); } } exports.DamonJsTrack = DamonJsTrack;