Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instagram reels skip function here #69

Open
Dark3n89 opened this issue Jun 29, 2024 · 5 comments
Open

Instagram reels skip function here #69

Dark3n89 opened this issue Jun 29, 2024 · 5 comments

Comments

@Dark3n89
Copy link

I've been working on the removal script for a long time, it's almost unreal ... Here I made a function that automatically skips INSTAGRAM REELS and remembers "infected" url addresses, for the next faster rewind.
I like your project, you saved me a lot of time and I would like to return the favor :)
As a bonus, you can save the list of unwanted urls for future use when you click on the icon :)

`
// ==UserScript==
// @name Skip Instagram Content on Facebook Reels with URL Tracking
// @namespace Skip Instagram
// @Version 1.0
// @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.
// @author Projekt Darkside - Brno city Bohemia.
// @match https://www.facebook.com/*
// @grant none
// ==/UserScript==

(function() {
'use strict';

// Multilanguage support for "Next card" button
const multilangNextButton = {
    'en': 'Next card',
    'cs': 'Další karta',
    // Add more languages as needed
};

// Function to save skipped URL
function saveSkippedURL(url) {
    let skippedURLs = JSON.parse(localStorage.getItem('skippedURLs')) || [];
    if (!skippedURLs.includes(url)) {
        skippedURLs.push(url);
        localStorage.setItem('skippedURLs', JSON.stringify(skippedURLs));
        updateSkippedCountBadge(skippedURLs.length);
        showAndAutoHideBadge();
    }
}

// Function to get all skipped URLs
function getSkippedURLs() {
    return JSON.parse(localStorage.getItem('skippedURLs')) || [];
}

// Function to check if URL is skipped
function isURLSkipped(url) {
    let skippedURLs = getSkippedURLs();
    return skippedURLs.includes(url);
}

// Function to detect browser language
function detectBrowserLanguage() {
    return navigator.language || navigator.userLanguage || 'en';
}

// Function to update the skipped count badge
function updateSkippedCountBadge(count) {
    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: 50%; padding: 5px; cursor: pointer; z-index: 9999; display: none;';
        badge.title = 'Total skipped Instagram Reels';
        document.body.appendChild(badge);
    }
    badge.textContent = count;
}

// Function to show badge and automatically hide it after a short delay
function showAndAutoHideBadge() {
    let badge = document.getElementById('skippedCountBadge');
    if (badge) {
        badge.style.display = 'block';
        setTimeout(() => {
            badge.style.display = 'none';
        }, 4000); // Hide badge after 4 seconds
    }
}

// Function to export skipped URLs to a text file
function exportSkippedURLs() {
    let skippedURLs = getSkippedURLs();
    let blob = new Blob([skippedURLs.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);
}

function skipInstagramContent() {
    if (window.location.href.includes("/reel/")) {
        if (isURLSkipped(window.location.href)) {
            // If URL is already skipped, click on the "Next card" button
            let nextButton = findNextButton();
            if (nextButton) {
                console.log("Skipping already skipped URL:", window.location.href);
                nextButton.click();
            }
            return;
        }

        let foundInstagramContent = false;

        // Check visible elements containing the word "Instagram"
        document.querySelectorAll('*').forEach(function(node) {
            if (node.offsetParent !== null && node.innerText && node.innerText.includes("Instagram")) {
                console.log("Found Instagram content in text:", node);
                foundInstagramContent = true;
            }
        });

        // Check visible images containing the specified URL
        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')) {
                console.log("Found Instagram content in image:", img);
                foundInstagramContent = true;
            }
        });

        // If Instagram content is found, click on "Next card" and save URL
        if (foundInstagramContent) {
            let nextButton = findNextButton();
            if (nextButton) {
                console.log("Clicking next button:", nextButton);
                saveSkippedURL(window.location.href);
                nextButton.click();
            }
        }
    }
}

// Function to find the "Next card" button based on language
function findNextButton() {
    let language = detectBrowserLanguage().split('-')[0]; // Extract language code
    let ariaLabel = multilangNextButton[language];
    if (ariaLabel) {
        return document.querySelector(`[aria-label="${ariaLabel}"]`);
    } else {
        console.warn(`No translation found for language: ${language}`);
        return null;
    }
}

// Initialize check on page load
skipInstagramContent();

// Observe DOM changes and apply function to newly loaded posts
const observer = new MutationObserver(skipInstagramContent);
observer.observe(document.body, { childList: true, subtree: true });

})();
`

@Dark3n89
Copy link
Author

Allready working at pure extenssion... i have big problems with same seasson or localstorage load back. ..

image

@zbluebugz
Copy link
Owner

Userscript looks good - parts of it is likely to be implemented in fb-cmf.

re issue with storage: - Are you referring to the userscript or the extension?

If userscript,
FB will wipe out the "unauthorised" cookies and most storage options.

The following options would work:

  • Userscript manager's storage facility(restricted to that script - can't be shared with other scripts)
  • Indexed DB storage (not restricted to a particular userscript)

fb-cmf uses the Indexed DB option to store user's settings. Relies on the idb-keyval library to manage the storage. (https://unpkg.com/browse/[email protected]/README.md)

If extension,
In Firefox use this: browser.storage.local.set(...) / browser.storage.local.get(...)
In Chromium use this: chrome.storage.local.set(...) / chrome.storage.local.get(...)

In the extension, you might need the "permissions" option "unlimitedStorage" in the manifest.json file - this allows more than 5Mb of data to be stored.

@Dark3n89
Copy link
Author

Dark3n89 commented Jun 29, 2024 via email

@zbluebugz
Copy link
Owner

FYI, the indexedDB data is wiped out when the browser clears the cache.

I do note that sometimes the script stops working if db is not opened/ready.

Below is a suggestion on tweaking the code that detects IG content (you'll need to test it more):

// -- This html pattern occurs 1-2 times per reel post
const elements = Array.from(document.querySelectorAll('div > span[dir] > span > div'));
for (const node of elements) {
    if (node.offsetParent !== null && node.innerText && node.innerText.includes("Instagram")) {
        foundInstagramContent = true;
        break;
    }
};

if (foundInstagramContent === false) {
    // -- Try again, but query for a sprite image that has the IG icon
    // -- (do not specify the filename - fb has multiple copies with different filenames)
    // -- Has to be in a certain HTML structure/pattern that is unique to the IG reel posts
    foundInstagramContent = (document.querySelector('span > div > div > span > i[style*="background-image"]') !== null);
}

@Dark3n89
Copy link
Author

I am currently working on a version of a regular extension where everything works perfectly and holds the data until the user reloads the extension.

I experimented with an external database, in my new project the reels are destroyed immediately after loading the site even as suggestions.

But it will still take some time, I assume that the external database will help all people globally to get rid of ballast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants