// ==UserScript== // @name GitHub 访问代理助手 // @namespace lzwme.github.fast // @author lzwme // @homepageURL https://github.com/lzwme/vm-gh-proxy-cn // @supportURL https://github.com/lzwme/vm-gh-proxy-cn/issues // @license MIT License // @description GitHub 访问加速助手。支持 GitHub 的 clone、release/raw/zip 下载加速 // @include *://github.com/* // @include *://github* // @include *://hub.fastgit.xyz/* // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.slim.min.js // @icon https://github.githubassets.com/favicon.ico // @version 1.0.4 // @downloadURL https://update.greasyfork.icu/scripts/461115/GitHub%20%E8%AE%BF%E9%97%AE%E4%BB%A3%E7%90%86%E5%8A%A9%E6%89%8B.user.js // @updateURL https://update.greasyfork.icu/scripts/461115/GitHub%20%E8%AE%BF%E9%97%AE%E4%BB%A3%E7%90%86%E5%8A%A9%E6%89%8B.meta.js // ==/UserScript== (function () { const clonePrefix = 'git clone --depth 1 '; const Mirrors = { ghproxynet: { url: 'https://ghproxy.net/github.com', name: 'gh-net', desc: 'ghproxy.net 代理', types: ['clone', 'download', 'raw'], format: url => `${Mirrors.ghproxy.url}/${url.replace(/^\//, '')}`, }, ghproxy: { url: 'https://mirror.ghproxy.com/github.com', name: 'ghproxy', desc: 'ghproxy 代理', types: ['clone', 'download', 'raw'], format: url => `${Mirrors.ghproxy.url}/${url.replace(/^\//, '')}`, }, ghproxy1: { url: 'https://gh.api.99988866.xyz/github.com', name: 'gh-xyz', desc: 'ghproxy 代理(演示站)', types: ['clone', 'download', 'raw'], format: url => `${Mirrors.ghproxy1.url}/${url.replace(/^\//, '')}`, }, netnr: { "url": "https://cors.zme.ink/https://github.com", "name": "netnr", "desc": "由@netnr提供", types: ['mirror', 'raw', 'download'], }, gitclone: { "url": "https://gitclone.com/github.com", "name": "gitclone加速", "desc": "gitclone加速", types: ['clone'], }, jsDelivr: { "url": "https://cdn.jsdelivr.net/gh", "name": "jsDelivr", "desc": "项目当前分支总文件大小不可超过 50MB", types: ['raw'], // download }, staticaly: { "url": "https://cdn.staticaly.com/gh", "name": "Statically", "desc": "只能浏览图片和源代码文件,文件大小限制为30MB", types: ['raw'], }, gitmirror: { // url: 'https://gitmirror.com', url: 'https://hub.gitmirror.com', desc: 'GitMirror 为您提供 Github 静态资源加速服务', types: ['download', 'raw'], }, fastgitSsh: { "url": "git@ssh.fastgit.org", "name": "FastGit", "desc": "fastgit ssh", types: ['clone'], }, fastgitSsh: { "url": "https://raw.fastgit.org", "name": "FastGit-raw", "desc": "fastgit raw", types: ['raw'], }, zhlh6: { "url": "git@git.zhlh6.cn", "name": "加速你的Github", "desc": "利用ucloud提供的GlobalSSH", types: ['clone'], }, // fastgitdl: { // url: 'https://download.fastgit.org', // todo: only release files、zip // name: 'fastgit-dl', // desc: 'fastgit download', // types: ['download'], // }, // wuyanzheshui: { // url: 'https://github.wuyanzheshui.workers.dev', // name: 'CF加速 1', // desc: '【CF加速】每日10万次调用上限,由 wuyanzheshui 提供', // types: ['mirror', 'clone', 'download'], // }, // rc1844: { // "url": "https://github.rc1844.workers.dev", // "name": "CF加速 2", // "desc": "【CF加速】每日10万次调用上限,由 @rc1844 提供", // types: ['clone', 'download', 'raw'], // }, // lzwme: { // "url": "https://gh.lzwme.workers.dev", // "name": "CF加速 2", // "desc": "【CF加速】每日10万次调用上限,由 @renxia 提供", // types: ['clone', 'download', 'raw', 'mirror'], // }, // gitclone: { // "url": "https://gitclone.com/github.com", // "name": "GitClone", // "desc": "GitHub clone 缓存加速网站", // types: ['clone'], // }, }; const OtherUrl = [ ["https://github.com/lzwme/vm-gh-proxy-cn", "脚本Github仓库地址,点个赞谢谢"], ["https://greasyfork.org/zh-CN/scripts/461115", "GreasyFork 地址,请评分收藏"], ["https://doc.fastgit.org/", "FastGit,请仔细甄别"], ["https://d.serctl.com", "GitHub中转下载"], ["https://gitee.com/organizations/mirrors/projects", "Gitee 极速下载"], ]; const MirrorsList = Object.values(Mirrors); MirrorsList.forEach(item => { if (!item.format) { item.format = (href, type) => { if (type === 'raw' && ['Statically', 'jsDelivr'].includes(item.name)) { return item.url + href.replace(`${repo}/raw/`, `${repo}@`); } const sep = item.url.includes('@') ? ':' : '/'; return `${item.url}${sep}${href.replace(/^\//, '')}`; }; } if (!item.types) item.types = ['raw']; if (!item.name) item.name = item.url.split('.')[1]; if (!item.desc) item.desc = item.name; }); const CloneSet = MirrorsList.filter(d => d.types.includes('clone')); const MirrorSet = MirrorsList.filter(d => d.types.includes('mirror')); const DownloadSet = MirrorsList.filter(d => d.types.includes('download')); const RawSet = MirrorsList.filter(d => d.types.includes('raw')); const isPC = !/Android|iPhone|iPad|iPod|Windows Phone|SymbianOS/i.test(navigator.userAgent); const observer = new MutationObserver(() => setTimeout(run, 1500)); observer.observe(document.querySelector('head'), { attributes: true, childList: true }); let pathname = ''; let repo = ''; function run() { if (location.pathname != pathname) { pathname = location.pathname; repo = location.href.match(/github.com\/([^\/]+\/[^\/]+)\/?/)?.[1]; addMenus(); addRawList(); if (location.pathname.split("/")[3] == "releases") addReleasesList(); if (isPC) addDownloadZip(); } } run(); initProxyButton(); initEvents(); /** * 添加Raw列表 */ function addRawList() { let rawUrl = $("#raw-url"); if (!rawUrl.length) rawUrl = $(`a[data-testid="raw-button"]:last`); const rawHref = rawUrl.attr('href'); if (!rawHref) return; $('.raw-btn-proxy').remove(); RawSet.forEach((item) => { const span = rawUrl.clone().removeAttr('id'); span.attr({ href: item.format(rawHref, 'raw'), title: item.desc, target: "_blank", }); span.text(item.name).addClass('raw-btn-proxy'); rawUrl.before(span); }); } /** * Fast Download ZIP */ function addDownloadZip() { $("a[data-open-app='link']").each(function () { const span = $(`
  • `); const href = $(this).attr("href"); const clone = $(this) .clone() .removeAttr("data-hydro-click data-hydro-click-hmac data-ga-click") .addClass("Box-row Box-row--hover-gray"); DownloadSet.forEach(item => { const span1 = $(clone.html().replace("Download ZIP", `Download ZIP(${item.name})`)).attr({ href: item.format(href), title: item.desc, }); span.append(span1); }); $(this).parent().after(span); }); } /** * 添加Releases列表 */ function addReleasesList(retry = 3) { const $alist = $(".Box--condensed").find("[href]"); if (!$alist.length && retry) return setTimeout(() => addReleasesList(--retry), 1000); $alist.each(function() { const $el = $(this); const href = $el.attr('href'); $el.parent() .after(`
    ${ DownloadSet.map((item) => { return `${item.name}`; }).join('') }
    `); $el.parent().parent().css({ position: 'relative' }); }); } /** * 添加菜单列表 */ function addMenus() { if (!repo) return; const repoGit = `${repo}.git`; const info = `
    克隆与镜像
    镜像站点与快速克隆
    ${ CloneSet.map((item) => cloneHtml(`${clonePrefix}${item.format(repoGit, 'clone')}`, item.name)).join('') }${ cloneHtml("git remote set-url origin https://github.com/" + repoGit, "还原GitHub仓库地址") } ${ addBrowseList() }
    `; $('#mirror-menu').remove(); // remove old $(".pagehead-actions").before(info); function cloneHtml(Url, Tip) { return `
    `; } } /** * 添加镜像浏览列表 */ function addBrowseList() { const path = window.location.pathname; const info = MirrorSet.map(item => listHtml(item.format(path, 'mirror'), `镜像浏览(${item.name})`, item.desc)); if (location.hostname != "github.com") info.push(listHtml(`https://github.com${path}`, "返回GitHub")); return info.join(''); } function initProxyButton() { $('#js-repo-pjax-container').off('mouseenter', 'a').on('mouseenter', 'a', function(ev) { const $el = $(this); if ($el.attr('id') === 'gh-proxy-btn') return; const preBtn = $('#gh-proxy-btn'); const href =$el.attr('href').replace(/^https:\/\/github\.com/, ''); const proxyHref = `${Mirrors.ghproxy.url}${href}`; if (!/\/(blob|release|archive)\//.test(href) || href.startsWith('http') || preBtn.attr('href') === proxyHref) return; $('#gh-proxy-btn').remove(); const $btn = $(`🚀`); $el.parent().append($btn).css({ position: 'relative', overflow: 'visible' }); $btn.css({ position: 'absolute', left: 120, top: 2 }); $btn.on('mouseleave', () => $btn.remove()); }); } function initEvents() { $(document).on('click', 'a', function(ev) { const $el = $(this); const href = $el.attr('href'); if (['cors.zme.ink'].includes(location.host) && href.startsWith('/')) { ev.preventDefault(); const hrefFixed = `${location.origin}/https://github.com${href}`; $el.attr('target') === '_blank' ? window.open(hrefFixed) : location.href = hrefFixed; } }); } function listHtml(url, name, desc = "") { return ` ${name}`; } })();