Netflix Episode title and description Extractor

Extract episode number, title, and description from Netflix and save to file, with cookie handling

// ==UserScript==
// @name         Netflix Episode title and description Extractor
// @namespace    https://greasyfork.org/en/scripts/521575-netflix-episode-title-and-description-extractor
// @version      2.7
// @description  Extract episode number, title, and description from Netflix and save to file, with cookie handling
// @author       Your Name
// @match        https://www.netflix.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    console.log('Script loaded');

    // Function to clear all cookies
    function clearAllCookies() {
        const cookies = document.cookie.split("; ");
        for (const cookie of cookies) {
            const eqPos = cookie.indexOf("=");
            const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
            document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=.netflix.com`;
        }
        console.log('All cookies cleared');
    }

    // Function to inject a specific cookie
    function injectCookie() {
        document.cookie = "nfvdid=BQFmAAEBEIH1te_5mpKm6SCTdTtUHtNA1xa-MbxZd062DfWZ2g5DPjySYKsVjK8erVEsYMNgs76Uq9NhGzYx47l1Hn-YlpvFc4C4600kVvWtIkwlxu2d5Q%3D%3D; domain=.netflix.com; path=/";
        console.log('Cookie injected');
    }

    // Function to extract episode data
    function extractEpisodeData() {
        console.log('Extracting episode data...');
        const episodeContainers = document.querySelectorAll('li.episode');
        console.log('Episode containers found:', episodeContainers.length);
        const episodes = [];

        episodeContainers.forEach((container, index) => {
            console.log(`Processing episode ${index + 1}`);
            const episodeTitleElement = container.querySelector('h3.episode-title');
            const descriptionElement = container.querySelector('p.epsiode-synopsis'); // Corrected selector

            if (episodeTitleElement) {
                const fullTitle = episodeTitleElement.textContent.trim();
                console.log(`Episode ${index + 1} title element found: ${fullTitle}`);
                const match = fullTitle.match(/^(\d+)\.\s*(.+)$/);
                if (match) {
                    const episodeNumber = match[1];
                    const episodeTitle = match[2];

                    if (descriptionElement) {
                        console.log(`Episode ${index + 1} description element found: ${descriptionElement.textContent}`);
                        const description = descriptionElement.textContent.trim();

                        episodes.push({
                            episodeNumber,
                            episodeTitle,
                            description
                        });

                        // Debugging information for each episode
                        console.log(`Episode ${index + 1} data:`);
                        console.log(`Number: ${episodeNumber}`);
                        console.log(`Title: ${episodeTitle}`);
                        console.log(`Description: ${description}`);
                    } else {
                        console.log(`Episode ${index + 1} description element not found`);
                    }
                } else {
                    console.log(`Episode ${index + 1} title format not recognized: ${fullTitle}`);
                }
            } else {
                console.log(`Episode ${index + 1} title element not found`);
            }
        });

        return episodes;
    }

    // Display episodes in a popup
    function displayEpisodes(episodes) {
        console.log('Displaying episodes in a popup...');
        const popup = window.open('', '_blank', 'width=800,height=600');
        popup.document.write('<html><head><title>Episodes List</title></head><body>');
        popup.document.write('<h1>Episodes List</h1>');
        popup.document.write('<ul>');

        episodes.forEach(ep => {
            popup.document.write(`
                <li>
                    <h3>${ep.episodeTitle}</h3>
                    <p>${ep.description}</p>
                </li>
                <hr>
            `);
        });

        popup.document.write('</ul>');

        // Add the JSON download button
        popup.document.write(`
            <button id="downloadJson" style="
                padding: 10px 20px;
                background-color: #0c9;
                color: #fff;
                border: none;
                border-radius: 5px;
                cursor: pointer;
                font-size: 16px;
                margin-top: 20px;
            ">Download as JSON</button>
        `);

        popup.document.close();

        // Add JSON download functionality
        popup.document.getElementById('downloadJson').addEventListener('click', () => {
            const blob = new Blob([JSON.stringify(episodes, null, 2)], { type: 'application/json' });
            const link = popup.document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = 'episodes_titles.json';
            link.click();
        });
    }


    // Function to create the save button
    function createSaveButton() {
        console.log('Creating save button...');
        const saveButton = document.createElement('button');
        saveButton.textContent = 'Save Episode Data';
        saveButton.style.width = '100%';
        saveButton.style.padding = '10px';
        saveButton.style.margin = '10px 0';
        saveButton.style.backgroundColor = '#4CAF50';
        saveButton.style.color = 'white';
        saveButton.style.border = 'none';
        saveButton.style.borderRadius = '4px';
        saveButton.style.cursor = 'pointer';

        saveButton.addEventListener('click', () => {
            const episodes = extractEpisodeData();
                displayEpisodes(episodes); // Display episodes in a popup
        });

        const heroElement = document.getElementById('section-hero');
        if (heroElement) {
            heroElement.insertAdjacentElement('afterend', saveButton);
            console.log('Save button added after section-hero');
        } else {
            console.log('section-hero element not found');
        }
    }

    // Function to check for episode containers and handle cookies if not found
    function checkEpisodeContainers() {
        console.log('Checking for episode containers...');
        const episodeContainers = document.querySelectorAll('li.episode');
        if (episodeContainers.length === 0 && document.title != 'Episodes List' && window.location.href.includes("title")) {
            console.log('No episode containers found. Clearing cookies and injecting cookie...');
            clearAllCookies();
            injectCookie();
            window.location.replace(window.location.href);
        } else {
            console.log('Episode containers found:', episodeContainers.length);
        }
    }

    // MutationObserver to watch for changes in the DOM
    const observer = new MutationObserver((mutations, obs) => {
        const heroElement = document.getElementById('section-hero');
        if (heroElement) {
            createSaveButton();
            obs.disconnect(); // Stop observing after the button is added
        }
    });

    observer.observe(document, {
        childList: true,
        subtree: true
    });

    console.log('MutationObserver set up');

    // Check for episode containers on initial load
    checkEpisodeContainers();
})();