ytmusic_api_unofficial
Version:
A simple API to get music from YouTube Music
264 lines • 13.2 kB
JavaScript
;
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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.countriesCodes = exports.countries = exports.all_TYPES = exports.AvailableQuality = exports.AvailableFormat = exports.StreamPlayer = exports.Player = exports.Playlist = exports.Music = exports.Album = exports.Duration = exports.Artist = exports.Thumbnail = void 0;
exports.search = search;
exports.get = get;
exports.charts = charts;
exports.download = download;
exports.getPlayers = getPlayers;
exports.getUrlDecodeT = getUrlDecodeT;
const request_1 = __importDefault(require("./utils/request"));
const responseBuilder_1 = require("./utils/responseBuilder");
const utils_1 = require("./utils/utils");
const error_1 = require("./utils/error");
const default_1 = require("./utils/default");
Object.defineProperty(exports, "all_TYPES", { enumerable: true, get: function () { return default_1.all_TYPES; } });
Object.defineProperty(exports, "AvailableFormat", { enumerable: true, get: function () { return default_1.AvailableFormat; } });
Object.defineProperty(exports, "AvailableQuality", { enumerable: true, get: function () { return default_1.AvailableQuality; } });
Object.defineProperty(exports, "countries", { enumerable: true, get: function () { return default_1.countries; } });
Object.defineProperty(exports, "countriesCodes", { enumerable: true, get: function () { return default_1.countriesCodes; } });
const Music_1 = __importDefault(require("./classes/Music"));
exports.Music = Music_1.default;
const Artist_1 = __importDefault(require("./classes/Artist"));
exports.Artist = Artist_1.default;
const Playlist_1 = __importDefault(require("./classes/Playlist"));
exports.Playlist = Playlist_1.default;
const Player_1 = __importDefault(require("./classes/Player"));
exports.Player = Player_1.default;
const StreamPlayer_1 = __importDefault(require("./classes/StreamPlayer"));
exports.StreamPlayer = StreamPlayer_1.default;
const countries_1 = require("./utils/countries");
const decode_1 = require("./utils/decode");
const Duration_1 = __importDefault(require("./classes/Duration"));
exports.Duration = Duration_1.default;
const Album_1 = __importDefault(require("./classes/Album"));
exports.Album = Album_1.default;
/**
* Require for DOC API
*/
var Thumbnail_1 = require("./classes/Thumbnail");
Object.defineProperty(exports, "Thumbnail", { enumerable: true, get: function () { return Thumbnail_1.Thumbnail; } });
/**
* Search for a query in YouTube Music
* @param query - ex: "Hello Adele"
* @param filter - ex: "SONG" (Check available types)
* @param option - You can change country code. This parameter can be used to get a more precise result depending on location demand
* @example
* ```JS
* const search = await client.search("Hello Adele", "SONG")
* console.log(search)
* ```
*/
function search(query, filter, option = default_1.options) {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
var _a;
const hasFilter = !!filter;
filter = (_a = filter === null || filter === void 0 ? void 0 : filter.toString()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
if (hasFilter && (!default_1.all_TYPES.includes(filter) && !(!!(default_1.TYPE_SEARCH_CODE === null || default_1.TYPE_SEARCH_CODE === void 0 ? void 0 : default_1.TYPE_SEARCH_CODE[filter]))))
return reject((0, error_1.error)(1001, `Available types: ${default_1.all_TYPES.join(", ")}`));
const result = { query, filter: hasFilter ? filter : false, content: [] };
if ((0, utils_1.getYTIdFromText)(query).isValidId) {
result.content = [yield get(query).catch(reject)];
return resolve(result);
}
(0, request_1.default)('search', {
query,
params: hasFilter ? default_1.TYPE_SEARCH_CODE[filter] : ''
}, {}, option).then((response) => __awaiter(this, void 0, void 0, function* () {
try {
if (response.content)
return resolve(result);
else
response = response.contents;
if (response.tabbedSearchResultsRenderer)
response = response.tabbedSearchResultsRenderer.tabs[0].tabRenderer.content;
const sectionList = (0, responseBuilder_1.nav)(response, ['sectionListRenderer', 'contents']);
if (sectionList.length === 1 && sectionList[0].itemSectionRenderer)
return result;
for (const res of sectionList) {
let shelf_contents = null;
let category = null;
if (res.musicCardShelfRenderer) {
result.content.push((0, utils_1.topResults)(res.musicCardShelfRenderer));
shelf_contents = (0, responseBuilder_1.nav)(res, ["musicCardShelfRenderer", "contents"], true);
if (!shelf_contents)
continue;
if (shelf_contents[0].messageRenderer)
category = (0, responseBuilder_1.nav)(shelf_contents.shift(), ['messageRenderer', 'text', 'runs', 0, 'text']);
}
else if (res.musicShelfRenderer) {
shelf_contents = res["musicShelfRenderer"]["contents"];
category = (0, responseBuilder_1.nav)(res, [...responseBuilder_1.MUSIC_SHELF, ...responseBuilder_1.TITLE_TEXT], true);
}
else if (res.musicResponsiveListItemRenderer) {
shelf_contents = res['musicResponsiveListItemRenderer']['contents'];
}
else
continue;
shelf_contents = shelf_contents.filter((item) => item.musicResponsiveListItemRenderer || item.musicTwoRowItemRenderer || item.musicMultiRowListItemRenderer);
(0, utils_1.parseSearchResults)(shelf_contents, category).forEach((content, i) => {
if (!content || (filter && (hasFilter && (default_1.all_TYPES.includes(filter) && (content === null || content === void 0 ? void 0 : content.resultType) !== filter))))
return;
else
result.content.push(content);
});
}
result.content = result.content.filter((content) => !!(content === null || content === void 0 ? void 0 : content.id));
if (option.fetch) {
result.content = result.content.filter((content) => !!(content === null || content === void 0 ? void 0 : content.id));
const promises = result.content.map((content) => __awaiter(this, void 0, void 0, function* () {
if (content.id)
return yield get(content.id).catch((e) => {
if (process.env.YT_DEBUG_MODE === "true")
console.error(e);
return null;
});
else
return null;
}));
result.content = yield Promise.all(promises);
result.content = result.content.filter((content) => !!(content === null || content === void 0 ? void 0 : content.id));
}
result.content = (0, utils_1.rankingResponse)(result.content, query);
if (result.content.length === 0)
return reject((0, error_1.error)(1002, { query }));
return resolve(result);
}
catch (e) {
reject((0, error_1.error)(5000, {
code: 1005,
error: e,
message: `Please report this issue on the GitHub repository, this is a bug.`
}));
}
})).catch((e) => {
reject(e);
});
}));
}
/**
* Get music from YouTube Music by URL or ID or search query (Warning: search query length must be different from 11 characters)
* @param query - ex: "Hello Adele" or https://music.youtube.com/watch?v=abc
* @param param - Private parameter for the function (Make sure to not use it)
* @example
* const get = await client.get("Hello Adele")
* return:
* ```json
* {
* "thumbnails": [
* {
* "url": "https://lh3.googleusercontent.com/...",
* "width": 60,
* "height": 60
* }
* ],
* "id": "dQw4w9WgXcQ",
* "title": "Never Gonna Give You Up",
* "artists": [{
* "name": "Rick Astley",
* "id": "MPREb_5eN7fQq3J9_"
* }],
* "resultType": "song",
* "videoType": "MUSIC_VIDEO_TYPE_ATV"
* // Other properties
* }
* ```
*/
function get(query, param = null) {
return new Promise((resolve, reject) => {
const id = (0, utils_1.getYTIdFromText)(query, true);
const req = { url: '', body: {}, method: 'POST' };
if (param) {
req.url = "browse";
req.body = { browseId: query, params: param };
}
else {
switch (id.type) {
case "song":
req.url = 'next';
req.body = { videoId: id.id };
break;
case "playlist":
if (id.id.includes('_')) {
req.url = 'https://music.youtube.com/playlist/?list=' + id.id;
req.method = 'GET';
break;
}
case "artist":
case "album":
req.url = 'browse';
req.body = { browseId: id.id };
break;
}
}
if (!!req.url) {
(0, request_1.default)(req.url, req.body, {}, default_1.options, req.method).then((res) => {
resolve((0, utils_1.parseGetResult)(res, id.type));
}).catch(reject);
}
else
reject((0, error_1.error)(1006, { query: query, id: id.id, type: id.type }));
});
}
/**
* Get chart music from YouTube Music by country or global
* @param country - The country code (Check available countries)
*/
function charts(country = 'global') {
return new Promise((resolve, reject) => {
var _a, _b;
country = country === null || country === void 0 ? void 0 : country.toUpperCase();
if (!default_1.countries.includes(country) && !default_1.countriesCodes.includes(country))
return reject((0, error_1.error)(1007, `Available countries: ${default_1.countries.join(", ")}`));
(0, request_1.default)('browse', { browseId: (((_a = countries_1.COUNTRIES.find((c) => c.name === country)) === null || _a === void 0 ? void 0 : _a.id) || ((_b = countries_1.COUNTRIES.find((c) => c.codeCountry === country)) === null || _b === void 0 ? void 0 : _b.id)) }).then((res) => {
resolve((0, utils_1.parseGetResult)(res, 'charts'));
}).catch(reject);
});
}
/**
* Get a Download link of a music
* @param query - The music ID or URL
* @param format - The format of the music (Check available formats)
* @param quality - The quality of the music (Check available qualities)
* @example
*/
function download(query, format = default_1.AvailableFormat[0], quality = default_1.AvailableQuality[0]) {
return new Promise((resolve, reject) => {
(0, utils_1.downloadYTDL)(query, format, quality).then((res) => {
resolve(res);
}).catch(reject);
});
}
/**
* getPlayers is a function that returns the available players (music, video) in all qualities
* @param query - The music ID or URL
*/
function getPlayers(query) {
return (0, utils_1.getPlayers_dv)((0, utils_1.getYTIdFromText)(query).isValidId ? (0, utils_1.getYTIdFromText)(query).id : query).catch((e) => {
throw e;
});
}
/**
* @hideconstructor
* @param format - The format of the music (Check available formats)
*/
function getUrlDecodeT(format) {
return new Promise((resolve, reject) => {
(0, decode_1.getUrlDecode)(format).then((decoded) => __awaiter(this, void 0, void 0, function* () {
return resolve(decoded);
})).catch(reject);
});
}
//# sourceMappingURL=index.js.map