FBase Lib

Base library

当前为 2023-07-24 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/461948/1224553/FBase%20Lib.js

  1. // ==UserScript==
  2. // @name FBase Lib
  3. // @description Base library
  4. // @version 0.0.10
  5. // ==/UserScript==
  6. const FOUR_MINUTES = 4 * 60 * 1000;
  7. const wait = (msMin, msMax) => new Promise(resolve => setTimeout(resolve, msMin && msMax && rndInt(msMin, msMax) || msMin || 3000));
  8. const rndInt = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
  9.  
  10. Element.prototype.isVisible = function() {
  11. return !!(this.offsetWidth||this.offsetHeight||this.getClientRects().length);
  12. };
  13. Element.prototype.isUserFriendly = function(selector) {
  14. let e = selector ? this.querySelector(selector) : this;
  15. return e && e.isVisible() ? e : null;
  16. };
  17. Document.prototype.isUserFriendly = Element.prototype.isUserFriendly;
  18.  
  19. async function triggerClick(elm, x =0, y = 0) {
  20. if (!elm) return;
  21. elm.dispatchEvent(new MouseEvent('mouseover', {
  22. clientX: x,
  23. clientY: y,
  24. bubbles: true,
  25. cancelable: true,
  26. view: window
  27. }));
  28. await wait(100, 300);
  29. elm.dispatchEvent(new MouseEvent('mousedown', {
  30. clientX: x,
  31. clientY: y,
  32. bubbles: true,
  33. cancelable: true,
  34. view: window
  35. }));
  36. await wait(100, 300);
  37. elm.dispatchEvent(new MouseEvent('mouseup', {
  38. clientX: x,
  39. clientY: y,
  40. bubbles: true,
  41. cancelable: true,
  42. view: window
  43. }));
  44. await wait(100, 300);
  45. elm.dispatchEvent(new MouseEvent('click', {
  46. clientX: x,
  47. clientY: y,
  48. bubbles: true,
  49. cancelable: true,
  50. view: window
  51. }));
  52. };
  53. function typer(inputElm, value) {
  54. let lastValue = inputElm.value;
  55. inputElm.value = value;
  56. let event = new Event('input', { bubbles: true });
  57. event.simulated = true;
  58. let tracker = inputElm._valueTracker;
  59. if (tracker) {
  60. tracker.setValue(lastValue);
  61. }
  62. inputElm.dispatchEvent(event);
  63. }
  64.  
  65. class CrawlerWidget {
  66. constructor(params) {
  67. if (!params || (!params.selector && !params.fnSelector)) {
  68. throw new Error('CrawlerWidget requires a selector or a function selector parameter');
  69. }
  70. this.context = this.context || document;
  71. Object.assign(this, params);
  72. }
  73.  
  74. get isUserFriendly() {
  75. if (this.selector) {
  76. this.element = this.context.isUserFriendly(this.selector);
  77. return this.element;
  78. } else {
  79. this.element = this.fnSelector();
  80. return this.element;
  81. }
  82. }
  83. }
  84.  
  85. class CaptchaWidget extends CrawlerWidget {
  86. constructor(params) {
  87. super(params);
  88. }
  89.  
  90. solve() { return true; }
  91.  
  92. async isSolved() { return false; }
  93. }
  94.  
  95. class HCaptchaWidget extends CaptchaWidget {
  96. constructor(params) {
  97. let defaultParams = {
  98. selector: '.h-captcha > iframe',
  99. waitMs: [1000, 5000],
  100. timeoutMs: FOUR_MINUTES
  101. };
  102. for (let p in params) {
  103. defaultParams[p] = params[p];
  104. }
  105. super(defaultParams);
  106. }
  107.  
  108. async isSolved() {
  109. return wait().then( () => {
  110. if (this.isUserFriendly && this.element.hasAttribute('data-hcaptcha-response') && this.element.getAttribute('data-hcaptcha-response').length > 0) {
  111. return Promise.resolve(true);
  112. }
  113. return this.isSolved();
  114. });
  115. }
  116. }
  117.  
  118. class RecaptchaWidget extends CaptchaWidget {
  119. constructor(params) {
  120. let defaultParams = {
  121. selector: function() { return grecaptcha },
  122. waitMs: [1000, 5000],
  123. timeoutMs: 4 * 60 * 1000
  124. };
  125. for (let p in params) {
  126. defaultParams[p] = params[p];
  127. }
  128. super(defaultParams);
  129. }
  130.  
  131. get isUserFriendly() {
  132. this.element = grecaptcha;
  133. return this.element;
  134. }
  135.  
  136. isInvisible() {
  137. let frames = [...document.querySelectorAll('iframe')];
  138. let anchor = frames.filter(x => x.src.toLowerCase().includes('/recaptcha/api2/anchor'));
  139. anchor = anchor.length > 0 ? anchor[0] : false;
  140. let bframe = frames.filter(x => x.src.toLowerCase().includes('/recaptcha/api2/bframe'));
  141. bframe = bframe.length > 0 ? bframe[0] : false;
  142. let isInvisibleAnchor = anchor && anchor.src.toLowerCase().includes('size=invisible');
  143. return !(anchor && !isInvisibleAnchor);
  144. }
  145.  
  146. async isSolved() {
  147. return wait().then( () => {
  148. try {
  149. if (this.isUserFriendly) {
  150. if (this.isInvisible()) {
  151. return Promise.resolve(true);
  152. }
  153. if(this.element.hasOwnProperty('getPageId') && this.element.getPageId() && this.element.hasOwnProperty('getResponse') && (typeof(this.element.getResponse) == 'function')
  154. && this.element.getResponse().length > 0) {
  155. return Promise.resolve(true);
  156. }
  157. }
  158. } catch (err) {}
  159. return this.isSolved();
  160. });
  161. }
  162. }
  163.  
  164. class OuoSolver {
  165. constructor() {
  166. this.btnImHuman;
  167. }
  168.  
  169. async doClick() {
  170. this.btnImHuman = document.querySelector('#btn-main:not(.disabled)');
  171. if (!this.btnImHuman) {
  172. await wait(1000, 3000);
  173. return this.doClick();
  174. }
  175. this.btnImHuman.click();
  176. }
  177.  
  178. async start() {
  179. return this.doClick();
  180. }
  181. }