// ==UserScript== // @name 斗鱼清爽版【整合功能】 // @author sam // @namespace https://greasyfork.org/zh-CN/scripts/390452 // @version 1.0.8 // @description douyu整合优化斗鱼功能脚本(斗鱼精简、斗鱼真实人数显示、斗鱼默认最高画质) // @match http*://www.douyu.com/* // @icon https://www.douyu.com/favicon.ico // @require https://code.jquery.com/jquery-2.2.4.min.js // @run-at document-end // @note 斗鱼精简 https://greasyfork.org/zh-CN/scripts/386642 // @note 斗鱼真实人数显示 https://greasyfork.org/zh-CN/scripts/388941 // @note 斗鱼默认最高画质 https://greasyfork.org/zh-CN/scripts/384173 /* 主要功能: 1.精简douyu.com页面元素 2.直播打开直播页面自动页面全屏,自动切换最高清晰度画质 3.弹幕栏顶部增加真实人数显示 2019/10/9 v1.0.7 1.调整<我的关注>页面,增加开播时间(缩小字体样式) 2.直播页面调整人数、人气,以万为单位(1万一下显示原始数据),增加<我的关注>页面按钮 todo:增加关注页面监控器模式 todo:通过页面播放器直接切换画质、切换全屏(不再依赖播放器控件自动点击,以提高自动切换速度) 2019/10/12 v1.0.8 1.增加快捷键控制播放器(shift=全屏切换 ctrl=静音开关 tab=弹幕开关)可自行通过KeyMap(263行)映射快捷键 */ // @downloadURL none // ==/UserScript== (function () { 'use strict'; window.onload = function () { var curent_url = window.location.href; console.log('[Neat Douyu Stream] url --> ' + curent_url) loadStyle(css);//精简界面 modifiedMyFollow();//调整“我的收藏”页面 changeDom();//调整右侧弹幕dom高度 autoSwitch();//切换最高画质 autoClickFullscreen();//窗口化全屏 addKeyboardListener(); setTimeout(getRealViewer, 3000);//真实人数,添加<我的关注>按钮 setInterval(getRealViewer, 10000); }; })(); function waitDom(dom_selector, func) { /* 功能:等待dom加载后执行函数 dom_selector :选择器参数 待加载的dom = document.querySelector(dom_selector) func:待执行函数体,用匿名函数传参 */ let dom_is_exist = false for (var i = 0; i < 100; i++) { (function (i) { setTimeout(function () { if (document.querySelector(dom_selector)) { if (!dom_is_exist) { func() dom_is_exist = true } } }, (i + 1) * 200); })(i) } }; const CODE2KEY = { '8': 'BackSpace', '9': 'Tab', '12': 'Clear', '13': 'Enter', '16': 'Shift', '17': 'Control', '18': 'Alt', '19': 'Pause', '20': 'CapsLock', '27': 'Escape', '32': 'space', '33': 'Prior', '34': 'Next', '35': 'End', '36': 'Home', '37': 'Left', '38': 'Up', '39': 'Right', '40': 'Down', '41': 'Select', '42': 'Print', '43': 'Execute', '45': 'Insert', '46': 'Delete', '47': 'Help', '48': '0', '49': '1', '50': '2', '51': '3', '52': '4', '53': '5', '54': '6', '55': '7', '56': '8', '57': '9', '65': 'a', '66': 'b', '67': 'c', '68': 'd', '69': 'e', '70': 'f', '71': 'g', '72': 'h', '73': 'i', '74': 'j', '75': 'k', '76': 'l', '77': 'm', '78': 'n', '79': 'o', '80': 'p', '81': 'q', '82': 'r', '83': 's', '84': 't', '85': 'u', '86': 'v', '87': 'w', '88': 'x', '89': 'y', '90': 'z', '96': 'KP_0', '97': 'KP_1', '98': 'KP_2', '99': 'KP_3', '100': 'KP_4', '101': 'KP_5', '102': 'KP_6', '103': 'KP_7', '104': 'KP_8', '105': 'KP_9', '106': 'KP_Multiply', '107': 'KP_Add', '108': 'KP_Separator', '109': 'KP_Subtract', '110': 'KP_Decimal', '111': 'KP_Divide', '112': 'F1', '113': 'F2', '114': 'F3', '115': 'F4', '116': 'F5', '117': 'F6', '118': 'F7', '119': 'F8', '120': 'F9', '121': 'F10', '122': 'F11', '123': 'F12', } const KEY2CODE = { 'BackSpace': 8, 'Tab': 9, 'Clear': 12, 'Enter': 13, 'Shift': 16, 'Control': 17, 'Alt': 18, 'Pause': 19, 'CapsLock': 20, 'Escape': 27, 'space': 32, 'Prior': 33, 'Next': 34, 'End': 35, 'Home': 36, 'Left': 37, 'Up': 38, 'Right': 39, 'Down': 40, 'Select': 41, 'Print': 42, 'Execute': 43, 'Insert': 45, 'Delete': 46, 'Help': 47, '0': 48, '1': 49, '2': 50, '3': 51, '4': 52, '5': 53, '6': 54, '7': 55, '8': 56, '9': 57, 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73, 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82, 's': 83, 't': 84, 'u': 85, 'v': 86, 'w': 87, 'x': 88, 'y': 89, 'z': 90, 'KP_0': 96, 'KP_1': 97, 'KP_2': 98, 'KP_3': 99, 'KP_4': 100, 'KP_5': 101, 'KP_6': 102, 'KP_7': 103, 'KP_8': 104, 'KP_9': 105, 'KP_Multiply': 106, 'KP_Add': 107, 'KP_Separator': 108, 'KP_Subtract': 109, 'KP_Decimal': 110, 'KP_Divide': 111, 'F1': 112, 'F2': 113, 'F3': 114, 'F4': 115, 'F5': 116, 'F6': 117, 'F7': 118, 'F8': 119, 'F9': 120, 'F10': 121, 'F11': 122, 'F12': 123, } const Controller_Selectors = { 'muted': ['div.volume-8e2726', 'div.volume-silent-3eb726'], 'danmu': ['div.showdanmu-42b0ac', 'div.hidedanmu-5d54e2'], 'fullscreen': ['div.fs-781153', 'div.fs-exit-b6e6a7'], } const KeyMap = { 'Control': 'muted', 'Tab': 'danmu', 'Shift': 'fullscreen', } const ClickedClassName = 'removed-9d4c42' function isClicked(dom) { let class_name = dom.className.split(' ') // console.log(class_name) if (class_name.includes(ClickedClassName)) { return true } else { return false }; } function checkKey(keyCode) { if (KeyMap[keyCode]) { let selectors = Controller_Selectors[KeyMap[keyCode]] let dom1 = document.querySelector(selectors[0]) let dom2 = document.querySelector(selectors[1]) if (isClicked(dom1)) { dom2.click() }else{ dom1.click() } } } function addKeyboardListener() { let dom_selector = 'div.right-e7ea5d' //播放器控制组件 waitDom(dom_selector, function () { console.log('初始化按键监听') document.onkeydown = function (event) { var e = event || window.event || arguments.callee.caller.arguments[0]; if (e && e.keyCode) { // 按 Esc if (CODE2KEY[event.keyCode]) { // console.log('按下了:', CODE2KEY[event.keyCode]); checkKey(CODE2KEY[event.keyCode]) } } }; }) }; function modifiedMyFollow() { var curent_path = window.location.pathname; if (curent_path == "/directory/myFollow") { //移除‘我的关注’页面推广主播 let dom_selector = "div.AthenaBoothPanel-content"; waitDom(dom_selector, function () { var cover_list = document.querySelectorAll("li.layout-Cover-item"); var cover_0 = cover_list[0].querySelector('div.layout-Cover-card').getAttribute('class') == "layout-Cover-card", cover_1 = cover_list[1].querySelector('div.layout-Cover-card').getAttribute('class') == "layout-Cover-card dycard-first"; if (cover_0 & cover_1) { cover_list[0].remove(); console.log('[Neat Douyu Stream]移除‘我的关注’页面推广主播') let parent = document.querySelector("#js-follow > section > div.layout-Module-container.layout-Cover.ScrollTabFrame-layoutContainer > ul"); let frame = "" //$(frame).prependTo(parent); //cover_list[1].innerHTML = frame; }; //调整收藏页面,增加开播时间显示 let css_stream = ".DyLiveCover-user {display: block;padding-right: 5px;overflow: hidden;-o-text-overflow: ellipsis;text-overflow: ellipsis;white-space: nowrap;color: #888;font-size: 10px;line-height: 24px;margin: 0;font-weight: 500}" loadStyle(css_stream); cover_list.forEach(each => { let cover_card = each.querySelector("div.DyLiveCover") if (cover_card) { let stream_start_time = timeStampTurnTime(cover_card.getAttribute("showtime")), stream_title = cover_card.querySelector("h2.DyLiveCover-user") if (stream_start_time) { console.log(stream_start_time); stream_title.innerText = stream_start_time //stream_title.style.fontSize = 10; } } }); }); }; }; function autoClickFullscreen() { let dom_selector = "div.wfs-2a8e83" waitDom(dom_selector, function () { document.querySelector(dom_selector).click(); console.log('[Neat Douyu Stream]页面自动全屏'); }); }; function changeDom() { let dom_selector = "div.Barrage"; waitDom(dom_selector, function () { document.querySelector(dom_selector).style.top = "38px";//调整弹幕区域高度 console.log('[Neat Douyu Stream]弹幕区域已调整'); }); }; var css = '{display:none !important;height:0 !important}'; css += '.layout-Player-rank{display:none !important}'; css += '.layout-Player-barrage{top:0px !important;}'; css += '.layout-Player-video{bottom:0px !important}'; css += '.layout-Player-toolbar{visibility:hidden !important;}'; css += '.layout-Bottom{display:none !important;}'; css += '.guessGameContainer.is-normalRoom{display:none !important;}'; css += '.DropPane-ad{display:none !important}'; css += '.SignBaseComponent-sign-ad{display:none !important}'; //css += '.AnchorAnnounce{display:none !important;}'; //斗鱼真实人数显示 css += '.FansMedalPanel-enter{display:none !important;}'; css += '.layout-Aside{display:none !important;}'; css += '.Header-download-wrap{display:none !important;}'; css += '.Header-broadcast-wrap{display:none !important;}'; css += '#js-header > div > div > div.Header-left > div > ul > li:nth-child(5){display:none !important;}'; css += '.ChatNobleBarrage{display:none !important;}'; css += '.ChatFansBarrage{display:none !important;}'; css += '.Horn4Category{display:none !important;}'; css += '.FirePower{display:none !important;}'; css += '.TreasureDetail{display:none !important;}'; css += '.SignChatAd-chat-ad-cls{display:none !important;}'; css += '.Promotion-nobleRights{display:none !important;}'; css += '.Task{display:none !important;}'; css += '.UPlayerLotteryEnter.is-active{display:none !important;}'; css += '.LotteryContainer{display:none !important;}'; css += '.layout-Module-head.FollowList-head.is-fixed{display:none !important;}'; css += '.layout-Banner-item{display:none !important;}'; css += '.layout-Module-extra{display:none !important;}'; css += '.Title-anchorPic{display:none !important;}'; css += '.Title-roomOtherBottom{display:none !important;}'; css += '.Act129684Bar-view1{display:none !important;}'; css += '.Act129684Bar-content{display:none !important;}'; css += '.Act129684-logo{display:none !important;}'; css += '.ActBase-switch{display:none !important;}'; css += '.HeaderNav{display:none !important;}'; css += '.HeaderGif-left{display:none !important;}'; css += '.HeaderGif-right{display:none !important;}'; css += '.Prompt-container{display:none !important;}'; css += '.SysSign-Ad{display:none !important;}'; css += '.ActDayPay-toast{display:none !important;}'; css += '.code_box-5cdf5a{display:none !important;}'; css += '.normalDiv-8b686d{display:none !important;}'; css += '.closeBg-998534{display:none !important;}'; css += '.bg-d4758b{display:none !important;}'; css += '.fireOpenRanking react-draggable react-draggable-dragged{display:none !important;}'; css += '.vsFestival1908{display:none !important;}'; css += '.ActSuperFansGroup-component.ActSuperFansGroupBar-normalBody{display:none !important;}'; css += '.ActSuperFansGroup-component.ActSuperFansGroupBar-miniBody{display:none !important;}'; css += '.ActSuperFansGroup-component.ActSuperFansGroupBar-plusBody{display:none !important;}'; css += '.ActSuperFansGroup-logo{display:none !important;}'; css += '.ActSuperFansGroup-switch{display:none !important;}'; css += '.TitleSuperFansIcon{display:none !important;}'; css += '.Act156581Bar{display:none !important;}'; css += '.Act159742Bar-main--pre{display:none !important;}'; css += '.Act159742-logo{display:none !important;}'; css += '.Act159742Bar-wrap{display:none !important;}'; css += '.Title-columnTag{display:none !important;}'; css += '.Title-impress.clearFix{display:none !important;}'; function loadStyle(css) { var style = document.createElement('style'); style.type = 'text/css'; style.rel = 'stylesheet'; style.appendChild(document.createTextNode(css)); var head = document.getElementsByTagName('head')[0]; head.appendChild(style); console.log('[Neat Douyu Stream]css已加载'); }; function formatNumber(fmt_num) { let num_tmp = Number(fmt_num) //console.log('num_tmp ->',num_tmp) if (num_tmp == void 0) { return '0' } else { if (num_tmp > 10000) { return String((num_tmp / 10000).toFixed(1)) + '万' } else { return String(fmt_num) } } }; function genIcon(lable, message, color) { if (lable !== '') { lable = encodeURI(lable) } message = encodeURI(message) if (color === '') { color = 'E61A1A' } let img_src = 'https://img.shields.io/badge/' + lable + '-' + message + '-' + color let icon = ''; return icon }; function getRealViewer() { let viewIcon = '' let hotIcon = '' let a = { view: "", showtime: "", hot: "" } let myFollow_icon = '我的关注' let myFollow = "" + myFollow_icon + " " + ""; //let myFollow = genIcon('我的收藏',10,'E61A1A') let url = document.getElementsByTagName('html')[0].innerHTML; let urlLen = ("$ROOM.room_id =").length; let ridPos = url.indexOf('$ROOM.room_id ='); let rid = url.substring(ridPos + urlLen, url.indexOf(';', ridPos + urlLen)); rid = rid.trim(); if (document.querySelector(".MatchSystemChatRoomEntry") != null) { document.querySelector(".MatchSystemChatRoomEntry").style.display = "none"; } $.get("https://www.douyu.com/swf_api/h5room/" + rid, function (retData) { a.view = retData.data.online; a.view = formatNumber(a.view) a.view = '' + a.view + "" a.view = "
" + viewIcon + a.view + "
" a.hot = document.querySelector(".Title-anchorText").innerHTML; a.hot = formatNumber(a.hot) a.hot = '' + a.hot + "" a.showtime = timeStampTurnTime(retData.data.show_time); a.hot = "
" + hotIcon + a.hot + "
" /* a.view = retData.data.online; a.view = genIcon('人数',formatThousand(a.view),'') a.hot = document.querySelector(".Title-anchorText").innerHTML; a.hot = genIcon('人气',formatThousand(a.hot),'') */ document.querySelector(".AnchorAnnounce").innerHTML = myFollow + a.view + " " + a.hot + '' + "开播时间:" + a.showtime + ""; }); }; function timeStampTurnTime(timeStamp) { if (timeStamp > 0) { let date = new Date(); date.setTime(timeStamp * 1000); let y = date.getFullYear(); let m = date.getMonth() + 1; m = m < 10 ? ('0' + m) : m; let d = date.getDate(); d = d < 10 ? ('0' + d) : d; let h = date.getHours(); h = h < 10 ? ('0' + h) : h; let minute = date.getMinutes(); let second = date.getSeconds(); minute = minute < 10 ? ('0' + minute) : minute; second = second < 10 ? ('0' + second) : second; return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second; } else { return ""; } }; function autoSwitch() { const startTime = new Date().getTime() let count = 1 let dom = Array.from(document.querySelectorAll('input')).find((item, index) => { return item.value.includes('画质') }); if (dom) { const ul_dom = Array.from(dom.parentNode.childNodes).find((item) => item.tagName == 'UL') const li_dom = Array.from(ul_dom.childNodes) let seleteIndex = 0 li_dom.forEach((item, index) => { if (item.className != '') { seleteIndex = index } }) if (seleteIndex == 0) { const endTime = new Date().getTime() console.log('默认为最高画质,无需切换') console.log(`脚本结束,耗时:${(endTime - startTime) / 1000}秒`) } else { const endTime = new Date().getTime() const old_quality = li_dom[seleteIndex].innerText const new_quelity = li_dom[0].innerText li_dom[0].click() console.log(`已从${old_quality}切换到${new_quelity}`) console.log(`脚本结束,耗时:${(endTime - startTime) / 1000}秒`) console.log('[Neat Douyu Stream]画质已切换为最高'); } } else { if (count++ < 50) { setTimeout(() => { autoSwitch() }, 200) } else { console.log('脚本结束,可能此网站不是直播间') } } };