TMDB load unloadable images

Force TMDB to load unloaded images

目前为 2024-11-25 提交的版本。查看 最新版本

// ==UserScript==
// @name        TMDB load unloadable images
// @namespace   https://github.com/Tetrax-10
// @description Force TMDB to load unloaded images
// @icon        https://www.google.com/s2/favicons?sz=64&domain=themoviedb.org
// @license     MIT
// @version     1.2
// @match       *://*.themoviedb.org/*
// @run-at      document-idle
// ==/UserScript==

;(() => {
    function changeSrc(img) {
        if (
            img.src.includes("media.themoviedb.org") &&
            [".jpg", ".png"].some((e) => img.src.endsWith(e)) &&
            !img.naturalHeight &&
            img.hasAttribute("srcset")
        ) {
            // Get the resolution and id of the image
            const resolution = img.src.match(/\/t\/p\/([^\/]+)\/[^\/]+$/)?.[1] ?? ""
            const id = img.src.split("/").pop()

            img.src = `https://image.tmdb.org/t/p/${resolution}/${id}`
            img.removeAttribute("srcset")
        }
    }

    // Function to handle intersection events
    function handleIntersection(entries, observer) {
        entries.forEach((entry) => {
            if (entry.isIntersecting) {
                // Check if the element is visible in the viewport
                const imgElement = entry.target
                changeSrc(imgElement) // Change the image source if it's unloaded
                observer.unobserve(imgElement) // Stop observing the current image after it's logged
            }
        })
    }

    async function waitForElement(selector, timeout = null, nthElement = 1) {
        // wait till document body loads
        while (!document.body) {
            await new Promise((resolve) => setTimeout(resolve, 10))
        }

        nthElement -= 1

        return new Promise((resolve) => {
            if (document.querySelectorAll(selector)?.[nthElement]) {
                return resolve(document.querySelectorAll(selector)?.[nthElement])
            }

            const observer = new MutationObserver(async () => {
                if (document.querySelectorAll(selector)?.[nthElement]) {
                    resolve(document.querySelectorAll(selector)?.[nthElement])
                    observer.disconnect()
                } else {
                    if (timeout) {
                        async function timeOver() {
                            return new Promise((resolve) => {
                                setTimeout(() => {
                                    observer.disconnect()
                                    resolve(undefined)
                                }, timeout)
                            })
                        }
                        resolve(await timeOver())
                    }
                }
            })

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

    function changeDivSrc(div) {
        // Get the background image URL from the div
        const bgImageUrl = getComputedStyle(div).backgroundImage

        // Extract the URL from the `url('...')` syntax
        const matches = bgImageUrl.match(/url\(['"]?(.*?)['"]?\)/)
        if (matches && matches[1]) {
            const url = matches[1]

            // Create a new Image object to check if it loads successfully
            const img = new Image()
            img.onerror = () => {
                if (url.includes("media.themoviedb.org") && [".jpg", ".png"].some((e) => url.endsWith(e))) {
                    // Get the resolution and id of the image
                    const resolution = url.match(/\/t\/p\/([^\/]+)\/[^\/]+$/)?.[1] ?? ""
                    const id = url.split("/").pop()

                    div.style.backgroundImage = `url("https://image.tmdb.org/t/p/${resolution}/${id}")`
                }
            }

            // Set the src to the extracted URL
            img.src = url
        } else {
            console.log("No valid background image URL found.")
        }
    }

    // Create a new IntersectionObserver instance
    const observer = new IntersectionObserver(handleIntersection, {
        root: null, // Observe the viewport
        rootMargin: "0px", // No margin around the viewport
        threshold: 0.1, // Trigger when at least 10% of the image is visible
    })

    // Select all img elements and observe them
    document.querySelectorAll("img").forEach((img) => {
        observer.observe(img)
    })

    // Change non img elements
    const nonImgEle = [".header.large"]

    for (const ele of nonImgEle) {
        waitForElement(ele, 10000).then((ele) => {
            changeDivSrc(ele)
        })
    }
})()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址