https://note.src.moe/fhcq BV11c411q7SM BV1Lm4y1W7zo data-zop='{"authorName":"${target.author.name}","itemId":${target.id},"title":"${target.question.title}","type":"${targetType}"}' 改成 data-zop='{"authorName":"${target.author.name}","itemId":"${target.id}","title":"${target.question.title}","type":"${targetType}"}' https://mirrorbits.lineageos.org/full/polaris/20250101/lineage-22.2-20250101-nightly-polaris-signed.zip https://wayland.freedesktop.org/libinput/doc/latest/device-configuration-via-udev.html https://gitlab.com/brlin/linux-input-utils -1f0d-462e-ba76-627b344989f2/openai.yaml sudo evtest --grab /dev/input/event4 >/dev/null https://raw.githubusercontent.com/Cats-Team/AdRules/main/adblock.txt nvme_core.default_ps_max_latency_us=5500 【【忍唱大挑战】当年大爆的韩流洗脑神曲,DNA真的控制不住动了!】 https://www.bilibili.com/videoBV19n53zBEw5 https://m.weibo.cn/status/5168690745054444?jumpfrom=weibocom 15:/!G9HZo4b0Sh47agv2! MU5104 // ==UserScript== // @name Bilibili - 在未登录的情况下自动并无限试用最高画质 // @namespace https://bilibili.com/ // @version 1.5 // @description 在未登录的情况下自动并无限试用最高画质 | V1.5 代码优化 & 新增自定义设置面板 // @license GPL-3.0 // @author DD1969 // @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/list/* // @match https://www.bilibili.com/festival/* // @icon https://www.bilibili.com/favicon.ico // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @run-at document-start // ==/UserScript== (async function() { 'use strict'; // initialize options const options = { // 偏好分辨率 preferQuality: GM_getValue('preferQuality', '1080'), // 是否暂停播放视频直至画质切换完成(以此规避音画不同步现象) isWaitUntilHighQualityLoaded: GM_getValue('isWaitUntilHighQualityLoaded', false), } // essential keys const keys = ['bilibili_player_codec_prefer_type', 'b_miniplayer', 'recommend_auto_play', 'bpx_player_profile']; // apply configs from scriptStorage to localStorage keys.forEach(key => { const value = GM_getValue(key); if (value) window.localStorage.setItem(key, value); }); // override 'setItem' const originSetItem = Storage.prototype.setItem; Storage.prototype.setItem = function(key, value) { // fix TypeError: Cannot read properties of null (reading 'offLoudness') at turnOffLoudnessNormalization if (key === 'bpx_player_profile') { const profile = JSON.parse(value); if (!profile.audioEffect) profile.audioEffect = {}; value = JSON.stringify(profile); } originSetItem.call(this, key, value); // save configs into scriptStorage if (keys.includes(key)) { setTimeout(() => { GM_setValue('bilibili_player_codec_prefer_type', window.localStorage.getItem('bilibili_player_codec_prefer_type') || '0'); GM_setValue('b_miniplayer', window.localStorage.getItem('b_miniplayer') || '1'); GM_setValue('recommend_auto_play', window.localStorage.getItem('recommend_auto_play') || 'open'); GM_setValue('bpx_player_profile', window.localStorage.getItem('bpx_player_profile') || `{ lastView: ${Date.now() - 864e5}, lastUid: 0 }`); }, 100); } } // no need to continue this script if user has logged in if (document.cookie.includes('DedeUserID')) return; // setup setting panel & entry setupSettingPanel(); setupSettingPanelEntry(); // enable trial every time a new video loaded const originDefineProperty = Object.defineProperty; Object.defineProperty = function(obj, prop, descriptor) { if (prop === 'isViewToday' || prop === 'isVideoAble') { descriptor = { get: () => true, enumerable: !1, configurable: !0 } } return originDefineProperty.call(this, obj, prop, descriptor); } // extend trial time by overriding "setTimeout" const originSetTimeout = unsafeWindow.setTimeout; unsafeWindow.setTimeout = function(func, delay) { if (delay === 3e4) delay = 3e8; return originSetTimeout.call(this, func, delay); } // click the trial button automatically setInterval(async () => { const trialBtn = document.querySelector('.bpx-player-toast-confirm-login'); if (!trialBtn) return; // start trialling await new Promise(resolve => setTimeout(resolve, 1000)); trialBtn.click(); // avoid audio and video out of sync if (options.isWaitUntilHighQualityLoaded) { // pause if playing const isPlaying = !unsafeWindow.player.mediaElement().paused; if (isPlaying) unsafeWindow.player.mediaElement().pause(); // search for end signal const timer4Toast = setInterval(() => { const toasts = Array.from(document.querySelectorAll('.bpx-player-toast-text')); if (toasts.some(toast => toast.textContent.endsWith('试用中'))) { if (isPlaying) unsafeWindow.player.mediaElement().play();; clearInterval(timer4Toast); } }, 100); } // switch to preferred video quality const preferQualityNum = ({ '1080': 80, '720': 64, '480': 32, '360': 16 })[options.preferQuality] || 80; setTimeout(() => { if (unsafeWindow.player.getSupportedQualityList()?.includes(preferQualityNum) && preferQualityNum < unsafeWindow.player.getQuality().nowQ) { unsafeWindow.player.requestQuality(preferQualityNum); } }, 5000); }, 1500); // ---------- functions below ---------- function setupSettingPanel() { // CSS const settingPanelCSS = document.createElement('style'); settingPanelCSS.textContent = ` #userscript-467511-setting-panel-container { position: fixed; top: 0; left: 0; z-index: 999999999; width: 100vw; height: 100vh; display: none; flex-direction: column; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.5); } .userscript-467511-setting-panel-wrapper { width: 600px; padding: 16px; display: flex; flex-direction: column; background-color: #FFFFFF; border-radius: 8px; user-select: none; } .userscript-467511-setting-panel-title { margin-top: 0; margin-bottom: 8px; padding-top: 16px; padding-left: 12px; font-size: 28px; } .userscript-467511-setting-panel-option-group { display: flex; flex-direction: column; width: 100%; font-size: 16px; } .userscript-467511-setting-panel-option-item { padding: 16px 16px; display: flex; justify-content: space-between; align-items: center; border-radius: 4px; } .userscript-467511-setting-panel-option-item:hover { background-color: #FAFAFA; } .userscript-467511-setting-panel-option-item-switch { display: flex; align-items: center; width: 40px; height: 20px; padding: 2px; cursor: pointer; border-radius: 4px; } .userscript-467511-setting-panel-option-item-switch[data-status="off"] { justify-content: flex-start; background-color: #CCCCCC; } .userscript-467511-setting-panel-option-item-switch[data-status="on"] { justify-content: flex-end; background-color: #00AEEC; } .userscript-467511-setting-panel-option-item-switch:after { content: ''; width: 20px; height: 20px; background-color: #FFFFFF; border-radius: 4px; } #userscript-467511-setting-panel-close-btn { margin-top: 16px; padding: 2px; width: 20px; height: 20px; display: flex; justify-content: center; align-items: center; font-size: 20px; color: #FFFFFF; border: 2px solid #FFFFFF; border-radius: 100%; cursor: pointer; user-select: none; } `; // HTML const containerElement = document.createElement('div'); containerElement.id = 'userscript-467511-setting-panel-container'; containerElement.innerHTML = ` <div class="userscript-467511-setting-panel-wrapper"> <p class="userscript-467511-setting-panel-title">自定义设置</p> <div class="userscript-467511-setting-panel-option-group"> <div class="userscript-467511-setting-panel-option-item"> <span class="userscript-467511-setting-panel-option-item-title">偏好分辨率</span> <select class="userscript-467511-setting-panel-option-item-select" data-key="preferQuality" name="preferQuality"> <option value="1080" ${options.preferQuality === '1080' ? 'selected' : ''}>1080p</option> <option value="720" ${options.preferQuality === '720' ? 'selected' : ''}>720p</option> <option value="480" ${options.preferQuality === '480' ? 'selected' : ''}>480p</option> <option value="360" ${options.preferQuality === '360' ? 'selected' : ''}>360p</option> </select> </div> <div class="userscript-467511-setting-panel-option-item"> <span class="userscript-467511-setting-panel-option-item-title">暂停播放视频直至画质切换完成(以此规避音画不同步现象)</span> <span class="userscript-467511-setting-panel-option-item-switch" data-key="isWaitUntilHighQualityLoaded" data-status="${options.isWaitUntilHighQualityLoaded ? 'on' : 'off'}"></span> </div> </div> <div style="margin-top: 16px; align-self: center; font-size: 14px;"> <span style="display: inline-block; transform: translateY(-1.5px);">⚠️</span> <span style="color: #AAAAAA;">所有改动将在页面刷新后生效</span> </div> </div> <span id="userscript-467511-setting-panel-close-btn">×</span> `; // setup event handler containerElement.querySelectorAll('.userscript-467511-setting-panel-option-item-select').forEach(selectElement => { selectElement.onchange = function(e) { const { key } = this.dataset; GM_setValue(key, e.target.value); } }); containerElement.querySelectorAll('.userscript-467511-setting-panel-option-item-switch').forEach(switchElement => { switchElement.onclick = function(e) { const { key, status } = this.dataset; this.dataset.status = status === 'off' ? 'on' : 'off'; GM_setValue(key, this.dataset.status === 'on'); } }); containerElement.querySelector('#userscript-467511-setting-panel-close-btn').onclick = () => containerElement.style.display = 'none'; // append to document const timer = setInterval(() => { if (document.head && document.body) { document.head.appendChild(settingPanelCSS); document.body.appendChild(containerElement); clearInterval(timer); } }, 1000); } function setupSettingPanelEntry() { const timer = setInterval(() => { const otherSettingElement = document.querySelector('.bpx-player-ctrl-setting-others-content'); if (otherSettingElement) { const entryElement = document.createElement('div'); entryElement.textContent = '脚本设置 >'; entryElement.style = `height: 20px; line-height: 20px; cursor: pointer;`; entryElement.onclick = () => document.querySelector('#userscript-467511-setting-panel-container').style.display = 'flex'; otherSettingElement.appendChild(entryElement); clearInterval(timer); } }, 1000); } })();