// ==UserScript== // @name 直播插件 // @namespace http://tampermonkey.net/ // @version 3.4 // @description 虎牙直播、斗鱼直播 页面简化,屏蔽主播直播间 // @author wuxin001 // @match https://www.huya.com/* // @match https://www.douyu.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net // @grant GM_addStyle // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; const huya_address_pattern = /^https:\/\/.*\.huya\.((com)|(cn)).*/ const doyu_address_pattern = /^https:\/\/.*\.douyu\.((com)|(cn)).*/ const bg_regx = /.*(\.(png|jpg|jpeg|apng|avif|bmp|gif|ico|cur|svg|tiff|webp).*)$/; // 图片格式 const local_url = window.location.href const is_huya = huya_address_pattern.test(local_url) // 是否是虎牙地址 const is_douyu = doyu_address_pattern.test(local_url) // 是否是斗鱼地址 const wd = window.document const wls = window.localStorage // 简化存储对象 const download_plugin_url = 'https://greasyfork.org/zh-CN/scripts/449261-%E8%99%8E%E7%89%99%E7%9B%B4%E6%92%AD' // 下载地址 const source_code_url = 'https://github.com/wuxin0011/huya-live' // 源码地址 const time = 2000 //延迟时间 /** * 页面加载完成调用该方法! */ window.onload = () => { setTimeout(() => { try { let text = is_huya ? '虎牙' : '斗鱼' text = '%c欢迎使用' + text + '直播插件,下载地址%c' console.log( text .concat(download_plugin_url, ''), 'background: rgb(255, 93, 35); padding: 1px; border-radius: 3px 0 0 3px; color: #fff', 'border-radius: 0 3px 3px 0; color: #fff') console.log( '%c源码地址:%c ' .concat(source_code_url, ''), 'background: rgb(255, 93, 35); padding: 1px; border-radius: 3px 0 0 3px; color: #fff', 'border-radius: 0 3px 3px 0; color: #fff') //插件执行入口 if (is_huya) { // 执行虎牙直播插件 new TriggerLive() } else if (is_douyu) { // 执行斗鱼直播插件 new FishLive() } else { console.warn('插件地址不适配,请检查匹配地址!!!') } } catch (e) { } }, 0) } /** * 日志输出 */ const log = (msg, level = 'log') => { try { if (level == 'log') { console.log(new Date().toLocaleString(), msg); } if (level == 'info') { console.info(new Date().toLocaleString(), msg); } if (level == 'warn') { console.warn(new Date().toLocaleString(), msg); } if (level == 'error') { console.error(new Date().toLocaleString(), msg); } } catch (e) { console.log(e) } } /** * 主播类 */ class HostUser { constructor(roomId, name) { this.roomId = roomId; this.name = name; } } /** * 直播插件,要求所有直播插件继承该类,并实现要求重写的方法! */ class LivePlugin { constructor() { // 存放内容信息 this.key = 'key' // 存放背景图 this.bg_key = 'bg_key' // 是否显示背景key this.bg_show_key = 'bg_show_key' // 是否显示菜单 this.menu_show_key = 'menu_show_key' // 直播源 this.baseUrl = "baseUrl" // 默认背景图 this.defaultBackgroundImage = 'defaultBackgroundImage' // 存放屏蔽主播信息 this.users = [] // body this.html = null // body this.body = null // 菜单 this.menu = null // 操作数据 this.tbody = null // 操作容器 this.m_container = null } // 初始化操作方法,子类可以继承该类,实现该类中空方法,参考此操作,初始化构造器实调用该方法就可以了。。。 init() { if (!this.removeRoom()) { this.detail() this.common() this.index() this.category() this.create_container() } // 设置壁纸 this.settingBackgroundImage() // 设置菜单 this.loadLeftMenu() } /*********************************建议下面操作方法必须重写的,并且参考此步骤*****************************/ // 公共部分页面操作 common() {} //首页操作 index() {} // 分类页面操作 category() {} // 详情页操作 detail() {} // 通过点击直播间名称删除直播间 removeRoomByClickRoomName() {} // 通过房间号获取直播间name getNameByRoomId(roomId) { alert('该操作未实现!'); return null } // 通过房间地址获取房间号 getRoomIdByUrl(url) { return null } /*********************************下面方法不建议重写******************************/ /** * 容器,所有操作容器均在此容器中, */ create_container() { // 初始化房间号 let that = this if (!that.body || !that.html) { that.html = wd.querySelector('html') that.body = wd.querySelector('body') } if (!that.body) { that.body = wd.createElement('body') } that.users = that.getLocalStore(that.key, Array.name) let show1 = that.getLocalStore(that.bg_key, Boolean.name) let show2 = that.getLocalStore(that.menu_show_key, Boolean.name) that.m_container = that.s2d(`
背景 菜单 更新
序号 名称 房间号 操作
`) that.body.appendChild(that.m_container) that.tbody = that.m_container.querySelector('.m-container table tbody') // 生成操作按钮 that.operationDOMButton() // 添加直播房间号信息 that.createRoomItem(that.users) // 右侧点击添加button that.createButton() } /** * 通过用户列表构建列表 * @param {Object} arr 用户列表 */ createRoomItem(arr) { if (!Array.isArray(arr)) { return; } let that = this arr.forEach((item, index) => { let tr = wd.createElement('tr') tr.style.borderBottom = '1px solid rgba(0,0,0,0.4)' tr.style.margin = '10px 0' tr.style.padding = '20px 10px' tr.innerHTML = `${index+1} ${item.name} ${item.roomId} ` that.tbody.appendChild(tr) // 添加删除事件 const deleteBtn = tr.querySelector('button') deleteBtn.addEventListener('click', function (e) { let roomId = e.target.getAttribute('room-id'); that.userDelete(roomId) // 如果是当前主播,需要刷新 if (that.getRoomIdByUrl(local_url) == roomId) { window.location.reload() } that.removeDOM(tr) }) }) } /** * 解析DOM字符串 * @param {Object} string DOM文档树 */ s2d(string) { return new DOMParser().parseFromString(string, 'text/html').body.childNodes[0] } /** * 绘制表格 * @param {Object} arr 表格数据 */ resetTbody(arr) { // 删除原来dom this.removeDOM(this.tbody, true) let table = this.m_container.querySelector('.m-container table') this.tbody = wd.createElement('tbody') let thead = wd.createElement('thead') let room_index = wd.createElement('th') let room_name = wd.createElement('th') let room_id = wd.createElement('th') let room_operation = wd.createElement('th') thead.appendChild(room_index) thead.appendChild(room_name) thead.appendChild(room_id) thead.appendChild(room_operation) table.appendChild(this.tbody) // 添加操作窗口 this.createRoomItem(arr) } /** * 操作框容器 */ operationDOMButton() { let that = this if (!that.m_container) { return; } const inputValue = that.m_container.querySelector('.m-container .operation input') if (inputValue) { // 输入框 inputValue.addEventListener('keyup', function (e) { if (e.key == 'Enter') { let arr = that.users.filter(item => { return (item.roomId && item.roomId.indexOf(inputValue.value) != - 1) || (item.name && item.name.indexOf(inputValue.value) != -1) }) that.resetTbody(arr) } }) } // 添加 const addRoomBtn = that.m_container.querySelector('.m-container .operation button.add-room') if (addRoomBtn) { addRoomBtn.addEventListener('click', function () { const keywords = inputValue.value.trim() if (!keywords) { return alert('请输入房间号!') } if (!that.userIsExist(keywords)) { const name = that.getNameByRoomId(keywords) if (name) { that.addUser(keywords, name) inputValue.value = '' } else { if (confirm(`房间号为${keywords}的主播不存在!确定添加?`)) { that.addUser(keywords, keywords) inputValue.value = '' } } } else { alert('该主播已添加!') } }) } // 刷新 const flushRoomBtn = that.m_container.querySelector('.m-container button.flush-room') if (flushRoomBtn) { flushRoomBtn.addEventListener('click', function () { that.users = that.getLocalStore() that.resetTbody(that.users) }) } // 搜索 const searchRoomBtn = that.m_container.querySelector('.m-container .operation .search-room') if (searchRoomBtn) { searchRoomBtn.addEventListener('click', function () { let arr = that.users.filter(item => { return (item.roomId && item.roomId.indexOf(inputValue.value) != -1) || ( item.name && item.name.indexOf(inputValue.value) != -1) }) that.resetTbody(arr) }) } // 清空 const clearRoomBtn = that.m_container.querySelector('.m-container button.clear-room') if (clearRoomBtn) { clearRoomBtn.addEventListener('click', function () { if (confirm('确认重置?')) { that.users = [] wls.removeItem(that.key) wls.removeItem(that.bg_key) wls.removeItem(that.menu_show_key) that.resetTbody(that.users) window.location.reload() } }) } // 文件上传 const uploadButton = that.m_container.querySelector('.m-container #file') if (uploadButton) { uploadButton.addEventListener('change', function (e) { const file = uploadButton.files[0] || null // 图片格式校验 if(!bg_regx.test(file.name)){ return alert("图片格式不正确!") }else{ let fileReader = new FileReader() fileReader.onload = (e) => { // 保存到本地 that.addLocalStore(that.bg_key, e.target.result, String.name, false) that.settingBackgroundImage(e.target.result) } // 转码 fileReader.readAsDataURL(file) } }) } // 文件上传 const upload = that.m_container.querySelector('.m-container .bg-btn') if (upload) { upload.addEventListener('click', function (e) { uploadButton.click() }) } // 选择背景 const checkbox = that.m_container.querySelector('.m-container #checkbox1') if (checkbox) { checkbox.addEventListener('change', function (e) { that.addLocalStore(that.bg_show_key, e.target.checked, Boolean.name) that.settingBackgroundImage() }) } // 是否关闭菜单 const menu = that.m_container.querySelector('.m-container #checkbox2') if (menu) { menu.addEventListener('change', function (e) { that.getLeftMenu(e.target.checked) }) } } /** * 右侧操作按钮 * @param text 指定按钮文本,默认是小虎牙或者是小鱼丸 */ createButton(text) { let that = this if (!that.body) { return; } const btn = wd.createElement('button') btn.style.cursor = 'pointer' btn.style.position = 'fixed' btn.style.top = '300px' btn.style.right = '0px' btn.style.padding = '5px 10px' btn.style.backgroundColor = 'rgb(255, 93, 35)' btn.style.border = 'none' btn.style.borderRadius = '20px' btn.style.fontSize = '12px' btn.style.color = '#fff' btn.style.zIndex = 100000 btn.textContent = text ? text : (is_huya ? '小虎牙' : '小鱼丸') btn.addEventListener('click', function (e) { if (that.m_container.style.display === 'block') { that.m_container.style.display = 'none' } else { that.m_container.style.display = 'block' } }) btn.addEventListener('mouseenter', function () { btn.style.backgroundColor = 'rgba(255, 93, 35,0.6)' }) btn.addEventListener('mouseleave', function () { btn.style.backgroundColor = 'rgba(255, 93, 35,1)' }) that.body.appendChild(btn) } /** * 删除DOM * @param element 需要删除的元素 * @param realRemove 是否真实删除,默认不删除 */ removeDOM(element, realRemove = false) { try { if (element) { element.style.display = 'none' if (realRemove) { element.remove() } } } catch (e) {} // 防止element没有remove方法而抛出异常 } /** * 删除DOM * @param selector 选择器 * @param realRemove 是否真实删除,默认不删除 * */ removeElement(selector, realRemove = false) { this.removeDOM(wd.querySelector(selector), realRemove) } /** * 该房间是否已改被删除 * @param url 房间链接地址 默认 window.location.href */ removeRoom(url = local_url) { if (!this.isRemove(url)) { return false } this.roomIsNeedRemove(); return true } /** * 房间已被删除之后操作 * @param url 房间链接地址 默认 window.location.href */ roomAlreadyRemove() { this.removeDOM(this.body, true) this.body = null; //必须设置为空!否则无法设置新的button const h2 = wd.createElement('h2') let html = wd.querySelector('html') let body = wd.querySelector('body') if (!body) { // 如果原来的删除了,从新创建一个body存放内容 body = wd.createElement('body') } body.style.display = 'flex' body.style.justifyContent = 'center' body.style.alignItems = 'center' // 获取主播名称 let name = this.getUser(this.getRoomIdByUrl(local_url)) ? this.getUser(this.getRoomIdByUrl( local_url)).name : '' h2.textContent = `主播【${name}】已被你屏蔽` h2.style.fontSize = '40px' let title = wd.querySelector('title') if (!title) { title = wd.createElement('title') } title.textContent = `主播【${name}】已被你屏蔽` html.appendChild(body) body.appendChild(h2) this.removeDOM(this.m_container, true) this.m_container = null // 创建操作面板 this.create_container() } /** * 判断链接是否应该被删除 * @param href 房间链接地址 默认 window.location.href */ isRemove(href) { return this.userIsExist(this.getRoomIdByUrl(href)); } /** * 设置背景图 * @param url 背景图地址 默认 是默认地址 */ settingBackgroundImage(url) { if (this.getLocalStore(this.bg_show_key, Boolean.name)) { if (!url) { url = this.getImageUrl(url) } this.body.style.backgroundSize = "cover" this.body.style.backgroundRepeat = 'no-repeat ' this.body.style.backgroundAttachment = 'fixed' this.body.style.backgroundImage = `url(${url})` } else { this.body.style.backgroundImage = 'none' } } /** * 获取本地图片地址 * @param url 背景图地址 默认 是默认地址 */ getImageUrl(url) { if (!url) { url = wls.getItem(this.bg_key) } return url ? url : this.defaultBackgroundImage; } /** * 通过房间名称或者id判断房间是否已经保存到本地 * @param keywords 房间名或者id * @param list 本地缓存数据,默认是本地缓存用户数据 */ userIsExist(keywords, list = this.users) { return this.getUser(keywords, list) ? true : false } /** * 通过房间名称或者id判断房间是否已经保存到本地 * @param keywords 房间名或者id * @param list 本地缓存数据,默认是本地缓存用户数据 */ getUser(keywords, list = this.users) { for (let i = 0; i < list.length; i++) { if ((list[i].name && list[i].name == keywords) || (list[i].roomId && list[i].roomId == keywords)) { return list[i] } } return null } /** * 通过房间id或者房间名删除本地缓存的数据 * @param keywords 房间名或者id */ userDelete(keywords) { let that = this that.users.forEach((item, index) => { if (keywords == item.name || keywords == item.roomId) { that.users.splice(index, 1) } }) that.addLocalStore(this.key, this.users) } /** * 添加并保存直播间 * @param id, 房间id * @param name 房间名 */ addUser(id, name) { if (this.userIsExist(id) || this.userIsExist(name)) { alert('该房间已存在!') return; } const newUser = new HostUser(id, name); // 添加 this.users.unshift(newUser) // 保存到本地 this.addLocalStore(this.key, this.users) this.resetTbody(this.users) // 如果是当前主播需要屏蔽 if (id == this.getRoomIdByUrl(local_url)) { this.roomIsNeedRemove(local_url); } } /** * 获取本地保存的直播数据 * @param {defaultKey} = [存储key] * @param {obj} = [需要存储的value] * @param {type} = [要解析参数类型] * @param {isparse} = [是否需要解析] */ addLocalStore(defaultKey = this.key, obj = this.users, type = Array.name, isParse = true) { try { if (type == Object.name || type == Array.name) { if (isParse) { window.localStorage.setItem(defaultKey, JSON.stringify(obj)) } else { window.localStorage.setItem(defaultKey, obj) } } if (type == String.name || type == Boolean.name) { window.localStorage.setItem(defaultKey, obj) } } catch (e) {} } /** * 获取本地保存的直播数据 * @param {key} = [存储key] * @param {type} = [要解析参数类型] * @param {isparse} = [是否需要解析] */ getLocalStore(k = this.key, type = Array.name, isParse = true) { let obj = window.localStorage.getItem(k) if (type == Array.name) { if (isParse) { try { if (obj) { obj = JSON.parse(obj) } else { obj = [] } } catch (e) { obj = [] } } return Array.isArray(obj) ? obj : [] } if (type == Object.name) { if (isParse) { try { if (obj) { obj = JSON.parse(obj) } else { obj = {} } } catch (e) { obj = {} } } return obj ? obj : {} } if (type == String.name) { return obj ? obj : ''; } if (type == Boolean.name) { return (obj == 'true' || obj == true) ? true : false; } return obj; } /** * @param {selector} = 选择器 * @param {selector} = [是否真的删除,默认删除而不是display = 'none'] * @param {time1} 循环执行时间 默认5000ms */ removeVideo(selector, realyRemove = true, time1 = 5000) { // 第一次执行该操作 try { const video = wd.querySelector(selector) if (video) { video.pause() } this.removeDOM(video, realyRemove) } catch (e) {} // 循环执行该操作] let count = 0 let video_timer = setInterval(() => { try { const video = wd.querySelector(selector) if (video) { video.pause() } this.removeDOM(video, realyRemove) count = count + 1 // 结束循环器 if (count >= 10) { clearInterval(video_timer) } } catch (e) {} }, time1) } /** * @param {selector} = [选择器] * @param {selector} = [是否真的删除,默认删除而不是display = 'none'] */ roomIsNeedRemove(selector = wd.querySelector('video'), realyRemove = true) { // 移除直播间视频 this.removeVideo(selector, true) // 添加直播间删除禁言提示 this.roomAlreadyRemove() // 重新设置背景图 this.settingBackgroundImage() } /* * 操作左侧导航栏,需要传入选择器,和修改值 建议放到公共方法下执行! * @param {selector} = [选择器] * @param {value} = [要修改的值] */ getLeftMenu(value = false) { if (!this.menu) { return alert('获取不到导航菜单,操作失败!') } if (value) { this.menu.style.display = 'block'; } else { this.menu.style.display = 'none' } this.addLocalStore(this.menu_show_key, value, Boolean.name, false) } /* * 操作左侧导航栏,需要传入选择器,和修改值 建议放到公共方法下执行! * @param {selector} = [选择器] */ loadLeftMenu() { //首次加载是否显示 let d_show = this.getLocalStore(this.menu_show_key, Boolean.name, false) if (this.menu) { if (d_show) { this.menu.style.display = 'block'; } else { this.menu.style.display = 'none'; } } } } /** * 虎牙直播插件 */ class TriggerLive extends LivePlugin { constructor() { super() this.key = 'huyazhibo' this.bg_key = 'huyazhibo_bg' this.bg_show_key = 'huyazhibo_bg_show' this.menu_show_key = 'huyazhibo_menu_show_key' this.defaultBackgroundImage = 'https://livewebbs2.msstatic.com/huya_1664197944_content.jpg' this.baseUrl = "https://www.huya.com/" this.users = this.getLocalStore(this.key, Array.name, true) this.html = wd.querySelector('html') this.body = wd.querySelector('body') this.menu = wd.querySelector('.mod-sidebar') this.tbody = null this.m_container = null // 初始化,请务必调用该方法!!! this.init() } // 首页操作 index() { // 直播源 const url = local_url if (url == this.baseUrl) { // 操作视频 this.removeVideo('.mod-index-main video', true) // 触发点击关闭广告 const banner_close = wd.querySelector('.mod-index-wrap #banner i') if (banner_close) { banner_close.click(); } } // 暂停播放 立即执行 let pauseBtn = wd.querySelector('.player-pause-btn') if (pauseBtn) { pauseBtn.click() } let count = 0; // 暂停播放 防止后续加载出现 let timer = setInterval(() => { pauseBtn = wd.querySelector('.player-pause-btn') if (pauseBtn) { pauseBtn.click() } if (count >= 3) { clearInterval(timer) } }, 1000) } // 分类页操作 category() { if (new RegExp(/^https:\/\/.*\.huya\.((com)|(cn))\/g(\/.*)$/).test(local_url)) { let that = this const dd = wd.querySelectorAll('.live-list-nav dd') if (dd) { for (let d of dd) { d.addEventListener('click', () => { setTimeout(() => { that.removeRoomByClickRoomName() }, 2000) }) } } } } // 公共部分操作 common() { this.removeRoomByClickRoomName() } // 详情操作 detail() { if (new RegExp(/^https:\/\/www\.huya\.com(\/\w+)$/).test(local_url)) { let that = this // 点击直播间移除直播间操作 const hostName = wd.querySelector('.host-name') if (hostName) { hostName.addEventListener('click', () => { if (confirm(`确认禁用 ${hostName.textContent}?`)) { that.addUser(that.getRoomIdByUrl(local_url), hostName.textContent) } }) } } } // 通过地址获取房间号 getRoomIdByUrl = (url = local_url) => { let arr = url.split('/') let roomId = arr[arr.length - 1] return roomId } // 通过房间号查找名称 getNameByRoomId(roomId) { let that = this const hostName = document.querySelector('.host-name') if (!hostName) { const rooms = document.querySelectorAll('.game-live-item') if (rooms) { for (let room of rooms) { const a = room.querySelector('a') if (a && a.href) { const id = that.getRoomIdByUrl(a.href) const user = room.querySelector('.txt i') if (id === roomId) { hostName = user } } } } } return hostName && hostName.textContent ? hostName.textContent : '' } // 通过点击直播间名称删除直播间 removeRoomByClickRoomName() { const that = this const rooms = document.querySelectorAll('.game-live-item') if (rooms) { for (let li of rooms) { try { const a = li.querySelector('a') // 获取单个主播间房间地址 const url = a.href // 获取房间i const user = li.querySelector('.txt i') const name = user.textContent || '' user.addEventListener('click', () => { if (confirm(`确认禁用 ${name}?`)) { that.addUser(that.getRoomIdByUrl(url), name); that.removeDOM(li); } }) if (that.isRemove(url)) { that.removeDOM(li) } } catch (e) {} } } } } /** * 斗鱼直播插件 */ class FishLive extends LivePlugin { constructor() { super() this.key = 'douyuzhibo' this.bg_key = 'douyuzhibo_bg' this.bg_show_key = 'douyuzhibo_show' this.menu_show_key = 'douyuzhibo_menu_show_key' this.baseUrl = "https://www.douyu.com/" this.defaultBackgroundImage = 'https://sta-op.douyucdn.cn/dylamr/2022/11/07/1e10382d9a430b4a04245e5427e892c8.jpg' this.users = this.getLocalStore(this.key, Array.name, true) this.html = wd.querySelector('html') this.body = wd.querySelector('body') this.menu = wd.querySelector('#js-aside') this.tbody = null this.m_container = null // 初始化,请务必调用该方法!!! this.init() } // 公共部分页面操作 common() {} //首页操作 index() { let that = this // 直播源 if (window.location.href == that.baseUrl) { window.scroll(0, 0) // 移除直播 that.removeVideo('.layout-Slide-player video', true) // 获取暂停button const vbox = wd.querySelector('#room-html5-player'); const divs = vbox.querySelectorAll('div') if (divs) { divs.forEach(div => { if (div && div.title && div.title == '暂停') { div.click() } }) } // 初始化默认高度,默认浏览器可视化高度 let init = window.innerHeight; // 初始化容器存放用户 let init_users = [] // 页面加载完毕 setTimeout(() => { that.removeRoomByClickRoomName(init_users) }, time) // 斗鱼直播使用懒加载方式,只有鼠标下滑,下方直播间才会加载,首次加载不会加载所有页面直播间列表 // 因此,添加滚动事件来添加 // 另外防止二次或者多次添加点击事件,将之前保存到init_users中来记录是否该添加 window.addEventListener('scroll', (e) => { // 超过可视化高度,需要重新加载 if (window.pageYOffset > init) { init = init + 100; // 重新扫描点击事件 that.removeRoomByClickRoomName(init_users) } }) } } // 分类页面操作 category() { let that = this // 匹配分类页 if (new RegExp(/https:\/\/www.douyu.com(\/((directory.*)|(g_.*)))$/).test(window.location.href)) { that.removeRoomByClickRoomName() const labels = wd.querySelectorAll('.layout-Module-filter .layout-Module-label') if (labels) { for (let label of labels) { if (label) { label.addEventListener('click', (e) => { e.preventDefault() // 获取当前地址 let to_link = label && label.href ? label.href : null if (to_link) { window.location.href = to_link } else { // 获取全部地址 var result = 'https://www.douyu.com/g_' + local_url.match(RegExp( /subCate\/.*/g))[0].replace('subCate', '').match(new RegExp( /\w+/g))[0] window.location.href = result } }) } } } } } // 详情页操作 detail() { let that = this window.scroll(0, 0) // 匹配只有在播放直播间才会生效 if (new RegExp(/.*douyu.*(\/((.*rid=\d+)|(\d+)))$/).test(local_url)) { // 详情页名称操作 setTimeout(() => { // 点击主播直播间名称进行操作 const hostName = wd.querySelector('.Title-roomInfo h2.Title-anchorNameH2') if (hostName) { hostName.addEventListener('click', () => { if (confirm(`确认禁用 ${hostName.textContent}?`)) { that.addUser(that.getRoomIdByUrl(local_url), hostName .textContent) } }) } // 带有轮播图 广告 if (new RegExp(/.*douyu.*\/topic(\/(.*rid=\d+))$/).test(local_url)) { // 移除直播间背景 let count = 0; let timer = setInterval(() => { // 去掉默认样式 const bgc = wd.querySelector('#bc3-bgblur') if (bgc) { bgc.style.background = 'none' bgc.style.backgroundImage = 'none' } const bg = wd.querySelector('#bc3') if (bg) { bg.style.background = 'none' bg.style.backgroundImage = 'none' } count = count + 1 // 结束循环器 if (count >= 4) { clearInterval(timer) } }, time) } // 不带有轮播图 广告 if (new RegExp(/.*douyu.*(\/(\d+))$/).test(local_url)) { // 如果是小窗口 setTimeout(() => { const closeBtn = document.querySelector('.roomSmallPlayerFloatLayout-closeBtn') if (closeBtn) { closeBtn.click() } }, time) } }, time) } } // 通过点击直播间名称删除直播间 removeRoomByClickRoomName(list = []) { let that = this if (this.baseUrl == local_url) { const room = wd.querySelectorAll('.layout-Wrapper.layout-Module.RoomList .layout-List-item') if (room) { for (let li of room) { try { // 获取单个主播间房间地址 const a = li.querySelector('a') if (a) { a.onclick = (e) => { e.preventDefault() } const url = a.href const user = li.querySelector('.DyCover-user') const name = user.textContent || '' if (user && (!that.userIsExist(name, list) || !that.userIsExist( url, list))) { // 添加记录,下次不再添加!!! list.unshift(new HostUser(url, name)) user.addEventListener('click', () => { if (confirm(`确认禁用 ${name}`)) { that.addUser(that.getRoomIdByUrl(url), name); that.removeDOM(li); } }, true) } if (that.isRemove(url) || that.userIsExist(name)) { that.removeDOM(li) } } } catch (e) {} } } } if (new RegExp(/https:\/\/www.douyu.com(\/((directory.*)|(g_.*)))$/).test(local_url)) { const rooms = wd.querySelectorAll('.layout-Cover-item') if (rooms) { for (let li of rooms) { try { if (li) { const link = li.querySelector('a.DyListCover-wrap') if (link) { link.addEventListener('click', (e) => { e.preventDefault() }) const url = link.href const user = link.querySelector('div.DyListCover-userName') const name = user.textContent || '' // 判断该直播间列表窗口是否需要删除 if (that.isRemove(url) || that.userIsExist(name)) { that.removeDOM(li, true) } else { if (user) { user.addEventListener('click', (e) => { if (confirm(`确认禁用 ${name}?`)) { const id = that.getRoomIdByUrl(url); that.addUser(id, name); that.removeDOM(li); } e.preventDefault() }) } // 监听鼠标移入事件 li.addEventListener('mouseenter', (e) => { e.preventDefault() const a = e.target.querySelector( 'a.DyListCover-wrap.is-hover') if (a) { const url = a.href const user = a.querySelector('.DyListCover-userName') const name = user.textContent || '' if (user) { user.addEventListener('click', (a) => { a.preventDefault() if (confirm(`确认禁用 ${name}?`)) { const id = that.getRoomIdByUrl(url); that.addUser(id, name); that.removeDOM(li); } }) } a.addEventListener('click', (t) => { t.preventDefault() }) } }) } } } } catch (e) {} } } } } // 通过房间号获取直播间name getNameByRoomId(keywords) { let that = this // 从详情页获取 const hostName = document.querySelector('.Title-blockInline .Title-anchorName h2') let rooms = null; if (!hostName) { rooms = document.querySelectorAll('.layout-List-item') // index if (rooms) { for (let room of rooms) { const id = that.getRoomIdByUrl(room.querySelector('a').href) const user = room.querySelector('.DyCover-user') if (id == keywords) { hostName = user } } } // 如果还是获取不到从分类页面获取 if (!hostName) { rooms = document.querySelectorAll('.layout-Cover-item') if (rooms) { for (let room of rooms) { const id = that.getRoomIdByUrl(room.querySelector('a').href) const user = room.querySelector('.DyListCover-userName') if (id == keywords) { hostName = user } } } } } return hostName && hostName.textContent ? hostName.textContent : '' } // 通过房间地址获取房间号 getRoomIdByUrl(url) { try { if (new RegExp(/https:\/\/.*(rid=.*)$/).test(local_url)) { return local_url.match(new RegExp(/rid=.*/g))[0].replace('rid=', '') } else { let arr = url.split('/') let roomId = arr[arr.length - 1] return roomId } } catch (e) { return null } } } // 样式部分 GM_addStyle(` .m-container { box-sizing: border-box; position: fixed; display: none; width: 600px; height: 400px; top: 100px; left: 50%; border-radius: 0; overflow: hidden scroll; background-color: white; transform: translateX(-50%); z-index:1000; transition: display linear 1s; box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2), -2px -2px 2px rgba(0, 0, 0, 0.2); } .m-container .operation { box-sizing: border-box; height: 80px; padding: 20px 0 0 0; text-align: center; } .m-container .operation input[type="text"] { width:130px; box-sizing: border-box; outline: none; border: 1px solid teal; padding: 5px; } .m-container .operation input[type="text"]:focus { border: 2px solid teal !important; } .m-container .operation input[type="checkbox"] { display:inline !important; } .m-container .operation input[type="file"] { display:none !important; } .m-container table { position: relative; box-sizing: border-box; overflow: hidden; padding: 10px; text-align: left !important; margin: 0 auto; max-height:200px; width: 90%; } .m-container table tbody { max-height: 250px; text-align: left !important; } .m-container table thead{ border-top: 1px solid rgba(0,0,0,0.4); border-bottom: 1px solid rgba(0,0,0,0.4); text-align: left !important; padding: 10px; } .m-container table th, m-container table td { padding: 10px; } .m-container table tr { border-bottom: 1px solid rgba(0,0,0,0.4); margin:5px 0; } .m-container .m-link,.m-container .m-link:visited{ color:blnk !important; } .m-container .m-link:hover{ color:blue !important; text-decoration:underline !important; } .m-container .btn { cursor: pointer !important; padding: 5px 7px !important; border: none !important; color: #fff !important; font-size:10px !important; border-radius:20px !important; max-width:50px !important; margin:0 0 !important; background-color:rgba(166, 169, 173,1) !important; z-index:1000 !important; } .m-container .btn:hover { background-color:rgba(166, 169, 173,0.6) !important; } .m-container .btn-teal{ background-color:rgba(64, 158, 255,1) !important; } .m-container .btn-teal:hover{ background-color:rgba(64, 158, 255,0.6) !important; } .m-container .btn-success{ background-color: rgba(103, 194, 58,1) !important; } .m-container .btn-success:hover{ background-color: rgba(103, 194, 58,0.6) !important; } .m-container .btn-info{ background-color:rgba(119, 119, 119,1) !important; } .m-container .btn-info:hover{ background-color:rgba(119, 119, 119,0.6) !important; } .m-container .btn-warning{ background-color:rgba(230, 162, 60,1) !important; } .m-container .btn-warning:hover{ background-color:rgba(230, 162, 60,0.6) !important; } .m-container .btn-danger{ background-color:rgba(245, 108, 108,1) !important; } .m-container .btn-danger:hover{ background-color:rgba(245, 108, 108,0.6) !important; } .game-live-item i,.host-name { cursor:pointer; } .game-live-item .txt i:hover,.host-name:hover { color:rgb(255, 135, 0); } .layout-List-item .DyCover-content .DyCover-user,.layout-Cover-item .DyListCover-userName,.Title-blockInline .Title-anchorName h2{ cursor:pointer !important; } .layout-List-item .DyCover-content .DyCover-user:hover,.layout-Cover-item .DyListCover-userName:hover,.Title-blockInline .Title-anchorName h2:hover { color:rgb(255, 135, 0) !important; } /********************斗鱼直播********************************/ .layout-Section.layout-Slide .layout-Slide-player, .layout-Slide-bannerInner, #lazyModule3, #lazyModule4, #lazyModule5, #lazyModule6, #lazyModule7, #lazyModule8, #lazyModule23, #lazyModule24, #js-room-activity, #js-right-nav, #js-bottom, #js-header .Header .HeaderNav, #js-header .Header .HeaderGif-left, #js-header .Header .HeaderGif-right, .Header-download-wrap, .AnchorInterToolsUser, #js-room-activity, #js-right-nav, #js-bottom, li.Header-menu-link, .layout-Main .layout-Customize, .HeaderCell-label-wrap, .Title-AnchorLevel,.RoomVipSysTitle, .Aside-nav .Aside-nav-item, .Title-roomInfo .Title-row, .multiBitRate-da4b60{ display:none !important; } li.Header-menu-link:nth-child(1), li.Header-menu-link:nth-child(2), li.Header-menu-link:nth-child(3), .Aside-nav .Aside-nav-item:nth-child(1), .Title-roomInfo .Title-row:nth-child(1), .Title-roomInfo .Title-row:nth-child(2) { display:inline-block !important; } .Barrage-main .UserLevel, .Barrage-main .js-user-level, .Barrage-main .Barrage-icon, .Barrage-main .Motor, .Barrage-main .Motor-flag, .Barrage-main .Barrage-hiIcon, .Barrage-main .UserGameDataMedal, .Barrage-main .ChatAchievement, .Barrage-main .Barrage-notice, .layout-Player .layout-Player-announce, .layout-Player .layout-Player-rank, #js-player-toolbar, .MatchSystemTeamMedal, .Barrage .Barrage-userEnter{ display:none !important; } #root div.layout-Main{ margin-top:70px !important; } div#root div.wm-general { display: none !important; background: none !important; background-image:none !important; } div#root div.wm-general:nth-child(3) { display: inline-block !important; } #bc3,#bc3-bgblur{ background:none !important; background-image:none !important; } .Barrage-main .Barrage-content { color:#333 !important; } .Barrage-main .Barrage-nickName{ color:#2b94ff !important; } .Barrage-listItem{ color: #333 !important; background-color: #f2f5f6 !important; } .layout-Player-barrage{ position: absolute !important; top: 0 !important; } /********************虎牙直播********************************/ .helperbar-root--12hgWk_4zOxrdJ73vtf1YI, .mod-index-wrap .mod-index-main .main-bd, .mod-index-wrap .mod-index-main .main-hd, .mod-index-wrap #js-main, .mod-index-wrap #banner, .mod-index-wrap .mod-game-type, .mod-index-wrap .mod-actlist, .mod-index-wrap .mod-news-section, .mod-index-wrap .mod-index-list .live-box #J_adBnM, .mod-index-wrap .mod-index-recommend, .mod-index-wrap .mod-news-section, .mod-index-wrap .recommend-wrap, .liveList-header-r, .room-footer, .J_roomSideHd, #J_roomSideHd, #player-gift-wrap, #match-cms-content, #matchComponent2, .hy-nav-item, .list-adx, .layout-Banner, .room-weeklyRankList{ display:none !important; } .hy-nav-item:nth-child(1), .hy-nav-item:nth-child(2), .hy-nav-item:nth-child(3) { display:inline-block !important; } .mod-index-wrap .mod-index-list{ margin-top:80px !important; } .duya-header{ background: hsla(0,0%,100%,.95) !important; border-bottom: 1px solid #e2e2e2 !important; box-shadow: 0 0 6px rgb(0 0 0 / 6%) !important; } .duya-header a,.duya-header i{ color:#000 !important; } .chat-room__list .msg-normal,.chat-room__list .msg-bubble{ background:none !important; } .chat-room__list .msg-normal-decorationPrefix, .chat-room__list .msg-normal-decorationSuffix, .chat-room__list .msg-bubble-decorationPrefix, .chat-room__list img, .chat-room__list .msg-noble, .chat-room__list .msg-sys, .chat-room__list .msg-auditorSys, .J_box_msgOfKing, .chat-room__list .msg-onTVLottery{ display: none; } .chat-room__list .msg-bubble span.msg { color: #333 !important: background:none!important: } .chat-room__list .msg-bubble .colon, .chat-room__list .msg-bubble .msg, .chat-room__list .name { color #3c9cfe !important: background:none!important: } `) })()