Modificando facebook con una extensión de chrome

freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
436
Nota:
Éste es un post recopilatorio acerca de como modifiqué Facebook para mis propios fines. No pretende ser un tutorial para nada.

No puedo decir que me gustan las redes sociales.
Son adictivas, las personas se compontan como animales virtuales, hay funas a la orden del día, y te muestran una cantidad innecesaria de información.

Lamentablemente Facebook me reporta buenos ingresos últimamente como para ignorarlo.

Así que, ¿por qué no hacer de facebook un lugar agradable y llevadero para el día a día?

Marketplace

Primero me propuse eliminar los anuncios del marketplace para vitrinear alguna que otra cosa tranquilo.

JavaScript:
if (/\/marketplace\//g.test(document.location.pathname)) {
    let products = [];
    // Query marketplace products for remove
    document.querySelector('div.x1xfsgkm.xqmdsaz.x1t9mz0v.x1mtsufr.x1w9j1nh')
        .querySelectorAll('div.x9f619.x78zum5.x1r8uery')
        .forEach(e => {
        let a = e.querySelector('a');
        if (
            a !== null && (
                !/web\.facebook\.com/g.test(a.href)
                || /permalink\.php/g.test(a.href)
                || /\=app\_tab\#/g.test(a.href)
                || /l\.php\?u\=/g.test(a.href)
            )
        ) {
            if (e !== null && e.parentNode !== null)
                e.parentNode.removeChild(e)
        }
    });

    // Query marketplace product titles for remove
    document.querySelector('div.x1xfsgkm.xqmdsaz.x1t9mz0v.x1mtsufr.x1w9j1nh')
        .querySelectorAll('div.x1pha0wt.x78zum5.x1r8uery')
        .forEach(e => {
        let a = e.querySelector('a');
        if (a !== null && /\/ads\/about/g.test(a.href)) {
            e.parentNode.removeChild(e)
        }
    });

}

Anuncios

Esto fue lo mas dificil, pero curiosamente el shadow doom no logró su cometido, en cambio, todos los anuncios del home los pude detectar por el css que llevan embebido :clap
JavaScript:
let panel = document.querySelector('div.x9f619.x1n2onr6.x1ja2u2z.x78zum5[role=main]');
if (panel !== null) {
    panel.querySelectorAll('div.x1yztbdb.x1n2onr6.xh8yej3')
        .forEach(div => {
        div.querySelectorAll('a[role=link]')
            .forEach(a => {
            if (/facebook\.com\/\#/g.test(a.href)) {
                a.querySelectorAll('*')
                    .forEach(e => {
                    if (/[a-z]*\-[a-z]*/gi.test(e.tagName)) {
                        e.querySelectorAll('svg').forEach(svg => {
                            if (svg.getAttribute('style') == 'height: 14px; overflow: visible; width: 55.375px;') {
                                if (div !== null && div.parentNode !== null) {
                                    div.parentNode.removeChild(div);
                                }
                            }
                        });
                    }
                });
            }
        })
    });
}

Reels e Historias

Luego le llegó el turno a los reels e historias, tanto en el header del home como las intermedias, nada muy complejo de hacer.

JavaScript:
// Remove header history & reels
let container = document.querySelector('div.x78zum5.x1q0g3np.xl56j7k.x1yztbdb.x1y1aw1k');
if (container !== null)
    container.parentNode.removeChild(container);

// Remove intermedium Reels
document.querySelectorAll('div.x1lliihq')
    .forEach(div => {
    div.querySelectorAll('span').forEach(span => {
        if (/Reels/g.test(span.innerText)) {
            if (div !== null && div.parentNode !== null)
                div.parentNode.removeChild(div);
        }
    })
});

Panel derecho del home

Otra cosa fue remover el panel derecho al que le doy 0 uso.

Código:
let panel = document.querySelector('div[role="complementary"]');
if (panel !== null && panel.parentNode !== null)
    panel.parentNode.removeChild(panel);

Funas

Que wea mas desagradable por la xuxa, como las odio, no me podía quedar tranquiley sin eliminarlas de mi vista. Así que me hice un util para sacar publicaciones según palabras clave.

JavaScript:
let text = 'funa';
let panel = document.querySelector('div.x9f619.x1n2onr6.x1ja2u2z.x78zum5[role=main]');
       
if (panel !== null) {
    panel.querySelectorAll('div.x1yztbdb.x1n2onr6.xh8yej3')
        .forEach(div => {
        if ((new RegExp(text, 'ig')).test(div.innerText)) {
            if (div !== null && div.parentNode !== null)
                div.parentNode.removeChild(div);
        }
    });
}

Competencia

Por último la competencia... no es que me moleste ver post de la competencia, pero me agradaría mas si solo pudiera ver post de la clientela. Para ello tuve que hacer 2 cosas, primero exponer visiblemente los id de los usuarios que publican, y segundo, filtrar publicaciones por id de usuario.

JavaScript:
let panel = document.querySelector('div[role=feed]');
if (panel !== null) {
    panel.querySelectorAll('div.x1yztbdb.x1n2onr6.xh8yej3.x1ja2u2z')
        .forEach(div => {
        div.querySelectorAll('a').forEach(a => {
            if (/\/user\/[0-9]*\/*/g.test(a.href)) {
                if (div.querySelectorAll('span.user-id').length == 0) {
                    let userId = a.href.split('user/')[1].split('/?')[0];

                    let divId     = document.createElement('div');
                    let spanTitle = document.createElement('span');
                    let spanId    = document.createElement('span');

                    divId.appendChild(spanTitle);
                    divId.appendChild(spanId);

                    divId.style.marginBottom = '10px';

                    spanTitle.innerText = 'User Id: ';
                    spanTitle.style.color = '#FAFAFA';
                    spanTitle.style.fontWeight = 'bold';
                    spanTitle.style.fontSize = '16px';

                    spanId.innerText = userId;
                    spanId.style.color = '#FAFAFA';
                    spanId.style.fontSize = '16px';
                    spanId.classList.add('user-id');

                    div.prepend(divId);
                }
            }
        });
    });
}
JavaScript:
let users = [];
let panel = document.querySelector('div[role=feed]');
if (panel !== null) {
    panel.querySelectorAll('div.x1yztbdb.x1n2onr6.xh8yej3.x1ja2u2z')
        .forEach(div => {
        div.querySelectorAll('a').forEach(a => {
            if (/\/user\/[0-9]*\/*/g.test(a.href)) {
                let userId = a.href.split('user/')[1].split('/?')[0];
                if (users.includes(userId) && div !== null && div.parentNode !== null) {
                    div.parentNode.removeChild(div);
                }
            }
        });
    });
}

Observadores
Lo único que me faltaba en este punto era agregar la observación de los métodos para que detectaran el contenido dinámico. Ésto se soluciona con programar la próxima ejecución con setTimeout a 100/200 ms.

Ahora si por la rechucha... Facebook es un lugar mucho mas agradable...
Quizá lo único que me faltó es quitare esos colores asquerosos que tiene y dejar todo mas agradable a la vista.
Pero bue...

PD: de repente salta el debugger interno de Facebook y termina su ejecución, nada que no se arregle recargando la página...
PD2: me pregunto si detectarán eventualmente que no estoy visualizando anuncios :circulos
 

MaxSF

Capo
Se incorporó
17 Julio 2009
Mensajes
388
No uso Facebook, pero qué trabajo tan minucioso y maravilloso hiciste. Suena a que recién ahora es un sitio utilizable gracias a tus cambios.
 
Upvote 0

freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
436
Que extensión de chrome estás usado?

Saludos
Ninguna de la store, hice una propia para meter las funciones usando manifest v3, a través de un content script.


JSON:
{
  "manifest_version": 3,
  "name": "EXTENSION NAME HERE",
  "description": "DESCRIPTION HERE",
  "version": "1.0",
  "action": {
    "default_popup": "popup.html",
    "default_icon": "ico.png"
  },
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "host_permissions": [
    "https://web.facebook.com/*"
  ],
  "content_scripts": [
    {
        "js": ["js/script.js"],
        "matches": [
            "https://web.facebook.com/*"
        ]
    }
  ],
  "web_accessible_resources": [
    {
      "resources": ["users-id.txt"],
      "matches": ["https://web.facebook.com/*"]
    }
  ]
}

popup.html está vacío.
El truco para que todo funcione es dejar todas las funciones como observadoras usando setTimeout a 100 o 200 ms, según soporte el ordenador.
users-id es un archivo de texto que almacena los id de los usuarios para que la extension valla borrando sus publicaciones.

users-id.txt

Código:
USER-ID
USER-ID
USER-ID
...

Se accesa así desde el interior del content script:

JavaScript:
async () => {
    const url = chrome.runtime.getURL('users-id.txt');
    const r = await fetch(url);
    let list = await r.text();
    list = list.split('\n');
    return list;
}
 
Última modificación:
Upvote 0
Subir