Github屏蔽用户

屏蔽Github搜索页面某些丝麻用户的内容,如cirosantilli发的与代码无关的Shit Repo,我囸你写吗狗罕见

  1. // ==UserScript==
  2. // @name Github屏蔽用户
  3. // @namespace Violentmonkey Scripts
  4. // @match https://github.com/*
  5. // @grant GM_getValue
  6. // @grant GM_setValue
  7. // @grant unsafeWindow
  8. // @grant GM_registerMenuCommand
  9. // @version 1.0
  10. // @author Gwen0x4c3
  11. // @license MIT
  12. // @description 屏蔽Github搜索页面某些丝麻用户的内容,如cirosantilli发的与代码无关的Shit Repo,我囸你写吗狗罕见
  13. // ==/UserScript==
  14. (function() {
  15. 'use strict';
  16. const log = {
  17. info(message, obj) {
  18. if (typeof(message) == 'string') {
  19. console.log("%c[INFO] " + message, "color:blue;font-weight:bold;", obj);
  20. } else {
  21. console.log("%c[INFO] ", "color:blue;font-weight:bold;", arguments);
  22. }
  23. },
  24. error(message, obj) {
  25. if (typeof(message) == 'string') {
  26. console.log("%c[ERROR] " + message, "color:red;font-weight:bold;", obj);
  27. } else {
  28. console.log("%c[ERROR] ", "color:red;font-weight:bold;", arguments);
  29. }
  30. }
  31. }
  32. const REGEX_SEARCH_REPO = /\/search\?.*?type=repositories.*?/;
  33. const REGEX_SEARCH_USER = /\/search\?.*?type=users.*?/;
  34. const REGEX_EXCLUDE_USER = /-user:([a-zA-Z0-9_]+)/g;
  35. const store = {
  36. blockedUsers: GM_getValue("blocked_users", ['cirosantilli', 'wumaoland']),
  37. dialog: null
  38. }
  39. GM_registerMenuCommand("⚙查看屏蔽用户", () => {
  40. store.dialog.show();
  41. });
  42. function createElement(tag, clazz, attrs) {
  43. const elem = document.createElement(tag);
  44. elem.className = clazz;
  45. if (attrs) {
  46. for (let key in attrs) {
  47. elem[key] = attrs[key];
  48. }
  49. }
  50. return elem;
  51. }
  52. function blockElem(target) {
  53. const div = createElement('div', target.className, {
  54. innerText: `🚫Blocked this shit content by user: ${target.getAttribute('gb_user')}`
  55. })
  56. target.replaceWith(div);
  57. }
  58. function blockRepoSearch() {
  59. const resultList = document.querySelector('div[data-testid="results-list"]');
  60. // log.info("获取results list", { resultList });
  61. if (!resultList || resultList.gb_blocked) {
  62. setTimeout(blockRepoSearch, 100);
  63. } else {
  64. resultList.gb_blocked = true;
  65. const repos = resultList.children;
  66. for (let i = 0; i < repos.length; i++) {
  67. const repo = repos[i];
  68. const span = repo.querySelector('.search-match');
  69. log.info({repo, span});
  70. const user = span.innerText.split('/')[0];
  71. repo.setAttribute('gb_user', user);
  72. for (let blockedUser of store.blockedUsers) {
  73. if (blockedUser == user) {
  74. log.info("BLOCKED " + span.innerText);
  75. blockElem(repo);
  76. break;
  77. }
  78. }
  79. const exampleButton = repo.querySelector('button');
  80. const blockButton = createElement('button', exampleButton.className, {
  81. innerText: '🚫Block',
  82. onclick: e => {
  83. if (confirm("Are you sure to BLOCK this MF:" + user)) {
  84. store.blockedUsers.push(user);
  85. GM_setValue('blocked_users', store.blockedUsers);
  86. for (let j = 0; j < repos.length; j++) {
  87. if (repos[j].getAttribute('gb_user') == user) {
  88. blockElem(repos[j]);
  89. }
  90. }
  91. }
  92. }
  93. });
  94. blockButton.setAttribute('data-size', 'small');
  95. const buttonWrapper = createElement('div', exampleButton.parentElement.className);
  96. buttonWrapper.appendChild(blockButton);
  97. exampleButton.parentElement.parentElement.prepend(buttonWrapper);
  98. }
  99. }
  100. }
  101. function blockUserSearch() {
  102. const resultList = document.querySelector('div[data-testid="results-list"]');
  103. // log.info("获取results list", { resultList });
  104. if (!resultList || resultList.gb_blocked) {
  105. setTimeout(blockRepoSearch, 100);
  106. } else {
  107. resultList.gb_blocked = true;
  108. const users = resultList.children;
  109. for (let i = 0; i < users.length; i++) {
  110. const userElem = users[i];
  111. const a = user.querySelector('a:last-of-type');
  112. const user = a.innerText;
  113. userElem.setAttribute('gb_user', user);
  114. for (let blockedUser of store.blockedUsers) {
  115. if (blockedUser == user) {
  116. log.info("BLOCKED " + span.innerText);
  117. blockElem(userElem);
  118. break;
  119. }
  120. }
  121. const exampleButton = user.querySelector('button');
  122. const blockButton = createElement('button', exampleButton.className, {
  123. innerText: '🚫Block',
  124. onclick: e => {
  125. if (confirm("Are you sure to BLOCK this MF:" + user)) {
  126. store.blockedUsers.push(user);
  127. GM_setValue('blocked_users', store.blockedUsers);
  128. for (let j = 0; j < users.length; j++) {
  129. if (users[j].getAttribute('gb_user') == user) {
  130. // users[j].remove();
  131. // j--;
  132. blockElem(users[j]);
  133. }
  134. }
  135. }
  136. }
  137. });
  138. blockButton.setAttribute('data-size', 'small');
  139. const buttonWrapper = createElement('div', exampleButton.parentElement.className);
  140. buttonWrapper.appendChild(blockButton);
  141. exampleButton.parentElement.parentElement.prepend(buttonWrapper);
  142. }
  143. }
  144. }
  145. function initDialog() {
  146. if (document.getElementById('gb_block_dialog')) {
  147. return;
  148. }
  149. const dialog = createElement('dialog', '', {
  150. id: 'gb_block_dialog',
  151. style: 'width:50%;position:fixed;left:0;top:50px;'
  152. });
  153. store.dialog = dialog;
  154. const closeBtn = createElement('span', '', {
  155. innerText: '×',
  156. style: 'position:absolute;right:5px;top:2px;font-size:18px;cursor:pointer',
  157. onclick: e => {
  158. dialog.close();
  159. }
  160. })
  161. const tips = createElement('p', '', {
  162. innerText: '多个用户使用英文逗号","分隔',
  163. style: 'text-align: center'
  164. })
  165. const textArea = createElement('textarea', '', {
  166. style: 'width:100%;min-height:200px;font-size:18px;resize:none;',
  167. value: store.blockedUsers.join(', '),
  168. onblur: e => {
  169. const arr = textArea.value.split(',');
  170. for (let i = 0; i < arr.length; i++) {
  171. arr[i] = arr[i].trim();
  172. if (arr[i].length == 0) {
  173. arr.splice(i, 1);
  174. i--;
  175. }
  176. }
  177. store.blockedUsers = [...arr];
  178. GM_setValue('blocked_users', store.blockedUsers);
  179. textArea.value = arr.join(', ');
  180. }
  181. })
  182. dialog.appendChild(closeBtn);
  183. dialog.appendChild(tips);
  184. dialog.appendChild(textArea);
  185. document.body.append(dialog);
  186. }
  187. function handleUrlChange(url) {
  188. initDialog();
  189. // const _url = new URL(url);
  190. // if (_url.pathname == '/search') {
  191. // let q = _url.searchParams.get('q');
  192. // if (!q) {
  193. // q = '';
  194. // }
  195. // let users = [];
  196. // let match = null;
  197. // while ((match = REGEX_EXCLUDE_USER.exec(q)) !== null) {
  198. // users.push(match[1]);
  199. // }
  200. // }
  201. if (REGEX_SEARCH_REPO.test(lastUrl)) {
  202. blockRepoSearch();
  203. } else if (REGEX_SEARCH_USER.test(lastUrl)) {
  204. blockUserSearch();
  205. }
  206. }
  207. let lastUrl = '';
  208. handleUrlChange(location.href);
  209. const urlTimer = setInterval(() => {
  210. if (lastUrl != location.href) {
  211. log.info("url changed to " + location.href);
  212. lastUrl = location.href;
  213. handleUrlChange(lastUrl);
  214. }
  215. }, 300);
  216. })();

QingJ © 2025

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