diff --git a/newnew.py b/newnew.py new file mode 100644 index 0000000..02cc391 --- /dev/null +++ b/newnew.py @@ -0,0 +1,215 @@ +import aiohttp +import random +import string +import time +import socket +import threading +import discord +import asyncio +from datetime import datetime +import json +import signal +import sys + +# IRC connection settings +SERVER = "irc.supernets.org" +PORT = 6667 +CHANNEL = "#superbowl" +OLD_CHANNEL = "#blackhole" +NICKNAME = "butts" +NICKSERV_PASSWORD = "butts" + +# Discord Bot Token +DISCORD_BOT_TOKEN = "il1k3A1pH4B3tS0upZcUz1tT4ugHtM32r33dGuDS" + +# Counters and metrics +valid_invite_count = 0 +scanned_invite_count = 0 +valid_invites = [] +error_count = 0 +rate_limited_count = 0 +scan_state_file = "scan_state.json" +user_agents = [ + "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Mobile Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.101 Mobile Safari/537.36" +] + +# Load scan state if exists +def load_scan_state(): + global valid_invite_count, scanned_invite_count, error_count + try: + with open(scan_state_file, 'r') as f: + state = json.load(f) + valid_invite_count = state.get('valid_invite_count', 0) + scanned_invite_count = state.get('scanned_invite_count', 0) + error_count = state.get('error_count', 0) + except FileNotFoundError: + pass + +# Save scan state to file +def save_scan_state(): + state = { + 'valid_invite_count': valid_invite_count, + 'scanned_invite_count': scanned_invite_count, + 'error_count': error_count + } + with open(scan_state_file, 'w', encoding='utf-8') as f: + json.dump(state, f, ensure_ascii=False) + +# Generate a random user-agent +def get_random_user_agent(): + return random.choice(user_agents) + +# Generate a random Discord invite code +def generate_random_code(): + length = random.randint(2, 10) + characters = string.ascii_letters + string.digits + return ''.join(random.choice(characters) for _ in range(length)) + +async def join_discord_and_list_members(client, invite_url, server_name, log_file, irc_socket): + try: + invite = await client.fetch_invite(invite_url) + guild_id = invite.guild.id + guild = client.get_guild(guild_id) + + if guild is None: + print(f"Invite URL {invite_url} is valid but does not reference a guild.") + irc_socket.sendall(f"PRIVMSG {CHANNEL} :Invite URL {invite_url} is valid but does not reference a guild.\r\n".encode("utf-8")) + return + + members = await guild.fetch_members(limit=None).flatten() + member_count = len(members) + creation_date = guild.created_at.strftime("%Y-%m-%d %H:%M:%S") + print(f"Joined server: {guild.name} (Members: {member_count}, Created: {creation_date})") + irc_socket.sendall(f"PRIVMSG {CHANNEL} :Joining server: {server_name} ({invite_url}, Members: {member_count}, Created: {creation_date})\r\n".encode("utf-8")) + member_names = ", ".join(member.name for member in members) + log_file.write(f"{server_name}, {invite_url}, Members: {member_count}, Created: {creation_date}, {member_names}\n") + log_file.flush() + valid_invites.append((invite_url, datetime.now())) + except Exception as e: + global error_count + error_count += 1 + print(f"Error joining server or fetching members: {e}") + irc_socket.sendall(f"PRIVMSG {CHANNEL} :Error joining server or fetching members: {e}\r\n".encode("utf-8")) + +async def check_invite_http(url, log_file, irc_socket, client): + global valid_invite_count, scanned_invite_count, rate_limited_count + scanned_invite_count += 1 + headers = {'User-Agent': get_random_user_agent()} + async with aiohttp.ClientSession() as session: + try: + async with session.get(url, headers=headers, timeout=10) as response: + if response.status == 429: + rate_limited_count += 1 + print("Rate limit encountered. Slowing down.") + await asyncio.sleep(10) + return + if response.status == 200 and "Join the" in await response.text(): + server_name = "Unknown Server" + if "" in await response.text() and "" in await response.text(): + start = (await response.text()).find("") + len("<title>") + end = (await response.text()).find("") + server_name = (await response.text())[start:end].strip() + print(f"Valid invite found: {url}, {server_name}") + log_file.write(f"Valid invite: {url}, {server_name}\n") + log_file.flush() + valid_invite_count += 1 + await join_discord_and_list_members(client, url, server_name, log_file, irc_socket) + else: + print(f"Invalid invite: {url}") + except Exception as e: + global error_count + error_count += 1 + print(f"Error checking invite: {url} - {e}") + +def keep_connection_alive(irc_socket): + try: + while True: + data = irc_socket.recv(2048).decode("utf-8", errors="replace") + for line in data.split("\r\n"): + if line.startswith("PING"): + pong_response = line.split()[1] + irc_socket.sendall(f"PONG {pong_response}\r\n".encode("utf-8")) + print(f"Sent PONG {pong_response}") + except socket.error as e: + print(f"Connection error in keep_connection_alive: {e}") + +def handle_irc_connection(irc_socket): + irc_socket.sendall(f"NICK {NICKNAME}\r\n".encode("utf-8")) + irc_socket.sendall(f"USER {NICKNAME} 0 * :{NICKNAME}\r\n".encode("utf-8")) + threading.Thread(target=keep_connection_alive, args=(irc_socket,), daemon=True).start() + print("Waiting 5 seconds before identifying with NickServ...") + time.sleep(5) + irc_socket.sendall(f"PRIVMSG NickServ :IDENTIFY {NICKSERV_PASSWORD}\r\n".encode("utf-8")) + print("Identified with NickServ.") + print("Waiting 5 seconds before leaving #blackhole...") + time.sleep(5) + irc_socket.sendall(f"PART {OLD_CHANNEL}\r\n".encode("utf-8")) + print(f"Left channel {OLD_CHANNEL}") + irc_socket.sendall(f"JOIN {CHANNEL}\r\n".encode("utf-8")) + print(f"Joined channel {CHANNEL}") + irc_socket.sendall(f"PRIVMSG {CHANNEL} :Starting invite scanner...\r\n".encode("utf-8")) + +async def report_valid_invites(irc_socket): + global valid_invite_count, scanned_invite_count, error_count, rate_limited_count + while True: + await asyncio.sleep(600) # 10 minutes + irc_socket.sendall(f"PRIVMSG {CHANNEL} :Valid invites found: {valid_invite_count}, Links scanned: {scanned_invite_count}, Errors: {error_count}, Rate limits hit: {rate_limited_count}\r\n".encode("utf-8")) + +async def shutdown_handler(irc_socket, client): + print("Shutting down gracefully...") + irc_socket.sendall(f"PRIVMSG {CHANNEL} :Stopping invite scanner.\r\n".encode("utf-8")) + irc_socket.close() + await client.close() + save_scan_state() + sys.exit() + +async def run_scanner(log_file, irc_socket, client): + global shutdown_event + try: + while not shutdown_event.is_set(): + random_code = generate_random_code() + invite_url = f"https://discord.com/invite/{random_code}" + await check_invite_http(invite_url, log_file, irc_socket, client) + await asyncio.sleep(random.uniform(0.5, 1)) + except KeyboardInterrupt: + pass + +async def main(): + log_filename = "valid_invites.txt" + with open(log_filename, 'a', encoding='utf-8') as log_file: + irc_socket = socket.create_connection((SERVER, PORT)) + handle_irc_connection(irc_socket) + + intents = discord.Intents.all() + client = discord.Client(intents=intents) + + @client.event + async def on_ready(): + print(f'Logged in as {client.user}') + + global shutdown_event + shutdown_event = threading.Event() # Use threading.Event instead of asyncio.Event + + def on_signal(signum, frame): + shutdown_event.set() # Set the shutdown_event to signal termination + + signal.signal(signal.SIGINT, on_signal) + signal.signal(signal.SIGTERM, on_signal) + + asyncio.create_task(report_valid_invites(irc_socket)) + scanner_task = asyncio.create_task(run_scanner(log_file, irc_socket, client)) + + try: + await client.start(DISCORD_BOT_TOKEN) # Properly start the Discord client + await scanner_task + finally: + await shutdown_handler(irc_socket, client) + +if __name__ == "__main__": + load_scan_state() + try: + asyncio.run(main()) + except (KeyboardInterrupt, SystemExit): + print("Program terminated.")