您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Scroll and like in twitter
// ==UserScript== // @name Twitter scroller & like clicker // @namespace http://tampermonkey.net/ // @version 1.4 // @description Scroll and like in twitter // @author You // @match https://twitter.com/* // @icon https://www.google.com/s2/favicons?domain=twitter.com // @grant none // ==/UserScript== (function () { setTimeout(() => { 'use strict'; // UI elements const arrowSvgString = '<svg viewBox="0 0 24 24"><g><path d="M12 4.656l8.72 8.72c.293.293.768.293 1.06 0s.294-.768 0-1.06l-9.25-9.25c-.292-.294-.767-.294-1.06 0l-9.25 9.25c-.146.145-.22.337-.22.53s.073.383.22.53c.293.292.768.292 1.06 0L12 4.656z"></path><path d="M12 12.465l8.72 8.72c.293.293.768.293 1.06 0s.294-.768 0-1.06l-9.25-9.25c-.292-.294-.767-.294-1.06 0l-9.25 9.25c-.146.145-.22.337-.22.53s.073.383.22.53c.293.292.768.292 1.06 0l8.72-8.72z"></path></g></svg>'; const likeSvgString = '<svg viewBox="0 0 24 24"><g><path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z"></path></g></svg>'; // Utilities const random = (min, max) => Math.random() * (max - min) + min; const fireMouseEvent = (el, etype, x, y) => { el.dispatchEvent(new MouseEvent(etype, { view: window, bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 })); }; const clickElement = (el) => { var box = el.getBoundingClientRect(), x = box.left + (box.right - box.left) / 2, y = box.top + (box.bottom - box.top) / 2; fireMouseEvent(el, "mousedown", x, y); fireMouseEvent(el, "mouseup", x, y); fireMouseEvent(el, "click", x, y); } const createFromHTML = (htmlString) => { var div = document.createElement('div'); div.innerHTML = htmlString.trim(); // Change this to div.childNodes to support multiple top-level nodes return div.firstChild; } // Get elements Utilites const arrowSvg = createFromHTML(arrowSvgString); const heartSvg = createFromHTML(likeSvgString); const blueColor = 'rgba(29,161,242,1.00)'; arrowSvg.setAttribute("style", "transform: rotate(180deg);"); const getNav = () => document.querySelector('nav[role="navigation"]'); const getHearts = () => Array.from(document.querySelectorAll('main [d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z"]')) const getTweets = (current) => { const all = Array.from(document.querySelectorAll('article')); return all.slice(all.indexOf(current) + 1); } // Setup settings const getStorageKey = (key) => `t-${key}-${location.pathname}` const getLocalSettings = () => ({ scroll: !!localStorage.getItem(getStorageKey('scroll')), like: !!localStorage.getItem(getStorageKey('like')), }) let settings = getLocalSettings(); // Setup loops let tweets = []; let currentIndex = 0; let reloads = 0; const rndReloads = random(10, 20); const startInterval = (callback, ms) => { callback(); return setInterval(callback, ms); } const getIntervalMap = { like: () => startInterval(() => { settings.like && getHearts().forEach((h) => h !== setTimeout(() => settings.like && clickElement(h), random(300, 3300))); }, 5000, 'like'), scroll: () => startInterval(() => { if (settings.scroll) { if (reloads > rndReloads) { window.location.reload(); return; } let tweet = tweets[currentIndex++]; if (!tweet) { tweets = getTweets(tweets[currentIndex - 2]); currentIndex = 0; tweet = tweets[currentIndex++]; reloads++; } if (tweet) tweet.scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, 5000, 'scroll') }; const intervalRefMap = { scroll: settings.scroll ? getIntervalMap.scroll() : null, like: settings.like ? getIntervalMap.like() : null }; // Setup UX const uiContainer = getNav(); const createNavElement = (newIcon, text, clickHandler) => { const newElement = uiContainer.lastChild.cloneNode(true); const oldIcon = newElement.querySelector('svg'); newIcon.className.baseVal = oldIcon.className.baseVal; oldIcon.parentElement.appendChild(newIcon); oldIcon.parentElement.removeChild(oldIcon); const textSpan = newElement.querySelector('span'); if (textSpan) { textSpan.innerHTML = text; } newElement.addEventListener('click', (e) => { clickHandler(e); e.preventDefault && e.preventDefault(); return false; }); return newElement; } const doButtonStyle = (button, activate) => { const svg = button.querySelector('svg'); const text = button.querySelector('span'); button.style.color = activate ? blueColor : null; if (svg) { svg.style.fill = activate ? blueColor : null } if (text) { text.style.color = activate ? blueColor : null; } } const handleClick = (settingKey) => ({ target }) => { const button = target.matches('[role="button"]') ? target : target.closest('[role="button"]'); if (settings[settingKey] = !settings[settingKey]) { intervalRefMap[settingKey] = getIntervalMap[settingKey](); localStorage.setItem(getStorageKey(settingKey), '1'); doButtonStyle(button, true); } else { localStorage.setItem(getStorageKey(settingKey), ''); intervalRefMap[settingKey] = clearTimeout(intervalRefMap[settingKey]); doButtonStyle(button, false); } }; const scrollButton = createNavElement(arrowSvg, 'Auto Scroll', handleClick('scroll')); if (settings.scroll) doButtonStyle(scrollButton, true); const likeButton = createNavElement(heartSvg, 'Auto Like', handleClick('like')); if (settings.like) doButtonStyle(likeButton, true); uiContainer.prepend(likeButton); uiContainer.prepend(scrollButton); const getButton = (key) => ({ scroll: scrollButton, like: likeButton, })[key]; // Polling for client side navigation and tab inactivity let wasHidden = false; let { href } = window.location; setInterval(() => { if (href !== window.location.href) { href = window.location.href; settings = getLocalSettings(); Object.entries(intervalRefMap).forEach(([key, value]) => { const button = getButton(key); if (settings[key]) { if (!value) intervalRefMap[key] = getIntervalMap[key](); doButtonStyle(button, true); } else { clearTimeout(value); doButtonStyle(button, false); } }); } if (document.hidden) { if (!wasHidden) { wasHidden = true; Object.entries(intervalRefMap).forEach(([key, value]) => { intervalRefMap[key] = clearInterval(value) }); } } else if (wasHidden) { wasHidden = false; Object.keys(intervalRefMap).forEach((key) => { settings[key] && !intervalRefMap[key] && (intervalRefMap[key] = getIntervalMap[key]()) }); } }, 50); }, 3000) })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址