Auto All Page

Otomatis menampilkan semua halaman artikel berita dalam 1 halaman

  1. // ==UserScript==
  2. // @name Auto All Page
  3. // @version 2.5.0
  4. // @author reforget-id
  5. // @namespace autoallpage
  6. // @description Otomatis menampilkan semua halaman artikel berita dalam 1 halaman
  7. // @homepage https://github.com/reforget-id/AutoAllPage
  8. // @supportURL https://github.com/reforget-id/AutoAllPage/issues
  9. // @icon https://raw.githubusercontent.com/reforget-id/AutoAllPage/main/assets/icon.png
  10. // @run-at document-start
  11. // @grant GM_addStyle
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_registerMenuCommand
  14. // @noframes
  15. // @exclude https://*?single=1
  16. // @exclude https://*?showpage=all
  17. // @exclude https://*.idxchannel.com/*/all
  18. // @exclude https://*.inews.id/*/all
  19. // @exclude https://*?page=all
  20. // @exclude https://*?page=all#page*
  21. // @exclude https://*?page=all#sectionall
  22. // @exclude https://*/amp/*
  23. // @exclude https://amp.*
  24. // @exclude https://*/amp-*/*
  25. // @exclude https://*/?amp*
  26. // @exclude https://*?amp=1*
  27. // @exclude https://*/*&amp*
  28. // @exclude https://*/*&amp=1*
  29. // @include https://*.20jam.com/*/*/*
  30. // @include https://*.100kpj.com/*/*
  31. // @include https://*.aboutmalang.com/*/*/*
  32. // @include https://*.akurat.co/*/*/*
  33. // @include https://*.antaranews.com/berita/*/*
  34. // @include https://*.ayocirebon.com/*/*/*
  35. // @include https://*.ayoindonesia.com/*/*/*
  36. // @include https://*.bolanas.com/read/*
  37. // @include https://*.bolasport.com/read/*
  38. // @include https://*.cnbcindonesia.com/*/*/*
  39. // @include https://*.cnnindonesia.com/*/*/*
  40. // @include https://*.dagangberita.com/*/*/*
  41. // @include https://*.detik.com/*/d-*/*
  42. // @include https://*.genpi.co/*/*/*
  43. // @include https://*.grid.id/read/*
  44. // @include https://*.gridoto.com/read/*
  45. // @include https://herstory.co.id/read*
  46. // @include https://*.hops.id/*/*/*
  47. // @include https://*.hukumonline.com/berita/a/*
  48. // @include https://*.idxchannel.com/*/*
  49. // @include https://*.indozone.id/*/*/*
  50. // @include https://*.inews.id/*/*
  51. // @include https://*.intipseleb.com/*/*
  52. // @include https://*.jagodangdut.com/*/*
  53. // @include https://*.jatimnetwork.com/*/*/*
  54. // @include https://*.juara.net/read/*
  55. // @include https://*.jpnn.com/*/*
  56. // @include https://*.kilat.com/*/*/*
  57. // @include https://*.kompas.com/read/*
  58. // @include https://*.kompas.com/*/read/*
  59. // @include https://*.kompas.tv/*/*
  60. // @include https://*.kompasiana.com/*/*/*
  61. // @include https://*.kontan.co.id/news/*
  62. // @include https://*.motorplus-online.com/read/*
  63. // @include https://*.okezone.com/read/*
  64. // @include https://*.papanskor.com/*/*/*
  65. // @include https://*.parapuan.co/read/*
  66. // @include https://*.pikiran-rakyat.com/*/pr-*/*
  67. // @include https://*.pojoksatu.id/*/*/*
  68. // @include https://*.republika.co.id/berita/*
  69. // @include https://republika.co.id/berita/*
  70. // @include https://*.sahijab.com/*/*
  71. // @include https://*.sindonews.com/read/*
  72. // @include https://*.sonora.id/read/*
  73. // @include https://*.suara.com/*/*/*/*
  74. // @include https://*.tempo.co/read/*
  75. // @include https://*.tribunnews.com/*/*/*/*
  76. // @include https://*.tvonenews.com/*/*
  77. // @include https://*.unews.id/*/*/*
  78. // @include https://*.viva.co.id/*/*
  79. // @include https://wartaekonomi.co.id/read*
  80. // ==/UserScript==
  81.  
  82. 'use strict';
  83.  
  84. (() => {
  85. GM_addStyle(`
  86. .aap-divider {
  87. font-size: 18px !important;
  88. font-weight: 600 !important;
  89. margin: 30px 0 30px 0 !important;
  90. text-align: center !important;
  91. }
  92. `)
  93.  
  94. GM_registerMenuCommand('Donate me on Trakteer', () => {
  95. window.open('https://trakteer.id/reforget-id', '_blank')
  96. })
  97.  
  98. class URLBuilder {
  99. constructor() {
  100. this._protocol = 'https'
  101. this._hostname = ''
  102. this._path = ''
  103. this._param = ''
  104. }
  105.  
  106. hostname(hostname) {
  107. this._hostname = hostname
  108. return this
  109. }
  110.  
  111. path(...pathname) {
  112. this._path = this._path + pathname.join('/')
  113. return this
  114. }
  115.  
  116. param(query) {
  117. this._param = '?' + query
  118. return this
  119. }
  120.  
  121. toString() {
  122. let url = `${this._protocol}://${this._hostname}/${this._path}`
  123. if (this._param !== '') url = url + this._param
  124. return url
  125. }
  126. }
  127.  
  128. const url = {
  129. get url() {
  130. return window.location
  131. },
  132. href: () => url.url.href,
  133. hostname: () => url.url.hostname,
  134. path: () => url.url.pathname,
  135. param: () => url.url.search
  136. }
  137.  
  138. function splitPath(pathname) {
  139. return pathname.split('/').filter(v => v)
  140. }
  141.  
  142. function redirect(url) {
  143. window.location.replace(url)
  144. }
  145.  
  146. function hostnameChecker(website) {
  147. return website.hostname.test(url.hostname())
  148. }
  149.  
  150. function urlChecker(website) {
  151. return hostnameChecker(website) && website.path.test(url.path())
  152. }
  153.  
  154. function log(message) {
  155. console.log('[AutoAllPage] ' + message)
  156. }
  157.  
  158. function pageDivider(currentPage, totalPages) {
  159. const divider = new DOMParser().parseFromString(`
  160. <div class="aap-divider">
  161. === [AutoAllPage] Halaman ${currentPage} dari ${totalPages} ===
  162. </div>
  163. `, 'text/html')
  164. return divider.body.firstElementChild
  165. }
  166.  
  167. // https://stackoverflow.com/a/52809105
  168. function watchURL(website) {
  169. let oldPushState = history.pushState
  170. history.pushState = function pushState() {
  171. let ret = oldPushState.apply(this, arguments)
  172. window.dispatchEvent(new Event('pushstate'))
  173. window.dispatchEvent(new Event('locationchange'))
  174. return ret
  175. }
  176.  
  177. let oldReplaceState = history.replaceState
  178. history.replaceState = function replaceState() {
  179. let ret = oldReplaceState.apply(this, arguments)
  180. window.dispatchEvent(new Event('replacestate'))
  181. window.dispatchEvent(new Event('locationchange'))
  182. return ret
  183. }
  184.  
  185. window.addEventListener('popstate', () => {
  186. window.dispatchEvent(new Event('locationchange'))
  187. })
  188.  
  189. window.addEventListener('locationchange', () => {
  190. if (urlChecker(website)) {
  191. log(url.href())
  192. redirect(url.href())
  193. }
  194. })
  195. }
  196.  
  197. //******************************************************************************
  198.  
  199. const websiteList = [
  200. {
  201. id: 'akurat',
  202. description: 'akurat.co',
  203. hostname: /(^|\.)akurat\.co$/,
  204. path: /^\/[a-z-]+\/.+(?<!\/\w+)$/,
  205. method: 'param',
  206. dynamic: false,
  207. fullpage: 'page=all'
  208. },
  209. {
  210. id: 'antara',
  211. description: 'antaranews.com',
  212. hostname: /(^|\.)antaranews\.com$/,
  213. path: /\/berita\/\d+\/.+(?<!\/\w+)$/,
  214. method: 'param',
  215. dynamic: false,
  216. fullpage: 'page=all'
  217. },
  218. {
  219. id: 'cnbc',
  220. description: 'cnbcindonesia.com',
  221. hostname: /(^|\.)cnbcindonesia\.com$/,
  222. path: /\/\d+-\d+-\d+\/.+(\/\d+|(?<!\/\w+))$/,
  223. method: 'param',
  224. dynamic: false,
  225. fullpage: 'page=all'
  226. },
  227. {
  228. id: 'detik',
  229. description: 'detik.com',
  230. hostname: /(^|\.)detik\.com$/,
  231. path: /\/d-\d+\/.+(\/\d+|(?<!\/\w+))$/,
  232. method: 'param',
  233. dynamic: false,
  234. fullpage: 'single=1'
  235. },
  236. {
  237. id: 'fajar',
  238. description: 'fajar.co.id',
  239. hostname: /(^|\.)fajar\.co\.id$/,
  240. path: /\/\d{4}\/\d{2}\/\d{2}\/.+(\/\d+|(?<!\/\w+))$/,
  241. method: 'param',
  242. dynamic: false,
  243. fullpage: 'page=all'
  244. },
  245. {
  246. id: 'grid',
  247. description: 'bolanas.com, bolasport.com, grid.id, gridoto.com, juara.net, motorplus-online.com, parapuan.co, sonora.id',
  248. hostname: /(^|\.)(juara\.net|parapuan\.co|(grid|sonora)\.id|(bolanas|bolasport|gridoto|motorplus-online)\.com)$/,
  249. path: /^\/read\/\d+\/.+(?<!\/\w+)$/,
  250. method: 'param',
  251. dynamic: false,
  252. fullpage: 'page=all'
  253. },
  254. {
  255. id: 'hukumonline',
  256. description: 'hukumonline.com',
  257. hostname: /(^|\.)hukumonline\.com$/,
  258. path: /^\/berita\/a\/.+(?<!\/\w+)$/,
  259. method: 'param',
  260. dynamic: false,
  261. fullpage: 'page=all'
  262. },
  263. {
  264. id: 'idx',
  265. description: 'idxchannel.com',
  266. hostname: /(^|\.)idxchannel\.com$/,
  267. path: /\/[a-z-]+\/.+(\/\d+|(?<!\/\w+))$/,
  268. method: 'path',
  269. dynamic: false,
  270. fullpage: 'all'
  271. },
  272. {
  273. id: 'indozone',
  274. description: 'indozone.id',
  275. hostname: /(^|\.)indozone\.id$/,
  276. path: /^\/[a-z-]+\/\d+\/.+(?<!\/\w+)$/,
  277. method: 'param',
  278. dynamic: false,
  279. fullpage: 'page=all'
  280. },
  281. {
  282. id: 'inews',
  283. description: 'inews.id',
  284. hostname: /(^|\.)inews\.id$/,
  285. path: /\/(berita|read\/\d+|[a-z-]+\/[a-z-]+)\/.+(\/\d+|(?<!\/\w+))$/,
  286. method: 'path',
  287. dynamic: false,
  288. fullpage: 'all'
  289. },
  290. {
  291. id: 'jagodangdut',
  292. description: 'jagodangdut.com',
  293. hostname: /(^|\.)jagodangdut\.com$/,
  294. path: /\/artikel\/.+(?<!\/\w+)$/,
  295. method: 'param',
  296. dynamic: false,
  297. fullpage: 'page=all'
  298. },
  299. {
  300. id: 'kompascom',
  301. description: 'kompas.com',
  302. hostname: /(^|\.)kompas\.com$/,
  303. path: /\/read\/.+(?<!\/\w+)$/,
  304. method: 'param',
  305. dynamic: false,
  306. fullpage: 'page=all'
  307. },
  308. {
  309. id: 'kompasiana',
  310. description: 'kompasiana.com',
  311. hostname: /(^|\.)kompasiana\.com$/,
  312. path: /\/[a-z0-9_]+(?<!series)\/\w{24}\/.+(?<!\/\w+)$/,
  313. method: 'param',
  314. dynamic: false,
  315. fullpage: 'page=all'
  316. },
  317. {
  318. id: 'kompastv',
  319. description: 'kompas.tv',
  320. hostname: /(^|\.)kompas\.tv$/,
  321. path: /^\/[a-z-]+\/\d+\/.+(?<!\/\w+)$/,
  322. method: 'param',
  323. dynamic: false,
  324. fullpage: 'page=all'
  325. },
  326. {
  327. id: 'kontan',
  328. description: 'kontan.co.id',
  329. hostname: /(^|\.)kontan\.co\.id$/,
  330. path: /^\/news\/.+(?<!\/\w+)$/,
  331. method: 'param',
  332. dynamic: false,
  333. fullpage: 'page=all'
  334. },
  335. {
  336. id: 'merdeka',
  337. description: 'merdeka.com',
  338. hostname: /(^|\.)merdeka\.com$/,
  339. path: /\/[\w-]+\/.+\.html(?<!\/\w+)$/,
  340. method: 'dom',
  341. dynamic: false
  342. },
  343. {
  344. id: 'pr',
  345. description: 'pikiran-rakyat.com',
  346. hostname: /(^|\.)pikiran-rakyat\.com$/,
  347. path: /\/pr-\d+\/.+(?<!\/\w+)$/,
  348. method: 'param',
  349. dynamic: false,
  350. fullpage: 'page=all'
  351. },
  352. {
  353. id: 'promedia',
  354. description: '20jam.com, aboutmalang.com, ayocirebon.com, jatimnetwork.com, hops.id, unews.id',
  355. hostname: /(^|\.)((20jam|aboutmalang|ayocirebon|ayoindonesia|dagangberita|kilat|jatimnetwork|papanskor)\.com|(hops|pojoksatu|unews)\.id)$/,
  356. path: /\/(pr-|)\d+\/.+(?<!\/\w+)$/,
  357. method: 'param',
  358. dynamic: false,
  359. fullpage: 'page=all'
  360. },
  361. {
  362. id: 'sindo',
  363. description: 'sindonews.com',
  364. hostname: /(^|\.)sindonews\.com$/,
  365. path: /^\/read\/\d+\/\d+\/.+(\/\d+0|(?<!\/\w+))$/,
  366. method: 'param',
  367. dynamic: false,
  368. fullpage: 'showpage=all'
  369. },
  370. {
  371. id: 'suara',
  372. description: 'suara.com',
  373. hostname: /(^|\.)suara\.com$/,
  374. path: /\/\d{4}\/\d{2}\/\d{2}\/\d+\/.+(?<!\/\w+)$/,
  375. method: 'param',
  376. dynamic: false,
  377. fullpage: 'page=all'
  378. },
  379. {
  380. id: 'tribun',
  381. description: 'tribunnews.com',
  382. hostname: /(^|\.)tribunnews\.com$/,
  383. path: /\/\d{4}\/\d{2}\/\d{2}\/.+(?<!\/\w+)$/,
  384. method: 'param',
  385. dynamic: false,
  386. fullpage: 'page=all'
  387. },
  388. {
  389. id: 'viva',
  390. description: 'viva.co.id, tvonenews.com, intipseleb.com, sahijab.com, 100kpj.com',
  391. hostname: /(^|\.)(viva\.co\.id|(tvonenews|intipseleb|sahijab|100kpj)\.com)$/,
  392. path: /\/.+\/\d+-.+(?<!\/\w+)$/,
  393. method: 'param',
  394. dynamic: false,
  395. fullpage: 'page=all'
  396. },
  397. {
  398. id: 'wartaekonomi',
  399. description: 'wartaekonomi.co.id, herstory.co.id',
  400. hostname: /(^|\.)(wartaekonomi|herstory)\.co\.id$/,
  401. path: /^\/read\d+\/.+(?<!\/\w+)$/,
  402. method: 'param',
  403. dynamic: false,
  404. fullpage: 'page=all'
  405. },
  406. {
  407. id: 'cnn',
  408. description: 'cnnindonesia.com',
  409. hostname: /(^|\.)cnnindonesia\.com$/,
  410. path: /\/\d+-\d+-\d+\/.+(\/\d+|(?<!\/\w+))$/,
  411. method: 'xhr',
  412. dynamic: false,
  413. nextURL: '/',
  414. urlHelper: 0,
  415. desktop: {
  416. pagination: '.mb-8 > .gap-2.text-base',
  417. totalPages: 'a:last-of-type',
  418. content: '.detail-text'
  419. },
  420. mobile: {
  421. pagination: '.mb-8 > .gap-2.text-base',
  422. totalPages: 'a:last-of-type',
  423. content: '.detail-text'
  424. }
  425. },
  426. {
  427. id: 'disway',
  428. description: 'disway.id',
  429. hostname: /(^|\.)disway\.id$/,
  430. path: /\/read\/\d+\/.+(\/\d+|(?<!\/\w+))$/,
  431. method: 'xhr',
  432. dynamic: false,
  433. nextURL: '/',
  434. urlHelper: -13,
  435. desktop: {
  436. pagination: '.pagination',
  437. totalPages: 'li.active:nth-last-of-type(1), li:nth-last-of-type(2) a',
  438. content: '.post'
  439. },
  440. mobile: {
  441. pagination: '.pagination',
  442. totalPages: 'li.active:nth-last-of-type(1), li:nth-last-of-type(2) a',
  443. content: '.post'
  444. }
  445. },
  446. {
  447. id: 'genpi',
  448. description: 'genpi.co',
  449. hostname: /(^|\.)genpi\.co$/,
  450. path: /\/\d+\/.+(?<!\/\w+)$/,
  451. method: 'xhr',
  452. dynamic: false,
  453. nextURL: '?page=',
  454. urlHelper: 0,
  455. desktop: {
  456. pagination: '.mnmd-pagination',
  457. totalPages: 'li:nth-last-of-type(3) a',
  458. content: 'div.entry-content div.col-md-10'
  459. },
  460. mobile: {
  461. pagination: '.mnmd-pagination',
  462. totalPages: 'li:nth-last-of-type(3) a',
  463. content: '.entry-content'
  464. }
  465. },
  466. {
  467. id: 'jpnn',
  468. description: 'jpnn.com',
  469. hostname: /(^|\.)jpnn\.com$/,
  470. path: /\/(news|[a-z-]+\/\d+)\/.+(?<!\/\w+)$/,
  471. method: 'xhr',
  472. dynamic: false,
  473. nextURL: '?page=',
  474. urlHelper: 0,
  475. desktop: {
  476. pagination: '.pagination',
  477. totalPages: 'li:nth-last-of-type(3) a',
  478. content: 'div[itemprop=articleBody]'
  479. },
  480. mobile: {
  481. pagination: '.pagination',
  482. totalPages: 'li:nth-last-of-type(3) a',
  483. content: '.page-content'
  484. }
  485. },
  486. {
  487. id: 'okezone',
  488. description: 'okezone.com',
  489. hostname: /(^|\.)okezone\.com$/,
  490. path: /^\/read\/.+(?<!\/\w+)$/,
  491. method: 'xhr',
  492. dynamic: false,
  493. nextURL: '?page=',
  494. urlHelper: 0,
  495. desktop: {
  496. pagination: '.paging',
  497. totalPages: '.second-paging',
  498. content: '#contentx, #article-box'
  499. },
  500. mobile: {
  501. pagination: '.pagingxm',
  502. totalPages: '.halnext',
  503. content: '.read, #article-box'
  504. }
  505. },
  506. {
  507. id: 'republika',
  508. description: 'republika.co.id',
  509. hostname: /(^|\.)republika\.co\.id$/,
  510. path: /^\/berita\/.+(?<!\/\w+)$/,
  511. method: 'xhr',
  512. dynamic: false,
  513. nextURL: '-part',
  514. urlHelper: 1,
  515. desktop: {
  516. pagination: '.pagination',
  517. totalPages: 'a:nth-last-of-type(2)',
  518. content: 'article'
  519. },
  520. mobile: {
  521. pagination: '.pagination',
  522. totalPages: 'li:nth-last-of-type(2) a',
  523. content: 'article'
  524. }
  525. },
  526. {
  527. id: 'tempo',
  528. description: 'tempo.co',
  529. hostname: /(^|\.)tempo\.co$/,
  530. path: /^\/read\/.+(?<!\/\w+)$/,
  531. method: 'xhr',
  532. dynamic: false,
  533. nextURL: '?page_num=',
  534. urlHelper: 0,
  535. desktop: {
  536. pagination: '.pagging',
  537. totalPages: 'li:nth-last-of-type(2) a',
  538. content: '#isi'
  539. },
  540. mobile: {
  541. pagination: '.pagging',
  542. totalPages: 'li:nth-last-of-type(2) a',
  543. content: '#isi'
  544. }
  545. }
  546. ]
  547.  
  548. //******************************************************************************
  549.  
  550. const isValidURL = websiteList.find(urlChecker)
  551. if (isValidURL !== undefined) urlRedirector(isValidURL)
  552.  
  553. function urlRedirector(website) {
  554. const redirectURL = new URLBuilder().hostname(url.hostname())
  555. switch (website.method) {
  556. case 'param' :
  557. if (website.id === 'cnbc' || website.id === 'detik' || website.id === 'fajar') {
  558. const newPath = url.path().replace(/\/\d+(|\/)$/, '')
  559. redirectURL.path(...splitPath(newPath))
  560. }
  561. else {
  562. redirectURL.path(...splitPath(url.path()))
  563. }
  564. redirectURL.param(website.fullpage)
  565. const newURL = redirectURL.toString()
  566. if (url.href() !== newURL) redirect(newURL)
  567. break
  568. case 'path' :
  569. const newPath = url.path().replace(/\/\d+$/, '')
  570. redirectURL.path(...splitPath(newPath), website.fullpage)
  571. redirect(redirectURL.toString())
  572. break
  573. case 'dom' :
  574. case 'xhr' :
  575. neutralizeURL(redirectURL, website.id)
  576. }
  577. }
  578.  
  579. function neutralizeURL(redirectURL, id) {
  580. switch (id) {
  581. case 'genpi' :
  582. case 'jpnn' :
  583. case 'okezone' :
  584. case 'tempo' :
  585. clearParamRedirect(redirectURL)
  586. break
  587. case 'cnn' :
  588. cnnRedirect(redirectURL)
  589. break
  590. case 'republika' :
  591. republikaRedirect(redirectURL)
  592. }
  593. }
  594.  
  595. function clearParamRedirect(redirectURL) {
  596. if (url.href().includes('?')) {
  597. redirectURL.path(...splitPath(url.path()))
  598. redirect(redirectURL.toString())
  599. }
  600. }
  601.  
  602. function cnnRedirect(redirectURL) {
  603. if (/\/\d+$/.test(url.path())) {
  604. const newPath = url.path().replace(/\/\d+$/, '')
  605. redirectURL.path(...splitPath(newPath))
  606. redirect(redirectURL.toString())
  607. }
  608. }
  609.  
  610. function republikaRedirect(redirectURL) {
  611. if (/-part\d+$/.test(url.path())) {
  612. const newPath = url.path().replace(/-part\d+$/, '')
  613. redirectURL.path(...splitPath(newPath))
  614. redirect(redirectURL)
  615. }
  616. }
  617.  
  618. //******************************************************************************
  619.  
  620. window.addEventListener('DOMContentLoaded', async () => {
  621. log('DOM telah selesai dimuat')
  622. const isValidHostname = websiteList.find(hostnameChecker)
  623. if (isValidHostname.dynamic === true) watchURL(isValidHostname)
  624. if (isValidURL !== undefined) {
  625. switch (isValidURL.method) {
  626. case 'dom':
  627. generalDOM(isValidURL)
  628. break
  629. case 'xhr':
  630. await generalXHR(isValidURL)
  631. break
  632. }
  633. }
  634. })
  635.  
  636. const isMobile = /(^|\.)m\./.test(url.hostname()) || window.navigator.userAgent.includes('Mobi')
  637. const isDesktop = !isMobile
  638.  
  639. function generalDOM(website) {
  640. if (website.id === 'idntimes') {}
  641. }
  642.  
  643. // Deprecated for now
  644. function idntimesDOM() {
  645. const readMoreButton = document.querySelector('.read-more-btn-check')
  646. const splitPage = document.getElementsByClassName('split-page')
  647.  
  648. if (readMoreButton !== null) {
  649. readMoreButton.remove()
  650. for (let i = 1; i < splitPage.length; i++) {
  651. splitPage[i].classList.add('open')
  652. }
  653. }
  654. }
  655.  
  656.  
  657. async function generalXHR(website) {
  658. const selector = isMobile ? website.mobile : website.desktop
  659. const totalPages = findTotalPages(selector.pagination, selector.totalPages)
  660. if (totalPages === 1) return
  661. const mainPageNode = document.querySelector(selector.content)
  662. cleaner(website.id, mainPageNode, 1, selector.pagination)
  663.  
  664. for (let i = 2; i <= totalPages; i++) {
  665. let nextPageUrl = url.href() + website.nextURL + (i - website.urlHelper)
  666. let nextPageNode = await getNextPage(nextPageUrl, i, selector.content)
  667. if (nextPageNode === null) return
  668. cleaner(website.id, nextPageNode, i, selector.pagination)
  669. let divider = pageDivider(i, totalPages)
  670. mainPageNode.append(divider, ...nextPageNode.children)
  671. log('Menambahkan halaman ke ' + i)
  672. }
  673. }
  674.  
  675. function findTotalPages(paginationSelector, totalPagesSelector) {
  676. let pagination, totalPages
  677. try {
  678. pagination = document.querySelector(paginationSelector)
  679. totalPages = pagination.querySelector(totalPagesSelector)
  680. .textContent
  681. .match(/\d+/)
  682. } catch (e) {
  683. totalPages = 1
  684. log(e)
  685. } finally {
  686. if (totalPages > 1) {
  687. //pagination.style.display = 'none'
  688. log('Pagination ditemukan, halaman berjumlah ' + totalPages)
  689. } else {
  690. totalPages = 1
  691. log('Pagination tidak ditemukan')
  692. }
  693. }
  694. return totalPages
  695. }
  696.  
  697. function getNextPage(url, pageNumber, target) {
  698. log('Bersiap membuat XHR')
  699. return new Promise((resolve, reject) => {
  700. const xhrParameter = {
  701. method: 'GET',
  702. url: url,
  703. overrideMimeType: 'text/html; charset=UTF-8',
  704. responseType: 'document',
  705. binary: false,
  706. timeout: 0,
  707. headers: {
  708. 'user-agent': window.navigator.userAgent
  709. },
  710. onerror: function () {
  711. alert('[AutoAllPage] Tidak bisa membuka halaman ke ' + pageNumber)
  712. log('Gagal membuat request XHR')
  713. reject(null)
  714. },
  715. onload: function (res) {
  716. if (res.status === 429) {
  717. log('Retry page ' + pageNumber)
  718. setTimeout(() => GM_xmlhttpRequest(xhrParameter), 2000)
  719. } else {
  720. const content = res.response.querySelector(target)
  721. if (content != null) {
  722. log('Berhasil mendapatkan halaman ke ' + pageNumber)
  723. resolve(content)
  724. } else {
  725. alert('[AutoAllPage] Gagal mendapatkan halaman ke ' + pageNumber)
  726. log('Gagal mendapatkan halaman ke ' + pageNumber)
  727. reject(null)
  728. }
  729. }
  730. }
  731. }
  732. GM_xmlhttpRequest(xhrParameter)
  733. })
  734. }
  735.  
  736. //******************************************************************************
  737.  
  738. function cleaner(id, pageNode, pageNumber, pagination) {
  739. switch (id) {
  740. case 'cnn' :
  741. cnnCleaner(pageNode, pageNumber, pagination)
  742. break
  743. case 'genpi' :
  744. genpiCleaner(pageNode, pageNumber, pagination)
  745. break
  746. case 'okezone' :
  747. okezoneCleaner(pageNode, pageNumber)
  748. break
  749. case 'republika' :
  750. republikaCleaner(pageNode, pageNumber, pagination)
  751. break
  752. case 'tempo' :
  753. tempoCleaner(pageNode, pageNumber, pagination)
  754. }
  755. }
  756.  
  757. function cnnCleaner(pageNode, pageNumber, pagination) {
  758. if (pageNumber === 1) {
  759. document.querySelector('select[name="multipage"]')?.parentElement.remove()
  760. if (isDesktop) document.querySelector('.skybanner')?.remove()
  761. if (isMobile) {
  762. document.querySelector(pagination)?.parentElement.remove()
  763. document.querySelector('.inline-block > a')?.parentElement.remove()
  764. }
  765. }
  766.  
  767. if (isDesktop) {
  768. pageNode.querySelector('.inline-block > a[dtr-evt="halaman"]')?.remove()
  769. pageNode.querySelector(pagination)?.parentElement.remove()
  770. }
  771. log('Membersihkan halaman ke ' + pageNumber)
  772. }
  773.  
  774. function genpiCleaner(pageNode, pageNumber, pagination) {
  775. if (isDesktop && pageNumber > 1) pageNode.querySelector('.entry-thumb')?.remove()
  776. const footer = pageNode.querySelector(pagination)
  777. footer?.nextElementSibling.remove()
  778. footer?.remove()
  779. log('Membersihkan halaman ke ' + pageNumber)
  780. }
  781.  
  782. function okezoneCleaner(pageNode, pageNumber) {
  783. let footerArticle = pageNode.querySelector('#rctiplus')
  784. if (footerArticle === null) footerArticle = pageNode.querySelector('.box-gnews')
  785. if (footerArticle !== null) {
  786. while (pageNode.contains(footerArticle)) {
  787. pageNode.lastElementChild.remove()
  788. }
  789. log('Membersihkan halaman ke ' + pageNumber)
  790. }
  791. }
  792.  
  793. function republikaCleaner(pageNode, pageNumber, pagination) {
  794. pageNode.querySelector('.baca-juga')?.remove()
  795. pageNode.querySelector(pagination)?.remove()
  796. log('Membersihkan halaman ke ' + pageNumber)
  797. }
  798.  
  799. function tempoCleaner(pageNode, pageNumber, pagination) {
  800. pageNode.querySelector(pagination)?.remove()
  801. log('Membersihkan halaman ke ' + pageNumber)
  802. }
  803. })()