22from colorama import Fore , init
33import os
44import time
5- import threading
6- from concurrent .futures import ThreadPoolExecutor , as_completed
5+ import asyncio
6+ import aiohttp
7+ import random
8+ from datetime import datetime , timedelta
79
810init (autoreset = True )
911
12+ def format_time (seconds ):
13+ if seconds == float ('inf' ):
14+ return "Unknown"
15+ return str (timedelta (seconds = int (seconds )))
16+
17+ class RateLimiter :
18+ def __init__ (self ):
19+ self .reset_time = time .time ()
20+ self .success_count = 0
21+ self .fail_count = 0
22+ self .delay = 0.1
23+ self .last_success = time .time ()
24+ self .consecutive_fails = 0
25+
26+ async def should_send (self ):
27+
28+ success_ratio = self .success_count / (self .success_count + self .fail_count + 1 )
29+ if success_ratio < 0.5 :
30+ self .delay = min (2.0 , self .delay * 1.2 )
31+ elif success_ratio > 0.8 :
32+ self .delay = max (0.1 , self .delay * 0.8 )
33+
34+ await asyncio .sleep (self .delay )
35+ return True
36+
37+ def update_stats (self , success ):
38+ if success :
39+ self .success_count += 1
40+ self .consecutive_fails = 0
41+ self .last_success = time .time ()
42+ else :
43+ self .fail_count += 1
44+ self .consecutive_fails += 1
45+
46+ class MessageQueue :
47+ def __init__ (self , total_messages ):
48+ self .queue = asyncio .Queue ()
49+ self .failed_queue = asyncio .Queue ()
50+ self .total = total_messages
51+ self .sent = 0
52+ self .retries = 0
53+ self .start_time = time .time ()
54+
55+ async def add_failed (self , message_id ):
56+ await self .failed_queue .put (message_id )
57+ self .retries += 1
58+
59+ def get_stats (self ):
60+ elapsed = time .time () - self .start_time
61+ rate = self .sent / elapsed if elapsed > 0 else 0
62+ remaining = self .total - self .sent
63+ eta = remaining / rate if rate > 0 else float ('inf' )
64+ return rate , eta , remaining
65+
1066def extract_webhooks (file_path ):
1167 try :
1268 if not os .path .exists (file_path ):
1369 print (f"{ Fore .RED } [!] File not found: { file_path } " )
1470 return []
1571
1672 with open (file_path , 'r' ) as file :
17-
1873 for _ in range (2 ):
19- next (file , None )
20- # Read remaining lines
74+ next (file )
75+
2176 webhooks = [line .strip () for line in file if line .strip ()]
2277 return webhooks
2378 except Exception as e :
2479 print (f"{ Fore .RED } [!] Error reading webhooks file: { e } " )
2580 return []
2681
2782def display_webhooks (webhooks ):
28- print (f"\n { Fore .RED } [*] { Fore . GREEN } Available Webhooks:" )
83+ print (f"\n { Fore .GREEN } Available Webhooks:" )
2984 for i , webhook in enumerate (webhooks , 1 ):
30- print (f"{ Fore .RED } [{ i } ] { Fore .GREEN } { webhook } " )
85+ short_webhook = webhook [:50 ] + "..." if len (webhook ) > 50 else webhook
86+ print (f"{ Fore .RED } [{ Fore .MAGENTA } { i } { Fore .RED } ] -> { Fore .GREEN } URL: { Fore .RED } { short_webhook } { Fore .RESET } " )
3187
32- def spam_single_message ( webhook , message ):
88+ async def send_message ( session , webhook , message , message_id , queue , rate_limiter ):
3389 try :
34- response = requests .post (webhook , json = {"content" : message })
35- if response .status_code == 429 :
36- retry_after = float (response .headers .get ('Retry-After' , 0.5 ))
37- time .sleep (retry_after )
38- # Retry the request
39- response = requests .post (webhook , json = {"content" : message })
90+ await rate_limiter .should_send ()
4091
41- if response .status_code == 204 :
42- print (f"{ Fore .GREEN } [*] Successfully sent message to webhook: { Fore .RED } { webhook } { Fore .RESET } " )
43- else :
44- print (f"{ Fore .RED } [!] Failed to send message to webhook: { Fore .RED } { webhook } (Status: { response .status_code } ){ Fore .RESET } " )
45- except Exception as e :
46- print (f"{ Fore .RED } [!] Error sending message to webhook: { e } " )
92+ headers = {
93+ 'Content-Type' : 'application/json' ,
94+ 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
95+ }
4796
48- def spam_webhook (webhook , message , count = 1 ):
49- with ThreadPoolExecutor (max_workers = 7 ) as executor :
50- futures = [
51- executor .submit (spam_single_message , webhook , message )
52- for _ in range (count )
53- ]
54- for _ in as_completed (futures ):
55- pass
97+ async with session .post (webhook , json = {"content" : message }, headers = headers , timeout = 5 ) as response :
98+ if response .status == 429 :
99+ retry_after = float (response .headers .get ('Retry-After' , 1 ))
100+ rate_limiter .update_stats (False )
101+ print (f"{ Fore .RED } [!] { Fore .GREEN } Rate Limited : { Fore .RED } Message queued ({ retry_after :.1f} s){ Fore .RESET } " )
102+ await queue .add_failed (message_id )
103+ return False
56104
105+ elif response .status == 204 :
106+ rate_limiter .update_stats (True )
107+ queue .sent += 1
108+ print (f"{ Fore .RED } [+] { Fore .GREEN } Success : { Fore .RED } Message sent{ Fore .RESET } " )
109+ return True
57110
58- def run ():
111+ else :
112+ rate_limiter .update_stats (False )
113+ print (f"{ Fore .RED } [!] { Fore .GREEN } Failed : { Fore .RED } Status { response .status } { Fore .RESET } " )
114+ if response .status != 404 :
115+ await queue .add_failed (message_id )
116+ return False
117+
118+ except Exception as e :
119+ print (f"{ Fore .RED } [!] { Fore .GREEN } Error : { Fore .RED } { str (e )} { Fore .RESET } " )
120+ await queue .add_failed (message_id )
121+ return False
122+
123+ async def spam_webhook (webhook , message , count ):
124+ connector = aiohttp .TCPConnector (limit = None , ttl_dns_cache = 300 )
125+ timeout = aiohttp .ClientTimeout (total = 30 )
126+ rate_limiter = RateLimiter ()
127+ queue = MessageQueue (count )
128+
129+ async with aiohttp .ClientSession (connector = connector , timeout = timeout ) as session :
130+ message_ids = list (range (count ))
131+ chunk_size = 4
132+
133+ while message_ids or not queue .failed_queue .empty ():
134+ current_chunk = []
135+
136+
137+ while len (current_chunk ) < chunk_size :
138+ if message_ids :
139+ current_chunk .append (message_ids .pop (0 ))
140+ elif not queue .failed_queue .empty ():
141+ failed_id = await queue .failed_queue .get ()
142+ current_chunk .append (failed_id )
143+ else :
144+ break
145+
146+ if not current_chunk :
147+ break
148+
149+ tasks = [
150+ asyncio .create_task (
151+ send_message (session , webhook , message , msg_id , queue , rate_limiter )
152+ )
153+ for msg_id in current_chunk
154+ ]
155+
156+ await asyncio .gather (* tasks )
157+
158+ rate , eta , remaining = queue .get_stats ()
159+ print (f"{ Fore .YELLOW } Progress: { queue .sent } /{ count } sent ({ rate :.1f} msg/s | ETA: { format_time (eta )} )" )
160+
161+
162+ await asyncio .sleep (0.5 )
163+
164+ return queue .sent
165+
166+ async def main ():
59167 webhooks_file_path = "input/discord-webhooks.txt"
60168 webhooks = extract_webhooks (webhooks_file_path )
61169
62170 if not webhooks :
63- print (f"{ Fore .RED } [!] No webhooks found in /input/discord-webhooks.txt - Exiting... " )
171+ print (f"{ Fore .RED } [!] No webhooks found in /input/discord-webhooks.txt" )
64172 return
65173
66174 display_webhooks (webhooks )
67-
68- choice = input (f"\n { Fore .RED } [* ] { Fore .GREEN } Select webhook or enter 'A' to use all: " ).strip ()
175+ print ( f" \n { Fore . YELLOW } Select webhook or type 'A' to use all..." )
176+ choice = input (f"{ Fore .RED } [+ ] { Fore .GREEN } Webhook >> { Fore . RED } " ).strip ()
69177
70178 if choice .lower () == 'a' :
71- selected_webhooks = webhooks
179+ selected_webhooks = webhooks
72180 elif choice .isdigit () and 1 <= int (choice ) <= len (webhooks ):
73- selected_webhooks = [webhooks [int (choice ) - 1 ]]
181+ selected_webhooks = [webhooks [int (choice ) - 1 ]]
74182 else :
75183 print (f"{ Fore .RED } [!] Invalid choice. Exiting..." )
76184 return
77185
78- message = input (f"\n { Fore .RED } [+] { Fore .GREEN } Message -> " ).strip ()
79- count = input (f"\n { Fore .RED } [+] { Fore .GREEN } Number of messages to send -> " ).strip ()
186+ message = input (f"{ Fore .RED } [+] { Fore .GREEN } Message >> { Fore . RED } " ).strip ()
187+ count = input (f"{ Fore .RED } [+] { Fore .GREEN } Count >> { Fore . RED } " ).strip ()
80188
81189 try :
82190 count = int (count )
83191 if count < 1 :
84192 raise ValueError
85193 except ValueError :
86- print (f"{ Fore .RED } [!] Invalid number . Exiting..." )
194+ print (f"{ Fore .RED } [!] Invalid count . Exiting..." )
87195 return
88196
89- for webhook in selected_webhooks :
90- spam_webhook (webhook , message , count )
197+ print (f"\n { Fore .YELLOW } Starting..." )
198+ total_start_time = time .time ()
199+ total_sent = 0
91200
92- print (f"\n { Fore .RED } [*] { Fore .LIGHTGREEN_EX } Finished sending { count } messages to { len (selected_webhooks )} webhook(s)!" )
201+ try :
202+ for webhook in selected_webhooks :
203+ sent = await spam_webhook (webhook , message , count )
204+ total_sent += sent
205+
206+ except KeyboardInterrupt :
207+ print (f"\n { Fore .RED } [!] Operation interrupted by user" )
208+ except Exception as e :
209+ print (f"\n { Fore .RED } [!] An error occurred: { str (e )} " )
210+ finally :
211+ total_time = time .time () - total_start_time
212+ rate = total_sent / total_time if total_time > 0 else 0
213+
214+ print (f"\n { Fore .RED } [+] { Fore .GREEN } Final Summary:" )
215+ print (f"{ Fore .RED } [+] { Fore .GREEN } Total Sent : { Fore .RED } { total_sent } " )
216+ print (f"{ Fore .RED } [+] { Fore .GREEN } Time Elapsed : { Fore .RED } { format_time (total_time )} " )
217+ print (f"{ Fore .RED } [+] { Fore .GREEN } Average Rate : { Fore .RED } { rate :.1f} msg/s" )
218+ print (f"{ Fore .RED } [+] { Fore .GREEN } Webhooks Used : { Fore .RED } { len (selected_webhooks )} " )
219+
220+ def run ():
221+ asyncio .run (main ())
93222
94223if __name__ == "__main__" :
95224 run ()
0 commit comments