GreasyFork 一键回报垃圾评论

在 Greasy Fork镜像 一键回报垃圾评论

  1. // ==UserScript==
  2. // @name GreasyFork: One Click Report Spam
  3. // @name:zh-TW GreasyFork 一鍵回報垃圾評論
  4. // @name:zh-CN GreasyFork 一键回报垃圾评论
  5. // @namespace UserScripts
  6. // @match https://gf.qytechs.cn/*
  7. // @grant none
  8. // @version 1.9
  9. // @author CY Fung
  10. // @license MIT
  11. // @description To report spam comments in Greasy Fork镜像 with one click
  12. // @description:zh-TW 在 Greasy Fork镜像 一鍵回報垃圾評論
  13. // @description:zh-CN 在 Greasy Fork镜像 一键回报垃圾评论
  14. // ==/UserScript==
  15.  
  16. (() => {
  17.  
  18. const TEST_MODE = 0;
  19. let skipMode = false;
  20.  
  21. const onIframeLoad = async (evt) => {
  22. const iframe = evt.target;
  23. if (!(iframe instanceof HTMLIFrameElement)) return;
  24.  
  25. if (skipMode) return;
  26.  
  27.  
  28. const onNewUrl = async () => {
  29. skipMode = true;
  30.  
  31. alert('reported');
  32. await new Promise(requestAnimationFrame);
  33. iframe.remove();
  34. skipMode = false;
  35.  
  36. }
  37. const onAbort = async () => {
  38. skipMode = true;
  39.  
  40. await new Promise(requestAnimationFrame);
  41. iframe.remove();
  42. skipMode = false;
  43. }
  44.  
  45. iframe.removeEventListener('load', onIframeLoad, false);
  46.  
  47. if (!iframe.contentDocument) {
  48. alert('Iframe Access Error. Action aborted.');
  49. onAbort();
  50. return;
  51. }
  52.  
  53.  
  54. const reportReasonRadio = iframe.contentDocument.querySelector('input[name="report[reason]"]');
  55. if (reportReasonRadio) {
  56. for(const s of iframe.contentDocument.querySelectorAll('html, body, main')){
  57. s.style.scrollBehavior = 'auto';
  58. }
  59. reportReasonRadio.scrollIntoView();
  60. await new Promise(requestAnimationFrame);
  61. reportReasonRadio.click();
  62. const form = reportReasonRadio.closest('form');
  63. let currentUrl = iframe.contentWindow.location.pathname;
  64. skipMode = true;
  65. if (TEST_MODE) {
  66.  
  67. iframe.contentWindow.location.href = 'https://gf.qytechs.cn/'
  68. } else {
  69. form.submit();
  70. }
  71. let cid = setInterval(() => {
  72. if (!cid) return;
  73. let nextUrl = iframe.contentWindow.location.pathname;
  74. if (nextUrl !== currentUrl) {
  75. clearInterval(cid)
  76. cid = 0;
  77. setTimeout(onNewUrl, 300);
  78. }
  79. }, 100)
  80.  
  81. } else if (iframe.contentDocument.querySelector('#open-report-:not(:empty)')) {
  82. alert("The spam report is already submitted for moderator's review. Action aborted.");
  83. onAbort();
  84.  
  85. } else {
  86. alert('Cannot find the report[reason] radio button. Action aborted.');
  87. onAbort();
  88. }
  89.  
  90. };
  91. const clickHandler = (evt) => {
  92. evt.preventDefault();
  93. if (!(evt.target instanceof HTMLElement)) return;
  94. let url = evt.target.getAttribute('ohref');
  95. if (!url) return;
  96. let discussionId = /id=(\d+)\b/.exec(url);
  97. if (discussionId) discussionId = discussionId[1];
  98. let r = window.confirm(`Confirm to report discussion#${discussionId || "------"} ?`);
  99. if (!r) return;
  100. const iframe = document.createElement('iframe');
  101. skipMode = false;
  102. iframe.addEventListener('load', onIframeLoad, false);
  103. iframe.name = "u423323";
  104. iframe.src = url;
  105. Object.assign(iframe.style, {
  106. display: 'block',
  107. position: 'fixed',
  108. top: '0px',
  109. left: '0px',
  110. width: '300px',
  111. height: '300px',
  112. 'contain': 'strict',
  113. });
  114. document.body.appendChild(iframe);
  115. }
  116.  
  117.  
  118. for (const anchor of document.querySelectorAll('a[href*="/reports/new?item_class=comment&item_id="],a[href*="/reports/new?item_class=discussion&item_id="]')) {
  119.  
  120. let anchorNode = anchor;
  121. if (anchor.parentNode.firstElementChild === anchor.parentNode.lastElementChild) {
  122. anchorNode = anchorNode.parentNode;
  123. }
  124. let newAnchorNode = anchorNode.cloneNode(true);
  125. let newAnchor = newAnchorNode.querySelector('a[href]') || newAnchorNode;
  126. newAnchor.classList.add('report-spam-btn');
  127. newAnchor.setAttribute('ohref', newAnchor.getAttribute('href'));
  128. newAnchor.setAttribute('href', '#');
  129. newAnchor.addEventListener('click', clickHandler, false)
  130. newAnchor.textContent = 'Report Spam';
  131. anchorNode.parentNode.insertBefore(newAnchorNode, anchorNode.nextSibling);
  132.  
  133.  
  134. }
  135.  
  136. document.head.appendChild(document.createElement('style')).textContent=`
  137. .discussion-list-container{
  138. display:flex;
  139. flex-direction: row;
  140. flex-wrap: nowrap;
  141. }
  142. .discussion-list-container > .discussion-list-item {
  143. flex-grow:1;
  144. width:0;
  145. }
  146. .discussion-list-container > .discussion-list-item ~ .report-spam-btn {
  147. align-self: center;
  148. }
  149. `
  150.  
  151. setTimeout(()=>{
  152.  
  153. if(document.querySelector('ul#user-control-panel')) return;
  154.  
  155. for(const li of document.querySelectorAll('.discussion-list-item')){
  156.  
  157. let a = li.querySelector('a[href*="/discussions/"].discussion-title');
  158. if(!a) continue;
  159. let href = a.getAttribute('href');
  160. let idx = href.lastIndexOf('/discussions/');
  161. let discussionId = parseInt(href.substring(idx+'/discussions/'.length)||0);
  162. if(isNaN(discussionId) || discussionId < 0)continue;
  163.  
  164. let btn = document.createElement('a');
  165. btn.classList.add('report-spam-btn');
  166. btn.setAttribute('ohref', 'https://gf.qytechs.cn/en/reports/new?item_class=discussion&item_id='+discussionId)
  167. btn.setAttribute('href','#')
  168. btn.textContent='Report Spam';
  169. btn.addEventListener('click', clickHandler, false)
  170. li.parentNode.insertBefore(btn, li.nextSibling);
  171.  
  172.  
  173. }
  174.  
  175. }, 270);
  176.  
  177. })();

QingJ © 2025

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