The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
at master 528 lines 19 kB view raw
1/* eslint-disable @typescript-eslint/no-this-alias */ 2/* eslint-disable prefer-rest-params */ 3// eslint-disable-next-line @typescript-eslint/ban-ts-comment 4// @ts-nocheck GeeTest typescript sucks 5 6// "v4.1.4 Geetest Inc."; 7 8interface CaptchaOptions { 9 captchaId: string; 10 product?: string; 11 nativeButton?: string; 12 rem?: number; 13 language?: string; 14 protocol?: string; 15 timeout?: number; 16 hideBar?: string[]; 17 mask?: { 18 outside: boolean; 19 bgColor: string; 20 }; 21 apiServers?: string[]; 22 nextWidth?: string; 23 riskType?: string; 24 offlineCb?: () => void; 25 onError?: () => void; 26 hideSuccess?: boolean; 27 userInfo?: string; 28} 29 30export function gt4init() { 31 "use strict"; 32 if (typeof window === "undefined") { 33 throw new Error("Geetest requires browser environment"); 34 } 35 36 const { document } = window; 37 const { Math } = window; 38 const head = document.getElementsByTagName("head")[0]; 39 const TIMEOUT = 10000; 40 41 function _Object(obj) { 42 this._obj = obj; 43 } 44 45 _Object.prototype = { 46 _each: function (process) { 47 const { _obj } = this; 48 for (const k in _obj) { 49 if (Object.prototype.hasOwnProperty.call(_obj, k)) { 50 process(k, _obj[k]); 51 } 52 } 53 return this; 54 }, 55 _extend: function (obj) { 56 const self = this; 57 new _Object(obj)._each(function (key, value) { 58 self._obj[key] = value; 59 }); 60 } 61 }; 62 63 const uuid = function () { 64 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { 65 const r = (Math.random() * 16) | 0; 66 const v = c === "x" ? r : (r & 0x3) | 0x8; 67 return v.toString(16); 68 }); 69 }; 70 71 function Config(config: CaptchaOptions): CaptchaOptions { 72 const self = this; 73 new _Object(config)._each(function (key, value) { 74 self[key] = value; 75 }); 76 } 77 78 Config.prototype = { 79 apiServers: ["gcaptcha4.geetest.com", "gcaptcha4.geevisit.com", "gcaptcha4.gsensebot.com"], 80 staticServers: ["static.geetest.com", "static.geevisit.com", "dn-staticdown.qbox.me"], 81 protocol: "http://", 82 typePath: "/load", 83 fallback_config: { 84 bypass: { 85 staticServers: ["static.geetest.com", "static.geevisit.com", "dn-staticdown.qbox.me"], 86 type: "bypass", 87 bypass: "/v4/bypass.js" 88 } 89 }, 90 _get_fallback_config: function () { 91 const self = this; 92 if (isString(self.type)) { 93 return self.fallback_config[self.type]; 94 } else { 95 return self.fallback_config.bypass; 96 } 97 }, 98 _extend: function (obj) { 99 const self = this; 100 new _Object(obj)._each(function (key, value) { 101 self[key] = value; 102 }); 103 } 104 }; 105 const isNumber = function (value) { 106 return typeof value === "number"; 107 }; 108 const isString = function (value) { 109 return typeof value === "string"; 110 }; 111 const isBoolean = function (value) { 112 return typeof value === "boolean"; 113 }; 114 const isObject = function (value) { 115 return typeof value === "object" && value !== null; 116 }; 117 const isFunction = function (value) { 118 return typeof value === "function"; 119 }; 120 const MOBILE = /Mobi/i.test(navigator.userAgent); 121 122 const callbacks = {}; 123 const status = {}; 124 125 const random = function () { 126 return parseInt(Math.random() * 10000) + new Date().valueOf(); 127 }; 128 129 // bind 函数polify, 不带new功能的bind 130 131 const bind = function (target, context) { 132 if (typeof target !== "function") { 133 return; 134 } 135 const args = Array.prototype.slice.call(arguments, 2); 136 137 if (Function.prototype.bind) { 138 return target.bind(context, args); 139 } else { 140 return function () { 141 const _args = Array.prototype.slice.call(arguments); 142 return target.apply(context, args.concat(_args)); 143 }; 144 } 145 }; 146 147 const { toString } = Object.prototype; 148 149 const _isFunction = function (obj) { 150 return typeof obj === "function"; 151 }; 152 const _isObject = function (obj) { 153 return obj === Object(obj); 154 }; 155 const _isArray = function (obj) { 156 return toString.call(obj) === "[object Array]"; 157 }; 158 const _isDate = function (obj) { 159 return toString.call(obj) === "[object Date]"; 160 }; 161 const _isRegExp = function (obj) { 162 return toString.call(obj) === "[object RegExp]"; 163 }; 164 const _isBoolean = function (obj) { 165 return toString.call(obj) === "[object Boolean]"; 166 }; 167 168 function resolveKey(input) { 169 return input.replace(/(\S)(_([a-zA-Z]))/g, function (match, $1, $2, $3) { 170 return $1 + $3.toUpperCase() || ""; 171 }); 172 } 173 174 function camelizeKeys(input, convert) { 175 if (!_isObject(input) || _isDate(input) || _isRegExp(input) || _isBoolean(input) || _isFunction(input)) { 176 return convert ? resolveKey(input) : input; 177 } 178 let temp = undefined; 179 180 if (_isArray(input)) { 181 temp = []; 182 for (let i = 0; i < input.length; i++) { 183 temp.push(camelizeKeys(input[i])); 184 } 185 } else { 186 temp = {}; 187 for (const prop in input) { 188 if (Object.prototype.hasOwnProperty.call(input, prop)) { 189 temp[camelizeKeys(prop, true)] = camelizeKeys(input[prop]); 190 } 191 } 192 } 193 return temp; 194 } 195 196 const loadScript = function (url: string, cb: (_: boolean) => void, timeout: number) { 197 const script = document.createElement("script"); 198 script.charset = "UTF-8"; 199 script.async = true; 200 201 // 对geetestçš„é™æ€èµ„æºæ·»åŠ crossOrigin 202 if (/static\.geetest\.com/g.test(url)) { 203 script.crossOrigin = "anonymous"; 204 } 205 206 script.onerror = function () { 207 cb(true); 208 // 错误触发了,超时逻辑就不用了 209 loaded = true; 210 }; 211 let loaded = false; 212 script.onload = script.onreadystatechange = function () { 213 if (!loaded && (!script.readyState || script.readyState === "loaded" || script.readyState === "complete")) { 214 loaded = true; 215 setTimeout(function () { 216 cb(false); 217 }, 0); 218 } 219 }; 220 script.src = url; 221 head.appendChild(script); 222 223 setTimeout(function () { 224 if (!loaded) { 225 script.onerror = script.onload = null; 226 script.remove && script.remove(); 227 cb(true); 228 } 229 }, timeout || TIMEOUT); 230 }; 231 232 const normalizeDomain = function (domain) { 233 // special domain: uems.sysu.edu.cn/jwxt/geetest/ 234 // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn 235 return domain.replace(/^https?:\/\/|\/$/g, ""); // uems.sysu.edu.cn/jwxt/geetest 236 }; 237 const normalizePath = function (path) { 238 path = path.replace(/\/+/g, "/"); 239 if (path.indexOf("/") !== 0) { 240 path = "/" + path; 241 } 242 return path; 243 }; 244 const normalizeQuery = function (query) { 245 if (!query) { 246 return ""; 247 } 248 let q = "?"; 249 new _Object(query)._each(function (key, value) { 250 if (isString(value) || isNumber(value) || isBoolean(value)) { 251 q = q + encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&"; 252 } 253 }); 254 if (q === "?") { 255 q = ""; 256 } 257 return q.replace(/&$/, ""); 258 }; 259 const makeURL = function (protocol, domain, path, query) { 260 domain = normalizeDomain(domain); 261 262 let url = normalizePath(path) + normalizeQuery(query); 263 if (domain) { 264 url = protocol + domain + url; 265 } 266 267 return url; 268 }; 269 270 const load = function (config: CaptchaOptions, protocol: "http://" | "https://", domains: string[], path: string, query, cb: (_: boolean) => void, handleCb: (_: boolean) => void) { 271 const tryRequest = function (at) { 272 let cbName = undefined; 273 // 处理jsonp回调,这里为了保证每个不同jsonp都有唯一的回调函数 274 if (handleCb) { 275 cbName = "geetest_" + random(); 276 // 需要与预先定义好cbnameå‚æ•°ï¼Œåˆ é™¤å¯¹è±¡ 277 window[cbName] = bind(handleCb, null, cbName); 278 query.callback = cbName; 279 } 280 const url = makeURL(protocol, domains[at], path, query); 281 loadScript( 282 url, 283 function (err) { 284 if (err) { 285 // 超时或者出错的时候 移除回调 286 if (cbName) { 287 try { 288 window[cbName] = function () { 289 window[cbName] = null; 290 }; 291 } catch (e) { return; } 292 } 293 294 if (at >= domains.length - 1) { 295 cb(true); 296 // report gettype error 297 } else { 298 tryRequest(at + 1); 299 } 300 } else { 301 cb(false); 302 } 303 }, 304 config.timeout 305 ); 306 }; 307 tryRequest(0); 308 }; 309 310 const jsonp = function (domains: string[], path: string, config: CaptchaOptions, callback: () => void) { 311 const handleCb = function (cbName, data) { 312 // 保证只执行一次,全部超时的情况下不会再触发; 313 314 if (data.status === "success") { 315 callback(data.data); 316 } else if (!data.status) { 317 callback(data); 318 } else { 319 // 接口有返回,但是返回了错误状态,进入报错逻辑 320 callback(data); 321 } 322 window[cbName] = undefined; 323 try { 324 delete window[cbName]; 325 } catch (e) { return; } 326 }; 327 328 load( 329 config, 330 config.protocol, 331 domains, 332 path, 333 { 334 captcha_id: config.captchaId, 335 challenge: config.challenge || uuid(), 336 client_type: MOBILE ? "h5" : "web", 337 risk_type: config.riskType, 338 call_type: config.callType, 339 lang: config.language 340 ? config.language 341 : navigator.appName === "Netscape" 342 ? navigator.language.toLowerCase() 343 : navigator.userLanguage.toLowerCase(), 344 user_info: config.userInfo 345 }, 346 function (err) { 347 // ç½‘ç»œé—®é¢˜æŽ¥å£æ²¡æœ‰è¿”å›žï¼Œç›´æŽ¥ä½¿ç”¨æœ¬åœ°éªŒè¯ç ï¼Œèµ°å®•æœºæ¨¡å¼ 348 // è¿™é‡Œå¯ä»¥æ·»åŠ ç”¨æˆ·çš„é€»è¾‘ 349 if (err && typeof config.offlineCb === "function") { 350 // 执行自己的宕机 351 config.offlineCb(); 352 return; 353 } 354 355 if (err) { 356 callback(config._get_fallback_config()); 357 } 358 }, 359 handleCb 360 ); 361 }; 362 363 const throwError = function (errorType, config, errObj) { 364 const errors = { 365 networkError: "网络错误", 366 gtTypeError: "gt字段不是字符串类型" 367 }; 368 if (typeof config.onError === "function") { 369 config.onError({ 370 desc: errObj.desc, 371 msg: errObj.msg, 372 code: errObj.code 373 }); 374 } else { 375 throw new Error(errors[errorType]); 376 } 377 }; 378 379 const detect = function () { 380 return window.Geetest || document.getElementById("gt_lib"); 381 }; 382 383 if (detect()) { 384 status.slide = "loaded"; 385 } 386 const GeetestIsLoad = function (fname: string) { 387 let GeetestIsLoad = false; 388 const tags = { js: "script", css: "link" }; 389 const tagname = tags[fname.split(".").pop()]; 390 if (tagname !== undefined) { 391 const elts = document.getElementsByTagName(tagname); 392 for (const i in elts) { 393 if ((elts[i].href && elts[i].href.toString().indexOf(fname) > 0) || (elts[i].src && elts[i].src.toString().indexOf(fname) > 0)) { 394 GeetestIsLoad = true; 395 } 396 } 397 } 398 return GeetestIsLoad; 399 }; 400 401 const init = function (userConfig, callback: (c) => void) { 402 const config = new Config(userConfig) as CaptchaOptions; 403 if (userConfig.https) { 404 config.protocol = "https://"; 405 } else if (!userConfig.protocol) { 406 config.protocol = window.location.protocol + "//"; 407 } 408 409 if (isObject(userConfig.getType)) { 410 config._extend(userConfig.getType); 411 } 412 413 jsonp(config.apiServers, config.typePath, config, function (newConfig) { 414 // 错误捕获,第一个load请求可能直接报错 415 newConfig = camelizeKeys(newConfig); 416 417 if (newConfig.status === "error") { 418 return throwError("networkError", config, newConfig); 419 } 420 421 const { type } = newConfig; 422 423 if (config.debug) { 424 new _Object(newConfig)._extend(config.debug); 425 } 426 const init = function () { 427 config._extend(newConfig); 428 callback(new window.Geetest4(config)); 429 }; 430 431 callbacks[type] = callbacks[type] || []; 432 433 const s = status[type] || "init"; 434 if (s === "init") { 435 status[type] = "loading"; 436 437 callbacks[type].push(init); 438 439 if (newConfig.gctPath) { 440 load( 441 config, 442 config.protocol, 443 Object.hasOwnProperty.call(config, "staticServers") ? config.staticServers : newConfig.staticServers || config.staticServers, 444 newConfig.gctPath, 445 null, 446 function (err) { 447 if (err) { 448 throwError("networkError", config, { 449 code: "60205", 450 msg: "Network failure", 451 desc: { 452 detail: "gct resource load timeout" 453 } 454 }); 455 } 456 } 457 ); 458 } 459 460 load( 461 config, 462 config.protocol, 463 Object.hasOwnProperty.call(config, "staticServers") ? config.staticServers : newConfig.staticServers || config.staticServers, 464 newConfig.bypass || newConfig.staticPath + newConfig.js, 465 null, 466 function (err) { 467 if (err) { 468 status[type] = "fail"; 469 throwError("networkError", config, { 470 code: "60204", 471 msg: "Network failure", 472 desc: { 473 detail: "js resource load timeout" 474 } 475 }); 476 } else { 477 status[type] = "loaded"; 478 const cbs = callbacks[type]; 479 for (let i = 0, len = cbs.length; i < len; i += 1) { 480 const cb = cbs[i]; 481 if (isFunction(cb)) { 482 cb(); 483 } 484 } 485 callbacks[type] = []; 486 } 487 } 488 ); 489 } else if (s === "loaded") { 490 // 判断gctæ˜¯å¦éœ€è¦é‡æ–°åŠ è½½ 491 if (!GeetestIsLoad(newConfig.gctPath)) { 492 load( 493 config, 494 config.protocol, 495 Object.hasOwnProperty.call(config, "staticServers") ? config.staticServers : newConfig.staticServers || config.staticServers, 496 newConfig.gctPath, 497 null, 498 function (err) { 499 if (err) { 500 throwError("networkError", config, { 501 code: "60205", 502 msg: "Network failure", 503 desc: { 504 detail: "gct resource load timeout" 505 } 506 }); 507 } 508 } 509 ); 510 } 511 return init(); 512 } else if (s === "fail") { 513 throwError("networkError", config, { 514 code: "60204", 515 msg: "Network failure", 516 desc: { 517 detail: "js resource load timeout" 518 } 519 }); 520 } else if (s === "loading") { 521 callbacks[type].push(init); 522 } 523 }); 524 }; 525 526 return { init }; 527 528}