Greasy Fork

Greasy Fork is available in English.

旋转的五分硬币排队

旋转的五分硬币直播间深渊排队脚本

当前为 2021-12-06 提交的版本,查看 最新版本

// ==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
// ==/UserScript==
// With lots of thx to Rexze
// http://greasyfork.icu/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)

})()