您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically sort teaser images on /videos, /images, /subscriptions, /users, and sidebars using customizable sort function.
当前为
- // ==UserScript==
- // @name Iwara Custom Sort
- // @version 0.153
- // @grant GM.setValue
- // @grant GM.getValue
- // @grant GM.deleteValue
- // @run-at document-start
- // @noframes
- // @match https://ecchi.iwara.tv/*
- // @match https://www.iwara.tv/*
- // @match http://ecchi.iwara.tv/*
- // @match http://www.iwara.tv/*
- // @description Automatically sort teaser images on /videos, /images, /subscriptions, /users, and sidebars using customizable sort function.
- // @license AGPL-3.0-or-later
- // @namespace https://gf.qytechs.cn/users/245195
- // ==/UserScript==
- /* jshint esversion: 6 */
- /* global GM */
- 'use strict';
- const additionalPageCount = 0;
- const logDebug = (...args) => {
- const debugging = true;
- if (debugging) {
- console.log(...args);
- }
- };
- const teaserDivSelector = '.node-teaser';
- const getTeaserGrids = (node) => {
- const teaserGridSelector = '.views-responsive-grid';
- return Array.from(node.querySelectorAll(teaserGridSelector))
- .filter(grid => grid.querySelector(teaserDivSelector));
- };
- const timeout = delay => new Promise(resolve => setTimeout(resolve, delay));
- const sortTeasers = (grid, valueExpression) => {
- const viewsIconSelector = '.glyphicon-eye-open';
- const likesIconSelector = '.glyphicon-heart';
- const imageFieldSelector = '.field-type-image';
- const galleryIconSelector = '.glyphicon-th-large';
- const privateDivSelector = '.private-video';
- const teaserDivs = Array.from(grid.querySelectorAll(teaserDivSelector));
- const getNearbyNumber = (element) => {
- const parsePrefixed = str => Number.parseFloat(str) * (str.includes('k') ? 1000 : 1);
- return element ? parsePrefixed(element.parentElement.textContent) : 0;
- };
- const teaserItems = teaserDivs.map(div => ({
- div,
- viewCount: getNearbyNumber(div.querySelector(viewsIconSelector)),
- likeCount: getNearbyNumber(div.querySelector(likesIconSelector)),
- imageFactor: div.querySelector(imageFieldSelector) ? 1 : 0,
- galleryFactor: div.querySelector(galleryIconSelector) ? 1 : 0,
- privateFactor: div.querySelector(privateDivSelector) ? 1 : 0,
- }));
- const evalSortValue = (item, expression) =>
- // eslint-disable-next-line no-new-func
- new Function(
- 'views',
- 'likes',
- 'ratio',
- 'image',
- 'gallery',
- 'private',
- `return (${expression})`,
- )(
- item.viewCount,
- item.likeCount,
- Math.min(item.likeCount / Math.max(1, item.viewCount), 1),
- item.imageFactor,
- item.galleryFactor,
- item.privateFactor,
- );
- teaserItems.forEach((item) => {
- // eslint-disable-next-line no-param-reassign
- item.sortValue = evalSortValue(item, valueExpression);
- });
- teaserItems.sort((itemA, itemB) => itemB.sortValue - itemA.sortValue);
- teaserDivs.map((div) => {
- const anchor = document.createElement('div');
- div.before(anchor);
- return anchor;
- }).forEach((div, index) => div.replaceWith(teaserItems[index].div));
- };
- const sortAllTeasers = (valueExpression) => {
- GM.setValue('sortValue', valueExpression);
- let sortedCount = 0;
- try {
- getTeaserGrids(document).forEach((grid) => {
- sortTeasers(grid, valueExpression);
- sortedCount += 1;
- });
- } catch (message) {
- alert(message);
- }
- logDebug(`${sortedCount} grids sorted at ${window.location}`);
- };
- const getNumberParam = (URL, name) => {
- const params = URL.searchParams;
- return params.has(name) ? Number.parseInt(params.get(name)) : 0;
- };
- const getPageParam = URL => getNumberParam(URL, 'page');
- const addAdditionalPages = (URL) => {
- const params = URL.searchParams;
- let page = getPageParam(URL);
- for (let pageLeft = additionalPageCount; pageLeft > 0; pageLeft -= 1) {
- page += 1;
- params.set('page', page);
- const nextPage = document.createElement('embed');
- nextPage.src = URL;
- nextPage.style.display = 'none';
- logDebug('page', nextPage.src, pageLeft);
- document.documentElement.append(nextPage);
- }
- };
- const createTextInput = (text, maxLength, size) => {
- const input = document.createElement('input');
- input.value = text;
- input.maxLength = maxLength;
- input.size = size;
- return input;
- };
- const createButton = (text, clickHandler) => {
- const button = document.createElement('button');
- button.innerHTML = text;
- button.addEventListener('click', clickHandler);
- return button;
- };
- const createUI = async () => {
- const defaultValue = '(ratio / (private * 2.5 + 1) + Math.sqrt(likes) / 3000) / (image + 3)';
- const sortValueInput = createTextInput(await GM.getValue('sortValue', defaultValue), 120, 60);
- const sortButton = createButton('Sort', () => sortAllTeasers(sortValueInput.value));
- sortValueInput.addEventListener('keyup', (event) => {
- if (event.key === 'Enter') {
- sortButton.click();
- }
- });
- const resetDefaultButton = createButton('Default', () => {
- sortValueInput.value = defaultValue;
- });
- return {
- sortValueInput,
- sortButton,
- resetDefaultButton,
- };
- };
- const addUI = (UI) => {
- const UIDiv = document.createElement('div');
- UIDiv.style.display = 'inline';
- UIDiv.style.margin = '5px';
- UIDiv.append(UI.resetDefaultButton, UI.sortValueInput, UI.sortButton);
- document.querySelector('#user-links').prepend(UIDiv);
- };
- const addTeasersToParent = (teaserGrids) => {
- const parentGrids = getTeaserGrids(window.parent.document);
- for (let i = 0, j = 0; i < parentGrids.length; i += 1) {
- if (teaserGrids[j].className === parentGrids[i].className) {
- // eslint-disable-next-line no-param-reassign
- teaserGrids[j].className = '';
- parentGrids[i].prepend(teaserGrids[j]);
- j += 1;
- }
- }
- };
- const adjustPageAnchors = (container) => {
- const currentPage = getPageParam(new URL(window.location));
- const changePageParam = (anchor, value) => {
- const anchorURL = new URL(anchor.href, window.location);
- anchorURL.searchParams.set('page', value);
- // eslint-disable-next-line no-param-reassign
- anchor.href = anchorURL.pathname + anchorURL.search;
- };
- if (currentPage > 0) {
- const previousPageAnchor = container.querySelector('.pager-previous a');
- changePageParam(previousPageAnchor, Math.max(0, currentPage - 1 - additionalPageCount));
- }
- const nextPage = currentPage + 1 + additionalPageCount;
- {
- const lastPageAnchor = container.querySelector('.pager-last a');
- if (lastPageAnchor) {
- const nextPageAnchor = container.querySelector('.pager-next a');
- if (getPageParam(new URL(lastPageAnchor.href, window.location)) >= nextPage) {
- changePageParam(nextPageAnchor, nextPage);
- } else {
- nextPageAnchor.remove();
- lastPageAnchor.remove();
- }
- }
- }
- const loadedPageAnchors = Array.from(container.querySelectorAll('.pager-item a'))
- .filter((anchor) => {
- const page = getPageParam(new URL(anchor.href, window.location));
- return page >= currentPage && page < nextPage;
- });
- if (loadedPageAnchors.length > 0) {
- const parentItem = document.createElement('li');
- const groupList = document.createElement('ul');
- groupList.style.display = 'inline';
- groupList.style.backgroundColor = 'hsla(0, 0%, 75%, 50%)';
- loadedPageAnchors[0].parentElement.before(parentItem);
- const currentPageItem = container.querySelector('.pager-current');
- currentPageItem.style.marginLeft = '0';
- groupList.append(currentPageItem);
- loadedPageAnchors.forEach((anchor) => {
- anchor.parentNode.classList.toggle('pager-item', false);
- anchor.parentNode.classList.toggle('pager-current', true);
- groupList.append(anchor.parentElement);
- });
- parentItem.append(groupList);
- }
- };
- const adjustAnchors = () => {
- const pageAnchorList = document.querySelectorAll('.pager');
- pageAnchorList.forEach((list) => {
- adjustPageAnchors(list);
- });
- };
- const initParent = async (teasersAddedMeesage) => {
- const UI = await createUI();
- addUI(UI);
- window.addEventListener('message', (event) => {
- if (
- new URL(event.origin).hostname === window.location.hostname &&
- event.data === teasersAddedMeesage
- ) {
- sortAllTeasers(UI.sortValueInput.value);
- }
- });
- UI.sortButton.click();
- const extraPageRegEx = /\/(videos|images|subscriptions)$/;
- if (extraPageRegEx.test(window.location.pathname)) {
- addAdditionalPages(new URL(window.location));
- adjustAnchors();
- }
- };
- const init = async () => {
- const teaserGrids = getTeaserGrids(document);
- if (teaserGrids.length === 0) {
- return;
- }
- const teasersAddedMeesage = 'iwara custom sort: teasersAdded';
- if (window === window.parent) {
- logDebug('I am a Parent.');
- initParent(teasersAddedMeesage);
- } else {
- logDebug('I am a child.');
- await timeout(500);
- addTeasersToParent(teaserGrids);
- window.parent.postMessage(teasersAddedMeesage, window.location.origin);
- }
- };
- logDebug(`Parsed:${window.location}, ${document.readyState} Parent:`, window.parent);
- document.addEventListener('DOMContentLoaded', init);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址