├── LICENSE ├── README.md ├── bda.py ├── browser.py └── solver.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Pr0t0n 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Funcaptcha Audio Solver 2 | 3 | 4 | 5 | 6 | Feel free to contact @autographed on Telegram if you're looking to purchase a stable funcaptcha solution. 7 | 8 | Telegram - @autographed | https://t.me/autographed 9 | 10 | Funcaptcha Solver Made by Pr0t0n 11 | 12 | **Features** 13 | - Proxy/Proxyless HTTP(s) Support 14 | - 100% Requests Based 15 | - Quick Solve time 16 | - v1 funcap Audio solver 17 | - Custom Useragent option 18 | - Retries Option 19 | 20 | **Class Args/Params Explained** (You don't need to specify anything if you want to test with default arg/param values) 21 | - host [required] --> Website URL you're trying to solve for (Sometimes works without decleration) 22 | - site_key [required] --> Funcaptcha Site Key for the site you're trying to solve for 23 | - ua [optional] --> Custom User-Agent option (More advanced Option for people who know what they're doing for higher quality responses) 24 | - proxy [optional] --> Rotating/Static Proxy Option (Pass in proxy to solve with proxy) 25 | - retries [optional] --> Amount of attempts before giving up (Since my audio solver isn't that accurate you can specify the amount of times to attempt to re-solve a funcaptcha before giving up atm the recommended amt of retries would be 5-6) 26 | 27 | **Extra** 28 | Please feel free to make PR's (Pull Request) to help improve code. I will be more than happy to review and commit the code if it's good (No typo pr's please). 29 | (Looking for Unflagged BDA method, Bio method, Improving Audio Recognition) 30 | 31 | Extra Credits: useragents (High Audio Quality Dictonary); imvast (providing me with the bda src code even though he didn't make it); tranny & keepitlowkey (AES Encryption method src) 32 | 33 | **Notes** 34 | Please don't bully me for formatting I coded this on replit with a chromebook cuz i felt like it 😆 35 | 36 | If you want to use a new proxy & Session you will need to call the class along with the solve function 37 | Example: Funcap(site_key="").solve() # As you can see im calling the class itself along with the function 38 | 39 | **50 Stars = ???** <-- (this repo will not be updated because I am currently running an active private solution) 40 | -------------------------------------------------------------------------------- /bda.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import json 3 | import random 4 | import time 5 | import secrets 6 | # import codecs 7 | 8 | import numpy as np 9 | from browser import encrypt as cipher 10 | 11 | 12 | def cfp_hash(string_in: str) -> int: 13 | int1 = np.int32(0) 14 | for int2 in range(len(string_in)): 15 | int3 = np.int32(ord(string_in[int2])) 16 | int1 = np.int32((int1 << 5) - int1 + int3) 17 | int1 = np.bitwise_and(int1, np.int32(-1)) 18 | return int1.item() 19 | 20 | 21 | def get_bda(user_agent: str) -> str: 22 | ts = time.time() 23 | timeframe = int(ts - ts % 21600) 24 | key = user_agent + str(timeframe) 25 | test = str(random.uniform(124.0, 125.0)) 26 | # print(test) 27 | current_time = int(time.time()) 28 | encoded = base64.b64encode(str(current_time).encode()).decode() 29 | # print(encoded) 30 | the_data = [ 31 | {"key": "api_type", "value": "js"}, 32 | {"key": "p", "value": 1}, 33 | {"key": "f", "value": secrets.token_hex(16)}, 34 | {"key": "n", "value": encoded}, 35 | { 36 | "key": "wh", 37 | "value": f"{secrets.token_hex(16)}|{secrets.token_hex(16)}", 38 | }, 39 | { 40 | "key": "enhanced_fp", 41 | "value": [ 42 | { 43 | "key": "webgl_extensions", 44 | "value": "ANGLE_instanced_arrays;EXT_blend_minmax;EXT_color_buffer_half_float;EXT_float_blend;EXT_frag_depth;EXT_shader_texture_lod;EXT_texture_compression_bptc;EXT_texture_compression_rgtc;EXT_texture_filter_anisotropic;EXT_sRGB;OES_element_index_uint;OES_fbo_render_mipmap;OES_standard_derivatives;OES_texture_float;OES_texture_float_linear;OES_texture_half_float;OES_texture_half_float_linear;OES_vertex_array_object;WEBGL_color_buffer_float;WEBGL_compressed_texture_astc;WEBGL_compressed_texture_etc;WEBGL_compressed_texture_etc1;WEBGL_compressed_texture_s3tc;WEBGL_compressed_texture_s3tc_srgb;WEBGL_debug_renderer_info;WEBGL_depth_texture;WEBGL_draw_buffers;WEBGL_lose_context;WEBGL_multi_draw", 45 | }, 46 | { 47 | "key": "webgl_extensions_hash", 48 | "value": secrets.token_hex(16), 49 | }, 50 | {"key": "webgl_renderer", "value": "WebKit WebGL"}, 51 | {"key": "webgl_vendor", "value": "WebKit"}, 52 | { 53 | "key": "webgl_version", 54 | "value": "WebGL 1.0 (OpenGL ES 2.0 Chromium)", 55 | }, 56 | { 57 | "key": "webgl_shading_language_version", 58 | "value": "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)", 59 | }, 60 | {"key": "webgl_aliased_line_width_range", "value": "[1, 1]"}, 61 | { 62 | "key": "webgl_aliased_point_size_range", 63 | "value": "[1, 1023]", 64 | }, 65 | {"key": "webgl_antialiasing", "value": "yes"}, 66 | {"key": "webgl_bits", "value": "8,8,24,8,8,0"}, 67 | { 68 | "key": "webgl_max_params", 69 | "value": "16,64,16384,4096,8192,32,8192,31,16,32,4096", 70 | }, 71 | {"key": "webgl_max_viewport_dims", "value": "[8192, 8192]"}, 72 | { 73 | "key": "webgl_unmasked_vendor", 74 | "value": "Google Inc. (Google)", 75 | }, 76 | { 77 | "key": "webgl_unmasked_renderer", 78 | "value": "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)", 79 | }, 80 | { 81 | "key": "webgl_vsf_params", 82 | "value": "23,127,127,10,15,15,10,15,15", 83 | }, 84 | { 85 | "key": "webgl_vsi_params", 86 | "value": "0,31,30,0,15,14,0,15,14", 87 | }, 88 | { 89 | "key": "webgl_fsf_params", 90 | "value": "23,127,127,10,15,15,10,15,15", 91 | }, 92 | { 93 | "key": "webgl_fsi_params", 94 | "value": "0,31,30,0,15,14,0,15,14", 95 | }, 96 | {"key": "webgl_hash_webgl", "value": secrets.token_hex(16)}, 97 | { 98 | "key": "user_agent_data_brands", 99 | "value": "Chromium,Not A(Brand,Google Chrome", 100 | }, 101 | {"key": "user_agent_data_mobile", "value": "true"}, 102 | {"key": "navigator_connection_downlink", "value": 10}, 103 | {"key": "navigator_connection_downlink_max", "value": "null"}, 104 | {"key": "network_info_rtt", "value": 100}, 105 | {"key": "network_info_save_data", "value": "false"}, 106 | {"key": "network_info_rtt_type", "value": "null"}, 107 | {"key": "screen_pixel_depth", "value": 24}, 108 | {"key": "navigator_device_memory", "value": 8}, 109 | {"key": "navigator_languages", "value": "en-US"}, 110 | {"key": "window_inner_width", "value": 1365}, 111 | {"key": "window_inner_height", "value": 937}, 112 | {"key": "window_outer_width", "value": 1920}, 113 | {"key": "window_outer_height", "value": 1040}, 114 | {"key": "browser_detection_firefox", "value": "false"}, 115 | {"key": "browser_detection_brave", "value": "false"}, 116 | { 117 | "key": "audio_codecs", 118 | "value": '{"ogg":"probably","mp3":"probably","wav":"probably","m4a":"maybe","aac":"probably"}', 119 | }, 120 | { 121 | "key": "video_codecs", 122 | "value": '{"ogg":"probably","h264":"probably","webm":"probably","mpeg4v":"","mpeg4a":"","theora":""}', 123 | }, 124 | {"key": "media_query_dark_mode", "value": "true"}, 125 | {"key": "headless_browser_phantom", "value": "false"}, 126 | {"key": "headless_browser_selenium", "value": "false"}, 127 | {"key": "headless_browser_nightmare_js", "value": "false"}, 128 | {"key": "document__referrer", "value": "null"}, 129 | {"key": "window__ancestor_origins", "value": []}, 130 | {"key": "window__tree_index", "value": []}, 131 | {"key": "window__tree_structure", "value": "[]"}, 132 | {"key": "client_config__surl", "value": "null"}, 133 | {"key": "client_config__language", "value": "en"}, 134 | {"key": "navigator_battery_charging", "value": "true"}, 135 | {"key": "audio_fingerprint", "value": test}, 136 | ], 137 | }, 138 | { 139 | "key": "fe", 140 | "value": [ 141 | "DNT:unknown", 142 | "L:en-US", 143 | "D:24", 144 | "PR:1", 145 | "S:1920,1080", 146 | "AS:1920,1040", 147 | "TO:-120", 148 | "SS:true", 149 | "LS:true", 150 | "IDB:true", 151 | "B:false", 152 | "ODB:true", 153 | "CPUC:unknown", 154 | "PK:Win32", 155 | f"CFP:{cfp_hash(secrets.token_urlsafe(64))}", 156 | "FR:false", 157 | "FOS:false", 158 | "FB:false", 159 | "JSF:Arial,Arial Black,Arial Narrow,Calibri,Cambria,Cambria Math,Comic Sans MS,Consolas,Courier,Courier New,Georgia,Helvetica,Impact,Lucida Console,Lucida Sans Unicode,Microsoft Sans Serif,MS Gothic,MS PGothic,MS Sans Serif,MS Serif,Palatino Linotype,Segoe Print,Segoe Script,Segoe UI,Segoe UI Light,Segoe UI Semibold,Segoe UI Symbol,Tahoma,Times,Times New Roman,Trebuchet MS,Verdana,Wingdings", 160 | "P:Chrome PDF Viewer,Chromium PDF Viewer,Microsoft Edge PDF Viewer,PDF Viewer,WebKit built-in PDF", 161 | "T:0,false,false", 162 | "H:4", 163 | "SWF:false", 164 | ], 165 | }, 166 | {"key": "ife_hash", "value": secrets.token_hex(16)}, 167 | {"key": "cs", "value": 1}, 168 | { 169 | "key": "jsbd", 170 | "value": '{"HL":3,"NCE":true,"DT":"Roblox","NWD":"false","DA":null,"DR":null,"DMT":1,"DO":null,"DOT":1}', 171 | }, 172 | ] 173 | data = cipher(json.dumps(the_data, separators=(',', ':')), key) 174 | return base64.b64encode(data.encode("utf-8")).decode("utf-8") 175 | -------------------------------------------------------------------------------- /browser.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import hashlib 3 | import json 4 | import random 5 | import string 6 | 7 | from Crypto.Cipher import AES 8 | 9 | 10 | def encrypt(data, key): 11 | data = data + chr(16 - len(data) % 16) * (16 - len(data) % 16) 12 | 13 | salt = b"".join(random.choice(string.ascii_lowercase).encode() for _ in range(8)) 14 | salted, dx = b"", b"" 15 | while len(salted) < 48: 16 | dx = hashlib.md5(dx + key.encode() + salt).digest() 17 | salted += dx 18 | 19 | key = salted[:32] 20 | iv = salted[32 : 32 + 16] 21 | aes = AES.new(key, AES.MODE_CBC, iv) 22 | 23 | encrypted_data = { 24 | "ct": base64.b64encode(aes.encrypt(data.encode())).decode("utf-8"), 25 | "iv": iv.hex(), 26 | "s": salt.hex(), 27 | } 28 | return json.dumps(encrypted_data, separators=(",", ":")) 29 | 30 | 31 | def decrypt(data, key): 32 | data = json.loads(data) 33 | dk = key.encode() + bytes.fromhex(data["s"]) 34 | md5 = [hashlib.md5(dk).digest()] 35 | result = md5[0] 36 | for i in range(1, 3 + 1): 37 | md5.insert(i, hashlib.md5((md5[i - 1] + dk)).digest()) 38 | result += md5[i] 39 | 40 | aes = AES.new(result[:32], AES.MODE_CBC, bytes.fromhex(data["iv"])) 41 | data = aes.decrypt(base64.b64decode(data["ct"])) 42 | return data 43 | -------------------------------------------------------------------------------- /solver.py: -------------------------------------------------------------------------------- 1 | import tls_client, random, urllib, time, requests, os, json 2 | import speech_recognition as sr 3 | from bda import get_bda as bda 4 | 5 | # MADE BY Pr0t0n 6 | # AUDIO replacement dict taken from useragents 7 | 8 | 9 | class Funcap: 10 | 11 | def __init__(self, 12 | host: str = 'https://client-demo.arkoselabs.com', 13 | site_key: str = "029EF0D3-41DE-03E1-6971-466539B47725", ua: str="Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", 14 | proxy: str = None, retries: int=5): 15 | self.host = host 16 | self.site_key = site_key 17 | self.ua = ua 18 | self.uav = self.ua.split("Chrome/")[1].split(".")[0] 19 | self.rnd = random.uniform(0.21263337817840222, 0.31263337817840222) 20 | self.session = tls_client.Session(client_identifier=f"chrome_{self.uav}", 21 | random_tls_extension_order=True) 22 | if proxy != None: 23 | self.session.proxies = { 24 | 'https': f'http://{proxy}', 25 | 'http': f'http://{proxy}' 26 | } 27 | self.bda = bda(self.ua) 28 | self.attempts = 0 29 | self.retries = retries 30 | def skey_request(self): 31 | try: 32 | url = f'https://client-api.arkoselabs.com/fc/gt2/public_key/{self.site_key}' 33 | 34 | self.session.headers = { 35 | 'accept': '*/*', 36 | 'accept-language': 'en-US,en;q=0.9', 37 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 38 | 'origin': self.host, 39 | 'referer': self.host, 40 | 'sec-ch-ua': 41 | f'"Google Chrome";v="{self.uav}", "Chromium";v="{self.uav}", "Not-A.Brand";v="24"', 42 | 'sec-ch-ua-mobile': '?0', 43 | 'sec-ch-ua-platform': '"Chrome OS"', 44 | 'sec-fetch-dest': 'empty', 45 | 'sec-fetch-mode': 'cors', 46 | 'sec-fetch-site': 'same-site', 47 | 'user-agent': self.ua 48 | } 49 | 50 | payload = f'bda={urllib.parse.quote(self.bda, safe="")}&public_key={self.site_key}&site={urllib.parse.quote(self.host,safe="")}&userbrowser={urllib.parse.quote(self.ua, safe="")}&rnd={self.rnd}' 51 | response = self.session.post(url, data=payload) 52 | self.session.cookies = response.cookies 53 | print("[DEBUG]: Fetched Challenge Token") 54 | return response.json()['token'] 55 | except: 56 | self.attempts += 1 57 | return self.solve() 58 | def log(self): 59 | try: 60 | url = 'https://client-api.arkoselabs.com/fc/a/' 61 | 62 | self.session.headers = { 63 | 'accept': '*/*', 64 | 'accept-language': 'en-US,en;q=0.9', 65 | 'cache-control': 'no-cache', 66 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 67 | 'origin': self.host, 68 | 'referer': self.host, 69 | 'sec-ch-ua': f'"Google Chrome";v="{self.uav}", "Chromium";v="{self.uav}", "Not-A.Brand";v="24"', 70 | 'sec-ch-ua-mobile': '?0', 71 | 'sec-ch-ua-platform': '"Chrome OS"', 72 | 'sec-fetch-dest': 'empty', 73 | 'sec-fetch-mode': 'cors', 74 | 'sec-fetch-site': 'same-origin', 75 | 'user-agent': self.ua 76 | } 77 | data = f"sid={self.region}&session_token={self.token}&render_type=canvas&category=Site+URL&action={urllib.parse.quote(self.host, safe='')}F&analytics_tier={self.at}" 78 | self.session.post(url, data=data) 79 | print("[DEBUG]: Logged Site Session") 80 | return 81 | except: 82 | self.attempts += 1 83 | return self.solve() 84 | 85 | 86 | def get_challenge(self): 87 | try: 88 | url = 'https://client-api.arkoselabs.com/fc/gfct/' 89 | 90 | data = f"token={self.token}&sid={self.region}&lang=&render_type=canvas&analytics_tier={self.at}&data%5Bstatus%5D=init" 91 | 92 | response = self.session.post(url, data=data).json() 93 | self.challenge_id = response['challengeID'] 94 | print("[DEBUG]: Requested Picture Challenge") 95 | return 96 | except: 97 | self.attempts += 1 98 | return self.solve() 99 | 100 | def get_audio_challenge(self): 101 | try: 102 | url = f'https://client-api.arkoselabs.com/fc/get_audio/?session_token={self.token}&analytics_tier={self.at}&r={self.region}&game=0&language=en' 103 | print("[DEBUG]: Fetched Audio Challenge") 104 | return self.session.get(url).headers['Location'] 105 | except: 106 | self.attempts += 1 107 | return self.solve() 108 | 109 | def game_loaded(self): 110 | try: 111 | url = "https://client-api.arkoselabs.com/fc/a/" 112 | 113 | data = f'sid={self.region}&game_token={self.challenge_id}&session_token={self.token}&game_type=1&render_type=canvas&category=loaded&action=game+loaded&analytics_tier={self.at}' 114 | 115 | self.session.post(url, data=data) 116 | print("[DEBUG]: Logged Canvas Loaded") 117 | return 118 | except: 119 | self.attempts += 1 120 | return self.solve() 121 | 122 | def switch_audio(self): 123 | try: 124 | url = 'https://client-api.arkoselabs.com/fc/a/' 125 | 126 | data = f"sid={self.region}&game_token={self.challenge_id}&session_token={self.token}&game_type=1&render_type=canvas&category=audio+captcha&action=user+clicked+audio&label=swapped+to+audio+captcha&analytics_tier={self.at}" 127 | self.session.post(url, data=data) 128 | print("[DEBUG]: Switched to Audio") 129 | return 130 | except: 131 | self.attempts += 1 132 | return self.solve() 133 | 134 | def download_challenge(self): 135 | try: 136 | response = requests.get(self.challenge).content 137 | with open(f"{os.getcwd()}/challenges/{self.challenge_id}.wav", "wb") as f: 138 | f.write(response) 139 | print(f"[DEBUG]: Downloaded Challenge --> ({self.challenge_id}.wav)") 140 | return 141 | except: 142 | self.attempts += 1 143 | return self.solve() 144 | 145 | def replace_resp(self, resp: str): 146 | resp = resp.lower() 147 | replacements = { 148 | "one": "1", 149 | "to": "2", 150 | "two": "2", 151 | "tree": "3", 152 | "three": "3", 153 | "four": "4", 154 | "for": "4", 155 | "or": "4", 156 | "zero": "0", 157 | "do": "5", 158 | "right": "5", 159 | "hero": "4", 160 | "five": "5", 161 | "six": "6", 162 | "nine": "9", 163 | "white": "1", 164 | "whine": "1", 165 | "dial": "69", 166 | "wine": "1", 167 | "guys": "9", 168 | "sides": "9", 169 | "store": "44", 170 | "door": "04", 171 | "side": "9", 172 | "buy": "55", 173 | "rightly": "53", 174 | "rightfully": "53", 175 | "lee": "53", 176 | "now": "9", 177 | "eight": "8", 178 | "soon": "2", 179 | "wireless": "8", 180 | "find": "5", 181 | "rise": "1", 182 | "italy": "34", 183 | "ice": "0", 184 | "lights": "9", 185 | "light": "9", 186 | "sites": "9", 187 | "pwell": "9", 188 | "well": "9", 189 | "size": "9", 190 | "by": "1", 191 | "knights": "9", 192 | "knight": "9", 193 | "nights": "9", 194 | "night": "9", 195 | "-": "", 196 | " ": "", 197 | "r": "9", 198 | "l": "2", 199 | "a": "4" 200 | } 201 | for key in replacements: 202 | if key in resp: 203 | resp = resp.replace(key, replacements[key]) 204 | return resp 205 | 206 | def solve_audio_challenge(self): 207 | try: 208 | path = f"{os.getcwd()}/challenges/{self.challenge_id}.wav" 209 | try: 210 | possible_solutions = [] 211 | reformed_solutions = [] 212 | r = sr.Recognizer() 213 | with sr.WavFile(path) as s: 214 | #r.adjust_for_ambient_noise(s) 215 | audio = r.record(s) 216 | response = r.recognize_google(audio, show_all=True) 217 | for transcript in response["alternative"]: 218 | transcript = transcript['transcript'] 219 | resp = self.replace_resp(transcript) 220 | possible_solutions.append(resp) 221 | for solution in possible_solutions: 222 | reform_solution = "" 223 | for digit in solution: 224 | try: 225 | digit = int(digit) 226 | reform_solution += str(digit) 227 | except: 228 | pass 229 | if len(reform_solution) < 4: 230 | pass 231 | else: 232 | reformed_solutions.append(reform_solution) 233 | if len(reformed_solutions) == 0: 234 | self.attempts += 1 235 | return self.solve() 236 | reformed_solutions.sort(key=len) 237 | return reformed_solutions[len(reformed_solutions) - 1] 238 | except LookupError: 239 | pass 240 | except: 241 | self.attempts += 1 242 | return self.solve() 243 | 244 | def sumbit_answer(self): 245 | try: 246 | url = 'https://client-api.arkoselabs.com/fc/audio/' 247 | 248 | data = f'r={self.region}&session_token={self.token}&response={self.solution}&analytics_tier={self.at}&audio_type=2&language=en&bio=' 249 | 250 | response = self.session.post(url, data=data).json()['response'] 251 | if response == "correct": 252 | print("[SOLVED]: Solved Captcha") 253 | return 254 | elif response == "incorrect": 255 | print("[INCORRECT]: Captcha Solved Incorrectly!") 256 | self.attempts += 1 257 | else: 258 | print("[FAILED]: Unexpected Error Sumbitting Captcha Solution") 259 | self.attempts += 1 260 | if self.retries == self.attempts: 261 | self.token = None 262 | return 263 | return self.solve() 264 | except: 265 | self.attempts += 1 266 | return self.solve() 267 | 268 | def solve(self): 269 | if self.retries == self.attempts: 270 | return None 271 | print(f"[DEBUG]: Attempt #{self.attempts + 1}") 272 | token = self.skey_request() 273 | self.origin_token = token 274 | parsed_token = token.split("|") 275 | try: 276 | self.token = parsed_token[0] 277 | self.region = parsed_token[1].split("=")[1] 278 | self.meta = parsed_token[2].split("=")[1] 279 | self.at = parsed_token[7].split("=")[1] 280 | self.atp = parsed_token[8].split("=")[1] 281 | except: 282 | pass 283 | self.log() 284 | self.get_challenge() 285 | self.game_loaded() 286 | self.switch_audio() 287 | self.challenge = self.get_audio_challenge() 288 | self.download_challenge() 289 | self.solve_audio_challenge() 290 | self.solution = self.solve_audio_challenge() 291 | print(f"[ANSWER]: Possible Answer --> ({self.solution})") 292 | self.sumbit_answer() 293 | if self.token != None: 294 | return token 295 | else: 296 | return None 297 | if __name__ == "__main__": 298 | token = Funcap().solve() 299 | print(token) 300 | --------------------------------------------------------------------------------