GutterTart/newnew.py
2025-01-20 14:21:02 -05:00

216 lines
8.8 KiB
Python

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 "<title>" in await response.text() and "</title>" in await response.text():
start = (await response.text()).find("<title>") + len("<title>")
end = (await response.text()).find("</title>")
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.")