您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically hides Bluesky posts immediately after confirming the block action using the native Block button.
当前为
- // ==UserScript==
- // @name Bluesky Unified Block & Hide
- // @namespace https://greasyfork.org/en/users/567951-stuart-saddler
- // @version 1.0
- // @description Automatically hides Bluesky posts immediately after confirming the block action using the native Block button.
- // @icon https://images.seeklogo.com/logo-png/52/2/bluesky-logo-png_seeklogo-520643.png
- // @match https://bsky.app/*
- // @grant none
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- // Global variable to store the currently selected username
- let currentUsername = null;
- /**
- * Utility function to log messages with a prefix for easier debugging.
- * @param {string} message - The message to log.
- */
- function log(message) {
- console.log(`[Bluesky Auto Hide Blocked Posts] ${message}`);
- }
- /**
- * Determines if a given element is the "Three Dots" (Post Options) button.
- * @param {Element} element - The DOM element to check.
- * @returns {boolean} - True if it's the "Three Dots" button, else false.
- */
- function isPostOptionsButton(element) {
- if (!element) return false;
- const ariaLabel = element.getAttribute('aria-label') || '';
- return ariaLabel.includes('Open post options menu');
- }
- /**
- * Determines if a given element is the "Block account" button based on its text content.
- * @param {Element} element - The DOM element to check.
- * @returns {boolean} - True if it's the "Block account" button, else false.
- */
- function isBlockButton(element) {
- if (!element) return false;
- const blockButtonText = "Block account";
- return element.textContent.trim() === blockButtonText;
- }
- /**
- * Extracts the username from a post container.
- * @param {Element} postContainer - The post container element.
- * @returns {string|null} - The username or null if not found.
- */
- function getUsernameFromPost(postContainer) {
- if (!postContainer) return null;
- log('Attempting to extract username from post container.');
- // Attempt to find an <a> tag with href containing "/profile/"
- const usernameLink = postContainer.querySelector('a[href*="/profile/"]');
- if (usernameLink) {
- const href = usernameLink.getAttribute('href');
- const parts = href.split('/');
- const username = parts[parts.length - 1] || null;
- if (username) {
- log(`Extracted username: ${username}`);
- return username.toLowerCase(); // Ensure lowercase for consistency
- }
- }
- // Alternative method: Look for a span containing "@" symbol
- const possibleUsernameElements = postContainer.querySelectorAll('span, div');
- for (let el of possibleUsernameElements) {
- const text = el.textContent.trim();
- if (text.startsWith('@')) { // Look for text starting with "@"
- const username = text.substring(1); // Remove "@" symbol
- log(`Extracted username from span: ${username}`);
- return username.toLowerCase(); // Ensure lowercase for consistency
- }
- }
- log('Username could not be extracted from the post.');
- return null;
- }
- /**
- * Hides all posts from the specified username.
- * @param {string} username - The username whose posts should be hidden.
- */
- function hidePostsFromUser(username) {
- if (!username) return;
- log(`Hiding posts from user: @${username}`);
- // Define selectors based on post container identification
- const selector = `div[role="link"][tabindex="0"], div[role="article"], section[role="article"]`;
- const posts = document.querySelectorAll(selector);
- let hiddenCount = 0;
- posts.forEach(post => {
- const postUsername = getUsernameFromPost(post);
- if (postUsername && postUsername === username) {
- post.style.display = 'none';
- log(`Post from @${username} has been hidden.`);
- hiddenCount++;
- }
- });
- log(`Total posts hidden from @${username}: ${hiddenCount}`);
- }
- /**
- * Adds a username to the blocked list and hides their posts.
- * @param {string} username - The username to block.
- */
- function addBlockedUser(username) {
- if (!username) return;
- hidePostsFromUser(username);
- }
- /**
- * Hides all posts from blocked users.
- * (This function is now redundant since we're not maintaining a blocked users list.)
- */
- function hidePostsFromBlockedUsers() {
- // No longer needed as we're not maintaining a blocked users list.
- // Removed to streamline the script.
- }
- /**
- * Initializes the script by hiding posts from blocked users.
- * (This function is now redundant since we're not maintaining a blocked users list.)
- */
- function initializeBlockedUsers() {
- // No longer needed as we're not maintaining a blocked users list.
- // Removed to streamline the script.
- // Optionally, if you still want to hide posts immediately after blocking without relying on storage,
- // you can keep any necessary logic here.
- }
- /**
- * Sets up the listener for the "Three Dots" (Post Options) button to capture the username.
- */
- function setupPostOptionsListener() {
- document.addEventListener('click', function(event) {
- let target = event.target;
- // Traverse up the DOM tree to check if a "Three Dots" button was clicked
- while (target && target !== document.body) {
- if (isPostOptionsButton(target)) {
- log('"Three Dots" button clicked.');
- // Find the post container associated with this button
- const postContainer = target.closest('div[role="link"][tabindex="0"], div[role="article"], section[role="article"]');
- if (postContainer) {
- const username = getUsernameFromPost(postContainer);
- if (username) {
- currentUsername = username;
- log(`Current post's username set to: @${username}`);
- } else {
- log('Username could not be determined from the post.');
- currentUsername = null;
- }
- } else {
- log('Post container not found.');
- currentUsername = null;
- }
- break; // Exit once handled
- }
- target = target.parentElement;
- }
- }, true); // Use capture phase
- }
- /**
- * Sets up the listener for the "Block account" button within the menu to handle confirmation.
- */
- function setupBlockButtonListener() {
- document.addEventListener('click', function(event) {
- let target = event.target;
- // Traverse up the DOM tree to check if a "Block account" button was clicked
- while (target && target !== document.body) {
- if (isBlockButton(target)) {
- log('"Block account" button clicked.');
- // Do NOT hide posts here; wait for confirmation
- // The hiding will be handled in the confirmation dialog listener
- break; // Exit once handled
- }
- target = target.parentElement;
- }
- }, true); // Use capture phase
- }
- /**
- * Sets up a listener for the confirmation button to add the user to the blocked list and hide their posts.
- */
- function setupConfirmationButtonListener() {
- document.addEventListener('click', function(event) {
- const target = event.target;
- // Check if the clicked element or its parent has data-testid="confirmBtn"
- const confirmBtn = target.closest('button[data-testid="confirmBtn"]');
- if (confirmBtn) {
- log('Confirmation button clicked.');
- if (currentUsername) {
- addBlockedUser(currentUsername);
- currentUsername = null;
- } else {
- log('No user recorded for blocking.');
- }
- }
- }, true); // Use capture phase
- }
- /**
- * Utility function to debounce frequent function calls.
- * @param {Function} func - The function to debounce.
- * @param {number} delay - The delay in milliseconds.
- * @returns {Function} - The debounced function.
- */
- function debounce(func, delay) {
- let timeout;
- return function(...args) {
- clearTimeout(timeout);
- timeout = setTimeout(() => func.apply(this, args), delay);
- };
- }
- /**
- * Initializes the script by setting up listeners.
- */
- function init() {
- setupPostOptionsListener();
- setupBlockButtonListener();
- setupConfirmationButtonListener();
- // initializeBlockedUsers(); // No longer needed
- log('Bluesky Auto Hide Blocked Posts script has been initialized.');
- }
- /**
- * Waits for the DOM to be fully loaded before initializing the script.
- */
- function waitForDOM() {
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', () => {
- setTimeout(init, 500); // Slight delay to ensure all elements are loaded
- });
- } else {
- setTimeout(init, 500);
- }
- }
- // Start the script
- waitForDOM();
- })();