- // ==UserScript==
- // @name you-get
- // @description 视频下载 bilibili acfun youtube 西瓜 快手 抖音
- // @namespace http://tampermonkey.net/
- // @version 0.0.2
- // @description try to take over the world!
- // @author You
- // @match https://www.ixigua.com/*
- // @match https://www.bilibili.com/video/*
- // @match https://www.douyin.com/*
- // @match https://www.kuaishou.com/*
- // @match https://www.acfun.cn/v/*
- // @match https://www.youtube.com/watch/*
- // @match https://v.qq.com/*
- // @match https://v.cctv.com/*
- // @match https://v.youku.com/*
- // @license MIT
- // @grant none
- // ==/UserScript==
- (() => {
- // src/util/index.js
- var download = async (blob, fileName) => {
- let link = window.URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.download = `${fileName}`;
- a.href = link;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- window.URL.revokeObjectURL(link);
- };
- var safetyParse = (str) => {
- try {
- return JSON.parse(str);
- } catch (error) {
- return null;
- }
- };
- var getFile = async (url) => {
- const res = await fetch(url);
- const reader = res.body.getReader();
- const contentLength = +res.headers.get("Content-Length");
- if (!contentLength) {
- const data = await res.arrayBuffer();
- return new Uint8Array(data);
- }
- let receivedLength = 0;
- let chunks = [];
- while (true) {
- const { done, value } = await reader.read();
- if (done) {
- break;
- }
- chunks.push(value);
- receivedLength += value.length;
- console.log(
- `fileSize: ${contentLength} %c downloaded ${receivedLength}`,
- "background: #222; color: #bada55"
- );
- }
- return new Blob(chunks);
- };
- var getUrlsByM3u8 = async (url, parser) => {
- const urlObj = new URL(url);
- urlObj.pathname = urlObj.pathname.split("/").slice(0, -1).join("/");
- urlObj.search = "";
- const base = urlObj.toString();
- const res = await fetch(url);
- const data = await res.text();
- return data.split("\n").filter((i) => !!i && !i.startsWith("#")).map((i) => {
- if (parser) {
- return parser(i);
- }
- return i.startsWith("/") ? `${base}${i}` : `${base}/${i}`;
- });
- };
- var getFiles = (urls, max = 8) => {
- let connections = 0;
- let files = [];
- urls = urls.map((i, index) => ({
- ...i,
- index
- }));
- return new Promise((resolve, reject) => {
- const getSingleFile = async ({ url, index, ...rest }) => {
- if (connections < max) {
- try {
- connections = connections + 1;
- const data = await getFile(url);
- connections = connections - 1;
- files[index] = data;
- if (urls?.length) {
- getSingleFile(urls.shift());
- } else {
- connections === 0 && resolve(files);
- }
- } catch (error) {
- console.log(error);
- urls.push({
- url,
- index,
- ...rest
- });
- }
- }
- };
- new Array(max).fill(0).forEach((i) => {
- getSingleFile(urls.shift());
- });
- });
- };
-
- // src/module/acfun.js
- var getVideoInfo = async () => {
- const m3u8FileUrl = safetyParse(window.pageInfo.currentVideoInfo.ksPlayJson)?.adaptationSet?.[0]?.representation?.[0]?.url;
- const urls = await getUrlsByM3u8(m3u8FileUrl);
- return urls.map((url) => ({ url }));
- };
- var acfun_default = async () => {
- const urls = await getVideoInfo();
- const files = await getFiles(urls);
- download(new Blob(files), "download.mp4");
- };
-
- // src/module/xigua.js
- var getXiGuaVideoInfo = async () => {
- const res = await fetch(window.location.href);
- const str = await res.text();
- const data = safetyParse(
- str.match(/window?._SSR_HYDRATED_DATA=([\d\D]+?)<\/script>/)[1].replaceAll("undefined", "null")
- );
- const videoResource = data?.anyVideo?.gidInformation?.packerData?.video?.videoResource || data?.anyVideo?.gidInformation?.packerData?.videoResource;
- const videoList = Object.values(videoResource?.normal?.video_list ?? {}).sort(
- (a, b) => b?.vheight - a?.vheight
- );
- const video = videoList?.[0];
- return {
- url: atob(video.main_url, "base64"),
- fileName: `download.${video.vtype || "mp4"}`
- };
- };
- var xigua_default = async () => {
- const url = await getXiGuaVideoInfo();
- const file = await getFile(url.url);
- download(file, "download.mp4");
- };
-
- // src/module/bilibili.js
- var getBilibiliVideoInfo = async () => {
- const res = await fetch(window.location.href);
- const str = await res.text();
- const data = JSON.parse(
- str.match(/window.__playinfo__=([\d\D]+?)<\/script>/)[1]
- );
- const dash = data.data.dash;
- const video = dash.video.sort((a, b) => b?.width - a?.width)?.[0];
- const audio = dash.audio[0];
- return [
- {
- url: video.baseUrl,
- fileName: `download.${video?.mimeType?.split("/")?.[1] || "mp4"}`
- },
- {
- url: audio.baseUrl,
- fileName: `download.${video?.mimeType?.split("/")?.[1] || "mp4"}`
- }
- ];
- };
- var bilibili_default = async () => {
- const urls = await getBilibiliVideoInfo();
- while (urls?.length) {
- const { url, fileName } = urls.shift();
- const file = await getFile(url);
- download(file, fileName);
- }
- };
-
- // src/module/douyin.js
- var getDouyinVideoInfo = () => {
- const urls = [...document.querySelectorAll("video source")].map((i) => i.src);
- return {
- url: urls[0],
- fileName: `download.mp4`
- };
- };
- var douyin_default = async () => {
- const url = await getDouyinVideoInfo();
- const file = await getFile(url.url);
- download(file, url.fileName);
- };
-
- // src/module/kuaishou.js
- var getKuaishouVideoInfo = () => {
- const urls = [...document.querySelectorAll("video")].map((i) => i.src);
- return {
- url: urls[0],
- fileName: `download.mp4`
- };
- };
- var kuaishou_default = async () => {
- const url = await getKuaishouVideoInfo();
- const file = await getFile(url.url);
- download(file, url.fileName);
- };
-
- // src/module/youtube.js
- var getYoutubeVideoInfo = async () => {
- const res = await fetch(window.location.href);
- const str = await res.text();
- const parser = new DOMParser();
- const doc = parser.parseFromString(str, "text/html");
- const data = safetyParse(
- doc.body.innerHTML.match(/("formats":)([\d\D]+?}]+?)/)[2]
- );
- const video = data.sort((a, b) => b?.width - a?.width)?.[0];
- return {
- url: video.url,
- fileName: `download.mp4`
- };
- };
- var youtube_default = async () => {
- const url = await getYoutubeVideoInfo();
- const file = await getFile(url.url);
- download(file, url.fileName);
- };
-
- // src/module/qq.js
- var proxyhttpBody = null;
- var monitor = async () => {
- try {
- window.__PLAYER__.pluginMsg.emit = new Proxy(
- window.__PLAYER__.pluginMsg.emit,
- {
- apply: (...args) => {
- if (args?.[2]?.[0] === "PROXY_HTTP_START" && args?.[2]?.[1]?.vinfoparam) {
- console.log(args?.[2]?.[1]);
- proxyhttpBody = JSON.stringify(args?.[2]?.[1]);
- }
- return Reflect.apply(...args);
- }
- }
- );
- } catch (error) {
- console.log("monitor error");
- }
- };
- var getVideoInfo2 = async () => {
- let m3u8FileUrl = null;
- if (!m3u8FileUrl) {
- let res = await fetch("https://vd6.l.qq.com/proxyhttp", {
- method: "post",
- body: proxyhttpBody
- });
- res = await res.json();
- if (res?.errCode === 0 && res?.vinfo) {
- const data = safetyParse(res?.vinfo);
- const m3u8 = data?.vl?.vi?.sort((a, b) => b.vw - a.vw)?.[0]?.ul;
- if (m3u8) {
- m3u8FileUrl = m3u8.ui[0].url;
- }
- }
- }
- const urls = await getUrlsByM3u8(m3u8FileUrl);
- return urls.map((url) => ({
- url,
- fileName: `download.mp4`
- }));
- };
- if (window.location.host === "v.qq.com") {
- monitor();
- }
- var qq_default = async () => {
- const urls = await getVideoInfo2();
- const files = await getFiles(urls);
- download(new Blob(files), "download.mp4");
- };
-
- // src/module/cctv.js
- var getVideoInfo3 = async () => {
- let data = await fetch(
- `https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=${window.guid}`
- );
- data = await data.json();
- const urls = data?.video?.[`chapters${data?.video?.validChapterNum}`];
- return { urls, fileName: `${data?.title}.mp4` };
- };
- var cctv_default = async () => {
- const { urls, fileName } = await getVideoInfo3();
- while (urls.length) {
- const file = await getFile(urls.shift().url);
- download(file, fileName);
- }
- };
-
- // src/module/youku.js
- var youku_default = async () => {
- if (!document.querySelector("meta#you-get-youku")) {
- const meta = document.createElement("meta");
- meta.httpEquiv = "Content-Security-Policy";
- meta.content = "upgrade-insecure-requests";
- meta.id = "you-get-youku";
- document.querySelector("head").appendChild(meta);
- }
- const data = window?.videoPlayer?.context?.mediaData?.mediaResource?._model;
- if (data) {
- const m3u8FileUrl = data.streamList.sort((a, b) => b.width - a.width)[0].uri.HLS;
- const urls = await getUrlsByM3u8(m3u8FileUrl, (i) => i);
- const files = await getFiles(urls.map((url) => ({ url })));
- download(new Blob(files), `${data.video.title}.ts`);
- }
- };
-
- // src/module/index.js
- var module_default = {
- ixigua: xigua_default,
- bilibili: bilibili_default,
- douyin: douyin_default,
- kuaishou: kuaishou_default,
- youtube: youtube_default,
- acfun: acfun_default,
- qq: qq_default,
- cctv: cctv_default,
- youku: youku_default
- };
-
- // src/index.js
- var fetch2 = window.fetch;
- var youget = () => {
- const handler = Object.entries(module_default).find(
- ([key, fn]) => window.location.host.toLocaleLowerCase().includes(key)
- )?.[1];
- if (handler) {
- handler();
- } else {
- console.log("not support");
- }
- };
- youget.toString = () => {
- youget();
- return 1;
- };
- window.you = 1;
- window.get = youget;
- window.youget = youget;
- })();