GreasyFork: User Control Panel Button

To add User Control Panel Button into navigation bar

目前为 2023-09-21 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name GreasyFork: User Control Panel Button
  3. // @namespace UserScripts
  4. // @match https://greasyfork.org/*
  5. // @grant none
  6. // @version 0.1.4
  7. // @license MIT
  8. // @author CY Fung
  9. // @description To add User Control Panel Button into navigation bar
  10. // ==/UserScript==
  11.  
  12.  
  13. (async () => {
  14.  
  15.  
  16. function bufferToHex(buffer) {
  17. const byteArray = new Uint8Array(buffer);
  18. const len = byteArray.length;
  19. const hexCodes = new Array(len * 2);
  20. const chars = '0123456789abcdef';
  21. for (let i = 0, j = 0; i < len; i++) {
  22. const byte = byteArray[i];
  23. hexCodes[j++] = chars[byte >> 4];
  24. hexCodes[j++] = chars[byte & 0x0F];
  25. }
  26. return hexCodes.join('');
  27. }
  28.  
  29. async function digestMessage(message) {
  30. const encoder = new TextEncoder("utf-8");
  31. const msgUint8 = encoder.encode(message);
  32. const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8);
  33. return bufferToHex(hashBuffer);
  34. }
  35.  
  36. if(!document.querySelector('.sign-out-link') || document.querySelector('.sign-in-link')) return;
  37.  
  38. let plink = document.querySelector('.user-profile-link');
  39. if (!plink) return;
  40.  
  41. let href = plink.querySelector('a[href*="/users/"]').href;
  42.  
  43. let mi = href.indexOf('/users/');
  44. if (mi < 0) return;
  45.  
  46. if(href.includes('/users/sign')) return;
  47.  
  48.  
  49.  
  50.  
  51. let dm = await digestMessage(href);
  52.  
  53. const stKey = `gf_control_panel_${dm}`
  54.  
  55. for (let trialN = 8; trialN--;) {
  56. let s = sessionStorage.getItem(stKey);
  57. let d = typeof s ==='string' ? parseInt(s) : 0;
  58. if(d > 9 && Date.now()-d < 8000) await new Promise(r => setTimeout(r, 320));
  59. else break;
  60. }
  61.  
  62. const cpHTML = await new Promise(resolve => {
  63.  
  64.  
  65. let t = sessionStorage.getItem(stKey)
  66.  
  67. if (`${t}`.length > 32) resolve(t);
  68.  
  69.  
  70. sessionStorage.setItem(stKey, `${Date.now()}`);
  71.  
  72.  
  73. fetch(href, {
  74. method: "GET",
  75. mode: "cors",
  76. cache: "force-cache",
  77. credentials: "same-origin",
  78. redirect: "follow",
  79. referrerPolicy: "no-referrer",
  80.  
  81.  
  82. }).then(res => res.text()).then(async res => {
  83.  
  84.  
  85. let template = document.createElement('template');
  86. template.innerHTML = res;
  87. let w = template.content;
  88.  
  89. let cp = w.querySelector('#control-panel');
  90.  
  91. if (!cp) return;
  92.  
  93. const html = cp.innerHTML.trim();
  94.  
  95. sessionStorage.setItem(stKey, html);
  96.  
  97. resolve(html);
  98.  
  99.  
  100. });
  101.  
  102.  
  103.  
  104. });
  105.  
  106. if (!cpHTML || typeof cpHTML !== 'string') return;
  107.  
  108. let cpm = document.createElement('template');
  109.  
  110. cpm.innerHTML = cpHTML;
  111.  
  112. let h = (cpm.content.querySelector('h3') || cpm.content.querySelector('header'));
  113. if (!h) return;
  114.  
  115. let nav = document.createElement('nav');
  116.  
  117. for (const anchor of cpm.content.querySelectorAll('li a[href]')) {
  118. let li = nav.appendChild(document.createElement('li'));
  119. li.appendChild(anchor);
  120. }
  121.  
  122. let pos = document.querySelectorAll('#site-nav>nav>li.with-submenu');
  123. pos = pos.length >= 1 ? pos[pos.length - 1] : null;
  124.  
  125. if (!pos) return;
  126.  
  127. let tm = document.createElement('template');
  128. tm.innerHTML = `
  129.  
  130. <li class="with-submenu" style="display: block;">
  131. <a href="#" onclick="return false">${h.textContent}</a>
  132. <nav>
  133. ${nav.innerHTML}
  134. </nav>
  135. </li>
  136.  
  137. `.trim();
  138. pos.parentNode.insertBefore(tm.content, pos.nextSibling)
  139.  
  140.  
  141.  
  142. })();