index.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const axios_1 = require("axios");
  4. function formatMusicItem(item) {
  5. var _a, _b, _c, _d, _e, _f, _g;
  6. return {
  7. id: item.videoId,
  8. title: (_b = (_a = item.title.runs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text,
  9. artist: (_d = (_c = item.ownerText.runs) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.text,
  10. artwork: (_g = (_f = (_e = item === null || item === void 0 ? void 0 : item.thumbnail) === null || _e === void 0 ? void 0 : _e.thumbnails) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.url,
  11. };
  12. }
  13. let lastQuery;
  14. let musicContinToken;
  15. async function searchMusic(query, page) {
  16. if (query !== lastQuery || page === 1) {
  17. musicContinToken = undefined;
  18. }
  19. lastQuery = query;
  20. let data = JSON.stringify({
  21. context: {
  22. client: {
  23. hl: "zh-CN",
  24. gl: "US",
  25. deviceMake: "",
  26. deviceModel: "",
  27. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0,gzip(gfe)",
  28. clientName: "WEB",
  29. clientVersion: "2.20231121.08.00",
  30. osName: "Windows",
  31. osVersion: "10.0",
  32. platform: "DESKTOP",
  33. userInterfaceTheme: "USER_INTERFACE_THEME_LIGHT",
  34. browserName: "Edge Chromium",
  35. browserVersion: "119.0.0.0",
  36. acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
  37. screenWidthPoints: 1358,
  38. screenHeightPoints: 1012,
  39. screenPixelDensity: 1,
  40. screenDensityFloat: 1.2395833730697632,
  41. utcOffsetMinutes: 480,
  42. memoryTotalKbytes: "8000000",
  43. mainAppWebInfo: {
  44. pwaInstallabilityStatus: "PWA_INSTALLABILITY_STATUS_UNKNOWN",
  45. webDisplayMode: "WEB_DISPLAY_MODE_BROWSER",
  46. isWebNativeShareAvailable: true,
  47. },
  48. timeZone: "Asia/Shanghai",
  49. },
  50. user: {
  51. lockedSafetyMode: false,
  52. },
  53. request: {
  54. useSsl: true,
  55. internalExperimentFlags: [],
  56. },
  57. },
  58. query: musicContinToken ? undefined : query,
  59. continuation: musicContinToken || undefined,
  60. });
  61. var config = {
  62. method: "post",
  63. url: "https://www.youtube.com/youtubei/v1/search?prettyPrint=false",
  64. headers: {
  65. "Content-Type": "text/plain",
  66. },
  67. data: data,
  68. };
  69. const response = (await (0, axios_1.default)(config)).data;
  70. const contents = response.contents.twoColumnSearchResultsRenderer.primaryContents
  71. .sectionListRenderer.contents;
  72. const isEndItem = contents.find((it) => {
  73. var _a, _b, _c;
  74. return ((_c = (_b = (_a = it.continuationItemRenderer) === null || _a === void 0 ? void 0 : _a.continuationEndpoint) === null || _b === void 0 ? void 0 : _b.continuationCommand) === null || _c === void 0 ? void 0 : _c.request) === "CONTINUATION_REQUEST_TYPE_SEARCH";
  75. });
  76. if (isEndItem) {
  77. musicContinToken =
  78. isEndItem.continuationItemRenderer.continuationEndpoint
  79. .continuationCommand.token;
  80. }
  81. const musicData = contents.find((it) => it.itemSectionRenderer)
  82. .itemSectionRenderer.contents;
  83. let resultMusicData = [];
  84. for (let i = 0; i < musicData.length; ++i) {
  85. if (musicData[i].videoRenderer) {
  86. resultMusicData.push(formatMusicItem(musicData[i].videoRenderer));
  87. }
  88. }
  89. return {
  90. isEnd: !isEndItem,
  91. data: resultMusicData,
  92. };
  93. }
  94. async function search(query, page, type) {
  95. if (type === "music") {
  96. return await searchMusic(query, page);
  97. }
  98. }
  99. let cacheMediaSource = {
  100. id: null,
  101. urls: {},
  102. };
  103. function getQuality(label) {
  104. if (label === "small") {
  105. return "standard";
  106. }
  107. else if (label === "tiny") {
  108. return "low";
  109. }
  110. else if (label === "medium") {
  111. return "high";
  112. }
  113. else if (label === "large") {
  114. return "super";
  115. }
  116. else {
  117. return "standard";
  118. }
  119. }
  120. async function getMediaSource(musicItem, quality) {
  121. var _a, _b;
  122. if (musicItem.id === cacheMediaSource.id) {
  123. return {
  124. url: cacheMediaSource.urls[quality],
  125. };
  126. }
  127. cacheMediaSource = {
  128. id: null,
  129. urls: {},
  130. };
  131. const data = {
  132. context: {
  133. client: {
  134. screenWidthPoints: 689,
  135. screenHeightPoints: 963,
  136. screenPixelDensity: 1,
  137. utcOffsetMinutes: 120,
  138. hl: "en",
  139. gl: "GB",
  140. remoteHost: "1.1.1.1",
  141. deviceMake: "",
  142. deviceModel: "",
  143. userAgent: "com.google.android.apps.youtube.music/6.14.50 (Linux; U; Android 13; GB) gzip",
  144. clientName: "ANDROID_MUSIC",
  145. clientVersion: "6.14.50",
  146. osName: "Android",
  147. osVersion: "13",
  148. originalUrl: "https://www.youtube.com/tv?is_account_switch=1&hrld=1&fltor=1",
  149. theme: "CLASSIC",
  150. platform: "MOBILE",
  151. clientFormFactor: "UNKNOWN_FORM_FACTOR",
  152. webpSupport: false,
  153. timeZone: "Europe/Amsterdam",
  154. acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  155. },
  156. user: { enableSafetyMode: false },
  157. request: {
  158. internalExperimentFlags: [],
  159. consistencyTokenJars: [],
  160. },
  161. },
  162. contentCheckOk: true,
  163. racyCheckOk: true,
  164. video_id: musicItem.id,
  165. };
  166. var config = {
  167. method: "post",
  168. url: "https://www.youtube.com/youtubei/v1/player?prettyPrint=false",
  169. headers: {
  170. "Content-Type": "application/json",
  171. },
  172. data: JSON.stringify(data),
  173. };
  174. const result = (await (0, axios_1.default)(config)).data;
  175. const formats = (_a = result.streamingData.formats) !== null && _a !== void 0 ? _a : [];
  176. const adaptiveFormats = (_b = result.streamingData.adaptiveFormats) !== null && _b !== void 0 ? _b : [];
  177. [...formats, ...adaptiveFormats].forEach((it) => {
  178. const q = getQuality(it.quality);
  179. if (q && it.url && !cacheMediaSource.urls[q]) {
  180. cacheMediaSource.urls[q] = it.url;
  181. }
  182. });
  183. return {
  184. url: cacheMediaSource.urls[quality],
  185. };
  186. }
  187. module.exports = {
  188. platform: "Youtube",
  189. author: '猫头猫',
  190. version: "0.0.1",
  191. supportedSearchType: ["music"],
  192. srcUrl: "https://gitee.com/maotoumao/MusicFreePlugins/raw/v0.1/dist/youtube/index.js",
  193. cacheControl: "no-cache",
  194. search,
  195. getMediaSource,
  196. };