Auto All Page

Otomatis menampilkan semua halaman artikel berita dalam 1 halaman

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