Greasy Fork is available in English.

Auto All Page

Otomatis menampilkan semua halaman artikel berita dalam 1 halaman

// ==UserScript==
// @name          Auto All Page
// @version       2.2.6
// @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:\/\/(?!.+\.(idntimes|fortuneidn|popbela)\.com).+\?page=all$/
// @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://*.fortuneidn.com/*
// @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://*.merdeka.com/*/*
// @include       https://*.motorplus-online.com/read/*
// @include       https://*.okezone.com/read/*
// @include       https://*.parapuan.co/read/*
// @include       https://*.pikiran-rakyat.com/*/pr-*/*
// @include       https://*.pojoksatu.id/*/*/*
// @include       https://*.popbela.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: true,
            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',
            hostname: /(^|\.)idntimes\.com$/,
            path: /\/[\w-]+\/[\w-]+\/[\w-]+\/.+(?<!\/\w+)$/,
            method: 'dom',
            dynamic: false,
            pagination: '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: 'popbela',
            description: 'popbela.com',
            hostname: /(^|\.)popbela\.com$/,
            path: /\/[\w-]+\/[\w-]+\/[\w-]+\/.+(?<!\/\w+)$/,
            method: 'param',
            dynamic: true,
            fullpage: 'page=all',
        },
        {
            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)\.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 'idntimes' :
            case 'jpnn' :
            case 'merdeka':
            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) {
        switch (website.id) {
            case 'idntimes':
                idntimesDOM()
                break
            case 'merdeka':
                merdekaDOM()
                break
        }
    }

    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')
            }
        }
    }

    function merdekaDOM() {
        const readMoreButton = document.querySelector('.btn--readarticle')
        if (readMoreButton != null) {
            (function findExpand() {
                setTimeout(() => {
                    if (document.body.classList.contains('expand')) {
                        document.body.classList.remove('expand')
                        readMoreButton?.parentElement.classList.add('hidden')
                    } else {
                        findExpand()
                    }
                }, 1000)
            })()
        }
    }

    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)
    }
})()