一个简单的等待循环程序。有任何问题,欢迎反馈
// ==UserScript== // @name 神乐直播间自动打卡 // @namespace pyroho // @version 2.1 // @description 一个简单的等待循环程序。有任何问题,欢迎反馈 // @author PyroHo // @match https://www.douyu.com/* // @run-at document-start // @icon https://www.google.com/s2/favicons?sz=64&domain=douyu.com // @license MIT // ==/UserScript== const CLOCK_IN_INTERVAL = 30 * 60 * 1000 + 10000; // 打卡间隔30分钟,单位为毫秒 const ROOM_ID = /(85894|122402|6566671|20415)/i.exec(window.location.href)?.[0] ?? 0; // 通过网页地址获取房间号 const TimeSave = new Proxy({}, { get: (t, prop, r) => localStorage.getItem(`lastClockInTime${prop}`), set: (t, prop, value, r) => localStorage.setItem(`lastClockInTime${prop}`, value), deleteProperty: (t, key) => localStorage.removeItem(`lastClockInTime${key}`), }); let timestop = ()=>{}; const STYLE = ` div[class*=host][class*=danmuItem] { display: none !important; } .btn-ci { display: inline-block; padding: 0 3px; border-radius: 3px; margin-right: 8px; vertical-align: middle; line-height: 1.5; font-size: 12px; cursor: pointer; color: #fff !important; background-color: #888 !important; } .btn-ci.btn-ci-cur { color: #7e7e7e !important; background-color: #464646 !important; /* cursor: not-allowed; */ } .btn-ci.btn-clock-in { background-color: #4caf50 !important; } `; // 创建一个链接 function nodeLink(text, link) { let node = document.createElement("a"); node.innerText = text; node.setAttribute('href', link); node.classList.add('btn-room-change'); return node; } // 创建一个按钮节点 function nodeButton(text, onclick) { let btn = document.createElement("button"); btn.addEventListener('click', onclick, false); btn.innerText = text; btn.classList.add('btn-ci', 'btn-clock-in'); return btn; } // 插入按钮 function insertDom() { const wrap = document.querySelector('div.ChatToolBar'); const domInfo = [ ['星', '85894'] , ['华', '122402'] , ['粤', '6566671'] , ['欧', '20415'] ]; domInfo.forEach(([name, id]) => { let btn = nodeLink(name, `/${id}`); if(ROOM_ID === id) { btn.classList.add('btn-ci-cur'); btn.removeAttribute('href'); } btn.classList.add('btn-ci'); wrap.appendChild(btn); }); wrap.appendChild(nodeButton('打卡', () => autoClockIn(true))); } // 可读时间 function timeStr(ms) { const date = new Date(ms); return ['getMinutes', 'getSeconds'].map(f => date[f]()).join(':'); } // 元素聚焦之后的一定时间内,保持元素聚焦 // function keepEleFocus(el, time = 8000) { // let timeout = false; // const setTimer = () => { // timeout = setTimeout(() => timeout=false, time) // }; // const resetTimer = _.throttle(() => { // if(timeout) { // el.focus(); // clearTimeout(timeout); // setTimer(); // } // }, 300, { leading: true, trailing: true }); // el.addEventListener('focus', () => timeout || setTimer(), false); // el.addEventListener('blur', resetTimer, false); // el.addEventListener('input', resetTimer, false); // } // 一秒钟刷新一次时间 // 返回一个函数:调用即可停止 function loopShowTimeInElement({ele, prop, delay=0, onclose=()=>{}}) { const targetTime = new Date(Date.now() + delay); let stop; (function updateTime() { ele.setAttribute(prop, `下次打卡:${timeStr(targetTime - Date.now())}`) if(Date.now() > targetTime) { clearTimeout(stop); onclose(); } else { stop = setTimeout(updateTime, 1000); } })(); return () => clearTimeout(stop); } // 创建打卡,自带循环 function autoClockIn(force = false) { const textarea = document.querySelector('textarea.ChatSend-txt'); const button = document.querySelector('div.ChatSend-button'); // keepEleFocus(textarea); const lastClockIn = parseInt(TimeSave[ROOM_ID]) || 0; // 获取上次打卡时间 const now = Date.now(); // 获取当前时间 const timeGoes = now - lastClockIn; let nextClockInDelay = CLOCK_IN_INTERVAL-timeGoes; timestop(); if (force || timeGoes >= CLOCK_IN_INTERVAL) { const temp = textarea.value; // 如果上次打卡时间不存在或距离当前时间已经超过了30分钟,则进行打卡操作 textarea.value = "#打卡"; button.click(); textarea.value = temp; TimeSave[ROOM_ID] = now; // 将本次打卡时间存储在本地存储中 nextClockInDelay = CLOCK_IN_INTERVAL; } timestop = loopShowTimeInElement({ ele: textarea, prop: 'placeholder', delay: nextClockInDelay, onclose: autoClockIn, }); } 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); } ROOM_ID && (function loadApp(total, stop=0) { const appLoaded = document.readyState === 'complete' && document.querySelector('.btn-clock-in') === null; if(appLoaded) { insertDom(); loadStyle(STYLE); // clearTimeout(stop); stop || (stop = setTimeout(autoClockIn, 4500)); } setTimeout(() => loadApp(--total, stop), 300); })(100);