Make BiliBili Great Again

useful tweaks for bilibili.com

目前为 2023-04-05 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Make BiliBili Great Again
  3. // @namespace https://www.kookxiang.com/
  4. // @version 1.4.5
  5. // @description useful tweaks for bilibili.com
  6. // @author kookxiang
  7. // @match https://*.bilibili.com/*
  8. // @run-at document-body
  9. // @grant unsafeWindow
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. GM_addStyle("html, body { -webkit-filter: none !important; filter: none !important; }");
  14.  
  15. window.addEventListener('load', function () {
  16. document.body.classList.remove('harmony-font');
  17. })
  18.  
  19. // 动态页面优化
  20. if (location.host === "t.bilibili.com") {
  21. GM_addStyle("html[wide] #app { display: flex; } html[wide] .bili-dyn-home--member { box-sizing: border-box;padding: 0 10px;width: 100%;flex: 1; } html[wide] .bili-dyn-content { width: initial; } html[wide] main { margin: 0 8px;flex: 1;overflow: hidden;width: initial; } #wide-mode-switch { margin-left: 0;margin-right: 20px; }");
  22. if (!localStorage.WIDE_OPT_OUT) {
  23. document.documentElement.setAttribute('wide', 'wide');
  24. }
  25. window.addEventListener('load', function () {
  26. const tabContainer = document.querySelector('.bili-dyn-list-tabs__list');
  27. const placeHolder = document.createElement('div');
  28. placeHolder.style.flex = 1;
  29. const switchButton = document.createElement('a');
  30. switchButton.id = 'wide-mode-switch';
  31. switchButton.className = 'bili-dyn-list-tabs__item';
  32. switchButton.textContent = '宽屏模式';
  33. switchButton.addEventListener('click', function (e) {
  34. e.preventDefault();
  35. if (localStorage.WIDE_OPT_OUT) {
  36. localStorage.removeItem('WIDE_OPT_OUT');
  37. document.documentElement.setAttribute('wide', 'wide');
  38. } else {
  39. localStorage.setItem('WIDE_OPT_OUT', '1');
  40. document.documentElement.removeAttribute('wide');
  41. }
  42. })
  43. tabContainer.appendChild(placeHolder);
  44. tabContainer.appendChild(switchButton);
  45. })
  46. }
  47.  
  48. // 去广告
  49. GM_addStyle('.ad-report, a[href*="cm.bilibili.com"] { display: none !important; }');
  50. if (unsafeWindow.__INITIAL_STATE__?.adData) {
  51. for (const key in unsafeWindow.__INITIAL_STATE__.adData) {
  52. for (const item of unsafeWindow.__INITIAL_STATE__.adData[key]) {
  53. item.name = 'B 站未来有可能会倒闭,但绝不会变质';
  54. item.pic = 'https://static.hdslb.com/images/transparent.gif';
  55. item.url = 'https://space.bilibili.com/208259';
  56. }
  57. }
  58. }
  59.  
  60. // 去充电列表(叔叔的跳过按钮越做越小了,就尼玛离谱)
  61. if (unsafeWindow.__INITIAL_STATE__?.elecFullInfo) {
  62. delete unsafeWindow.__INITIAL_STATE__.elecFullInfo;
  63. }
  64.  
  65. // 修复文章区复制
  66. if (location.href.startsWith('https://www.bilibili.com/read/cv')) {
  67. unsafeWindow.original.reprint = "1";
  68. document.querySelector('.article-holder').classList.remove("unable-reprint");
  69. document.querySelector('.article-holder').addEventListener('copy', e => e.stopImmediatePropagation(), true);
  70. }
  71.  
  72. // 去 P2P CDN
  73. if (location.href.startsWith('https://www.bilibili.com/video/') || location.href.startsWith('https://www.bilibili.com/bangumi/play/')) {
  74. let cdnDomain;
  75.  
  76. function replaceP2PUrl(url) {
  77. cdnDomain ||= document.head.innerHTML.match(/up[\w-]+\.bilivideo\.com/)?.[0];
  78.  
  79. try {
  80. const urlObj = new URL(url);
  81. const hostName = urlObj.hostname;
  82. if (urlObj.hostname.endsWith(".mcdn.bilivideo.cn")) {
  83. urlObj.host = cdnDomain || 'upos-sz-mirrorcoso1.bilivideo.com';
  84. urlObj.port = 443;
  85. console.warn(`更换视频源: ${hostName} -> ${urlObj.host}`);
  86. return urlObj.toString();
  87. } else if (urlObj.hostname.endsWith(".szbdyd.com")) {
  88. urlObj.host = urlObj.searchParams.get('xy_usource');
  89. urlObj.port = 443;
  90. console.warn(`更换视频源: ${hostName} -> ${urlObj.host}`);
  91. return urlObj.toString();
  92. }
  93. return url;
  94. } catch(e) {
  95. return url;
  96. }
  97. }
  98.  
  99. function replaceP2PUrlDeep(obj) {
  100. for (const key in obj) {
  101. if (typeof obj[key] === 'string') {
  102. obj[key] = replaceP2PUrl(obj[key]);
  103. } else if (typeof obj[key] === 'array' || typeof obj[key] === 'object') {
  104. replaceP2PUrlDeep(obj[key]);
  105. }
  106. }
  107. }
  108.  
  109. replaceP2PUrlDeep(unsafeWindow.__playinfo__);
  110.  
  111. (function (open) {
  112. unsafeWindow.XMLHttpRequest.prototype.open = function () {
  113. try {
  114. arguments[1] = replaceP2PUrl(arguments[1]);
  115. } finally {
  116. return open.apply(this, arguments);
  117. }
  118. }
  119. })(unsafeWindow.XMLHttpRequest.prototype.open);
  120. }
  121.  
  122. // 视频裁切
  123. if (location.href.startsWith('https://www.bilibili.com/video/')) {
  124. GM_addStyle("body[video-fit] #bilibili-player video { object-fit: cover; } .bpx-player-ctrl-setting-fit-mode { display: flex;width: 100%;height: 32px;line-height: 32px; } .bpx-player-ctrl-setting-box .bui-panel-wrap, .bpx-player-ctrl-setting-box .bui-panel-item { min-height: 172px !important; }");
  125. let timer;
  126. function toggleMode(enabled) {
  127. if (enabled) {
  128. document.body.setAttribute('video-fit', '');
  129. } else {
  130. document.body.removeAttribute('video-fit');
  131. }
  132. }
  133. function injectButton() {
  134. if (!document.querySelector('.bpx-player-ctrl-setting-menu-left')) {
  135. return;
  136. }
  137. clearInterval(timer);
  138. const parent = document.querySelector('.bpx-player-ctrl-setting-menu-left');
  139. const item = document.createElement('div');
  140. item.className = 'bpx-player-ctrl-setting-fit-mode bui bui-switch';
  141. item.innerHTML = '<input class="bui-switch-input" type="checkbox"><label class="bui-switch-label"><span class="bui-switch-name">裁切模式</span><span class="bui-switch-body"><span class="bui-switch-dot"><span></span></span></span></label>';
  142. parent.insertBefore(item, document.querySelector('.bpx-player-ctrl-setting-more'));
  143. document.querySelector('.bpx-player-ctrl-setting-fit-mode input').addEventListener('change', e => toggleMode(e.target.checked));
  144. document.querySelector('.bpx-player-ctrl-setting-box .bui-panel-item').style.height = '';
  145. }
  146. timer = setInterval(injectButton, 200);
  147. }
  148.  
  149. // 去掉 B 站的傻逼上报
  150. !function(){
  151. unsafeWindow.MReporter = {}
  152. unsafeWindow.navigator.sendBeacon = function(){}
  153. const sentryHub = class{ bindClient(){} }
  154. const fakeSentry = {
  155. SDK_NAME: 'sentry.javascript.browser',
  156. SDK_VERSION: '0.0.0',
  157. BrowserClient: class{},
  158. Hub: sentryHub,
  159. Integrations: { Vue: class{} },
  160. init(){},
  161. configureScope(){},
  162. getCurrentHub: new sentryHub(),
  163. setContext(){},
  164. setExtra(){},
  165. setExtras(){},
  166. setTag(){},
  167. setTags(){},
  168. setUser(){},
  169. wrap(){},
  170. }
  171. if (!unsafeWindow.Sentry || unsafeWindow.Sentry.SDK_VERSION !== fakeSentry.SDK_VERSION) {
  172. if (unsafeWindow.Sentry) { delete unsafeWindow.Sentry }
  173. Object.defineProperty(unsafeWindow, 'Sentry', { value: fakeSentry, enumerable: false, writable: false });
  174. }
  175. }()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址