Greasy Fork

Greasy Fork is available in English.

Facebook remove suggested sponsored ads blocks

Remove suggested/sponsored blocks from Facebook

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name Facebook remove suggested sponsored ads blocks
// @version 1.20.13
// @description Remove suggested/sponsored blocks from Facebook
// @author Sly_North
// @match https://www.facebook.com/*
// @exclude https://www.facebook.com/*/about
// @exclude https://www.facebook.com/login/*
// @exclude https://www.facebook.com/groups/*
// @exclude https://www.facebook.com/privacy/*
// @exclude https://www.facebook.com/photo/*
// @exclude https://www.facebook.com/settings/*
// @exclude https://www.facebook.com/marketplace/*
// @exclude https://www.facebook.com/*/about
// @exclude https://www.facebook.com/*/photos
// @exclude https://www.facebook.com/*/friends
// @namespace http://greasyfork.icu/en/users/759669-sly-north
// @license MIT
// @grant none
// @icon https://www.facebook.com/favicon.ico
// @run-at document-start
// ==/UserScript==

console.log('Start RemoveAllSponsored Facebook');

const maxPostHeight = 800;
const maxMessageLog = 300;

// Rebuild texts that are scrambled, like "Sponsored" where each letter is in a different div, which are not present in the word letter order.
function getVisibleContent(e) {
  var t = e.innerText.replaceAll("\n","");
 
  var children = e.childNodes;
  while (children.length == 1) children = children[0].childNodes;
  var spanBottom = e.getBoundingClientRect().bottom;
  children = Array.from(children).filter((c) => c.getBoundingClientRect && c.getBoundingClientRect().top <= spanBottom);
  var a = [];
  for (var c of children) {
    var order = getComputedStyle(c).order;
    if (order && window.getComputedStyle(c).display !== 'none') {
      a[order] = c.innerText;
      // console.log(c.style.order,'=',c.innerText, ' y=',c.getBoundingClientRect().top,' vs span.bottom=', spanBottom);
    }
  }
  if (a.length == 0) a = t.split();
  var intext = a.join().replaceAll(",","").replaceAll("\n","");
  // if (a.length > 0) console.log('Array = ', intext, ' -OR- ', a.join().replaceAll(",","").replaceAll("\n",""));
  if (intext == "") intext = t;
  return intext;
}

function getWholePost(e, maxParentHeightDiff = 150) {
  let parent = e.parentElement.parentElement.parentElement.parentElement;
  let h = parent.getBoundingClientRect().height;
  if (h > maxPostHeight) return null;
  while (h < 90) {
    parent = parent.parentElement;
    h = parent.getBoundingClientRect().height;
  }
  let h2 = 0;
  const postMaxWidth = window.innerWidth*0.8;
  while (true) {
    if (!parent.parentElement) { console.warn('Err: element has no parent H=', parent.getBoundingClientRect().height); break; }
    const parentBR = parent.parentElement.getBoundingClientRect();
    h2 = parentBR.height;
    if (h2 > maxPostHeight || h2 - h > maxParentHeightDiff) break;
    if (parentBR.width > postMaxWidth && parentBR.height > window.innerHeight/2) {
      const br = e.getBoundingClientRect();
      console.log('- Fb ads - Could not find parent, was selecting whole screen from elt tag=', e.tagName, ' w=', br.width, ' h=', br.height);
      e.style.display = "block"; // Prevent this script from running again on this element. 
      return null;
    }
    parent = parent.parentElement;
    h = h2;
  }
  return parent;
}

function removeElement(type, e, parent) {
  const height = parent.getBoundingClientRect().height;
  if (height === 0 || height > maxPostHeight) {
    console.log('- Fb ads - could not find parent for ', type, ' tag= ', parent.tagName, ' H=', height, ' ', e.innerText.substring(0, maxMessageLog).replaceAll('\n',''));
    return;
  }
  console.log('- Fb ads ', type, ' tag=', parent.tagName, ' H=', height, ' ',
              parent.innerText.replaceAll("\n"," ").replaceAll(/Facebook  *Facebook  */g, ""), ' from ', e.innerText.substring(0, maxMessageLog).replaceAll('\n',''));
  e.style.display = "none";
  parent.style.display = "none";
  // e.style.display = "block"; parent.style.display = "block"; parent.style.background = "red"; // Debug - in red instead of hidden
}

function RemoveAllSponsored()
{
  setTimeout(RemoveAllSponsored, 750);

  // Remove top right corner ads
  for (let e of Array.from(document.getElementsByTagName('h3')).filter((e) => {
    const br = e.getBoundingClientRect();
    return br.top < 150 && br.left > window.innerWidth*0.6 && br.width > 200 && br.width < 500 && br.height > 10 && br.height < 100;
  })) {
    let parent = e.parentElement.parentElement.parentElement;
    while (parent.parentElement.getBoundingClientRect().height < 500) parent = parent.parentElement;
    if (parent && parent.getBoundingClientRect().height > 200) {
      console.log('- Removing Fb top right ads - bounding rect: ', parent.getBoundingClientRect());
      // parent.style.background = 'red';
      parent.innerHTML = "";
    }
  }

  // Remove the "suggestion" posts
  if (document.URL.match(/facebook.com\/*(\?.*)*/)) {
    for (tag of ['a', 'use']) {
      const maybeAds = Array.from(document.getElementsByTagName(tag)).filter(e => {
        const br = e.getBoundingClientRect();
        return !e.style.display &&  // Already filtered-out
          // e.innerText === '' && // Content must be hidden in shadow block
          br.left < window.innerWidth*0.7 && // Comment in photo view
          br.left > window.innerWidth/2 && br.width > 60 && br.width < 200 && br.top > 100;
      });
      for (let e of maybeAds) {
        const parent = getWholePost(e);
        if (!parent) { console.log(' - Fb ads sponsored element: parent element not found!'); continue; }
        if (parent.innerText.match(/Create new account/) || parent.innerText.match(/shared a memory/)) continue;
        removeElement('sponsored post', e, parent);
      }
    }

    // "Learn more" suggestions
    const maybeAds = Array.from(document.getElementsByTagName('span')).filter(e => e.textContent === 'Learn more');
    for (let e of maybeAds) {
      const parent = getWholePost(e);
      if (!parent) { console.log(' - Fb ads sponsored element: parent element not found!'); continue; }
      removeElement('learn more', e, parent);
    }
  }

  // Unwanted elements
  var elts = Array.from(document.getElementsByTagName('span'));
  elts = elts.filter((e) => {var br = e.getBoundingClientRect(); return !e.style.display && br.bottom >= 0 && br.top <= window.innerHeight + 1000 && !e.style.display});
  elts = elts.filter((e) => {
    const t = e.innerText;
    const br = e.getBoundingClientRect();
    if (br.height === 0) return false;
    return t === 'Suggested for you' || t === 'Remember Password' || t === 'Reels and short videos' || t === 'Reels 和短视频' || t === 'Suggested for you' || t === 'People You May Know' ||
       t.match(/groups you might like/) || t.match(/groups suggested just for you/) || t === 'Follow' || t === 'Join';
  });
  for (let e of elts) {
    const parent = getWholePost(e);
    if (!parent) { console.log(' - Fb ads/block remover: parent element not found!'); continue; }
    const br = e.getBoundingClientRect();
    const parentBr = parent.getBoundingClientRect();
    if (br.height === 0 || parentBr.height > 1000 || br.top-parentBr.top > 500) { // Ignore post citing post
      // console.log(' - Fb ads/block: NOT removing tag=', e.tagName, ' H=', e.getBoundingClientRect().height, ' parent tag= ', parent.tagName, 'H=', parent.getBoundingClientRect().height, ' ', parent.innerText.replaceAll("\n", "  ").substring(0, 200));
      continue;
    }
    removeElement('ads/block', e, parent);
  }

  // Old Style - rare but still appears from time to time.
  var elts = Array.from(document.getElementsByTagName('span'));
  elts = elts.filter((e) => {
    var br = e.getBoundingClientRect();
    return e.parentElement.tagName === 'SPAN' && br.bottom >= 0 && br.top <= window.innerHeight + 1000 && !e.style.display
  });

  const keywords = [ /Sponsored/,/Commandvit/, /Sponsori/,/Reklamo/, /Publicid/,/Gesponser/, /Patrocinado/,/sugerisdos/, /贊助/, /RememberPassword/];
  var nbrSpans = elts.length;
  for (var i = elts.length - 1; i >= 0; --i)
  {
    var e = elts[i];
    var boundingRect = e.getBoundingClientRect();
    if (boundingRect.width == 0 || boundingRect.height == 0) continue; // Not visible

    var intext = getVisibleContent(e);
    if (intext.length > 0) for (k of keywords) {
      if (intext.match(k)) {
        let parent = e.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement
            .parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement;
        parent.style.display = "none";
        e.style.display = "none";
        ++nbrRemovedAds;
        console.log('- Removing Sponsored ads span', i, '[', parent.innerText.replaceAll("\n", "  ").substring(0, 200), '] matching ', k, ' at ', intext);
        break;
      }
    }
  }
}

setTimeout(RemoveAllSponsored, 1000);