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