you-get

视频下载 bilibili acfun youtube 西瓜 快手 抖音

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey to install this script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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;
})();