OpEx Countdown Skip

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

当前为 2022-07-17 提交的版本,查看 最新版本

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