Greasy Fork

Greasy Fork is available in English.

bilibili Video CDN

change bilibili video CDN URL

目前为 2024-01-02 提交的版本。查看 最新版本

// ==UserScript==
// @name           bilibili Video CDN
// @version        1.0.0
// @description    change bilibili video CDN URL
// @author         Vanisoul
// @match          https://www.bilibili.com/*
// @license        MIT
// @namespace      http://greasyfork.icu/users/429936
// @grant          GM_registerMenuCommand
// @grant          GM_setValue
// @grant          GM_getValue
// ==/UserScript==

(function () {
    'use strict';

    const bilivideoRegex = /^https:\/\/[a-z.-\d]*(bilivideo.com)/i;
    const akamaizedRegex = /^https:\/\/upos[a-z.-\d]*(akamaized.net)/i;
    const poolCdns = [
        'upos-sz-mirrorks3.bilivideo.com',
        'upos-sz-mirrorks3b.bilivideo.com',
        'upos-sz-mirrorks3c.bilivideo.com',
        'upos-sz-mirrorks32.bilivideo.com',
        'upos-sz-mirrorcos.bilivideo.com',
        'upos-sz-mirrorcosb.bilivideo.com',
        'upos-sz-mirrorbos.bilivideo.com',
        'upos-sz-mirrorhw.bilivideo.com',
        'upos-sz-mirrorhwb.bilivideo.com',
        'upos-sz-upcdnbda2.bilivideo.com',
        'upos-sz-upcdnws.bilivideo.com',
        'upos-sz-upcdnhw.bilivideo.com',
        'upos-tf-all-js.bilivideo.com',
        'cn-hk-eq-bcache-01.bilivideo.com',
        'upos-hz-mirrorakam.akamaized.net',
        'upos-sz-mirrorali.bilivideo.com',
        'upos-sz-mirroraliov.bilivideo.com',
        'upos-sz-mirror08h.bilivideo.com',
    ];
    const defaultSelectedCDNs = [
        'upos-sz-mirror08h.bilivideo.com',
    ];
    GM_registerMenuCommand('選擇 CDN', chooseCDNs);
    function chooseCDNs() {
        const savedCDNs = GM_getValue('selectedCDNs', defaultSelectedCDNs);
        const dialog = document.createElement('div');
        dialog.style.position = 'absolute';
        dialog.style.top = '50%';
        dialog.style.left = '50%';
        dialog.style.transform = 'translate(-50%, -50%)';
        dialog.style.backgroundColor = 'white';
        dialog.style.padding = '20px';
        dialog.style.border = '1px solid black';
        dialog.style.boxShadow = '0px 0px 10px rgba(0,0,0,0.5)';
        dialog.style.zIndex = "1000";
        dialog.innerHTML = '<h3>選擇 CDN</h3>';
        poolCdns.forEach(cdn => {
            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.id = cdn;
            checkbox.checked = savedCDNs.includes(cdn);
            const label = document.createElement('label');
            label.htmlFor = cdn;
            label.textContent = cdn;
            dialog.appendChild(checkbox);
            dialog.appendChild(label);
            dialog.appendChild(document.createElement('br'));
        });
        const saveButton = document.createElement('button');
        saveButton.textContent = '保存設置';
        saveButton.onclick = function () {
            let selectedCDNs = poolCdns.filter(cdn => { var _a; return (_a = document.getElementById(cdn)) === null || _a === void 0 ? void 0 : _a.checked; });
            GM_setValue('selectedCDNs', selectedCDNs);
            alert('設置已保存');
            dialog.remove();
        };
        dialog.appendChild(saveButton);
        document.body.appendChild(dialog);
    }
    const httpRequestOriginOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function () {
        const savedCDNs = GM_getValue('selectedCDNs', defaultSelectedCDNs);
        const [method, url, async, user, password] = arguments;
        const isBiliBiliVideo = bilivideoRegex.test(url) || akamaizedRegex.test(url);
        if (!isBiliBiliVideo) {
            return httpRequestOriginOpen.apply(this, [method, url, async, user, password]);
        }
        const videoUrl = new URL(url);
        const isGoodUrl = savedCDNs.includes(videoUrl.host);
        if (isGoodUrl) {
            return httpRequestOriginOpen.apply(this, [method, url, async, user, password]);
        }
        else {
            const goodUrl = savedCDNs[Math.floor(Math.random() * savedCDNs.length)];
            videoUrl.host = goodUrl;
            return httpRequestOriginOpen.apply(this, [method, videoUrl.href, async, user, password]);
        }
    };

})();