// ==UserScript== // @name 旋转的五分硬币排队 // @namespace http://tampermonkey.net/ // @version 0.0.6 // @description 旋转的五分硬币直播间深渊排队脚本 // @author Mimiko // @license MIT // @match *://live.bilibili.com/3140454* // @match *://live.bilibili.com/743364* // @icon http://i0.hdslb.com/bfs/activity-plat/static/20211202/dddbda27ce6f43bf18f5bca141752a99/fCo7evLooK.webp@128w // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== // With lots of thx to Rexze // https://greasyfork.org/en/scripts/436443-%E6%97%8B%E8%BD%AC%E7%9A%84%E4%BA%94%E5%88%86%E7%A1%AC%E5%B8%81%E6%8E%92%E9%98%9F (() => { if (window.top !== window.self) return // variable const cacheId = new Set() const cacheName = new Map() const interval = 30e3 const observer = new MutationObserver(() => pick()) const port = 9644 const speaker = new SpeechSynthesisUtterance() // function const add = async ( name, id, ) => { if (!validate(name, id)) return const data = await get(`http://localhost:${port}/add?name=${name}`) if (!data) return speak(data.message) } const get = ( url, ) => new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url, onError: () => resolve(null), onload: (response) => resolve(JSON.parse(response.responseText)), }) }) const main = () => { pauseVideo() observer.observe(document.getElementById('chat-items'), { childList: true, attributes: true, characterData: true, }) } const pauseVideo = () => document.querySelector('video')?.pause() const pick = () => Array.from(document.querySelectorAll('#chat-items .danmaku-item')).forEach($danmaku => { const content = $danmaku.getAttribute('data-danmaku')?.trim() || '' const id = $danmaku.getAttribute('data-ct')?.trim() || '' const name = $danmaku.getAttribute('data-uname')?.trim() || '' if (content === '排队') return add(name, id) if (['查询排队', '排队查询'].includes(content)) return search(name, id) }) const search = async ( name, id, ) => { if (!validate(name, id)) return const data = await get(`http://localhost:${port}/search?name=${name}`) if (!data) return speak(data.message) } const speak = ( message, ) => { console.log(message) speaker.text = message window.speechSynthesis.speak(speaker) } const validate = ( name, id, ) => { if (cacheId.has(id)) return false cacheId.add(id) const ts = cacheName.get(name) || 0 const now = Date.now() if (now - ts < interval) return false cacheName.set(name, now) return true } // execute window.setTimeout(main, 1e3) })()