Greasy Fork is available in English.
倒计时自动点击,电商抢东西专用
// ==UserScript== // @name Timing Click // @namespace http://tampermonkey.net/ // @version 0.3.1 // @description 倒计时自动点击,电商抢东西专用 // @author Cherokeeli // @match *://*.taobao.com/* // @match *://*.jd.com/* // @match *://*.tmall.com/* // @require https://code.jquery.com/jquery-latest.js // @run-at document-idle // @grant GM_addStyle // @grant GM_getResourceText // @grant GM_xmlhttpRequest // @connect githubusercontent.com // @connect gitee.com // ==/UserScript== (function() { 'use strict'; var $ = $ || window.$; var _$ = $.noConflict(true); var countWoker = "https://gitee.com/erokee/monkey-lib/raw/master/timing-click/count-worker.js"; var avatar = "https://gitee.com/erokee/monkey-lib/raw/master/timing-click/image/1.pic.png"; var mainCss = `#ql-panel #counterClickTime { position:relative; z-index:999; height: 20px !important; width: 150px !important; font-size: 1em !important; padding: 5px !important; border: none !important; margin: 0 !important; } #ql-panel #counterClickSelector { position:relative; z-index:999; height: 20px !important; width: 150px !important; font-size: 1em !important; padding: 5px !important; border: none !important; margin: 0 !important; } #ql-panel #listenButton { position:relative; z-index:999; width: 100% !important; border: none !important; color: red !important; font-size: 1em !important; margin: 0 !important; background-color: #fff; } #ql-panel #triggerButton { height:50px; width:50px; position:relative; z-index:9999; background-position:center; background-size:100%; background-image:url(${avatar}); } #ql-panel { position:fixed; z-index:9999; top: 10vh; left: 5vw; } #ql-panel #hidePanel { position:absolute; z-index:9999; display:none; border: solid 1px rgb(238,238,238) !important; box-shadow: 0 0 5px rgb(213,210,210) !important; }`; /*拖动*/ class DragObj { constructor(dom) { this.mouse = { x: 0, y: 0 }; this.obj = { x: 0, y: 0 }; this.isClicked = false; if(dom) { this.dom = dom; } else { throw new Error('不存在的dom节点'); } } init(options={}) { document.addEventListener('mousedown', this.down.bind(this)); document.addEventListener('mousemove', this.move.bind(this)); document.addEventListener('mouseup', this.end.bind(this)); if(typeof options.click ==='function') { this.clickCb = options.click; } if(typeof options.exclude === 'object') { this.excludeDom = options.exclude; } if(typeof options.include === 'object') { this.includeDom = options.include; } } down(event) { if(this.includeDom.contains(event.target)) { this.isClicked = true; this.mouse.x = event.clientX; this.mouse.y = event.clientY; this.obj.x = this.dom.offsetLeft; this.obj.y = this.dom.offsetTop; } } move(event) { if(this.isClicked) { let moveX = event.clientX - this.mouse.x; let moveY = event.clientY - this.mouse.y; this.dom.style.left = `${this.obj.x+moveX}px`; this.dom.style.top = `${this.obj.y+moveY}px`; } } end(event) { this.isClicked = false; if(this.clickCb && (event.clientX === this.mouse.x && event.clientY===this.mouse.y)) { if(!this.excludeDom.contains(event.target) && this.includeDom.contains(event.target)) { this.clickCb(event); } } } } GM_addStyle(mainCss); let timeInput = _$('<input id="counterClickTime" placeholder="输入开抢时间" type="datetime-local" step="1" value="2019-10-12T07:22:00" />'); let selectorInput = _$('<input id="counterClickSelector" placeholder="输入抢按钮选择器" type="text" />'); let listenButton = _$('<button id="listenButton">准备开抢</button>'); let triggerButton = _$('<div id="triggerButton"></div>'); let panel = _$('<div id="ql-panel"></div>'); let hidePanel = _$('<div id="hidePanel"></div>'); hidePanel.append(timeInput.val(dateFormatter.call(new Date(), 'yyyy-MM-ddThh:mm:ss'))); hidePanel.append(selectorInput); hidePanel.append(listenButton); panel.append(triggerButton); panel.append(hidePanel); _$(document.body).append(panel); (new DragObj(panel[0])).init({ click: function(event) { hidePanel.toggle('slow'); }, exclude: hidePanel[0], include: panel[0] }); function dateFormatter(fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; } function fireEvent(dom, eventName) { let event = new MouseEvent(eventName); return dom.dispatchEvent(event); } function createWorkerFromExternalURL(url, callback) { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (response) { var script, dataURL, worker = null; if (response.status === 200) { script = response.responseText; dataURL = 'data:text/javascript;base64,' + btoa(script); worker = new unsafeWindow.Worker(dataURL); } callback(worker); }, onerror: function () { callback(null); } }); } function stepClick(times, stepInterval, clickFn) { if (!times) return; if (clickFn) clickFn(); setTimeout(function () { stepClick(--times, stepInterval, clickFn); }, stepInterval); } /*开始抢*/ listenButton.click(function(e) { let time = timeInput.val(); let targetTime = Date.parse(new Date(time)); let currentTime = Date.now(); let timeout = targetTime-currentTime; console.log(timeout, selectorInput.val()); createWorkerFromExternalURL(countWoker, function (worker) { if (!worker) throw Error('Create webworker failed'); let btn = listenButton[0]; worker.onmessage = function (event) { if (event.data === -1) { btn.disabled = false; stepClick(3, 100, function () { _$(selectorInput.val()).trigger('click'); fireEvent(document.querySelector(selectorInput.val()), 'click'); }); worker.terminate(); } else { btn.disabled = true; btn.innerHTML = `距离开抢还有${Math.ceil(event.data / 1000)}秒`; } }; worker.postMessage(timeout); }); }); })();