Iwara Custom Sort

Automatically sort video results in a page on /videos, /images, /subscriptions, and sidebars using customizable sort function.

当前为 2019-02-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Iwara Custom Sort
  3. // @version 0.114
  4. // @grant GM.setValue
  5. // @grant GM.getValue
  6. // @grant GM.deleteValue
  7. // @match https://ecchi.iwara.tv/*
  8. // @match https://www.iwara.tv/*
  9. // @match http://ecchi.iwara.tv/*
  10. // @match http://www.iwara.tv/*
  11. // @description Automatically sort video results in a page on /videos, /images, /subscriptions, and sidebars using customizable sort function.
  12. // @namespace https://gf.qytechs.cn/users/245195
  13. // ==/UserScript==
  14.  
  15. /* jshint esversion: 6 */
  16.  
  17. const logDebug = (...args) => {
  18. const debugging = true;
  19. if (debugging) {
  20. console.log(...args);
  21. }
  22. }
  23.  
  24. logDebug('Parsed.');
  25.  
  26. const parsePrefixed = (str) => {
  27. return Number.parseFloat(str) * (str.includes('k') ? 1000 : 1);
  28. }
  29.  
  30. const sortVideos = (videosContainer, sortValueExpression) => {
  31. const videoDivs = Array.from(videosContainer.querySelectorAll('.clearfix'));
  32. const views = videoDivs.map(div => div.querySelector('.glyphicon-eye-open'))
  33. .map(div => div ? parsePrefixed(div.parentElement.textContent) : 0);
  34. const likes = videoDivs.map(div => div.querySelector('.glyphicon-heart'))
  35. .map(div => div ? parsePrefixed(div.parentElement.textContent) : 0);
  36. const videoEntries = Object.entries(videoDivs);
  37. GM.setValue('sortValue', sortValueExpression);
  38. const evalSortValue = (views, likes) => {
  39. const ratio = Math.min(likes / Math.max(1, views), 1);
  40. return eval(sortValueExpression);
  41. }
  42. videoEntries.sort((entryA, entryB) => {
  43. return evalSortValue(views[entryB[0]], likes[entryB[0]]) - evalSortValue(views[entryA[0]], likes[entryA[0]]);
  44. });
  45. videoDivs.map(div => div.parentElement)
  46. .forEach((div, index) => {
  47. div.append(videoEntries[index][1]);
  48. });
  49. };
  50.  
  51. const sortAllVideos = (sortValueExpression) => {
  52. let gridCount = 0;
  53. try {
  54. document.querySelectorAll('.views-responsive-grid').forEach((grid) => {
  55. sortVideos(grid, sortValueExpression);
  56. gridCount++;
  57. });
  58. } catch (message) {
  59. alert(message);
  60. }
  61. logDebug(`${gridCount}grids sorted.`);
  62. };
  63.  
  64. const requestMorePages = (URL, pageCount) => {
  65. const params = URL.searchParams;
  66. const page = params.has('page') ? params.get('page') : 0;
  67. logDebug(page, pageCount);
  68. }
  69.  
  70. (async () => {
  71. const currentURL = new URL(location);
  72. if (/\/(videos|images|subscriptions)/.test(currentURL.pathname)) {
  73. const additionalPageCount = 2;
  74. requestMorePages(currentURL, additionalPageCount);
  75. }
  76. const sortValueInput = document.createElement('input');
  77. sortValueInput.type = 'text';
  78. sortValueInput.value = await GM.getValue('sortValue', '100 * ratio + Math.sqrt(likes) / 25');
  79. const uiContainer = (() => {
  80. const temp = document.querySelector('.list-inline');
  81. if (temp) {
  82. return temp;
  83. } else {
  84. return document.querySelector('#user-links');
  85. }
  86. })();
  87. uiContainer.insertAdjacentElement('afterbegin', sortValueInput);
  88. const sortButton = document.createElement('button');
  89. sortButton.innerHTML = 'Sort';
  90. uiContainer.insertAdjacentElement('afterbegin', sortButton);
  91. sortButton.addEventListener('click', () => sortAllVideos(sortValueInput.value));
  92. sortAllVideos(sortValueInput.value);
  93. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址