您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically skip URLs that have been previously skipped and click "Next" if Instagram content is detected on Facebook Reels. Displays total skipped reels count in a popup and allows exporting skipped URLs to a text file using IndexedDB for storage.
- // ==UserScript==
- // @name Remove & perma block instagram reels from Facebook
- // @namespace IG GONE
- // @version 1.2
- // @description Automatically skip URLs that have been previously skipped and click "Next" if Instagram content is detected on Facebook Reels. Displays total skipped reels count in a popup and allows exporting skipped URLs to a text file using IndexedDB for storage.
- // @author Projekt Darkside - Brno city Bohemia
- // @match https://www.facebook.com/*
- // @grant none
- // ==/UserScript==
- (async function() {
- 'use strict';
- const reelDurationMinutes = 2;
- let db;
- // Vícejazyčná podpora pro tlačítko "Další karta"
- const multilangNextButton = {
- 'en': 'Next card',
- 'cs': 'Další karta',
- 'sk': 'Ďalšia karta',
- 'fr': 'Carte suivante',
- 'es': 'Siguiente tarjeta',
- 'de': 'Nächste Karte',
- 'it': 'Prossima carta',
- 'pt': 'Próximo cartão',
- 'ru': 'Следующая карта',
- 'ja': '次のカード',
- };
- // Vícejazyčná podpora pro text v badge
- const multilangBadgeText = {
- 'en': 'Skipped (count) IG reels, this script saved you (time) minutes.',
- 'cs': 'Přeskočeno (count) IG reelů, tento skript vám ušetřil (time) minut.',
- 'sk': 'Preskočených (count) IG reelov, tento skript vám ušetril (time) minút.',
- 'fr': '(count) IG reels ignorés, ce script vous a fait gagner (time) minutes.',
- 'es': 'Saltado (count) IG reels, este script te ahorró (time) minutos.',
- 'de': '(count) IG-Reels übersprungen, dieses Skript hat Ihnen (time) Minuten gespart.',
- 'it': 'Saltato (count) IG reels, questo script ti ha fatto risparmiare (time) minuti.',
- 'pt': 'Ignorado (count) IG reels, este script te poupou (time) minutos.',
- 'ru': 'Пропущено (count) IG рилов, этот скрипт сэкономил вам (time) минут.',
- 'ja': 'スキップされた (count) IGリール、このスクリプトはあなたの時間を (time) 分節約しました。',
- };
- async function openDatabase() {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open('InstagramReelsDB', 1);
- request.onupgradeneeded = function(event) {
- db = event.target.result;
- if (!db.objectStoreNames.contains('skippedURLs')) {
- db.createObjectStore('skippedURLs', { keyPath: 'url' });
- }
- };
- request.onsuccess = function(event) {
- db = event.target.result;
- resolve(db);
- };
- request.onerror = function(event) {
- reject('Error opening database: ' + event.target.errorCode);
- };
- });
- }
- async function saveSkippedURL(url) {
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(['skippedURLs'], 'readwrite');
- const objectStore = transaction.objectStore('skippedURLs');
- const request = objectStore.add({ url: url });
- request.onsuccess = function(event) {
- updateSkippedCountBadge();
- resolve(event.target.result);
- };
- request.onerror = function(event) {
- if (event.target.error.name === 'ConstraintError') {
- resolve(false); // URL již existuje
- } else {
- reject('Error saving URL: ' + event.target.error);
- }
- };
- });
- }
- async function getSkippedURLs() {
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(['skippedURLs']);
- const objectStore = transaction.objectStore('skippedURLs');
- const request = objectStore.getAll();
- request.onsuccess = function(event) {
- resolve(event.target.result);
- };
- request.onerror = function(event) {
- reject('Error getting URLs: ' + event.target.error);
- };
- });
- }
- async function isURLSkipped(url) {
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(['skippedURLs']);
- const objectStore = transaction.objectStore('skippedURLs');
- const request = objectStore.get(url);
- request.onsuccess = function(event) {
- resolve(!!event.target.result);
- };
- request.onerror = function(event) {
- reject('Error checking URL: ' + event.target.error);
- };
- });
- }
- function getBadgeText(count, time) {
- let language = detectBrowserLanguage().split('-')[0];
- let template = multilangBadgeText[language] || multilangBadgeText['en'];
- return template.replace('(count)', count).replace('(time)', time);
- }
- async function updateSkippedCountBadge() {
- let skippedURLs = await getSkippedURLs();
- let count = skippedURLs.length;
- let savedTime = count * reelDurationMinutes;
- let badge = document.getElementById('skippedCountBadge');
- if (!badge) {
- badge = document.createElement('div');
- badge.id = 'skippedCountBadge';
- badge.style.cssText = 'position: fixed; bottom: 10px; left: 10px; background-color: #007bff; color: #fff; border-radius: 10px; padding: 10px; cursor: pointer; z-index: 9999;';
- badge.title = 'Celkový počet přeskočených Instagram Reels a ušetřený čas';
- badge.onclick = exportSkippedURLs;
- document.body.appendChild(badge);
- }
- badge.textContent = getBadgeText(count, savedTime);
- }
- function showAndAutoHideBadge() {
- let badge = document.getElementById('skippedCountBadge');
- if (badge) {
- badge.style.display = 'block';
- setTimeout(() => {
- badge.style.display = 'none';
- }, 4000);
- }
- }
- async function exportSkippedURLs() {
- let skippedURLs = await getSkippedURLs();
- let urls = skippedURLs.map(item => item.url);
- let blob = new Blob([urls.join('\n')], { type: 'text/plain' });
- let url = URL.createObjectURL(blob);
- let a = document.createElement('a');
- a.style.display = 'none';
- a.href = url;
- a.download = 'skipped_urls.txt';
- document.body.appendChild(a);
- a.click();
- window.URL.revokeObjectURL(url);
- }
- async function skipInstagramContent() {
- if (window.location.href.includes("/reel/")) {
- let isSkipped = await isURLSkipped(window.location.href);
- if (isSkipped) {
- let nextButton = findNextButton();
- if (nextButton) {
- nextButton.click();
- }
- return;
- }
- let foundInstagramContent = false;
- document.querySelectorAll('*').forEach(function(node) {
- if (node.offsetParent !== null && node.innerText && node.innerText.includes("Instagram")) {
- foundInstagramContent = true;
- }
- });
- document.querySelectorAll('img').forEach(function(img) {
- if (img.offsetParent !== null && img.src.includes('https://static.xx.fbcdn.net/rsrc.php/v3/yy/r/1M3EBv90kJA.png')) {
- foundInstagramContent = true;
- }
- });
- if (foundInstagramContent) {
- let nextButton = findNextButton();
- if (nextButton) {
- await saveSkippedURL(window.location.href);
- nextButton.click();
- }
- }
- }
- }
- function findNextButton() {
- let language = detectBrowserLanguage().split('-')[0];
- let ariaLabel = multilangNextButton[language];
- if (ariaLabel) {
- return document.querySelector(`[aria-label="${ariaLabel}"]`);
- } else {
- return null;
- }
- }
- function detectBrowserLanguage() {
- return navigator.language || navigator.userLanguage || 'en';
- }
- window.addEventListener('load', async () => {
- await openDatabase();
- await updateSkippedCountBadge();
- });
- window.addEventListener('beforeunload', async () => {
- await updateSkippedCountBadge();
- });
- const observer = new MutationObserver(skipInstagramContent);
- observer.observe(document.body, { childList: true, subtree: true });
- skipInstagramContent();
- })();