bundle.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. (() => {
  2. var __webpack_exports__ = {};
  3. console.log("bundle2!"), printable = e => "WEB" === e, parseCodecs = e => {
  4. const t = e.mimeType;
  5. if (!t) return {};
  6. const n = t.match(/(?<mimetype>[^/]+\/[^;]+)(?:;\s*codecs="?(?<codecs>[^"]+))?/);
  7. if (!n) return {};
  8. const o = n.groups.codecs;
  9. if (!o) return {};
  10. const s = o.trim().replace(/,$/, "").split(",").map((e => e.trim())).filter(Boolean);
  11. let i = null, c = null;
  12. for (const e of s) {
  13. const t = e.split(".")[0];
  14. ["avc1", "avc2", "avc3", "avc4", "vp9", "vp8", "hev1", "hev2", "h263", "h264", "mp4v", "hvc1", "av01", "theora"].includes(t) ? i || (i = e) : ["mp4a", "opus", "vorbis", "mp3", "aac", "ac-3", "ec-3", "eac3", "dtsc", "dtse", "dtsh", "dtsl"].includes(t) ? c || (c = e) : console.log(`WARNING: Unknown codec ${e}`)
  15. }
  16. return i || c ? {vcodec: i, acodec: c} : 2 === s.length ? {vcodec: s[0], acodec: s[1]} : {}
  17. }, parseSetCookie = e => {
  18. if (!e) return "";
  19. const t = e["Set-Cookie"];
  20. if (!t) return "";
  21. console.log(`setCookie: ${t}`);
  22. let n = "PREF=hl=en&tz=UTC; SOCS=CAI; GPS=1; ";
  23. const o = ["YSC", "VISITOR_INFO1_LIVE", "VISITOR_PRIVACY_METADATA"];
  24. for (const e in o) {
  25. const s = o[e], i = new RegExp(`${s}=([^;,]+)`), c = t.match(i);
  26. if (c && 2 === c.length) {
  27. const t = c[1];
  28. n += e != o.length - 1 ? `${s}=${t}; ` : `${s}=${t}`
  29. }
  30. }
  31. return console.log(`current cookie: ${n}`), n
  32. }, request = async (e, t, n = null, o = {}, s) => {
  33. if ("WEB" === s && (t = t.replace("https://www.youtube.com", "http://127.0.0.1")), console.log(`request url:${t}`), console.log(`request data:${n}`), console.log(`request method:${e}`), console.log(`request headers:${JSON.stringify(o)}`), "WEB" === s) {
  34. const s = await fetch(t, {mode: "cors", method: e, headers: o, body: n}), i = await s.text();
  35. return Promise.resolve({data: i, headers: s.headers})
  36. }
  37. return new Promise(((s, i) => {
  38. AF.request(t, e, n, o, ((e, t, n) => {
  39. n ? i(n) : (console.log(`response headers: ${t}`), s({data: e, headers: JSON.parse(t)}))
  40. }))
  41. }))
  42. }, getStringBetween = (e, t, n, o = 0, s = 0) => {
  43. const i = e.indexOf(t), c = n ? e.indexOf(n, i) : e.length;
  44. return e.substring(i + t.length + s, c + o)
  45. }, findFunction = (jsCode, regexp, platform) => {
  46. const match = jsCode.match(regexp);
  47. if (!match && match.length <= 1) return null;
  48. let result = "";
  49. const dependencyMatches = match[0].match(/([$a-zA-Z0-9]+\.[$a-zA-Z0-9]+)/g), existDependencies = [];
  50. if (dependencyMatches && dependencyMatches.length >= 1) for (let e of dependencyMatches) {
  51. const t = e.split(".")[0];
  52. if (existDependencies.includes(t)) continue;
  53. const n = jsCode.match(new RegExp(`var \\${t}={(.|\\n)*?};`), "ig");
  54. n && n.length >= 1 && (result += n[0] + "\n"), existDependencies.push(t)
  55. }
  56. return result += `\n${match[0]}`, printable(platform) && console.log("decipherFunction result: " + result), eval(result)
  57. };
  58. const cache = {};
  59. fetchBaseJSContent = async (e, t) => {
  60. const n = `jsContent:${e}`;
  61. if (cache[n]) return console.log(`baseContent from cache: ${e}`), cache[n];
  62. console.log(`extract baseUrl: ${e}`);
  63. const o = await request("GET", e, null, {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Safari/537.36"}, t), {
  64. data: s,
  65. _: i
  66. } = o;
  67. return cache[n] = s, s
  68. }, extractJSSignatureFunction = async (e, t) => {
  69. const n = `jsSign:${e}`;
  70. if (cache[n]) return console.log(`jsSign from cache: ${e}`), cache[n];
  71. const o = await fetchBaseJSContent(e, t),
  72. s = findFunction(o, /([a-zA-Z0-9]+)=function\([a-zA-Z0-9]+\)\{a=a\.split\(""\).*};/, t);
  73. return cache[n] = s, s
  74. }, extractNJSFunction = async (e, t) => {
  75. const n = `jsN:${e}`;
  76. if (cache[n]) return console.log(`jsN from cache: ${e}`), cache[n];
  77. const o = await fetchBaseJSContent(e, t),
  78. s = findFunction(o, /([a-zA-Z0-9]+)=function\([a-zA-Z0-9]+\)\{var b=a\.split\(""\)[\s\S]*?};/, t);
  79. return cache[n] = s, s
  80. }, signUrl = async (e, t, n) => {
  81. const o = {};
  82. for (const t of e.split("&")) {
  83. const [e, n] = t.split("=");
  84. o[decodeURIComponent(e)] = decodeURIComponent(n)
  85. }
  86. const [s, i, c] = [o.url, o.s, o.sp], r = await extractJSSignatureFunction(t, n);
  87. if (!r) return null;
  88. printable(n) && console.log(`signatureCipher=${e}, url=${s}, signature=${i}, sp=${c}`);
  89. let a = `${s}&${c}=${r(i)}`;
  90. for (const e of s.split("&")) {
  91. const [t, n] = e.split("=");
  92. o[decodeURIComponent(t)] = decodeURIComponent(n)
  93. }
  94. const l = await extractNJSFunction(t, n), u = o.n;
  95. if (u && l) {
  96. return function d(e, t, n) {
  97. let o = new RegExp(`([?&])${t}=.*?(&|$)`, "i"), s = e.replace(o, `$1${t}=${n}$2`);
  98. return s === e && -1 === e.indexOf("?") ? s += `?${t}=${n}` : s === e && (s += `&${t}=${n}`), s
  99. }(a, "n", l(u))
  100. }
  101. return a
  102. }, detail = async (e, t) => {
  103. try {
  104. const n = await request("GET", `${e}&bpctr=9999999999&has_verified=1`, null, {
  105. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
  106. Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  107. "Accept-Language": "en-us,en;q=0.5",
  108. "Sec-Fetch-Mode": "navigate",
  109. "Accept-Encoding": "gzip, deflate, br",
  110. Cookie: "PREF=hl=en&tz=UTC; SOCS=CAI"
  111. }, t);
  112. let {data: o, headers: s} = n, i = /var ytInitialPlayerResponse\s*=\s*({.*?});/, c = o.match(i);
  113. if (!c || !c.length) throw console.log("can not found JSON: ytInitialPlayerResponse"), new Error("JSON not found: ytInitialPlayerResponse");
  114. const r = JSON.parse(c[1]);
  115. printable(t) && console.log(r);
  116. const a = r.videoDetails, l = [];
  117. for (const e of a.thumbnail.thumbnails) l.push({url: e.url, width: e.width + "", height: e.height + ""});
  118. let u = [];
  119. const d = [];
  120. for (const e of r.streamingData.formats.concat(r.streamingData.adaptiveFormats)) e && (e.from = "web", d.push(e));
  121. u = u.concat(d), console.log(`after html, format size:${u.length}`);
  122. const h = `https://www.youtube.com${JSON.parse(o.match(/set\(({.+?})\);/)[1]).PLAYER_JS_URL}`;
  123. let p = [];
  124. const m = [];
  125. for (let e of u) if (printable(t) && console.log(e), e && -1 === p.indexOf(e.itag) && (e.url || (e.url = await signUrl(e.signatureCipher, h, t)), e.url)) {
  126. const {vcodec: n, acodec: o} = parseCodecs(e);
  127. if (n && o) {
  128. const s = {
  129. width: e.width + "",
  130. height: e.height + "",
  131. type: e.mimeType,
  132. quality: e.quality,
  133. itag: e.itag,
  134. fps: e.fps + "",
  135. bitrate: e.bitrate + "",
  136. url: e.url,
  137. ext: "mp4",
  138. vcodec: n,
  139. acodec: o,
  140. vbr: "0",
  141. abr: "0",
  142. container: "mp4_dash",
  143. from: e.from
  144. };
  145. "WEB" === t && (s.source = e), m.push(s), p.push(e.itag)
  146. }
  147. }
  148. const g = o.match(/var ytInitialData\s*=\s*({.*?});/), f = [];
  149. if (g && 2 === g.length) {
  150. const e = JSON.parse(g[1]);
  151. printable(t) && console.log(e);
  152. for (const t of e.contents?.twoColumnWatchNextResults?.secondaryResults?.secondaryResults?.results || []) if (t.compactVideoRenderer) {
  153. const e = t.compactVideoRenderer;
  154. console.log(`recommend video: ${JSON.stringify(e)}`), e.videoId && f.push({
  155. type: "gridVideoRenderer",
  156. videoId: e.videoId,
  157. title: e.title?.simpleText,
  158. thumbnails: e.thumbnail?.thumbnails,
  159. channelName: e.longBylineText?.runs?.[0]?.text,
  160. publishedTimeText: e.publishedTimeText?.simpleText,
  161. viewCountText: e.viewCountText?.simpleText,
  162. shortViewCountText: e.shortViewCountText?.simpleText,
  163. lengthText: e.lengthText?.simpleText
  164. })
  165. }
  166. }
  167. const x = {
  168. code: 200,
  169. msg: "",
  170. data: {
  171. videoDetails: {
  172. isLiveContent: a.isLiveContent,
  173. title: a.title,
  174. thumbnails: l,
  175. description: a.shortDescription,
  176. lengthSeconds: a.lengthSeconds,
  177. viewCount: a.viewCount,
  178. keywords: a.keywords,
  179. author: a.author,
  180. channelID: a.channelId,
  181. recommendInfo: f,
  182. channelURL: `https://www.youtube.com/channel/${a.channelId}`,
  183. videoId: a.videoId
  184. }, streamingData: {formats: m.reverse()}
  185. },
  186. id: "MusicDetailViewModel_detail_url"
  187. };
  188. return console.log(`detail result: ${JSON.stringify(x)}`), x
  189. } catch (e) {
  190. const t = {code: -1, msg: e.toString()};
  191. return console.log(`detail result error: ${JSON.stringify(t)}`), console.log(e), t
  192. }
  193. }, search = async (e, t, n) => {
  194. try {
  195. if (console.log(`search keyword: ${e}`), console.log(`search next: ${t}`), t) {
  196. const e = JSON.parse(t), o = e.key, s = {
  197. context: {client: {clientName: "WEB", clientVersion: "2.20240506.01.00"}},
  198. continuation: e.continuation
  199. };
  200. let i = await request("POST", `https://www.youtube.com/youtubei/v1/search?key=${o}`, JSON.stringify(s), {}, n);
  201. const {data: c, _: r} = i;
  202. i = JSON.parse(c);
  203. const a = [];
  204. for (const e of i.onResponseReceivedCommands[0].appendContinuationItemsAction.continuationItems[0].itemSectionRenderer.contents) {
  205. const t = e.videoRenderer;
  206. printable(n) && console.log(t), t && t.videoId && a.push({
  207. type: "videoWithContextRenderer",
  208. data: {
  209. videoId: t.videoId,
  210. title: t.title?.runs?.[0]?.text,
  211. thumbnails: t.thumbnail?.thumbnails,
  212. channelName: t.longBylineText?.runs?.[0]?.text,
  213. publishedTimeText: t.publishedTimeText?.simpleText,
  214. viewCountText: t.viewCountText?.simpleText,
  215. shortViewCountText: t.shortViewCountText?.simpleText,
  216. lengthText: t.lengthText?.simpleText
  217. }
  218. })
  219. }
  220. const l = {
  221. code: 200,
  222. msg: "",
  223. data: {
  224. data: a,
  225. next: JSON.stringify({
  226. key: e.key,
  227. continuation: i.onResponseReceivedCommands?.[0]?.appendContinuationItemsAction?.continuationItems?.[1]?.continuationItemRenderer?.continuationEndpoint?.continuationCommand?.token
  228. })
  229. },
  230. id: "MusicSearchResultViewModel_search_result"
  231. };
  232. return console.log(`[next] search result: ${JSON.stringify(l)}`), l
  233. }
  234. {
  235. let t = `https://www.youtube.com/results?q=${encodeURIComponent(e)}&sp=EgIQAQ%253D%253D`;
  236. const o = await request("GET", t, null, {}, n), {data: s, _: i} = o;
  237. let c = /var ytInitialData\s*=\s*({.*?});/, r = s.match(c);
  238. if (!r || !r.length) throw console.log("can not found ytInitialData"), new Error("JSON not found: ytInitialData");
  239. const a = JSON.parse(r[1]), l = [];
  240. for (const e of a.contents?.twoColumnSearchResultsRenderer?.primaryContents?.sectionListRenderer?.contents?.[0]?.itemSectionRenderer?.contents) if (e.videoRenderer) {
  241. const t = e.videoRenderer;
  242. printable(n) && console.log(t), t && t.videoId && l.push({
  243. type: "videoWithContextRenderer",
  244. data: {
  245. videoId: t.videoId,
  246. title: t.title?.runs?.[0]?.text,
  247. thumbnails: t.thumbnail?.thumbnails,
  248. channelName: t.longBylineText?.runs?.[0]?.text,
  249. publishedTimeText: t.publishedTimeText?.simpleText,
  250. viewCountText: t.viewCountText?.simpleText,
  251. shortViewCountText: t.shortViewCountText?.simpleText,
  252. lengthText: t.lengthText?.simpleText
  253. }
  254. })
  255. }
  256. let u = {};
  257. s.split("innertubeApiKey").length > 0 && (u.key = s.split("innertubeApiKey")[1].trim().split(",")[0].split('"')[2]), u.continuation = a.contents?.twoColumnSearchResultsRenderer?.primaryContents?.sectionListRenderer?.contents?.[1]?.continuationItemRenderer?.continuationEndpoint?.continuationCommand?.token;
  258. const d = {
  259. code: 200,
  260. msg: "",
  261. data: {data: l, next: JSON.stringify(u)},
  262. id: "MusicSearchResultViewModel_search_result"
  263. };
  264. return console.log(`unnext search result: ${JSON.stringify(d)}`), d
  265. }
  266. } catch (e) {
  267. const t = {code: -1, msg: e.toString()};
  268. return console.log(`search result error: ${JSON.stringify(t)}`), t
  269. }
  270. }
  271. })();
  272. //# sourceMappingURL=bundle.js.map