Hide Bot Comments

Removes comments made by bots on websites such as YouTube.

目前為 2022-02-20 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Hide Bot Comments
  3. // @namespace https://theusaf.org
  4. // @version 1.4.1
  5. // @description Removes comments made by bots on websites such as YouTube.
  6. // @author theusaf
  7. // @match https://www.youtube.com/**
  8. // @copyright 2022 theusaf
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. const SITES = Object.freeze({
  14. YOUTUBE: [
  15. /^\s{2,}/, // starts with too much whitespace
  16. /^(\s*@.+)?\s*(https:\/\/[^\s]+)(https:\/\/[^\s]+|\n.\s])+$/, // only links and other punctuation
  17. /^(\s*@.+)?\s*[A-Z\s\r\n!]*https:\/\/[^\s]+[A-Z\s\r\n!]*$/, // all caps and a link
  18. /^(\s*@.+)?\s*https:\/\/[^\s]+(\n|.|\s)*([dD]on'?t [mM]iss|Bots for u|Finally|💜|fax|only until|Bots are|:]|I found it :|Yes true)/i, // A link and a random message afterwards
  19. /^(\s*@.+)?\s*(This|[Ww]ow!?)\s*https:\/\/[^\s]+/, // word + link
  20. /^(\s*@.+)?\s*https:\/\/[^\s]+\s*[a-z]+\s*$/, // link + random "word"
  21. /PRIVATE S\*X|over 18/, // ...
  22. /beautyzone\.\w+|\.cam|lust\.\w+/i, // suspicious websites
  23. /-{5,}/, // too many "-"
  24. /SPECIAL FOR YOU|MY CONTENT|My mom.*subscribers|literally begging|MY VIDEOS|fucking cringe|Don'?t read my name/i, // common phrase
  25. /[ㄥϛㄣƐᄅƖ⅄Λ∩┴ɹԀ˥ʞſפℲƎƆ∀ʎʍʌʇɹɯʞɾᴉɥƃɟǝɔɐ]/, // upside down chars
  26. (text) => {
  27. const charSets = [
  28. {
  29. regex: /[ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘᴏ̨ʀsᴛᴜᴠᴡxʏᴢ\s]/g,
  30. matchPercent: 0.5
  31. },
  32. {
  33. regex: /[\u{1D538}-\u{1D56B}]/gu, // math letter symbols
  34. matchPercent: 0.5
  35. }
  36. ];
  37. for (const check of charSets) {
  38. const { regex, matchPercent } = check,
  39. matches = text.match(regex)?.length ?? 0;
  40. if (matches / text.length > matchPercent && text.length > 10) {
  41. return true;
  42. }
  43. }
  44. }
  45. ]
  46. }),
  47. site = getCurrentSite(),
  48. commentMutationListener = new MutationObserver((mutations) => {
  49. for (const mutation of mutations) {
  50. for (const node of mutation.addedNodes) {
  51. const text = getCommentText(node, site);
  52. if (text) {
  53. if (isCommentLikelyBotComment(text, site)) {
  54. node.style.display = "none";
  55. }
  56. }
  57. }
  58. }
  59. });
  60.  
  61. commentMutationListener.observe(document.body, {
  62. subtree: true,
  63. childList: true
  64. });
  65.  
  66. /**
  67. * Determines whether a comment is likely spam.
  68. *
  69. * @param {String} text The comment's content
  70. * @param {Object} site The website the comment is from
  71. * @return {Boolean}
  72. */
  73. function isCommentLikelyBotComment(text, siteChecks) {
  74. for (const check of siteChecks) {
  75. if (typeof check === "function") {
  76. if (check(text)) {
  77. return true;
  78. }
  79. } else {
  80. // assume regex
  81. if (check.test(text)) {
  82. return true;
  83. }
  84. }
  85. }
  86. return false;
  87. }
  88.  
  89. function getCommentText(node, site) {
  90. switch (site) {
  91. case SITES.YOUTUBE: {
  92. if (node.nodeName === "YTD-COMMENT-RENDERER") {
  93. return node.querySelector("#content-text").textContent;
  94. }
  95. }
  96. }
  97. return null;
  98. }
  99.  
  100. function getCurrentSite() {
  101. switch (location.hostname) {
  102. case "www.youtube.com": {
  103. return SITES.YOUTUBE;
  104. }
  105. }
  106. }