WaniKani Levels By Stage

See what level you are at for each stage (Apprentice/Guru/Master/Englightened/Burned).

  1. // ==UserScript==
  2. // @name WaniKani Levels By Stage
  3. // @version 0.0.2
  4. // @description See what level you are at for each stage (Apprentice/Guru/Master/Englightened/Burned).
  5. // @author hitechbunny
  6. // @include https://www.wanikani.com/
  7. // @include https://www.wanikani.com/dashboard
  8. // @run-at document-end
  9. // @grant none
  10. // @namespace https://greasyfork.org/users/149329
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Hook into App Store
  17. try { $('.app-store-menu-item').remove(); $('<li class="app-store-menu-item"><a href="https://community.wanikani.com/t/there-are-so-many-user-scripts-now-that-discovering-them-is-hard/20709">App Store</a></li>').insertBefore($('.navbar .dropdown-menu .nav-header:contains("Account")')); window.appStoreRegistry = window.appStoreRegistry || {}; window.appStoreRegistry[GM_info.script.uuid] = GM_info; localStorage.appStoreRegistry = JSON.stringify(appStoreRegistry); } catch (e) {}
  18.  
  19. var api_key;
  20.  
  21. var cached_json = localStorage.getItem('level-progress-cache');
  22. if (cached_json) {
  23. render(JSON.parse(cached_json));
  24. }
  25.  
  26. get_api_key().then(function() {
  27. ajax_retry('https://wanikanitools-golang.curiousattemptbunny.com/level/progress?api_key='+api_key).then(function(json) {
  28. localStorage.setItem('level-progress-cache', JSON.stringify(json));
  29. render(json);
  30. });
  31. });
  32.  
  33. function render(json) {
  34. console.log(json);
  35.  
  36. if (!json.stage_levels) {
  37. return;
  38. }
  39.  
  40. var html = '<section class="srs-progress">'+
  41. ' <ul>';
  42.  
  43. ['Apprentice', 'Guru', 'Master', 'Enlightened', 'Burned'].forEach(function(stage) {
  44. html += '<li style="box-shadow: initial; padding-top: 10px; padding-bottom: 6px;">'+
  45. '<span style="font-size: 16px; display: initial;">Level '+(json.stage_levels[stage].level == 60 ? 60 : json.stage_levels[stage].level + 1) +'</span><br>'+
  46. '<span style="display: initial; font-weight: initial; font-size: 16px;">'+(json.stage_levels[stage].percentage_next_level*100).toFixed(0)+'%</span>'+
  47. '</li>';
  48. });
  49.  
  50. html += ' </ul>'+
  51. '</section>';
  52.  
  53. var previous = $('.srs-progress')[1];
  54. if (previous) {
  55. $(previous).remove();
  56. }
  57. $(html).insertAfter('.srs-progress');
  58. }
  59.  
  60. //-------------------------------------------------------------------
  61. // Fetch a document from the server.
  62. //-------------------------------------------------------------------
  63. function ajax_retry(url, options) {
  64. //console.log(url, retries, timeout);
  65. options = options || {};
  66. var retries = options.retries || 3;
  67. var timeout = options.timeout || 3000;
  68. var headers = options.headers || {};
  69. var method = options.method || 'GET';
  70. var data = options.data || undefined;
  71. var cache = options.cache || false;
  72.  
  73. function action(resolve, reject) {
  74. $.ajax({
  75. url: url,
  76. method: method,
  77. timeout: timeout,
  78. headers: headers,
  79. data: data,
  80. cache: cache
  81. })
  82. .done(function(data, status){
  83. //console.log(status, data);
  84. if (status === 'success') {
  85. resolve(data);
  86. } else {
  87. //console.log("done (reject)", status, data);
  88. reject();
  89. }
  90. })
  91. .fail(function(xhr, status, error){
  92. //console.log(status, error);
  93. if ((status === 'error' || status === 'timeout') && --retries > 0) {
  94. //console.log("fail", status, error);
  95. action(resolve, reject);
  96. } else {
  97. reject();
  98. }
  99. });
  100. }
  101. return new Promise(action);
  102. }
  103.  
  104. function get_api_key() {
  105. return new Promise(function(resolve, reject) {
  106. api_key = localStorage.getItem('apiKey_v2');
  107. if (typeof api_key === 'string' && api_key.length == 36) return resolve();
  108.  
  109. // status_div.html('Fetching API key...');
  110. ajax_retry('/settings/account').then(function(page) {
  111.  
  112. // --[ SUCCESS ]----------------------
  113. // Make sure what we got is a web page.
  114. if (typeof page !== 'string') {return reject();}
  115.  
  116. // Extract the user name.
  117. page = $(page);
  118.  
  119. // Extract the API key.
  120. api_key = page.find('#user_api_key_v2').attr('value');
  121. if (typeof api_key !== 'string' || api_key.length !== 36) {
  122. return reject(new Error('generate_apikey'));
  123. }
  124.  
  125. localStorage.setItem('apiKey_v2', api_key);
  126. resolve();
  127.  
  128. },function(result) {
  129. // --[ FAIL ]-------------------------
  130. reject(new Error('Failed to fetch API key!'));
  131.  
  132. });
  133. });
  134. }
  135. })();