Kemono Party Blacklist with Reasons

Blacklists posts by Creator ID with reasons, featuring "Blacklist All Users", "Blacklist", and "Unblacklist" (with reasons and multiple delete)

  1. // ==UserScript==
  2. // @name Kemono Party Blacklist with Reasons
  3. // @namespace https://MeusArtis.ca
  4. // @version 2.4.0
  5. // @description Blacklists posts by Creator ID with reasons, featuring "Blacklist All Users", "Blacklist", and "Unblacklist" (with reasons and multiple delete)
  6. // @author Meus Artis
  7. // @icon https://www.google.com/s2/favicons?domain=kemono.su
  8. // @match https://kemono.su/*
  9. // @match https://coomer.su/*
  10. // @license CC BY-NC-SA 4.0
  11. // @run-at document-end
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. const BlacklistStorage = window.localStorage;
  16.  
  17. // Initialize blacklist storage
  18. if (!BlacklistStorage.getItem("blacklist")) {
  19. BlacklistStorage.setItem("blacklist", JSON.stringify([]));
  20. }
  21. const Blacklisted = JSON.parse(BlacklistStorage.getItem("blacklist"));
  22.  
  23. // Helper to save blacklist
  24. function saveBlacklist() {
  25. BlacklistStorage.setItem("blacklist", JSON.stringify(Blacklisted));
  26. }
  27.  
  28. // Apply blacklist to hide elements
  29. function applyBlacklist() {
  30. Blacklisted.forEach(({ id }) => {
  31. document.querySelectorAll(`[data-user='${id}']`).forEach((el) => {
  32. el.closest("article").style.display = "none";
  33. });
  34. });
  35. }
  36.  
  37. // Add "Blacklist All Users" button
  38. function addBlacklistAllButton() {
  39. if (document.querySelector("#blacklist-all-users")) return;
  40.  
  41. const button = document.createElement("button");
  42. button.id = "blacklist-all-users";
  43. button.textContent = "Blacklist All Users";
  44. button.style.cssText = `
  45. position: fixed;
  46. bottom: 70px;
  47. right: 20px;
  48. z-index: 1000;
  49. padding: 10px 15px;
  50. background: #ff4d4f;
  51. color: white;
  52. border: none;
  53. border-radius: 5px;
  54. cursor: pointer;
  55. font-size: 14px;
  56. font-weight: bold;
  57. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
  58. `;
  59.  
  60. button.onclick = () => {
  61. const userIds = new Set();
  62. document.querySelectorAll("article[data-user]").forEach((card) => {
  63. const userId = card.getAttribute("data-user");
  64. if (userId && !Blacklisted.some((entry) => entry.id === userId)) {
  65. userIds.add(userId);
  66. }
  67. });
  68.  
  69. if (userIds.size > 0) {
  70. const reason = prompt(`Enter a reason for blacklisting these ${userIds.size} users:`);
  71.  
  72. if (reason) {
  73. userIds.forEach((id) => {
  74. Blacklisted.push({ id, reason });
  75. });
  76. saveBlacklist();
  77. alert(`Blacklisted ${userIds.size} users!`);
  78. applyBlacklist();
  79. }
  80. } else {
  81. alert("No new users found to blacklist.");
  82. }
  83. };
  84.  
  85. document.body.appendChild(button);
  86. }
  87.  
  88. // Add "Blacklist" button on creator/user pages
  89. function addBlacklistButton() {
  90. if (document.querySelector("#blacklist-button")) return;
  91.  
  92. const button = document.createElement("button");
  93. button.id = "blacklist-button";
  94. button.textContent = "Blacklist";
  95. button.style.cssText = `
  96. position: fixed;
  97. bottom: 20px;
  98. right: 20px;
  99. z-index: 1000;
  100. padding: 10px 15px;
  101. background: #ff4d4f;
  102. color: white;
  103. border: none;
  104. border-radius: 5px;
  105. cursor: pointer;
  106. font-size: 14px;
  107. font-weight: bold;
  108. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
  109. `;
  110.  
  111. button.onclick = () => {
  112. const HeadMetaPost = document.querySelector("meta[name='user']");
  113. const HeadMetaArtistID = document.querySelector("meta[name='id']")?.getAttribute("content");
  114. const currentUserId = HeadMetaPost?.getAttribute("content") || HeadMetaArtistID;
  115.  
  116. if (currentUserId && !Blacklisted.some((entry) => entry.id === currentUserId)) {
  117. const reason = prompt(`Enter a reason for blacklisting user ID: ${currentUserId}`);
  118. if (reason) {
  119. Blacklisted.push({ id: currentUserId, reason });
  120. saveBlacklist();
  121. alert("Creator/User Blacklisted!");
  122. applyBlacklist();
  123. }
  124. } else {
  125. alert("This creator/user is already blacklisted.");
  126. }
  127. };
  128.  
  129. document.body.appendChild(button);
  130. }
  131.  
  132. // Add "Unblacklist Users" button
  133. function addUnblacklistButton() {
  134. if (document.querySelector("#unblacklist-users")) return;
  135.  
  136. const button = document.createElement("button");
  137. button.id = "unblacklist-users";
  138. button.textContent = "Unblacklist Users";
  139. button.style.cssText = `
  140. position: fixed;
  141. bottom: 120px;
  142. right: 20px;
  143. z-index: 1000;
  144. padding: 10px 15px;
  145. background: #4caf50;
  146. color: white;
  147. border: none;
  148. border-radius: 5px;
  149. cursor: pointer;
  150. font-size: 14px;
  151. font-weight: bold;
  152. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
  153. `;
  154.  
  155. button.onclick = () => {
  156. const modal = document.createElement("div");
  157. modal.style.cssText = `
  158. position: fixed;
  159. top: 50%;
  160. left: 50%;
  161. transform: translate(-50%, -50%);
  162. z-index: 1001;
  163. padding: 20px;
  164. background: #ffffff;
  165. border-radius: 10px;
  166. box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
  167. max-height: 80%;
  168. overflow-y: auto;
  169. width: 800px;
  170. text-align: center;
  171. color: black;
  172. `;
  173.  
  174. modal.innerHTML = `
  175. <div style="margin-bottom: 15px;">
  176. <button id="delete-selected" style="padding: 5px 10px; background: #ff4d4f; color: white; border: none; border-radius: 5px; cursor: pointer;">Delete Selected</button>
  177. <button id="close-modal" style="padding: 5px 10px; background: #4caf50; color: white; border: none; border-radius: 5px; cursor: pointer;">Close</button>
  178. </div>
  179. <form id="blacklist-form">
  180. <label>
  181. <input id="select-all" type="checkbox" style="margin-bottom: 10px; cursor: pointer;">
  182. Select All
  183. </label>
  184. <ul style="list-style: none; padding: 0; margin: 0; text-align: left; max-height: 400px; overflow-y: scroll;">
  185. ${Blacklisted.length > 0
  186. ? Blacklisted.map(({ id, reason }) => `
  187. <li>
  188. <label>
  189. <input type="checkbox" value="${id}" style="margin-right: 5px; cursor: pointer;">
  190. <b>${id}</b> - <i>${reason || 'No reason provided'}</i>
  191. </label>
  192. </li>
  193. `).join("")
  194. : "<li>No users are blacklisted.</li>"
  195. }
  196. </ul>
  197. </form>
  198. `;
  199.  
  200. modal.querySelector("#select-all").onclick = (e) => {
  201. const checked = e.target.checked;
  202. modal.querySelectorAll("input[type='checkbox']").forEach((checkbox) => {
  203. checkbox.checked = checked;
  204. });
  205. };
  206.  
  207. modal.querySelector("#delete-selected").onclick = () => {
  208. const selectedIds = Array.from(modal.querySelectorAll("input[type='checkbox']:checked"))
  209. .map((checkbox) => checkbox.value);
  210. if (selectedIds.length > 0) {
  211. // Filter out selected IDs and remove them from the blacklist
  212. selectedIds.forEach((id) => {
  213. const index = Blacklisted.findIndex((entry) => entry.id === id);
  214. if (index > -1) {
  215. Blacklisted.splice(index, 1);
  216. }
  217. });
  218. saveBlacklist();
  219. modal.remove();
  220. applyBlacklist();
  221. addUnblacklistButton();
  222. } else {
  223. alert("No users selected.");
  224. }
  225. };
  226.  
  227. modal.querySelector("#close-modal").onclick = () => modal.remove();
  228.  
  229. document.body.appendChild(modal);
  230. };
  231.  
  232. document.body.appendChild(button);
  233. }
  234.  
  235. // Initialize the script
  236. function initializeScript() {
  237. applyBlacklist();
  238. addBlacklistAllButton();
  239. addBlacklistButton();
  240. addUnblacklistButton();
  241. }
  242.  
  243. // Observe URL changes and DOM mutations
  244. function observeDomChanges(callback) {
  245. const observer = new MutationObserver(callback);
  246. observer.observe(document.body, { childList: true, subtree: true });
  247. return observer;
  248. }
  249.  
  250. // Run script on page load and observe DOM changes
  251. window.addEventListener("DOMContentLoaded", initializeScript);
  252. observeDomChanges(() => {
  253. initializeScript();
  254. });
  255. })();