Closed soulslaver closed 4 years ago
// ==UserScript== // @name Bilibili 港澳台 // @namespace http://kghost.info/ // @version 1.3.6 // @description: Remove area restriction // @description:zh-CN 解除区域限制 (修正大会员限制,添加国际友人看国内功能) // @supportURL https://github.com/kghost/bilibili-area-limit // @author zealot0630 // @include https://*.bilibili.com/* // @run-at document-start // @description Bilibili 港澳台, 解除区域限制 (修正大会员限制,添加国际友人看国内功能) // @grant GM_notification // @grant GM_cookie // @grant GM.setValue // @grant GM.getValue // ==/UserScript==
/**/ (function(modules) { // webpackBootstrap /**/ // The module cache /**/ var installedModules = {}; /**/ /**/ // The require function /**/ function webpack_require(moduleId) { /**/ /**/ // Check if module is in cache /**/ if(installedModules[moduleId]) { /**/ return installedModules[moduleId].exports; /**/ } /**/ // Create a new module (and put it into the cache) /**/ var module = installedModules[moduleId] = { /**/ i: moduleId, /**/ l: false, /**/ exports: {} /**/ }; /**/ /**/ // Execute the module function /**/ modules[moduleId].call(module.exports, module, module.exports, webpack_require); /**/ /**/ // Flag the module as loaded /**/ module.l = true; /**/ /**/ // Return the exports of the module /**/ return module.exports; /**/ } /**/ /**/ /**/ // expose the modules object (webpack_modules) /**/ webpack_require.m = modules; /**/ /**/ // expose the module cache /**/ webpack_require.c = installedModules; /**/ /**/ // define getter function for harmony exports /**/ webpack_require.d = function(exports, name, getter) { /**/ if(!webpack_require.o(exports, name)) { /**/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /**/ } /**/ }; /**/ /**/ // define esModule on exports /**/ __webpack_require.r = function(exports) { /**/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /**/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /**/ } /**/ Object.defineProperty(exports, 'esModule', { value: true }); /**/ }; /**/ /**/ // create a fake namespace object /**/ // mode & 1: value is a module id, require it /**/ // mode & 2: merge all properties of value into the ns /**/ // mode & 4: return value when already ns object /**/ // mode & 8|1: behave like require /**/ webpack_require.t = function(value, mode) { /**/ if(mode & 1) value = webpack_require(value); /**/ if(mode & 8) return value; /**/ if((mode & 4) && typeof value === 'object' && value && value.esModule) return value; /**/ var ns = Object.create(null); /**/ webpack_require.r(ns); /**/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /**/ if(mode & 2 && typeof value != 'string') for(var key in value) webpack_require.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /**/ return ns; /**/ }; /**/ /**/ // getDefaultExport function for compatibility with non-harmony modules /**/ webpack_require.n = function(module) { /**/ var getter = module && module.esModule ? /**/ function getDefault() { return module['default']; } : /**/ function getModuleExports() { return module; }; /**/ __webpack_require.d(getter, 'a', getter); /**/ return getter; /**/ }; /**/ /**/ // Object.prototype.hasOwnProperty.call /**/ webpack_require.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /**/ /**/ // webpack_public_path /**/ webpack_require.p = ""; /**/ /**/ /**/ // Load entry module and return exports /**/ return webpack_require(webpack_require.s = "./src/main.js"); /**/ }) /****/ /**/ ({
// "./src/main.js": /!*****!*\ !** ./src/main.js ! *****/ /! no exports provided / /***/ (function(module, webpack_exports, webpack_require) {
"use strict"; webpack_require.r(webpack_exports); / harmony import / var _urlWEBPACK_IMPORTED_MODULE_0 = webpack_require(/! ./url / "./src/url.js");
(function(XMLHttpRequest) { class ClassHandler { constructor(proxy) { this.proxy = proxy; }
construct(target, args) { const obj = new target(...args); return new Proxy(obj, new this.proxy(obj)); }
}
const ProxyGetTarget = Symbol('ProxyGetTarget'); const ProxyGetHandler = Symbol('ProxyGetHandler'); class ObjectHandler { constructor(target) { this.target = target; }
get(target, prop, receiver) { if (target.hasOwnProperty(prop)) { return Reflect.get(target, prop, receiver); } else if (prop == ProxyGetTarget) { return target; } else if (prop == ProxyGetHandler) { return this; } else { const value = target[prop]; if (typeof value == 'function') return new Proxy(value, new FunctionHandler(value)); return value; } } set(target, prop, value) { return Reflect.set(target, prop, value); }
class FunctionHandlerBase extends ObjectHandler { apply(target, thisArg, argumentsList) { const realTarget = thisArg[ProxyGetTarget]; if (!realTarget) throw new Error('illegal invocations'); return this.call(this.target, thisArg, realTarget, argumentsList); } }
class FunctionHandler extends FunctionHandlerBase { call(fn, proxy, target, argumentsList) { return fn.apply(target, argumentsList); } }
class EventTargetHandler extends ObjectHandler { constructor(target) { super(target); this.listeners = {}; }
getListeners(event) { if (!this.listeners.hasOwnProperty(event)) this.listeners[event] = new Map(); return this.listeners[event]; } get(target, prop, receiver) { if (prop === 'addEventListener') { return new Proxy( target.addEventListener, new this.addEventListener(target.addEventListener) ); } else if (prop === 'removeEventListener') { return new Proxy( target.removeEventListener, new this.removeEventListener(target.removeEventListener) ); } else return super.get(target, prop, receiver); }
EventTargetHandler.prototype.addEventListener = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { const event = argumentsList[0]; const listener = argumentsList[1]; const bridge = listener.bind(proxy); argumentsList[1] = bridge; proxy[ProxyGetHandler].getListeners(event).set(listener, bridge); return fn.apply(realTarget, argumentsList); } };
EventTargetHandler.prototype.removeEventListener = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { const event = argumentsList[0]; const listener = argumentsList[1]; const cache = proxy[ProxyGetHandler].getListeners(event); if (cache.has(listener)) { argumentsList[1] = cache.get(listener); cache.delete(listener); } return fn.apply(realTarget, argumentsList); } };
class XhrHandler extends EventTargetHandler { constructor(target) { super(target); this.overrideResponse = false; this.overrideResponseValue = null; }
get(target, prop, receiver) { if (prop === 'open') { return new Proxy(target.open, new this.open(target.open)); } else if (prop === 'send') { return new Proxy(target.send, new this.send(target.send)); } else if (prop === 'response' && this.overrideResponse) { console.log('BAL: Return hooked area limit'); return this.overrideResponseValue; } else if (prop === 'responseText' && this.overrideResponse) { console.log('BAL: Return hooked area limit'); return this.overrideResponseValue; } else { return super.get(target, prop, receiver); } }
const showTamperMonkeyUpdate = () => { GM.getValue('arealimit__', 0).then(last => { if (last > new Date().getTime() - 86400000) return; if ( confirm( 'Bilibili 港澳台: 无法获取播放文件信息,如果已开通大会员,请升级油猴到BETA版本' ) ) { window.open( 'https://chrome.google.com/webstore/detail/tampermonkey-beta/gcalenpjmijncebpfijmoaglllgpjagf', '_blank' ); } else { GM.setValue('arealimit__', new Date().getTime()); } }); };
let limited = false; XhrHandler.prototype.open = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { const method = argumentsList[0]; const url = argumentsList[1];
if (method === 'GET') { if (limited && url.match(_url__WEBPACK_IMPORTED_MODULE_0__["url_play"])) { for (const [regs, to] of _url__WEBPACK_IMPORTED_MODULE_0__["url_replace_to"]) { function any() { for (const reg of regs) { if (document.title.match(reg)) return true; } return false; } if (any()) { argumentsList[1] = url.replace(_url__WEBPACK_IMPORTED_MODULE_0__["url_api_replace"], to.api); realTarget.hookCookie = true; console.log(`BAL: playurl via proxy ${to.api}.`); break; } } } else if ( (function() { for (const status of _url__WEBPACK_IMPORTED_MODULE_0__["url_status"]) { if (url.match(status)) return true; } })() ) { realTarget.addEventListener('readystatechange', () => { if (realTarget.readyState === 4 && realTarget.status === 200) { const status = JSON.parse(realTarget.response); if (status && status.result && status.result.area_limit === 1) { status.result.area_limit = 0; limited = true; console.log('BAL: Hook area limit'); proxy[ProxyGetHandler].overrideResponse = true; proxy[ProxyGetHandler].overrideResponseValue = JSON.stringify( status ); } } }); } } return fn.apply(realTarget, argumentsList); }
};
XhrHandler.prototype.send = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { if (realTarget.hookCookie) { GM_cookie.list( { domain: '.bilibili.com', name: 'SESSDATA' }, (cookies, error) => { if (error) { console.log('BAL: Error fetch cookie, not login'); realTarget.addEventListener('readystatechange', () => { if (realTarget.readyState === 4 && realTarget.status === 200) { const status = JSON.parse(realTarget.response); if (status.code == -10403) showTamperMonkeyUpdate(); } }); fn.apply(realTarget, argumentsList); } else { console.log(BAL: Get Cookie ${cookies}); realTarget.setRequestHeader('X-Cookie', cookies[0].value); fn.apply(realTarget, argumentsList); } } ); } else { fn.apply(realTarget, argumentsList); } } };
BAL: Get Cookie ${cookies}
unsafeWindow.XMLHttpRequest = new Proxy( XMLHttpRequest, new ClassHandler(XhrHandler) );
(() => { var info = undefined; Object.defineProperty(unsafeWindow, '__PGC_USERSTATE__', { configurable: true, get: () => info, set: v => { if (v.area_limit == 1) { console.log('BAL: modify area_limit = 0'); limited = true; v.area_limit = 0; } info = v; }, }); })();
window.addEventListener('load', () => { if (document.querySelector('div.error-body')) { // try load via proxy console.log('BAL: Load failed, try use proxy'); const avid = /\/av(\d*)/gm.exec(window.location.pathname)[1]; for (const [u, loc] of _url__WEBPACK_IMPORTED_MODULE_0__["url_replace_to"]) { const detail = loc.api + 'x/web-interface/view/detail?aid=' + avid; const xhr = new unsafeWindow.XMLHttpRequest(); xhr.open('GET', detail); xhr.hookCookie = true; xhr.onreadystatechange = function() { if (this.readyState === xhr.DONE && this.status === 200) { const r = JSON.parse(this.responseText).data.View.redirect_url; console.log(BAL: Redirected to ${r}.); window.location = r; } }; xhr.send(); } } }); })(XMLHttpRequest);
BAL: Redirected to ${r}.
/***/ }),
// "./src/url.js": /!**!*\ ! ./src/url.js ! ******/ /! exports provided: url_status, url_play, url_api_replace, url_replace_to / /*/ (function(module, webpack_exports, webpack_require) {
"use strict"; webpack_require.r(webpack_exports); / harmony export (binding) / webpack_require.d(webpack_exports, "url_status", function() { return url_status; }); / harmony export (binding) / webpack_require.d(webpack_exports, "url_play", function() { return url_play; }); / harmony export (binding) / webpack_require.d(webpack_exports, "url_api_replace", function() { return url_api_replace; }); / harmony export (binding) / webpack_require.d(webpack_exports, "url_replace_to", function() { return url_replace_to; }); const url_status = [ /^https:\/\/bangumi.bilibili.com\/view\/web_api\/season\/user\/status\?./, /^https:\/\/api.bilibili.com\/pgc\/view\/web\/season\/user\/status\?./, ];
const url_play = /^https:\/\/api.bilibili.com\/pgc\/player\/web\/playurl\?.*/;
const url_api_replace = /^https:\/\/api.bilibili.com\//;
const url_replace_to = [ [ // TW [/僅.台/], { api: 'https://bilibili-tw-api.kghost.info/', }, ], [ // HK [/僅.港/], { api: 'https://bilibili-hk-api.kghost.info/', }, ], [ // SG [/仅限东南亚/], { api: 'https://bilibili-sg-api.kghost.info/', }, ], [ // CN [/^((?!僅).)*$/], { api: 'https://bilibili-cn-api.kghost.info/', }, ], ];
/***/ })
/**/ }); //# sourceMappingURL=bundle.js.map
这里是 Issues,不是 Wiki 页面,如果愿意提供文档更新,请使用 Pull Request 功能。
// ==UserScript== // @name Bilibili 港澳台 // @namespace http://kghost.info/ // @version 1.3.6 // @description: Remove area restriction // @description:zh-CN 解除区域限制 (修正大会员限制,添加国际友人看国内功能) // @supportURL https://github.com/kghost/bilibili-area-limit // @author zealot0630 // @include https://*.bilibili.com/* // @run-at document-start // @description Bilibili 港澳台, 解除区域限制 (修正大会员限制,添加国际友人看国内功能) // @grant GM_notification // @grant GM_cookie // @grant GM.setValue // @grant GM.getValue // ==/UserScript==
/**/ (function(modules) { // webpackBootstrap /**/ // The module cache /**/ var installedModules = {}; /**/ /**/ // The require function /**/ function webpack_require(moduleId) { /**/ /**/ // Check if module is in cache /**/ if(installedModules[moduleId]) { /**/ return installedModules[moduleId].exports; /**/ } /**/ // Create a new module (and put it into the cache) /**/ var module = installedModules[moduleId] = { /**/ i: moduleId, /**/ l: false, /**/ exports: {} /**/ }; /**/ /**/ // Execute the module function /**/ modules[moduleId].call(module.exports, module, module.exports, webpack_require); /**/ /**/ // Flag the module as loaded /**/ module.l = true; /**/ /**/ // Return the exports of the module /**/ return module.exports; /**/ } /**/ /**/ /**/ // expose the modules object (webpack_modules) /**/ webpack_require.m = modules; /**/ /**/ // expose the module cache /**/ webpack_require.c = installedModules; /**/ /**/ // define getter function for harmony exports /**/ webpack_require.d = function(exports, name, getter) { /**/ if(!webpack_require.o(exports, name)) { /**/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /**/ } /**/ }; /**/ /**/ // define esModule on exports /**/ __webpack_require.r = function(exports) { /**/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /**/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /**/ } /**/ Object.defineProperty(exports, 'esModule', { value: true }); /**/ }; /**/ /**/ // create a fake namespace object /**/ // mode & 1: value is a module id, require it /**/ // mode & 2: merge all properties of value into the ns /**/ // mode & 4: return value when already ns object /**/ // mode & 8|1: behave like require /**/ webpack_require.t = function(value, mode) { /**/ if(mode & 1) value = webpack_require(value); /**/ if(mode & 8) return value; /**/ if((mode & 4) && typeof value === 'object' && value && value.esModule) return value; /**/ var ns = Object.create(null); /**/ webpack_require.r(ns); /**/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /**/ if(mode & 2 && typeof value != 'string') for(var key in value) webpack_require.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /**/ return ns; /**/ }; /**/ /**/ // getDefaultExport function for compatibility with non-harmony modules /**/ webpack_require.n = function(module) { /**/ var getter = module && module.esModule ? /**/ function getDefault() { return module['default']; } : /**/ function getModuleExports() { return module; }; /**/ __webpack_require.d(getter, 'a', getter); /**/ return getter; /**/ }; /**/ /**/ // Object.prototype.hasOwnProperty.call /**/ webpack_require.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /**/ /**/ // webpack_public_path /**/ webpack_require.p = ""; /**/ /**/ /**/ // Load entry module and return exports /**/ return webpack_require(webpack_require.s = "./src/main.js"); /**/ }) /****/ /**/ ({
// "./src/main.js": /!*****!*\ !** ./src/main.js ! *****/ /! no exports provided / /***/ (function(module, webpack_exports, webpack_require) {
"use strict"; webpack_require.r(webpack_exports); / harmony import / var _urlWEBPACK_IMPORTED_MODULE_0 = webpack_require(/! ./url / "./src/url.js");
(function(XMLHttpRequest) { class ClassHandler { constructor(proxy) { this.proxy = proxy; }
}
const ProxyGetTarget = Symbol('ProxyGetTarget'); const ProxyGetHandler = Symbol('ProxyGetHandler'); class ObjectHandler { constructor(target) { this.target = target; }
}
class FunctionHandlerBase extends ObjectHandler { apply(target, thisArg, argumentsList) { const realTarget = thisArg[ProxyGetTarget]; if (!realTarget) throw new Error('illegal invocations'); return this.call(this.target, thisArg, realTarget, argumentsList); } }
class FunctionHandler extends FunctionHandlerBase { call(fn, proxy, target, argumentsList) { return fn.apply(target, argumentsList); } }
class EventTargetHandler extends ObjectHandler { constructor(target) { super(target); this.listeners = {}; }
}
EventTargetHandler.prototype.addEventListener = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { const event = argumentsList[0]; const listener = argumentsList[1]; const bridge = listener.bind(proxy); argumentsList[1] = bridge; proxy[ProxyGetHandler].getListeners(event).set(listener, bridge); return fn.apply(realTarget, argumentsList); } };
EventTargetHandler.prototype.removeEventListener = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { const event = argumentsList[0]; const listener = argumentsList[1]; const cache = proxy[ProxyGetHandler].getListeners(event); if (cache.has(listener)) { argumentsList[1] = cache.get(listener); cache.delete(listener); } return fn.apply(realTarget, argumentsList); } };
class XhrHandler extends EventTargetHandler { constructor(target) { super(target); this.overrideResponse = false; this.overrideResponseValue = null; }
}
const showTamperMonkeyUpdate = () => { GM.getValue('arealimit__', 0).then(last => { if (last > new Date().getTime() - 86400000) return; if ( confirm( 'Bilibili 港澳台: 无法获取播放文件信息,如果已开通大会员,请升级油猴到BETA版本' ) ) { window.open( 'https://chrome.google.com/webstore/detail/tampermonkey-beta/gcalenpjmijncebpfijmoaglllgpjagf', '_blank' ); } else { GM.setValue('arealimit__', new Date().getTime()); } }); };
let limited = false; XhrHandler.prototype.open = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { const method = argumentsList[0]; const url = argumentsList[1];
};
XhrHandler.prototype.send = class extends FunctionHandlerBase { call(fn, proxy, realTarget, argumentsList) { if (realTarget.hookCookie) { GM_cookie.list( { domain: '.bilibili.com', name: 'SESSDATA' }, (cookies, error) => { if (error) { console.log('BAL: Error fetch cookie, not login'); realTarget.addEventListener('readystatechange', () => { if (realTarget.readyState === 4 && realTarget.status === 200) { const status = JSON.parse(realTarget.response); if (status.code == -10403) showTamperMonkeyUpdate(); } }); fn.apply(realTarget, argumentsList); } else { console.log(
BAL: Get Cookie ${cookies}
); realTarget.setRequestHeader('X-Cookie', cookies[0].value); fn.apply(realTarget, argumentsList); } } ); } else { fn.apply(realTarget, argumentsList); } } };unsafeWindow.XMLHttpRequest = new Proxy( XMLHttpRequest, new ClassHandler(XhrHandler) );
(() => { var info = undefined; Object.defineProperty(unsafeWindow, '__PGC_USERSTATE__', { configurable: true, get: () => info, set: v => { if (v.area_limit == 1) { console.log('BAL: modify area_limit = 0'); limited = true; v.area_limit = 0; } info = v; }, }); })();
window.addEventListener('load', () => { if (document.querySelector('div.error-body')) { // try load via proxy console.log('BAL: Load failed, try use proxy'); const avid = /\/av(\d*)/gm.exec(window.location.pathname)[1]; for (const [u, loc] of _url__WEBPACK_IMPORTED_MODULE_0__["url_replace_to"]) { const detail = loc.api + 'x/web-interface/view/detail?aid=' + avid; const xhr = new unsafeWindow.XMLHttpRequest(); xhr.open('GET', detail); xhr.hookCookie = true; xhr.onreadystatechange = function() { if (this.readyState === xhr.DONE && this.status === 200) { const r = JSON.parse(this.responseText).data.View.redirect_url; console.log(
BAL: Redirected to ${r}.
); window.location = r; } }; xhr.send(); } } }); })(XMLHttpRequest);/***/ }),
// "./src/url.js": /!**!*\ ! ./src/url.js ! ******/ /! exports provided: url_status, url_play, url_api_replace, url_replace_to / /*/ (function(module, webpack_exports, webpack_require) {
"use strict"; webpack_require.r(webpack_exports); / harmony export (binding) / webpack_require.d(webpack_exports, "url_status", function() { return url_status; }); / harmony export (binding) / webpack_require.d(webpack_exports, "url_play", function() { return url_play; }); / harmony export (binding) / webpack_require.d(webpack_exports, "url_api_replace", function() { return url_api_replace; }); / harmony export (binding) / webpack_require.d(webpack_exports, "url_replace_to", function() { return url_replace_to; }); const url_status = [ /^https:\/\/bangumi.bilibili.com\/view\/web_api\/season\/user\/status\?./, /^https:\/\/api.bilibili.com\/pgc\/view\/web\/season\/user\/status\?./, ];
const url_play = /^https:\/\/api.bilibili.com\/pgc\/player\/web\/playurl\?.*/;
const url_api_replace = /^https:\/\/api.bilibili.com\//;
const url_replace_to = [ [ // TW [/僅.台/], { api: 'https://bilibili-tw-api.kghost.info/', }, ], [ // HK [/僅.港/], { api: 'https://bilibili-hk-api.kghost.info/', }, ], [ // SG [/仅限东南亚/], { api: 'https://bilibili-sg-api.kghost.info/', }, ], [ // CN [/^((?!僅).)*$/], { api: 'https://bilibili-cn-api.kghost.info/', }, ], ];
/***/ })
/**/ }); //# sourceMappingURL=bundle.js.map