Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Hide Posts & Comments by Keywords with UI on Reddit (Universal)
- // @namespace https://naroman.tl
- // @version 1.2.13-custom-colours
- // @description Hide posts and comments containing specified keywords on both new and old Reddit interfaces. A small purple circle opens a modal to update keywords. Works on both reddit.com and old.reddit.com.
- // @author
- // @match *://*.reddit.com/*
- // @match *://old.reddit.com/*
- // @grant none
- // @updateURL https://naroman.tl/wp-content/hidepost/hide-posts.js
- // @downloadURL https://naroman.tl/wp-content/hidepost/hide-posts.js
- // ==/UserScript==
- (function () {
- 'use strict';
- // Load keywords from localStorage (or use defaults)
- let postKeywords = JSON.parse(localStorage.getItem("redditPostKeywords") || '["musk", "elon", "biden"]');
- let commentKeywords = JSON.parse(localStorage.getItem("redditCommentKeywords") || '["hawk tuah"]');
- // Returns true if the provided text contains any of the keywords (case-insensitive)
- function containsKeyword(text, keywords) {
- return keywords.some(keyword => text.toLowerCase().includes(keyword.toLowerCase()));
- }
- // Helper: Get visible text from an element.
- // Prefer innerText (which better reflects what the user sees); fallback to textContent.
- function getVisibleText(el) {
- return el.innerText || el.textContent || "";
- }
- // Main filtering function – hides posts and comments whose visible text includes a keyword.
- function hideContent() {
- console.log("hideContent() called");
- if (window.location.hostname.includes("old.reddit.com")) {
- // -------- OLD REDDIT --------
- // Old Reddit posts: select .thing elements that do NOT also have the class "comment"
- const oldPosts = document.querySelectorAll('.thing:not(.comment):not([data-checked])');
- console.log("Old posts found: " + oldPosts.length);
- oldPosts.forEach(post => {
- const title = post.querySelector('a.title');
- if (title && containsKeyword(getVisibleText(title), postKeywords)) {
- post.style.display = 'none';
- console.log("Hiding OLD post: " + getVisibleText(title));
- }
- post.setAttribute('data-checked', 'true');
- });
- // Old Reddit comments: select .thing.comment elements
- const oldComments = document.querySelectorAll('.thing.comment:not([data-checked])');
- console.log("Old comments found: " + oldComments.length);
- oldComments.forEach(comment => {
- // The comment text is usually inside a descendant with class "usertext-body"
- const textElement = comment.querySelector('.usertext-body');
- if (textElement && containsKeyword(getVisibleText(textElement), commentKeywords)) {
- comment.style.display = 'none';
- console.log("Hiding OLD comment: " + getVisibleText(textElement).substring(0,50));
- }
- comment.setAttribute('data-checked', 'true');
- });
- } else {
- // -------- NEW REDDIT --------
- // New posts: select using data-testid or <shreddit-post>
- const newPosts = document.querySelectorAll(
- 'div[data-testid="post-container"]:not([data-checked]), shreddit-post:not([data-checked])'
- );
- console.log("New posts found: " + newPosts.length);
- newPosts.forEach(post => {
- const title = post.querySelector('h3, a[slot="title"]');
- if (title && containsKeyword(getVisibleText(title), postKeywords)) {
- post.style.display = 'none';
- console.log("Hiding NEW post: " + getVisibleText(title));
- }
- post.setAttribute('data-checked', 'true');
- });
- // New comments: try selector for div elements with id starting with "t1_"
- const newComments = document.querySelectorAll('div[id^="t1_"]:not([data-checked])');
- console.log("New comments found (div[id^='t1_']): " + newComments.length);
- newComments.forEach(comment => {
- const text = getVisibleText(comment);
- if (containsKeyword(text, commentKeywords)) {
- comment.style.display = 'none';
- console.log("Hiding NEW comment (t1_): " + text.substring(0,50));
- }
- comment.setAttribute('data-checked', 'true');
- });
- // Also try alternative selectors
- const newCommentsAlt = document.querySelectorAll(
- 'div[data-testid="comment"]:not([data-checked]), shreddit-comment:not([data-checked]), reddit-comment:not([data-checked])'
- );
- console.log("New comments found (alt selectors): " + newCommentsAlt.length);
- newCommentsAlt.forEach(comment => {
- const text = getVisibleText(comment);
- if (containsKeyword(text, commentKeywords)) {
- comment.style.display = 'none';
- console.log("Hiding NEW comment (alt): " + text.substring(0,50));
- }
- comment.setAttribute('data-checked', 'true');
- });
- }
- }
- // Set up a MutationObserver to catch new nodes (e.g. infinite scrolling)
- const observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
- if (mutation.addedNodes.length > 0) {
- console.log("MutationObserver: " + mutation.addedNodes.length + " node(s) added");
- hideContent();
- }
- });
- });
- observer.observe(document.body, { childList: true, subtree: true });
- // Also run hideContent() on window load
- window.addEventListener('load', () => {
- console.log("Window load event fired");
- hideContent();
- });
- // Periodic filtering: run hideContent() every 1 second for up to 60 seconds.
- let attempts = 0;
- const maxAttempts = 60;
- const intervalId = setInterval(() => {
- console.log("Interval attempt " + attempts);
- hideContent();
- attempts++;
- if (attempts >= maxAttempts) {
- clearInterval(intervalId);
- console.log("Cleared interval after " + attempts + " attempts");
- }
- }, 1000);
- // --- UI: Create a modal for updating keywords with updated colour scheme ---
- function createKeywordUI() {
- // Create the floating button (now using #9232E4)
- const button = document.createElement("button");
- button.innerText = "";
- button.title = "Keywords";
- button.id = "keywordsButton";
- button.style.position = "fixed";
- button.style.top = "10px";
- button.style.right = "10px";
- button.style.zIndex = "9999";
- button.style.width = "20px";
- button.style.height = "20px";
- button.style.backgroundColor = "#9232E4"; // purple accent
- button.style.border = "none";
- button.style.borderRadius = "50%";
- button.style.cursor = "pointer";
- button.style.boxShadow = "0 0 3px rgba(0,0,0,0.3)";
- document.body.appendChild(button);
- // Create the modal overlay with a semi-transparent #0C1824 background.
- const modal = document.createElement("div");
- modal.id = "keywordsModal";
- modal.style.display = "none";
- modal.style.position = "fixed";
- modal.style.top = "0";
- modal.style.left = "0";
- modal.style.width = "100%";
- modal.style.height = "100%";
- modal.style.backgroundColor = "rgba(12, 24, 36, 0.8)"; // dark, using #0C1824
- modal.style.zIndex = "10000";
- modal.style.backdropFilter = "blur(5px)";
- // Modal content container
- const modalContent = document.createElement("div");
- modalContent.style.position = "absolute";
- modalContent.style.top = "50%";
- modalContent.style.left = "50%";
- modalContent.style.transform = "translate(-50%, -50%)";
- modalContent.style.backgroundColor = "#FFFFFF";
- modalContent.style.padding = "20px";
- modalContent.style.borderRadius = "8px";
- modalContent.style.boxShadow = "0 4px 15px rgba(0,0,0,0.2)";
- modalContent.style.maxWidth = "90%";
- modalContent.style.width = "320px";
- modalContent.style.fontFamily = "Arial, sans-serif";
- // Modal title (using #9232E4 as accent)
- const modalTitle = document.createElement("h3");
- modalTitle.innerText = "Set Keywords";
- modalTitle.style.marginBottom = "15px";
- modalTitle.style.fontSize = "18px";
- modalTitle.style.color = "#9232E4";
- modalContent.appendChild(modalTitle);
- // Input for Post Keywords
- const postLabel = document.createElement("label");
- postLabel.innerText = "Post Keywords:";
- postLabel.style.display = "block";
- postLabel.style.marginBottom = "5px";
- postLabel.style.fontSize = "14px";
- postLabel.style.fontWeight = "bold";
- modalContent.appendChild(postLabel);
- const postInput = document.createElement("input");
- postInput.type = "text";
- postInput.id = "postKeywordsInput";
- postInput.style.width = "100%";
- postInput.style.padding = "8px";
- postInput.style.marginBottom = "15px";
- postInput.style.border = "1px solid #ccc";
- postInput.style.borderRadius = "4px";
- postInput.style.fontSize = "14px";
- postInput.value = postKeywords.join(", ");
- modalContent.appendChild(postInput);
- // Input for Comment Keywords
- const commentLabel = document.createElement("label");
- commentLabel.innerText = "Comment Keywords:";
- commentLabel.style.display = "block";
- commentLabel.style.marginBottom = "5px";
- commentLabel.style.fontSize = "14px";
- commentLabel.style.fontWeight = "bold";
- modalContent.appendChild(commentLabel);
- const commentInput = document.createElement("input");
- commentInput.type = "text";
- commentInput.id = "commentKeywordsInput";
- commentInput.style.width = "100%";
- commentInput.style.padding = "8px";
- commentInput.style.marginBottom = "15px";
- commentInput.style.border = "1px solid #ccc";
- commentInput.style.borderRadius = "4px";
- commentInput.style.fontSize = "14px";
- commentInput.value = commentKeywords.join(", ");
- modalContent.appendChild(commentInput);
- // Buttons container
- const buttonsContainer = document.createElement("div");
- buttonsContainer.style.display = "flex";
- buttonsContainer.style.justifyContent = "flex-end";
- buttonsContainer.style.marginTop = "10px";
- // Save button
- const saveButton = document.createElement("button");
- saveButton.innerText = "Save";
- saveButton.style.marginRight = "10px";
- saveButton.style.padding = "8px 12px";
- saveButton.style.backgroundColor = "#9232E4";
- saveButton.style.color = "white";
- saveButton.style.border = "none";
- saveButton.style.borderRadius = "4px";
- saveButton.style.cursor = "pointer";
- saveButton.style.fontSize = "14px";
- saveButton.style.fontWeight = "bold";
- saveButton.style.transition = "background-color 0.2s";
- saveButton.onmouseover = () => (saveButton.style.backgroundColor = "#7A1CC4");
- saveButton.onmouseout = () => (saveButton.style.backgroundColor = "#9232E4");
- buttonsContainer.appendChild(saveButton);
- // Cancel button
- const cancelButton = document.createElement("button");
- cancelButton.innerText = "Cancel";
- cancelButton.style.padding = "8px 12px";
- cancelButton.style.backgroundColor = "#aaa";
- cancelButton.style.color = "white";
- cancelButton.style.border = "none";
- cancelButton.style.borderRadius = "4px";
- cancelButton.style.cursor = "pointer";
- cancelButton.style.fontSize = "14px";
- cancelButton.style.fontWeight = "bold";
- cancelButton.style.transition = "background-color 0.2s";
- cancelButton.onmouseover = () => (cancelButton.style.backgroundColor = "#888");
- cancelButton.onmouseout = () => (cancelButton.style.backgroundColor = "#aaa");
- buttonsContainer.appendChild(cancelButton);
- modalContent.appendChild(buttonsContainer);
- modal.appendChild(modalContent);
- document.body.appendChild(modal);
- // Modal event listeners
- button.addEventListener("click", () => {
- console.log("Keyword button clicked; opening modal.");
- modal.style.display = "block";
- });
- cancelButton.addEventListener("click", () => {
- console.log("Cancel button clicked; closing modal.");
- modal.style.display = "none";
- });
- saveButton.addEventListener("click", () => {
- const newPostKeywords = postInput.value.split(",").map(s => s.trim()).filter(s => s);
- const newCommentKeywords = commentInput.value.split(",").map(s => s.trim()).filter(s => s);
- postKeywords = newPostKeywords;
- commentKeywords = newCommentKeywords;
- localStorage.setItem("redditPostKeywords", JSON.stringify(postKeywords));
- localStorage.setItem("redditCommentKeywords", JSON.stringify(commentKeywords));
- modal.style.display = "none";
- console.log("Save button clicked; keywords updated. Re-running filter.");
- // Remove all data-checked attributes so that hideContent() re-checks all content.
- document.querySelectorAll('[data-checked]').forEach(el => el.removeAttribute('data-checked'));
- hideContent();
- });
- }
- // Initialize the UI.
- createKeywordUI();
- })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement