OpEx Countdown Skip

A small script to skip the silly countdown of One Piece Ex website

  1. // ==UserScript==
  2. // @name OpEx Countdown Skip
  3. // @name:pt-BR OpEx Pula Tempo de Espera
  4. // @autor SecretX
  5. // @namespace namespace_secretx
  6. // @description A small script to skip the silly countdown of One Piece Ex website
  7. // @description:pt-br Um pequeno script para pular o contador irritante do site OpEx
  8. // @version 2022.11.16
  9. // @match *://onepiecex.*/download/?*
  10. // @match *://onepieceex.*/download/?*
  11. // @match *://onepiecex.*/dw/*/*/*/*
  12. // @match *://onepieceex.*/dw/*/*/*/*
  13. // @run-at document-start
  14. // @grant GM.xmlHttpRequest
  15. // @icon https://onepieceex.net/favicon/favicon-32x32.png
  16. // @license GNU LGPLv3
  17. // ==/UserScript==
  18.  
  19. const opexTorrentRegex = /^\w+:\/\/onepiecee?x\.\w+\/download\/\?\d+$/i;
  20. const opexServerRegex = /^\w+:\/\/onepiecee?x\.\w+\/dw\/(?:\d+\/?)+$/i;
  21.  
  22. Object.defineProperty(Array.prototype, "firstNotNull", {
  23. value: function firstNotNull() {
  24. for (const element of this) if (element != null) return element;
  25. throw new Error("Array contains no non null element.");
  26. },
  27. writable: true,
  28. configurable: true
  29. });
  30.  
  31. function isDownloadFromOpexServer() {
  32. const url = window.location.href;
  33. return opexServerRegex.test(url);
  34. }
  35.  
  36. function isDownloadFromTorrentServer() {
  37. const url = window.location.href;
  38. return opexTorrentRegex.test(url);
  39. }
  40.  
  41. // Torrent protector bypass methods
  42.  
  43. const countElem = () => document.getElementById("contador");
  44.  
  45. const awaitElem = () => document.getElementById("aguarde");
  46.  
  47. const countdownScript = () => document.querySelector("body > script:nth-child(4)").innerText;
  48.  
  49. function firstScriptLineThatMatches(regex) {
  50. return countdownScript().split("\n")
  51. .map(line => line.trim().match(regex))
  52. .firstNotNull();
  53. }
  54.  
  55. function bypassTorrentProtector() {
  56. const magnetLinkRegex = /^.+?href="(magnet[^"]+)".*$/i;
  57.  
  58. try {
  59. const magnetLink = firstScriptLineThatMatches(magnetLinkRegex)[1];
  60. console.info(`Automatically redirecting you to the extracted magnet link from this page: ${magnetLink}`);
  61. haltAllPageIntervals();
  62. try {
  63. countElem().remove();
  64. awaitElem().innerText = "Protetor desativado =)";
  65. } catch (e) {}
  66. window.location.replace(magnetLink);
  67. } catch (e) {
  68. console.error(`Oops, this script was not able to automatically grab the magnet link from this page because of an error. Using fallback that set the countdown to 1. ${e}`);
  69. countElem().innerHTML = 1;
  70. }
  71. }
  72.  
  73. // Opex protector bypass methods
  74.  
  75. function doRequest(httpMethod, url) {
  76. const hostRegex = /\w+:\/\/((?:\w+\.?)+)/;
  77.  
  78. return new Promise((resolve, reject) => {
  79. GM.xmlHttpRequest({
  80. method: httpMethod.toUpperCase(),
  81. url: url,
  82. onload: resolve,
  83. onerror: reject,
  84. responseType: "text",
  85. timeout: 6000,
  86. headers: {
  87. "Accept": "application/json, text/javascript, */*; q=0.01",
  88. "Accept-Encoding": "gzip, deflate, br",
  89. "Accept-Language": "en-US,en;q=0.5",
  90. "Cache-Control": "no-cache",
  91. "Connection": "keep-alive",
  92. "DNT": "1",
  93. "Host": url.match(hostRegex)[1],
  94. "Origin": window.location.origin,
  95. "Referer": window.location.origin,
  96. "Pragma": "no-cache",
  97. "Sec-Fetch-Dest": "empty",
  98. "Sec-Fetch-Mode": "cors",
  99. "Sec-Fetch-Site": "cross-site",
  100. }
  101. });
  102. });
  103. }
  104.  
  105. function haltAllPageIntervals() {
  106. // Get a reference to the last interval + 1
  107. const interval_id = window.setInterval(function(){}, Number.MAX_SAFE_INTEGER);
  108.  
  109. // Clear any timeout/interval up to that id
  110. for (let i = 1; i < interval_id; i++) {
  111. window.clearInterval(i);
  112. }
  113. }
  114.  
  115. function bypassOpexServerProtector() {
  116. const scriptRegex = /https?:\/\/(?:\w+\.?)+\/\?code=[^'"]+/i;
  117.  
  118. const requestUrl = Array.from(document.querySelector("head").children)
  119. .filter(node => node.nodeName === "SCRIPT")
  120. .map(node => node.innerText)
  121. .filter(script => script != null && script.length > 0)
  122. .map(script => script.match(scriptRegex))
  123. .firstNotNull()[0];
  124.  
  125. if (requestUrl == null || typeof requestUrl !== "string") {
  126. console.error("Oops, this script was not able to automatically grab the request URL from the header.");
  127. return;
  128. }
  129.  
  130. doRequest("GET", requestUrl)
  131. .then(response => {
  132. try {
  133. const downloadLink = JSON.parse(response.responseText).link;
  134.  
  135. haltAllPageIntervals();
  136. const loadingDiv = document.getElementById("andamento");
  137. loadingDiv.setAttribute("style", "width: 100%; background: rgba(65, 26, 26, 0.9) none repeat scroll 0% 0%; display: block !important;");
  138.  
  139. const messageButton = document.getElementById("mensagem");
  140. messageButton.innerText = "Protetor desativado =)"
  141.  
  142. const downloadButton = document.getElementById("link");
  143. downloadButton.href = downloadLink;
  144. downloadButton.innerText = "Baixar";
  145. downloadButton.setAttribute("style", "display: inline !important;");
  146. } catch (e) {
  147. console.error(`Could not bypass page. Requested URL ${requestUrl}. Status code: ${response.status}. Server response: ${response.responseText}`, e);
  148. }
  149. })
  150. .catch(e => console.error(`Could not bypass page. Requested URL ${requestUrl}`, e));
  151. }
  152.  
  153. window.addEventListener("DOMContentLoaded", function() {
  154. 'use strict';
  155.  
  156. if (isDownloadFromTorrentServer()) {
  157. bypassTorrentProtector();
  158. } else if (isDownloadFromOpexServer()) {
  159. bypassOpexServerProtector();
  160. }
  161. }, false);