BiliBili 消息清理助手

清理 B站 消息(回复我的,@ 我的)

  1. // ==UserScript==
  2. // @name BiliBili 消息清理助手
  3. // @namespace moecasts
  4. // @version 0.3
  5. // @description 清理 B站 消息(回复我的,@ 我的)
  6. // @author Caster
  7. // @match *://message.bilibili.com/
  8. // @match *://message.bilibili.com/?spm_id_from=*
  9. // @contributionURL https://www.tore.moe/post/bilibili-massage-cleaner
  10. // @grant none
  11. // @run-at context-end
  12. // ==/UserScript==
  13.  
  14. (async function() {
  15. "use strict";
  16. /**
  17. * @param number interval 每次请求间隔时间
  18. */
  19. const options = {
  20. interval: 500
  21. };
  22. let isLoaded = false;
  23. let isActive = false;
  24. let routerMenu = document.querySelector(".list");
  25. let activeMenu = document.querySelector(".router-link-exact-active");
  26. let actionButton;
  27.  
  28. const isEmpty = val => {
  29. // null or undefined
  30. if (val == null) return true;
  31.  
  32. if (typeof val === "boolean") return false;
  33.  
  34. if (typeof val === "number") return !val;
  35.  
  36. if (val instanceof Error) return val.message === "";
  37.  
  38. switch (Object.prototype.toString.call(val)) {
  39. // String or Array
  40. case "[object String]":
  41. case "[object Array]":
  42. return !val.length;
  43.  
  44. // Map or Set or File
  45. case "[object File]":
  46. case "[object Map]":
  47. case "[object Set]": {
  48. return !val.size;
  49. }
  50. // Plain Object
  51. case "[object Object]": {
  52. return !Object.keys(val).length;
  53. }
  54. }
  55.  
  56. return false;
  57. };
  58.  
  59. const createActionButton = () => {
  60. actionButton = document.createElement("div");
  61. actionButton.classList.add("moecasts-bilibili-message-cleaner-button");
  62. actionButton.innerText = "启动清理功能";
  63. actionButton.style =
  64. "color: rgb(255, 255, 255);background: #f45a8d;position: absolute;z-index: 99999;right: 10px;top: 45vh;height: 20px;line-height: 20px;padding: 8px;border-radius: 5px;cursor: pointer;";
  65. document.body.appendChild(actionButton);
  66.  
  67. actionButton.addEventListener("click", () => {
  68. if (isActive) {
  69. isActive = false;
  70. actionButton.innerText = "启动清理功能";
  71. console.log("关闭");
  72. } else {
  73. if (confirm("确认要开启功能吗?")) {
  74. console.log("正在清理。。。");
  75. isActive = true;
  76. actionButton.innerText = "暂停清理";
  77. clean();
  78. }
  79. }
  80. });
  81. };
  82.  
  83. const sleep = (fn, times) => {
  84. return new Promise(resolve => {
  85. setTimeout(() => resolve(fn()), times);
  86. });
  87. };
  88.  
  89. const clean = async () => {
  90. let deleteButton = document.querySelector(".action-button>.action-delete");
  91. let scrollPane = document.querySelector(".space-right-bottom");
  92. let panel = scrollPane.querySelector(".router-view");
  93.  
  94. while (isActive && !isEmpty(deleteButton)) {
  95. scrollPane.scrollTop = panel.offsetHeight - scrollPane.offsetHeight;
  96. scrollPane.scrollTop = 0;
  97. try {
  98. deleteButton.click();
  99. await sleep(() => {
  100. if (isActive) {
  101. try {
  102. let confirmButton = document.querySelector(
  103. ".popup-btn-ctnr .bl-button:first-child"
  104. );
  105. if (!isEmpty(confirmButton)) {
  106. confirmButton.click();
  107. }
  108. } catch (e) {
  109. console.log("清理错误,正在重试。。。");
  110. }
  111. }
  112. }, 100);
  113. } catch (e) {
  114. console.log("清理错误,正在重试。。。");
  115. }
  116. deleteButton = document.querySelector(".action-button>.action-delete");
  117. await sleep(() => {}, options.interval);
  118. }
  119.  
  120. isActive = false;
  121. actionButton.innerText = "启动清理功能";
  122.  
  123. if (isEmpty(deleteButton)) {
  124. console.log("清理完毕。");
  125. alert("清理完毕。");
  126. }
  127. };
  128.  
  129. const init = () => {
  130. if (
  131. activeMenu &&
  132. (activeMenu.href.indexOf("reply") > -1 ||
  133. activeMenu.href.indexOf("at") > -1)
  134. ) {
  135. if (!actionButton) {
  136. createActionButton();
  137. } else {
  138. actionButton.style.display = "block";
  139. }
  140. } else {
  141. if (actionButton) {
  142. actionButton.style.display = "none";
  143. }
  144. }
  145. };
  146.  
  147. const load = async () => {
  148. console.log("脚本启动中。。。");
  149. while (isEmpty(activeMenu)) {
  150. await sleep(() => {}, 1000);
  151. routerMenu = document.querySelector(".list");
  152. activeMenu = document.querySelector(".router-link-exact-active");
  153. if (!isEmpty(activeMenu)) {
  154. break;
  155. }
  156. console.log(document.body);
  157. console.log("正在重试");
  158. }
  159. init();
  160.  
  161. routerMenu.addEventListener("click", e => {
  162. activeMenu = document.querySelector(".router-link-exact-active");
  163. init();
  164. });
  165.  
  166. console.log("脚本启动完毕!");
  167. };
  168.  
  169. await load();
  170. })();

QingJ © 2025

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