// ==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 // @downloadURL https://raw.githubusercontent.com/reforget-id/AutoAllPage/main/script/autoallpage.user.js // @updateURL https://raw.githubusercontent.com/reforget-id/AutoAllPage/main/script/autoallpage.user.js // @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://*/*&* // @exclude https://*/*&=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(`
=== [AutoAllPage] Halaman ${currentPage} dari ${totalPages} ===
`, '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: /^\/.+(? .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+|(? { 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) } })()