Greasy Fork

Greasy Fork is available in English.

旋转的五分硬币排队

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

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

// ==UserScript==
// @name         旋转的五分硬币排队
// @namespace    http://tampermonkey.net/
// @version      0.0.7
// @description  旋转的五分硬币直播间深渊排队脚本
// @author       Mimiko
// @license      MIT
// @match        *://live.bilibili.com/3140454*
// @icon         http://i0.hdslb.com/bfs/activity-plat/static/20211202/dddbda27ce6f43bf18f5bca141752a99/fCo7evLooK.webp@128w
// @grant        GM.xmlhttpRequest
// ==/UserScript==

(() => {
    if (window.top !== window.self)
        return;
    const cacheId = new Set();
    const cacheName = new Map();
    const interval = 30e3;
    const listMaster = ['旋转的五分硬币', '御御子'];
    const observer = new MutationObserver(() => pick());
    const port = 9644;
    const speaker = new SpeechSynthesisUtterance();
    let isPaused = false;
    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',
            onerror: () => resolve(null),
            onload: (response) => resolve(JSON.parse(response.responseText)),
            url,
        });
    });
    const log = (message) => {
        console.log(message);
        return message;
    };
    const main = () => {
        pauseVideo();
        observe();
    };
    const observe = () => {
        const timer = window.setInterval(() => {
            const $el = document.getElementById('chat-items');
            if (!$el)
                return;
            window.clearInterval(timer);
            observer.observe($el, {
                childList: true,
                attributes: true,
                characterData: true,
            });
        }, 50);
    };
    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 ([
            '恢复排队', '排队恢复',
            '开始排队', '排队开始',
        ].includes(content) && listMaster.includes(name))
            return isPaused = false;
        if ([
            '结束排队', '排队结束',
            '停止排队', '排队停止',
            '暂停排队', '排队暂停',
        ].includes(content) && listMaster.includes(name))
            return isPaused = true;
        if (content === '排队') {
            if (isPaused)
                return speak('现在暂时不能排队');
            return add(name, id);
        }
        if (content.startsWith('查询排队') || content.startsWith('排队查询')) {
            const name2 = content
                .replace('查询排队', '')
                .replace('排队查询', '')
                .trim() || '';
            return search(name2 || name, id);
        }
        return;
    });
    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) => {
        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;
    };
    window.setTimeout(main, 1e3);
})();