facebook - ad block v3

Hides sponsored posts in FB's news-feed

当前为 2021-09-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         facebook - ad block v3
// @version      3.02
// @description  Hides sponsored posts in FB's news-feed
// @author       zbluebugz
// @match        https://*.facebook.com/*
// @-icon         https://www.google.com/s2/favicons?domain=facebook.com
// @-icon64URL    https://www.google.com/s2/favicons?domain=facebook.com
// @run-at       document-idle
// @namespace https://greasyfork.org/users/812551
// ==/UserScript==
/*
  Comments:
    original: https://pastebin.com/raw/vmaiA8jJ
    05/09/2021: FB has changed the way sponsored posts are marked - made harder to detect
                - this script detects the new way.
    06/09/2021: Detected a slight variation of the new way - amended code to cope with that.
*/

(function () {
    'use strict';

    var title = 'facebook - ad block';

    // sponsered posts' keyword(s)
    // - if more than one keyword, use this format: ['keyword 1', 'keyword 2']
    var SPONSORED_WORDS = ['Sponsored'];

    // hide various suggested items (often flagged as sponsored posts - not all the time)
    // var suggestions = ['Shop Now', 'Learn More', 'Sign Up', 'Download', 'Get Offer', 'Apply Now', 'Book Now', 'Play Game', 'Get Quote'];
    var suggestions = ['Shop Now', 'Sign Up', 'Download', 'Get Offer', 'Book Now', 'Play Game', 'Get Quote'];

    // hide / highlight the selected posts
    let HIDE_STYLE = (true) ? 'display:none !important' : 'border:3px solid yellow !important';

    // hide certain elements ...
    const TOGGLE_SUGGESTED_CONTENT = false;
    const TOGGLE_SUGGESTED_EVENTS = false;
    const TOGGLE_SUGGESTED_GROUPS = false;
    const TOGGLE_CREATE_ROOM = true;
    const TOGGLE_PEOPLE_YOU_MAY_KNOW = true;
    const TOGGLE_SUGGESTED_PAGES = true ;
    const TOGGLE_PAID_PARTNERSHIP = true;
    const TOGGLE_BLUE_NAVBAR = false;

    if(TOGGLE_SUGGESTED_CONTENT) 	suggestions.push('Suggested for you');
    if(TOGGLE_SUGGESTED_EVENTS) 	suggestions.push('Suggested Events');
    if(TOGGLE_PEOPLE_YOU_MAY_KNOW) 	suggestions.push('People you may know');
    if(TOGGLE_SUGGESTED_PAGES) 	 	suggestions.push('Suggested Pages');
    if(TOGGLE_PAID_PARTNERSHIP) 	suggestions.push('Paid partnership');
    if(TOGGLE_SUGGESTED_GROUPS)	 	suggestions.push('Suggested groups');

    // how often to run this script
    const CHECK_RATE_MS = 100;

    function hide(el) {
        return el.setAttribute('style',HIDE_STYLE);
    };

    function doChanges() {

        if(TOGGLE_BLUE_NAVBAR){
            var navbar = document.querySelector('div[aria-label="Facebook"]');
            if(navbar) navbar.setAttribute('style','background-color:#3b5998 !important');
        };

        if(TOGGLE_CREATE_ROOM){
            var create_room = document.querySelector('div[data-pagelet="VideoChatHomeUnitNoDDD"]');
            if(create_room) hide(create_room);
        };

        function findSponsoredPosts() {
            // get collection of posts, ignore those already read by this script.
            let posts = Array.from(
                document.querySelectorAll('div[data-pagelet*=FeedUnit]:not([adbpr])')
                // next line for use in debugging - ignores the posts that have been already processed.
                //document.querySelectorAll('div[data-pagelet*=FeedUnit]')
            );
            // loop through each post to see if it is a sponsored one or not
            let hidePosts = [];
            posts.forEach(
                post => {
                    // flag this post as not to be read again
                    post.setAttribute('adbpr', true);
                    // within this unread post, find the SPAN element(s) having aria-label = Sponsored
                    // (usually only one is found)
                    let alSpans = Array.from(post.querySelectorAll('span[aria-label="Sponsored"]'));
                    // is the word "Sponsored" visible?
                    // - there are several spans having single letters - all randomised, but will make up "sponsored" when certain span tags are "visible".
                    alSpans.forEach(sp => {
                        let daText = '';
                        /*let nsp = sp.nextSibling.firstChild; */
                        let nsp = sp.nextSibling;
                        if (nsp.tagName === "SPAN") {
                            if (!nsp.style.top) {
                                // visible SPANs do not have a TOP value.
                                daText += nsp.innerText.charAt(0);
                            }
                        }
                        nsp = nsp.firstChild;
                        
                        do {
                            if (nsp.tagName === "SPAN") {
                                if (!nsp.style.top) {
                                    // visible SPANs do not have a TOP value.
                                    daText += nsp.innerText.charAt(0);
                                }
                            }
                            nsp = nsp.nextSibling;
                        } while (nsp);
                        // console.info("--sp:", daText, WORD_SPONSORED.indexOf(daText));
                        if (SPONSORED_WORDS.indexOf(daText) > -1 ) {
                            //console.info("-- sp pushing:", sp);
                            hidePosts.push(sp)
                        }
                    });

                    // suggestions
                    if (suggestions) {
                        // scan the a tags
                        let els = Array.from(post.querySelectorAll('a'));
                        let skip = false;
                        for (let x = 0; x < els.length; x++) {
                            if (suggestions.includes(els[x].textContent)) {
                                hidePosts.push(els[x]);
                                skip = true;
                                break;
                            }
                        };
                        // scan the span tags
                        if (!skip) {
                            els = Array.from(post.querySelectorAll('span'));
                            for (let x = 0; x < els.length; x++) {
                                if (suggestions.includes(els[x].textContent)) {
                                    hidePosts.push(els[x]);
                                    break;
                                }
                            }
                        }
                    }
                }
            );
            return hidePosts
        };

        function kill(element) {
            try {
                if(element) {
                    var limit = 0;
                    while(limit++ < 100) {
                        if(typeof element.getAttribute('data-pagelet') == "string")
                        {
                            if(element.getAttribute('data-pagelet').contains('FeedUnit'))
                            {
                                hide(element);
                                return;
                            };
                        };
                        element = element.parentNode;
                    };
                };
            } catch (e) {
            };
        };

        findSponsoredPosts().forEach( e => kill(e) );

    };

    const callback = function () {
        try {
            doChanges();
        } catch (e) {
            console.warn(title, e);
        }
    };

    setInterval(callback, CHECK_RATE_MS);
})();