WK Move a Lesson To Review

Selectively move a Lesson to Review

  1. // ==UserScript==
  2. // @name WK Move a Lesson To Review
  3. // @namespace wanikani
  4. // @version 0.2.1
  5. // @description Selectively move a Lesson to Review
  6. // @author polv
  7. // @match *://www.wanikani.com/*
  8. // @match *://preview.wanikani.com/*
  9. // @license MIT
  10. // @connect api.wanikani.com
  11. // @require https://gf.qytechs.cn/scripts/430565-wanikani-item-info-injector/code/WaniKani%20Item%20Info%20Injector.user.js?version=1276163
  12. // @icon https://www.google.com/s2/favicons?sz=64&domain=wanikani.com
  13. // @grant GM_xmlhttpRequest
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. 'use strict';
  18.  
  19. const localStorageKey = 'MOVE_TO_REVIEW_API_KEY';
  20. let apikey = localStorage.getItem(localStorageKey);
  21.  
  22. let lessons = null;
  23.  
  24. const injector = wkItemInfo.on('itemPage').appendAtTop('', (o) => {
  25. if (!lessons) return;
  26.  
  27. const assignment = lessons.find((r) => r.data.subject_id === o.id);
  28. if (!assignment) return;
  29.  
  30. const button = document.createElement('button');
  31. button.type = 'button';
  32. button.onclick = () => {
  33. send_api_request(
  34. 'https://api.wanikani.com/v2/assignments/' + assignment.id + '/start',
  35. 'PUT',
  36. ).then((r) => {
  37. if (r) {
  38. location.reload();
  39. }
  40. });
  41. };
  42. button.className = 'wk-button wk-button--default';
  43. button.innerText = 'Move to Review';
  44. return button;
  45. });
  46.  
  47. send_api_request(
  48. 'https://api.wanikani.com/v2/assignments?immediately_available_for_lessons=true',
  49. 'GET',
  50. ).then((result) => {
  51. if (result) {
  52. lessons = result.data;
  53. console.log(lessons);
  54. injector.renew();
  55. }
  56. });
  57.  
  58. async function send_api_request(url, method) {
  59. return new Promise((resolve, reject) => {
  60. // not sure if `fetch` with @connect can already bypass CORS, but just to be sure
  61. GM_xmlhttpRequest({
  62. method,
  63. url,
  64. headers: {
  65. Authorization: 'Bearer ' + apikey,
  66. 'Wanikani-Revision': '20170710',
  67. },
  68. onload: function (response) {
  69. if (response.status != 200) {
  70. if (
  71. confirm(
  72. 'WK API answered : ' +
  73. response.status +
  74. ' ' +
  75. response.statusText +
  76. '\nDo you want to enter a different API key?',
  77. )
  78. ) {
  79. if (add_key()) {
  80. return resolve(send_api_request(url, method));
  81. }
  82. return resolve(false);
  83. }
  84. }
  85.  
  86. try {
  87. const result = JSON.parse(response.responseText);
  88. console.log(result);
  89. resolve(result);
  90. } catch (e) {
  91. reject(e);
  92. }
  93.  
  94. return reject();
  95. },
  96. onerror: reject,
  97. });
  98. });
  99. }
  100.  
  101. function add_key() {
  102. apikey = prompt(
  103. "Please enter an API key with 'assignment start' permission",
  104. );
  105. if (apikey != null) {
  106. localStorage.setItem(localStorageKey, apikey);
  107. return true;
  108. }
  109. }
  110. })();

QingJ © 2025

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