您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
[s]try to take over the world![/s] infinite scroll, filter: public, private, duration
当前为
// ==UserScript== // @name thisvid infinite scroll and filter // @license MIT // @namespace http://tampermonkey.net/ // @version 2.0.0 // @description [s]try to take over the world![/s] infinite scroll, filter: public, private, duration // @author smartacephale // @match https://thisvid.com/ // @match https://thisvid.com/latest-updates/* // @match https://thisvid.com/tags/* // @match https://thisvid.com/categories/* // @match https://thisvid.com/*/?q=* // @match https://thisvid.com/members/* // @match https://thisvid.com/videos/* // @icon data:image/jpeg;base64,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 // @grant GM_addStyle // @grant GM_addElement // @run-at document-end // ==/UserScript== (function () { // biome-ignore lint/suspicious/noRedundantUseStrict: <explanation> 'use strict'; console.clear(); console.log('\n\ntapermonkey-thisvidscript\n\n'); // biome-ignore lint/complexity/noStaticOnlyClass: <explanation> class Utils { static $ = (x, e = document.body) => e.querySelector(x); static $$ = (x, e = document.body) => e.querySelectorAll(x); static findElementsBetweenIds = (startId, endId) => { const startElement = document.getElementById(startId); const endElement = document.getElementById(endId); if (!startElement || !endElement) { return []; } const elementsBetween = []; let currentElement = startElement.nextElementSibling; while (currentElement && currentElement !== endElement) { elementsBetween.push(currentElement); currentElement = currentElement.nextElementSibling; } return elementsBetween; }; static parseHTML = (str) => { const temp = document.createElement('html'); temp.innerHTML = str; return temp; }; static fetchHtml = async (url) => fetch(url) .then((r) => r.text()) .then((d) => parseHTML(d)); static getRandomRgb = () => { const n = Math.round(0xffffff * Math.random()); return `rgb(${n >> 16},${(n >> 8) & 255},${n & 255})`; }; static parseCSSUrl = (s) => s.match(/(?<=\(").*(?="\))/)[0]; static timeToSeconds = (t) => (t.match(/\d+/gm) || ['0']) .reverse() .map((s, i) => parseInt(s) * 60 ** i) .reduce((a, b) => a + b) || 0; static circularShift = (n, c = 6, s = 1) => (n + s) % c || c; static isElementInViewport = (el) => { const rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement .clientHeight) /* or $(window).height() */ && rect.right <= (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */ ); }; static toggleClass = (element, className, condition) => { if (condition) { element.classList.add(className); } else { element.classList.remove(className); } }; static parseDom = (html) => { return new DOMParser().parseFromString(html, 'text/html').body.firstChild; }; static parseIntegerOr = (n, or) => Number.isInteger(parseInt(n)) ? parseInt(n) : or; } const { $, $$, findElementsBetweenIds, fetchHtml, parseHTML, parseCSSUrl, circularShift, isElementInViewport, timeToSeconds, getRandomRgb, toggleClass, parseDom, parseIntegerOr, } = Utils; class Tick { constructor(interval) { this.interval = interval; } start(callback) { if (this.ticker) { this.stop(); } callback(); this.ticker = setInterval(callback, this.interval); } stop() { clearInterval(this.ticker); this.ticker = false; } } class ReactiveLocalStorage { constructor(data) { if (data) { Object.assign(this, data); this.observeProps(this); } } getLS(prop) { return JSON.parse(localStorage.getItem(prop)); } setLS(prop, value) { localStorage.setItem(prop, JSON.stringify(value)); } toObservable(obj, prop) { const lsvalue = this.getLS(prop); let value = lsvalue !== null ? lsvalue : obj[prop]; Object.defineProperty(obj, prop, { get() { return value; }, set(newValue) { this.setLS(prop, newValue); value = newValue; }, }); } observeProps(obj) { for (const [key, _] of Object.entries(obj)) { this.toObservable(obj, key); } } } const SCROLL_RESET_DELAY = 500; const ANIMATION_DELAY = 750; // biome-ignore lint/complexity/noStaticOnlyClass: <explanation> class DomManager { static thumbIsPrivate(t) { return t.firstElementChild.classList.contains('private'); } static filterPrivate(container = document.body) { // biome-ignore lint/complexity/noForEach: <explanation> data.forEach((v) => toggleClass(v.element, 'filtered-private', state.filterPrivate && thumbIsPrivate(v.element))); } static filterPublic(container = document.body) { // biome-ignore lint/complexity/noForEach: <explanation> data.forEach((v) => toggleClass(v.element, 'filtered-public', state.filterPublic && !thumbIsPrivate(v.element))); } static filterByDuration(container = document.body) { const { filterDurationFrom: from, filterDurationTo: to, filterDuration, } = state; // biome-ignore lint/complexity/noForEach: <explanation> data.forEach((v) => toggleClass(v.element, 'filtered-duration', filterDuration && (v.duration < from || v.duration > to))); } static runFilters(container) { if (state.filterPrivate) filterPrivate(container); if (state.filterPublic) filterPublic(container); if (state.filterDuration) filterByDuration(container); } static createThumbsContainer() { return GM_addElement('div', { class: 'thumbs-items' }); } static handleLoadedHTML = (htmlPage, mount, useStateContainer = true) => { const thumbs = $$('.tumbpu', htmlPage); const container = !useStateContainer ? createThumbsContainer() : containerGlobal; for (const thumbElement of thumbs) { const url = thumbElement.getAttribute('href'); if (!url || data.has(url)) { thumbElement.remove(); } else { data.set(url, { element: thumbElement, duration: timeToSeconds($('.thumb > .duration', thumbElement).textContent) }); const img = $('img', thumbElement); const privateEl = $('.private', thumbElement); if (privateEl) { img.src = parseCSSUrl(privateEl.style.background); privateEl.style.background = '#000'; } else { img.src = img.getAttribute('data-original'); } img.classList.add('tracking'); container.appendChild(thumbElement); } } DomManager.runFilters(container); mount.before(container); }; } class PreviewManager { constructor() { this.tick = new Tick(ANIMATION_DELAY); } iteratePreviewImages(src) { return src.replace(/(\d)\.jpg$/, (_, n) => `${circularShift(parseInt(n))}.jpg`); } animatePreview = (e) => { const { target: el, type } = e; if (el.tagName === 'IMG' && el.classList.contains('tracking')) { if (type === 'mouseout') { this.tick.stop(); if (el.getAttribute('orig')) el.src = el.getAttribute('orig'); } if (type === 'mouseover') { if (!el.getAttribute('orig')) el.setAttribute('orig', el.src); this.tick.start(() => { el.src = this.iteratePreviewImages(el.src); }); } } }; listen(e) { e.addEventListener('mouseout', this.animatePreview); e.addEventListener('mouseover', this.animatePreview); } } class PaginationPageManager { constructor() { this.pagination = $('.pagination'); this.pagination.style.opacity = 0; handleLoadedHTML(document.body, this.pagination); previewManager.listen(this.pagination.parentElement); this.offsetLast = this.getOffsetLast(); this.paginationGenerator = this.createNextPageGenerator(); this.generatorDone = false; this.resetScroller(); this.tick = new Tick(SCROLL_RESET_DELAY); this.fixScrollViewPort(); this.ui = new UI(true); this.setPagIndex = (offset) => this.ui.setPagIndex(offset, this.offsetLast); this.setPagIndex(this.getCurrentOffset()); } fixScrollViewPort() { this.tick.start(() => { if (this.generatorDone) this.tick.stop(); if (isElementInViewport(this.pagination)) this.generatorConsumer(); }); } async generatorConsumer() { const { value: { url, offset } = {}, done, } = this.paginationGenerator.next(); this.generatorDone = done; if (!done) { const nextPageHTML = await fetchHtml(url); const prevScrollPos = document.documentElement.scrollTop; handleLoadedHTML(nextPageHTML, this.pagination); this.setPagIndex(offset); window.scrollTo(0, prevScrollPos); } } getCurrentOffset() { return parseInt(window.location.pathname.split(/(\d+\/)$/)[1] || '1'); } getOffsetLast() { return parseInt( $('.pagination-next').previousElementSibling.firstElementChild .textContent, ); } createNextPageGenerator() { let { origin, pathname, search } = window.location; let offset; [pathname, offset = '1'] = pathname.split(/(\d+\/)$/); offset = parseInt(offset); pathname = pathname === '/' ? '/latest-updates/' : pathname; const offsetLast = this.getOffsetLast(); function* nextPageGenerator() { for (let c = offset + 1; c <= offsetLast; c++) { const url = `${origin}${pathname}${c}/${search}`; console.log(url); yield { url, offset: c }; } } return nextPageGenerator(); } resetScroller = () => { this.infiniteScrollTriggered = false; window.dispatchEvent(new CustomEvent('scroll')); }; infiniteScroll = () => { const inViewport = isElementInViewport(this.pagination); if (inViewport === this.infiniteScrollTriggered) return; this.infiniteScrollTriggered = inViewport; if (inViewport) this.generatorConsumer(); }; } class Router { constructor() { this.route(); } route() { const { pathname } = window.location; if ($('.pagination-next')) { this.handlePaginationPage(); } else if (/\/members\/\d+\/$/.test(pathname)) { this.handleMemberPage(); } else if (/\/tag\//.test(pathname) || /\/?q=.*/.test(pathname)) { this.handlePageWithVideosButNoPagination(); } else if (/\/videos\//.test(pathname)) { //this.handlePageWithVideosButNoPagination() } } handlePageWithVideosButNoPagination() { const vid = $('.tumbpu'); if (!vid) return; handleLoadedHTML(document.body, vid.parentElement); previewManager.listen(vid.parentElement); const ui = new UI(false); } handlePaginationPage() { this.paginationManager = new PaginationPageManager(); } handleMemberPage() { const privates = $('#list_videos_private_videos_items'); if (privates) { const mistakes = findElementsBetweenIds( 'list_videos_private_videos_items', 'list_videos_favourite_videos', ); for (const m of mistakes) privates.appendChild(m); handleLoadedHTML(privates, privates, false); const ui = new UI(false); } const favorites = $('#list_videos_favourite_videos'); if (favorites) { const mountTo = favorites.firstElementChild.nextElementSibling; handleLoadedHTML(favorites, mountTo, false); } if (privates || favorites) { previewManager.listen((privates || favorites).parentElement); } } } class UI { templateHTML = (haspag) => ` <div id="tapermonkey-app"> <div class="subbox"> <input type="checkbox" id="filterPrivate" name="filterPrivate" ${state.filterPrivate ? 'checked' : '' }/> <label for="filterPrivate">filter private</label> <input type="checkbox" id="filterPublic" name="filterPublic" ${state.filterPublic ? 'checked' : '' }/> <label for="filterPublic">filter public</label> ${haspag ? '<span id="pagIndex">0/0</span>' : ''} </div> <div class="subbox"> <input type="checkbox" id="filterl" name="filterl" ${state.filterDuration ? 'checked' : '' } /> <label for="filterl">filter duration seconds</label> <input type="number" placeholder="min sec" step="10" min="0" max="100000" id="minL" value=${state.filterDurationFrom} /> <input type="number" placeholder="max sec" step="10" min="0" max="100000" id="maxL" value=${state.filterDurationTo} /> </div> </div>`; constructor(haspag = true) { document.body.appendChild(parseDom(this.templateHTML(haspag))); this.tapermonkeyAppTemplate = document.querySelector('#tapermonkey-app'); this.control(); } setPagIndex(index, total) { $('#pagIndex').innerText = `${index}/${total}`; } control() { this.tapermonkeyAppTemplate.addEventListener('click', (e) => { const { id, checked, value } = e.target; if (id === 'filterPublic') { state.filterPublic = checked; filterPublic(); } if (id === 'filterPrivate') { state.filterPrivate = checked; filterPrivate(); } if (id === 'filterl') { state.filterDuration = checked; filterByDuration(); } if (id === 'minL') { state.filterDurationFrom = parseIntegerOr(value, state.filterDurationFrom); filterByDuration(); } if (id === 'maxL') { state.filterDurationTo = parseIntegerOr(value, state.filterDurationTo); filterByDuration(); } }); } } const state = new ReactiveLocalStorage({ filterDurationFrom: 0, filterDurationTo: 100000, filterDuration: false, filterPrivate: false, filterPublic: false, infiniteScrollTriggered: false, }); const data = new Map(); const { filterPrivate, filterPublic, filterByDuration, handleLoadedHTML, createThumbsContainer, thumbIsPrivate } = DomManager; const containerGlobal = createThumbsContainer(); const previewManager = new PreviewManager(); const router = new Router(); const tampermonkeyCSS = ` #tapermonkey-app { background: #151515; padding: 10px; position: fixed; z-index: 9999; bottom: 10px; right: 10px; border-radius: 15px; width: max-content; box-shadow: 20px 20px 60px #000000, -20px -20px 60px #000000; } #tapermonkey-app .subbox { background: #2c2c2c; border-radius: 5px; padding: 4px; margin: 6px; } #tapermonkey-app .subbox input[type=number] { padding-left: 10px; width: 5rem; background: #26282b; } #tapermonkey-app .subbox input[type=checkbox] { margin-left: 5px; } #tapermonkey-app .subbox label { user-select: none; } #pagIndex { color: #969696;} #tapermonkey-app .subbox * { padding-left: 8px; float: none; width: auto; font-family: monospace; font-size: 0.8rem; } .tracking { content-visibility: auto; } .filtered-private, .filtered-duration, .filtered-public { display: none !important; } `; GM_addStyle(tampermonkeyCSS); })();