WaniKani Update Review Count and Forecast

Auto update Update Review Count and Forecast by hour

目前為 2023-11-06 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name WaniKani Update Review Count and Forecast
  3. // @namespace http://wanikani.com
  4. // @version 0.1.1
  5. // @description Auto update Update Review Count and Forecast by hour
  6. // @author polv
  7. // @match *://www.wanikani.com/*
  8. // @match *://preview.wanikani.com/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=wanikani.com
  10. // @license MIT
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. wkof.include('ItemData');
  18.  
  19. Object.assign(window, { updateWkStats });
  20.  
  21. addEventListener('turbo:load', (ev) => {
  22. const u = new URL(ev.detail?.url);
  23. if (['/', '/dashboard', '/dashboard/'].includes(u.pathname)) {
  24. setTimeout(updateWkStats, getMillisecondsToNewHour());
  25. }
  26. });
  27.  
  28. let forecastTimeoutId = 0;
  29. let reviewsTimeoutId = 0;
  30.  
  31. async function updateWkStats() {
  32. const forecastFrame = document.querySelector(
  33. 'turbo-frame[data-controller="review-forecast"]',
  34. );
  35. if (forecastFrame) {
  36. const updateFrame = (timeout = 1000 * 60 * 60) => {
  37. forecastFrame.reload();
  38.  
  39. clearTimeout(forecastTimeoutId);
  40. forecastTimeoutId = setTimeout(() => updateFrame(), timeout);
  41. };
  42. updateFrame();
  43. }
  44.  
  45. const reviewsBtn = document.querySelector(
  46. '.lessons-and-reviews__reviews-button',
  47. );
  48.  
  49. if (reviewsBtn) {
  50. return wkof
  51. .ready('ItemData')
  52. .then(() =>
  53. wkof.ItemData.get_items({
  54. wk_items: { options: { assignments: true } },
  55. }),
  56. )
  57. .then((rs) => {
  58. const updateFrame = (timeout = 1000 * 60 * 60) => {
  59. const d = new Date().toISOString();
  60. const count = rs.filter(
  61. (r) => r.assignments?.available_at <= d,
  62. ).length;
  63.  
  64. let countClass = 0;
  65. if (count >= 1000) {
  66. countClass = 1000;
  67. } else if (count >= 500) {
  68. countClass = 500;
  69. } else if (count >= 250) {
  70. countClass = 250;
  71. } else if (count >= 100) {
  72. countClass = 100;
  73. } else if (count >= 50) {
  74. countClass = 50;
  75. } else if (count) {
  76. countClass = 1;
  77. }
  78.  
  79. const clickable = document.createElement('a');
  80. clickable.href = '/subjects/review';
  81.  
  82. clickable.className =
  83. reviewsBtn.className.replace(
  84. / lessons-and-reviews__reviews-button--\d+/,
  85. '',
  86. ) +
  87. ' lessons-and-reviews__reviews-button--' +
  88. countClass;
  89. clickable.title = reviewsBtn.title;
  90. clickable.append(...reviewsBtn.childNodes);
  91.  
  92. const elCount = clickable.querySelector(
  93. '.lessons-and-reviews__button-count',
  94. );
  95. if (elCount) {
  96. elCount.innerText = count;
  97. }
  98.  
  99. reviewsBtn.replaceWith(clickable);
  100.  
  101. clearTimeout(reviewsTimeoutId);
  102. reviewsTimeoutId = setTimeout(() => updateFrame(), timeout);
  103. };
  104. updateFrame(getMillisecondsToNewHour());
  105. });
  106. }
  107. }
  108.  
  109. function getMillisecondsToNewHour() {
  110. const d = new Date();
  111. return (
  112. 60 * 60 * 1000 -
  113. ((d.getMinutes() * 60 + d.getSeconds()) * 1000 + d.getMilliseconds())
  114. );
  115. }
  116. })();

QingJ © 2025

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