├── .github ├── images │ ├── addSignals.png │ ├── after.png │ ├── before.png │ ├── challengeVals.png │ ├── ddm.png │ ├── debug.jpg │ ├── example.png │ ├── module.png │ ├── submit.png │ └── submitParams.png └── signals.json ├── .gitignore ├── README.md ├── api ├── README.md ├── index.js ├── package.json ├── src │ ├── captchaChallenge.js │ ├── devices.js │ ├── gen.js │ ├── mouse.js │ └── signals.js └── yarn.lock ├── deobfuscate ├── README.md ├── assets │ ├── bracket_to_dot_notation.js │ ├── in.js │ ├── out_binary_expressions.js │ ├── out_bracket_dot.js │ ├── out_bracket_dot1.js │ ├── out_final.js │ ├── out_hex.js │ ├── out_string_concatenation.js │ └── out_string_decode.js ├── index.js ├── package-lock.json ├── package.json ├── transformers │ ├── binaryExpressionStrings.js │ ├── bracketToDot.js │ ├── hex.js │ ├── stringConcatenation.js │ ├── stringDeob.js │ └── stringDeob_v2.js └── utils │ └── genCode.js └── detection ├── README.md ├── api.py ├── requirements.txt └── slide.py /.github/images/addSignals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/addSignals.png -------------------------------------------------------------------------------- /.github/images/after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/after.png -------------------------------------------------------------------------------- /.github/images/before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/before.png -------------------------------------------------------------------------------- /.github/images/challengeVals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/challengeVals.png -------------------------------------------------------------------------------- /.github/images/ddm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/ddm.png -------------------------------------------------------------------------------- /.github/images/debug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/debug.jpg -------------------------------------------------------------------------------- /.github/images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/example.png -------------------------------------------------------------------------------- /.github/images/module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/module.png -------------------------------------------------------------------------------- /.github/images/submit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/submit.png -------------------------------------------------------------------------------- /.github/images/submitParams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekav/SlideCaptcha/0c6f32989715868abdaa32c80f7683be78ded981/.github/images/submitParams.png -------------------------------------------------------------------------------- /.github/signals.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": "1.8.2", 3 | "h": "97946689b033b3727194dd2bffeb337ba15cd6fba2ab5775e8b5e6d255da6074", 4 | "tstf": 24, 5 | "tagpu": 15.80000000000291, 6 | "ccsT": "Error\nat e (http://127.0.0.1:5500/test.html:3505:14)\nat http://127.0.0.1:5500/test.html:4062:22\nat http://127.0.0.1:5500/test.html:3458:50\nat e. { 9 | // Validate request body 10 | if (!req.body) { 11 | res.status(400).send({ 12 | error: "Invalid request body: no body provided" 13 | }) 14 | return 15 | } else if (!req.body.ddm.hash || !req.body.ddm.ua || !req.body.ddm.cid) { 16 | res.status(400).send({ 17 | error: "Invalid request body: invalid ddm" 18 | }) 19 | return 20 | } else if (!req.body.background_image) { 21 | res.status(400).send({ 22 | error: "Invalid request body: no image url" 23 | }) 24 | return 25 | } 26 | 27 | var response = await generatePayload.main(req.body) 28 | res.send(response); 29 | }); 30 | 31 | app.listen(port, () => { 32 | console.log(`API server is running on port ${port}`); 33 | }); 34 | -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slide-api", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "dependencies": { 10 | "axios": "^1.6.7", 11 | "express": "^4.18.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /api/src/captchaChallenge.js: -------------------------------------------------------------------------------- 1 | 2 | ddExecuteCaptchaChallenge = function (ddCookie, userAgent, language) { 3 | var t = 10; 4 | class e { 5 | constructor() { 6 | var t = 1723; 7 | var e = 7532; 8 | var r = (function (r) { 9 | for (var t = 126 ^ r.charCodeAt(0), e = 1; e < r.length; e++) 10 | t += 11 | ((r.charCodeAt(e) * e) ^ 12 | r.charCodeAt(e - 1)) >> 13 | e % 2; 14 | return t; 15 | })(ddCookie) 16 | 17 | this.seed = r 18 | 19 | this.currentNumber = r % t 20 | this.offsetParameter = t 21 | this.multiplier = e 22 | this.currentNumber <= 0 && (this.currentNumber += t); 23 | 24 | } 25 | getNext() { 26 | return ( 27 | (this.currentNumber = 28 | (this.multiplier * this.currentNumber) % 29 | this.offsetParameter), 30 | this.currentNumber 31 | ); 32 | } 33 | } 34 | for ( 35 | var n = [ 36 | function (r, t) { 37 | var e = 26157, 38 | n = 0; 39 | if ( 40 | ((s = 41 | "VEc5dmEybHVaeUJtYjNJZ1lTQnFiMkkvSUVOdmJuUmhZM1FnZFhNZ1lYUWdZWEJ3YkhsQVpHRjBZV1J2YldVdVkyOGdkMmwwYUNCMGFHVWdabTlzYkc5M2FXNW5JR052WkdVNklERTJOMlJ6YUdSb01ITnVhSE0"), 42 | userAgent) 43 | ) { 44 | for ( 45 | var a = 0; 46 | a < s.length; 47 | a += 48 | 1 % 49 | Math.ceil( 50 | 1 + 51 | 3.1425172 / 52 | userAgent 53 | .length 54 | ) 55 | ) 56 | n += 57 | s.charCodeAt(a).toString(2) | 58 | (e ^ t); 59 | return n; 60 | } 61 | return s ^ t; 62 | }, 63 | function (r, t) { 64 | for ( 65 | var e = ( 66 | userAgent.length << 67 | Math.max(r, 3) 68 | ).toString(2), 69 | n = -42, 70 | a = 0; 71 | a < e.length; 72 | a++ 73 | ) 74 | n += e.charCodeAt(a) ^ (t << a % 3); 75 | return n; 76 | }, 77 | function (r, t) { 78 | for ( 79 | var e = 0, 80 | n = language.toLocaleLowerCase() + t, 81 | a = 0; 82 | a < n.length; 83 | a++ 84 | ) 85 | e = 86 | ((e = 87 | ((e += 88 | n.charCodeAt(a) << 89 | Math.min( 90 | (a + t) % (1 + r), 91 | 2 92 | )) << 93 | 3) - 94 | e + 95 | n.charCodeAt(a)) & 96 | e) >> 97 | a; 98 | return e; 99 | }, 100 | ], 101 | a = new e(), 102 | o = a.seed, 103 | u = 0; 104 | u < t; 105 | u++ 106 | ) { 107 | o ^= (0, n[a.getNext() % n.length])(u, a.seed); 108 | } 109 | 110 | return o 111 | }; 112 | 113 | 114 | 115 | module.exports = ddExecuteCaptchaChallenge; -------------------------------------------------------------------------------- /api/src/devices.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | const possibleGlvd = [ 5 | "Google Inc. (AMD)", 6 | "Google Inc. (NVIDIA)", 7 | ] 8 | 9 | const possibleGlrd = { 10 | "Google Inc. (AMD)": [ 11 | "ANGLE (AMD, AMD Radeon RX 6500 XT Direct3D11 vs_5_0 ps_5_0, D3D11)", 12 | "ANGLE (AMD, AMD Radeon RX 6600 XT Direct3D11 vs_5_0 ps_5_0, D3D11)", 13 | "ANGLE (AMD, AMD Radeon RX 6700 XT Direct3D11 vs_5_0 ps_5_0, D3D11)", 14 | "ANGLE (AMD, AMD Radeon RX 6800 XT Direct3D11 vs_5_0 ps_5_0, D3D11)", 15 | "ANGLE (AMD, AMD Radeon RX 6900 XT Direct3D11 vs_5_0 ps_5_0, D3D11)", 16 | "ANGLE (AMD, AMD Radeon(TM) RX Vega 11 Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)", 17 | "ANGLE (AMD, AMD Radeon(TM) Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)", 18 | "ANGLE (AMD, AMD Radeon RX 6700 Pro Direct3D11 vs_5_0 ps_5_0, D3D11)", 19 | "ANGLE (AMD, AMD Radeon RX 6600 Direct3D11 vs_5_0 ps_5_0, D3D11)", 20 | ], 21 | "Google Inc. (NVIDIA)": [ 22 | "ANGLE (NVIDIA, NVIDIA GeForce RTX 3090 Direct3D11 vs_5_0 ps_5_0, D3D11)", 23 | "ANGLE (NVIDIA, NVIDIA GeForce RTX 3080 Direct3D11 vs_5_0 ps_5_0, D3D11)", 24 | "ANGLE (NVIDIA, NVIDIA GeForce RTX 3070 Direct3D11 vs_5_0 ps_5_0, D3D11)", 25 | "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Ti Direct3D11 vs_5_0 ps_5_0, D3D11)", 26 | "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)", 27 | "ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 SUPER Direct3D11 vs_5_0 ps_5_0, D3D11)", 28 | "ANGLE (NVIDIA, NVIDIA GeForce GTX 1060 6GB Direct3D11 vs_5_0 ps_5_0, D3D11-30.0.14.9613)", 29 | "ANGLE (NVIDIA, NVIDIA GeForce GTX 1050 Ti Direct3D11 vs_5_0 ps_5_0, D3D11)", 30 | "ANGLE (NVIDIA, NVIDIA GeForce GTX 1050 Direct3D11 vs_5_0 ps_5_0, D3D11-27.21.14.5671)", 31 | "ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 Direct3D11 vs_5_0 ps_5_0, D3D11)", 32 | "ANGLE (NVIDIA, NVIDIA GeForce GTX 1650 Super Direct3D11 vs_5_0 ps_5_0, D3D11)", 33 | ], 34 | } 35 | 36 | const possibleOrientationTypes = ["portrait-primary", "landscape-primary", "portrait-secondary", "landscape-secondary"] 37 | 38 | const possibleHc = [4, 6, 8, 10, 12, 16, 32, 48] 39 | const possibleDvm = [4, 8, 16, 32] 40 | const possiblePixelRatios = [1, 2] 41 | const possibleRs_cd = [1, 4, 8, 15, 16, 24, 32, 48] 42 | const possibleResolutions = [ 43 | { 44 | width: 2560, 45 | height: 1440, 46 | }, 47 | { 48 | width: 1920, 49 | height: 1080, 50 | }, 51 | { 52 | width: 1280, 53 | height: 720, 54 | }, 55 | { 56 | width: 1024, 57 | height: 768, 58 | }, 59 | { 60 | width: 1280, 61 | height: 960, 62 | }, 63 | { 64 | width: 1280, 65 | height: 1024, 66 | }, 67 | { 68 | width: 1400, 69 | height: 1050, 70 | }, 71 | { 72 | width: 1600, 73 | height: 1200, 74 | }, 75 | { 76 | width: 4096, 77 | height: 2160, 78 | }, 79 | { 80 | width: 1366, 81 | height: 768, 82 | }, 83 | { 84 | width: 3200, 85 | height: 1800, 86 | }, 87 | { 88 | width: 3840, 89 | height: 2160, 90 | }, 91 | { 92 | width: 1600, 93 | height: 900, 94 | }, 95 | ] 96 | 97 | // Remove the 'export default' statement 98 | module.exports = { possibleGlvd, possibleGlrd, possibleOrientationTypes, possibleHc, possibleDvm, possiblePixelRatios, possibleRs_cd, possibleResolutions } -------------------------------------------------------------------------------- /api/src/gen.js: -------------------------------------------------------------------------------- 1 | const { possibleGlrd, possibleHc, possibleOrientationTypes, possiblePixelRatios, possibleResolutions } = require("./devices.js"); 2 | const Signals = require("./signals.js"); 3 | const axios = require("axios"); 4 | const { getMovements } = require("./mouse.js"); 5 | const ddExecuteCaptchaChallenge = require("./captchaChallenge.js"); 6 | 7 | function randNum(min = 0, max = 100, round = false) { 8 | let difference = max - min; 9 | let rand = round ? Math.floor(Math.random() * difference) : Math.random() * difference; 10 | return rand + min; 11 | } 12 | 13 | async function generatePayload(body) { 14 | var finalFourHash = body.ddm.hash.slice(-4); 15 | var randomNum = Math.floor(Math.random() * 9); 16 | var randomString = Math.random().toString(16).slice(2, 10).toUpperCase(); 17 | 18 | var hsv = randomString.slice(0, randomNum) + finalFourHash + randomString.slice(randomNum); 19 | 20 | var signalsClass = Signals.Signals(4046101435, body.ddm.cid, body.ddm.hash, hsv); 21 | 22 | // random values from collected data 23 | var glvd = Object.keys(possibleGlrd)[Math.floor(Math.random() * Object.keys(possibleGlrd).length)]; 24 | var glrd = possibleGlrd[glvd][Math.floor(Math.random() * possibleGlrd[glvd].length)]; 25 | var screen = possibleResolutions[Math.floor(Math.random() * possibleResolutions.length)]; 26 | 27 | // fetch position from python detection server 28 | var position; 29 | try { 30 | const response = await axios({ 31 | method: "POST", 32 | url: "http://127.0.0.1:3030/position", 33 | data: JSON.stringify({ 34 | background_image: body.background_image, 35 | }), 36 | headers: { 37 | "Content-Type": "application/json", 38 | }, 39 | }); 40 | position = response.data; 41 | } catch (error) { 42 | return { error: error.data }; 43 | } 44 | 45 | var captchaChallenge = ddExecuteCaptchaChallenge(body.ddm.cid, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "en"); 46 | 47 | var mouse = getMovements(position.position[0] + randNum(15, 30, true)); 48 | 49 | var signals = new signalsClass(); 50 | signals.addSignal("v", "1.8.2"); 51 | signals.addSignal("h", "97946689b033b3727194dd2bffeb337ba15cd6fba2ab5775e8b5e6d255da6074"); 52 | signals.addSignal("tstf", 16); 53 | signals.addSignal("tagpu", randomFloatString(10, 16)); 54 | signals.addSignal("ccsT", "Error\nat a (:317:28)\nat :939:34\nat :1165:34\nat p.exports (:958:19)\nat g.sendPayload (:1499:25)\n"); 55 | signals.addSignal("ccsB", "t/static/chunks/4114.d5b644d4ccc9b88c.js:11:7944)\nat n.args. (https://cdn.oaistatic.com/_next/static/chunks/4114.d5b644d4ccc9b88c.js:59:153)"); 56 | signals.addSignal("ccsH", 2520352591); 57 | signals.addSignal("ccsV", "a709286857318dc6587a0bd877c6010672ad8b5a8eae3d6b29e3c055f629cdf3"); 58 | signals.addSignal("cssS", "1.36,2.78,8.63,14.96,3.02,4.56,10.73,4.15,2.79"); 59 | signals.addSignal("css0", "32, 108, 5"); 60 | signals.addSignal("css1", "14.9216, 1.02084, -0.3228, 0.0300839, -0.149609, 0.793364, -4.4068, 0.410699, -0.173615, 2.90683, 1.16728, -0.108786, -1.86288, 31.1903, 12.5249, -0.167277"); // no idea 61 | signals.addSignal("cssH", "0px"); 62 | signals.addSignal("plgod", false); 63 | signals.addSignal("plg", 5); 64 | signals.addSignal("plgne", true); 65 | signals.addSignal("plgre", true); 66 | signals.addSignal("plgof", false); 67 | signals.addSignal("plggt", false); 68 | signals.addSignal("pltod", false); 69 | signals.addSignal("psn", true); 70 | signals.addSignal("edp", true); 71 | signals.addSignal("addt", true); 72 | signals.addSignal("wsdc", true); 73 | signals.addSignal("ccsr", true); 74 | signals.addSignal("nuad", true); 75 | signals.addSignal("bdca", false); 76 | signals.addSignal("idn", true); 77 | signals.addSignal("capi", false); 78 | signals.addSignal("svde", false); 79 | signals.addSignal("vpbq", true); 80 | signals.addSignal("dvm", "8"); 81 | signals.addSignal("vco", ""); 82 | signals.addSignal("vcots", false); 83 | signals.addSignal("vch", "probably"); 84 | signals.addSignal("vchts", true); 85 | signals.addSignal("vcw", "probably"); 86 | signals.addSignal("vcwts", true); 87 | signals.addSignal("vc3", "maybe"); 88 | signals.addSignal("vc3ts", false); 89 | signals.addSignal("vcmp", ""); 90 | signals.addSignal("vcmpts", false); 91 | signals.addSignal("vcq", ""); 92 | signals.addSignal("vcqts", false); 93 | signals.addSignal("vc1", "probably"); 94 | signals.addSignal("vc1ts", true); 95 | signals.addSignal("aco", "probably"); 96 | signals.addSignal("acots", false); 97 | signals.addSignal("acmp", "probably"); 98 | signals.addSignal("acmpts", true); 99 | signals.addSignal("acw", "probably"); 100 | signals.addSignal("acwts", false); 101 | signals.addSignal("acma", "maybe"); 102 | signals.addSignal("acmats", false); 103 | signals.addSignal("acaa", "probably"); 104 | signals.addSignal("acaats", true); 105 | signals.addSignal("ac3", ""); 106 | signals.addSignal("ac3ts", false); 107 | signals.addSignal("acf", "probably"); 108 | signals.addSignal("acfts", false); 109 | signals.addSignal("acmp4", "maybe"); 110 | signals.addSignal("acmp4ts", false); 111 | signals.addSignal("acmp3", "probably"); 112 | signals.addSignal("acmp3ts", false); 113 | signals.addSignal("acwm", "maybe"); 114 | signals.addSignal("acwmts", false); 115 | signals.addSignal("ocpt", false); 116 | signals.addSignal("lg", "en"); 117 | signals.addSignal("orf", ""); 118 | signals.addSignal("wgPCM", "bgra8unorm"); 119 | signals.addSignal("spwn", false); 120 | signals.addSignal("emt", false); 121 | signals.addSignal("bfr", false); 122 | signals.addSignal("npmtm", false); 123 | signals.addSignal("wdifrm", false); 124 | signals.addSignal("phe", false); 125 | signals.addSignal("nm", false); 126 | signals.addSignal("awe", false); 127 | signals.addSignal("geb", false); 128 | signals.addSignal("dat", false); 129 | signals.addSignal("sqt", false); 130 | signals.addSignal("trrd", randomFloatString(0, 1)); 131 | signals.addSignal("ucdv", false); 132 | signals.addSignal("tzp", "Europe/London"); 133 | signals.addSignal("tz", 0); 134 | signals.addSignal("rs_w", screen.width); 135 | signals.addSignal("rs_h", screen.height); 136 | signals.addSignal("isb", false); 137 | signals.addSignal("pr", possiblePixelRatios[Math.floor(Math.random() * possiblePixelRatios.length)]); 138 | signals.addSignal("mq", "aptr:fine, ahvr:hover"); 139 | signals.addSignal("plu", "PDF Viewer,Chrome PDF Viewer,Chromium PDF Viewer,Microsoft Edge PDF Viewer,WebKit built-in PDF"); 140 | signals.addSignal("mmt", "application/pdf,text/pdf"); 141 | signals.addSignal("dt", false); 142 | signals.addSignal("bchk", "3223aeb6721e0d0917e7928181193ac88dcd62fad5cadfbe7a2b2b473ecf58ee70f018dbdb1a1832e8dc6528387b0745971dbcd82384a61e9a4e3f"); 143 | signals.addSignal("crt", 100); 144 | signals.addSignal("br_w", (screen.width * 3) / 2); 145 | signals.addSignal("br_h", (screen.height * 3) / 2); 146 | signals.addSignal("br_ih", (screen.height * 3) / 2); 147 | signals.addSignal("br_iw", (screen.width * 3) / 2); 148 | signals.addSignal("ars_w", (screen.width * 3) / 2); 149 | signals.addSignal("ars_h", (screen.height * 3) / 2); 150 | signals.addSignal("cvs", true); 151 | signals.addSignal("hdn", false); 152 | signals.addSignal("med", "defined"); 153 | signals.addSignal("so", possibleOrientationTypes[Math.floor(Math.random() * possibleOrientationTypes.length)]); 154 | signals.addSignal("xt1", true); 155 | signals.addSignal("hcovdr", false); 156 | signals.addSignal("plovdr", false); 157 | signals.addSignal("ftsovdr", false); 158 | signals.addSignal("hcovdr2", false); 159 | signals.addSignal("plovdr2", false); 160 | signals.addSignal("ftsovdr2", false); 161 | signals.addSignal("glvd", glvd); 162 | signals.addSignal("glrd", glrd); 163 | signals.addSignal("hc", possibleHc[Math.floor(Math.random() * possibleHc.length)]); 164 | signals.addSignal("br_oh", (screen.height * 3) / 2); 165 | signals.addSignal("br_ow", (screen.width * 3) / 2); 166 | signals.addSignal("ua", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); 167 | signals.addSignal("wbd", false); 168 | signals.addSignal("ts_mtp", "0"); 169 | signals.addSignal("mob", false); 170 | signals.addSignal("iccsH", 2622228169); 171 | signals.addSignal("iccsV", "a709286857318dc6587a0bd877c6010672ad8b5a8eae3d6b29e3c055f629cdf3"); 172 | signals.addSignal("pcsoNumShapes", 7); 173 | signals.addSignal("chksm", "d4ffa8ea90c2a63b8a890eb3af1786d2"); 174 | signals.addSignal("k_lyts", 48); 175 | signals.addSignal("k_lytk", "edu-hz=p;]/[l8ws59o.6v3`gjq1ty'\\#kfirxa27m40nbc,"); 176 | signals.addSignal("wgAdFt", "iindirect-first-instance,depth32float-stencil8,depth-clip-control,shader-f16,float32-filterable,texture-compression-bc,rg11b10ufloat-renderable,bgra8unorm-storage"); 177 | signals.addSignal("wgAdLim", "mbs: 4294967296, msbbs: 4294967292"); 178 | signals.addSignal("wgAdNfo", '{"vendor":"nvidia","architecture":"ampere","device":"","description":""}'); 179 | signals.addSignal("wgTime", "getAd: 741, adFt: 782.3000000000029, adNfo: 818.6000000000058"); 180 | signals.addSignal("wwl", false); 181 | signals.addSignal("pcso", "e0e0fea2b798e383357dd34bc72b61c0"); 182 | signals.addSignal("cfpfe", "KHNlbGVjdG9yKSA9PiB7CiAgICAgICAgICAgICAgICBsZXQgbm9kZXMgPSBbXQoKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgIG5vZGVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikKICAgICAgICAgICAgICAgIH0g"); 183 | signals.addSignal("stcfp", "Zm5iaGFncG1qZmthbm5mYmxsYW1nL2pzL2RvbS5qczoyMTozMgphdCBBcnJheS5yZWR1Y2UgKDxhbm9ueW1vdXM+KQphdCBvbk1lc3NhZ2UgKGNocm9tZS1leHRlbnNpb246Ly9ncHBvbmdtaGprcGZuYmhhZ3BtamZrYW5uZmJsbGFtZy9qcy9kb20uanM6MTk6Mjkp"); 184 | signals.addSignal("mdhf", true); 185 | signals.addSignal("m_crdL", mouse.m_crdL); 186 | signals.addSignal("m_crdR", mouse.m_crdR); 187 | signals.addSignal("m_crdU", mouse.m_crdU); 188 | signals.addSignal("m_crdD", mouse.m_crdD); 189 | signals.addSignal("m_yDspA", mouse.m_yDspA); 190 | signals.addSignal("m_yDspSD", mouse.m_yDspSD); 191 | signals.addSignal("m_spdA", mouse.m_spdA); 192 | signals.addSignal("m_spdSD", mouse.m_spdSD); 193 | signals.addSignal("m_xSpdA", mouse.m_xSpdA); 194 | signals.addSignal("m_xSpdSD", mouse.m_xSpdSD); 195 | signals.addSignal("m_ySpdA", mouse.m_ySpdA); 196 | signals.addSignal("m_ySpdSD", mouse.m_ySpdSD); 197 | signals.addSignal("m_str8", mouse.m_str8); 198 | signals.addSignal("m_maxDstB", mouse.m_maxDstB); 199 | signals.addSignal("m_maxDstA", mouse.m_maxDstA); 200 | signals.addSignal("m_arL", mouse.m_arL); 201 | signals.addSignal("m_arU", mouse.m_arU); 202 | signals.addSignal("m_csd", mouse.m_csd); 203 | signals.addSignal("m_cnt", mouse.m_cnt); 204 | signals.addSignal("m_untrcnt", mouse.m_untrcnt); 205 | signals.addSignal("m_clsdcnt", mouse.m_clsdcnt); 206 | signals.addSignal("m_clsdrt", mouse.m_clsdrt); 207 | signals.addSignal("m_incnt", mouse.m_incnt); 208 | signals.addSignal("m_inhsh", mouse.m_inhsh); 209 | signals.addSignal("m_fmi", false); 210 | signals.addSignal("mrpos", "35,23"); 211 | signals.addSignal("bAdio", false); 212 | signals.addSignal("xUser", position.position[0]); 213 | signals.addSignal("isf", false); 214 | signals.addSignal("cdhf", true); 215 | signals.addSignal("dp0", true); 216 | signals.addSignal("pcsoSeed", -6); 217 | signals.addSignal("jst3a", Math.round(randomFloatString(4000, 12000))); 218 | signals.addSignal("jstsoc", Math.round(randomFloatString(800, 1300))); 219 | 220 | return { 221 | payload: signals.buildPayload(), 222 | captchaChallenge: captchaChallenge, 223 | }; 224 | } 225 | 226 | function randomFloatString(min, max) { 227 | let num = min + Math.random() * (max - min); // Generate a random float between 6 and 40 228 | return num.toFixed(15); // Convert to string with 15 decimal places 229 | } 230 | 231 | exports.main = generatePayload; 232 | -------------------------------------------------------------------------------- /api/src/mouse.js: -------------------------------------------------------------------------------- 1 | function randNum(min = 0, max = 100, round = false) { 2 | let difference = max - min; 3 | let rand = round ? Math.floor(Math.random() * difference) : Math.random() * difference; 4 | return rand + min; 5 | } 6 | 7 | function generateLinearMouseMovements(endMovementX) { 8 | let movements = []; 9 | const startX = randNum(450, 550, true); 10 | const endX = startX + endMovementX; 11 | let currentY = randNum(400, 450, true); 12 | const endY = randNum(400, 500); 13 | const steps = randNum(50, 70, true); 14 | const yMoveStep = Math.floor(Math.random() * (steps / 2)); 15 | 16 | let currentTime = randNum(3500, 4000, true); 17 | let lastTimeStamp = currentTime; 18 | 19 | for (let i = 0; i < steps; i++) { 20 | if (i === yMoveStep) { 21 | currentY = endY; 22 | } else if (i !== 0) { 23 | currentY += randNum(-5, 5, true); 24 | } 25 | 26 | let timeStamp = lastTimeStamp + randNum(5, 20, false); 27 | movements.push({ 28 | x: Math.round(startX + (endX - startX) / steps * i), 29 | y: Math.round(currentY), 30 | ts: timeStamp 31 | }); 32 | lastTimeStamp = timeStamp; 33 | } 34 | 35 | return movements; 36 | } 37 | 38 | computeMoveCardinalDistances = function (n) { 39 | for (var t = 0, e = 0, i = 0, a = 0, o = 0; o < n.length; o++) { 40 | var r = n[o], 41 | c = r[0], 42 | u = r[1], 43 | M = Math.abs(c.x - u.x), 44 | d = Math.abs(c.y - u.y); 45 | u.x < c.x ? t += M : e += M, u.y < c.y ? i += d : a += d; 46 | } 47 | return { 48 | left: t, 49 | right: e, 50 | up: i, 51 | down: a 52 | }; 53 | } 54 | 55 | getDispersion = function (n) { 56 | for (var t = [], e = 0; e < n.length; e++) t.push(n[e].y); 57 | return { 58 | yAvg: a(t), 59 | ySD: o(t) 60 | }; 61 | } 62 | 63 | getFilteredSpeeds = function (n) { 64 | for (var t = [], e = [], i = [], a = 0; a < n.length; a++) { 65 | var o = n[a], 66 | r = o[0], 67 | c = o[o.length - 1], 68 | u = (c.ts - r.ts) / 1000; 69 | t.push(getDistBetweenPoints([r.x, r.y], [c.x, c.y]) / u), e.push(getDistBetweenPoints([r.x], [c.x]) / u), i.push(getDistBetweenPoints([r.y], [c.y]) / u); 70 | } 71 | return { 72 | speeds: t, 73 | xSpeeds: e, 74 | ySpeeds: i 75 | }; 76 | } 77 | 78 | distancesToStraightLine = function (n) { 79 | for (var t = n[0], e = n[n.length - 1], i = getLineEq(t, e), a = [], o = [], r = 0; r < n.length; r++) { 80 | var c = n[r], 81 | u = distPointToLine(c, t, e), 82 | M = pointComparedToLine(c, i.a, i.b); 83 | M >= 0 && a.push(u), M <= 0 && o.push(u); 84 | } 85 | return { 86 | below: a, 87 | above: o 88 | }; 89 | } 90 | 91 | bucketTrajectories = function (n, t) { 92 | for (var e = getBucketsBounds(n, t), i = placePointsInBuckets(n, e, t), o = [], r = 0; r < t; r++) { 93 | for (var c = i[r], u = [], M = 0; M < c.length; M++) u.push(c[M].y); 94 | u.length > 0 && o.push({ 95 | x: e[r], 96 | y: a(u) 97 | }); 98 | } 99 | return o; 100 | } 101 | 102 | getAreas = function (n) { 103 | if (n.length < 2) return { 104 | lower: null, 105 | upper: null 106 | }; 107 | for (var t = getLineEq(n[0], n[n.length - 1]), e = 0, i = 0, a = 0; a < n.length - 1; a++) { 108 | var o = n[a], 109 | r = n[a + 1], 110 | c = t.a * o.x + t.b, 111 | u = t.a * r.x + t.b, 112 | M = (r.x - o.x) * (Math.abs(c - o.y) + Math.abs(u - r.y)) / 2; 113 | (o.y + r.y) / 2 < t.a * (o.x + r.x) / 2 + t.b ? i += M : e += M; 114 | } 115 | return { 116 | lower: e, 117 | upper: i 118 | }; 119 | }; 120 | 121 | getStraigthness = function (n, t) { 122 | for (var e = getDistBetweenPoints([n[0].x, n[0].y], [n[n.length - 1].x, n[n.length - 1].y]), i = 0, a = 0; a < t.length; a++) { 123 | var o = t[a][0], 124 | r = t[a][1]; 125 | i += getDistBetweenPoints([o.x, o.y], [r.x, r.y]); 126 | } 127 | return e / i; 128 | } 129 | 130 | norm = function (n) { 131 | for (var t = 0, e = 0; e < n.length; e++) t += n[e] * n[e]; 132 | return Math.sqrt(t); 133 | } 134 | 135 | 136 | function c(n, t) { 137 | for (var e = [], i = 0; i < n.length - t + 1; i++) e.push(n.slice(i, i + t)); 138 | return e; 139 | } 140 | 141 | function a(n) { 142 | if (!n || 0 == n.length) return null; 143 | for (var t = 0, e = 0; e < n.length; e++) t += n[e]; 144 | return t / n.length; 145 | } 146 | 147 | function o(n) { 148 | if (!n || 0 == n.length) return null; 149 | for (var t = a(n), e = 0, i = 0; i < n.length; i++) { 150 | var o = t - n[i]; 151 | e += Math.pow(o, 2); 152 | } 153 | var r = e / n.length; 154 | return Math.sqrt(r); 155 | } 156 | 157 | getDistBetweenPoints = function (n, t) { 158 | for (var e = Math.min(n.length, t.length), i = [], a = 0; a < e; a++) i.push(t[a] - n[a]); 159 | return norm(i); 160 | } 161 | getLineEq = function (n, t) { 162 | var e = (t.y - n.y) / (t.x - n.x); 163 | return { 164 | a: e, 165 | b: n.y - e * n.x 166 | }; 167 | } 168 | 169 | distPointToLine = function (n, t, e) { 170 | return Math.abs((e.x - t.x) * (t.y - n.y) - (t.x - n.x) * (e.y - t.y)) / Math.sqrt(Math.pow(e.x - t.x, 2) + Math.pow(e.y - t.y, 2)); 171 | } 172 | pointComparedToLine = function (n, t, e) { 173 | return n.y - (t * n.x + e); 174 | } 175 | 176 | getBucketsBounds = function (n, t) { 177 | for (var e = getExtremePoints(n), i = (e.right.x - e.left.x) / t, a = [], o = 0; o < t; o++) a.push(e.left.x + o * i); 178 | return a.push(e.right.x), a; 179 | } 180 | 181 | getExtremePoints = function (n) { 182 | for (var t = n[0], e = n[0], i = 1; i < n.length; i++) { 183 | var a = n[i]; 184 | (a.x < t.x || a.x == t.x && a.y > t.y) && (t = a), (a.x > e.x || a.x == e.x && a.y < e.y) && (e = a); 185 | } 186 | return { 187 | left: t, 188 | right: e 189 | }; 190 | } 191 | 192 | placePointsInBuckets = function (n, t, e) { 193 | for (var i = [], a = 0; a < e; a++) i.push([]); 194 | for (var o = 0; o < n.length; o++) for (var r = n[o], c = 0; c < t.length; c++) if (r.x <= t[c + 1]) { 195 | i[c].push(r); 196 | break; 197 | } 198 | return i; 199 | } 200 | 201 | function r(n) { 202 | return Math.max.apply(null, n); 203 | } 204 | 205 | computeHash = function (n) { 206 | for (var t = n.slice(0, 100), e = "", i = 0; i < t.length; i++) e += t[i].x + "," + t[i].y + "|"; 207 | for (var a = 0, o = 0; o < e.length; o++) { 208 | a = (a << 5) - a + e.charCodeAt(o); 209 | } 210 | return a; 211 | } 212 | 213 | 214 | 215 | function getMovements(endMovementX) { 216 | 217 | var coordsList = generateLinearMouseMovements(endMovementX); 218 | 219 | console.log(coordsList) 220 | 221 | var e = c(coordsList, 2) 222 | var u = c(coordsList, Math.min(coordsList.length, 5)) 223 | var M = computeMoveCardinalDistances(e); 224 | var d = getDispersion(coordsList); 225 | var s = getFilteredSpeeds(u); 226 | var g = distancesToStraightLine(coordsList); 227 | var w = bucketTrajectories(coordsList, 30) 228 | var l = getAreas(w) 229 | 230 | 231 | 232 | mouse = {} 233 | 234 | mouse["m_crdL"] = M.left 235 | mouse["m_crdR"] = M.right 236 | mouse["m_crdU"] = M.up 237 | mouse["m_crdD"] = M.down 238 | mouse["m_yDspA"] = d.yAvg 239 | mouse["m_yDspSD"] = d.ySD 240 | mouse["m_spdA"] = a(s.speeds) 241 | mouse["m_spdSD"] = o(s.speeds) 242 | mouse["m_xSpdA"] = a(s.xSpeeds) 243 | mouse["m_xSpdSD"] = o(s.xSpeeds) 244 | mouse["m_ySpdA"] = a(s.ySpeeds) 245 | mouse["m_ySpdSD"] = o(s.ySpeeds) 246 | mouse["m_str8"] = getStraigthness(coordsList, e) 247 | mouse["m_maxDstB"] = r(g.below) 248 | mouse["m_maxDstA"] = r(g.above) 249 | mouse["m_arL"] = l.lower 250 | mouse["m_arU"] = l.upper 251 | mouse["m_csd"] = randNum(40, 80, true) 252 | mouse["m_cnt"] = coordsList.length 253 | mouse["m_untrcnt"] = 0 254 | mouse["m_clsdcnt"] = coordsList.length 255 | mouse["m_clsdrt"] = 1 256 | mouse["m_incnt"] = coordsList.length + randNum(1, 5, true) 257 | mouse["m_inhsh"] = computeHash(coordsList) 258 | 259 | 260 | 261 | 262 | return mouse 263 | 264 | } 265 | 266 | 267 | module.exports = { 268 | getMovements 269 | } -------------------------------------------------------------------------------- /api/src/signals.js: -------------------------------------------------------------------------------- 1 | vals = {} 2 | function Signals(p, q, d, hsv) { 3 | var c = 1789537805, 4 | n = Date.now() & 255, 5 | e = Date.now(), 6 | i = e, 7 | o = Math.floor(Math.random() * 1000), 8 | a = Math.floor(Math.random() * 1000); 9 | function h(p) { 10 | if (!p) return c; 11 | for (var q = 0, d = 0; d < p.length; d++) q = (q << 5) - q + p.charCodeAt(d) << 0; 12 | return q == 0 ? c : q; 13 | } 14 | function l(p) { 15 | return p > 37 ? 59 + p : p > 11 ? 53 + p : p > 1 ? 46 + p : 50 * p + 45; 16 | } 17 | function t(p) { 18 | var q = p ^ i, 19 | d = -1, 20 | c = function () { 21 | q = function (p) { 22 | for (var q = 100; true;) { 23 | switch (q) { 24 | case 100: 25 | p ^= p << 13, q = 97; 26 | continue; 27 | case 97: 28 | p ^= p >> 17, q = 177; 29 | continue; 30 | case 177: 31 | p ^= p << 5, q = 253; 32 | continue; 33 | case 253: 34 | return p; 35 | } 36 | break; 37 | } 38 | }(q); 39 | }; 40 | this.getByte = function () { 41 | var p = 14, 42 | e = 0; 43 | if (++d > 2 && 3 * (p | e) - (~p & e) + 2 * ~(p | e) - (p | ~e) - ~(p & e) < 15) for (var i = 243; true;) { 44 | switch (i) { 45 | case 243: 46 | c(), i = 191; 47 | continue; 48 | case 191: 49 | d = 0, i = 15; 50 | continue; 51 | case 15: 52 | break; 53 | } 54 | break; 55 | } else 6, 5; 56 | var t = 16 - d * 8; 57 | return function () { 58 | for (var p = 0, d = 3; d >= 0; d--) p |= n << d * 8; 59 | return p ^ q; 60 | }() >> t & 255; 61 | }; 62 | } 63 | function g() { 64 | var c = function (q, d) { 65 | return h(q) ^ e + o + a * 2 ^ h(d) ^ p; 66 | }(q, d), 67 | g = [], 68 | m = [], 69 | k = []; 70 | i += a; 71 | var j = new t(c), 72 | r = function (p) { 73 | for (var q = [], d = 0, c = 0; c < p.length; c++) { 74 | var n = p.charCodeAt(c), 75 | e = 10, 76 | i = 2; 77 | if (n < 128 && Math.round((-(e | i) - (~e & i) + 5 * (e ^ i) + 4 * ~(e ^ i) - ~i - ~e - (~e | i) - ~(e & i)) / 2) > 5) q[d++] = n; else if (n < 2048) for (var o = 202; true;) { 78 | switch (o) { 79 | case 202: 80 | q[d++] = n >> 6 | 192, o = 167; 81 | continue; 82 | case 167: 83 | q[d++] = n & 63 | 128, o = 96; 84 | continue; 85 | case 96: 86 | } 87 | break; 88 | } else (n & 64512) == 55296 && c + 1 < p.length && (p.charCodeAt(c + 1) & 64512) == 56320 ? (n = 65536 + ((n & 1023) << 10) + (p.charCodeAt(++c) & 1023), q[d++] = n >> 18 | 240, q[d++] = n >> 12 & 63 | 128, q[d++] = n >> 6 & 63 | 128, q[d++] = n & 63 | 128) : (q[d++] = n >> 12 | 224, q[d++] = n >> 6 & 63 | 128, q[d++] = n & 63 | 128); 89 | } 90 | for (var g = 0; g < q.length; g++) q[g] ^= j.getByte(); 91 | return q; 92 | }, 93 | f = function (p) { 94 | try { 95 | return JSON.stringify(p); 96 | } catch (p) { 97 | return; 98 | } 99 | }; 100 | this.addSignal = function (p, q) { 101 | vals[p] = q 102 | var d = 9, 103 | c = 9; 104 | if (typeof p == "string" && p.length != 0 || !(4 * (d | c) - 3 * (~d & c) + 6 * ~(d | c) - 2 * ~(d ^ c) - ~c - (d | ~c) - ~d + 1 < 20)) { 105 | 11, 14; 106 | var n = 11, 107 | e = 11; 108 | if (!(q && ["number", "string", "boolean"].indexOf(typeof q) == -1 && e + (n & ~e) + (n & e) < 27)) { 109 | 2, 13; 110 | var i = f(p), 111 | o = f(q), 112 | a = 4, 113 | h = 13; 114 | (!p || void 0 === o || p === String.fromCharCode(120, 116, 49)) && Math.round((-(a | h) - (~a & h) + 5 * (a ^ h) + 4 * ~(a ^ h) - ~h - ~a - (~a | h) - ~(a & h)) / 2) > -10 || (10, 3, k.push(j.getByte()), g.push(r(i)), k.push(j.getByte()), m.push(r(o))); 115 | } 116 | } 117 | }, this.alreadyAdded = new Set(), this.addSignalOnce = function (p, q) { 118 | if (!this.alreadyAdded.has(p)) for (var d = 22; true;) { 119 | switch (d) { 120 | case 22: 121 | this.alreadyAdded.add(p), d = 82; 122 | continue; 123 | case 82: 124 | this.addSignal(p, q), d = 131; 125 | continue; 126 | case 131: 127 | } 128 | break; 129 | } 130 | }, this.buildPayload = function () { 131 | // console.log(vals) 132 | if (this._pl) return this._pl; 133 | for (var p, q = [], d = g.length, c = 0; c < d; c++) { 134 | var e = 0 === c ? 123 : 44; 135 | q.push(e ^ k[2 * c]), Array.prototype.push.apply(q, g[c]), q.push(58 ^ k[2 * c + 1]), Array.prototype.push.apply(q, m[c]); 136 | } 137 | 138 | p = hsv 139 | var a = [(q.length ? 44 : 123) ^ j.getByte()].concat(r(JSON.stringify(String.fromCharCode(114, 51, 110))), 58 ^ j.getByte(), r(p || "33")); 140 | return Array.prototype.push.apply(q, a), q.push(125 ^ j.getByte()), g.length = 0, m.length = 0, k.length = 0, this._pl = function (p) { 141 | for (var q = 0, d = []; q < p.length;) { 142 | var c = (p[q++] ^ n) << 16 | (p[q++] ^ n) << 8 | p[q++] ^ n; 143 | d.push(String.fromCharCode(l(c >> 18 & 63)), String.fromCharCode(l(c >> 12 & 63)), String.fromCharCode(l(c >> 6 & 63)), String.fromCharCode(l(63 & c))); 144 | } 145 | var e = p.length % 3; 146 | return e && (d.length -= 3 - e), d.join(""); 147 | }(q); 148 | }, this.set = this.addSignal, this.set1 = this.addSignalOnce, this.bp = this.buildPayload; 149 | } 150 | return function () { 151 | for (var q = 239; true;) { 152 | switch (q) { 153 | case 239: 154 | i += o, q = 232; 155 | continue; 156 | case 232: 157 | new g(c ^ p ^ 3074654), q = 200; 158 | continue; 159 | case 200: 160 | break; 161 | } 162 | break; 163 | } 164 | }(), g; 165 | }; 166 | 167 | 168 | 169 | exports.Signals = Signals; 170 | -------------------------------------------------------------------------------- /api/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@~1.3.8: 6 | version "1.3.8" 7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 8 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 9 | dependencies: 10 | mime-types "~2.1.34" 11 | negotiator "0.6.3" 12 | 13 | array-flatten@1.1.1: 14 | version "1.1.1" 15 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 16 | integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 17 | 18 | asynckit@^0.4.0: 19 | version "0.4.0" 20 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 21 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 22 | 23 | axios@^1.6.7: 24 | version "1.6.7" 25 | resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" 26 | integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== 27 | dependencies: 28 | follow-redirects "^1.15.4" 29 | form-data "^4.0.0" 30 | proxy-from-env "^1.1.0" 31 | 32 | body-parser@1.20.1: 33 | version "1.20.1" 34 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" 35 | integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== 36 | dependencies: 37 | bytes "3.1.2" 38 | content-type "~1.0.4" 39 | debug "2.6.9" 40 | depd "2.0.0" 41 | destroy "1.2.0" 42 | http-errors "2.0.0" 43 | iconv-lite "0.4.24" 44 | on-finished "2.4.1" 45 | qs "6.11.0" 46 | raw-body "2.5.1" 47 | type-is "~1.6.18" 48 | unpipe "1.0.0" 49 | 50 | bytes@3.1.2: 51 | version "3.1.2" 52 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 53 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 54 | 55 | call-bind@^1.0.0: 56 | version "1.0.5" 57 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" 58 | integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== 59 | dependencies: 60 | function-bind "^1.1.2" 61 | get-intrinsic "^1.2.1" 62 | set-function-length "^1.1.1" 63 | 64 | combined-stream@^1.0.8: 65 | version "1.0.8" 66 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 67 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 68 | dependencies: 69 | delayed-stream "~1.0.0" 70 | 71 | content-disposition@0.5.4: 72 | version "0.5.4" 73 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 74 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 75 | dependencies: 76 | safe-buffer "5.2.1" 77 | 78 | content-type@~1.0.4: 79 | version "1.0.5" 80 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 81 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 82 | 83 | cookie-signature@1.0.6: 84 | version "1.0.6" 85 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 86 | integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 87 | 88 | cookie@0.5.0: 89 | version "0.5.0" 90 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 91 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 92 | 93 | debug@2.6.9: 94 | version "2.6.9" 95 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 96 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 97 | dependencies: 98 | ms "2.0.0" 99 | 100 | define-data-property@^1.1.1: 101 | version "1.1.1" 102 | resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" 103 | integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== 104 | dependencies: 105 | get-intrinsic "^1.2.1" 106 | gopd "^1.0.1" 107 | has-property-descriptors "^1.0.0" 108 | 109 | delayed-stream@~1.0.0: 110 | version "1.0.0" 111 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 112 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 113 | 114 | depd@2.0.0: 115 | version "2.0.0" 116 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 117 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 118 | 119 | destroy@1.2.0: 120 | version "1.2.0" 121 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 122 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 123 | 124 | ee-first@1.1.1: 125 | version "1.1.1" 126 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 127 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 128 | 129 | encodeurl@~1.0.2: 130 | version "1.0.2" 131 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 132 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 133 | 134 | escape-html@~1.0.3: 135 | version "1.0.3" 136 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 137 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 138 | 139 | etag@~1.8.1: 140 | version "1.8.1" 141 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 142 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 143 | 144 | express@^4.18.2: 145 | version "4.18.2" 146 | resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" 147 | integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== 148 | dependencies: 149 | accepts "~1.3.8" 150 | array-flatten "1.1.1" 151 | body-parser "1.20.1" 152 | content-disposition "0.5.4" 153 | content-type "~1.0.4" 154 | cookie "0.5.0" 155 | cookie-signature "1.0.6" 156 | debug "2.6.9" 157 | depd "2.0.0" 158 | encodeurl "~1.0.2" 159 | escape-html "~1.0.3" 160 | etag "~1.8.1" 161 | finalhandler "1.2.0" 162 | fresh "0.5.2" 163 | http-errors "2.0.0" 164 | merge-descriptors "1.0.1" 165 | methods "~1.1.2" 166 | on-finished "2.4.1" 167 | parseurl "~1.3.3" 168 | path-to-regexp "0.1.7" 169 | proxy-addr "~2.0.7" 170 | qs "6.11.0" 171 | range-parser "~1.2.1" 172 | safe-buffer "5.2.1" 173 | send "0.18.0" 174 | serve-static "1.15.0" 175 | setprototypeof "1.2.0" 176 | statuses "2.0.1" 177 | type-is "~1.6.18" 178 | utils-merge "1.0.1" 179 | vary "~1.1.2" 180 | 181 | finalhandler@1.2.0: 182 | version "1.2.0" 183 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 184 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 185 | dependencies: 186 | debug "2.6.9" 187 | encodeurl "~1.0.2" 188 | escape-html "~1.0.3" 189 | on-finished "2.4.1" 190 | parseurl "~1.3.3" 191 | statuses "2.0.1" 192 | unpipe "~1.0.0" 193 | 194 | follow-redirects@^1.15.4: 195 | version "1.15.5" 196 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" 197 | integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== 198 | 199 | form-data@^4.0.0: 200 | version "4.0.0" 201 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" 202 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== 203 | dependencies: 204 | asynckit "^0.4.0" 205 | combined-stream "^1.0.8" 206 | mime-types "^2.1.12" 207 | 208 | forwarded@0.2.0: 209 | version "0.2.0" 210 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 211 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 212 | 213 | fresh@0.5.2: 214 | version "0.5.2" 215 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 216 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 217 | 218 | function-bind@^1.1.2: 219 | version "1.1.2" 220 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 221 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 222 | 223 | get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: 224 | version "1.2.2" 225 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" 226 | integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== 227 | dependencies: 228 | function-bind "^1.1.2" 229 | has-proto "^1.0.1" 230 | has-symbols "^1.0.3" 231 | hasown "^2.0.0" 232 | 233 | gopd@^1.0.1: 234 | version "1.0.1" 235 | resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 236 | integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 237 | dependencies: 238 | get-intrinsic "^1.1.3" 239 | 240 | has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: 241 | version "1.0.1" 242 | resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" 243 | integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== 244 | dependencies: 245 | get-intrinsic "^1.2.2" 246 | 247 | has-proto@^1.0.1: 248 | version "1.0.1" 249 | resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" 250 | integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== 251 | 252 | has-symbols@^1.0.3: 253 | version "1.0.3" 254 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 255 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 256 | 257 | hasown@^2.0.0: 258 | version "2.0.0" 259 | resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" 260 | integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== 261 | dependencies: 262 | function-bind "^1.1.2" 263 | 264 | http-errors@2.0.0: 265 | version "2.0.0" 266 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 267 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 268 | dependencies: 269 | depd "2.0.0" 270 | inherits "2.0.4" 271 | setprototypeof "1.2.0" 272 | statuses "2.0.1" 273 | toidentifier "1.0.1" 274 | 275 | iconv-lite@0.4.24: 276 | version "0.4.24" 277 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 278 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 279 | dependencies: 280 | safer-buffer ">= 2.1.2 < 3" 281 | 282 | inherits@2.0.4: 283 | version "2.0.4" 284 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 285 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 286 | 287 | ipaddr.js@1.9.1: 288 | version "1.9.1" 289 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 290 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 291 | 292 | media-typer@0.3.0: 293 | version "0.3.0" 294 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 295 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 296 | 297 | merge-descriptors@1.0.1: 298 | version "1.0.1" 299 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 300 | integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 301 | 302 | methods@~1.1.2: 303 | version "1.1.2" 304 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 305 | integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 306 | 307 | mime-db@1.52.0: 308 | version "1.52.0" 309 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 310 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 311 | 312 | mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: 313 | version "2.1.35" 314 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 315 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 316 | dependencies: 317 | mime-db "1.52.0" 318 | 319 | mime@1.6.0: 320 | version "1.6.0" 321 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 322 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 323 | 324 | ms@2.0.0: 325 | version "2.0.0" 326 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 327 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 328 | 329 | ms@2.1.3: 330 | version "2.1.3" 331 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 332 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 333 | 334 | negotiator@0.6.3: 335 | version "0.6.3" 336 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 337 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 338 | 339 | object-inspect@^1.9.0: 340 | version "1.13.1" 341 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" 342 | integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== 343 | 344 | on-finished@2.4.1: 345 | version "2.4.1" 346 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 347 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 348 | dependencies: 349 | ee-first "1.1.1" 350 | 351 | parseurl@~1.3.3: 352 | version "1.3.3" 353 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 354 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 355 | 356 | path-to-regexp@0.1.7: 357 | version "0.1.7" 358 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 359 | integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 360 | 361 | proxy-addr@~2.0.7: 362 | version "2.0.7" 363 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 364 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 365 | dependencies: 366 | forwarded "0.2.0" 367 | ipaddr.js "1.9.1" 368 | 369 | proxy-from-env@^1.1.0: 370 | version "1.1.0" 371 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" 372 | integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== 373 | 374 | qs@6.11.0: 375 | version "6.11.0" 376 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 377 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 378 | dependencies: 379 | side-channel "^1.0.4" 380 | 381 | range-parser@~1.2.1: 382 | version "1.2.1" 383 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 384 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 385 | 386 | raw-body@2.5.1: 387 | version "2.5.1" 388 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 389 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 390 | dependencies: 391 | bytes "3.1.2" 392 | http-errors "2.0.0" 393 | iconv-lite "0.4.24" 394 | unpipe "1.0.0" 395 | 396 | safe-buffer@5.2.1: 397 | version "5.2.1" 398 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 399 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 400 | 401 | "safer-buffer@>= 2.1.2 < 3": 402 | version "2.1.2" 403 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 404 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 405 | 406 | send@0.18.0: 407 | version "0.18.0" 408 | resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 409 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 410 | dependencies: 411 | debug "2.6.9" 412 | depd "2.0.0" 413 | destroy "1.2.0" 414 | encodeurl "~1.0.2" 415 | escape-html "~1.0.3" 416 | etag "~1.8.1" 417 | fresh "0.5.2" 418 | http-errors "2.0.0" 419 | mime "1.6.0" 420 | ms "2.1.3" 421 | on-finished "2.4.1" 422 | range-parser "~1.2.1" 423 | statuses "2.0.1" 424 | 425 | serve-static@1.15.0: 426 | version "1.15.0" 427 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 428 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 429 | dependencies: 430 | encodeurl "~1.0.2" 431 | escape-html "~1.0.3" 432 | parseurl "~1.3.3" 433 | send "0.18.0" 434 | 435 | set-function-length@^1.1.1: 436 | version "1.2.0" 437 | resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" 438 | integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== 439 | dependencies: 440 | define-data-property "^1.1.1" 441 | function-bind "^1.1.2" 442 | get-intrinsic "^1.2.2" 443 | gopd "^1.0.1" 444 | has-property-descriptors "^1.0.1" 445 | 446 | setprototypeof@1.2.0: 447 | version "1.2.0" 448 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 449 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 450 | 451 | side-channel@^1.0.4: 452 | version "1.0.4" 453 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 454 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 455 | dependencies: 456 | call-bind "^1.0.0" 457 | get-intrinsic "^1.0.2" 458 | object-inspect "^1.9.0" 459 | 460 | statuses@2.0.1: 461 | version "2.0.1" 462 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 463 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 464 | 465 | toidentifier@1.0.1: 466 | version "1.0.1" 467 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 468 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 469 | 470 | type-is@~1.6.18: 471 | version "1.6.18" 472 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 473 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 474 | dependencies: 475 | media-typer "0.3.0" 476 | mime-types "~2.1.24" 477 | 478 | unpipe@1.0.0, unpipe@~1.0.0: 479 | version "1.0.0" 480 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 481 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 482 | 483 | utils-merge@1.0.1: 484 | version "1.0.1" 485 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 486 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 487 | 488 | vary@~1.1.2: 489 | version "1.1.2" 490 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 491 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 492 | -------------------------------------------------------------------------------- /deobfuscate/README.md: -------------------------------------------------------------------------------- 1 | # Slide Captcha Deobfuscation 2 | 3 | This section of the repository focuses on the deobfuscation of the slide captcha javascript provided by Datadome. Although it isn't the cleanest deobfuscation I was focussing on maintaining the logic of the script, enabling you to put it into your own html page and run the script. This allowed me to gather the signals to give me a better understanding of the data the script collects, and how they encode the signals when they are sent for valdiation to Datadome's servers. 4 | 5 | 6 | ## Installing dependencies 7 | 8 | If you are using npm, run the following command: 9 | 10 | ```npm install``` 11 | 12 | 13 | ## Running the deobfuscator 14 | 15 | Insert the captcha script found on the Datadome captcha block page to `/assets/in.js`. 16 | 17 | Then, simply run 18 | 19 | ```npm start``` 20 | 21 | 22 | ## Output 23 | 24 | The output can be found inside the `assets` folder, where you will find 5 output files, which include a new file after each transformation has been run, and the final file `out_final.js` 25 | 26 | `out_hex.js` is the first transformation, which is written after all hexadecimal strings are converted to their normal string values. 27 | 28 | `out_string_decode.js` is the second transformation, which evaluates function calls like this `window[ln(nn(A(7, 14), f(127, 73)))][ln(k(x(137, 82), M(6, 8)))]` to this `window["_hsv"]["length"]` 29 | 30 | `out_binary_expressions.js` is the third transformation, which takes long binary expressions like this `window["d" + "d" + "R" + "e" + "s" + "O" + "b" + "j"]["o" + "v" + "h" + "t"]` to this `window["ddResObj]["ovht"]` 31 | 32 | `out_bracket_dot.js` is the fourth and final transformation, which converts all member expressions using bracket notation like this `document[["querySelector"]](".sliderContainer")` to this `document.querySelector(".sliderContainer")` with dot notation instead. 33 | 34 | 35 | ## Difference 36 | 37 | 38 | Before any transformations 39 | 40 | ![before](https://github.com/joekav/SlideCaptcha/blob/main/.github/images/before.png?raw=true) 41 | 42 | 43 | After all transformations 44 | 45 | ![before](https://github.com/joekav/SlideCaptcha/blob/main/.github/images/after.png?raw=true) 46 | -------------------------------------------------------------------------------- /deobfuscate/index.js: -------------------------------------------------------------------------------- 1 | const babel = require('@babel/core'); 2 | const traverse = require('@babel/traverse').default; 3 | const t = require('@babel/types'); 4 | const fs = require('fs'); 5 | const generate = require('@babel/generator').default; 6 | const traverseHexStrings = require('./transformers/hex.js'); 7 | // const stringDeobfuscation = require('./transformers/stringDeob.js'); 8 | // const deobBinaryExpressionStrings = require('./transformers/binaryExpressionStrings.js'); 9 | const bracketToDot = require('./transformers/bracketToDot.js'); 10 | const stringDeobfuscationV2 = require('./transformers/stringDeob_v2.js'); 11 | const stringConcatenation = require('./transformers/stringConcatenation.js'); 12 | 13 | const obfuscatedCode = fs.readFileSync('./assets/in.js', 'utf8'); 14 | const ast = babel.parseSync(obfuscatedCode); 15 | 16 | console.log("Hexadecimal encoding") 17 | traverseHexStrings(ast); 18 | fs.writeFileSync('./assets/out_hex.js', generate(ast).code); 19 | 20 | console.log("Bracket to dot notation"); 21 | bracketToDot(ast); 22 | fs.writeFileSync("./assets/bracket_to_dot_notation.js", generate(ast).code); 23 | 24 | console.log("Deobfuscating strings"); 25 | stringDeobfuscationV2(ast); 26 | fs.writeFileSync('./assets/out_string_decode.js', generate(ast).code); 27 | 28 | console.log("Concatenating strings"); 29 | stringConcatenation(ast); 30 | fs.writeFileSync("./assets/out_string_concatenation.js", generate(ast).code); 31 | 32 | console.log("Converting bracket notation to dot notation") 33 | bracketToDot(ast); 34 | fs.writeFileSync('./assets/out_bracket_dot1.js', generate(ast).code); 35 | 36 | const { code } = babel.transformFromAstSync(ast); 37 | 38 | fs.writeFileSync('./assets/out_final.js', code); 39 | -------------------------------------------------------------------------------- /deobfuscate/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "captcha_deob", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "captcha_deob", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@babel/core": "^7.23.7", 13 | "@babel/generator": "^7.23.6", 14 | "@babel/parser": "^7.23.6", 15 | "@babel/preset-react": "^7.23.3", 16 | "@babel/traverse": "^7.23.7", 17 | "fs": "^0.0.1-security", 18 | "vm": "^0.1.0" 19 | }, 20 | "devDependencies": { 21 | "@babel/plugin-transform-literals": "^7.23.3" 22 | } 23 | }, 24 | "node_modules/@ampproject/remapping": { 25 | "version": "2.2.1", 26 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", 27 | "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", 28 | "dependencies": { 29 | "@jridgewell/gen-mapping": "^0.3.0", 30 | "@jridgewell/trace-mapping": "^0.3.9" 31 | }, 32 | "engines": { 33 | "node": ">=6.0.0" 34 | } 35 | }, 36 | "node_modules/@babel/code-frame": { 37 | "version": "7.23.5", 38 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", 39 | "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", 40 | "dependencies": { 41 | "@babel/highlight": "^7.23.4", 42 | "chalk": "^2.4.2" 43 | }, 44 | "engines": { 45 | "node": ">=6.9.0" 46 | } 47 | }, 48 | "node_modules/@babel/compat-data": { 49 | "version": "7.23.5", 50 | "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", 51 | "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", 52 | "engines": { 53 | "node": ">=6.9.0" 54 | } 55 | }, 56 | "node_modules/@babel/core": { 57 | "version": "7.23.9", 58 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", 59 | "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", 60 | "dependencies": { 61 | "@ampproject/remapping": "^2.2.0", 62 | "@babel/code-frame": "^7.23.5", 63 | "@babel/generator": "^7.23.6", 64 | "@babel/helper-compilation-targets": "^7.23.6", 65 | "@babel/helper-module-transforms": "^7.23.3", 66 | "@babel/helpers": "^7.23.9", 67 | "@babel/parser": "^7.23.9", 68 | "@babel/template": "^7.23.9", 69 | "@babel/traverse": "^7.23.9", 70 | "@babel/types": "^7.23.9", 71 | "convert-source-map": "^2.0.0", 72 | "debug": "^4.1.0", 73 | "gensync": "^1.0.0-beta.2", 74 | "json5": "^2.2.3", 75 | "semver": "^6.3.1" 76 | }, 77 | "engines": { 78 | "node": ">=6.9.0" 79 | }, 80 | "funding": { 81 | "type": "opencollective", 82 | "url": "https://opencollective.com/babel" 83 | } 84 | }, 85 | "node_modules/@babel/generator": { 86 | "version": "7.23.6", 87 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", 88 | "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", 89 | "dependencies": { 90 | "@babel/types": "^7.23.6", 91 | "@jridgewell/gen-mapping": "^0.3.2", 92 | "@jridgewell/trace-mapping": "^0.3.17", 93 | "jsesc": "^2.5.1" 94 | }, 95 | "engines": { 96 | "node": ">=6.9.0" 97 | } 98 | }, 99 | "node_modules/@babel/helper-annotate-as-pure": { 100 | "version": "7.22.5", 101 | "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", 102 | "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", 103 | "dependencies": { 104 | "@babel/types": "^7.22.5" 105 | }, 106 | "engines": { 107 | "node": ">=6.9.0" 108 | } 109 | }, 110 | "node_modules/@babel/helper-compilation-targets": { 111 | "version": "7.23.6", 112 | "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", 113 | "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", 114 | "dependencies": { 115 | "@babel/compat-data": "^7.23.5", 116 | "@babel/helper-validator-option": "^7.23.5", 117 | "browserslist": "^4.22.2", 118 | "lru-cache": "^5.1.1", 119 | "semver": "^6.3.1" 120 | }, 121 | "engines": { 122 | "node": ">=6.9.0" 123 | } 124 | }, 125 | "node_modules/@babel/helper-environment-visitor": { 126 | "version": "7.22.20", 127 | "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", 128 | "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", 129 | "engines": { 130 | "node": ">=6.9.0" 131 | } 132 | }, 133 | "node_modules/@babel/helper-function-name": { 134 | "version": "7.23.0", 135 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", 136 | "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", 137 | "dependencies": { 138 | "@babel/template": "^7.22.15", 139 | "@babel/types": "^7.23.0" 140 | }, 141 | "engines": { 142 | "node": ">=6.9.0" 143 | } 144 | }, 145 | "node_modules/@babel/helper-hoist-variables": { 146 | "version": "7.22.5", 147 | "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", 148 | "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", 149 | "dependencies": { 150 | "@babel/types": "^7.22.5" 151 | }, 152 | "engines": { 153 | "node": ">=6.9.0" 154 | } 155 | }, 156 | "node_modules/@babel/helper-module-imports": { 157 | "version": "7.22.15", 158 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", 159 | "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", 160 | "dependencies": { 161 | "@babel/types": "^7.22.15" 162 | }, 163 | "engines": { 164 | "node": ">=6.9.0" 165 | } 166 | }, 167 | "node_modules/@babel/helper-module-transforms": { 168 | "version": "7.23.3", 169 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", 170 | "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", 171 | "dependencies": { 172 | "@babel/helper-environment-visitor": "^7.22.20", 173 | "@babel/helper-module-imports": "^7.22.15", 174 | "@babel/helper-simple-access": "^7.22.5", 175 | "@babel/helper-split-export-declaration": "^7.22.6", 176 | "@babel/helper-validator-identifier": "^7.22.20" 177 | }, 178 | "engines": { 179 | "node": ">=6.9.0" 180 | }, 181 | "peerDependencies": { 182 | "@babel/core": "^7.0.0" 183 | } 184 | }, 185 | "node_modules/@babel/helper-plugin-utils": { 186 | "version": "7.22.5", 187 | "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", 188 | "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", 189 | "engines": { 190 | "node": ">=6.9.0" 191 | } 192 | }, 193 | "node_modules/@babel/helper-simple-access": { 194 | "version": "7.22.5", 195 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", 196 | "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", 197 | "dependencies": { 198 | "@babel/types": "^7.22.5" 199 | }, 200 | "engines": { 201 | "node": ">=6.9.0" 202 | } 203 | }, 204 | "node_modules/@babel/helper-split-export-declaration": { 205 | "version": "7.22.6", 206 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", 207 | "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", 208 | "dependencies": { 209 | "@babel/types": "^7.22.5" 210 | }, 211 | "engines": { 212 | "node": ">=6.9.0" 213 | } 214 | }, 215 | "node_modules/@babel/helper-string-parser": { 216 | "version": "7.23.4", 217 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", 218 | "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", 219 | "engines": { 220 | "node": ">=6.9.0" 221 | } 222 | }, 223 | "node_modules/@babel/helper-validator-identifier": { 224 | "version": "7.22.20", 225 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", 226 | "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", 227 | "engines": { 228 | "node": ">=6.9.0" 229 | } 230 | }, 231 | "node_modules/@babel/helper-validator-option": { 232 | "version": "7.23.5", 233 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", 234 | "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", 235 | "engines": { 236 | "node": ">=6.9.0" 237 | } 238 | }, 239 | "node_modules/@babel/helpers": { 240 | "version": "7.23.9", 241 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", 242 | "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", 243 | "dependencies": { 244 | "@babel/template": "^7.23.9", 245 | "@babel/traverse": "^7.23.9", 246 | "@babel/types": "^7.23.9" 247 | }, 248 | "engines": { 249 | "node": ">=6.9.0" 250 | } 251 | }, 252 | "node_modules/@babel/highlight": { 253 | "version": "7.23.4", 254 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", 255 | "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", 256 | "dependencies": { 257 | "@babel/helper-validator-identifier": "^7.22.20", 258 | "chalk": "^2.4.2", 259 | "js-tokens": "^4.0.0" 260 | }, 261 | "engines": { 262 | "node": ">=6.9.0" 263 | } 264 | }, 265 | "node_modules/@babel/parser": { 266 | "version": "7.23.9", 267 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", 268 | "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", 269 | "bin": { 270 | "parser": "bin/babel-parser.js" 271 | }, 272 | "engines": { 273 | "node": ">=6.0.0" 274 | } 275 | }, 276 | "node_modules/@babel/plugin-syntax-jsx": { 277 | "version": "7.23.3", 278 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", 279 | "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", 280 | "dependencies": { 281 | "@babel/helper-plugin-utils": "^7.22.5" 282 | }, 283 | "engines": { 284 | "node": ">=6.9.0" 285 | }, 286 | "peerDependencies": { 287 | "@babel/core": "^7.0.0-0" 288 | } 289 | }, 290 | "node_modules/@babel/plugin-transform-literals": { 291 | "version": "7.23.3", 292 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", 293 | "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", 294 | "dev": true, 295 | "dependencies": { 296 | "@babel/helper-plugin-utils": "^7.22.5" 297 | }, 298 | "engines": { 299 | "node": ">=6.9.0" 300 | }, 301 | "peerDependencies": { 302 | "@babel/core": "^7.0.0-0" 303 | } 304 | }, 305 | "node_modules/@babel/plugin-transform-react-display-name": { 306 | "version": "7.23.3", 307 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz", 308 | "integrity": "sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==", 309 | "dependencies": { 310 | "@babel/helper-plugin-utils": "^7.22.5" 311 | }, 312 | "engines": { 313 | "node": ">=6.9.0" 314 | }, 315 | "peerDependencies": { 316 | "@babel/core": "^7.0.0-0" 317 | } 318 | }, 319 | "node_modules/@babel/plugin-transform-react-jsx": { 320 | "version": "7.23.4", 321 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", 322 | "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", 323 | "dependencies": { 324 | "@babel/helper-annotate-as-pure": "^7.22.5", 325 | "@babel/helper-module-imports": "^7.22.15", 326 | "@babel/helper-plugin-utils": "^7.22.5", 327 | "@babel/plugin-syntax-jsx": "^7.23.3", 328 | "@babel/types": "^7.23.4" 329 | }, 330 | "engines": { 331 | "node": ">=6.9.0" 332 | }, 333 | "peerDependencies": { 334 | "@babel/core": "^7.0.0-0" 335 | } 336 | }, 337 | "node_modules/@babel/plugin-transform-react-jsx-development": { 338 | "version": "7.22.5", 339 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", 340 | "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", 341 | "dependencies": { 342 | "@babel/plugin-transform-react-jsx": "^7.22.5" 343 | }, 344 | "engines": { 345 | "node": ">=6.9.0" 346 | }, 347 | "peerDependencies": { 348 | "@babel/core": "^7.0.0-0" 349 | } 350 | }, 351 | "node_modules/@babel/plugin-transform-react-pure-annotations": { 352 | "version": "7.23.3", 353 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", 354 | "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", 355 | "dependencies": { 356 | "@babel/helper-annotate-as-pure": "^7.22.5", 357 | "@babel/helper-plugin-utils": "^7.22.5" 358 | }, 359 | "engines": { 360 | "node": ">=6.9.0" 361 | }, 362 | "peerDependencies": { 363 | "@babel/core": "^7.0.0-0" 364 | } 365 | }, 366 | "node_modules/@babel/preset-react": { 367 | "version": "7.23.3", 368 | "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", 369 | "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", 370 | "dependencies": { 371 | "@babel/helper-plugin-utils": "^7.22.5", 372 | "@babel/helper-validator-option": "^7.22.15", 373 | "@babel/plugin-transform-react-display-name": "^7.23.3", 374 | "@babel/plugin-transform-react-jsx": "^7.22.15", 375 | "@babel/plugin-transform-react-jsx-development": "^7.22.5", 376 | "@babel/plugin-transform-react-pure-annotations": "^7.23.3" 377 | }, 378 | "engines": { 379 | "node": ">=6.9.0" 380 | }, 381 | "peerDependencies": { 382 | "@babel/core": "^7.0.0-0" 383 | } 384 | }, 385 | "node_modules/@babel/template": { 386 | "version": "7.23.9", 387 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", 388 | "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", 389 | "dependencies": { 390 | "@babel/code-frame": "^7.23.5", 391 | "@babel/parser": "^7.23.9", 392 | "@babel/types": "^7.23.9" 393 | }, 394 | "engines": { 395 | "node": ">=6.9.0" 396 | } 397 | }, 398 | "node_modules/@babel/traverse": { 399 | "version": "7.23.9", 400 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", 401 | "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", 402 | "dependencies": { 403 | "@babel/code-frame": "^7.23.5", 404 | "@babel/generator": "^7.23.6", 405 | "@babel/helper-environment-visitor": "^7.22.20", 406 | "@babel/helper-function-name": "^7.23.0", 407 | "@babel/helper-hoist-variables": "^7.22.5", 408 | "@babel/helper-split-export-declaration": "^7.22.6", 409 | "@babel/parser": "^7.23.9", 410 | "@babel/types": "^7.23.9", 411 | "debug": "^4.3.1", 412 | "globals": "^11.1.0" 413 | }, 414 | "engines": { 415 | "node": ">=6.9.0" 416 | } 417 | }, 418 | "node_modules/@babel/types": { 419 | "version": "7.23.9", 420 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", 421 | "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", 422 | "dependencies": { 423 | "@babel/helper-string-parser": "^7.23.4", 424 | "@babel/helper-validator-identifier": "^7.22.20", 425 | "to-fast-properties": "^2.0.0" 426 | }, 427 | "engines": { 428 | "node": ">=6.9.0" 429 | } 430 | }, 431 | "node_modules/@jridgewell/gen-mapping": { 432 | "version": "0.3.3", 433 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 434 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 435 | "dependencies": { 436 | "@jridgewell/set-array": "^1.0.1", 437 | "@jridgewell/sourcemap-codec": "^1.4.10", 438 | "@jridgewell/trace-mapping": "^0.3.9" 439 | }, 440 | "engines": { 441 | "node": ">=6.0.0" 442 | } 443 | }, 444 | "node_modules/@jridgewell/resolve-uri": { 445 | "version": "3.1.2", 446 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 447 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 448 | "engines": { 449 | "node": ">=6.0.0" 450 | } 451 | }, 452 | "node_modules/@jridgewell/set-array": { 453 | "version": "1.1.2", 454 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 455 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 456 | "engines": { 457 | "node": ">=6.0.0" 458 | } 459 | }, 460 | "node_modules/@jridgewell/sourcemap-codec": { 461 | "version": "1.4.15", 462 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 463 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" 464 | }, 465 | "node_modules/@jridgewell/trace-mapping": { 466 | "version": "0.3.22", 467 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", 468 | "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", 469 | "dependencies": { 470 | "@jridgewell/resolve-uri": "^3.1.0", 471 | "@jridgewell/sourcemap-codec": "^1.4.14" 472 | } 473 | }, 474 | "node_modules/ansi-styles": { 475 | "version": "3.2.1", 476 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 477 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 478 | "dependencies": { 479 | "color-convert": "^1.9.0" 480 | }, 481 | "engines": { 482 | "node": ">=4" 483 | } 484 | }, 485 | "node_modules/browserslist": { 486 | "version": "4.23.0", 487 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", 488 | "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", 489 | "funding": [ 490 | { 491 | "type": "opencollective", 492 | "url": "https://opencollective.com/browserslist" 493 | }, 494 | { 495 | "type": "tidelift", 496 | "url": "https://tidelift.com/funding/github/npm/browserslist" 497 | }, 498 | { 499 | "type": "github", 500 | "url": "https://github.com/sponsors/ai" 501 | } 502 | ], 503 | "dependencies": { 504 | "caniuse-lite": "^1.0.30001587", 505 | "electron-to-chromium": "^1.4.668", 506 | "node-releases": "^2.0.14", 507 | "update-browserslist-db": "^1.0.13" 508 | }, 509 | "bin": { 510 | "browserslist": "cli.js" 511 | }, 512 | "engines": { 513 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 514 | } 515 | }, 516 | "node_modules/caniuse-lite": { 517 | "version": "1.0.30001588", 518 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz", 519 | "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==", 520 | "funding": [ 521 | { 522 | "type": "opencollective", 523 | "url": "https://opencollective.com/browserslist" 524 | }, 525 | { 526 | "type": "tidelift", 527 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 528 | }, 529 | { 530 | "type": "github", 531 | "url": "https://github.com/sponsors/ai" 532 | } 533 | ] 534 | }, 535 | "node_modules/chalk": { 536 | "version": "2.4.2", 537 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 538 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 539 | "dependencies": { 540 | "ansi-styles": "^3.2.1", 541 | "escape-string-regexp": "^1.0.5", 542 | "supports-color": "^5.3.0" 543 | }, 544 | "engines": { 545 | "node": ">=4" 546 | } 547 | }, 548 | "node_modules/color-convert": { 549 | "version": "1.9.3", 550 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 551 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 552 | "dependencies": { 553 | "color-name": "1.1.3" 554 | } 555 | }, 556 | "node_modules/color-name": { 557 | "version": "1.1.3", 558 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 559 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" 560 | }, 561 | "node_modules/convert-source-map": { 562 | "version": "2.0.0", 563 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", 564 | "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" 565 | }, 566 | "node_modules/debug": { 567 | "version": "4.3.4", 568 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 569 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 570 | "dependencies": { 571 | "ms": "2.1.2" 572 | }, 573 | "engines": { 574 | "node": ">=6.0" 575 | }, 576 | "peerDependenciesMeta": { 577 | "supports-color": { 578 | "optional": true 579 | } 580 | } 581 | }, 582 | "node_modules/electron-to-chromium": { 583 | "version": "1.4.678", 584 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.678.tgz", 585 | "integrity": "sha512-NbdGC2p0O5Q5iVhLEsNBSfytaw7wbEFJlIvaF71wi6QDtLAph5/rVogjyOpf/QggJIt8hNK3KdwNJnc2bzckbw==" 586 | }, 587 | "node_modules/escalade": { 588 | "version": "3.1.2", 589 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", 590 | "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", 591 | "engines": { 592 | "node": ">=6" 593 | } 594 | }, 595 | "node_modules/escape-string-regexp": { 596 | "version": "1.0.5", 597 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 598 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 599 | "engines": { 600 | "node": ">=0.8.0" 601 | } 602 | }, 603 | "node_modules/fs": { 604 | "version": "0.0.1-security", 605 | "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", 606 | "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" 607 | }, 608 | "node_modules/gensync": { 609 | "version": "1.0.0-beta.2", 610 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 611 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 612 | "engines": { 613 | "node": ">=6.9.0" 614 | } 615 | }, 616 | "node_modules/globals": { 617 | "version": "11.12.0", 618 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 619 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 620 | "engines": { 621 | "node": ">=4" 622 | } 623 | }, 624 | "node_modules/has-flag": { 625 | "version": "3.0.0", 626 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 627 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 628 | "engines": { 629 | "node": ">=4" 630 | } 631 | }, 632 | "node_modules/js-tokens": { 633 | "version": "4.0.0", 634 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 635 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 636 | }, 637 | "node_modules/jsesc": { 638 | "version": "2.5.2", 639 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 640 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 641 | "bin": { 642 | "jsesc": "bin/jsesc" 643 | }, 644 | "engines": { 645 | "node": ">=4" 646 | } 647 | }, 648 | "node_modules/json5": { 649 | "version": "2.2.3", 650 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 651 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 652 | "bin": { 653 | "json5": "lib/cli.js" 654 | }, 655 | "engines": { 656 | "node": ">=6" 657 | } 658 | }, 659 | "node_modules/lru-cache": { 660 | "version": "5.1.1", 661 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 662 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 663 | "dependencies": { 664 | "yallist": "^3.0.2" 665 | } 666 | }, 667 | "node_modules/ms": { 668 | "version": "2.1.2", 669 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 670 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 671 | }, 672 | "node_modules/node-releases": { 673 | "version": "2.0.14", 674 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", 675 | "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" 676 | }, 677 | "node_modules/picocolors": { 678 | "version": "1.0.0", 679 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 680 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" 681 | }, 682 | "node_modules/semver": { 683 | "version": "6.3.1", 684 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 685 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 686 | "bin": { 687 | "semver": "bin/semver.js" 688 | } 689 | }, 690 | "node_modules/supports-color": { 691 | "version": "5.5.0", 692 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 693 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 694 | "dependencies": { 695 | "has-flag": "^3.0.0" 696 | }, 697 | "engines": { 698 | "node": ">=4" 699 | } 700 | }, 701 | "node_modules/to-fast-properties": { 702 | "version": "2.0.0", 703 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 704 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", 705 | "engines": { 706 | "node": ">=4" 707 | } 708 | }, 709 | "node_modules/update-browserslist-db": { 710 | "version": "1.0.13", 711 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", 712 | "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", 713 | "funding": [ 714 | { 715 | "type": "opencollective", 716 | "url": "https://opencollective.com/browserslist" 717 | }, 718 | { 719 | "type": "tidelift", 720 | "url": "https://tidelift.com/funding/github/npm/browserslist" 721 | }, 722 | { 723 | "type": "github", 724 | "url": "https://github.com/sponsors/ai" 725 | } 726 | ], 727 | "dependencies": { 728 | "escalade": "^3.1.1", 729 | "picocolors": "^1.0.0" 730 | }, 731 | "bin": { 732 | "update-browserslist-db": "cli.js" 733 | }, 734 | "peerDependencies": { 735 | "browserslist": ">= 4.21.0" 736 | } 737 | }, 738 | "node_modules/vm": { 739 | "version": "0.1.0", 740 | "resolved": "https://registry.npmjs.org/vm/-/vm-0.1.0.tgz", 741 | "integrity": "sha512-1aKVjgohVDnVhGrJLhl2k8zIrapH+7HsdnIjGvBp3XX2OCj6XGzsIbDp9rZ3r7t6qgDfXEE1EoEAEOLJm9LKnw==" 742 | }, 743 | "node_modules/yallist": { 744 | "version": "3.1.1", 745 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 746 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 747 | } 748 | } 749 | } 750 | -------------------------------------------------------------------------------- /deobfuscate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "captcha_deob", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "node --stack-size=3936 index.js" 8 | }, 9 | "dependencies": { 10 | "@babel/core": "^7.23.7", 11 | "@babel/generator": "^7.23.6", 12 | "@babel/parser": "^7.23.6", 13 | "@babel/preset-react": "^7.23.3", 14 | "@babel/traverse": "^7.23.7", 15 | "fs": "^0.0.1-security", 16 | "vm": "^0.1.0" 17 | }, 18 | "babel": { 19 | 20 | }, 21 | "devDependencies": { 22 | "@babel/plugin-transform-literals": "^7.23.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /deobfuscate/transformers/binaryExpressionStrings.js: -------------------------------------------------------------------------------- 1 | const traverse = require('@babel/traverse').default; 2 | const t = require('@babel/types'); 3 | 4 | 5 | function deobBinaryExpressionStrings(ast) { 6 | traverse(ast, { 7 | BinaryExpression(path) { 8 | if (path.node.operator === '+') { 9 | let nodes = []; 10 | let current = path.node; 11 | 12 | while (t.isBinaryExpression(current, { operator: '+' })) { 13 | nodes.unshift(current.right); 14 | current = current.left; 15 | } 16 | nodes.unshift(current); 17 | 18 | if (nodes.every(node => t.isStringLiteral(node))) { 19 | let concatenatedString = nodes.reduce((acc, node) => acc + node.value, ''); 20 | path.replaceWith(t.stringLiteral(concatenatedString)); 21 | } 22 | } 23 | } 24 | }); 25 | } 26 | 27 | 28 | 29 | module.exports = deobBinaryExpressionStrings; -------------------------------------------------------------------------------- /deobfuscate/transformers/bracketToDot.js: -------------------------------------------------------------------------------- 1 | const traverse = require('@babel/traverse').default; 2 | const t = require('@babel/types'); 3 | 4 | function bracketToDot(ast) { 5 | traverse(ast, { 6 | MemberExpression(path) { 7 | if (path.node.computed && t.isArrayExpression(path.node.property)) { 8 | path.node.computed = false; 9 | path.node.property = t.identifier(path.node.property.elements[0].value); 10 | } 11 | 12 | if (path.node.computed && t.isStringLiteral(path.node.property) && path.node.property.value !== "") { 13 | path.node.computed = false; 14 | path.node.property = t.identifier(path.node.property.value); 15 | } 16 | } 17 | }); 18 | } 19 | 20 | 21 | module.exports = bracketToDot; -------------------------------------------------------------------------------- /deobfuscate/transformers/hex.js: -------------------------------------------------------------------------------- 1 | const traverse = require('@babel/traverse').default; 2 | 3 | 4 | // Removes hexadecimal encoding from StringLiterals 5 | function traverseHexStrings(ast) { 6 | traverse(ast, { 7 | StringLiteral(path) { 8 | delete path.node.extra; 9 | } 10 | }); 11 | } 12 | 13 | module.exports = traverseHexStrings; -------------------------------------------------------------------------------- /deobfuscate/transformers/stringConcatenation.js: -------------------------------------------------------------------------------- 1 | const traverse = require('@babel/traverse').default; 2 | const t = require("@babel/types"); 3 | 4 | 5 | // BASIC string concatenation 6 | function stringConcatenation(ast) { 7 | traverse(ast, { 8 | BinaryExpression: { 9 | exit(path){ 10 | const [left, right] = [path.get("left"), path.get("right")]; 11 | if(!left.isStringLiteral() || !right.isStringLiteral())return; 12 | 13 | path.replaceWith(t.stringLiteral(left.node.value + right.node.value)); 14 | } 15 | } 16 | }); 17 | } 18 | 19 | module.exports = stringConcatenation; -------------------------------------------------------------------------------- /deobfuscate/transformers/stringDeob.js: -------------------------------------------------------------------------------- 1 | const traverse = require('@babel/traverse').default; 2 | const t = require('@babel/types'); 3 | const generate = require('@babel/generator').default; 4 | const vm = require('vm'); 5 | 6 | 7 | 8 | function stringDeobfuscation(ast) { 9 | // Finds all functions which are called to deob strings 10 | var functions = {} 11 | 12 | // Keeps track of which ObjectProperty we are in, there is 8 of them as of 1.8.2 13 | var contextStack = [] 14 | 15 | // Context for vm 16 | var context = {} 17 | 18 | traverse(ast, { 19 | ObjectProperty: { 20 | enter(path) { 21 | if (path.node.key.type === "NumericLiteral" && path.node.key.value >= 1 && path.node.key.value <= 8) { 22 | contextStack.push(path.node.key.value); 23 | 24 | if (path.node.key.value == 2 || path.node.key.value == 7) { 25 | return 26 | } 27 | 28 | functions[path.node.key.value] = {} 29 | for (var i = 0; i < path.node.value.elements[0].body.body.length; i++) { 30 | var subNode = path.node.value.elements[0].body.body[i] 31 | 32 | if (subNode.type != "FunctionDeclaration") { 33 | continue 34 | } 35 | 36 | functions[path.node.key.value][subNode.id.name] = generate(subNode).code 37 | 38 | } 39 | } 40 | }, 41 | exit(path) { 42 | if (path.node.key.type === "NumericLiteral" && path.node.key.value >= 1 && path.node.key.value <= 8) { 43 | contextStack.pop(); 44 | } 45 | }, 46 | }, 47 | // Very hacky, `wn` can change at any point 48 | VariableDeclarator(path) { 49 | const currentContextKey = contextStack[contextStack.length - 1]; 50 | 51 | if (path.node.id.name === 'wn' && path.node.init && path.node.init.type === 'ArrayExpression') { 52 | var codeToRun = Object.values(functions[currentContextKey]).join("\n") 53 | vm.runInNewContext(`${codeToRun}\nvar ${generate(path.node).code}\n`, context) 54 | } 55 | 56 | }, 57 | CallExpression(path) { 58 | const { node } = path; 59 | const { arguments: args, callee } = node; 60 | const currentContextKey = contextStack[contextStack.length - 1]; 61 | 62 | if (currentContextKey && functions[currentContextKey] && Object.keys(functions[currentContextKey]).includes(callee.name)) { 63 | var codeToRun = Object.values(functions[currentContextKey]).join("\n") 64 | 65 | try { 66 | vm.runInNewContext(`${codeToRun}\nvar result = ${generate(node).code} `, context) 67 | 68 | if (context.result === undefined) { 69 | return 70 | } 71 | if (typeof context.result === "function") { 72 | return 73 | } 74 | var val = t.valueToNode(context.result) 75 | 76 | path.replaceWith(val) 77 | } catch (e) { 78 | return 79 | } 80 | 81 | } 82 | } 83 | }); 84 | } 85 | 86 | 87 | module.exports = stringDeobfuscation; 88 | -------------------------------------------------------------------------------- /deobfuscate/transformers/stringDeob_v2.js: -------------------------------------------------------------------------------- 1 | const traverse = require('@babel/traverse').default; 2 | const t = require('@babel/types'); 3 | const generate = require('@babel/generator').default; 4 | const vm = require('vm'); 5 | const genCode = require('../utils/genCode'); 6 | 7 | 8 | const clone = t.cloneDeepWithoutLoc; 9 | 10 | function stringDeobfuscationV2(ast) { 11 | const props = ast.program.body[0].expression.argument.arguments[0].properties; 12 | 13 | console.log("We have " + props.length + " files!"); 14 | for (let i = 0; i < props.length; i++) { 15 | const context = {}; 16 | const prop = props[i]; 17 | 18 | const program = t.program([t.expressionStatement(t.unaryExpression("!", clone(prop.value.elements[0])))]); 19 | 20 | /** @type {t.BlockStatement} */ 21 | const wantedMainBlockStatement = program.body[0].expression.argument.body; 22 | 23 | for (let node of wantedMainBlockStatement.body) { 24 | if ( 25 | !( 26 | t.isFunctionDeclaration(node) || 27 | t.isVariableDeclaration(node) 28 | ) 29 | ) continue; 30 | 31 | if(t.isVariableDeclaration(node)){ 32 | const declarations = node.declarations; 33 | if(declarations.length > 1)continue; 34 | 35 | const [declaration] = declarations; 36 | 37 | if(!declaration.init || !t.isArrayExpression(declaration.init))continue; 38 | } 39 | 40 | vm.runInNewContext(genCode(node), context); 41 | } 42 | 43 | traverse(t.file(program), { 44 | CallExpression: { 45 | exit(path) { 46 | const [callee, args] = [path.get("callee"), path.get("arguments")]; 47 | 48 | if (!callee.isIdentifier()) return; 49 | 50 | const calleeName = callee.node.name; 51 | 52 | if (context[calleeName] == undefined) return; 53 | 54 | if(typeof context[calleeName] !== "function")return; 55 | 56 | if(args.some(arg => !arg.isNumericLiteral()))return; 57 | 58 | const value = vm.runInNewContext(path.toString(), context); 59 | 60 | path.replaceWith(t.valueToNode(value)); 61 | 62 | } 63 | } 64 | }); 65 | 66 | traverse.cache.clear(); 67 | 68 | traverse(t.file(program), { 69 | Program(path){ 70 | const stmts = path.get("body.0.expression.argument.body.body"); 71 | 72 | for(let stmt of stmts){ 73 | if(!stmt.isFunctionDeclaration())continue; 74 | 75 | const id = stmt.get("id"); 76 | 77 | if(!id.isIdentifier())continue; 78 | 79 | const isReferenced = stmt.scope.getBinding(id.node.name).referenced; 80 | 81 | if(!isReferenced)stmt.remove(); 82 | } 83 | } 84 | }); 85 | 86 | traverse.cache.clear(); 87 | 88 | prop.value.elements[0] = clone(program.body[0].expression.argument); 89 | 90 | console.log(`Finished file ${i+1}`); 91 | } 92 | } 93 | 94 | 95 | module.exports = stringDeobfuscationV2; 96 | -------------------------------------------------------------------------------- /deobfuscate/utils/genCode.js: -------------------------------------------------------------------------------- 1 | const generate = require("@babel/generator").default; 2 | function genCode(code){ 3 | return generate(code).code; 4 | } 5 | module.exports = genCode -------------------------------------------------------------------------------- /detection/README.md: -------------------------------------------------------------------------------- 1 | # Puzzle Detection 2 | 3 | This section of the repository focuses on determining the x,y position of the puzzle piece inside the background image. 4 | 5 | 6 | ## Installing dependencies 7 | 8 | `pip install -r requirements.txt` 9 | 10 | 11 | ## Run API 12 | 13 | Run `python api.py` 14 | 15 | This will start the flask API on port 3030. 16 | 17 | 18 | 19 | 20 | ## API Usage 21 | 22 | There is only one endpoint, which is `/solve` with a method of `POST`. 23 | 24 | Request body: 25 | 26 | ``` 27 | { 28 | "background_image": "https://dd.prod.captcha-delivery.com/image/2024-01-28/9ddaf44e46e88d029428151370891a5c.jpg", 29 | "debug": true 30 | } 31 | ``` 32 | 33 | 1. `background_image` which should be the url to the background image provided by datadome. 34 | 35 | 2. `debug` (optional) which is a boolean to write an image of the found position surrounded by a box. 36 | 37 | Returns: 38 | 39 | ``` 40 | { 41 | "position": [ 42 | 190, 43 | 18 44 | ] 45 | } 46 | ``` 47 | 48 | `position` is the x and y coordinates of the left side of the puzzle piece. 49 | 50 | This value is then used in the [payload generator](https://github.com/joekav/SlideCaptcha/tree/main/api). 51 | 52 | 53 | 54 | ## Debug images 55 | 56 | The debug images found if `debug` is true look like this. 57 | 58 | ![debug](https://github.com/joekav/SlideCaptcha/blob/main/.github/images/debug.jpg?raw=true) 59 | -------------------------------------------------------------------------------- /detection/api.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | from slide import SlidePosition 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route('/position', methods=['POST']) 7 | def solve(): 8 | """ 9 | Solve the slide position based on the provided background image. 10 | Returns: 11 | dict: A dictionary containing the slide position. 12 | If successful, the dictionary will have a "position" key with the slide position value. 13 | If there is an error, the dictionary will have a "message" key with an error message. 14 | """ 15 | debug = request.json.get("debug", False) 16 | background_image = request.json.get("background_image", "") 17 | 18 | # Check if the background_image is in the request 19 | if request.json.get("background_image", "") == "": 20 | return {"message": "background_image is required"}, 400, {'Content-Type': 'application/json'} 21 | 22 | # Get the slide position from the slide class 23 | position = SlidePosition(background_image, debug) 24 | 25 | if not hasattr(position, "slide_position"): 26 | return {"message": "Error: Could not load the images. Check the image url."}, 400, {'Content-Type': 'application/json'} 27 | 28 | return {"position": position.slide_position}, 200, {'Content-Type': 'application/json'} 29 | 30 | 31 | if __name__ == '__main__': 32 | app.run(port=3030) 33 | -------------------------------------------------------------------------------- /detection/requirements.txt: -------------------------------------------------------------------------------- 1 | archspec @ file:///home/conda/feedstock_root/build_artifacts/archspec_1699370045702/work 2 | blinker==1.7.0 3 | boltons @ file:///home/conda/feedstock_root/build_artifacts/boltons_1703154663129/work 4 | Brotli @ file:///Users/runner/miniforge3/conda-bld/brotli-split_1695989934239/work 5 | certifi @ file:///home/conda/feedstock_root/build_artifacts/certifi_1700303426725/work/certifi 6 | cffi @ file:///Users/runner/miniforge3/conda-bld/cffi_1696001737800/work 7 | charset-normalizer @ file:///home/conda/feedstock_root/build_artifacts/charset-normalizer_1698833585322/work 8 | click==8.1.7 9 | colorama @ file:///home/conda/feedstock_root/build_artifacts/colorama_1666700638685/work 10 | conda @ file:///Users/runner/miniforge3/conda-bld/conda_1701731166956/work 11 | conda-libmamba-solver @ file:///home/conda/feedstock_root/build_artifacts/conda-libmamba-solver_1702406360642/work/src 12 | conda-package-handling @ file:///home/conda/feedstock_root/build_artifacts/conda-package-handling_1691048088238/work 13 | conda_package_streaming @ file:///home/conda/feedstock_root/build_artifacts/conda-package-streaming_1691009212940/work 14 | distro @ file:///home/conda/feedstock_root/build_artifacts/distro_1675116244235/work 15 | Flask==3.0.1 16 | idna @ file:///home/conda/feedstock_root/build_artifacts/idna_1701026962277/work 17 | itsdangerous==2.1.2 18 | Jinja2==3.1.3 19 | jsonpatch @ file:///home/conda/feedstock_root/build_artifacts/jsonpatch_1695536281965/work 20 | jsonpointer @ file:///Users/runner/miniforge3/conda-bld/jsonpointer_1695397382064/work 21 | libmambapy @ file:///Users/runner/miniforge3/conda-bld/mamba-split_1702310516100/work/libmambapy 22 | mamba @ file:///Users/runner/miniforge3/conda-bld/mamba-split_1702310516100/work/mamba 23 | MarkupSafe==2.1.4 24 | menuinst @ file:///Users/runner/miniforge3/conda-bld/menuinst_1702317138933/work 25 | numpy==1.26.3 26 | opencv-python-headless==4.9.0.80 27 | packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1696202382185/work 28 | platformdirs @ file:///home/conda/feedstock_root/build_artifacts/platformdirs_1701708255999/work 29 | pluggy @ file:///home/conda/feedstock_root/build_artifacts/pluggy_1693086607691/work 30 | pycosat @ file:///Users/runner/miniforge3/conda-bld/pycosat_1696355969704/work 31 | pycparser @ file:///home/conda/feedstock_root/build_artifacts/pycparser_1636257122734/work 32 | PySocks @ file:///home/conda/feedstock_root/build_artifacts/pysocks_1661604839144/work 33 | requests @ file:///home/conda/feedstock_root/build_artifacts/requests_1684774241324/work 34 | ruamel.yaml @ file:///Users/runner/miniforge3/conda-bld/ruamel.yaml_1699007390921/work 35 | ruamel.yaml.clib @ file:///Users/runner/miniforge3/conda-bld/ruamel.yaml.clib_1695996997220/work 36 | tqdm @ file:///home/conda/feedstock_root/build_artifacts/tqdm_1691671248568/work 37 | truststore @ file:///home/conda/feedstock_root/build_artifacts/truststore_1694154605758/work 38 | urllib3 @ file:///home/conda/feedstock_root/build_artifacts/urllib3_1699933488691/work 39 | Werkzeug==3.0.1 40 | zstandard==0.22.0 41 | -------------------------------------------------------------------------------- /detection/slide.py: -------------------------------------------------------------------------------- 1 | import cv2 as cv 2 | import numpy as np 3 | from io import BytesIO 4 | import time, requests 5 | 6 | class SlidePosition: 7 | # fragment_image: url to the fragment image from dd 8 | # background_image: url to the background image from dd 9 | # debug: if true, will save the image with the rectangle and coordinates 10 | 11 | def __init__(self, background_image="", debug=True): 12 | start = time.time() 13 | self.background_image = background_image 14 | self.debug = debug 15 | 16 | # Load images to class 17 | self.get_images() 18 | 19 | # Finds top left corner of puzzle piece 20 | self.find_puzzle_piece_left() 21 | 22 | # Draws a rectangle around the puzzle piece and save to disk 23 | self.draw_rectangle_around_piece() 24 | 25 | end = time.time() 26 | self.time_taken = end - start 27 | 28 | def get_images(self): 29 | """ 30 | Gets the images from the datadome url and saves them to the class. 31 | """ 32 | background_raw = BytesIO(requests.get(self.background_image).content) 33 | background_array = np.asarray(bytearray(background_raw.read()), dtype=np.uint8) 34 | self.background = cv.imdecode(background_array, cv.IMREAD_UNCHANGED) 35 | 36 | fragment_raw = BytesIO(requests.get(self.background_image.replace(".jpg", ".frag.png")).content) 37 | fragment_array = np.asarray(bytearray(fragment_raw.read()), dtype=np.uint8) 38 | 39 | self.fragment = cv.imdecode(fragment_array, cv.IMREAD_UNCHANGED) 40 | 41 | 42 | def find_puzzle_piece_left(self): 43 | """ 44 | This function is used to find a puzzle piece in a background image and returns the top left corner of the piece's coordinates 45 | """ 46 | 47 | # Check if the fragment and background images are loaded 48 | if self.fragment is None or self.background is None: 49 | return "Error: Could not load the images. Check the file paths." 50 | 51 | # Convert images to grayscale 52 | gray_piece = cv.cvtColor(self.fragment, cv.COLOR_BGRA2GRAY) 53 | full_image_gray = cv.cvtColor(self.background, cv.COLOR_BGRA2GRAY) 54 | 55 | # Apply threshold to the grayscale image of the puzzle piece 56 | _, mask = cv.threshold(gray_piece, 1, 255, cv.THRESH_BINARY) 57 | 58 | # Find contours in the mask 59 | contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) 60 | 61 | # Get the contour with the maximum area 62 | piece_contour = max(contours, key=cv.contourArea) 63 | 64 | # Get the bounding rectangle for the largest contour 65 | x, y, w, h = cv.boundingRect(piece_contour) 66 | 67 | # Crop the fragment image to the bounding rectangle 68 | self.fragment_cropped = self.fragment[y:y+h, x:x+w] 69 | 70 | # Convert the cropped image to grayscale 71 | cropped_piece_gray = cv.cvtColor(self.fragment_cropped, cv.COLOR_BGRA2GRAY) 72 | 73 | # Apply Canny edge detection to the grayscale images 74 | cropped_piece_edges = cv.Canny(cropped_piece_gray, 50, 150) 75 | full_image_edges = cv.Canny(full_image_gray, 50, 150) 76 | 77 | # Match the template (cropped piece edges) in the full image edges 78 | res = cv.matchTemplate(full_image_edges, cropped_piece_edges, cv.TM_CCOEFF_NORMED) 79 | 80 | # Find the location of the best match 81 | _, _, _, max_loc = cv.minMaxLoc(res) 82 | 83 | # Store the position of the slide 84 | self.slide_position = max_loc 85 | 86 | def draw_rectangle_around_piece(self): 87 | """ 88 | Draws a rectangle around the found puzzle piece on the background image for debugging. 89 | """ 90 | 91 | # Check if the slide position attribute exists 92 | if not hasattr(self, 'slide_position'): 93 | return "Error: Puzzle piece position not found." 94 | 95 | # Get the top left coordinates of the slide position 96 | top_left_x, top_left_y = self.slide_position 97 | 98 | # Get the height and width of the cropped fragment 99 | piece_height, piece_width = self.fragment_cropped.shape[:2] 100 | 101 | # Calculate the bottom right coordinates of the rectangle 102 | bottom_right_x = top_left_x + piece_width 103 | bottom_right_y = top_left_y + piece_height 104 | 105 | # Draw a rectangle on the background image around the puzzle piece 106 | cv.rectangle(self.background, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), (0, 255, 0), 2) 107 | 108 | # If debugging is enabled, write the image with the rectangle to a file 109 | if self.debug: 110 | cv.imwrite(f'tests/test.jpg', self.background) 111 | 112 | # Return the background image 113 | return self.background --------------------------------------------------------------------------------