IYF Ad Filter

过滤广告 on iyf.tv

// ==UserScript==
// @name         IYF Ad Filter
// @namespace    http://tampermonkey.net/
// @version      0.2.10
// @description  Filter ads on iyf.tv
// @description:zh-CN  过滤广告 on iyf.tv
// @author       Dylan Zhang
// @match        https://*.iyf.tv/*
// @match        https://*.yifan.tv/*
// @match        https://*.yfsp.tv/*
// @match        https://*.aiyifan.tv/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=iyf.tv
// @license      MIT
// @grant        unsafeWindow
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // variables
    const win = unsafeWindow
    const doc = win.document
    let commonStyle
    let homePageStyle
    let playPageStyle
    let listPageStyle

    const TIME_OUT = 5000

    /* utilities */
    function $(selector) {
        return doc.querySelector(selector)
    }

    function getCurrentPath() {
        const path = win.location.pathname.split('/')[1]
        return path ? `/${path}` : ''
    }

    function addEvent(el, type, handler) {
        if (typeof el === 'string') el = $(el)
        el.addEventListener(type, handler, false)
    }

    function ensureDOM(selector) {
        let timer
        let timeout
        let clearTimer = () => {
            if (timer) clearInterval(timer)
            if (timeout) clearTimeout(timeout)
        }

        const p = new Promise((resolve, reject) => {
            const find = () => {
                const el = $(selector)
                if (el) resolve(el)
            }
            const notFound = () => reject()
            timer = setInterval(find, 1000)
            timeout = setTimeout(notFound, TIME_OUT)
        })

        p.finally(() => clearTimer())

        return p
    }

    /* metadata modification */
    const history = win.history
    const originalPushState = history.pushState
    const originalReplaceState = history.replaceState
    const pushstateEvent = new Event('pushstate')
    const replacestate = new Event('replacestate')

    // override pushState
    history.pushState = function() {
        const result = originalPushState.apply(this, arguments)
        win.dispatchEvent(pushstateEvent)
        return result
    };

    // override replaceState
    history.replaceState = function() {
        const result = originalReplaceState.apply(this, arguments)
        win.dispatchEvent(replacestate)
        return result
    }

    ;['popstate', 'pushstate', 'replaceState'].forEach(eventName => {
        addEvent(win, eventName, main)
    })

    /* common ads */
    function filterCommonAds() {
        if (!commonStyle) {
            commonStyle = GM_addStyle(`
                a:has(img[alt="广告"]),
                a[href="https://www.wyav.tv/"],
                i.vip-label {
                    display: none!important;
                }

                .navbar .multi-top-buttons,
                .navbar app-dn-user-menu-item.top-item,
                .navbar .login-inner-box,
                .navbar .menu-item:has(a[href="https://www.wyav.tv/"]) {
                    display: none!important;
                }
                .navbar .menu-pop.two-col {
                    width: 160px!important;
                    left: 0!important;
                }
                .navbar .my-card.none-user,
                .navbar .none-user-content {
                    height: auto!important;
                }

                .login-frame-container .gg-dl {
                    display: none!important;
                }
                .login-frame-container .login-frame-box.heighter,
                .login-frame-container .inner {
                    width: auto!important;
                    margin-left: 0px!important;
                }

                #sticky-block .inner {
                   display: none!important;
                }
            `)
        }
    }

    /* home page */
    function filterHomePage() {
        if (!homePageStyle) {
            homePageStyle = GM_addStyle(`
                .sliders .sec4,
                .sliders .sec4 + .separater,

                app-index app-recommended-news:nth-of-type(2),
                app-index app-classified-top-videos:nth-of-type(1) > app-home-collection,
                app-index div:has(> app-discovery-in-home),
                app-index .new-list {
                   display: none!important;
                }
            `)
        }
    }

    /* play/watch page */
    function filterPlayPage() {
        if (!playPageStyle) {
            playPageStyle = GM_addStyle(`
                .video-player > div:last-child,
                .video-player vg-pause-f,
                .video-player .overlay-logo,
                .video-player .caption,
                .video-player .quanlity-items .use-coin-box {
                   display: none!important;
                }
                .video-player .player-title {
                    margin-left: 0!important;
                }

                .video-player + div.ps > div.bl {
                   display: none!important;
                }

                .main div.playPageTop {
                    min-height: 594px!important;
                }
            `)
        }

        if (!$('#video_player')) {
            filterPlayer()
        }
    }

    function filterPlayer() {
        let playerEl
        let fullscreenEl

        init()

        function init() {
            ensureDOM('#video_player').then(el => {
                playerEl = el
                fullscreenEl = $('.video-player vg-fullscreen')
                setPlayer()
            })
        }

        function setPlayer(){
            addEvent(playerEl, 'pause', onPause)
            addEvent(win, 'keydown', onFullscreen)
            closeDanmu()
        }

        function closeDanmu() {
            const btn = $('.video-player .action-pannel i.iconfont')
            const openedName = 'icondanmukai'
            if (btn?.classList.contains(openedName)) {
                btn.click()
            }
        }

        function onPause() {
            let pauseOverlayEl = $('.video-player .publicbox')
            if (pauseOverlayEl) {
                pauseOverlayEl.remove()
                pauseOverlayEl = null
                if (playerEl.paused) {
                    playerEl.play()
                }
            }
        }

        function onFullscreen(event) {
            const activeElement = doc.activeElement
            const tagName = activeElement.tagName.toLowerCase()
            const isTyping =
                tagName === 'input' ||
                tagName === 'textarea' ||
                activeElement.isContentEditable === true

            if (isTyping) return
            if (event.key.toLowerCase() !== 'f') return

            event.preventDefault()
            fullscreenEl.click()
        }
    }

    /* list page */
    function filterListPage() {
        if (!listPageStyle) {
            listPageStyle = GM_addStyle(`
                #filterDiv,
                .filters {
                    width: 100%;
                }

                .filters +  div.ss-ctn {
                    display: none!important;
                }
            `)
        }
    }

    // main
    function main() {
        filterCommonAds()

        const path = getCurrentPath()
        switch (path) {
            case '':
                filterHomePage()
                break
            case '/watch':
            case '/play':
                filterPlayPage()
                break
            case '/list':
            case '/search':
                filterListPage()
                break
        }
    }

    main()
})();