// ==UserScript==
// @name 纯净版斗鱼(douyu)
// @namespace https://github.com/ljezio
// @version 4.2.0
// @description 斗鱼纯净版(douyu.com)。只保留直播和弹幕【斗鱼精简版、斗鱼极简版、斗鱼清爽版】;支持按钮切换关闭脚本;支持自动切换最高画质;
// @homepage https://github.com/ljezio/pure-douyu
// @author ljezio
// @license MIT
// @match *://*.douyu.com/0*
// @match *://*.douyu.com/1*
// @match *://*.douyu.com/2*
// @match *://*.douyu.com/3*
// @match *://*.douyu.com/4*
// @match *://*.douyu.com/5*
// @match *://*.douyu.com/6*
// @match *://*.douyu.com/7*
// @match *://*.douyu.com/8*
// @match *://*.douyu.com/9*
// @match *://*.douyu.com/topic/*
// @match *://*.douyu.com/beta/*
// @icon https://www.douyu.com/favicon.ico
// @grant GM_addStyle
// @downloadURL none
// ==/UserScript==
const switchKey = 'pure_douyu_switch';
const autoHighestImageKey = 'pure_douyu_auto_highest';
(function () {
'use strict';
window.onload = () => {
const buttonGroup = functionButtons();
if (localStorage.getItem(switchKey)) return;
restyle();
avoidSmallWindow();
autoFullWindow()
.then(() => autoHighestImage());
dbClick(buttonGroup);
};
})();
/**
* 功能按钮
*/
function functionButtons() {
const buttonGroup = document.createElement('div');
buttonGroup.style.cssText = 'z-index: 999; position: fixed; top: 0; right: 0;';
document.body.appendChild(buttonGroup);
// 开关脚本按钮
const switchButton = document.createElement('button');
switchButton.title = localStorage.getItem(switchKey) ? '启用脚本' : '关闭脚本';
switchButton.innerHTML = `
`;
switchButton.onclick = () => {
if (localStorage.getItem(switchKey)) {
localStorage.removeItem(switchKey);
} else {
localStorage.setItem(switchKey, 'off');
}
location.reload();
};
buttonGroup.appendChild(switchButton);
if (!localStorage.getItem(switchKey)) {
// 开关自动切换最高画质按钮
const autoHighestImageButton = document.createElement('button');
autoHighestImageButton.title = localStorage.getItem(autoHighestImageKey) ? '开启自动切换最高画质' : '关闭自动切换最高画质';
autoHighestImageButton.innerHTML = `
`;
autoHighestImageButton.onclick = () => {
if (localStorage.getItem(autoHighestImageKey)) {
autoHighestImageButton.title = '关闭自动切换最高画质';
localStorage.removeItem(autoHighestImageKey);
} else {
autoHighestImageButton.title = '开启自动切换最高画质';
localStorage.setItem(autoHighestImageKey, 'off');
}
};
buttonGroup.appendChild(autoHighestImageButton);
}
// 按钮半透明样式与鼠标悬停透明度变化
[...buttonGroup.children].forEach(button => {
button.style.cssText = 'display: block; cursor: pointer; opacity: 0.5; transition: opacity 0.3s ease;';
button.onmouseover = () => button.style.opacity = '1';
button.onmouseout = () => button.style.opacity = '0.5';
})
return buttonGroup;
}
/**
* 调整样式
*/
function restyle() {
GM_addStyle(`
/* 隐藏无用元素 */
header,
aside,
.wm-general,
.bc-wrapper ,
.RechangeJulyPopups,
#js-bottom-left,
#bc3,
#bc3-bgblur,
#js-player-dialog,
#js-player-above-controller,
#js-layout-fixed-buff,
[class^="snapbar__"],
[class^="sidebar__"],
[class^="title__"],
[class^="interactive__"],
[class^="toggle__"] {
display: none !important;
}
/* 修改样式 */
#root, #js-player-main {
margin: 0 !important;
}
[class^="stream__"] {
bottom: 0 !important;
top: 0 !important;
}
[class^="case__"] {
padding: 0 !important;
}
/* 强制修改伪元素样式 */
#js-player-main::before {
content: none !important;
}
[class^="player__"]::before {
padding-top: 0 !important;
padding-bottom: ${innerHeight - 16}px !important;
}
`);
}
/**
* 避免小窗口化 todo
*/
function avoidSmallWindow() {
const observer = new MutationObserver(() => {
document.querySelector('#js-player-video-widgets .roomSmallPlayerFloatLayout-closeBtn')?.click();
observer.disconnect();
});
observer.observe(document.querySelector('#js-player-video-case'), {
attributes: true,
attributeFilter: ['class', 'style']
});
}
/**
* 自动网页全屏
*/
function autoFullWindow() {
return new Promise((resolve) => {
const fullWindowInterval = setInterval(() => {
// 自动网页全屏
if (!controlBar.fullWindow()) return;
setTimeout(() => {
// 网页全屏可以输入弹幕
document.querySelector('#js-player-main [class^="toggle__"] button')?.click();
}, 10);
clearInterval(fullWindowInterval);
resolve();
}, 300);
})
}
/**
* 自动切换最高画质
*/
function autoHighestImage() {
if (localStorage.getItem(autoHighestImageKey)) return;
let times = 0;
const highestImageInterval = setInterval(() => {
if (times++ >= 10) { // 小主播没有画质切换功能
clearInterval(highestImageInterval);
return;
}
const highestImageButton = document.querySelector('#js-player-controlbar [class^="tipItem-"]:nth-child(2) li:first-child');
if (!highestImageButton) return;
setTimeout(() => {
if (!highestImageButton.className.startsWith('selected-')) {
highestImageButton.click();
}
}, 5000);
clearInterval(highestImageInterval);
}, 1000);
}
/**
* 双击全屏
*/
function dbClick(buttonGroup) {
document.body.ondblclick = event => {
event.stopPropagation();
if (!document.fullscreenElement) {
controlBar.fullScreen();
} else {
document.exitFullscreen().then();
}
};
document.onfullscreenchange = () => {
if (!document.fullscreenElement) {
setTimeout(() => controlBar.fullWindow(), 0);
buttonGroup.style.display = 'block';
} else {
buttonGroup.style.display = 'none';
}
};
}
/**
* 获取控制栏按钮
*/
const controlBar = {
fullWindow() {
return this._clickControlButton(2)
},
fullScreen() {
return this._clickControlButton(1)
},
_clickControlButton(nthLast) {
const parent = '#js-player-controlbar';
const nth = `:nth-last-child(${nthLast})`;
const button = document.querySelector(`${parent} [class^="right-"] > ${nth}, ${parent} [class^="right__"] > ${nth}`);
if (!button) return false;
button.click();
return true;
}
}