Auto All Page

Otomatis menampilkan semua halaman artikel berita dalam 1 halaman

目前為 2025-04-03 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name          Auto All Page
// @version       2.2.11
// @author        reforget-id
// @namespace     autoallpage
// @description   Otomatis menampilkan semua halaman artikel berita dalam 1 halaman
// @homepage      https://github.com/reforget-id/AutoAllPage
// @supportURL    https://github.com/reforget-id/AutoAllPage/issues
// @icon          https://raw.githubusercontent.com/reforget-id/AutoAllPage/main/assets/icon.png
// @run-at        document-start
// @grant         GM_addStyle
// @grant         GM_xmlhttpRequest
// @grant         GM_registerMenuCommand
// @noframes
// @exclude       https://*?single=1
// @exclude       https://*?showpage=all
// @exclude       https://*.inews.id/*/all
// @exclude       https://*?page=all#page*
// @exclude       https://*?page=all#sectionall
// @exclude       https://*/amp/*
// @exclude       https://amp.*
// @exclude       https://*/amp-*/*
// @exclude       https://*/?amp*
// @exclude       https://*?amp=1*
// @exclude       https://*/*&amp*
// @exclude       https://*/*&amp=1*
// @include       https://*.20jam.com/*/*/*
// @include       https://*.100kpj.com/*/*
// @include       https://*.aboutmalang.com/*/*/*
// @include       https://akurat.co/*
// @include       https://*.antaranews.com/berita/*/*
// @include       https://*.ayocirebon.com/*/*/*
// @include       https://*.ayoindonesia.com/*/*/*
// @include       https://*.bolasport.com/read/*
// @include       https://*.cnbcindonesia.com/*/*/*
// @include       https://*.cnnindonesia.com/*/*/*
// @include       https://*.dagangberita.com/*/*/*
// @include       https://*.detik.com/*/d-*/*
// @include       https://*.genpi.co/*/*/*
// @include       https://*.grid.id/read/*
// @include       https://*.gridoto.com/read/*
// @include       https://herstory.co.id/read*
// @include       https://*.hops.id/*/*/*
// @include       https://*.idntimes.com/*/*/*/*
// @include       https://*.idxchannel.com/*/*
// @include       https://*.inews.id/*/*
// @include       https://*.intipseleb.com/*/*
// @include       https://*.jatimnetwork.com/*/*/*
// @include       https://*.jpnn.com/*/*
// @include       https://*.kilat.com/*/*/*
// @include       https://*.kompas.com/read/*
// @include       https://*.kompas.com/*/read/*
// @include       https://*.kompas.tv/article/*
// @include       https://*.kompasiana.com/*/*/*
// @include       https://*.kontan.co.id/news/*
// @include       https://*.motorplus-online.com/read/*
// @include       https://*.okezone.com/read/*
// @include       https://*.papanskor.com/*/*/*
// @include       https://*.parapuan.co/read/*
// @include       https://*.pikiran-rakyat.com/*/pr-*/*
// @include       https://*.pojoksatu.id/*/*/*
// @include       https://*.popbela.com/*/*/*/*
// @include       https://*.popmama.com/*/*/*/*
// @include       https://*.republika.co.id/berita/*
// @include       https://republika.co.id/berita/*
// @include       https://*.sahijab.com/*/*
// @include       https://*.sindonews.com/read/*
// @include       https://*.sonora.id/read/*
// @include       https://*.suara.com/*/*/*/*
// @include       https://*.tempo.co/read/*
// @include       https://*.tribunnews.com/*/*/*/*
// @include       https://*.tvonenews.com/*/*
// @include       https://*.unews.id/*/*/*
// @include       https://*.viva.co.id/*/*
// @include       https://wartaekonomi.co.id/read*
// ==/UserScript==

'use strict';

(() => {
    GM_addStyle(`
        .aap-divider {
            font-size: 18px !important;
            font-weight: 600 !important;
            margin: 30px 0 30px 0 !important;
            text-align: center !important;  
        }
    `)

    GM_registerMenuCommand('Donate me on Trakteer', () => {
        window.open('https://trakteer.id/reforget-id', '_blank')
    })

    class URLBuilder {
        constructor() {
            this._protocol = 'https'
            this._hostname = ''
            this._path = ''
            this._param = ''
        }

        hostname(hostname) {
            this._hostname = hostname
            return this
        }

        path(...pathname) {
            this._path = this._path + pathname.join('/')
            return this
        }

        param(query) {
            this._param = '?' + query
            return this
        }

        toString() {
            let url = `${this._protocol}://${this._hostname}/${this._path}`
            if (this._param !== '') url = url + this._param
            return url
        }
    }

    const url = {
        get url() {
            return window.location
        },
        href: () => url.url.href,
        hostname: () => url.url.hostname,
        path: () => url.url.pathname,
        param: () => url.url.search
    }

    function splitPath(pathname) {
        return pathname.split('/').filter(v => v)
    }

    function redirect(url) {
        window.location.replace(url)
    }

    function hostnameChecker(website) {
        return website.hostname.test(url.hostname())
    }

    function urlChecker(website) {
        return hostnameChecker(website) && website.path.test(url.path())
    }

    function log(message) {
        console.log('[AutoAllPage] ' + message)
    }

    function pageDivider(currentPage, totalPages) {
        const divider = new DOMParser().parseFromString(`
            <div class="aap-divider">
                === [AutoAllPage] Halaman ${currentPage} dari ${totalPages} ===
            </div>
        `, 'text/html')
        return divider.body.firstElementChild
    }

    // https://stackoverflow.com/a/52809105
    function watchURL(website) {
        let oldPushState = history.pushState
        history.pushState = function pushState() {
            let ret = oldPushState.apply(this, arguments)
            window.dispatchEvent(new Event('pushstate'))
            window.dispatchEvent(new Event('locationchange'))
            return ret
        }

        let oldReplaceState = history.replaceState
        history.replaceState = function replaceState() {
            let ret = oldReplaceState.apply(this, arguments)
            window.dispatchEvent(new Event('replacestate'))
            window.dispatchEvent(new Event('locationchange'))
            return ret
        }

        window.addEventListener('popstate', () => {
            window.dispatchEvent(new Event('locationchange'))
        })

        window.addEventListener('locationchange', () => {
            if (urlChecker(website)) {
                log(url.href())
                redirect(url.href())
            }
        })
    }

    //******************************************************************************

    const websiteList = [
        {
            id: 'akurat',
            description: 'akurat.co',
            hostname: /(^|\.)akurat\.co$/,
            path: /^\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'antara',
            description: 'antaranews.com',
            hostname: /(^|\.)antaranews\.com$/,
            path: /\/berita\/\d+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'cnbc',
            description: 'cnbcindonesia.com',
            hostname: /(^|\.)cnbcindonesia\.com$/,
            path: /\/\d+-\d+-\d+\/.+(\/\d+|(?<!\/\w+))$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'detik',
            description: 'detik.com',
            hostname: /(^|\.)detik\.com$/,
            path: /\/d-\d+\/.+(\/\d+|(?<!\/\w+))$/,
            method: 'param',
            dynamic: false,
            fullpage: 'single=1'
        },
        {
            id: 'fajar',
            description: 'fajar.co.id',
            hostname: /(^|\.)fajar\.co\.id$/,
            path: /\/\d{4}\/\d{2}\/\d{2}\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'fortuneidn',
            description: 'fortuneidn.com',
            hostname: /(^|\.)fortuneidn\.com$/,
            path: /\/[\w-]+\/[\w-]+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'grid',
            description: 'bolasport.com, grid.id, gridoto.com, motorplus-online.com, parapuan.co, sonora.id',
            hostname: /(^|\.)(parapuan\.co|(grid|sonora)\.id|(bolasport|gridoto|motorplus-online)\.com)$/,
            path: /^\/read\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'idntimes',
            description: 'idntimes.com, popbela.com, popmama.com',
            hostname: /(^|\.)(idntimes|popbela|popmama)\.com$/,
            path: /\/[\w-]+\/[\w-]+\/[\w-]+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'idx',
            description: 'idxchannel.com',
            hostname: /(^|\.)idxchannel\.com$/,
            path: /\/.+\/.+(\/\d+|(?<!\/\w+))$/,
            method: 'path',
            dynamic: false,
            fullpage: 'all'
        },
        {
            id: 'inews',
            description: 'inews.id',
            hostname: /(^|\.)inews\.id$/,
            path: /\/(berita|read\/\d+|[a-z-]+\/[a-z-]+)\/.+(\/\d+|(?<!\/\w+))$/,
            method: 'path',
            dynamic: false,
            fullpage: 'all'
        },
        {
            id: 'kompascom',
            description: 'kompas.com',
            hostname: /(^|\.)kompas\.com$/,
            path: /\/read\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'kompasiana',
            description: 'kompasiana.com',
            hostname: /(^|\.)kompasiana\.com$/,
            path: /\/.+(?<!series)\/\w{24}\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'kompastv',
            description: 'kompas.tv',
            hostname: /(^|\.)kompas\.tv$/,
            path: /^\/article\/\d+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'kontan',
            description: 'kontan.co.id',
            hostname: /(^|\.)kontan\.co\.id$/,
            path: /^\/news\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'merdeka',
            description: 'merdeka.com',
            hostname: /(^|\.)merdeka\.com$/,
            path: /\/[\w-]+\/.+\.html(?<!\/\w+)$/,
            method: 'dom',
            dynamic: false
        },
        {
            id: 'pr',
            description: 'pikiran-rakyat.com',
            hostname: /(^|\.)pikiran-rakyat\.com$/,
            path: /\/pr-\d+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'promedia',
            description: '20jam.com, aboutmalang.com, ayocirebon.com, jatimnetwork.com, hops.id, unews.id',
            hostname: /(^|\.)((20jam|aboutmalang|ayocirebon|ayoindonesia|dagangberita|kilat|jatimnetwork|papanskor)\.com|(hops|pojoksatu|unews)\.id)$/,
            path: /\/(pr-|)\d+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'sindo',
            description: 'sindonews.com',
            hostname: /(^|\.)sindonews\.com$/,
            path: /^\/read\/\d+\/\d+\/.+(\/\d+0|(?<!\/\w+))$/,
            method: 'param',
            dynamic: false,
            fullpage: 'showpage=all'
        },
        {
            id: 'suara',
            description: 'suara.com',
            hostname: /(^|\.)suara\.com$/,
            path: /\/\d{4}\/\d{2}\/\d{2}\/\d+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'tribun',
            description: 'tribunnews.com',
            hostname: /(^|\.)tribunnews\.com$/,
            path: /\/\d{4}\/\d{2}\/\d{2}\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'viva',
            description: 'viva.co.id, tvonenews.com, intipseleb.com, sahijab.com, 100kpj.com',
            hostname: /(^|\.)(viva\.co\.id|(tvonenews|intipseleb|sahijab|100kpj)\.com)$/,
            path: /\/.+\/\d+-.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'wartaekonomi',
            description: 'wartaekonomi.co.id, herstory.co.id',
            hostname: /(^|\.)(wartaekonomi|herstory)\.co\.id$/,
            path: /^\/read\d+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: false,
            fullpage: 'page=all'
        },
        {
            id: 'cnn',
            description: 'cnnindonesia.com',
            hostname: /(^|\.)cnnindonesia\.com$/,
            path: /\/\d+-\d+-\d+\/.+(\/\d+|(?<!\/\w+))$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '/',
            urlHelper: 0,
            desktop: {
                pagination: '.mb-8 > .gap-2.text-base',
                totalPages: 'a:last-of-type',
                content: '.detail-text'
            },
            mobile: {
                pagination: '.mb-8 > .gap-2.text-base',
                totalPages: 'a:last-of-type',
                content: '.detail-text'
            }
        },
        {
            id: 'disway',
            description: 'disway.id',
            hostname: /(^|\.)disway\.id$/,
            path: /\/read\/\d+\/.+(\/\d+|(?<!\/\w+))$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '/',
            urlHelper: -13,
            desktop: {
                pagination: '.pagination',
                totalPages: 'li.active:nth-last-of-type(1), li:nth-last-of-type(2) a',
                content: '.post'
            },
            mobile: {
                pagination: '.pagination',
                totalPages: 'li.active:nth-last-of-type(1), li:nth-last-of-type(2) a',
                content: '.post'
            }
        },
        {
            id: 'genpi',
            description: 'genpi.co',
            hostname: /(^|\.)genpi\.co$/,
            path: /\/\d+\/.+(?<!\/\w+)$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '?page=',
            urlHelper: 0,
            desktop: {
                pagination: '.mnmd-pagination',
                totalPages: 'li:nth-last-of-type(3) a',
                content: 'div.entry-content div.col-md-10'
            },
            mobile: {
                pagination: '.mnmd-pagination',
                totalPages: 'li:nth-last-of-type(3) a',
                content: '.entry-content'
            }
        },
        {
            id: 'jpnn',
            description: 'jpnn.com',
            hostname: /(^|\.)jpnn\.com$/,
            path: /\/(news|[a-z-]+\/\d+)\/.+(?<!\/\w+)$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '?page=',
            urlHelper: 0,
            desktop: {
                pagination: '.pagination',
                totalPages: 'li:nth-last-of-type(3) a',
                content: 'div[itemprop=articleBody]'
            },
            mobile: {
                pagination: '.pagination',
                totalPages: 'li:nth-last-of-type(3) a',
                content: '.page-content'
            }
        },
        {
            id: 'okezone',
            description: 'okezone.com',
            hostname: /(^|\.)okezone\.com$/,
            path: /^\/read\/.+(?<!\/\w+)$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '?page=',
            urlHelper: 0,
            desktop: {
                pagination: '.paging',
                totalPages: '.second-paging',
                content: '#contentx, #article-box'
            },
            mobile: {
                pagination: '.pagingxm',
                totalPages: '.halnext',
                content: '.read, #article-box'
            }
        },
        {
            id: 'republika',
            description: 'republika.co.id',
            hostname: /(^|\.)republika\.co\.id$/,
            path: /^\/berita\/.+(?<!\/\w+)$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '-part',
            urlHelper: 1,
            desktop: {
                pagination: '.pagination',
                totalPages: 'a:nth-last-of-type(2)',
                content: 'article'
            },
            mobile: {
                pagination: '.pagination',
                totalPages: 'li:nth-last-of-type(2) a',
                content: 'article'
            }
        },
        {
            id: 'tempo',
            description: 'tempo.co',
            hostname: /(^|\.)tempo\.co$/,
            path: /^\/read\/.+(?<!\/\w+)$/,
            method: 'xhr',
            dynamic: false,
            nextURL: '?page_num=',
            urlHelper: 0,
            desktop: {
                pagination: '.pagging',
                totalPages: 'li:nth-last-of-type(2) a',
                content: '#isi'
            },
            mobile: {
                pagination: '.pagging',
                totalPages: 'li:nth-last-of-type(2) a',
                content: '#isi'
            }
        }
    ]

    //******************************************************************************

    const isValidURL = websiteList.find(urlChecker)
    if (isValidURL !== undefined) urlRedirector(isValidURL)

    function urlRedirector(website) {
        const redirectURL = new URLBuilder().hostname(url.hostname())
        switch (website.method) {
            case 'param' :
                if (website.id === 'cnbc' || website.id === 'detik') {
                    const newPath = url.path().replace(/\/\d+$/, '')
                    redirectURL.path(...splitPath(newPath))
                } else {
                    redirectURL.path(...splitPath(url.path()))
                }
                redirectURL.param(website.fullpage)
                const newURL = redirectURL.toString()
                if (url.href() !== newURL) redirect(newURL)
                break
            case 'path' :
                inewsRedirect(redirectURL, website.fullpage)
                break
            case 'dom' :
            case 'xhr' :
                neutralizeURL(redirectURL, website.id)
        }
    }

    function inewsRedirect(redirectURL, fullPage) {
        const newPath = url.path().replace(/\/\d+$/, '')
        redirectURL.path(...splitPath(newPath), fullPage)
        redirect(redirectURL.toString())
    }

    function neutralizeURL(redirectURL, id) {
        switch (id) {
            case 'genpi' :
            case 'jpnn' :
            case 'okezone' :
            case 'tempo' :
                clearParamRedirect(redirectURL)
                break
            case 'cnn' :
                cnnRedirect(redirectURL)
                break
            case 'republika' :
                republikaRedirect(redirectURL)
        }
    }

    function clearParamRedirect(redirectURL) {
        if (url.href().includes('?')) {
            redirectURL.path(...splitPath(url.path()))
            redirect(redirectURL.toString())
        }
    }

    function cnnRedirect(redirectURL) {
        if (/\/\d+$/.test(url.path())) {
            const newPath = url.path().replace(/\/\d+$/, '')
            redirectURL.path(...splitPath(newPath))
            redirect(redirectURL.toString())
        }
    }

    function republikaRedirect(redirectURL) {
        if (/-part\d+$/.test(url.path())) {
            const newPath = url.path().replace(/-part\d+$/, '')
            redirectURL.path(...splitPath(newPath))
            redirect(redirectURL)
        }
    }

    //******************************************************************************

    window.addEventListener('DOMContentLoaded', async () => {
        log('DOM telah selesai dimuat')
        const isValidHostname = websiteList.find(hostnameChecker)
        if (isValidHostname.dynamic === true) watchURL(isValidHostname)
        if (isValidURL !== undefined) {
            switch (isValidURL.method) {
                case 'dom':
                    generalDOM(isValidURL)
                    break
                case 'xhr':
                    await generalXHR(isValidURL)
                    break
            }
        }
    })

    const isMobile = /(^|\.)m\./.test(url.hostname()) || window.navigator.userAgent.includes('Mobi')
    const isDesktop = !isMobile

    function generalDOM(website) {
        if (website.id === 'idntimes') {}
    }

    // Deprecated for now
    function idntimesDOM() {
        const readMoreButton = document.querySelector('.read-more-btn-check')
        const splitPage = document.getElementsByClassName('split-page')

        if (readMoreButton !== null) {
            readMoreButton.remove()
            for (let i = 1; i < splitPage.length; i++) {
                splitPage[i].classList.add('open')
            }
        }
    }


    async function generalXHR(website) {
        const selector = isMobile ? website.mobile : website.desktop
        const totalPages = findTotalPages(selector.pagination, selector.totalPages)
        if (totalPages === 1) return
        const mainPageNode = document.querySelector(selector.content)
        cleaner(website.id, mainPageNode, 1, selector.pagination)

        for (let i = 2; i <= totalPages; i++) {
            let nextPageUrl = url.href() + website.nextURL + (i - website.urlHelper)
            let nextPageNode = await getNextPage(nextPageUrl, i, selector.content)
            if (nextPageNode === null) return
            cleaner(website.id, nextPageNode, i, selector.pagination)
            let divider = pageDivider(i, totalPages)
            mainPageNode.append(divider, ...nextPageNode.children)
            log('Menambahkan halaman ke ' + i)
        }
    }

    function findTotalPages(paginationSelector, totalPagesSelector) {
        let pagination, totalPages
        try {
            pagination = document.querySelector(paginationSelector)
            totalPages = pagination.querySelector(totalPagesSelector)
                .textContent
                .match(/\d+/)
        } catch (e) {
            totalPages = 1
            log(e)
        } finally {
            if (totalPages > 1) {
                //pagination.style.display = 'none'
                log('Pagination ditemukan, halaman berjumlah ' + totalPages)
            } else {
                totalPages = 1
                log('Pagination tidak ditemukan')
            }
        }
        return totalPages
    }

    function getNextPage(url, pageNumber, target) {
        log('Bersiap membuat XHR')
        return new Promise((resolve, reject) => {
            const xhrParameter = {
                method: 'GET',
                url: url,
                overrideMimeType: 'text/html; charset=UTF-8',
                responseType: 'document',
                binary: false,
                timeout: 0,
                headers: {
                    'user-agent': window.navigator.userAgent
                },
                onerror: function () {
                    alert('[AutoAllPage] Tidak bisa membuka halaman ke ' + pageNumber)
                    log('Gagal membuat request XHR')
                    reject(null)
                },
                onload: function (res) {
                    if (res.status === 429) {
                        log('Retry page ' + pageNumber)
                        setTimeout(() => GM_xmlhttpRequest(xhrParameter), 2000)
                    } else {
                        const content = res.response.querySelector(target)
                        if (content != null) {
                            log('Berhasil mendapatkan halaman ke ' + pageNumber)
                            resolve(content)
                        } else {
                            alert('[AutoAllPage] Gagal mendapatkan halaman ke ' + pageNumber)
                            log('Gagal mendapatkan halaman ke ' + pageNumber)
                            reject(null)
                        }
                    }
                }
            }
            GM_xmlhttpRequest(xhrParameter)
        })
    }

    //******************************************************************************

    function cleaner(id, pageNode, pageNumber, pagination) {
        switch (id) {
            case 'cnn' :
                cnnCleaner(pageNode, pageNumber, pagination)
                break
            case 'genpi' :
                genpiCleaner(pageNode, pageNumber, pagination)
                break
            case 'okezone' :
                okezoneCleaner(pageNode, pageNumber)
                break
            case 'republika' :
                republikaCleaner(pageNode, pageNumber, pagination)
                break
            case 'tempo' :
                tempoCleaner(pageNode, pageNumber, pagination)
        }
    }

    function cnnCleaner(pageNode, pageNumber, pagination) {
        if (pageNumber === 1) {
            document.querySelector('select[name="multipage"]')?.parentElement.remove()
            if (isDesktop) document.querySelector('.skybanner')?.remove()
            if (isMobile) {
                document.querySelector(pagination)?.parentElement.remove()
                document.querySelector('.inline-block > a')?.parentElement.remove()
            }
        }

        if (isDesktop) {
            pageNode.querySelector('.inline-block > a[dtr-evt="halaman"]')?.remove()
            pageNode.querySelector(pagination)?.parentElement.remove()
        }
        log('Membersihkan halaman ke ' + pageNumber)
    }

    function genpiCleaner(pageNode, pageNumber, pagination) {
        if (isDesktop && pageNumber > 1) pageNode.querySelector('.entry-thumb')?.remove()
        const footer = pageNode.querySelector(pagination)
        footer?.nextElementSibling.remove()
        footer?.remove()
        log('Membersihkan halaman ke ' + pageNumber)
    }

    function okezoneCleaner(pageNode, pageNumber) {
        let footerArticle = pageNode.querySelector('#rctiplus')
        if (footerArticle === null) footerArticle = pageNode.querySelector('.box-gnews')
        if (footerArticle !== null) {
            while (pageNode.contains(footerArticle)) {
                pageNode.lastElementChild.remove()
            }
            log('Membersihkan halaman ke ' + pageNumber)
        }
    }

    function republikaCleaner(pageNode, pageNumber, pagination) {
        pageNode.querySelector('.baca-juga')?.remove()
        pageNode.querySelector(pagination)?.remove()
        log('Membersihkan halaman ke ' + pageNumber)
    }

    function tempoCleaner(pageNode, pageNumber, pagination) {
        pageNode.querySelector(pagination)?.remove()
        log('Membersihkan halaman ke ' + pageNumber)
    }
})()