Mrrrr's Forum (VIEW ONLY)
Un forum care ofera solutii pentru unele probleme legate in general de PC. Pe langa solutii, aici puteti gasi si alte lucruri interesante // A forum that offers solutions to some PC related issues. Besides these, here you can find more interesting stuff.
Lista Forumurilor Pe Tematici
Mrrrr's Forum (VIEW ONLY) | Reguli | Inregistrare | Login

POZE MRRRR'S FORUM (VIEW ONLY)

Nu sunteti logat.
Nou pe simpatie:
Ioana24 pe Simpatie.ro
Femeie
25 ani
Bucuresti
cauta Barbat
27 - 43 ani
Mrrrr's Forum (VIEW ONLY) / Tutoriale si Ghiduri Utile // Tutorials and useful guides / [CHROME, TAMPERMONKEY] Copy IMDB Data to Clipboard or Save as File Moderat de TRaP, TonyTzu
Autor
Mesaj Pagini: 1
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2374
I needed a way to easily copy some data for movies or series from iMDB. I'm making a list of things to watch and would like to have some info locally.
I know there are programs doing this already (such as EMDB for example and surely others), but I want my own script doing only the things I need.

The following Tampermonkey script provides buttons to do several things:
- saves the top 3 actors in the "Stars" section to a text file with their names as file name
- saves the rating as a text file with the rating as name, and the rating inside the file as well
- saves the imdb link as .url internet shortcut
- copies the genres to clipboard
- searches for the name of the movie on a desired website, e.g. TMDB

When loading an IMDB page of a movie, the buttons corresponding to the above options appear in the bottom right of the page. If clicked, they do the actions above. The files get saved in the default Chrome download directory.


// ==UserScript==
// @name         IMDb Multi-Tool (copy some imdb metadata)
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Save info about top 3 actors, main genres, rating and url
// @match        https://www.imdb.com/title/tt*
// @grant        GM_setClipboard
// @grant        GM_download
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // Helper: Utility to parse JSON-LD metadata safely
    function getImdbMetadata() {
        const jsonLdScript = document.querySelector('script[type="application/ld+json"]');
        if (jsonLdScript) {
            try {
                return JSON.parse(jsonLdScript.textContent);
            } catch (err) {
                console.warn('JSON-LD parse failed', err);
            }
        }
        return null;
    }

// 1. Create a container for all buttons (Bottom Right)
    const buttonContainer = document.createElement('div');
    buttonContainer.style.cssText = `
        position: fixed;
        bottom: 20px;
        right: 20px;
        z-index: 99999;
        display: flex;
        flex-direction: column;
        gap: 10px;
        align-items: flex-end;
        font-family: sans-serif;
    `;
    document.body.appendChild(buttonContainer);

    // 2. Button factory
    function createButton(text, color, clickHandler) {
        const btn = document.createElement('button');
        btn.innerText = text;
        btn.style.cssText = `
            padding: 10px 16px;
            background-color: ${color};
            color: #000000;
            font-weight: bold;
            border: none;
            border-radius: 18px;
            box-shadow: 0 4px 10px rgba(0,0,0,0.3);
            cursor: pointer;
            font-size: 13px;
            transition: all 0.2s ease;
            white-space: nowrap;
        `;
        btn.addEventListener('click', () => clickHandler(btn));
        buttonContainer.appendChild(btn);
        return btn;
    }

    // Temporary button visual feedback
    function showSuccess(btn, message) {
        const origText = btn.innerText;
        const origBg = btn.style.backgroundColor;
        const origColor = btn.style.color;

        btn.innerText = message;
        btn.style.backgroundColor = '#4CAF50';
        btn.style.color = '#FFFFFF';

        setTimeout(() => {
            btn.innerText = origText;
            btn.style.backgroundColor = origBg;
            btn.style.color = origColor;
        }, 2500);
    }

    // --- BUTTON 1: Save Top 3 actors.txt ---
    createButton('📋 Save Top 3 Actors.txt', '#f5c518', (btn) => {
        let actors = [];
        const metadata = getImdbMetadata();

        if (metadata && metadata.actor && Array.isArray(metadata.actor)) {
            actors = metadata.actor
                .filter(item => item['@type'] === 'Person' && item.name)
                .map(item => item.name.trim());
        } else {
            const castEls = document.querySelectorAll('[data-testid="title-cast-item__actor"]');
            castEls.forEach(el => actors.push(el.innerText.trim()));
        }

        const top3 = actors.slice(0, 3);
        if (top3.length === 0) {
            alert('No actors found on page.');
            return;
        }

        const result = top3.join(', ');

// The following 2 lines to copy the names of the actors to clipboard:
        /* GM_setClipboard(result);
        showSuccess(btn, `✓ Copied: ${result}`); */


// Save file with actor names START ---->
        // Download the file to default download directory

        const fileName = `${result}.txt`;
        const blob = new Blob([' '], { type: 'text/plain;charset=utf-8' }); // this is what goes inside the text file
        const blobUrl = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = blobUrl;
        a.download = fileName;
        document.body.appendChild(a);
        a.click();

        // Cleanup
        document.body.removeChild(a);
        setTimeout(() => URL.revokeObjectURL(blobUrl), 100);

        showSuccess(btn, `✓ Saved: ${fileName}`);
// Save file with actor names END <----

    });

    // --- BUTTON 2: Save IMDb Rating ---
    createButton('⭐ Save iMDb rating.txt', '#f5c518', (btn) => {
        let rawRating = null;
        const metadata = getImdbMetadata();

        if (metadata && metadata.aggregateRating && metadata.aggregateRating.ratingValue) {
            rawRating = metadata.aggregateRating.ratingValue;
        } else {
            // Fallback DOM selector
            const ratingEl = document.querySelector('[data-testid="hero-rating-bar__aggregate-rating__score"] span');
            if (ratingEl) rawRating = ratingEl.innerText.trim();
        }

        if (!rawRating) {
            alert('Could not find IMDb rating on this page.');
            return;
        }

        // Format decimal dot into a comma (e.g., 5.7 -> 5,7)
        let formattedRating = String(rawRating).replace('.', ',');

        // If rating is a single digit (e.g., "7"), append ",0"
        if (/^\d+$/.test(formattedRating)) {
            formattedRating += ',0';
        }


        const fileName = `iMDB = ${formattedRating}.txt`;

        // Download the file to default download directory
        const blob = new Blob([formattedRating], { type: 'text/plain;charset=utf-8' });
        const blobUrl = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = blobUrl;
        a.download = fileName; // Forces the specific "iMDB = RATING_HERE.txt" filename
        document.body.appendChild(a);
        a.click();

        // Cleanup
        document.body.removeChild(a);
        setTimeout(() => URL.revokeObjectURL(blobUrl), 100);

        showSuccess(btn, `✓ Saved: ${fileName}`);

    });

/* FOR THIS TO WORK WITHOUT RESULTING IN BLOCKED FILES (requiring right click -> properties -> unblock)
   Disable "Mark of the Web" in Windows
      Option 1 - gpedit.msc
        - User Configuration > Administrative Templates > Windows Components > Attachment Manager
        - Double-click Do not preserve zone information in file attachments.
        - Set it to Enabled and click OK.
      Option 2 - cmd/powershell command (as admin)
        - reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Attachments" /v SaveZoneInformation /t REG_DWORD /d 1 /f
        - Restart Windows
*/
    // --- BUTTON 3: Save IMDb URL Shortcut ---

    createButton('🔗 Save iMDb link as url file', '#f5c518', (btn) => {
        // 1. Extract the 'tt' ID from the current page URL
        const match = window.location.href.match(/tt\d+/);

        if (!match) {
            alert('Could not find IMDb title ID in URL.');
            return;
        }

        const titleId = match[0]; // e.g. "tt0104257"
        const cleanUrl = `https://www.imdb.com/title/${titleId}/`; // Trims everything after the ID
        const fileName = `${titleId}.url`;

        // 2. Format as a standard Windows Internet Shortcut file content
        const fileContent = `[InternetShortcut]\r\nURL=${cleanUrl}\r\n`;

        // 3. Trigger Download
        const blob = new Blob([fileContent], { type: 'application/x-mswinurl' });
        const blobUrl = URL.createObjectURL(blob);

        const a = document.createElement('a');
        a.href = blobUrl;
        a.download = fileName; // Saves as tt0104257.url
        document.body.appendChild(a);
        a.click();

        // Cleanup
        document.body.removeChild(a);
        setTimeout(() => URL.revokeObjectURL(blobUrl), 100);

        showSuccess(btn, `✓ Saved: ${fileName}`);
    });

    // --- BUTTON 4: Copy Genres ---
    createButton('🎭 Copy Genres to clipboard', '#f5c518', (btn) => {

let genres = [];

        // 1. Try Next.js internal data script (contains full "genres" list)
        const nextDataScript = document.querySelector('script[id="__NEXT_DATA__"]');
        if (nextDataScript) {
            try {
                const text = nextDataScript.textContent;

                // Match the full "genres":{"genres":[{...}]} object
                const genreMatch = text.match(/"genres"\s*:\s*\{\s*"genres"\s*:\s*(\[\s*\{.*?\}\s*\])/);
                if (genreMatch && genreMatch[1]) {
                    const parsedGenres = JSON.parse(genreMatch[1]);
                    genres = parsedGenres.map(g => g.text).filter(Boolean);
                }
            } catch (err) {
                console.warn('Failed to parse __NEXT_DATA__ genres', err);
            }
        }

        // 2. Fallback: Check standard JSON-LD
        if (genres.length === 0) {
            const metadata = getImdbMetadata();
            if (metadata && metadata.genre) {
                genres = Array.isArray(metadata.genre) ? metadata.genre : [metadata.genre];
            }
        }

        // 3. Fallback: DOM Search
        if (genres.length === 0) {
            const genreEls = document.querySelectorAll('a[href*="/search/title/?genres="], a[href*="/genre/"]');
            genreEls.forEach(el => {
                const txt = el.innerText.trim();
                if (txt && !genres.includes(txt)) genres.push(txt);
            });
        }

        if (genres.length === 0) {
            alert('No genres found on page.');
            return;
        }

        const result = genres.join(', ');
        GM_setClipboard(result);
        showSuccess(btn, `✓ Copied: ${result}`);
    });

    // --- BUTTON: Search TMDB ---
    createButton('🔍 Search TMDB', '#f5c518', (btn) => {
        let movieTitle = '';

        // 1. Try getting clean title from JSON-LD metadata
        const metadata = getImdbMetadata();
        if (metadata && metadata.name) {
            movieTitle = metadata.name;
        }

        // 2. Fallback to h1 title if metadata wasn't available
        if (!movieTitle) {
            const titleEl = document.querySelector('h1[data-testid="hero__pageTitle"] span, h1');
            if (titleEl) {
                movieTitle = titleEl.innerText.trim();
            }
        }

        if (!movieTitle) {
            alert('Could not find movie title on this page.');
            return;
        }

        // 3. Format title: replace spaces with "+" and trim extra whitespace
        const formattedTitle = movieTitle.trim().replace(/\s+/g, '+');

        // 4. Construct target URL
        const targetUrl = `https://www.themoviedb.org/search?query=${formattedTitle}`;

        // 5. Open in a new tab
        window.open(targetUrl, '_blank');

        showSuccess(btn, '✓ Opening Search...');
    });
})();


Source: Gemini


_______________________________________


pus acum 6 zile
   
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2374
First off, added the code colored in this color above so that when a movie has .0 rating it doesn't remove that .0 in the name of the text file.
- previously if a movie had rating e.g., 7.0, the resulting text file was being named iMDB = 7.txt
- now it is being named iMDB = 7,0.txt

****

The code below replaces button 4 above, if you want. It changes the pattern copied to clipboard from:

Genre, Genre, Genre
    to
Movie Name (Year) Genre, Genre, Genre ---- [iMDB rating]


// --- BUTTON 4: Copy Movie (Year) Genres ---- [IMDb rating] ---
    createButton('🎭 Copy Info to Clipboard', '#f5c518', (btn) => {
        let genres = [];
        let movieTitle = '';
        let movieYear = '';
        let imdbRating = '';

        const metadata = getImdbMetadata();

        // 1. Get Title, Year, and Rating from JSON-LD Metadata
        if (metadata) {
            if (metadata.name) movieTitle = metadata.name;

            if (metadata.datePublished) {
                const yearMatch = metadata.datePublished.match(/\d{4}/);
                if (yearMatch) movieYear = yearMatch[0];
            }

            if (metadata.aggregateRating && metadata.aggregateRating.ratingValue) {
                imdbRating = String(metadata.aggregateRating.ratingValue);
            }
        }

        // 2. Fallback for Title
        if (!movieTitle) {
            const titleEl = document.querySelector('h1[data-testid="hero__pageTitle"] span, h1');
            if (titleEl) movieTitle = titleEl.innerText.trim();
        }

        // 3. Fallback for Year
        if (!movieYear) {
            const yearEl = document.querySelector('a[href*="/releaseinfo"], [data-testid="hero-title-block__metadata"] li');
            if (yearEl) {
                const yearMatch = yearEl.innerText.match(/\b(19|20)\d{2}\b/);
                if (yearMatch) movieYear = yearMatch[0];
            }
        }

        // 4. Fallback for Rating (DOM & raw text match)
        if (!imdbRating) {
            const ratingEl = document.querySelector('[data-testid="hero-rating-bar__aggregate-rating__score"] span');
            if (ratingEl) {
                imdbRating = ratingEl.innerText.trim();
            }
        }

        if (!movieTitle) {
            alert('Could not find movie title on this page.');
            return;
        }

        // --- FORMAT RATING (.0 / ,0 handling) ---
        if (imdbRating) {
            // Convert dot to comma if needed (e.g. 7.0 -> 7,0). Change ',' to '.' if you prefer dots.
            imdbRating = imdbRating.replace('.', ',');

            // If rating is a single digit (e.g., "7"), append ",0"
            if (/^\d+$/.test(imdbRating)) {
                imdbRating += ',0';
            }
        } else {
            imdbRating = 'N/A';
        }

        // --- GENRES EXTRACTION ---
        // 1. Try Next.js internal data script (contains full "genres" list)

        const nextDataScript = document.querySelector('script[id="__NEXT_DATA__"]');
        if (nextDataScript) {
            try {
                const text = nextDataScript.textContent;
                const genreMatch = text.match(/"genres"\s*:\s*\{\s*"genres"\s*:\s*(\[\s*\{.*?\}\s*\])/);
                if (genreMatch && genreMatch[1]) {
                    const parsedGenres = JSON.parse(genreMatch[1]);
                    genres = parsedGenres.map(g => g.text).filter(Boolean);
                }
            } catch (err) {
                console.warn('Failed to parse __NEXT_DATA__ genres', err);
            }
        }

        // 2. Fallback: Check standard JSON-LD
        if (genres.length === 0 && metadata && metadata.genre) {
            genres = Array.isArray(metadata.genre) ? metadata.genre : [metadata.genre];
        }

        // 3. Fallback: DOM Search
        if (genres.length === 0) {
            const genreEls = document.querySelectorAll('a[href*="/search/title/?genres="], a[href*="/genre/"]');
            genreEls.forEach(el => {
                const txt = el.innerText.trim();
                if (txt && !genres.includes(txt)) genres.push(txt);
            });
        }

        if (genres.length === 0) {
            alert('No genres found on page.');
            return;
        }

        // --- FINAL ASSEMBLY ---
        const yearFormatted = movieYear ? ` (${movieYear})` : '';
        const genresFormatted = genres.join(', ');

        // Output pattern: Movie Name (Year) Genres ---- [7,0]
        const result = `${movieTitle}${yearFormatted} ${genresFormatted} ---- [${imdbRating}]`;

        GM_setClipboard(result);
        showSuccess(btn, `✓ Copied: ${result}`);
    });

Source: Gemini


_______________________________________


pus acum 2 zile
   
Pagini: 1  

Mergi la