Skip to content

Instantly share code, notes, and snippets.

@penk
Created January 8, 2025 03:00
Show Gist options
  • Save penk/1e66baba614f2c002bafb453a19153c1 to your computer and use it in GitHub Desktop.
Save penk/1e66baba614f2c002bafb453a19153c1 to your computer and use it in GitHub Desktop.
Block unwanted post on facebook
// Helper to find parent element matching a condition
function findParentMatching(element, condition, maxDepth = 10) {
let current = element;
let depth = 0;
while (current && depth < maxDepth) {
if (condition(current)) {
return current;
}
current = current.parentElement;
depth++;
}
return null;
}
// Helper to find exactly "Follow" buttons
function findFollowButtons() {
// Find spans containing exactly "Follow"
const followSpans = Array.from(document.querySelectorAll('span')).filter(
(span) => span.textContent.trim() === 'Follow'
);
// Get their button parents
const followButtons = followSpans
.map((span) => findParentMatching(span, (el) => el.getAttribute('role') === 'button'))
.filter(Boolean);
console.log(`Found ${followButtons.length} Follow buttons`);
return followButtons;
}
function findMenuButton(followButton) {
let current = followButton;
let depth = 0;
while (current && depth < 20) {
// Does this container have the 3-dot menu inside it?
const menuButton = current.querySelector('div[aria-label="Actions for this post"]');
if (menuButton) {
return menuButton;
}
current = current.parentElement;
depth++;
}
console.log('Could not find menu button');
return null;
}
// Function to wait for and find a menu item by partial or exact text
async function findMenuItem(text, timeout = 3000) {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
// Look for menu items containing the text
const items = Array.from(document.querySelectorAll('div[role="menuitem"]')).filter((item) =>
item.textContent.includes(text)
);
if (items.length > 0) {
return items[0];
}
// Wait a bit before trying again
await new Promise((resolve) => setTimeout(resolve, 100));
}
return null;
}
// Function to block a post
async function blockPost(followButton) {
try {
console.log('Starting to process post...');
// Find and click menu button
const menuButton = findMenuButton(followButton);
if (!menuButton) {
console.log('❌ Could not find the 3-dot menu for this post');
return false;
}
console.log('Found menu button, clicking...');
menuButton.click();
// Find and click "Not interested"
console.log('Looking for Not interested option...');
const notInterestedButton = await findMenuItem('Not interested');
if (!notInterestedButton) {
console.log('❌ Could not find "Not interested" option in the menu');
return false;
}
console.log('Clicking Not interested...');
notInterestedButton.click();
// Find and click "Block" or "Block profile"
console.log('Looking for Block profile option...');
// The text might be "Block" or "Block profile" or "Block X", so we’ll try "Block"
const blockButton = await findMenuItem('Block');
if (!blockButton) {
console.log('❌ Could not find Block/Block Profile option in the menu');
return false;
}
console.log('Clicking Block profile...');
blockButton.click();
console.log('🚫 Successfully blocked profile');
return true;
} catch (error) {
console.error('Error blocking post:', error);
return false;
}
}
// Main monitoring function
async function monitorPosts() {
console.log('🔎 Starting Facebook post blocker...');
// Process any found posts
async function processNewPosts() {
const followButtons = findFollowButtons();
for (const button of followButtons) {
console.log('Processing a post with Follow button...');
const blocked = await blockPost(button);
if (blocked) {
console.log('✅ Successfully blocked post');
} else {
console.log('❌ Failed to block post');
}
// Wait between processing posts
await new Promise((resolve) => setTimeout(resolve, 2000));
}
}
// Create observer for new content (so if FB loads more posts, we can re-scan)
const observer = new MutationObserver((mutations) => {
let hasNewContent = false;
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
hasNewContent = true;
}
});
});
if (hasNewContent) {
// Wait a bit for DOM to settle, then re-process
setTimeout(processNewPosts, 1500);
}
});
// Start observing
const mainContent = document.querySelector('[role="main"]') || document.body;
observer.observe(mainContent, {
childList: true,
subtree: true,
});
// Process existing posts
await processNewPosts();
return observer;
}
// Start monitoring
const observer = monitorPosts();
window.fbMonitor = observer;
// To stop monitoring later, type in console:
// window.fbMonitor.disconnect();
console.log(
'%c✅ Paste successful! Facebook Post Blocker is now running.',
'color: #fff; background: green; padding:4px;'
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment