Wanikani Forums Global Framework

A framework for global script services on Wanikani forums

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/27967/186167/Wanikani%20Forums%20Global%20Framework.js

  1. // ==UserScript==
  2. // @name Wanikani Forums Global Framework
  3. // @namespace rfindley
  4. // @description A framework for global script services on Wanikani forums
  5. // @version 1.0.3
  6. // @copyright 2017+, Robin Findley
  7. // @license MIT; http://opensource.org/licenses/MIT
  8. // ==/UserScript==
  9.  
  10. if (window.wkf_global === undefined) window.wkf_global = {};
  11.  
  12. (function(gobj) {
  13. if (gobj.already_loaded === true) return;
  14. gobj.already_loaded = true;
  15.  
  16. var settings_url = '/scripts/global';
  17.  
  18. var html =
  19. '<div class="settings">'+
  20. ' <h1>Global script settings</h1>'+
  21. ' <p>'+
  22. ' <label>Public API Key</label>'+
  23. ' <input id="apikey" value="" placeholder="Enter your API Key here" type="text" class="span6">'+
  24. ' <span class="note">(You can find it [<a href="https://www.wanikani.com/settings/account/" target="_">here</a>])</span>'+
  25. ' </p>'+
  26. ' <p>'+
  27. ' <label></label>'+
  28. ' <input id="save" type="submit" name="commit" value="Save" class="btn">'+
  29. ' <span id="save_status" class="note"></span>'+
  30. ' </p>'+
  31. ' <h1>Individual Script Settings</h1>'+
  32. ' <div id="script_list">'+
  33. ' </div>'+
  34. '</div>'+
  35. '';
  36.  
  37. var css =
  38. '.settings > h1 {padding-bottom: 0.2em; margin-bottom:0.5em; border-bottom:1px solid black;}'+
  39. '.settings > h1:not(:first-child) {margin-top:40px;}'+
  40. '.settings label {display:inline-block; text-align:right; padding-right:8px; width:120px;}'+
  41. '.settings .note {color:#aaa; margin-left:8px; font-size:0.9em;}'+
  42. '#save_status {color:#c22;}'+
  43. '.settings a {color:#c22;}'+
  44. '.settings .btn {'+
  45. ' border-color: rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25);'+
  46. ' color: #555;'+
  47. ' cursor: pointer;'+
  48. ' text-shadow: 0 1px 1px rgba(255,255,255,0.75);'+
  49. ' background-color: #f5f5f5;'+
  50. ' background-image: linear-gradient(to bottom, #fff, #e6e6e6);'+
  51. ' border: 1px solid #bbbbbb;'+
  52. ' border-radius: 4px;'+
  53. ' box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 1px 2px rgba(0,0,0,0.05);'+
  54. ' line-height: 1em;'+
  55. '}'+
  56. '';
  57.  
  58. // Load jquery (if not already).
  59. function load_jquery() {
  60. return new Promise(function(resolve, reject){
  61. if (typeof jQuery !== 'undefined') return resolve();
  62.  
  63. function jquery_loaded(){
  64. resolve();
  65. }
  66.  
  67. var headTag = document.getElementsByTagName("head")[0];
  68. var jqTag = document.createElement('script');
  69. jqTag.type = 'text/javascript';
  70. jqTag.src = 'https://code.jquery.com/jquery-3.1.1.min.js';
  71. jqTag.onload = jquery_loaded;
  72. headTag.appendChild(jqTag);
  73. });
  74. }
  75.  
  76. // Load
  77. if (window.location.pathname.match('^/scripts/') !== null) {
  78. document.getElementById('main-outlet').innerHTML = '';
  79. var promise = load_jquery();
  80. if (window.location.pathname === settings_url) {
  81. promise.then(function(){
  82. $('head').append('<style type="text/css">'+css+'</style>');
  83. $('#main-outlet').html(html);
  84. var apikey = localStorage.getItem('apikey');
  85. if (apikey !== null) {
  86. $('#apikey').val(apikey);
  87. }
  88. $('#save').on('click', function(){
  89. var apikey = $('#apikey').val();
  90. if (apikey.match(/^[0-9a-f]{32}$/) !== null) {
  91. localStorage.setItem('apikey', apikey);
  92. $('#save_status').text('Saved!').fadeIn(0).delay(750).fadeOut(750);
  93. } else {
  94. alert('API Key is not valid!');
  95. }
  96. });
  97. $('body').on('add_script', function(e){
  98. var data = e.detail;
  99. $('#script_list').append('<p class="partner_script"><a href="'+data.url+'">'+data.name+'</a></p>');
  100. $('.settings .partner_script').sort(function(a,b){
  101. return $(a).text().localeCompare($(b).text());
  102. }).appendTo($('#script_list'));
  103. });
  104. document.getElementsByTagName('body')[0].dispatchEvent(new Event('global_settings_done'));
  105. });
  106. }
  107. }
  108.  
  109. gobj.add_script = function(name, url) {
  110. if (window.location.pathname === '/scripts/global') {
  111. document.getElementsByTagName('body')[0].addEventListener('global_settings_done', function(){
  112. document.getElementsByTagName('body')[0].dispatchEvent(new CustomEvent('add_script', {detail:{name:name, url:url}}));
  113. });
  114. }
  115. };
  116.  
  117. gobj.get_apikey = function(force_renew) {
  118. if (force_renew === true) localStorage.removeItem('apikey');
  119. var apikey = localStorage.getItem('apikey') || '';
  120. if (apikey.match(/^[0-9a-f]{32}$/) !== null) return apikey;
  121. if (window.location.pathname !== '/scripts/global') window.location.pathname = '/scripts/global';
  122. return null;
  123. };
  124.  
  125. gobj.query_api = function(partial_url) {
  126. return new Promise(function(resolve, reject){
  127. var apikey = localStorage.getItem('apikey');
  128. if (apikey.match(/^[0-9a-f]{32}$/) === null) return reject();
  129. $.getJSON('https://www.wanikani.com/api/user/'+apikey+partial_url, function(json){
  130. if (json.error !== undefined) return reject(json.error);
  131. var current_user = $('#current-user img').attr('title');
  132. var api_user = json.user_information.username;
  133. if (current_user !== api_user) gobj.get_apikey(true /* force_renew */);
  134. resolve(json);
  135. });
  136. });
  137. };
  138.  
  139. gobj.goto_settings = function(reason) {
  140. if (window.location.pathname !== '/scripts/global') window.location.pathname = '/scripts/global';
  141. };
  142.  
  143. })(window.wkf_global);

QingJ © 2025

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