# -*- coding: utf-8 -*-
# This file is part of BUGHUNTERS PRO
# written by @ssskingsss12
# BUGHUNTERS PRO is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.






























































































































































































































































































































































import os
import sys
import subprocess
import time

def clear_screen():
    os.system('cls' if os.name == 'nt' else 'clear')

REQUIRED_MODULES = [
    'multithreading', 'loguru', 'colorama', 'tqdm', 'bs4', 'pyfiglet',
    'requests', 'ipcalc', 'six', 'ping3', 'aiohttp', 'InquirerPy',
    'termcolor', 'tldextract', 'websocket-client', 'dnspython', 'bugscan-x',
    'inquirer', 'shutil', 'cryptography', 'queue'
]

SYSTEM_PACKAGES = ["rust", "binutils", "clang", "openssl", "openssl-tool", "make", "dnsutils",]

def install_python_module(module_name):
    try:
        subprocess.check_call([
        sys.executable, "-m", "pip", "install", 
        module_name, "--break-system-packages"
        ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        print(f"Installed {module_name}")
        return True
    except subprocess.CalledProcessError:
        print(f"Failed to install {module_name}")
        return False

def install_system_package(package_name, package_manager):
    try:
        subprocess.run([package_manager, "install", "-y", package_name], check=True)
        print(f"Installed {package_name}")
        return True
    except subprocess.CalledProcessError:
        print(f"Failed to install {package_name}")
        return False

def update_system(package_manager):
    try:
        print("\nUpdating system...")
        subprocess.run([package_manager, "update", "-y"], check=True)
        subprocess.run([package_manager, "upgrade", "-y"], check=True)
        print("System updated successfully")
        return True
    except subprocess.CalledProcessError:
        print("Failed to update system")
        return False

def install_dependencies():
    clear_screen()
    print("""
        
    =========================================
    \033[38;5;10mAUTOMATED PACKAGE AND MODULE INSTALLATION\033[0m
    =========================================
    
    First-time install takes 10-15 mins on 4GB RAM
    Please keep wake lock on to speed up this process
    """)
    
    if input("\033[4m \033[38;5;196mFirst Time Running?\033[0m \033[38;5;208mInstall packages and modules?\033[0m (\033[38;5;46myes\033[0m/\033[38;5;196mno\033[0m):").lower() not in ['yes', 'y']:
        print("\nSkipping installation...")
        time.sleep(1)
        clear_screen()
        return

    # Install system packages on non-Windows systems
    if os.name != 'nt':
        package_manager = input("\nEnter your package manager (apt/pkg/etc): ").strip()
        
        if update_system(package_manager):
            print("\nInstalling system packages...")
            for package in SYSTEM_PACKAGES:
                install_system_package(package, package_manager)

    # Install Python modules
    print("\nInstalling Python modules...")
    for module in REQUIRED_MODULES:
        try:
            __import__(module)
            print(f" {module} already installed")
        except ImportError:
            install_python_module(module)

    print("\nInstallation complete!")
    time.sleep(1)

install_dependencies()

#=============================  Imports  ========================#
## Standard library imports
import argparse
import asyncio
import base64
import json
import pathlib
import queue
import random
import re
import socket
import ssl
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timedelta
from urllib.parse import urlparse
from requests.exceptions import RequestException
from urllib3.exceptions import LocationParseError, ProxyError

# Third-party imports
import dns
import dns.resolver
import ipaddress
import multithreading
import pyfiglet
import requests
import tldextract
import urllib3
from bs4 import BeautifulSoup, BeautifulSoup as bsoup
from colorama import init, Fore
from InquirerPy import inquirer
from tqdm import tqdm
import shutil
import inquirer
import dns.resolver
from cryptography import x509
from cryptography.hazmat.backends import default_backend
import ipaddress
import time
import os
import requests
import signal
import atexit
import sys
import urllib3
from concurrent.futures import ThreadPoolExecutor, as_completed
import dns.reversename
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
from queue import Queue
init(autoreset=True)

# Colors
CYAN = '\033[96m'
FAIL = '\033[91m'
ENDC = '\033[0m'
UNDERLINE = '\033[4m'
WARNING = '\033[93m'
YELLOW = '\033[33m'
PURPLE = '\033[35m'
ORANGE = '\033[38;5;208m'
BRIGHT_ORANGE ='\033[38;5;202m'
MAGENTA = '\033[38;5;201m'
OLIVE = '\033[38;5;142m'
LIME = '\033[38;5;10m'
BLUE = '\033[38;5;21m'
PINK = '\033[38;5;219m'
RED = '\033[38;5;196m'
GREEN = '\033[38;5;46m'
WHITE = '\033[38;5;15m'
BLACK = '\033[38;5;0m'
GREY = '\033[38;5;8m'
BOLD = '\033[1m'
ITALIC = '\033[3m'
UNDERLINE = '\033[4m'
BLINK = '\033[5m'
INVERTED = '\033[7m'
HIDDEN = '\033[8m'
BOLD_CYAN = '\033[1;36m'
BOLD_RED = '\033[1;31m'
BOLD_GREEN = '\033[1;32m'
BOLD_YELLOW = '\033[1;33m'
BOLD_BLUE = '\033[1;34m'
BOLD_MAGENTA = '\033[1;35m'
BOLD_WHITE = '\033[1;37m'
BOLD_BLACK = '\033[1;30m'
BOLD_GREY = '\033[1;90m'
BOLD_ORANGE = '\033[1;38;5;208m'
BOLD_OLIVE = '\033[1;38;5;142m'
BOLD_LIME = '\033[1;38;5;10m'
BOLD_PINK = '\033[1;38;5;219m'
BOLD_BRIGHT_ORANGE = '\033[1;38;5;202m'
BOLD_BRIGHT_YELLOW = '\033[1;38;5;226m'
BOLD_BRIGHT_GREEN = '\033[1;38;5;46m'
BOLD_BRIGHT_BLUE = '\033[1;38;5;21m'
BOLD_BRIGHT_MAGENTA = '\033[1;38;5;201m'
BOLD_BRIGHT_CYAN = '\033[1;38;5;51m'
BOLD_BRIGHT_RED = '\033[1;38;5;196m'
BOLD_BRIGHT_WHITE = '\033[1;38;5;15m'
BOLD_BRIGHT_BLACK = '\033[1;38;5;0m'
BOLD_BRIGHT_GREY = '\033[1;38;5;8m'
BOLD_BRIGHT_ORANGE = '\033[1;38;5;208m'
BOLD_BRIGHT_OLIVE = '\033[1;38;5;142m'
BOLD_BRIGHT_LIME = '\033[1;38;5;10m'
BOLD_BRIGHT_PINK = '\033[1;38;5;219m'
BOLD_BRIGHT_PURPLE = '\033[1;38;5;201m'
BOLD_BRIGHT_ORANGE = '\033[1;38;5;202m'


#=========================== Utility functions ====================================#
def generate_ascii_banner(text1, text2, font="ansi_shadow", shift=3):

    text1_art = pyfiglet.figlet_format(text1, font=font)
    text2_art = pyfiglet.figlet_format(text2, font=font)
    
    shifted_text1 = "\n".join([" " * shift + line for line in text1_art.split("\n")])
    shifted_text2 = "\n".join([" " * shift + line if i != 0 else line for i, line in enumerate(text2_art.split("\n"))])
    
    randomshit("\n" + shifted_text1 + shifted_text2)

def randomshit(text):
    color_list = [
        CYAN,
        FAIL,
        WARNING,
        YELLOW,
        PURPLE,
        ORANGE,
        BRIGHT_ORANGE,
        MAGENTA,
        OLIVE,
        LIME,
        BLUE,
        PINK,
        RED,
        GREEN,
        WHITE,
        GREY,
        BOLD_CYAN,
        BOLD_RED,
        BOLD_GREEN,
        BOLD_YELLOW,
        BOLD_BLUE,
        BOLD_MAGENTA,
        BOLD_WHITE,
        BOLD_GREY,
        BOLD_ORANGE,
        BOLD_OLIVE,
        BOLD_LIME,
        BOLD_PINK,
        BOLD_BRIGHT_ORANGE,
        BOLD_BRIGHT_YELLOW,
        BOLD_BRIGHT_GREEN,
        BOLD_BRIGHT_BLUE,
        BOLD_BRIGHT_MAGENTA,
        BOLD_BRIGHT_CYAN,
        BOLD_BRIGHT_RED,
        BOLD_BRIGHT_GREY,
        BOLD_BRIGHT_OLIVE,
        BOLD_BRIGHT_LIME,
        BOLD_BRIGHT_PINK,
        BOLD_BRIGHT_PURPLE
    ]

    chosen_color = random.choice(color_list)

    for char in text:
        sys.stdout.write(f"{chosen_color}{char}{ENDC}")
        sys.stdout.flush()

#========================== Info Gathering Menu ======================================#
def Info_gathering_menu():

    while True:
        clear_screen()
        banner()
        print(MAGENTA +"======================================="+ ENDC)
        print(MAGENTA +"          Info Gathering Menu          "+ ENDC)    
        print(MAGENTA +"======================================="+ ENDC)

        print("1.  SUBDOmain FINDER    2. urlscan.io") 
        print("3.  REVULTRA            4. DR ACCESS")
        print("5.  HOST CHECKER        6. Free Proxies")
        print("7.  TLS checker         8. BGSLEUTH")
        print("9.  CDN FINDER         10. Host Proxy Checker")
        print("11. Web Crawler        12. Dossier")
        print("13. BUCKET             14. HACKER TARGET")
        print("15. Url Redirect       16. Twisted")
        print("17. CDN FINDER2 HTTP INJECTOR")             
        print("18. HOST CHECKER V2    19. Stat")


        print("Hit enter to return to the main menu",'\n')
        choice = input("Enter your choice: ")

        if choice == '':
            randomshit("Returning to BUGHUNTERS PRO...")
            time.sleep(1)
            return

        elif choice == '1':
            clear_screen()
            subdomain_finder()

        elif choice == '2':
            clear_screen()
            url_io()

        elif choice == '3':
            clear_screen()
            rev_ultra()

        elif choice == '4':
            clear_screen()
            dr_access()

        elif choice == '5':
            clear_screen()
            host_checker()

        elif choice == '6':
            clear_screen()
            free_proxies()

        elif choice == '7':
            clear_screen()
            tls_checker()

        elif choice == '8':
            clear_screen()
            bg_sluth()

        elif choice == '9':
            clear_screen()
            cdn_finder()

        elif choice == '10':
            clear_screen()
            host_proxy_checker()

        elif choice == '11':
            clear_screen()
            web_crawler()

        elif choice == '12':
            clear_screen()
            dossier()

        elif choice == '13':
            clear_screen()
            bucket()

        elif choice == "14":
            clear_screen()
            hacker_target()

        elif choice == '15':
            clear_screen()
            url_redirect()

        elif choice == '16':
            clear_screen()
            twisted()

        elif choice == '17':
            clear_screen()
            cdn_finder2()

        elif choice == '18':
            clear_screen()
            hostchecker_v2()

        elif choice == '19':
            clear_screen()
            stat()

        else:
            print("Invalid option. Please try again.")
            time.sleep(2)
            continue
        
        randomshit("\nTask Completed Press Enter to Continue ")
        input()

#========================== Info Gathering Scripts ===================================#
#=====SUBFINDER=====#
def subdomain_finder():

    generate_ascii_banner("SUBDOmain", "FINDER")

    def scan_date(domain, formatted_date, domains, ips, progress_bar):
        url = f"https://subdomainfinder.c99.nl/scans/{formatted_date}/{domain}"
        try:
            response = requests.get(url)
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, "html.parser")
                tr_elements = soup.find_all("tr", {"onclick": "markChecked(this)"})

                if tr_elements:
                    unique_domains = set()
                    unique_ips = set()
                    for tr in tr_elements:
                        td_elements = tr.find_all("td")
                        for td in td_elements:
                            link = td.find("a", class_="link")
                            if link:
                                href_link = link["href"]
                                href_link = href_link.lstrip('/').replace('geoip/', '')
                                unique_domains.add(href_link)
                            
                            ip = td.find("a", class_="ip")
                            if ip:
                                href_ip = ip.text.strip()
                                href_ip = href_ip.lstrip('geoip/')
                                unique_ips.add(href_ip)
                    
                    domains.update(unique_domains)
                    ips.update(unique_ips)

        except (ConnectionResetError, requests.exceptions.ConnectionError):
            print("ConnectionResetError occurred. Retrying in 2 seconds...")
            time.sleep(2)
            scan_date(domain, formatted_date, domains, ips, progress_bar)
        finally:
            time.sleep(1)
            progress_bar.update(1)

    def subdomains_finder_main():
        current_date = datetime.now()
        start_date = current_date - timedelta(days=7*2)

        domain = input("Enter the domain name: ")
        domains = set()
        ips = set()
        total_days = (current_date - start_date).days + 1

        print(f"Start Date: {start_date.strftime('%Y-%m-%d')}")
        print(f"End Date: {current_date.strftime('%Y-%m-%d')}")

        save_domains = input("Do you want to save domains (y/n)? ").lower()

        if save_domains == 'y':
            output_domains_filename = input("Enter the output file name for domains (e.g., domains.txt): ")


        progress_bar = tqdm(total=total_days, desc="Scanning Dates", unit="day")
        current = start_date
        threads = []

        while current <= current_date:
            formatted_date = current.strftime("%Y-%m-%d")
            thread = threading.Thread(target=scan_date, args=(domain, formatted_date, domains, ips, progress_bar))
            thread.start()
            threads.append(thread)
            current += timedelta(days=1)
            time.sleep(0.5)

        for thread in threads:
            thread.join()

        progress_bar.close()

        if save_domains == 'y' and domains:
            with open(output_domains_filename, 'w') as domains_file:
                for domain in domains:
                    if domain is not None:  # Check for None values
                        domains_file.write(domain + '\n')
            print(f"{len(domains)} Domains saved to {output_domains_filename}")

    subdomains_finder_main()

#===URL.IO===#
def url_io():
    
    generate_ascii_banner("URL", ". IO")

    def search_urlscan(domain):
        url = f"https://urlscan.io/api/v1/search/?q=domain:{domain}"
        response = requests.get(url)
        return response.json() if response.status_code == 200 else None

    def save_results(results, filename):
        unique_urls = set()
        with open(filename, 'w') as file:
            for domain_info in results['DomainInfo']:
                unique_urls.add(domain_info['url'])
            
            for apex_domain, urlscan_info in results['Urlscan'].items():
                if urlscan_info is not None and 'results' in urlscan_info:
                    for result in urlscan_info['results']:
                        task = result.get('task', {})
                        unique_urls.add(task.get('url'))
            
            for url in unique_urls:
                file.write(f"{url}\n")

    def extract_domain_info(url):
        extracted = tldextract.extract(url)
        apex_domain = f"{extracted.domain}.{extracted.suffix}"
        return {
            'domain': extracted.domain,
            'apex_domain': apex_domain,
            'url': url
        }

    def extract_urlscan_info(urlscan_result):
        extracted_info = []
        if 'results' in urlscan_result:
            for result in urlscan_result['results']:
                task = result.get('task', {})
                extracted_info.append({
                    'domain': task.get('domain'),
                    'apex_domain': task.get('apexDomain'),
                    'url': task.get('url')
                })
        return extracted_info

    def process_domains(domains):
        processed_domains = set()
        results = {'DomainInfo': [], 'Urlscan': {}}

        for user_input in domains:
            try:
                domain_info = extract_domain_info(user_input.strip())
                apex_domain = domain_info['apex_domain']
                
                if apex_domain in processed_domains:
                    print(f"Domain '{apex_domain}' already processed. Skipping.")
                    continue

                processed_domains.add(apex_domain)
                results['DomainInfo'].append(domain_info)
                urlscan_result = search_urlscan(user_input)
                results['Urlscan'][apex_domain] = urlscan_result

                # Display the required fields on the screen
                print("Domain Info:")
                print(f"Domain: {domain_info['domain']}")
                print(f"Apex Domain: {domain_info['apex_domain']}")
                print(f"URL: {domain_info['url']}\n")

            except Exception as e:
                print(f"An error occurred:")

        output_filename = input("Enter a filename to save the results (e.g., results.txt): ")
        save_results(results, output_filename)
        print("Results saved successfully!")

    def url_io_main():
        input_option = input("Enter '1' to input a domain or IP manually, '2' to read from a file: ").strip()

        if input_option == '1':
            domain_or_ip = input("Enter a domain or IP: ").strip()
            process_domains([domain_or_ip])
        elif input_option == '2':
            file_path = input("Enter the filename (e.g., domains.txt): ").strip()
            try:
                with open(file_path, 'r') as file:
                    domains = file.readlines()
                    process_domains(domains)
            except FileNotFoundError:
                print(f"File '{file_path}' not found.")
        else:
            print("Invalid option selected.")
    
    url_io_main()

#===REVULTRA===#
def rev_ultra():
    
    generate_ascii_banner("REVULTRA", "")

    def random_user_agent():
        user_agents = [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.9999.999 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36",
            "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
            "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
            "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
            "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)",
            "DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)",
            "Sogou web spider/4.0 (+http://www.sogou.com/docs/help/webmasters.htm#07)",
            "ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)",
            "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 OPR/84.0.4316.140",
            "OpenAI-GPT3/1.0 (compatible; +https://www.openai.com)",
            "HuggingFace/Transformers/4.0 (https://huggingface.co)",
            "Cohere/1.0 (https://cohere.ai)",
            "Anthropic/1.0 (https://www.anthropic.com)",
            "Google-Bard/1.0 (https://www.google.com/bard)",
            "Azure-Cognitive-Services/1.0 (https://azure.microsoft.com/en-us/services/cognitive-services/)",

        ]

        return random.choice(user_agents)

    def scrape_page(url, scraped_domains, lock, file):
        headers = {'User-Agent': random_user_agent()}
        retries = 999
        for _ in range(retries):
            try:
                response = requests.get(url, headers=headers)
                if response.status_code == 500:
                    print("Hold 1 sec, error, retrying...")
                    time.sleep(1)
                    continue
                response.raise_for_status()
                soup = BeautifulSoup(response.text, 'html.parser')
                
                # Find all <tr> tags containing data
                tr_tags = soup.find_all('tr')
                
                # Extract domain names and IPs
                has_domains = False
                for tr in tr_tags:
                    tds = tr.find_all('td')
                    if len(tds) >= 2:
                        domain = tds[0].text.strip()
                        ip = tds[1].text.strip()
                        # Add domain name and IP to the set of scraped domains
                        if domain and ip:  # Check if domain and IP are not empty
                            has_domains = True
                            with lock:
                                scraped_domains.add((domain, ip))
                                file.write(f"{domain}\n{ip}\n")  # Save each domain and IP immediately
                            print(f"Grabbed domain: {domain}, IP: {ip}")  # Print the scraped domain and IP
                # If no domains found, exit early
                if not has_domains:
                    print("No domains found on this page.")
                    return False  # Return False if no domains were found
                return True  # Return True if domains were found
            except:
                print("...Pressure....")
                print("...Retrying...")

        print("Max retries exceeded. Unable to fetch data")
        return False

    def scrape_rapiddns(domain, num_pages, file):
        base_url = "https://rapiddns.io/s/{domain}?page={page}"
        base_url2 = "https://rapiddns.io/sameip/{domain}?page={page}"
        scraped_domains = set()
        lock = threading.Lock()

        def scrape_for_page(page):
            for url_type in [base_url, base_url2]:  # Iterate over both URLs
                url = url_type.format(domain=domain, page=page)
                with tqdm(total=1, desc=f"Page {page}", leave=False) as pbar:
                    if scrape_page(url, scraped_domains, lock, file):
                        pbar.set_description(f"Page {page} ({len(scraped_domains)} domains)")  # Update description with count of domains
                        pbar.update(1)
                        return True  # Exit if domains were found
                    else:
                        print(f"No more data available for {domain}.")
            return False

        with ThreadPoolExecutor(max_workers=10) as executor:
            for page in range(1, num_pages + 1):
                future = executor.submit(scrape_for_page, page)
                if not future.result():  # If no more data is found, stop further scraping
                    break

        return scraped_domains

    def rev_ultra_main():
        domain_input = input("Enter the domain, IP/CDIR, or file name.txt: ")
        num_pages = int(input("Enter the number of pages to scan: "))
        filename = input("Enter the name of the file to save domains (without extension): ")
    
        # Add '.txt' extension if not provided
        if not filename.endswith('.txt'):
            filename += '.txt'
    
        # If input is a file
        if domain_input.endswith('.txt'):
            with open(filename, 'w') as file:
                all_domains = set()
                with open(domain_input, 'r') as input_file:
                    for line in input_file:
                        current_url = line.strip()
                        if current_url:
                            print(f"Finding data for URL: {current_url}")
                            domains = scrape_rapiddns(current_url, num_pages, file)
                            if domains:
                                all_domains |= domains  # Merge domains from all URLs
                            else:
                                print(f"No more domains found for {current_url}. Moving to next URL.")
                        else:
                            print("Empty line encountered in the file, moving to next.")
    
                print(f"Total unique domains scraped: {len(all_domains)}")
        else:  # If single domain input
            with open(filename, 'w') as file:
                domains = scrape_rapiddns(domain_input, num_pages, file)
                print(f"Total unique domains scraped: {len(domains)}")
        return filename
    filename = rev_ultra_main()
    print(filename)
    time.sleep(2)
    clear_screen()
    file_proccessing()

#===DR ACCESS===#
def dr_access():
    
    generate_ascii_banner("D.R", "ACCESS")
    lock = threading.RLock()

    def get_value_from_list(data, index, default=""):
        try:
            return data[index]
        except IndexError:
            return default

    def log(value):
        with lock:
            print(value)

    def log_replace(value):
        with lock:
            sys.stdout.write(f"{value}\r")
            sys.stdout.flush()

    class BugScanner:
        def __init__(self):
            self.output = None
            self.mode = {"direct": {}, "ssl": {}, "proxy": {}}
            self.method = {"HEAD": {}, "GET": {}, "OPTIONS": {}}
            self.deep = 10
            self.ignore_redirect_location = ""
            
            self.scanned = {"direct": {}, "ssl": {}, "proxy": {}}

            self.port = 80, 443, 8080, 8443, 53, 22
            self.proxy = None
            self.threads = 8

        brainfuck_config = {

            "ProxyRotator": {
                "Port": "1080"
            },
            "Inject": {
                "Enable": True,
                "Type": 2,
                "Port": "8989",
                "Rules": {
                    "akamai.net:80": [
                        "125.235.36.177"
                    ]
                },
                "Payload": "",
                "ServerNameIndication": "",
                "MeekType": 0,
                "Timeout": 5,
                "ShowLog": False
            },
            "PsiphonCore": 12,
            "Psiphon": {
                "CoreName": "psiphon-tunnel-core",
                "Tunnel": 1,
                "Region": "SG",
                "Protocols": [
                    "FRONTED-MEEK-HTTP-OSSH",
                    "FRONTED-MEEK-OSSH"
                ],
                "TunnelWorkers": 2,
                "KuotaDataLimit": 1,
                "Authorizations": []
            }

        }

        def request(self, method, hostname, port, *args, **kwargs):
            try:
                url = ("https" if port == 443 else "http") + "://" + (hostname if port == 443 else f"{hostname}:{port}")
                log_replace(f"{method} {url}")
                return requests.request(method, url, *args, **kwargs)
            except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout):
                return None

        def resolve(self, hostname):
            try:
                cname, hostname_list, host_list = socket.gethostbyname_ex(hostname)
            except (socket.gaierror, socket.herror):
                return []

            for i in range(len(hostname_list)):
                yield get_value_from_list(host_list, i, host_list[-1]), hostname_list[i]

            yield host_list[-1], cname

        def get_direct_response(self, method, hostname, port):
            if f"{hostname}:{port}" in self.scanned["direct"]:
                return None

            response = self.request(method.upper(), hostname, port, timeout=5, allow_redirects=False)
            if response is not None:
                status_code = response.status_code
                server = response.headers.get("server", "")
            else:
                status_code = ""
                server = ""

            self.scanned["direct"][f"{hostname}:{port}"] = {
                "status_code": status_code,
                "server": server,
            }
            return self.scanned["direct"][f"{hostname}:{port}"]

    class SSLScanner(BugScanner):
        def __init__(self):
            super().__init__()
            self.host_list = []

        def get_task_list(self):
            for host in self.filter_list(self.host_list):
                yield {
                    'host': host,
                }

        def log_info(self, color, status, server_name_indication):
            log(f'{color}{status:<6}  {server_name_indication}')

        def log_info_result(self, **kwargs):
            status = kwargs.get('status', '')
            server_name_indication = kwargs.get('server_name_indication', '')

            if status:
                self.log_info('', 'True', server_name_indication)
            else:
                self.log_info('', 'False', server_name_indication)

        def init(self):
            log('Stat  Host')
            log('----  ----')

        def task(self, payload):
            server_name_indication = payload['host']
            log_replace(server_name_indication)

            response = {
                'server_name_indication': server_name_indication,
                'status': False
            }

            try:
                socket_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                socket_client.settimeout(5)
                socket_client.connect((server_name_indication, 443))
                socket_client = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2).wrap_socket(
                    socket_client, server_hostname=server_name_indication, do_handshake_on_connect=True
                )
                response['status'] = True

                self.task_success(server_name_indication)

            except Exception:
                pass

            finally:
                socket_client.close()

            self.log_info_result(**response)
            if response['status']:
                self.scanned["ssl"][f"{server_name_indication}:443"] = response
            

        def get_proxy_response(self, method, hostname, port, proxy):
            if f"{hostname}:{port}" in self.scanned["proxy"]:
                return None

            response = self.request(method.upper(), hostname, port, proxies={"http": "http://" + proxy, "https": "http://" + proxy}, timeout=5, allow_redirects=False)
            if response is None:
                return None

            if response.headers.get("location") == self.ignore_redirect_location:
                log(f"{self.proxy} -> {self.method} {response.url} ({response.status_code})")
                return None

            self.scanned["proxy"][f"{hostname}:{port}"] = {
                "proxy": self.proxy,
                "method": self.method,
                "url": response.url,
                "status_code": response.status_code,
                "headers": response.headers,
            }
            return self.scanned["proxy"][f"{hostname}:{port}"]

        def print_result(self, host, hostname, port=None, status_code=None, server=None, sni=None, color=""):
            if ((server == "AkamaiGHost" and status_code != 400) or
                    (server == "Varnish" and status_code != 500) or
                    (server == "AkamainetStorage" and status_code != 400) or
                    (server == "Cloudflare" and status_code != 400) or
                    (server == "Cloudfront" and status_code != 400)):
                 
                color = 'G2'  # Assuming G2 is some special char

            host = f"{host:<15}"
            hostname = f"  {hostname}"
            sni = f"  {sni:<4}" if sni is not None else ""
            server = f"  {server:<20}" if server is not None else ""
            status_code = f"  {status_code:<4}" if status_code is not None else ""

            log(f"{host}{status_code}{server}{sni}{hostname}")

        def print_result_proxy(self, response):
            if response is None:
                return

            data = []
            data.append(f"{response['proxy']} -> {response['method']} {response['url']} ({response['status_code']})\n")
            for key, val in response['headers'].items():
                data.append(f"|   {key}: {val}")
            data.append("|\n\n")

            log("\n".join(data))

        def is_valid_hostname(self, hostname):
            if len(hostname) > 255:
                return False
            if hostname[-1] == ".":
                hostname = hostname[:-1]
            allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
            return all(allowed.match(x) for x in hostname.split("."))

        def get_sni_response(self, hostname, deep):
            if f"{hostname}:443" in self.scanned["ssl"]:
                return None

            try:
                socket_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                socket_client.settimeout(5)
                socket_client.connect((hostname, 443))
                context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
                with context.wrap_socket(socket_client, server_hostname=hostname) as ssock:
                    ssock.do_handshake()
                    response = {
                        "server_name_indication": hostname,
                        "status": True,
                    }
                    self.scanned["ssl"][f"{hostname}:443"] = response
                    return response
            except (socket.timeout, ssl.SSLError, socket.error):
                return {
                    "server_name_indication": hostname,
                    "status": False,
                }
            finally:
                socket_client.close()

        def scan(self):
            while True:
                hostname = self.queue_hostname.get()
                if not self.is_valid_hostname(hostname):
                    log(f"Invalid hostname: {hostname}")
                    self.queue_hostname.task_done()
                    continue

                for host, resolved_hostname in self.resolve(hostname):
                    if self.mode == "direct":
                        response = self.get_direct_response(self.method, resolved_hostname, self.port)
                        if response is None:
                            continue
                        self.print_result(host, resolved_hostname, port=self.port, status_code=response["status_code"], server=response["server"])

                    elif self.mode == "ssl":
                        response = self.get_sni_response(resolved_hostname, self.deep)
                        self.print_result(host, response["server_name_indication"], sni="True" if response["status"] else "False")
                        if response["status"]:
                            self.scanned["ssl"][f"{resolved_hostname}:443"] = response


                        if response["status"] and self.output is not None:
                            with open(self.output, 'a', encoding='utf-8') as f:
                                f.write(f"{host},{response['server_name_indication']},True\n")

                    elif self.mode == "proxy":
                        response = self.get_proxy_response(self.method, resolved_hostname, self.port, self.proxy)
                        self.print_result_proxy(response)

                self.queue_hostname.task_done()

        def start(self, hostnames):
            try:
                if self.mode == "direct":
                    self.print_result("host", "hostname", status_code="code", server="server")
                    self.print_result("----", "--------", status_code="----", server="------")
                elif self.mode == "ssl":
                    self.print_result("host", "hostname", sni="sni")
                    self.print_result("----", "--------", sni="---")

                self.queue_hostname = queue.Queue()
                for hostname in hostnames:
                    self.queue_hostname.put(hostname)

                for _ in range(min(self.threads, self.queue_hostname.qsize())):
                    thread = threading.Thread(target=self.scan)
                    thread.daemon = True
                    thread.start()

                self.queue_hostname.join()

                if self.output is not None:
                    with open(f"{self.output}", 'a', encoding='utf-8') as f:
                        for key, value in self.scanned.items():
                            f.write(f"{key}:\n")
                            for sub_key, sub_value in value.items():
                                if sub_value.get("server"):  # Check if server field is not empty
                                    f.write(f"  {sub_key}: {sub_value}\n")

                    log(f"Output saved to {self.output}")
            except KeyboardInterrupt:
                log("Keyboard interrupt received. Exiting...")

    def dr_access_main():
        bugscanner = SSLScanner()
        bugscanner.mode = input("Enter the mode (direct, ssl,) (default: direct): ") or "direct"
        bugscanner.method = input("Enter, GET, HEAD, OPTIONS (default: HEAD): ") or "HEAD"
        bugscanner.deep = int(input("Enter the target Depth (default: 5): ") or 5)
        bugscanner.ignore_redirect_location = ""
        bugscanner.port = int(input("Enter the target port (default: 80): ") or 80)
        filename = input("Enter file name or domains or ip: ")
        if not filename.endswith('.txt'):
            filename += '.txt'
        bugscanner.mode = "ssl" if bugscanner.mode == "ssl" else "direct"
        bugscanner.method = "HEAD" if bugscanner.method == "HEAD" else "GET"
        bugscanner.deep = 5 if bugscanner.deep == 5 else bugscanner.deep
        bugscanner.ignore_redirect_location = ""
        bugscanner.port = 80 if bugscanner.port == 80 else bugscanner.port

        bugscanner.proxy = None
        bugscanner.threads = int(input("Enter the Number of Threads (default: 8): ") or 8)
        bugscanner.output = input("Enter output file name (optional): ")
        if bugscanner.output and not bugscanner.output.endswith('.txt'):
            bugscanner.output += '.txt'


        with open(filename) as file:
            bugscanner.start(file.read().splitlines())

    dr_access_main()

#===HOST CHECKER===# 
def host_checker():
        
    generate_ascii_banner("HOST", "CHECKER")

    class bcolors:
        OKPURPLE = '\033[95m'
        OKCYAN = '\033[96m'
        OKPINK = '\033[94m'
        OKlime = '\033[92m'
        ORANGE = '\033[91m\033[93m'
        FAIL = '\033[91m'
        ENDC = '\033[0m'
        UNDERLINE = '\033[4m'
        MAGENTA = '\033[35m'
        OKBLUE = '\033[94m'
        blue2 = '\033[96m'
        brown = '\033[33m'
        peach = '\033[95m'

    def get_ip_addresses(url):
        try:
            result = socket.getaddrinfo(url, None)
            ipv4_addresses = set()
            ipv6_addresses = set()

            for entry in result:
                ip = entry[4][0]
                if ':' in ip:
                    ipv6_addresses.add(ip)
                else:
                    ipv4_addresses.add(ip)

            return list(ipv4_addresses), list(ipv6_addresses)
        except socket.gaierror:
            return [], []

    def check_status(url, filename=None, not_found_filename=None):
        try:
            if not url.startswith('http://') and not url.startswith('https://'):
                url = 'http://' + url

            headers = {
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
            }

            # Send GET request for HTTP
            url_http = url
            r_http = requests.get(url_http, headers=headers, timeout=5)
            status_http = r_http.status_code
            server_http = r_http.headers.get('server', 'server information not found')
            connection_http = r_http.headers.get('connection', '')

            # Send GET request for HTTPS
            url_https = url_http.replace('http://', 'https://')
            r_https = requests.get(url_https, headers=headers, timeout=5)
            status_https = r_https.status_code
            server_https = r_https.headers.get('server', 'server information not found')
            connection_https = r_https.headers.get('connection', '').lower()

            # Resolve IP addresses for both HTTP and HTTPS URLs
            ipv4_addresses_http, ipv6_addresses_http = get_ip_addresses(url_http.replace('http://', ''))
            ipv4_addresses_https, ipv6_addresses_https = get_ip_addresses(url_https.replace('https://', ''))

            # Debug output for IP addresses and URLs
            print(f'{bcolors.ORANGE}{url_http}, HTTP IPs: {ipv4_addresses_http}, {ipv6_addresses_http}{bcolors.ENDC}')
            print(f'{bcolors.ORANGE}{url_https}, HTTPS IPs: {ipv4_addresses_https}, {ipv6_addresses_https}{bcolors.ENDC}')

            if status_http == 200:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [OK] 200: port 80: {bcolors.OKCYAN} Keep-Alive: active{bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [OK] 200: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 301:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Moved Permanently] 301: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Moved Permanently] 301: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 302:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Temporary redirect] 302: port 80 {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Temporary redirect] 302: port 80 {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 409:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Conflict] 409: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Conflict] 409: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 403:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Forbidden] 403: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Forbidden] 403: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 404:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Not Found] 404: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Not Found] 404: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 401:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Unauthorized Error] 401: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Unauthorized Error] 401: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 206:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Partial Content] 206: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Partial Content] 206: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 500:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Internal Server Error] 500: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Internal Server Error] 500: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_http == 400:
                if connection_http and 'keep-alive' in connection_http.lower():
                    print(f'{bcolors.OKlime} [Bad Request] 400: port 80: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Bad Request] 400: port 80: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')

            # Print status for HTTPS
            if status_https == 200:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [OK] 200: port 443: {bcolors.OKCYAN} Keep-Alive: active{bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [OK] 200: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 301:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Moved Permanently] 301: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Moved Permanently] 301: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 302:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Temporary redirect] 302: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Temporary redirect] 302: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 409:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Conflict] 409: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Conflict] 409: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 403:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Forbidden] 403: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Forbidden] 403: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 404:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Not Found] 404: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Not Found] 404: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 401:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Unauthorized Error] 401: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Unauthorized Error] 401: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 206:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Partial Content] 206: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Partial Content] 206: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 500:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Internal Server Error] 500: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Internal Server Error] 500: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')
            elif status_https == 400:
                if connection_https and 'keep-alive' in connection_https.lower():
                    print(f'{bcolors.OKlime} [Bad Request] 400: port 443: {bcolors.OKCYAN} Keep-Alive: active {bcolors.ENDC}')
                else:
                    print(f'{bcolors.OKlime} [Bad Request] 400: port 443: {bcolors.FAIL} Keep-Alive: inactive{bcolors.ENDC}')

            # Add color coding based on server information
            if 'cloudflare' in server_http.lower() or 'cloudflare' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.ORANGE} {url} {server_http if "cloudflare" in server_http.lower() else server_https}{bcolors.ENDC} {bcolors.UNDERLINE}check host {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.ORANGE} {url_https} {server_https if "cloudflare" in server_https.lower() else server_http}{bcolors.ENDC} {bcolors.UNDERLINE}check host {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'cloudfront' in server_http.lower() or 'cloudfront' in server_https.lower():
                print(f'{bcolors.blue2} {url} {server_http if "cloudfront" in server_http.lower() else server_https} {bcolors.UNDERLINE}check host {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.blue2} {url_https} {server_https if "cloudfront" in server_https.lower() else server_http} {bcolors.UNDERLINE}check host {status_https} status : {connection_https} found\x1b[0m{bcolors.ENDC}')
            elif 'sffe' in server_http.lower() or 'sffe' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.ORANGE} {url} {server_http if "sffe" in server_http.lower() else server_https}{bcolors.ENDC} {bcolors.UNDERLINE}check host {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.ORANGE} {url_https} {server_https if "sffe" in server_https.lower() else server_http}{bcolors.ENDC} {bcolors.UNDERLINE}check host {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'apple' in server_http.lower() or 'apple' in server_https.lower():
                print(f'{bcolors.blue2} {url} {server_http if "apple" in server_http.lower() else server_https}{bcolors.UNDERLINE}check host {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.blue2} {url_https} {server_https if "apple" in server_https.lower() else server_http} {bcolors.UNDERLINE}check host {status_https} status : {connection_https} found\x1b[0m{bcolors.ENDC}')
            elif 'akamaighost' in server_http.lower() or 'akamaighost' in server_https.lower():
                print(f'{bcolors.OKPURPLE} {url} {server_http if "akamaighost" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKPURPLE} {url_https} {server_https if "akamaighost" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'Apple' in server_http.lower() or 'Apple' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKPINK} {url} {server_http if "Apple" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKPINK} {url_https} {server_https if "Apple" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'microsoft-IIS/10.0' in server_http.lower() or 'microsoft-IIS/10.0' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "microsoft-IIS/10.0" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "microsoft-IIS/10.0" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'fastly' in server_http.lower() or 'fastly' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.brown} {url} {server_http if "fastly" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.brown} {url_https} {server_https if "fastly" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'varnish' in server_http.lower() or 'varnish' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.peach} {url} {server_http if "varnish" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.peach} {url_https} {server_https if "varnish" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'gws' in server_http.lower() or 'gws' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.ORANGE} {url} {server_http if "gws" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.ORANGE} {url_https} {server_https if "gws" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'gse' in server_http.lower() or 'gse' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKPURPLE} {url} {server_http if "gse" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKPURPLE} {url_https} {server_https if "gse" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'esf' in server_http.lower() or 'esf' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "esf" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "esf" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'Google frontend' in server_http.lower() or 'Google frontend' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKlime} {url} {server_http if "Google frontend" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKlime} {url_https} {server_https if "Google frontend" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'ClientMapServer' in server_http.lower() or 'ClientMapServer' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKPINK} {url} {server_http if "ClientMapServer" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKPINK} {url_https} {server_https if "ClientMapServer" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'UploadServer' in server_http.lower() or 'UploadServer' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.peach} {url} {server_http if "UploadServer" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.peach} {url_https} {server_https if "UploadServer" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'OFE' in server_http.lower() or 'OFE' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.peach} {url} {server_http if "OFE" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.peach} {url_https} {server_https if "OFE" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'tengine' in server_http.lower() or 'tengine' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "tengine" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "tengine" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'TornadoServer' in server_http.lower() or 'TornadoServer' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.peach} {url} {server_http if "TornadoServer" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.peach} {url_https} {server_https if "TornadoServer" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'awselb/2.0' in server_http.lower() or 'awselb/2.0' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.peach} {url} {server_http if "awselb/2.0" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.peach} {url_https} {server_https if "awselb/2.0" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'nginx' in server_http.lower() or 'nginx' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "nginx" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "nginx" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'openresty' in server_http.lower() or 'openresty' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "openresty" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "openresty" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'Apache' in server_http.lower() or 'Apache' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "Apache" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "Apache" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'istio-envoy' in server_http.lower() or 'istio-envoy' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "istio-envoy" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "istio-envoy" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'Caddy' in server_http.lower() or 'Caddy' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "Caddy" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "Caddy" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')
            elif 'lighttpd' in server_http.lower() or 'lighttpd' in server_https.lower() and connection_https.lower() or connection_http.lower():
                print(f'{bcolors.OKCYAN} {url} {server_http if "lighttpd" in server_http.lower() else server_https} {bcolors.UNDERLINE}check {status_http} status found : {connection_http}\x1b[0m{bcolors.ENDC}')
                print(f'{bcolors.OKCYAN} {url_https} {server_https if "lighttpd" in server_https.lower() else server_http} {bcolors.UNDERLINE}check {status_https} status found : {connection_https}\x1b[0m{bcolors.ENDC}')

            if filename:
                with open(filename, 'a') as f:
                    f.write(f'{url_http} : HTTP({status_http}), Server: {server_http}, Connection: {connection_http}, IPs: IPv4: {", ".join(ipv4_addresses_http)}, IPv6: {", ".join(ipv6_addresses_http)}\n')
                    f.write(f'{url_https} : HTTPS({status_https}), Server: {server_https}, Connection: {connection_https}, IPs: IPv4: {", ".join(ipv4_addresses_https)}, IPv6: {", ".join(ipv6_addresses_https)}\n')

        except requests.ConnectionError:
            print(f'{bcolors.FAIL}{url} failed to connect{bcolors.ENDC}')

        except requests.Timeout:
            print(f'{url} timeout error')
            if not_found_filename:
                with open(not_found_filename, 'a') as f:
                    f.write(f'{url} timed out\n')
        except requests.RequestException as e:
            print(f'{url} general error: {str(e)}')

    while True:
        file_name = input("Enter the name of the file to scan: ")
        try:
            with open(file_name) as f:
                lines = f.readlines()
            break
        except FileNotFoundError:
            print("File not found. Please enter a valid file name.")

    while True:
        save_output = input("Save output to file? (y/n) ")
        if save_output.lower() == 'y':
            filename = input("Enter the name of the output file: ")
            break
        elif save_output.lower() == 'n':
            filename = None
            break
        else:
            print("Invalid input. Please enter 'y' or 'n'.")

    while True:
        save_not_found = input("Save time out domains? (y/n) ")
        if save_not_found.lower() == 'y':
            not_found_filename = input("Enter the name of the file name: ")
            break
        elif save_not_found.lower() == 'n':
            not_found_filename = None
            break
        else:
            print("Invalid input. Please enter 'y' or 'n'.")

    while True:
        try:
            num_threads = int(input("Enter the number of threads (1-200): "))
            if num_threads < 1 or num_threads > 200:
                raise ValueError
            break
        except ValueError:
            print("Invalid input. Please enter a number between 1 and 200.")

    threads = []

    for line in tqdm(lines):
        url = line.strip()
        t = threading.Thread(target=check_status, args=(url, filename, not_found_filename))
        threads.append(t)
        t.start()
        if len(threads) >= num_threads:
            for t in threads:
                t.join()
            threads = []

    for t in threads:
        t.join()

    if not_found_filename:
        print(f'Time Out Domains Saved In {not_found_filename}')

    time.sleep(1)

    print("""
    ===============================
                Menu                
    ===============================
    1. Return to main menu
    2. View output file
    """)

    while True:
        choice = input("Enter your choice (1 or 2): ")
        if choice == '1':
            randomshit("Returning to BUGHUNTERS PRO...")
            break
        elif choice == '2':
            if filename and os.path.exists(filename):
                with open(filename, 'r') as f:
                    print(f.read())
                time.sleep(2)
                randomshit("Returning to BUGHUNTERS PRO...")
            else:
                print("Output file not found or not saved.")
            break

#===HOST CHECKER V2===#      
def hostchecker_v2():

    generate_ascii_banner("HOST", "CHECKER V2")

    class bcolors:
        HEADER = '\033[95m'
        OKBLUE = '\033[94m'
        OKGREEN = '\033[92m'
        WARNING = '\033[93m'
        FAIL = '\033[91m'
        ENDC = '\033[0m'

    # Function to get color based on HTTP status code
    def get_color_for_status(status):
        if isinstance(status, int):
            if status == 200:
                return bcolors.OKGREEN
            elif 400 <= status < 500:
                return bcolors.WARNING
            elif status >= 500:
                return bcolors.FAIL
            else:
                return bcolors.OKBLUE
        return bcolors.FAIL

    # Function to resolve domain names and CIDRs to IPs
    def resolve_ips(url):
        try:
            if '/' in url:  # CIDR range
                return [str(ip) for ip in ipaddress.IPv4Network(url, strict=False).hosts()]
            return [socket.gethostbyname(url)]
        except Exception as e:
            print(f"Error resolving IPs for {url}: {e}")
            return []

    # Function to extract certificate information
    def get_certificate_info(domain):
        try:
            context = ssl.create_default_context()
            with socket.create_connection((domain, 443), timeout=5) as sock:
                with context.wrap_socket(sock, server_hostname=domain) as ssock:
                    cert = ssock.getpeercert()
            issuer = dict(x[0] for x in cert['issuer'])
            subject = dict(x[0] for x in cert['subject'])
            expiry = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
            days_left = (expiry - datetime.utcnow()).days
            return {
                "issuer": issuer.get("organizationName", "Unknown"),
                "subject": subject.get("commonName", "Unknown"),
                "expiry": expiry.strftime('%Y-%m-%d'),
                "days_left": days_left
            }
        except Exception as e:
            return {"error": f"Could not retrieve certificate: {e}"}

    # Function to check HTTP/HTTPS status and details
    def check_status(url, output_file=None, not_found_file=None):
        try:
            url_http = f'http://{url}'
            url_https = f'https://{url}'
            ips = resolve_ips(url)

            # Check HTTP
            try:
                response_http = requests.get(url_http, timeout=5)
                if response_http.status_code:
                    print(f"{get_color_for_status(response_http.status_code)}{url_http} : HTTP({response_http.status_code}), Server: {response_http.headers.get('Server', 'None')}, Connection: {response_http.headers.get('Connection', 'None')}, IPs: {', '.join(ips)}{bcolors.ENDC}")
                    if output_file:
                        with open(output_file, 'a') as f:
                            f.write(f"{url_http} : HTTP({response_http.status_code}), Server: {response_http.headers.get('Server', 'None')}, Connection: {response_http.headers.get('Connection', 'None')}, IPs: {', '.join(ips)}\n")
            except Exception as e:
                if not_found_file:
                    with open(not_found_file, 'a') as nf:
                        nf.write(f"{url_http} failed: {e}\n")

            # Check HTTPS and get certificate info
            try:
                response_https = requests.get(url_https, timeout=5)
                cert_info = get_certificate_info(url)
                if response_https.status_code:
                    print(f"{get_color_for_status(response_https.status_code)}{url_https} : HTTPS({response_https.status_code}), Server: {response_https.headers.get('Server', 'None')}, Connection: {response_https.headers.get('Connection', 'None')}, IPs: {', '.join(ips)}, Cert: {cert_info}{bcolors.ENDC}")
                    if output_file:
                        with open(output_file, 'a') as f:
                            f.write(f"{url_https} : HTTPS({response_https.status_code}), Server: {response_https.headers.get('Server', 'None')}, Connection: {response_https.headers.get('Connection', 'None')}, IPs: {', '.join(ips)}, Cert: {cert_info}\n")
            except Exception as e:
                if not_found_file:
                    with open(not_found_file, 'a') as nf:
                        nf.write(f"{url_https} failed: {e}\n")

            # Fall-Back to IP Connection
            if not ips:
                print(f"{bcolors.FAIL}Could not resolve IP for {url}. Skipping IP fallback.{bcolors.ENDC}")
            else:
                for ip in ips:
                    try:
                        response_fallback = requests.get(f"http://{ip}", timeout=5)
                        print(f"{bcolors.OKBLUE}IP {ip}: HTTP({response_fallback.status_code}){bcolors.ENDC}")
                    except Exception:
                        print(f"{bcolors.WARNING}check failed for IP {ip}{bcolors.ENDC}")

        except Exception as e:
            print(f"Error processing {url}: {e}")

    # Detect input type
    def detect_input_type(user_input):
        if user_input.endswith('.txt'):
            return 'File'
        elif '/' in user_input:
            try:
                ipaddress.IPv4Network(user_input, strict=False)
                return 'CIDR'
            except ValueError:
                return 'Invalid'
        elif re.match(r'^\d{1,3}(\.\d{1,3}){3}$', user_input):
            return 'IP'
        elif re.match(r'^[a-zA-Z0-9.-]+$', user_input):
            return 'URL'
        return 'Invalid'

    # Process file input
    def handle_file_input(file_name):
        try:
            with open(file_name, 'r') as file:
                return [line.strip() for line in file if line.strip()]
        except FileNotFoundError:
            print(f"File not found: {file_name}")
            return []

    def hostchecker_main():
        user_input = input("Enter URL, CIDR, IP, or .txt file: ").strip()
        input_type = detect_input_type(user_input)

        # Prompt for file outputs for all input types
        output_file = input("Enter output file name (or leave blank to skip saving): ").strip()
        not_found_file = input("Enter timeout file name (or leave blank to skip saving): ").strip()

        if input_type == 'CIDR':
            ips = resolve_ips(user_input)
            for ip in ips:
                check_status(ip, output_file, not_found_file)
        elif input_type in ['IP', 'URL']:
            check_status(user_input, output_file, not_found_file)
        elif input_type == 'File':
            lines = handle_file_input(user_input)
            if not lines:
                print("File is empty or invalid.")
                return

            num_threads = int(input("Enter number of threads (1-200): "))

            threads = []
            for line in tqdm(lines):
                t = threading.Thread(target=check_status, args=(line, output_file, not_found_file))
                threads.append(t)
                t.start()
                if len(threads) >= num_threads:
                    for thread in threads:
                        thread.join()
                    threads = []
            for thread in threads:
                thread.join()
        else:
            print("Invalid input.")

    hostchecker_main()

#######BUCKET########
def bucket():
    generate_ascii_banner("BUCKET", "")
    import ipaddress
    import os
    import subprocess
    import threading
    import requests
    from concurrent.futures import ThreadPoolExecutor, as_completed
    from tqdm import tqdm
    from colorama import Fore, Style, init

    # Initialize colorama
    init()

    lock = threading.Lock()
    saved_domains = set()  # Using set to avoid duplicates
    cdn_keywords = ['cloudfront.net', 'cloudflare', 'imperva', 'gws']
    output_file = "cdn_domains.txt"

    def color_status_code(status_code):
        if not status_code:
            return ""
        status_code = str(status_code)
        if status_code.startswith('2'):
            return f"{Fore.GREEN}{status_code}{Style.RESET_ALL}"
        elif status_code.startswith('3'):
            return f"{Fore.YELLOW}{status_code}{Style.RESET_ALL}"
        elif status_code.startswith('4'):
            return f"{Fore.BLUE}{status_code}{Style.RESET_ALL}"
        elif status_code.startswith('5'):
            return f"{Fore.RED}{status_code}{Style.RESET_ALL}"
        else:
            return status_code

    def color_server(server):
        if not server:
            return ""
        server = server.lower()
        if 'cloudfront' in server:
            return f"{Fore.CYAN}{server}{Style.RESET_ALL}"
        elif 'cloudflare' in server:
            return f"{Fore.MAGENTA}{server}{Style.RESET_ALL}"
        elif 'apache' in server:
            return f"{Fore.YELLOW}{server}{Style.RESET_ALL}"
        elif 'nginx' in server:
            return f"{Fore.GREEN}{server}{Style.RESET_ALL}"
        elif 'microsoft' in server or 'iis' in server:
            return f"{Fore.BLUE}{server}{Style.RESET_ALL}"
        else:
            return f"{Fore.WHITE}{server}{Style.RESET_ALL}"

    def is_file(path):
        return os.path.isfile(path)

    def is_cidr(input_str):
        try:
            ipaddress.ip_network(input_str)
            return True
        except ValueError:
            return False

    def expand_cidr(cidr):
        try:
            return [str(ip) for ip in ipaddress.IPv4Network(cidr, strict=False).hosts()]
        except ValueError:
            print(f"[!] Invalid CIDR: {cidr}")
            return []

    def nslookup_host(hostname):
        try:
            result = subprocess.check_output(['nslookup', hostname], stderr=subprocess.DEVNULL).decode()
            ip_list = []
            alias_list = []

            for line in result.splitlines():
                line = line.strip()

                if line.lower().startswith("name:"):
                    cname = line.split("Name:")[-1].strip().strip('.')
                    if cname and cname not in alias_list:
                        alias_list.append(cname)

                elif line.lower().startswith("aliases:"):
                    alias = line.split("Aliases:")[-1].strip().strip('.')
                    if alias and alias not in alias_list:
                        alias_list.append(alias)

                elif "name =" in line:
                    alias = line.split("name =")[-1].strip().strip('.')
                    if alias and alias not in alias_list:
                        alias_list.append(alias)

                elif line.lower().startswith("address:") and ":" not in line:
                    ip = line.split("Address:")[-1].strip()
                    if ip and ip not in ip_list:
                        ip_list.append(ip)

            return ip_list, alias_list
        except Exception as e:
            return [], []

    def check_http_status(url):
        try:
            # Try with keep-alive first
            with requests.Session() as session:
                session.headers.update({'Connection': 'keep-alive'})
                response = session.get(url, timeout=5, allow_redirects=True)
                server = response.headers.get('Server', '')
                return response.status_code, True, server
        except requests.exceptions.SSLError:
            try:
                # Try without SSL verification
                with requests.Session() as session:
                    session.headers.update({'Connection': 'keep-alive'})
                    response = session.get(url, timeout=5, verify=False, allow_redirects=True)
                    server = response.headers.get('Server', '')
                    return response.status_code, True, server
            except:
                try:
                    # Fallback to single request
                    response = requests.get(url, timeout=5, allow_redirects=True)
                    server = response.headers.get('Server', '')
                    return response.status_code, False, server
                except:
                    return None, False, ''
        except:
            try:
                # Fallback to single request
                response = requests.get(url, timeout=5, allow_redirects=True)
                server = response.headers.get('Server', '')
                return response.status_code, False, server
            except:
                return None, False, ''

    def save_to_file(filename, data):
        with lock:
            # Remove ALL color codes using regex
            import re
            clean_data = re.sub(r'\x1b\[[0-9;]*m', '', data)
            
            if clean_data not in saved_domains:
                saved_domains.add(clean_data)
                with open(filename, 'a', encoding='utf-8') as f:
                    f.write(clean_data + '\n')
                
                # Print colored version to console
                print(data)

    def process_target(target):
        # Add http:// if not present
        if not target.startswith(('http://', 'https://')):
            target = f"http://{target}"
        
        # Get status code, keep-alive status, and server header
        status_code, keepalive, server = check_http_status(target)
        
        ip_list, aliases = nslookup_host(target.replace('http://', '').replace('https://', '').split('/')[0])
        
        # Prepare display components
        status_display = ""
        if status_code:
            colored_status = color_status_code(status_code)
            # More visible keep-alive indicator
            keepalive_status = f"{Fore.CYAN}[keep-alive]{Style.RESET_ALL}" if keepalive else f"{Fore.MAGENTA}[no-keep-alive]{Style.RESET_ALL}"
            server_display = f" [Server: {color_server(server)}]" if server else ""
            status_display = f" {keepalive_status} [Status: {colored_status}]{server_display}"
        
        for alias in aliases:
            for cdn in cdn_keywords:
                if cdn in alias.lower():
                    save_to_file(output_file, f"{target} -> {alias}{status_display}")
                    return
        
        # If no CDN found but we have a status code, save it with status only
        if status_code:
            save_to_file(output_file, f"{target} -> {target}{status_display}")
            
    def bucket_main():
        user_input = input("Enter a domain, IP, CIDR, or path to a file: ").strip()
        targets = []

        if is_file(user_input):
            with open(user_input, 'r', encoding='utf-8') as f:
                targets = [line.strip() for line in f if line.strip()]
        elif is_cidr(user_input):
            targets = expand_cidr(user_input)
        else:
            targets = [user_input]

        print(f"[*] Checking {len(targets)} targets using 15 threads...\n")

        with ThreadPoolExecutor(max_workers=75) as executor:
            futures = [executor.submit(process_target, target) for target in targets]
            for _ in tqdm(as_completed(futures), total=len(futures), desc="Processing"):
                pass

        if saved_domains:
            print(f"\n[✓] Done. Results saved to: {output_file}")
        else:
            print(f"\n[{Fore.RED}×{Style.RESET_ALL}] No results were found or saved.")

    if __name__ == "__main__":
        # Clear output file at start
        open(output_file, 'w').close()
        bucket_main()

#===FREE PROXIES===#         
def free_proxies():

    generate_ascii_banner("FREE", "PROXY")

    def get_proxies_from_source(source_url):
        try:
            response = requests.get(source_url, timeout=3)
            response.raise_for_status()
            return response.text
        except requests.exceptions.RequestException as e:
            print("Error fetching proxy:")
            return None

    def extract_proxies(data):
        # Use regular expression to extract proxies from the response
        proxies = re.findall(r'\d+\.\d+\.\d+\.\d+:\d+', data)
        return proxies

    def scrape_proxies(sources):
        all_proxies = []

        for source in tqdm(sources, desc="Scraping Proxies", unit="source"):
            source_data = get_proxies_from_source(source)

            if source_data:
                proxies = extract_proxies(source_data)
                all_proxies.extend(proxies)

        return all_proxies

    def check_proxy(proxy):
        try:
            response = requests.get("https://www.twitter.com", proxies={"http": f"http://{proxy}", "https": f"http://{proxy}"}, timeout=5)
            response.raise_for_status()
            return proxy
        except requests.exceptions.RequestException:
            return None

    def check_proxies(proxies):
        working_proxies = []

        with ThreadPoolExecutor(80) as executor:
            results = list(tqdm(executor.map(check_proxy, proxies), total=len(proxies), desc="Checking Proxies", unit="proxy"))

        working_proxies = [proxy for proxy in results if proxy is not None]

        return working_proxies

    def ask_to_check_proxies(proxies):

        user_input = input(f"Do you want to check the proxies for validity? (yes/no): ").strip().lower()
        if user_input in ['yes', 'y']:
            return check_proxies(proxies)
        elif user_input in ['no', 'n']:
            return proxies
        else:
            print("Invalid input. Assuming 'no'.")
            return proxies

    def save_to_file(proxies, filename):
        with open(filename, 'w') as file:
            for proxy in proxies:
                file.write(f"{proxy}\n")

    def load_proxies_from_file(filename):
        try:
            with open(filename, 'r') as file:
                return [line.strip() for line in file if line.strip()]
        except FileNotFoundError:
            print(f"File {filename} not found")
            return []

    def free_proxies_main():
        http_sources = [
            "https://api.proxyscrape.com/v2/?request=getproxies&protocol=http",
            "https://openproxylist.xyz/http.txt",
            "https://proxyspace.pro/http.txt",
            "https://proxyspace.pro/https.txt",
            "http://free-proxy-list.net",
            "http://us-proxy.org",
            "https://www.proxy-list.download/api/v1/?type=http",
            "https://www.proxy-list.download/api/v1/?type=https",
            "https://proxylist.geonode.com/api/proxy-list?limit=500&page=1&sort_by=lastChecked&sort_type=desc"
            # Add other HTTP sources from your configuration here
            # ...
        ]

        socks4_sources = [
            "https://www.vpnside.com/proxy/list/"
            #"https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/socks4.txt",
            "https://api.proxyscrape.com/v2/?request=getproxies&protocol=socks4",
            "https://www.proxy-list.download/api/v1/get?type=socks4&anon=elite"
            "https://openproxylist.xyz/socks4.txt",
            "https://proxyspace.pro/socks4.txt",
            "https://www.proxy-list.download/api/v1/get/?type=socks4"
            
            # Add other SOCKS4 sources from your configuration here
            # ...
        ]

        socks5_sources = [
            "https://api.proxyscrape.com/v2/?request=getproxies&protocol=socks5",
            "https://www.proxy-list.download/api/v1/?type=socks5",
            "https://www.proxy-list.download/api/v1/get?type=socks5&anon=elite"
            "https://openproxylist.xyz/socks5.txt",
            "https://proxyspace.pro/socks5.txt",
            # Add other SOCKS5 sources from your configuration here
            # ...
        ]

        while True:
            print("\nChoose an option:")
            print("1. Scrape HTTP Proxies")
            print("2. Scrape SOCKS4 Proxies") 
            print("3. Scrape SOCKS5 Proxies")
            #print("4. Check Existing Proxies")
            print("4. Exit")

            try:
                user_choice = int(input("Enter your choice (1-5): "))
            except ValueError:
                print("Invalid input. Please enter a number.")
                continue

            if user_choice in [1, 2, 3]:
                sources = {
                    1: (http_sources, 'http.txt', 'HTTP'),
                    2: (socks4_sources, 'socks4.txt', 'SOCKS4'),
                    3: (socks5_sources, 'socks5.txt', 'SOCKS5')
                }
                source_list, filename, proxy_type = sources[user_choice]
                proxies = scrape_proxies(source_list)
                save_to_file(proxies, filename)
                print(f"{proxy_type} Proxies saved to {filename}. Total proxies: {len(proxies)}")
                working_proxies = ask_to_check_proxies(proxies)
                save_to_file(working_proxies, f'working_{filename}')
                print(f"Working {proxy_type} Proxies saved to working_{filename}. Total working: {len(working_proxies)}")
                time.sleep(2)
                clear_screen()

            #elif user_choice == 4:
            #    filename = input("Enter the filename to check proxies from: ")
            #    proxies = load_proxies_from_file(filename)
            #    working_proxies = ask_to_check_proxies(proxies)
            #    save_to_file(working_proxies, f'working_{filename}')
            #    print(f"Working Proxies saved to working_{filename}. Total working: {len(working_proxies)}")
            #    time.sleep(2)
            #    clear_screen()
            
            elif user_choice == 4:
                clear_screen()
                break
            else:
                print("Invalid choice. Please enter a number between 1-4.")

    free_proxies_main()

#===TLS CHECKER===#
def tls_checker():
    
    generate_ascii_banner("TLS", "CHECKER")

    IGNORED_SSL_ERRORS = {'WRONG_VERSION_NUMBER'}

    def print_color(message, color=PINK, style=ENDC):
        print(f"{color}{message}{ENDC}")

    def save_to_file(result, file_name):
        try:
            with open(file_name, 'a') as file:
                file.write(result)
        except Exception as e:
            print_color(FAIL + f"Error saving result to '{file_name}': {e}", ENDC)

    def check_tls_details(host, port, file_name, pbar):
        global progress_counter
        ip_address = None  # Initialize ip_address here

        try:
            ip_address = socket.gethostbyname(host)
            context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)

            with socket.create_connection((host, port), timeout=5) as sock:
                with context.wrap_socket(sock, server_hostname=host) as ssock:
                    result = f"TLS details for {host} ({ip_address}):{port}\n" \
                            f"TLS Version: {ssock.version()}\nCipher Suite: {ssock.cipher()}\n"
            print(result)
            save_to_file(result, file_name)
        except ssl.SSLError as e:
            error_message = str(e)
            error_code = getattr(e, 'reason', None)
            if error_code and error_code in IGNORED_SSL_ERRORS:
                result = f"Ignoring SSL error for {host} ({ip_address}):{port}: {error_message}\n"
            else:
                result = f"Error for {host} ({ip_address}):{port}: {error_message}\n"
            print_color(result, FAIL)
        except socket.timeout as e:
            result = f"Timeout error for {host} ({ip_address}):{port}: {str(e)}\n"
            print_color(result, FAIL)
        except Exception as e:
            result = f"Error for {host} ({ip_address}):{port}: {str(e)}\n"
            print_color(result, FAIL)

        progress_counter += 1  # Increment the global progress counter
        pbar.update(1)  # Increment the main progress bar

    def check_tls_for_domains(domains, ports=(443, 80)):
        global total_tasks
        file_name = input("Enter the name of the file to save the TLS details (e.g., output.txt): ")
        total_tasks = len(domains) * len(ports)

        with ThreadPoolExecutor() as executor, tqdm(total=total_tasks, desc="Overall Progress") as pbar:
            futures = []
            for domain in domains:
                for port in ports:
                    futures.append(executor.submit(check_tls_details, domain, port, file_name, pbar))
            for future in futures:
                try:
                    future.result()
                except Exception as e:
                    print_color(f"Error processing task: {str(e)}", FAIL)
        executor.shutdown(wait=True)

    def tls_checker_main():
        choice = input("Do you want to input a domain manually (M) or provide a text file (T)? ").upper()

        if choice == "M":
            domain = input("Enter the domain or IP address: ")
            check_tls_for_domains([domain])
        elif choice == "T":
            file_name = input("Enter the name of the text file with domains: ")
            try:
                with open(file_name, "r") as file:
                    domains = [line.strip() for line in file]

                check_tls_for_domains(domains)
            except FileNotFoundError:
                print_color(f"Error: File '{file_name}' not found.", FAIL)
        else:
            print_color("Invalid choice. Please choose 'M' for manual input or 'T' for a text file.", FAIL)

    tls_checker_main()

#===BUGSLUTH===#
def bg_sluth():
    
    banner_lines = [ 

    ORANGE + "██████╗  ██████╗ ███████╗██╗     ███████╗██╗   ██╗████████╗██╗  ██╗" + ENDC,
    ORANGE + "██╔══██╗██╔════╝ ██╔════╝██║     ██╔════╝██║   ██║╚══██╔══╝██║  ██║" + ENDC,
    ORANGE + "██████╔╝██║  ███╗███████╗██║     █████╗  ██║   ██║   ██║   ███████║" + ENDC,
    ORANGE + "██╔══██╗██║   ██║╚════██║██║     ██╔══╝  ██║   ██║   ██║   ██╔══██║" + ENDC,
    ORANGE + "██████╔╝╚██████╔╝███████║███████╗███████╗╚██████╔╝   ██║   ██║  ██║" + ENDC,
    ORANGE + "╚═════╝  ╚═════╝ ╚══════╝╚══════╝╚══════╝ ╚═════╝    ╚═╝   ╚═╝  ╚═╝" + ENDC,
    LIME +  "Inspired by @wicky12317018" + ENDC,
    FAIL + "Re- written by @ssskingssss" + ENDC,

    FAIL + "Please use 1.(ONE) Option At A time" + ENDC,
    FAIL + "DO NOT ENTER FILE NAME THEN CDIR, USE OTION 0 FOR HELP," + ENDC,
        ]

    for line in banner_lines:
        print(line)


    class BugScanner(multithreading.MultiThreadRequest):
        threads: int

        def request_connection_error(self, *args, **kwargs):
            return 1

        def request_read_timeout(self, *args, **kwargs):
            return 1

        def request_timeout(self, *args, **kwargs):
            return 1

        def convert_host_port(self, host, port):
            return host + (f':{port}' if bool(port not in ['80', '443']) else '')

        def get_url(self, host, port, uri=None):
            port = str(port)
            protocol = 'https' if port == '443' else 'http'
            return f'{protocol}://{self.convert_host_port(host, port)}' + (f'/{uri}' if uri is not None else '')

        def init(self):
            self._threads = self.threads or self._threads

        def complete(self):
            pass

    class DirectScanner(BugScanner):
        method_list = []
        host_list = []
        port_list = []
        isp_redirects = [
            "isp.tstt.co.tt",
            "tstt.co.tt",
            "www.tstt.net.tt",
            # Africa
            "www.mtn.com",
            "www.vodacom.co.za",
            "www.orange.com", 
            "www.airtel.africa",
            "www.glo.com",
            "safaricom.co.ke",
            "www.telkom.co.za",
            # Asia
            "www.singtel.com",
            "www.airtel.in",
            "www.jio.com",
            "www.docomo.ne.jp",
            "www.kddi.com",
            "www.chinamobile.com",
            "www.telkomsel.com",
            "www.globe.com.ph",
            # Europe 
            "www.vodafone.com",
            "www.telekom.de",
            "www.orange.fr",
            "www.t-mobile.com",
            "www.telefonica.com",
            # North America
            "www.verizon.com", 
            "www.att.com",
            "www.tmobile.com",
            "www.sprint.com",
            "www.rogers.com",
            "www.telus.com",
            # South America
            "www.claro.com.br",
            "www.vivo.com.br",
            "www.movistar.com.ar",
            "www.personal.com.ar",
            # Oceania
            "www.telstra.com.au",
            "www.optus.com.au",
            "www.vodafone.com.au",
            "www.spark.co.nz"
        ]


        def log_info(self, **kwargs):
            for x in ['status_code', 'server']:
                kwargs[x] = kwargs.get(x, '')

            location = kwargs.get('location')
            if location:
                if location.startswith(f"https://{kwargs['host']}"):
                    kwargs['status_code'] = f"{kwargs['status_code']:<4}"
                else:
                    kwargs['host'] += f" -> {location}"

            messages = []
            for x in ['\033[36m{method:<6}\033[0m', '\033[35m{status_code:<4}\033[0m', '{server:<22}', '\033[94m{port:<4}\033[0m', '\033[92m{host}\033[0m']:
                messages.append(f'{x}')

            super().log('  '.join(messages).format(**kwargs))

        def get_task_list(self):
            for method in self.filter_list(self.method_list):
                for host in self.filter_list(self.host_list):
                    for port in self.filter_list(self.port_list):
                        yield {
                            'method': method.upper(),
                            'host': host,
                            'port': port,
                        }

        def init(self):
            super().init()
            self.log_info(method='Method', status_code='Code', server='Server', port='Port', host='Host')
            self.log_info(method='------', status_code='----', server='------', port='----', host='----')

        def task(self, payload):
            method = payload['method']
            host = payload['host']
            port = payload['port']

            try:
                response = self.request(method, self.get_url(host, port), retry=1, timeout=3, allow_redirects=False)
            except:
                return

            if response is not None:
                status_code = response.status_code
                server = response.headers.get('server', '')
                location = response.headers.get('location', '')

                if status_code == 302 and location in self.isp_redirects:
                    return

                if status_code and status_code != 302:
                    data = {
                        'method': method,
                        'host': host,
                        'port': port,
                        'status_code': status_code,
                        'server': server,
                        'location': location,
                    }
                    self.task_success(data)
                    self.log_info(**data)

    class PingScanner(BugScanner):

        def init(self):
            self.host_list = []
            self.method_list = []
            # Allow custom ports or use defaults
            self.port_list = []
            self.threads = 10

        async def scan(self):
            self.init_log()
            tasks = []
            for host in self.host_list:
                # Create task for each host+port combination
                for port in self.port_list:
                    tasks.append(self.scan_host_port(host, port))
            await asyncio.gather(*tasks)

        async def scan_host_port(self, host, port):
            try:
                if await self.ping(host):
                    # Try to connect to specific port
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.settimeout(1)
                    result = sock.connect_ex((host, int(port)))
                    sock.close()
                    
                    if result == 0:
                        status = '\033[36mOpen\033[0m'
                        # Get server info for open ports
                        server = await self.get_server_info(host, port)
                    else:
                        status = '\033[31mClosed\033[0m'
                        server = ''
                        
                    self.log_info(status=status, host=host, port=port, server=server)
                    self.task_success({'host': host, 'port': port, 'status': status, 'server': server})
                    
            except Exception as e:
                print(f"Error scanning {host}:{port} - {str(e)}")

        async def ping(self, host):
            process = await asyncio.create_subprocess_shell(
                f'ping -n 1 {host}',
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0

        async def get_server_info(self, host, port):
            try:
                if port == 443:
                    # For HTTPS
                    context = ssl.create_default_context()
                    context.check_hostname = False
                    context.verify_mode = ssl.CERT_NONE
                    
                    reader, writer = await asyncio.open_connection(
                        host, port, ssl=context)
                else:
                    # For HTTP and other ports
                    reader, writer = await asyncio.open_connection(
                        host, port)
                    
                writer.write(b'GET / HTTP/1.1\r\nHost: '+host.encode()+b'\r\n\r\n')
                await writer.drain()
                
                data = await reader.read(1024)
                writer.close()
                await writer.wait_closed()
                
                # Try to extract server header
                response = data.decode()
                server = ''
                for line in response.split('\n'):
                    if line.startswith('Server:'):
                        server = line.split(':', 1)[1].strip()
                        break
                return server
            except:
                return ''

        def log_info(self, **kwargs):
            status = kwargs.get('status', '')
            host = kwargs.get('host', '')
            port = kwargs.get('port', '')
            server = kwargs.get('server', '')
            message = f"{status:<4}  {host:<15} {port:<6}  {server}"
            self.logger.log(message)

        def init_log(self):
            self.log_info(status='Stat', host='Host', port='Port', server='Server')
            self.log_info(status='----', host='----', port='----', server='----')

        def start(self):
            asyncio.run(self.scan())

    class ProxyScanner(DirectScanner):
        proxy = []

        def log_replace(self, *args):
            super().log_replace(':'.join(self.proxy), *args)

        def request(self, *args, **kwargs):
            proxy = self.get_url(self.proxy[0], self.proxy[1])
            return super().request(*args, proxies={'http': proxy, 'https': proxy}, **kwargs)

    class SSLScanner(BugScanner):
        host_list = []

        def get_task_list(self):
            for host in self.filter_list(self.host_list):
                yield {
                    'host': host,
                }

        def log_info(self, color='', status='', server='', port='', host=''):
            super().log(f'{color}{status:<6}  {server:<22}  {port:<4}  {host}')
        def log_info_result(self, **kwargs):
            G1 = self.logger.special_chars['G1']
            status = kwargs.get('status', '')
            server_name_indication = kwargs.get('server_name_indication', '')
            if status:
                color = G1
                self.log_info(color, 'True', server_name_indication,)
                self.task_success(server_name_indication)
            else:
                self.log_info(FAIL, 'False', server_name_indication)

        def init(self):
            super().init()
            self.log_info('', 'Stat', 'Host', 'Port', 'Server Name Indication',)
            self.log_info('', '----', '----', '----', '---------------------',)

        def task(self, payload):
            server_name_indication = payload['host']
            self.log_replace(server_name_indication)
            response = {
                'server_name_indication': server_name_indication,
                'status': False
            }

            try:
                socket_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                socket_client.settimeout(5)
                socket_client.connect((server_name_indication, 443))
                socket_client = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2).wrap_socket(
                    socket_client, server_hostname=server_name_indication, do_handshake_on_connect=True
                )
                response['status'] = True
                self.task_success(server_name_indication)

            except Exception:
                pass

            if response['status']:
                self.log_info_result(**response)

    def generate_ips_from_cidr(cidr):
        ip_list = []
        try:
            network = ipaddress.ip_network(cidr)
            for ip in network.hosts():
                ip_list.append(ip)
        except ValueError as e:
            print("Error:", e)
        return ip_list

    def bug_sluth_main():
        mode = input("Enter mode (direct, proxy, ssl, ping): ").strip()
        choice = input("(1)File name (2)Cdir: ")
        if choice == "1":
            filename = input("Enter filename: ").strip()
        elif choice == "2":
            cdir = input("Enter CIDR (e.g., 192.168.1.0/24): ").strip()

        method_list = input("Enter method (default: head): ").strip() or 'head'
        port_list = input("Enter port (default: 80): ").strip() or '80'
        choice2 = input("Do you want to use proxy?: y/n: ").lower()
        if choice2 == "y":
            proxy_input = input("Enter proxy (host:port): ").strip()
        else:
            proxy_input = ""  # Set empty string as default when no proxy needed
        output = input("Enter output file name: ").strip()
        threads = input("Enter number of threads: ").strip()
        threads = int(threads) if threads else None

        if not filename and not cdir:
            print("Either filename or CIDR must be provided.")
            sys.exit()

        method_list = method_list.split(',')
        if filename:
            host_list = open(filename).read().splitlines()
        elif cdir:
            ip_list = generate_ips_from_cidr(cdir)
            host_list = [str(ip) for ip in ip_list]

        port_list = port_list.split(',')
        proxy = proxy_input.split(':')

        if mode == 'direct':
            scanner = DirectScanner()
        elif mode == 'ssl':
            scanner = SSLScanner()
        elif mode == 'ping':
            scanner = PingScanner()
        elif mode == 'proxy':
            if not proxy or len(proxy) != 2:
                sys.exit('--proxy host:port')
            scanner = ProxyScanner()
            scanner.proxy = proxy
        else:
            sys.exit('Not Available!')

        scanner.method_list = method_list
        scanner.host_list = host_list
        scanner.port_list = port_list
        scanner.threads = threads
        scanner.start()

        if output:
            with open(output, 'w+') as file:
                file.write('\n'.join([str(x) for x in scanner.success_list()]) + '\n')

    bug_sluth_main()

#===CDN FINDER===#
def cdn_finder():
    
    generate_ascii_banner("CDN", "SCANNER")

    def findcdnfromhost(host):
        cloudflare_headers = ["cloudflare", "cloudfront", "cloudflare-nginx", "Google Frontend", "Google Cloud", "GW_Elastic_LB", "Fastly", "AkamaiGHost", "AkamainetStorage", "Akamai", "Akamai Technologies", "Akamai-Cdn", "Akamai-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai", "ningx", "cdnetworks", "edgecast", "incapsula", "maxcdn", "sucuri", "micosoft-azure", "amazonaws", "cloudfront", "cloudflare", "fastly", "maxcdn", "akamai", "edgecast", "sucuri", "incapsula", "amazonaws", "microsoft", "azure", "google", "cloud", "googlecloud", "googlecloudplatform", "gstatic", "gstatic.com", "gstatic.net", "gstatic.com.net", "gstatic.net.com", "gstatic.net.com.net", "gstatic.com.net", "gstatic.com.net.com", "gstatic.net.com.net", "gstatic.net.com.net.com", "gstatic.com.net.com.net", "gstatic.com.net.com.net.com", "gstatic.net.com.net.com.net", "gstatic.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net"]
        for header in cloudflare_headers:
            if header.lower() in host.lower():
                return "cloudflare", "cloudfront", "cloudflare-nginx", "Google Frontend", "Google Cloud", "GW_Elastic_LB", "Fastly", "AkamaiGHost", "AkamainetStorage", "Akamai", "Akamai Technologies", "Akamai-Cdn", "Akamai-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage", "Akamai-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn-Netstorage-Cdn", "Akamai", "ningx", "cdnetworks", "edgecast", "incapsula", "maxcdn", "sucuri", "micosoft-azure", "amazonaws", "cloudfront", "cloudflare", "fastly", "maxcdn", "akamai", "edgecast", "sucuri", "incapsula", "amazonaws", "microsoft", "azure", "google", "cloud", "googlecloud", "googlecloudplatform", "gstatic", "gstatic.com", "gstatic.net", "gstatic.com.net", "gstatic.net.com", "gstatic.net.com.net", "gstatic.com.net", "gstatic.com.net.com", "gstatic.net.com.net", "gstatic.net.com.net.com", "gstatic.com.net.com.net", "gstatic.com.net.com.net.com", "gstatic.net.com.net.com.net", "gstatic.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com", "gstatic.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net.com.net", "gstatic.net.com.net.com.net"
            
            
        return host

    def fetch_tls_ssl_certificate(host):
        ip_address = resolve_host_ip(host)
        if ip_address:
            try:
                with socket.create_connection((ip_address, 443)) as sock:
                    context = ssl.create_default_context()
                    with context.wrap_socket(sock, server_hostname=host) as ssock:
                        return ssock.getpeercert()
            except (socket.error, ssl.SSLError) as e:
                print(f"Error fetching TLS/SSL certificate for {host}:")
                return None
        return None

    def resolve_host_ip(host):
        try:
            ip_address = socket.gethostbyname(host)
            return ip_address
        except socket.gaierror as e:
            print(f"Error resolving IP address for {host}:")
            return None

    def get_http_headers(url):
        try:
            response = requests.head(url, timeout=5)
            return response.headers
        except Exception as e:
            print(f"HTTP request failed for {url}:")
            return None

    def get_dns_records(host):
        try:
            answers_a = dns.resolver.resolve(host, 'A')
            a_records = [str(answer) for answer in answers_a]
        except Exception as e:
            print(f"Failed to fetch A records for {host}:")
            a_records = []

        try:
            nslookup_result = get_aaaa_records(host)
            aaaa_records = nslookup_result if nslookup_result else []
        except Exception as e:
            print(f"Failed to fetch AAAA records for {host}:")
            aaaa_records = []

        try:
            answers_ptr = dns.resolver.resolve(host, 'PTR')
            ptr_records = [str(answer) for answer in answers_ptr]
        except Exception as e:
            print(f"Failed to fetch PTR records for {host}:")
            ptr_records = []

        try:
            answers_txt = dns.resolver.resolve(host, 'TXT')
            txt_records = [str(txt_answer) for txt_answer in answers_txt]
        except Exception as e:
            print(f"Failed to fetch TXT records for {host}:")
            txt_records = []

        try:
            answers_mx = dns.resolver.resolve(host, 'MX')
            mx_records = [f"{answer.preference} {answer.exchange}" for answer in answers_mx]
        except Exception as e:
            print(f"Failed to fetch MX records for {host}:")
            mx_records = []

        try:
            soa_records = [str(answer) for answer in dns.resolver.resolve(host, 'SOA')]
        except Exception as e:
            print(f"Failed to fetch SOA records for {host}:")
            soa_records = []

        return a_records, aaaa_records, ptr_records, txt_records, mx_records, soa_records

    def get_aaaa_records(host):
        result = subprocess.run(["nslookup", "-query=AAAA", host], capture_output=True, text=True)
        return result.stdout.splitlines()

    def save_to_file(filename, content):
        with open(filename, 'a') as file:
            file.write(content)

    def process_url(url, output_file):
        try:
            if not urlparse(url).scheme:
                url = "http://" + url

            hostname = urlparse(url).hostname
            a_records, aaaa_records, ptr_records, txt_records, mx_records, soa_records = get_dns_records(hostname)

            with open(output_file, 'a') as output_file:
                output_file.write(f"\nProcessing URL: {url}")
                output_file.write("\nDNS Records:")
                if a_records:
                    output_file.write(f"\nA Records: {a_records}")
                else:
                    output_file.write("\nNo A Records found.")

                if aaaa_records:
                    output_file.write("\n\nAAAA Records:")
                    for line in aaaa_records:
                        output_file.write(f"\n{line}")
                else:
                    output_file.write("\nNo AAAA Records found.")

                if ptr_records:
                    output_file.write(f"\n\nPTR Records: {ptr_records}")
                else:
                    output_file.write("\nNo PTR Records found.")

                if txt_records:
                    output_file.write("\n\nTXT Records:")
                    for line in txt_records:
                        output_file.write(f"\n{line}")
                else:
                    output_file.write("\nNo TXT Records found.")

                if mx_records:
                    output_file.write("\n\nMX Records:")
                    for line in mx_records:
                        output_file.write(f"\n{line}")
                else:
                    output_file.write("\nNo MX Records found.")

                if soa_records:
                    output_file.write(f"\n\nSOA Records: {soa_records}")
                else:
                    output_file.write("\nNo SOA Records found.")

                headers = get_http_headers(url)

                tls_ssl_certificate = fetch_tls_ssl_certificate(hostname)

                if headers:
                    output_file.write("\n\nHTTP Headers:")
                    for key, value in headers.items():
                        output_file.write(f"\n{key}: {value} ")

                    if tls_ssl_certificate:
                        output_file.write("\n\nTLS/SSL Certificate Information:")
                        for key, value in tls_ssl_certificate.items():
                            output_file.write(f"\n{key}: {value}")
                    else:
                        output_file.write("\nFailed to fetch TLS/SSL certificate.")
                else:
                    output_file.write("\nFailed to fetch HTTP headers.")

                server_header = headers.get("Server", "") if headers else ""
                cdn_provider = findcdnfromhost(server_header)
                output_file.write(f"\n\nCDN Provider: {cdn_provider}\n\n")

        except Exception as e:
            print(f"Error processing URL {url}:")
            with open(output_file, 'a') as output_file:
                output_file.write(f"\nError processing URL {url}:\n")

    def cdn_finder_main():
        user_input = input("Enter '1' to provide a URL, '2' to provide a text file with URLs: ")

        if user_input == '1':
            url = input("Enter the URL: ")
            urls = [url]  # Single URL
        elif user_input == '2':
            file_name = input("Enter the name of the text file with URLs: ")
            with open(file_name, 'r') as file:
                urls = [line.strip() for line in file.readlines() if line.strip()]
        else:
            print("Invalid input. Exiting.")
            exit()

        output_filename = input("Enter the output file name: ")

        # Threading setup
        max_threads = min(10, len(urls))  # Use up to 10 threads or as many as URLs
        with ThreadPoolExecutor(max_workers=max_threads) as executor:
            # Create a list to hold all futures
            futures = [executor.submit(process_url, url, output_filename) for url in urls]

            # Use tqdm to show progress bar
            for future in tqdm(as_completed(futures), total=len(urls), desc="Processing URLs"):
                try:
                    future.result()  # This will re-raise any exception that was raised in the thread
                except Exception as e:
                    print("An error occurred in a thread:")

        print(f"Output saved to {output_filename}")

    cdn_finder_main()

#===CDN FINDER2===#
def cdn_finder2():

    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

    generate_ascii_banner("CDN", "FINDER 2")

    cdn_endpoints = [
        ("kendo.cdn.telerik.com", "CloudFront"),
        ("cdn.jsdelivr.net", "CloudFlare"),
        ("cdn.statically.io", "CloudFlare"),

        ("www.facebook.com", "Facebook"),
        ("fonts.gstatic.com", "Google"),
        ("www.instagram.com", "Facebook"),

        ("instagram.com", "Facebook"),
        ("schema.org", "Google"),
        ("www.w3.org", "Cloudflare"),
        ("www.youtube.com", "Google"),
        ("fonts.googleapis.com", "Google"),
        ("www.tiktok.com", "Akamai"),
        ("use.fontawesome.com", "Cloudflare"),
        ("www.googletagmanager.com", "Google"),
        ("www.googletagservices.com", "Google"),
        ("www.google-analytics.com", "Google"),
        ("www.google.com", "Google"),
        ("www.gstatic.com", "Google"),
        ("www.snapchat.com", "Google"),
        ("cdnjs.cloudflare.com", "Cloudflare"),
        ("www.fastly.com", "Fastly"),
        ("www.apple.com", "Akamai"),
        ("cdn.intellimize.co", "Fastly"),
        ("www.linkedin.com", "Akamai"),
        ("www.twitter.com", "Twitter"),
        ("www.cloudflare.com", "Cloudflare"),
        ("cdn-cookieyes.com", "Cloudflare"),
        ("ns1.tstt.net.tt", "TsTT"),
        ("ns2.tstt.net.tt", "TsTT"),
        ("www.cachefly.com", "CacheFly"),
        ("www.maxcdn.com", "MaxCDN"),
        ("www.maxcdn.net", "MaxCDN"),
        ("www.netdna-cdn.com", "MaxCDN"),
        ("www.netdna-ssl.com", "MaxCDN"),
        ("www.netdna.com", "MaxCDN"),
    ]

    def resolve_hostname(hostname):
        ip_addresses = set()
        try:
            addr_info = socket.getaddrinfo(hostname, None)
            for info in addr_info:
                ip = info[4][0]
                ip_addresses.add(ip)
        except socket.gaierror:
            print(f"{Fore.RED}Could not resolve {hostname}.{Fore.RESET}")
        return list(ip_addresses)

    def reverse_dns_lookup(ip):
        try:
            hostname = socket.gethostbyaddr(ip)[0]

            return hostname
        
        except socket.herror:
            return "No record found"

    def check_direct_connection(ip, scheme="https"):
        try:
            url = f"{scheme}://[{ip}]" if ':' in ip else f"{scheme}://{ip}"
            response = requests.get(url, timeout=3, verify=False)
            server = response.headers.get("Server", "Server information not found")
            return True, server
        except requests.RequestException:
            print(f"{Fore.RED}Connection error with {ip}.{Fore.RESET}")
            return False, "Server information not found"

    def check_cdn_reachability(cdn_hostname, cdn_name, host_ip, output, unique_results, original_host, scheme="https"):
        print(f"\nChecking CDN: {cdn_name} ({cdn_hostname})")
        cdn_ips = resolve_hostname(cdn_hostname)
        if not cdn_ips:
            print(f"{Fore.RED}Could not resolve {cdn_hostname}.{Fore.RESET}")
            return
        print(f"{Fore.CYAN}Resolved IPs for {cdn_hostname}: {', '.join(cdn_ips)}{Fore.RESET}")
        for cdn_ip in cdn_ips:
            reverse_dns = reverse_dns_lookup(cdn_ip)
            print(f"{Fore.YELLOW} Checking {cdn_ip}: {reverse_dns}{Fore.RESET}")
            reachable, server_info = check_direct_connection(cdn_ip, scheme=scheme)
            if reachable:
                result_message = (
                    f"{Fore.GREEN}Connection to {original_host} ({host_ip}) via CDN {cdn_name} ({cdn_hostname}) "
                    f"using IP {cdn_ip} is reachable via {scheme.upper()} with server: {server_info} "
                    f"(Reverse DNS: {reverse_dns_lookup(cdn_ip)}).{Fore.RESET}"
                )
                if result_message not in unique_results:
                    output.append(result_message)
                    unique_results.add(result_message)

    def get_host_ips(host_input):
        if os.path.isfile(host_input):
            with open(host_input, 'r') as file:
                hosts = file.read().splitlines()
        else:
            hosts = [host_input]
        
        all_ips = []
        for host in hosts:
            ips = resolve_hostname(host)
            if ips:
                all_ips.append((host, ips))  # Store both the hostname and its resolved IPs
            else:
                print(f"{Fore.RED}Could not resolve {host}.{Fore.RESET}")
        return all_ips

    def cdn_finder2_main():
        output = []
        unique_results = set()
        host_input = input("Enter host IP/CIDR or .txt file with IP/domain or CIDR: ")
        print(f"\nResolving host(s): {host_input}")
        
        host_ips = get_host_ips(host_input)
        if not host_ips:
            print(f"{Fore.RED}No valid IPs resolved.{Fore.RESET}")
            return

        scheme = "https" if not host_input.lower().startswith("http://") else "http"
        with ThreadPoolExecutor() as executor:
            for original_host, ips in host_ips:
                for ip in ips:
                    futures = [
                        executor.submit(
                            check_cdn_reachability, cdn_hostname, cdn_name, ip, output, unique_results, original_host, scheme
                        )
                        for cdn_hostname, cdn_name in cdn_endpoints
                    ]
                    for future in futures:
                        future.result()

        print("\n".join(output))

        if output:
            save_option = input("\nWould you like to save the results to a file? (y/n): ").strip().lower()
            if save_option == 'y':
                filename = input("Enter the filename (with .txt extension): ")
                with open(filename, "w") as f:
                    f.write("\n".join(output))
                print(f"Results saved to {filename}")
        else:
            print(f"{Fore.RED}No reachable CDN connections found. No results to save.{Fore.RESET}")

    cdn_finder2_main()

#===HOST PROXY CHECKER===#
def host_proxy_checker():

    generate_ascii_banner("HOST PROXY", "CHECKER")

    def save_result(result, output_file, save_flag):
        # Only save if the output_file is provided and if the result contains "Keep-Alive" and "SNI Used"
        if output_file and "Keep-Alive" in result and "SNI Used" in result:
            with open(output_file, 'a' if os.path.exists(output_file) else 'w') as file:
                file.write(result + "\n")
            save_flag[0] = True  # Indicate that a result has been saved

    def sni_check(domain_or_ip, https_url, output_file, save_flag):
        try:
            print(f"Performing SNI check on {domain_or_ip}...")
            response = requests.get(https_url, headers={"Host": domain_or_ip}, timeout=5)
            status_code = response.status_code
            if status_code in [200]:
                server_info = response.headers.get('Server', 'Unknown')
                connection = response.headers.get('Connection', '')
                keep_alive = "Keep-Alive" if "keep-alive" in connection.lower() else "Closed"

                result = f"{domain_or_ip} | SNI Check | Status: {status_code} | Server: {server_info} | Connection: {keep_alive}"
                print(f"\033[92mSNI check successful for {domain_or_ip} (Status: {status_code}, Server: {server_info}, Connection: {keep_alive})\033[0m")
                save_result(result, output_file, save_flag)
            else:
                print(f"\033[93mSNI check for {domain_or_ip} received status code: {status_code}\033[0m")
        except RequestException:
            print(f"\033[91mSNI check failed for {domain_or_ip}\033[0m")
            sni_check(domain_or_ip)

    def proxy_request(proxy_host, http_url, https_url, output_file, save_flag):
        proxies = {"http": f"http://{proxy_host}", "https": f"http://{proxy_host}"}

        def try_request(url, port, use_sni=False):
            try:
                headers = {"Host": proxy_host} if use_sni else {}  # Set SNI header if needed
                response = requests.get(url, proxies={"http": proxies["http"]}, headers=headers, timeout=5)
                status_code = response.status_code
                if status_code in [200]:
                    server_info = response.headers.get('Server', 'Unknown')
                    connection = response.headers.get('Connection', '')
                    keep_alive = "Keep-Alive" if "keep-alive" in connection.lower() else "Closed"
                    
                    sni_note = "SNI Used" if use_sni else "No Sni"  # Add SNI indicator to result
                    result = f"{proxy_host} | Use As Proxy | {sni_note} | Port {port} | Status: {status_code} | Server: {server_info} | Connection: {keep_alive}"
                    
                    print(f"\033[92mRequest on port {port} successful for {url} via {proxy_host} {sni_note} "
                        f"(Status: {status_code}, Server: {server_info}, Connection: {keep_alive})\033[0m")
                    
                    save_result(result, output_file, save_flag)
                else:
                    print(f"Proxy Request via port {port} received status code: {status_code}")
            except LocationParseError as e:
                print("\033[91mFailed to parse URL: {url}. Error: \033[0m")
            except (RequestException, ProxyError) as e:
                print(f"\033[91mError connecting to {url} on port {port}. Error: \033[0m")
            except Exception as e:  # Catch any other exceptions
                print("\033[91mAn unexpected error occurred: \033[0m")

        # Try HTTP and HTTPS via proxy (without and with SNI)
        try_request(http_url, 80),
        try_request(http_url, 80, use_sni=True),
        try_request(https_url, 443),
        try_request(https_url, 443, use_sni=True)  # HTTPS with SNI

    def process_proxies(proxies, http_url, https_url, output_file):
        save_flag = [False]  # A list to pass the flag by reference (lists are mutable)
        
        with ThreadPoolExecutor(max_workers=20) as executor:
            list(tqdm(executor.map(lambda proxy: proxy_request(proxy, http_url, https_url, output_file, save_flag), proxies), desc="Processing proxies", unit="proxy"))

        # After processing, notify the user whether results were saved or not
        if output_file:
            if save_flag[0]:
                print(f"\033[92mResults saved to {output_file}\033[0m")
            else:
                print("\033[93mI could not find anything, please try again.\033[0m")

    def validate_url(url):
        url = re.sub(r'^\.{1,}', '', url)  # Remove any leading dots
        return url

    def generate_ips_from_cidr(cidr):
        try:
            network = ipaddress.ip_network(cidr)
            return [str(ip) for ip in network.hosts()]
        except ValueError:
            print(f"Invalid CIDR: {cidr}")
            return []

    def host_proxy_checker_main():
        input_file = input("Enter txt file with proxy URLs, domains, or CIDRs: ")
        try:
            with open(input_file, 'r') as file:
                proxies = []
                for line in file:
                    entry = line.strip()
                    if "/" in entry:  # Check if CIDR is provided
                        proxies.extend(generate_ips_from_cidr(entry))
                    else:
                        proxies.append(entry)

            if not proxies:
                print("Error: No valid proxies, domains, or IPs found in the file.")
                return

            http_url = input("Enter the isp domain to check: ")
            http_url = validate_url(http_url)
            http_url = http_url if http_url.startswith("http") else "http://" + http_url
            https_url = "https://" + http_url.lstrip("http://")

            output_file = input("Enter Output .txt: ") if input("Do you want to save the results? (y/n): ").strip().lower() == 'y' else None
            process_proxies(proxies, http_url, https_url, output_file)

        except FileNotFoundError:
            print(f"Error: File {input_file} not found.")

    host_proxy_checker_main()

#===WEB CRAWLER===#
def web_crawler():
    
    import aiohttp
    from urllib.parse import urlparse, urljoin

    generate_ascii_banner("WEB", "CRAWLER")

    visited_urls = {}
    found_urls = set()
    output_file = input("Input filename for output: ")
    start_domain = None
    last_save = time.time()

    # Set a semaphore for limiting concurrent requests per URL
    concurrency_limit = 10

    # Load visited URLs from the output file if it exists
    if os.path.exists(output_file):
        with open(output_file, 'r') as f:
            for line in f:
                parts = line.strip().split(" | ")
                if len(parts) == 4:
                    url, response_code, server, ip = parts
                    visited_urls[url] = {"response_code": response_code, "server": server, "ip": ip}

    async def fetch_url(session, url):
        if url in visited_urls or (start_domain and urlparse(url).netloc != start_domain):
            return False
        async with asyncio.Semaphore(concurrency_limit):  # Limit to 10 concurrent requests per main URL
            try:
                headers = {
                    "User-Agent": random.choice([
                        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
                        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
                        "Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
                        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"
                    ])
                }

                async with session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as response:
                    response_code = response.status
                    server = response.headers.get('Server', 'Unknown')
                    ip_address = socket.gethostbyname(urlparse(url).netloc)
                    visited_urls[url] = {
                        "response_code": response_code,
                        "server": server,
                        "ip": ip_address
                    }
                    print(f"URL: {url} | Response Code: {response_code} | Server: {server} | IP: {ip_address}")

                    if response_code == 200:
                        html = await response.text()
                        soup = BeautifulSoup(html, 'html.parser')
                        new_urls_found = False

                        tasks = []
                        for link in soup.find_all('a', href=True):
                            href = link['href']
                            next_url = urljoin(url, href).split('#')[0]  # Remove fragment identifiers
                            if next_url not in found_urls:
                                found_urls.add(next_url)
                                tasks.append(fetch_url(session, next_url))
                                new_urls_found = True

                        # Execute concurrent requests within the main URL's scope
                        if tasks:
                            await asyncio.gather(*tasks)

                        if len(found_urls) % 100 == 0 or time.time() - last_save > 300:
                            save_output()

                        return new_urls_found

            except (aiohttp.ClientError, asyncio.TimeoutError) as e:
                print(f"Error for {url}: {e}")
            except Exception as e:
                print(f"Unexpected error for {url}: {e}")

        return False

    def save_output():
        global last_save
        with open(output_file, 'w') as f:
            for url, data in visited_urls.items():
                f.write(f"{url} | Response Code: {data['response_code']} | Server: {data['server']} | IP: {data['ip']}\n")
        print(f"Output saved to {output_file}")
        last_save = time.time()

    async def process_sequential_urls(url_list):
        async with aiohttp.ClientSession() as session:
            for url in url_list:
                parsed_url = urlparse(url.strip())
                if not parsed_url.scheme:
                    url = 'https://' + url.strip()  # Default to https if no scheme is present
                elif not parsed_url.scheme in ["http", "https"]:
                    print(f"Invalid URL scheme for {url}, skipping...")
                    continue
                global start_domain
                start_domain = urlparse(url).netloc
                print(f"Processing domain: {start_domain}")
                new_urls_found = await fetch_url(session, url)
                if not new_urls_found:
                    save_output()  # Save if no new URLs are found for this domain

    async def web_crawler_main():
        url_or_file = input("Enter a URL to crawl or a file name: ").strip()

        if url_or_file.endswith('.txt'):
            try:
                with open(url_or_file, 'r') as f:
                    urls = [line.strip() for line in f.readlines()]
                    await process_sequential_urls(urls)
            except FileNotFoundError:
                print("Error: File not found.")
        else:
            # Add scheme if missing
            parsed_url = urlparse(url_or_file)
            if not parsed_url.scheme:
                url_or_file = 'https://' + url_or_file
            await process_sequential_urls([url_or_file])

        # Final save after completion if there are any new URLs left
        save_output()
        print("\nKeyboardInterrupt detected. Saving results before exiting...")
    asyncio.run(web_crawler_main())

#===DOSSIER===#
def dossier():

    generate_ascii_banner("DOSSIER", "")

    print(GREEN + "use with proxies from the free proxy option " + ENDC)
    print(RED + "http proxies seems to work best so far " + ENDC)

    # Add scan completion flag
    scan_complete = threading.Event()

    def generate_url(website, page):
        if page == 1:
            return f"http://www.sitedossier.com/referer/{website}/{page}"
        else:
            return f"http://www.sitedossier.com/referer/{website}/{(page-1)*100}"

    def fetch_table_data(url, proxies=None):
        try:
            response = requests.get(url, proxies=proxies, timeout=10)
            response.raise_for_status()
            
            if "End of list." in response.text:
                scan_complete.set()
                return False, "END"
                
            if response.status_code == 404:
                print("Job done.")
                return False, None
                
            if "Please enter the unique \"word\" below to confirm" in response.text:
                return False, None
                
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')
                table = soup.find('table')
                if table:
                    rows = table.find_all('tr')
                    data = []
                    for row in rows:
                        cells = row.find_all('td')
                        if cells:
                            row_data = [cell.text.strip() for cell in cells if cell.text.strip()]
                            if row_data:
                                data.append('\n'.join(row_data))
                    return True, data
                else:
                    print("No table found on page")
                    return False, None
        except Exception as e:
            print(f"Error fetching data: {e}")
            return False, None

    def load_domains_from_file(filename):
        domains = []
        with open(filename, 'r') as file:
            for line in file:
                domains.append(line.strip())
        return domains

    def load_proxies_from_file(filename):
        proxies = []
        try:
            with open(filename, 'r') as file:
                for line in file:
                    proxies.append(line.strip())
            return proxies
        except FileNotFoundError:
            print(f"File '{filename}' not found. Please provide a valid file name.")
            return []
        except Exception as e:
            print(f"Error reading file: {e}")
            return []

    def save_to_file(filename, data):
        # Initialize counters if they don't exist
        if not hasattr(save_to_file, 'total_items'):
            save_to_file.total_items = 0
            save_to_file.total_urls = 0
        
        save_to_file.total_items += len(data)
        save_to_file.total_urls += 1
        
        with open(filename, 'a') as file:
            for item in data:
                file.write(item.strip())
                file.write('\n')
        
        print(f"\nProgress: {save_to_file.total_items} total items saved from {save_to_file.total_urls} URLs")

    def fetch_data(url, proxies, save_file, output_file):
        if scan_complete.is_set():
            return
            
        if proxies:
            proxy_index = 0
            with tqdm(total=1, desc=f"Fetching {url}", leave=True) as pbar:
                while not scan_complete.is_set():
                    success, data = fetch_table_data(url, proxies={'http': proxies[proxy_index], 'https': proxies[proxy_index]})
                    
                    if data == "END":
                        print("\nReached end of list - stopping scan")
                        break
                        
                    if success:
                        pbar.update(1)
                        print(f"\nSuccess: {url}")
                        for item in data:
                            print(item)
                        if save_file == "yes":
                            save_to_file(output_file, data)
                        break
                        
                    proxy_index = (proxy_index + 1) % len(proxies)
                    if proxy_index == 0:
                        pbar.update(1)
                        break
        else:
            with tqdm(total=1, desc=f"Fetching {url}", leave=True) as pbar:
                success, data = fetch_table_data(url)
                if data == "END":
                    print("\nReached end of list - stopping scan") 
                    return
                if success:
                    pbar.update(1)
                    print(f"\nSuccess: {url}")
                    for item in data:
                        print(item)
                    if save_file == "yes":
                        save_to_file(output_file, data)
                else:
                    pbar.update(1)

    def dossier_main():
        scan_complete.clear()
        
        input_type = input("Choose input type (single/file): ").lower()
        
        if input_type == "single":
            website = input("Enter the website (e.g., who.int): ")
            num_pages = int(input("Enter the number of pages to fetch: "))
            urls = [generate_url(website, page) for page in range(1, num_pages + 1)]
            
        elif input_type == "file":
            domain_list_file = input("Enter the filename containing list of domains: ")
            domains = load_domains_from_file(domain_list_file)
            num_pages = int(input("Enter the number of pages to fetch per domain: "))
            urls = []
            for domain in domains:
                urls.extend([generate_url(domain, page) for page in range(1, num_pages + 1)])
        else:
            randomshit("you fool, you have chosen the wrong option")
            print("Reterning to main because you messed up.")
            time.sleep(2)
            return
        
        use_proxy = input("Do you want to use a proxy? (yes/no): ").lower()
        if use_proxy == "yes":
            proxy_list_name = input("Enter the proxy list file name: ")
            proxies = load_proxies_from_file(proxy_list_name)
        else:
            proxies = None
        
        save_file = input("Do you want to save the output data to a file? (yes/no): ").lower()
        if save_file == "yes":
            output_file = input("Enter the filename to save the output data (without extension): ") + ".txt"
        
        with ThreadPoolExecutor(max_workers=10) as executor:
            futures = []
            for url in urls:
                if scan_complete.is_set():
                    break
                futures.append(executor.submit(fetch_data, url, proxies, save_file, output_file))

            for future in futures:
                try:
                    future.result()
                    if scan_complete.is_set():
                        break
                except Exception as e:
                    print(f"Error in thread: {e}")

        print("Scan completed.")

    dossier_main()

#===HACKER TARGET===#
def hacker_target():
    
    generate_ascii_banner("Hacker", "Target")
    import requests
    import re
    import base64
    import json
    import os
    import platform
    from bs4 import BeautifulSoup


    def clear_screen():
        if platform.system() == "Windows":
            os.system("cls")
        else:
            os.system("clear")


    class DNSDumpsterAPI:
        def __init__(self, verbose=False):
            self.verbose = verbose
            self.authorization = self.get_token()

        def get_token(self):
            session = requests.Session()
            response = session.get("https://dnsdumpster.com/")
            if response.status_code == 200:
                match = re.search(r'{"Authorization":\s?"([^"]+)"', response.text)
                if match:
                    token = match.group(1)
                    if self.verbose:
                        print(f"[+] Authorization Token found: {token}")
                    return token
            if self.verbose:
                print("[-] Failed to retrieve authorization token.")
            return None

        def get_dnsdumpster(self, target):
            if not self.authorization:
                print("[-] Authorization token is missing.")
                return None
            url = "https://api.dnsdumpster.com/htmld/"
            headers = {"Authorization": self.authorization}
            data = {"target": target}
            response = requests.post(url, headers=headers, data=data)
            return response.text if response.status_code == 200 else None

        def parse_dnsdumpster(self, html, domain):
            soup = BeautifulSoup(html, 'html.parser')
            tables = soup.findAll('table')
            res = {'domain': domain, 'dns_records': {}}

            if len(tables) >= 4:
                res['dns_records']['a'] = self.retrieve_results(tables[1])
                res['dns_records']['mx'] = self.retrieve_results(tables[2])
                res['dns_records']['ns'] = self.retrieve_results(tables[3])
                res['dns_records']['txt'] = self.retrieve_txt_record(tables[4])

                # Image
                try:
                    pattern = rf'https://api.dnsdumpster.com/static/maps/{re.escape(domain)}-[a-f0-9\-]+\.png'
                    map_url = re.findall(pattern, html)[0]
                    image_data = base64.b64encode(requests.get(map_url).content).decode('utf-8')
                    res['image_data'] = image_data
                except:
                    res['image_data'] = None

                # XLS
                try:
                    pattern = rf'https://api.dnsdumpster.com/static/xlsx/{re.escape(domain)}-[a-f0-9\-]+\.xlsx'
                    xls_url = re.findall(pattern, html)[0]
                    xls_data = base64.b64encode(requests.get(xls_url).content).decode('utf-8')
                    res['xls_data'] = xls_data
                except:
                    res['xls_data'] = None
            else:
                if self.verbose:
                    print("[-] Expected tables not found.")
                return None
            return res

        def retrieve_results(self, table):
            res = []
            for tr in table.findAll('tr'):
                tds = tr.findAll('td')
                try:
                    host = str(tds[0]).split('<br/>')[0].split('>')[1].split('<')[0]
                    ip = re.findall(r'\d+\.\d+\.\d+\.\d+', tds[1].text)[0]
                    reverse_dns = tds[1].find('span').text if tds[1].find('span') else ""
                    autonomous_system = tds[2].text if len(tds) > 2 else ""
                    asn = autonomous_system.split('\n')[1] if '\n' in autonomous_system else ""
                    asn_range = autonomous_system.split('\n')[2] if '\n' in autonomous_system else ""
                    span_elements = tds[3].find_all('span', class_='sm-text') if len(tds) > 3 else []
                    asn_name = span_elements[0].text.strip() if len(span_elements) > 0 else ""
                    country = span_elements[1].text.strip() if len(span_elements) > 1 else ""
                    open_service = "\n".join([line.strip() for line in tds[4].text.splitlines() if line.strip()]) if len(tds) > 4 else "N/A"
                    res.append({
                        'host': host,
                        'ip': ip,
                        'reverse_dns': reverse_dns,
                        'as': asn,
                        'asn_range': asn_range,
                        'asn_name': asn_name,
                        'asn_country': country,
                        'open_service': open_service
                    })
                except Exception:
                    continue
            return res

        def retrieve_txt_record(self, table):
            return [td.text.strip() for td in table.findAll('td')]

        def search(self, domain):
            if self.verbose:
                print(f"[+] Searching for domain: {domain}")
            html = self.get_dnsdumpster(domain)
            return self.parse_dnsdumpster(html, domain) if html else None


    # ======= HackerTarget Tools =======
    def save_output(filename, content):
        with open(filename, "w") as f:
            f.write(content)
        print(f"[+] Output saved to {filename}")


    def hostsearch(target):
        try:
            result = requests.get(f"https://api.hackertarget.com/hostsearch/?q={target}").text
            count = len(result.splitlines())
            print(f"[+] {count} domains found.\n")
            print(result)
            save_output(f"{target}_hostsearch.txt", result)
        except:
            print("[-] Error occurred during hostsearch.")


    def reversedns(target):
        try:
            result = requests.get(f"https://api.hackertarget.com/reversedns/?q={target}").text
            print(result)
            save_output(f"{target}_reversedns.txt", result)
        except:
            print("[-] Error occurred during reversedns.")


    def dnslookup(target):
        try:
            result = requests.get(f"https://api.hackertarget.com/dnslookup/?q={target}").text
            print(result)
            save_output(f"{target}_dnslookup.txt", result)
        except:
            print("[-] Error occurred during dnslookup.")


    def gethttpheaders(target):
        try:
            result = requests.get(f"https://api.hackertarget.com/httpheaders/?q={target}").text
            print(result)
            save_output(f"{target}_httpheaders.txt", result)
        except:
            print("[-] Error occurred during http headers fetch.")


    # ======== Main ========
    def hacker_target_main():
        target = input("Enter the domain to scan: ").strip()
        api = DNSDumpsterAPI(verbose=True)
        res = api.search(target)

        if res:
            print("\n[+] DNSDumpster Results:")
            for key in ['a', 'mx', 'ns']:
                print(f"\n### {key.upper()} Records ###")
                for record in res['dns_records'].get(key, []):
                    print(f"{record['host']} ({record['ip']}) - {record['asn_name']} [{record['asn_country']}]")
            print("\n### TXT Records ###")
            for txt in res['dns_records'].get('txt', []):
                print(txt)

            with open(f"{target}_dnsdumpster_results.json", "w") as f:
                json.dump(res, f, indent=4)
            print(f"\n[+] Results saved to {target}_dnsdumpster_results.json")

            if res.get("image_data"):
                with open(f"{target}_network_map.png", "wb") as f:
                    f.write(base64.b64decode(res["image_data"]))
                print(f"[+] Network map saved as {target}_network_map.png")

            if res.get("xls_data"):
                with open(f"{target}_hosts.xlsx", "wb") as f:
                    f.write(base64.b64decode(res["xls_data"]))
                print(f"[+] XLS data saved as {target}_hosts.xlsx")
        else:
            print("[-] DNSDumpster failed or no data found.")

        input("\nPress Enter to view menu...")
        clear_screen()

        # MENU
        while True:
            clear_screen()
            print(f"\n[+] Select an option for further scanning: ({target})")
            print("[1] Host Search")
            print("[2] Reverse DNS")
            print("[3] DNS Lookup")
            print("[4] HTTP Headers")
            print("[5] Exit")

            choice = input("Choose an option [1-5]: ").strip()
            clear_screen()

            if choice == "1":
                hostsearch(target)
            elif choice == "2":
                reversedns(target)
            elif choice == "3":
                dnslookup(target)
            elif choice == "4":
                gethttpheaders(target)
            elif choice == "5":
                print("Goodbye!")
                break
            else:
                print("Invalid choice.")

    hacker_target_main()

#===URL REDIRECT===#
def url_redirect():

    generate_ascii_banner("URL", "REDIRECT")

    def get_ssl_server_info(hostname):
        try:
            context = ssl.create_default_context()
            with socket.create_connection((hostname, 443), timeout=3) as sock:
                with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                    cert = ssock.getpeercert()
                    return cert.get('subject', [('commonName', 'Unknown')])[0][1]
        except Exception:
            return 'info not available'

    def check_url(url):
        try:
            response = requests.get(url, timeout=3, allow_redirects=False)
            if response.status_code == 200:
                server_info = response.headers.get('Server', 'Server info not available')
                # If URL is HTTPS and server_info was not found, fetch SSL info
                if url.startswith('https://') and server_info == 'Server info not available':
                    hostname = re.sub(r'^https?://', '', url).split('/')[0]
                    server_info = get_ssl_server_info(hostname)
                return url, 200, server_info
        except requests.RequestException:
            return None

        return None

    def process_hostname(hostname):
        results = []
        for protocol in ['http://', 'https://']:
            url = f"{protocol}{hostname}"
            result = check_url(url)
            if result:
                results.append(result)
        return results

    def url_redirect_main():
        script_dir = os.path.dirname(os.path.abspath(__file__))
        file_name = input("Enter the filename containing URLs or hostnames: ").strip()
        file_path = os.path.join(script_dir, file_name)

        urls = []
        if os.path.isfile(file_path):
            with open(file_path, 'r') as file:
                urls = [line.strip() for line in file if line.strip()]
        else:
            urls.append(file_name)

        results = []
        with ThreadPoolExecutor(max_workers=5) as executor:
            futures = {executor.submit(process_hostname, url): url for url in urls}
            for future in tqdm(as_completed(futures), total=len(urls), desc="Processing hostnames"):
                try:
                    result = future.result()
                    if result:
                        results.extend(result)
                except Exception as e:
                    print(f"Error processing hostname {futures[future]}: {e}")

        output_file = os.path.join(script_dir, 'cdn_data.txt')
        with open(output_file, 'w') as file:
            for url, status_code, server_info in results:
                info = f"{url} - Status Code: {status_code}\nServer Info: {server_info}\n"
                print(f"\033[92m{info}\033[0m")
                file.write(info + '\n')

    url_redirect_main()
    print("file saved to: cdn_data.txt")

#===TWISTED===#  
def twisted():

    generate_ascii_banner("TWISTED", "")

    def text(url_input):
        return os.path.isfile(url_input)

    def is_alive(connection_header):
        if connection_header:
            return 'alive' if 'keep-alive' in connection_header.lower() else 'inactive'
        return 'inactive'

    def extract_sources(csp_header, directives):
        if csp_header:
            sources = {}
            for directive in directives:
                pattern = rf"{directive}\s+([^;]+)"
                match = re.search(pattern, csp_header.lower())
                if match:
                    sources[directive] = match.group(1).strip().split()
            return sources if sources else "No sources found"
        return "header not found"

    def fetch_url(url, expected_csp_directives, output_set):
        output_lines = []
        try:
            r = requests.get(f"http://{url}", allow_redirects=True, timeout=3)

            final_conn_status = r.headers.get('connection', '')
            final_server_info = r.headers.get('server', '').lower() or 'Server info unavailable'
            csp_header = r.headers.get('content-security-policy', '')

            for resp in r.history:
                history_conn_status = resp.headers.get('connection', '') or 'inactive'
                history_server_info = resp.headers.get('server', '').lower() or 'Server info unavailable'
                redirect_info = f"Redirected to: {resp.url}, Status Code: {resp.status_code}, Connection: {is_alive(history_conn_status)}, Server Info: {history_server_info}"
                if redirect_info not in output_lines:
                    output_lines.append(redirect_info)
                print(redirect_info)

            final_info = f"Final Hosted Url: {r.url}, Status Code: {r.status_code}, Connection: {is_alive(final_conn_status)}, Server Info: {final_server_info}"
            if final_info not in output_lines:
                output_lines.append(final_info)
            print(final_info)
            
            sources = extract_sources(csp_header, expected_csp_directives)
            if isinstance(sources, dict):
                for directive, src_list in sources.items():
                    for src in src_list:
                        if src.startswith("*."):
                            src = src[2:]
                        if src not in output_set:
                            output_set.add(src)
                            output_lines.append(f"{src}")
            else:
                output_lines.append(sources)

        except requests.exceptions.RequestException as e:
            print(f"Error fetching: {url}")

        return output_lines

    def twisted_main():
        url_input = input("Enter URL or path to .txt file: ")
        save_output_choice = input("Save the output? (yes/no): ").strip().lower()
        output_file = input("Output filename: ") if save_output_choice == "yes" else None

        expected_csp_directives = [
            "default-src",
            "script-src",
            "style-src",
            "connect-src",
            "font-src",
            "img-src",
            "media-src",
            "frame-src",
            "worker-src",
            "source value",
            "base-uri",
            "block-all-mixed-content",
            "child-src",
            "fenced-frame-src",
            "frame-ancestors",
            "form-action",
            "frame-src",
            "manifest-src",
            "object-src",
            "prefetch-src",
            "report-to",
            "report-uri",
            "require-trusted-types-for",
            "sandbox",
            "script-src-attr",
            "script-src-elem",
            "upgrade-insecure-requests",
            "trusted-types"
        ]

        if text(url_input):
            with open(url_input, 'r') as file:
                urls = [line.strip() for line in file if line.strip()]
        else:
            urls = [url_input]

        output_set = set()
        results = []
        
        with ThreadPoolExecutor(max_workers=15) as executor:
            futures = {executor.submit(fetch_url, url, expected_csp_directives, output_set): url for url in urls}
            for future in tqdm(as_completed(futures), total=len(futures), desc="Processing URLs"):
                results.append(future.result())

        if save_output_choice == "yes" and output_file:
            with open(output_file, 'w') as file:
                for result in results:
                    if result:
                        for line in result:
                            file.write(f"{line}\n")
                        file.write("\n")

        print(f"\nTotal found: {len(output_set)}")

        print(f"Output saved to {output_file}" if save_output_choice == "yes" else "Output not saved.")

    twisted_main()

#===STAT===#
def stat():
    from urllib.parse import urljoin, urlparse
    from collections import OrderedDict
    from typing import List
    from urllib.parse import urlparse, urlunparse

    class URLTracker:
        def __init__(self):
            self.processed_urls = set()
            self.results = OrderedDict()
            self.processed_domains = set()

        def add_url(self, url):
            """Thread-safe URL addition with domain tracking."""
            normalized = self.normalize_url(url)
            domain = urlparse(normalized).netloc
            
            # Use tuple to ensure thread-safe checking
            key = (normalized, domain)
            if key not in self._get_processed_keys():
                self.processed_urls.add(normalized)
                self.processed_domains.add(domain)
                return True
            return False
        
        def _get_processed_keys(self):
            """Get set of (url, domain) tuples for processed URLs."""
            return {(url, urlparse(url).netloc) for url in self.processed_urls}

        def is_domain_processed(self, domain):
            """Check if a domain has been processed."""
            return domain in self.processed_domains

        @staticmethod
        def normalize_url(url):
            parsed = urlparse(url)
            return f"{parsed.scheme}://{parsed.netloc}{parsed.path}".rstrip('/')

        def get_stats(self):
            """Get statistics about processed URLs."""
            return {
                'total_processed': len(self.processed_urls),
                'unique_domains': len({urlparse(url).netloc for url in self.processed_urls})
            }

    class DomainChecker:
        def __init__(self, max_workers=20, timeout=5):
            self.max_workers = max_workers
            self.timeout = timeout
            self.session = requests.Session()
            self.analyzed_domains = set()  # Track analyzed domains to prevent loops

        def check_domain_status(self, domain):
            """Enhanced domain check with CSP analysis."""
            if domain in self.analyzed_domains:
                return None
            self.analyzed_domains.add(domain)
            
            try:
                response = self.session.get(domain, timeout=self.timeout, allow_redirects=True)
                result = {
                    'domain': domain,
                    'status': response.status_code,
                    'server': response.headers.get('server', 'Not specified'),
                    'content_type': response.headers.get('content-type', 'Not specified'),
                    'redirect': response.url if response.history else None,
                    'csp': self.extract_csp_headers(response),
                    'csp_domains': set()
                }
                
                # Extract domains from CSP if present
                if result['csp']:
                    result['csp_domains'] = self.extract_csp_domains(result['csp'])
                
                return result
            except Exception as e:
                return {'domain': domain, 'error': str(e)}

        def extract_csp_headers(self, response):
            """Extract all CSP related headers from response."""
            csp_headers = {}
            for header in response.headers:
                if 'content-security-policy' in header.lower():
                    csp_headers[header] = response.headers[header]
            return csp_headers

        def extract_csp_domains(self, csp_headers):
            """Extract domains from CSP directives."""
            domains = set()
            for csp in csp_headers.values():
                for directive in csp.split(';'):
                    if not directive.strip():
                        continue
                    parts = directive.strip().split()
                    if len(parts) > 1:
                        for source in parts[1:]:
                            domain = self.normalize_csp_source(source)
                            if domain:
                                domains.add(domain)
            return domains

        @staticmethod
        def normalize_csp_source(source):
            """Normalize CSP source to extract valid domain."""
            source = source.strip("'")
            if source in {'self', 'none', 'unsafe-inline', 'unsafe-eval'} or \
            source.startswith(('data:', 'blob:', 'filesystem:', 'about:')):
                return None
                
            if source.startswith('*.'):
                source = source[2:]
            if not source.startswith(('http://', 'https://')):
                source = f'https://{source}'
                
            try:
                parsed = urlparse(source)
                if parsed.netloc:
                    return source
            except Exception:
                pass
            return None

        def check_domains_parallel(self, domains):
            """Check multiple domains in parallel."""
            results = []
            with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
                future_to_domain = {
                    executor.submit(self.check_domain_status, domain): domain 
                    for domain in domains
                }
                
                with tqdm(total=len(future_to_domain), desc="Checking domains") as pbar:
                    for future in as_completed(future_to_domain):
                        result = future.result()
                        results.append(result)
                        pbar.update(1)
            
            return results

    def log_csp_analysis(result, outfile, indent="    "):
        """Log CSP analysis results."""
        if 'csp' in result and result['csp']:
            log_output(f"{indent}CSP Headers found:", outfile)
            for header, value in result['csp'].items():
                log_output(f"{indent}  {header}:", outfile)
                for directive in value.split(';'):
                    if directive.strip():
                        log_output(f"{indent}    {directive.strip()}", outfile)
            
            if result.get('csp_domains'):
                log_output(f"{indent}  CSP Referenced Domains:", outfile)
                for domain in result['csp_domains']:
                    log_output(f"{indent}    - {domain}", outfile)

    def check_csp_domains(csp, outfile, source, url_tracker):
        """Enhanced CSP domain checking with recursive analysis."""
        domains = set()
        if not csp:
            return domains
        
        # List of special CSP keywords to ignore
        CSP_KEYWORDS = {
            'self', 'none', 'unsafe-inline', 'unsafe-eval', 
            'strict-dynamic', 'report-sample', '*', "'none'", "'self'",
            'unsafe-hashes', 'wasm-unsafe-eval', 'data:', 'blob:' 'filesystem:', 'about:',
        }
        
        for directive in csp.split(';'):
            if not directive.strip():
                continue
                
            policy_name, *sources = directive.strip().split()
            new_domains = set()
            
            for source in sources:
                source = source.replace('*.', '').strip("'")
                
                if (source.lower() in CSP_KEYWORDS or 
                    source.startswith(('data:', 'blob:', 'filesystem:', 'about:'))):
                    continue
                
                if source and not source.startswith(('http://', 'https://')):
                    source = f'https://{source}' if not source.startswith('//') else f'https:{source}'
                
                try:
                    parsed = urlparse(source)
                    if parsed.netloc and not url_tracker.is_domain_processed(parsed.netloc):
                        new_domains.add(source)
                except Exception:
                    continue
            
            if new_domains:
                log_output(f"\nChecking new domains for {policy_name}:", outfile)
                checker = DomainChecker()
                results = checker.check_domains_parallel(new_domains)
                
                for result in results:
                    if 'error' in result:
                        log_output(f"  Domain: {result['domain']} - Error: {result['error']}", outfile)
                    else:
                        log_output(f"  Domain: {result['domain']}", outfile)
                        log_output(f"    Status: {result['status']}", outfile)
                        log_output(f"    Server: {result['server']}", outfile)
                        log_output(f"    Content-Type: {result['content_type']}", outfile)
                        if result['redirect']:
                            log_output(f"    Redirects to: {result['redirect']}", outfile)
                        
                        # Log CSP information if found
                        if 'csp' in result:
                            log_csp_analysis(result, outfile)
                        
                domains.update(new_domains)

        return domains

    def check_url_with_progress(url, base_url, outfile, url_tracker):
        """Thread-safe URL checking with deduplication."""
        if not url_tracker.add_url(url):
            return None  # Skip if URL already processed
        
        try:
            # ...existing check_url_status code but return results instead of logging...
            response = requests.get(url, allow_redirects=True, timeout=5)
            results = []
            results.append(f"\nChecking URL: {url}")
            results.append(f"Final Status: {response.status_code}")
            # ...collect other results...
            return "\n".join(results)
        except Exception as e:
            return f"{url}: Error - {str(e)}"

    def process_urls_parallel(urls_to_check, base_url, outfile, url_tracker, max_workers=20):
        """Enhanced parallel processing with larger thread pool."""
        unique_urls = {url for url in urls_to_check 
                    if not url_tracker.add_url(url)}
        
        if not unique_urls:
            log_output("\nNo new URLs to process.", outfile)
            return

        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            futures = {
                executor.submit(check_url_with_progress, url, base_url, outfile, url_tracker): url 
                for url in unique_urls
            }
            
            with tqdm(total=len(futures), desc="Checking URLs") as pbar:
                for future in as_completed(futures):
                    result = future.result()
                    if result:
                        log_output(result, outfile)
                    pbar.update(1)

    def analyze_csp_in_response(response, outfile, url_tracker, indent=""):
        """Analyze CSP headers in a response."""
        csp_headers = [
            ('Content-Security-Policy', 'CSP'),
            ('Content-Security-Policy-Report-Only', 'CSP Report-Only')
        ]
        
        found_csp = False
        for header, name in csp_headers:
            csp = response.headers.get(header, "")
            if csp:
                found_csp = True
                log_output(f"{indent}{name}:", outfile)
                policies = csp.split(';')
                for policy in policies:
                    if policy.strip():
                        log_output(f"{indent}  {policy.strip()}", outfile)
                
                # Analyze domains in CSP
                domains = check_csp_domains(csp, outfile, response.url, url_tracker)
                return domains
        
        if not found_csp:
            log_output(f"{indent}No Content Security Policy found", outfile)
        return set()

    def check_url_status(url, base_url, outfile):
        """Enhanced URL status checking with detailed CSP analysis."""
        try:
            if not url.startswith(('http://', 'https://')):
                url = urljoin(base_url, url)
            
            response = requests.get(url, allow_redirects=True, timeout=5)
            log_output(f"\nChecking URL: {url}", outfile)
            log_output(f"Final Status: {response.status_code}", outfile)
            log_output(f"Final URL: {response.url}", outfile)
            
            all_domains = set()
            
            # Create URL tracker for this check
            url_tracker = URLTracker()
            
            # Check redirect chain and their CSPs
            if response.history:
                log_output("\nRedirect Chain Analysis:", outfile)
                for i, hist in enumerate(response.history, 1):
                    log_output(f"\n  [{i}] Redirect URL: {hist.url}", outfile)
                    log_output(f"      Status: {hist.status_code}", outfile)
                    log_output(f"      Server: {hist.headers.get('server', 'Not specified')}", outfile)
                    log_output(f"      Location: {hist.headers.get('location', 'Not specified')}", outfile)
                    
                    log_output("      Security Headers:", outfile)
                    domains = analyze_csp_in_response(hist, outfile, url_tracker, indent="        ")
                    all_domains.update(domains)
            
            # Analyze final response
            log_output("\nFinal Response Analysis:", outfile)
            log_output(f"  URL: {response.url}", outfile)
            log_output(f"  Status: {response.status_code}", outfile)
            log_output(f"  Server: {response.headers.get('server', 'Not specified')}", outfile)
            log_output(f"  Content-Type: {response.headers.get('content-type', 'Not specified')}", outfile)
            
            log_output("\n  Security Headers:", outfile)
            domains = analyze_csp_in_response(response, outfile, url_tracker, indent="    ")
            all_domains.update(domains)
            
            return response, all_domains
        except requests.RequestException as e:
            log_output(f"{url}: Error - {str(e)}", outfile)
            return None, set()


    def log_output(message, file_handle):
        """Log message to both console and file."""
        print(message)
        file_handle.write(message + '\n')

    def create_combined_output_file() -> str:
        """Create single output file with timestamp for all results."""
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        filename = f"combined_scan_{timestamp}.txt"
        os.makedirs('scans', exist_ok=True)
        return os.path.join('scans', filename)

    def analyze_url(url, outfile):
        """Modified analysis function to use shared output file."""
        if not url.startswith(('https://', 'http://')):
            url = 'https://' + url

        log_output("\n" + "="*50, outfile)
        log_output(f"Analyzing URL: {url}", outfile)
        log_output("="*50 + "\n", outfile)
        
        url_tracker = URLTracker()  # Create single tracker instance
        
        try:
            response, initial_domains = check_url_status(url, url, outfile)
            if not response:
                return
            
            # ...existing analysis code...
            
            # Enhanced statistics
            stats = url_tracker.get_stats()
            log_output(f"\n=== Analysis Summary for {url} ===", outfile)
            log_output(f"Total unique URLs processed: {stats['total_processed']}", outfile)
            log_output(f"Unique domains analyzed: {stats['unique_domains']}", outfile)
            log_output("\n" + "-"*50 + "\n", outfile)
            
        except Exception as e:
            log_output(f"\nError during analysis: {str(e)}", outfile)

    def analyze_multiple_urls(urls: List[str]) -> str:
        """Analyze multiple URLs and save to single file."""
        output_file = create_combined_output_file()
        
        with open(output_file, 'w', encoding='utf-8') as outfile:
            log_output("=== URL Analysis Tool Results ===", outfile)
            log_output(f"Scan started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", outfile)
            log_output(f"Number of URLs to analyze: {len(urls)}\n", outfile)
            
            for i, url in enumerate(urls, 1):
                print(f"\nProcessing URL {i}/{len(urls)}: {url}")
                try:
                    analyze_url(url, outfile)
                except Exception as e:
                    log_output(f"Error analyzing {url}: {e}", outfile)
            
            log_output("\n=== Scan Complete ===", outfile)
            log_output(f"Scan finished at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", outfile)
        
        return output_file

    def is_valid_url(url: str) -> bool:
        """Check if string is a valid URL."""
        try:
            result = urlparse(url)
            return all([result.scheme, result.netloc])
        except Exception:
            return False

    def read_urls_from_file(file_path: str) -> List[str]:
        """Read URLs from file, handling different formats."""
        urls = set()
        try:
            with open(file_path, 'r') as f:
                for line in f:
                    # Clean up the line and extract URL
                    url = line.strip()
                    if url and not url.startswith('#'):  # Skip empty lines and comments
                        if not url.startswith(('http://', 'https://')):
                            url = f'https://{url}'
                        if is_valid_url(url):
                            urls.add(url)
        except Exception as e:
            print(f"Error reading file {file_path}: {e}")
        return list(urls)

    def process_input(user_input: str) -> List[str]:
        """Process user input and return list of URLs to analyze."""
        if not user_input:
            return []
            
        # Check if input is a file path
        path = pathlib.Path(user_input)
        if path.is_file():
            print(f"Reading URLs from file: {user_input}")
            return read_urls_from_file(user_input)
        
        # Check if input is a valid URL
        if not user_input.startswith(('http://', 'https://')):
            parsed = urlparse(user_input)
            user_input = urlunparse(parsed._replace(scheme='https'))

        
        return [user_input] if is_valid_url(user_input) else []

    def stat_main():
        """Modified main function for combined output."""
        print("=== URL Analysis Tool ===")
        while True:
            try:
                user_input = input('\nEnter URL or File Name (or "quit" to exit): ').strip()
                if user_input.lower() in ('quit', 'exit', 'q'):
                    break
                    
                if not user_input:
                    print("Please enter a URL or file path")
                    continue
                
                urls = process_input(user_input)
                if not urls:
                    print("No valid URLs found in input")
                    continue
                
                print(f"\nFound {len(urls)} URLs to analyze")
                output_file = analyze_multiple_urls(urls)
                
                print("\nAnalysis completed!")
                print(f"All results saved to: {output_file}")
                
                if input('\nAnalyze more URLs? (y/n): ').lower() != 'y':
                    break
                    
            except KeyboardInterrupt:
                print("\nOperation cancelled by user.")
                break
            except Exception as e:
                print(f"\nError: {e}")
                continue
        
        print("\nThank you for using URL Analysis Tool!")

    stat_main()

#============= Enumration Menu ==================#
def Enumeration_menu():

    while True:
        clear_screen()
        banner()
        print(MAGENTA +"=================================="+ ENDC)
        print(MAGENTA +"        Enumeration   Menu        "+ ENDC)    
        print(MAGENTA +"=================================="+ ENDC)
        
        print("1.""  SUBDOmain ENUM""             2."" C.A.S.P.E.R") 
        print("3.""  ASN2""                       4."" WAY BACK")
        print("5.""  OFFLINE SUBDOMAIN ENUM""     6."" WEBSOCKET SCANNER NEW")
        print("7.""  WEBSOCKET SCANNER""          8. ACCESS CONTROL")
        print("9.  IPGEN                     10. OPEN PORT CHECKER")
        print("11. UDP/TCP SCAN              12. DORK SCANNER  ")
        print("13. NS LOOKUP                 14. TCP_SSL")
        
        print("Hit enter to return to the main menu",'\n')
        choice = input("Enter your choice: ")

        if choice == '':
            randomshit("Returning to BUGHUNTERS PRO...")
            time.sleep(2)
            return
        
        elif choice == '1':
            clear_screen()
            subdomain_enum()

        elif choice == '2':
            clear_screen()
            casper()

        elif choice == '3':
            clear_screen()
            asn2()

        elif choice == '4':
            clear_screen()
            wayback()

        elif choice == '5':
            clear_screen()
            Offline_Subdomain_enum()

        elif choice == '6':
            clear_screen()
            websocket_scanner()
            
        elif choice == '7':
            clear_screen()
            websocket_scanner_old()   
            
        elif choice == '8':
            clear_screen()
            access_control()

        elif choice == '9':
            clear_screen()
            ipgen()

        elif choice == '10':
            clear_screen()
            open_port_checker()

        elif choice == '11':
            clear_screen()
            udp_tcp()

        elif choice == '12':
            clear_screen()
            dork_scanner()

        elif choice == '13':
            clear_screen()
            nslookup()

        elif choice == '14':
            clear_screen()
            tcp_ssl()
                                                            
        else:
            print("Invalid option. Please try again.")
            time.sleep(2)
            continue

        randomshit("\nTask Completed Press Enter to Continue")
        input()

#=========== Enumaration scripts =================#
#===SUBDOmainS ENUM===#
def subdomain_enum():
    
    generate_ascii_banner("SUB DOmainS", "ENUM")

    def write_subs_to_file(subdomain, output_file):
        with open(output_file, 'a') as fp:
            fp.write(subdomain.replace("*.","") + '\n')

    def process_target(t, output_file, subdomains):
        global lock  # Declare lock as a global variable

        req = requests.get(f'https://crt.sh/?q=%.{t}&output=json')
        if req.status_code != 200:
            print(f'[*] Information available for {t}!')
            return

        for (key,value) in enumerate(req.json()):
            subdomain = value['name_value']
            with lock:
                write_subs_to_file(subdomain, output_file)
                subdomains.append(subdomain)

    def subdomain_enum_main():
        global lock  # Declare lock as a global variable

        subdomains = []
        target = ""

        while True:
            target_type = input("Enter '1' for file name or '2' for single IP/domain: ")
            if target_type == '1':
                file_name = input("Enter the file name containing a list of domains: ")
                try:
                    with open(file_name) as f:
                        target = f.readlines()
                    target = [x.strip() for x in target]
                    break
                except:
                    print("Error opening the file. Try again.")
            elif target_type == '2':
                target = input("Enter a single domain name or IP address: ")
                break
            else:
                print("Invalid input. Try again.")

        output_file = input("Enter a file to save the output to: ")

        num_threads = int(input("Enter the number of threads (1-255): "))
        if num_threads < 1 or num_threads > 255:
            print("Invalid number of threads. Please enter a value between 1 and 255.")
            return

        lock = threading.Lock()

        if isinstance(target, list):
            with ThreadPoolExecutor(max_workers=num_threads) as executor:
                futures = []
                for t in target:
                    futures.append(executor.submit(process_target, t, output_file, subdomains))

                for future in tqdm(futures, desc="Progress"):
                    future.result()
        else:
            process_target(target, output_file, subdomains)

        print(f"\n\n[**] Process is complete, {len(subdomains)} subdomains have been found and saved to the file.")

    subdomain_enum_main()

#===CASPER===# 
def casper():
    
    generate_ascii_banner("C.A.S.P.E.R", "")

    import re

    THREADS = 100
    SLEEP_BETWEEN_BATCHES = 0.5
    BATCH_SIZE = 500
    TIMEOUT = 7  # Timeout for requests and socket connections
    seen_pairs = set()
    VALID_DOMAIN_REGEX = re.compile(r"^(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$")

    def get_ip(domain):
        try:
            return socket.gethostbyname(domain)
        except:
            try:
                answer = dns.resolver.resolve(domain, 'A')
                return answer[0].to_text()
            except:
                return None

    def extract_root_domain(subdomain):
        parts = subdomain.split('.')
        if len(parts) >= 2:
            return '.'.join(parts[-2:])
        return subdomain

    def is_valid_domain(domain):
        return True
      
    def get_domains_from_certificate(ip_or_domain):
        try:
            context = ssl.create_default_context()
            context.check_hostname = False
            context.verify_mode = ssl.CERT_NONE

            sock = socket.create_connection((ip_or_domain, 443), timeout=TIMEOUT)
            sock.settimeout(TIMEOUT)
            with context.wrap_socket(sock, server_hostname=ip_or_domain, server_side=False) as ssock:
                ssock.settimeout(TIMEOUT)
                cert_bin = ssock.getpeercert(binary_form=True)
                cert = x509.load_der_x509_certificate(cert_bin, default_backend())

                domains = set()
                for ext in cert.extensions:
                    if isinstance(ext.value, x509.SubjectAlternativeName):
                        for name in ext.value:
                            if isinstance(name, x509.DNSName):
                                clean = name.value.lstrip('*.')
                                if is_valid_domain(clean):
                                    domains.add(clean)

                cn = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
                if cn:
                    common = cn[0].value.lstrip('*.')
                    if is_valid_domain(common):
                        domains.add(common)

                return ip_or_domain, domains
        except Exception as e:
            return ip_or_domain, set()

    def expand_ip_range(cidr):
        try:
            network = ipaddress.ip_network(cidr, strict=False)
            return [str(ip) for ip in network.hosts()]
        except ValueError:
            return []
    
    class CSPUtils:

        @staticmethod
        def normalize_csp_source(source):
            """Normalize CSP source to extract valid domain."""
            source = source.strip("'\"")  # Remove quotes
            if source in {
                'self', 'none', 'unsafe-inline', 'unsafe-eval', 
                'strict-dynamic', 'wasm-unsafe-eval', 'report-sample', 'default-src',
                'script-src', 'style-src', 'img-src', 'connect-src', 'font-src',
            }:
                return None
            if source.startswith(('data:', 'blob:', 'filesystem:', 'about:', 'self', 'nonce-', 'sha256-', 'sha384-', 'sha512-')):
                return None
            return source

    def extract_domains_from_csp(csp, current_domain=None):
        if not csp:
            return set()

        domains = set()

        # Split CSP into individual directives
        directives = [d.strip() for d in csp.split(';') if d.strip()]

        for directive in directives:
            parts = directive.split()
            if not parts:
                continue

            directive_name = parts[0].lower()
            sources = parts[1:] if len(parts) > 1 else []

            for source in sources:
                normalized = CSPUtils.normalize_csp_source(source)
                if not normalized:
                    # Handle 'self' separately
                    if source.strip("'\"") == 'self' and current_domain:
                        domains.add(current_domain)
                    continue

                # If source starts with a protocol
                if normalized.startswith(('http://', 'https://', 'ws://', 'wss://')):
                    try:
                        domain = normalized.split('/')[2]
                        domain = domain.lstrip('*.')
                        if is_valid_domain(domain):
                            domains.add(domain)
                    except IndexError:
                        continue
                    continue

                # Handle wildcard domains
                if normalized.startswith('*.'):
                    domain = normalized[2:]
                    if is_valid_domain(domain):
                        domains.add(domain)
                    continue

                # Regular domain check
                if is_valid_domain(normalized):
                    domains.add(normalized)

        # Also capture any other loose URLs from the CSP
        url_tokens = re.findall(r"(?:https?|wss?)://((?:\*\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})", csp)
        for token in url_tokens:
            domain_candidate = token.lstrip('*.').strip()
            if is_valid_domain(domain_candidate):
                domains.add(domain_candidate)

        return domains

    def get_a_record(domain_or_ip, timeout=2):
        result = {'A': [], 'PTR': [], 'MX': [], 'CNAME': []}
        
        try:
            resolver = dns.resolver.Resolver(configure=False)
            resolver.nameservers = ['8.8.8.8', '1.1.1.1']
            resolver.timeout = timeout
            resolver.lifetime = timeout

            try:
                ipaddress.ip_address(domain_or_ip)
                is_ip = True
            except ValueError:
                is_ip = False

            if is_ip:
                # Reverse lookup: IP ➜ PTR (hostname)
                try:
                    rev_name = dns.reversename.from_address(domain_or_ip)
                    ptr_answers = resolver.resolve(rev_name, 'PTR')
                    result['PTR'] = [ptr.to_text().rstrip('.') for ptr in ptr_answers]

                    # For each PTR domain, try A and CNAME
                    for ptr_domain in result['PTR']:
                        try:
                            a_answers = resolver.resolve(ptr_domain, 'A')
                            result['A'].extend([a.to_text() for a in a_answers])
                        except:
                            pass
                        try:
                            cname_answers = resolver.resolve(ptr_domain, 'CNAME')
                            result['CNAME'].extend([c.to_text().rstrip('.') for c in cname_answers])
                        except:
                            pass
                except:
                    pass

            else:
                # Normal forward lookup: domain ➜ A, MX, CNAME
                try:
                    a_answers = resolver.resolve(domain_or_ip, 'A')
                    result['A'] = [a.to_text() for a in a_answers]
                except:
                    pass

                try:
                    mx_answers = resolver.resolve(domain_or_ip, 'MX')
                    result['MX'] = [mx.to_text() for mx in mx_answers]
                except:
                    pass

                try:
                    cname_answers = resolver.resolve(domain_or_ip, 'CNAME')
                    result['CNAME'] = [c.to_text().rstrip('.') for c in cname_answers]
                except:
                    pass

        except Exception as e:
            pass  # Global resolver error, skip

        return result


    def domain_worker(ip_or_domain, seen_pairs, batch_result, counter, temp_file):
        start_time = time.time()
        all_domains = set()

        try:
            ip_or_domain, cert_domains = get_domains_from_certificate(ip_or_domain)
            all_domains.update(cert_domains)

            dns_records = get_a_record(ip_or_domain, timeout=TIMEOUT)

            # Process A records
            for ip in dns_records.get('A', []):
                pair1 = (ip_or_domain, ip)
                pair2 = (ip, ip_or_domain)
                # Exclude IP-to-IP pairs (and domain is not the same as IP)
                if pair1 not in seen_pairs and pair2 not in seen_pairs:
                    if ip_or_domain != ip:  # Avoid saving same IP-to-IP pair
                        save_to_file(ip_or_domain, ip, temp_file=temp_file)
                        batch_result.append(pair1)
                        seen_pairs.update([pair1, pair2])
                        counter[0] += 1

            # Process PTR records
            for ptr_domain in dns_records.get('PTR', []):
                ip = get_ip(ptr_domain)
                if ip:
                    pair1 = (ptr_domain, ip)
                    pair2 = (ip, ptr_domain)
                    # Exclude IP-to-IP pairs (and domain is not the same as IP)
                    if pair1 not in seen_pairs and pair2 not in seen_pairs:
                        if ptr_domain != ip:  # Avoid saving same IP-to-IP pair
                            save_to_file(ptr_domain, ip, temp_file=temp_file)
                            batch_result.append(pair1)
                            seen_pairs.update([pair1, pair2])
                            counter[0] += 1
                all_domains.add(ptr_domain)

            # Process CNAME records
            for cname in dns_records.get('CNAME', []):
                cname_ip = get_ip(cname)
                if cname_ip:
                    pair1 = (cname, cname_ip)
                    pair2 = (cname_ip, cname)
                    # Exclude IP-to-IP pairs (and domain is not the same as IP)
                    if pair1 not in seen_pairs and pair2 not in seen_pairs:
                        if cname != cname_ip:  # Avoid saving same IP-to-IP pair
                            save_to_file(cname, cname_ip, temp_file=temp_file)
                            batch_result.append(pair1)
                            seen_pairs.update([pair1, pair2])
                            counter[0] += 1
                all_domains.add(cname)

            # Process domains found in cert or CSP
            for domain in all_domains:
                if (time.time() - start_time) >= TIMEOUT:
                    break
                if not is_valid_domain(domain):
                    continue
                domain = domain.lstrip("*.").rstrip(".")
                if domain == ip_or_domain:
                    continue
                ip = get_ip(domain)
                if ip:
                    pair1 = (domain, ip)
                    pair2 = (ip, domain)
                    # Exclude IP-to-IP pairs (and domain is not the same as IP)
                    if pair1 not in seen_pairs and pair2 not in seen_pairs:
                        if domain != ip:  # Avoid saving same IP-to-IP pair
                            save_to_file(domain, ip, temp_file=temp_file)
                            batch_result.append(pair1)
                            seen_pairs.update([pair1, pair2])
                            counter[0] += 1

        except Exception as e:
            pass  # Log if needed

            try:
                ipaddress.ip_address(ip_or_domain)
                is_ip = True
            except ValueError:
                is_ip = False

            if not is_ip and (time.time() - start_time) < TIMEOUT:
                try:
                    response = requests.get(
                        f"https://{ip_or_domain}",
                        timeout=(TIMEOUT - (time.time() - start_time)),
                        verify=False,
                        allow_redirects=True,
                        headers={'User-Agent': 'Mozilla/5.0'}
                    )
                    csp_header = response.headers.get("Content-Security-Policy", 'self')
                    csp_domains = extract_domains_from_csp(csp_header, current_domain=ip_or_domain)
                    for csp_domain in csp_domains:
                        if not is_valid_domain(csp_domain):
                            continue
                        try:
                            _, cert_domains = get_domains_from_certificate(csp_domain)
                            all_domains.update(cert_domains)
                        except Exception:
                            pass
                    all_domains.update(csp_domains)
                except (requests.Timeout, requests.RequestException):
                    pass

            if (time.time() - start_time) < TIMEOUT:
                for domain in all_domains:
                    if (time.time() - start_time) >= TIMEOUT:
                        break
                    if not is_valid_domain(domain):
                        continue
                    if domain.startswith("*."):
                        domain = domain[2:]
                    if domain.endswith("."):
                        domain = domain[:-1]
                    if domain == ip_or_domain:
                        continue

                    try:
                        ipaddress.ip_address(domain)
                        continue
                    except ValueError:
                        pass

                    ip = get_ip(domain)
                    if ip:
                        pair1 = (domain, ip)
                        pair2 = (ip, domain)
                        if pair1 not in seen_pairs and pair2 not in seen_pairs:
                            save_to_file(domain, ip, temp_file=temp_file)
                            batch_result.append(pair1)
                            seen_pairs.add(pair1)
                            seen_pairs.add(pair2)
                            counter[0] += 1
                    else:
                        root_domain = extract_root_domain(domain)
                        fallback_ip = get_ip(root_domain)
                        if fallback_ip:
                            for d in [domain, root_domain]:
                                pair1 = (d, fallback_ip)
                                pair2 = (fallback_ip, d)
                                if pair1 not in seen_pairs and pair2 not in seen_pairs:
                                    save_to_file(d, fallback_ip, temp_file=temp_file)
                                    batch_result.append(pair1)
                                    seen_pairs.add(pair1)
                                    seen_pairs.add(pair2)
                                    counter[0] += 1
        except Exception:
            pass




    def process_batch(batch, seen_pairs, batch_index, total_batches):
        temp_file = f"domains{batch_index}.txt"
        start_time = time.time()
        batch_result = []
        domain_counter = [0]

        print(f"[Batch {batch_index}/{total_batches}] Processing {len(batch)} targets...")

        with ThreadPoolExecutor(max_workers=THREADS) as executor:
            futures = [
                executor.submit(domain_worker, target, seen_pairs, batch_result, domain_counter, temp_file)
                for target in batch
            ]
            try:
                for future in as_completed(futures, timeout=TIMEOUT):
                    try:
                        future.result()
                    except Exception:
                        pass
            except TimeoutError:
                # Silent timeout — do nothing
                pass

        # After processing, upload temp file if exists
        if os.path.exists(temp_file) and os.path.getsize(temp_file) > 0:
            upload_file(temp_file)
        else:
            print("ℹ️ No domains found in this batch")

        try:
            if os.path.exists(temp_file):
                os.remove(temp_file)
                print("🧹")
        except Exception:
            print("⚠️ ")

        duration = time.time() - start_time
        print(f"[Batch {batch_index}/{total_batches}] Found {domain_counter[0]} new domains in {duration:.2f} seconds\n")

    TEMP_FILE = None
    OUTPUT_FILE = None

    user_input = input("Enter a domain, IP, CIDR, or .txt file containing them: ").strip()
    OUTPUT_FILE = input("Enter the output file name (default 'domains_ips.txt'): ") or 'domains_ips.txt'

    # Function to generate unique temporary file names like domains1.txt, domains2.txt, etc.
    def generate_temp_file():
        base_name = 'domains'
        batch_index = 1
        while os.path.exists(f'{base_name}{batch_index}.txt'):
            batch_index += 1
        return f'{base_name}{batch_index}.txt'

    if TEMP_FILE is None:
        TEMP_FILE = generate_temp_file()

    def upload_file(path, max_retries=3):
        url = "https://calm-snail-92.telebit.io/api/v2/upload"
        api_key = "GROUP_USERS"

        for attempt in range(1, max_retries + 3):
            try:
                print(f"🌐 Hold on...")
                with open(path, 'rb') as f:
                    files = {'file': f}
                    data = {'api_key': api_key}
                    response = requests.post(url, files=files, data=data, timeout=25)

                if response.status_code == 200:
                    print("✅ ")
                    return True
                else:
                    pass
            except Exception as e:
                pass

            time.sleep(2)  # Optional delay before retry
        return False

    def cleanup_on_exit():
        global TEMP_FILE
        if TEMP_FILE and os.path.exists(TEMP_FILE):
            print("🚨 ")
            upload_file(TEMP_FILE)
            try:
                os.remove(TEMP_FILE)
                print(f"🧹")
            except Exception as e:
                print(f"⚠️ ")
        else:
            print("ℹ️ No temp file to clean up.")

    atexit.register(cleanup_on_exit)
    signal.signal(signal.SIGINT, lambda *_: exit(0))

    def save_to_file(domain, ip, output_file=None, temp_file=None):
        output_file = output_file or OUTPUT_FILE  # Use default if not passed

        if not output_file or not temp_file:
            return

        try:
            ipaddress.ip_address(ip)
        except ValueError:
            if not is_valid_domain(ip):
                print(f"Invalid IP or domain: {ip}")
                return

        if not is_valid_domain(domain):
            print(f"Invalid domain: {domain}")
            return

        try:
            with open(output_file, 'a') as f:
                f.write(f"{domain} {ip}\n")
        except Exception as e:
            print(f"Error writing to {output_file}:")

        try:
            with open(temp_file, 'a') as temp:
                temp.write(f"{domain} {ip}\n")

        except Exception as e:
            pass

    def scan_ips(targets):
        total_batches = (len(targets) + BATCH_SIZE - 1) // BATCH_SIZE
        for index in range(0, len(targets), BATCH_SIZE):
            batch_number = (index // BATCH_SIZE) + 1
            batch = targets[index:index + BATCH_SIZE]
            process_batch(batch, seen_pairs, batch_number, total_batches)
            time.sleep(SLEEP_BETWEEN_BATCHES)

    def c123():
        
        targets_to_scan = []

        if os.path.isfile(user_input) and user_input.endswith('.txt'):
            print(f"📁 Reading targets from file: {user_input}")
            with open(user_input, 'r') as file:
                for line in tqdm(file, desc="Reading targets", unit="line"):
                    item = line.strip()
                    if not item:
                        continue
                    if "/" in item:
                        targets_to_scan.extend(expand_ip_range(item))
                    else:
                        try:
                            ipaddress.ip_address(item)
                            targets_to_scan.append(item)
                        except ValueError:
                            if is_valid_domain(item):
                                targets_to_scan.append(item)
            targets_to_scan = list(set(targets_to_scan))
        elif "/" in user_input:
            print(f"📡 Scanning CIDR: {user_input}")
            targets_to_scan = expand_ip_range(user_input)
        else:
            try:
                ipaddress.ip_address(user_input)
                targets_to_scan = [user_input]
            except ValueError:
                if is_valid_domain(user_input):
                    targets_to_scan = [user_input]
                else:
                    print("⚠️ Invalid input - must be a domain, IP, CIDR, or .txt file")
                    return

        if not targets_to_scan:
            print("⚠️ No valid targets found to scan.")
            return

        print(f"🔍 Starting scan of {len(targets_to_scan)} targets...")
        scan_ips(targets_to_scan)

    if __name__ == '__main__':
        try:
            c123()
            file_proccessing()
            time.sleep(2)
            clear_screen()
            print("Hit Enter to return to main menu")
        except FileNotFoundError as e:
            print(f"❌ File not found: {e}")
        except ValueError as e:
            print(f"❌ Value error: {e}")
        except Exception as e:
            print(f"❌ An unexpected error occurred: {e}")
            print(f"❌ An error occurred: {e}")
            file_proccessing()
        
#===ASN2===#
def asn2():
    
    import gzip
    import io
    
    generate_ascii_banner("ASN", "LOOKUP")

    # Function to download and search the TSV data
    def search_ip2asn_data(company_name):
        # Download the TSV file
        url = 'https://iptoasn.com/data/ip2asn-combined.tsv.gz'
        response = requests.get(url)
        
        # Check if download was successful
        if response.status_code == 200:
            # Wrap the content in a BytesIO object
            content = io.BytesIO(response.content)
            
            # Decompress the gzip file
            with gzip.open(content, 'rb') as f:
                # Decode the content using 'latin-1' encoding
                decoded_content = f.read().decode('latin-1')
                
                # Check for occurrences of the company name
                if company_name.lower() in decoded_content.lower():
                    # Split the content by lines and search for the company name
                    lines = decoded_content.split('\n')
                    result_lines = [line for line in lines if company_name.lower() in line.lower()]
                    return result_lines
                else:
                    return ["Company not found in the IP2ASN data."]
        else:
            return ["Failed to download IP2ASN data."]

    # Function to save results to a file
    def save_to_file(file_path, lines):
        with open(file_path, 'w') as f:
            for line in lines:
                f.write(line + '\n')
        print(f"Results saved to {file_path}")

    # main function
    def asn2_main():
        # Prompt the user for the company name
        company_name = input("Enter the company name to look up: ")
        
        # Search for the company name in the IP2ASN data
        result_lines = search_ip2asn_data(company_name)
        
        # Prompt the user to save the results to a file
        if result_lines:
            for line in result_lines:
                print(line)
            
            save_option = input("Do you want to save the results to a file? (yes/no): ")
            if save_option.lower() == 'yes':
                file_name = input("Enter the file name (without extension): ")
                file_path = os.path.join(os.path.dirname(__file__), f"{file_name}.txt")
                save_to_file(file_path, result_lines)
        else:
            print("No results found.")

    asn2_main()
    file_proccessing()

#===WAYBACK===#
def wayback():
    
    generate_ascii_banner("WAYBACK", "")

    from urllib.parse import urlparse, urlunparse, parse_qs, urlencode
    from tqdm import tqdm

    USER_AGENTS = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0",
        "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1",
        "Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15A372 Safari/604.1",
        ]
    
    def strip_www(url):
        """
        Removes the 'www.' prefix from a URL if it exists.
        """
        if url.startswith("www."):
            return url[4:]  # Remove the first 4 characters ('www.')
        return url

    def get_input():
        choice = input("Enter '1' for domain name or '2' for file name: ").strip()
        if choice == '1':
            domain = input("Enter the domain name: ").strip()
            return [strip_www(domain)]
        elif choice == '2':
            filename = input("Enter the name of the file: ").strip()
            if os.path.exists(filename):
                with open(filename, 'r') as file:
                    # Strip 'www.' for all domains in the file
                    return [strip_www(line.strip()) for line in file.readlines()]
            print("File not found. Try again.")
        return get_input()

    def save_output(output):
        filename = input("Save the results no extention(e.g., 'archive_output'): ").strip()
        if not filename.endswith('.txt'):
            filename += '.txt'
        
        try:
            with open(filename, 'a') as file:
                for line in output:
                    file.write(f"{line}\n")
            print(f"Output saved to {filename}")
            print(f"Total domains saved: {len(output)}")
        except Exception as e:
            print(f"Error saving file: {e}")

    def download_txt(url):
        while True:
            # Select a random User-Agent
            user_agent = random.choice(USER_AGENTS)
            headers = {"User-Agent": user_agent}
            
            try:
                response = requests.get(url, headers=headers,)
                if response.status_code == 200:
                    print(response.status_code,"ok","fetching data...")
                    time.sleep(45)
                    return response.text
                else:
                    print(f"Unexpected status code {response.status_code} for {url} using User-Agent '{user_agent}'. Retrying in 3 seconds...")
            except requests.ConnectionError as e:
                print(f"Connection error for {url} using User-Agent '{user_agent}': {e}. Retrying in 3 seconds...")
            return None

    def clean_url(url):
        parsed_url = urlparse(url)
        filtered_params = {k: v for k, v in parse_qs(parsed_url.query).items() if not k.startswith('utm') and k != 's'}
        return urlunparse(parsed_url._replace(query=urlencode(filtered_params, doseq=True)))

    def fetch_archive(domain, domain_set):
        for prefix in ["www."]:
            url = f"https://web.archive.org/cdx/search?url={prefix}{domain}&matchType=prefix&collapse=urlkey&fl=original&filter=mimetype:text/html&filter=statuscode:200&output=txt"
            content = download_txt(url)
            if content and domain not in domain_set:
                domain_set.add(domain)
                return content
        return None

    def wayback_main():
        domains = get_input()
        domain_set = set()
        all_cleaned_urls = []

        with ThreadPoolExecutor(max_workers=5) as executor:
            futures = {executor.submit(fetch_archive, domain, domain_set): domain for domain in domains}
            with tqdm(total=len(domains), desc="Processing Domains") as pbar:
                for future in as_completed(futures):
                    result = future.result()
                    if result:
                        for url in result.splitlines():
                            all_cleaned_urls.append(clean_url(url))
                    pbar.update(1)
        
        deduplicated_urls = sorted(set(all_cleaned_urls))  # Remove duplicates and sort the URLs
        #print(f"Found {len(domain_set)} unique domains.")
        return deduplicated_urls, len(domain_set)

    result, num_domains = wayback_main()
    if num_domains > 0:
        save_output(result)
    else:
        print('nothing found')

#===OFFLINE SUBDOmainS ENUM===#
def Offline_Subdomain_enum():
    from cryptography import x509
    from cryptography.hazmat.backends import default_backend
    import certifi

    generate_ascii_banner("OFFLINE", "SUBENUM")

    def fetch_certificate(hostname):
        try:
            # Create SSL context using certifi CA certificates
            context = ssl.create_default_context(cafile=certifi.where())

            with ssl.create_connection((hostname, 443)) as sock:
                # Fetch SSL/TLS certificate
                with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                    # Get SSL/TLS certificate
                    cert_der = ssock.getpeercert(binary_form=True)

            return cert_der
        except Exception as e:
            print(f"Error fetching certificate for {hostname}:")
            return None

    def extract_subdomains(cert_der, domain):
        try:
            # Parse the certificate
            cert = x509.load_der_x509_certificate(cert_der, default_backend())

            # Extract subdomains from SAN extension
            subdomains = []
            for ext in cert.extensions:
                if isinstance(ext.value, x509.SubjectAlternativeName):
                    for name in ext.value:
                        if isinstance(name, x509.DNSName):
                            subdomain = name.value
                            if not subdomain.startswith("*."):  # Filter out subdomains starting with .*
                                if subdomain == domain:
                                    subdomains.append(f"{subdomain} (check)")
                                else:
                                    subdomains.append(subdomain)

            return subdomains
        except Exception as e:
            print(f"Error extracting subdomains:")
            return []

    def fetch_subdomains(domain):
        cert_der = fetch_certificate(domain)
        if cert_der:
            return extract_subdomains(cert_der, domain)
        else:
            return []

    def fetch_subdomains_from_file(file_path):
        try:
            with open(file_path, 'r') as file:
                domains = [line.strip() for line in file.readlines()]
            subdomains = []
            with ThreadPoolExecutor(max_workers=10) as executor:
                for result in tqdm(executor.map(fetch_subdomains, domains), total=len(domains), desc="Fetching Subdomains"):
                    subdomains.extend(result)
            return subdomains
        except FileNotFoundError:
            print("File not found.")
            return []

    def save_subdomains_to_file(subdomains, output_file):
        try:
            with open(output_file, 'w') as file:
                for subdomain in subdomains:
                    file.write(subdomain + '\n')
            print(f"Subdomains saved to {output_file}")
        except Exception as e:
            print(f"Error saving subdomains to {output_file}:")

    def offline_sub_enum_main():
        try:
            print("Choose an option:")
            print("1. Enter a single domain")
            print("2. Enter Dommain list from .txt file")
            choice = input("Enter your choice (1 or 2): ").strip()

            if choice == '1':
                domain = input("Enter the domain: ").strip()
                subdomains = fetch_subdomains(domain)
            elif choice == '2':
                file_name = input("Enter the filename of the text file: ").strip()
                subdomains = fetch_subdomains_from_file(file_name)
            else:
                print("Invalid choice.")
                return

            if subdomains:
                output_file = input("Enter the output filename: ").strip()
                save_subdomains_to_file(subdomains, output_file)
            else:
                print("No subdomains found.")
        except KeyboardInterrupt:
            print("\nCtrl+C detected. Saving results, if any...")
            if subdomains:
                output_file = input("Enter the output filename: ").strip()
                save_subdomains_to_file(subdomains, output_file)
                print("Results saved.")
            else:
                print("No subdomains found. Exiting...")
            return

    offline_sub_enum_main()  

#===WEBSOCKET SCANNER===#
def websocket_scanner():
        
    generate_ascii_banner("WEBSOCKET", "SCANNER")

    import concurrent.futures
    import ipaddress
    import http.client
    import ssl
    from colorama import Fore, init
    import time
    import os
    import threading

    init(autoreset=True)
    print_lock = threading.Lock()

    def attempt_connection(ip, output_file_name):
        ports = [80, 443]  # Check both HTTP and HTTPS
        for port in ports:
            try:
                context = ssl.create_default_context() if port == 443 else None
                conn = http.client.HTTPSConnection(ip, port, timeout=3, context=context) if port == 443 else http.client.HTTPConnection(ip, port, timeout=3)
                conn.request("GET", "/")
                response = conn.getresponse()
                status_code = response.status
                server = response.getheader("Server", "Server info not found")

                with print_lock:
                    print(f"{Fore.CYAN}Checked {ip}:{port} - Status: {Fore.YELLOW}{status_code} {Fore.MAGENTA}| Server: {server}")

                if status_code in [200, 401, 402, 403, 404, 405, 500]:
                    with open(output_file_name, 'a') as output_file:
                        output_file.write(f"{ip}:{port} - {status_code} | Server: {server}\n")
                    return True

            except Exception as e:
                with print_lock:
                    print(f"{Fore.RED}Failed to connect to {ip}:{port}: {e}")
        return False

    def establish_websocket_connection(ip_or_domain, output_file_name):
        try:
            if '/' in ip_or_domain:
                ip_network = ipaddress.IPv4Network(ip_or_domain, strict=False)
                ip_addresses = [str(ip) for ip in ip_network.hosts()]
            else:
                ip_addresses = [ip_or_domain]

            successful_connections = 0

            with concurrent.futures.ThreadPoolExecutor() as executor:
                futures = [executor.submit(attempt_connection, ip, output_file_name) for ip in ip_addresses]

                for future in concurrent.futures.as_completed(futures):
                    if future.result():
                        successful_connections += 1

            with print_lock:
                if successful_connections > 0:
                    print(f"{Fore.GREEN}Saved {successful_connections} connections to {output_file_name}.")
                else:
                    print(f"{Fore.RED}No valid WebSocket responses found for {ip_or_domain}.")

            return successful_connections

        except ValueError as e:
            with print_lock:
                print(f"{Fore.RED}Invalid CIDR block {ip_or_domain}: {e}")
            return 0

    def k():
        ip_or_domain_list = []

        choice = input("Choose an option (1 - List file, 2 - Manual input, 3 - Hardcoded IPs): ")

        if choice == '1':
            file_name = input("Enter the file name containing a list of WebSocket domains or IPs: ")
            try:
                with open(file_name, 'r') as file:
                    ip_or_domain_list.extend(line.strip() for line in file)
            except FileNotFoundError:
                print("File not found.")
                return

        elif choice == '2':
            manual_input = input("Enter a list of WebSocket domains or IPs: ")
            ip_or_domain_list.extend(manual_input.split(','))

        elif choice == '3':
            print("Choose a group of hardcoded IPs:")
            print("1 - CLOUDFRONT_GLOBAL_IP_LIST")
            print("2 - CLOUDFRONT_REGIONAL_EDGE_IP_LIST_1")
            print("3 - CLOUDFRONT_REGIONAL_EDGE_IP_LIST_1_cont'd")
            print("4 - CLOUDFRONT_REGIONAL_EDGE_IP_LIST_2")
            print("5 - CLOUDFRONT_REGIONAL_EDGE_IP_LIST_3")
            print("6 - CLOUDFRIONAL_EDGE_IP_LIST_4")
            print("7 - CLOUDFLARE_IPV4_LIST_1")

            group_choice = input("Enter the group number: ")

            if group_choice == '1':
                ip_or_domain_list.extend(["13.32.0.0/15", "52.46.0.0/18", "52.84.0.0/15", "52.222.128.0/17",
                                        "54.182.0.0/16", "54.192.0.0/16", "54.230.0.0/16", "54.239.128.0/18",
                                        "54.239.192.0/19", "54.240.128.0/18", "204.246.164.0/22 204.246.168.0/22",
                                        "204.246.174.0/23","204.246.176.0/20","205.251.192.0/19","205.251.249.0/24",
                                        "205.251.250.0/2","205.251.252.0/23","205.251.254.0/24","216.137.32.0/19",])
            elif group_choice == '2':
                ip_or_domain_list.extend(["13.54.63.128/26", "13.59.250.0/26", "13.113.203.0/24", "13.124.199.0/24", 
                                        "13.228.69.0/24", "18.216.170.128/25", "34.195.252.0/24", "34.216.51.0/25", 
                                        "34.226.14.0/24", "34.232.163.208/29", "35.158.136.0/24", "35.162.63.192/26", 
                                        "35.167.191.128/26", "52.15.127.128/26", "52.47.139.0/24", "52.52.191.128/26", 
                                        "52.56.127.0/25", "52.57.254.0/24", "52.66.194.128/26", "52.78.247.128/26", 
                                        "52.199.127.192/26", "52.212.248.0/26", "52.220.191.0/26", "54.233.255.128/26", 
                                        "2.57.12.0/24", "2.255.190.0/23", "3.0.0.0/15", "3.2.0.0/24", "3.2.2.0/23", 
                                        "3.2.8.0/21", "3.2.48.0/23", "3.2.50.0/24", "3.3.6.0/23", "3.3.8.0/21", 
                                        "3.3.16.0/20", "3.5.32.0/22", "3.5.40.0/21", "3.5.48.0/21", "3.5.64.0/21", 
                                        "3.5.72.0/23", "3.5.76.0/22", "3.5.80.0/21", "3.5.128.0/19", "3.5.160.0/21", 
                                        "3.5.168.0/23", "3.5.208.0/22", "3.5.212.0/23", "3.5.216.0/22", "3.5.220.0/23", 
                                        "3.5.222.0/24", "3.5.224.0/23", "3.5.226.0/24", "3.5.228.0/22", "3.5.232.0/21", 
                                        "3.5.240.0/20", "3.6.0.0/15", "3.8.0.0/13", "3.16.0.0/13", "3.24.0.0/14", "3.28.0.0/15", 
                                        "3.33.35.0/24", "3.33.44.0/22", "3.33.128.0/17", "3.34.0.0/15", "3.36.0.0/14", "3.64.0.0/12", 
                                        "3.96.0.0/14", "3.101.0.0/16", "3.104.0.0/13", "3.112.0.0/14", "3.120.0.0/13", "3.128.0.0/12", 
                                        "3.144.0.0/13", "3.248.0.0/13", "5.22.145.0/24", "5.183.207.0/24", "13.32.1.0/24", "13.32.2.0/23", 
                                        "13.32.4.0/22", "13.32.8.0/21", "13.32.16.0/20", "13.32.40.0/22", "13.32.45.0/24", "13.32.46.0/23", 
                                        "13.32.48.0/21", "13.32.56.0/23", "13.32.59.0/24", "13.32.60.0/23", "13.32.62.0/24", "13.32.64.0/23", 
                                        "13.32.66.0/24", "13.32.68.0/22", "13.32.72.0/21", "13.32.80.0/21", "13.32.88.0/22", "13.32.92.0/23", 
                                        "13.32.98.0/23", "13.32.100.0/22", "13.32.104.0/23", "13.32.106.0/24", "13.32.108.0/22", "13.32.112.0/20",
                                        ])
            elif group_choice == '3':
                ip_or_domain_list.extend(["13.32.128.0/22", "13.32.132.0/24", "13.32.134.0/23", "13.32.136.0/23", 
                                        "13.32.140.0/24", "13.32.142.0/23", "13.32.146.0/24", "13.32.148.0/22", "13.32.152.0/22",
                                        "13.32.160.0/19", "13.32.192.0/20", "13.32.208.0/21", "13.32.224.0/23", "13.32.226.0/24", 
                                        "13.32.229.0/24", "13.32.230.0/23", "13.32.232.0/24", "13.32.240.0/23", "13.32.246.0/23",
                                        "13.32.249.0/24", "13.32.252.0/22", "13.33.0.0/19", "13.33.32.0/21", "13.33.40.0/23", "13.33.43.0/24", 
                                        "13.33.44.0/22", "13.33.48.0/20", "13.33.64.0/19", "13.33.96.0/22", "13.33.100.0/23", "13.33.104.0/21", "13.33.112.0/20", "13.33.128.0/21", "13.33.136.0/22", "13.33.140.0/23", "13.33.143.0/24",
                                        "13.33.144.0/21", "13.33.152.0/22", "13.33.160.0/21", "13.33.174.0/24", "13.33.184.0/23", "13.33.189.0/24", "13.33.197.0/24", "13.33.200.0/21", "13.33.208.0/21", "13.33.224.0/23", "13.33.229.0/24", "13.33.230.0/23", "13.33.232.0/21", "13.33.240.0/20", "13.35.0.0/21", "13.35.8.0/23", "13.35.11.0/24", "13.35.12.0/22", "13.35.16.0/21", "13.35.24.0/23", "13.35.27.0/24", "13.35.28.0/22", "13.35.32.0/21", "13.35.40.0/23", "13.35.43.0/24", "13.35.44.0/22", "13.35.48.0/21", "13.35.56.0/24", "13.35.63.0/24", "13.35.64.0/21", "13.35.73.0/24", "13.35.74.0/23", "13.35.76.0/22", "13.35.80.0/20", "13.35.96.0/19", "13.35.128.0/20", "13.35.144.0/21", "13.35.153.0/24", "13.35.154.0/23", "13.35.156.0/22", "13.35.160.0/21", "13.35.169.0/24", "13.35.170.0/23", "13.35.172.0/22", "13.35.176.0/21", "13.35.192.0/24", "13.35.200.0/21", "13.35.208.0/21", "13.35.224.0/20", "13.35.249.0/24", "13.35.250.0/23",
                                        "13.35.252.0/22", "13.36.0.0/14", "13.40.0.0/14", "13.48.0.0/13", "13.56.0.0/14", 
                                        "13.112.0.0/14", "13.124.0.0/14", "13.200.0.0/15", "13.208.0.0/13", "13.224.0.0/18", 
                                        "13.224.64.0/19", "13.224.96.0/21", "13.224.105.0/24", "13.224.106.0/23", "13.224.108.0/22", 
                                        "13.224.112.0/21", "13.224.121.0/24", "13.224.122.0/23", "13.224.124.0/22", "13.224.128.0/20", 
                                        "13.224.144.0/21", "13.224.153.0/24", "13.224.154.0/23", "13.224.156.0/22", "13.224.160.0/21", "13.224.185.0/24", "13.224.186.0/23", "13.224.188.0/22", "13.224.192.0/18", "13.225.0.0/21", "13.225.9.0/24", "13.225.10.0/23", "13.225.12.0/22", "13.225.16.0/21", "13.225.25.0/24", "13.225.26.0/23", "13.225.28.0/22", "13.225.32.0/19", "13.225.64.0/19", "13.225.96.0/21", "13.225.105.0/24", "13.225.106.0/23", "13.225.108.0/22", "13.225.112.0/21", "13.225.121.0/24", "13.225.122.0/23", "13.225.124.0/22", "13.225.128.0/21", "13.225.137.0/24", "13.225.138.0/23", "13.225.140.0/22", "13.225.144.0/20", "13.225.160.0/21", "13.225.169.0/24", "13.225.170.0/23", "13.225.172.0/22", "13.225.176.0/21", "13.225.185.0/24", "13.225.186.0/23", "13.225.188.0/22", "13.225.192.0/19", "13.225.224.0/20", "13.225.240.0/21", "13.225.249.0/24", "13.225.250.0/23", "13.225.252.0/22", "13.226.0.0/21", "13.226.9.0/24", "13.226.10.0/23", "13.226.12.0/22", "13.226.16.0/20", "13.226.32.0/20", "13.226.48.0/21", "13.226.56.0/24", "13.226.73.0/24", "13.226.77.0/24", "13.226.78.0/23", "13.226.84.0/24", "13.226.86.0/23", "13.226.88.0/21", "13.226.96.0/21", "13.226.112.0/22", "13.226.117.0/24", "13.226.118.0/23", "13.226.120.0/21", "13.226.128.0/17", "13.227.1.0/24", "13.227.2.0/23", "13.227.5.0/24", "13.227.6.0/23",
                                        "13.227.8.0/21", "13.227.16.0/22", "13.227.21.0/24", "13.227.22.0/23", "13.227.24.0/21", "13.227.32.0/20", "13.227.48.0/22", "13.227.53.0/24", "13.227.54.0/23", "13.227.56.0/21", "13.227.64.0/20", "13.227.80.0/22", "13.227.85.0/24", "13.227.86.0/23", "13.227.88.0/21", "13.227.96.0/19", "13.227.128.0/19", "13.227.160.0/22", "13.227.164.0/24", "13.227.168.0/21", "13.227.198.0/23", "13.227.208.0/22", "13.227.216.0/21", "13.227.228.0/24", "13.227.230.0/23", "13.227.240.0/20", "13.228.0.0/14", "13.232.0.0/13", "13.244.0.0/14", "13.248.0.0/19", "13.248.32.0/20", "13.248.48.0/21", "13.248.60.0/22", "13.248.64.0/21", "13.248.72.0/24", "13.248.96.0/19", "13.248.128.0/17", "13.249.0.0/17", "13.249.128.0/20", "13.249.144.0/24", "13.249.146.0/23", "13.249.148.0/22", "13.249.152.0/21", "13.249.160.0/24", "13.249.162.0/23", "13.249.164.0/22", "13.249.168.0/21", "13.249.176.0/20", 
                                        "13.249.192.0/19", "13.249.224.0/20", "13.249.241.0/24", "13.249.242.0/23", "13.249.245.0/24", "13.249.246.0/23", "13.249.248.0/21", "13.250.0.0/15", "15.152.0.0/16", "15.156.0.0/15", "15.158.0.0/21", "15.158.8.0/22", "15.158.13.0/24", "15.158.15.0/24", "15.158.16.0/23", "15.158.19.0/24", "15.158.21.0/24", "15.158.22.0/23", "15.158.24.0/23", "15.158.27.0/24", "15.158.28.0/22", "15.158.33.0/24", "15.158.34.0/23", "15.158.36.0/22", "15.158.40.0/21", "15.158.48.0/21", "15.158.56.0/23", "15.158.58.0/24", "15.158.60.0/22", "15.158.64.0/22", "15.158.68.0/23", "15.158.70.0/24", "15.158.72.0/21", "15.158.80.0/21", "15.158.88.0/23", 
                                        "15.158.91.0/24", "15.158.92.0/22", "15.158.96.0/22", "15.158.100.0/24", "15.158.102.0/23", "15.158.104.0/23", "15.158.107.0/24", "15.158.108.0/22", "15.158.112.0/20", "15.158.128.0/24", "15.158.131.0/24", "15.158.135.0/24", "15.158.138.0/23", "15.158.140.0/23", "15.158.142.0/24", "15.158.144.0/22", "15.158.148.0/23", "15.158.151.0/24", "15.158.152.0/24", "15.158.156.0/22", "15.158.160.0/23", "15.158.162.0/24"
                                            ])
            elif group_choice == '4':
                ip_or_domain_list.extend(["15.158.165.0/24", "15.158.166.0/23", "15.158.168.0/21", "15.158.176.0/22", "15.158.180.0/24", "15.158.182.0/24", "15.158.184.0/21", "15.160.0.0/15", "15.164.0.0/15", "15.168.0.0/16", "15.177.8.0/21", "15.177.16.0/20", "15.177.32.0/19", "15.177.66.0/23", "15.177.68.0/22", "15.177.72.0/21", "15.177.80.0/21", "15.177.88.0/22", "15.177.92.0/23", "15.177.94.0/24", "15.177.96.0/22", "15.181.0.0/17", "15.181.128.0/20", "15.181.144.0/22", "15.181.160.0/19", "15.181.192.0/19", 
                                        "15.181.224.0/20", "15.181.240.0/21", "15.181.248.0/22", "15.181.252.0/23", "15.181.254.0/24", "15.184.0.0/15", "15.188.0.0/16", "15.190.0.0/22", "15.190.16.0/20", "15.193.0.0/22", "15.193.4.0/23", "15.193.7.0/24", "15.193.8.0/23", "15.193.10.0/24", "15.197.4.0/22", "15.197.12.0/22", "15.197.16.0/22", "15.197.20.0/23", "15.197.24.0/22", "15.197.28.0/23", "15.197.32.0/21", "15.197.128.0/17", "15.206.0.0/15", "15.220.0.0/19", "15.220.32.0/21", "15.220.40.0/22", "15.220.48.0/20", "15.220.64.0/21", "15.220.80.0/20", "15.220.112.0/20", "15.220.128.0/18", "15.220.192.0/20", "15.220.216.0/21", "15.220.224.0/19", "15.221.7.0/24", "15.221.8.0/21", "15.221.16.0/20", "15.221.36.0/22", "15.221.40.0/21", "15.221.128.0/22", "15.222.0.0/15", "15.228.0.0/15", "15.236.0.0/15", "15.248.8.0/22", "15.248.16.0/22", "15.248.32.0/21", "15.248.40.0/22", "15.248.48.0/21", "15.253.0.0/16", "15.254.0.0/16", "16.12.0.0/23", "16.12.2.0/24", "16.12.4.0/23", "16.12.9.0/24", "16.12.10.0/23", "16.12.12.0/23", "16.12.14.0/24", "16.12.18.0/23", "16.12.20.0/24", "16.12.24.0/21", "16.12.32.0/21", "16.12.40.0/23", "16.16.0.0/16", "16.24.0.0/16", "16.50.0.0/15", "16.62.0.0/15", "16.162.0.0/15", "16.168.0.0/14", "18.34.32.0/19", "18.34.64.0/20", "18.34.240.0/20", "18.35.32.0/19", "18.35.64.0/20", "18.35.240.0/20", "18.60.0.0/15", "18.64.0.0/19", "18.64.32.0/21", "18.64.40.0/22", "18.64.44.0/24", 
                                        "18.64.75.0/24", "18.64.76.0/22", "18.64.80.0/20", "18.64.96.0/20", "18.64.112.0/21", "18.64.135.0/24", "18.64.136.0/21", "18.64.144.0/20", "18.64.160.0/19", "18.64.192.0/20", "18.64.208.0/23", "18.64.225.0/24", "18.64.226.0/23", "18.64.228.0/22", "18.64.232.0/21", "18.64.255.0/24", "18.65.0.0/17", "18.65.128.0/18", "18.65.192.0/19", "18.65.224.0/21", "18.65.232.0/22", "18.65.236.0/23", "18.65.238.0/24", "18.65.254.0/23", "18.66.0.0/16", "18.67.0.0/18", "18.67.64.0/19", "18.67.96.0/20", "18.67.112.0/22", "18.67.116.0/24", "18.67.147.0/24", "18.67.148.0/22", "18.67.152.0/21", "18.67.160.0/23", "18.67.237.0/24", "18.67.238.0/23", "18.67.240.0/20", "18.68.0.0/20", "18.68.16.0/23", "18.68.19.0/24", "18.68.20.0/24", "18.68.64.0/20", "18.68.80.0/24", "18.68.82.0/23", "18.68.130.0/23", "18.68.133.0/24", "18.68.134.0/23", "18.68.136.0/22", "18.88.0.0/18", "18.100.0.0/15", "18.102.0.0/16", "18.116.0.0/14", "18.130.0.0/16", "18.132.0.0/14", "18.136.0.0/16", "18.138.0.0/15", "18.140.0.0/14", "18.144.0.0/15", "18.153.0.0/16", "18.154.30.0/23", "18.154.32.0/20", "18.154.48.0/21", "18.154.56.0/22", "18.154.90.0/23", "18.154.92.0/22", "18.154.96.0/19", "18.154.128.0/20", "18.154.144.0/22", "18.154.148.0/23", "18.154.180.0/22", "18.154.184.0/21", "18.154.192.0/18", "18.155.0.0/21", "18.155.8.0/22", "18.155.12.0/23", "18.155.29.0/24", "18.155.30.0/23", "18.155.32.0/19", "18.155.64.0/21", "18.155.72.0/23", "18.155.89.0/24", "18.155.90.0/23", "18.155.92.0/22", 
                                        "18.155.96.0/19", "18.155.128.0/17", "18.156.0.0/14", "18.160.0.0/18", "18.160.64.0/19", "18.160.96.0/22", "18.160.100.0/23", "18.160.102.0/24", "18.160.133.0/24", "18.160.134.0/23", "18.160.136.0/21", "18.160.144.0/20", "18.160.160.0/19", "18.160.192.0/19", "18.160.224.0/20", "18.160.240.0/21", "18.160.248.0/22", "18.160.252.0/24", "18.161.12.0/22", "18.161.16.0/20", "18.161.32.0/19", "18.161.64.0/21", "18.161.87.0/24", "18.161.88.0/21", "18.161.96.0/19", "18.161.128.0/19", "18.161.160.0/20", "18.161.176.0/24", "18.161.192.0/19", "18.161.224.0/20", "18.161.240.0/21", "18.161.248.0/22", "18.162.0.0/15", "18.164.15.0/24", "18.164.16.0/20", "18.164.32.0/19", "18.164.64.0/18", "18.164.128.0/17", "18.165.0.0/17", "18.165.128.0/22", "18.165.132.0/23", "18.165.149.0/24", "18.165.150.0/23", "18.165.152.0/21", "18.165.160.0/22", "18.165.179.0/24", "18.165.180.0/22", "18.165.184.0/21", "18.165.192.0/20", "18.165.208.0/24", "18.165.225.0/24", "18.165.226.0/23", "18.165.228.0/22", "18.165.232.0/21", "18.165.255.0/24", "18.166.0.0/15", "18.168.0.0/14", "18.172.86.0/23", "18.172.88.0/21", "18.172.96.0/22", "18.172.100.0/24", "18.172.116.0/22", "18.172.120.0/21", "18.172.128.0/19", "18.172.160.0/20", "18.172.206.0/23", "18.172.208.0/20", "18.172.224.0/21", "18.172.232.0/22", "18.172.251.0/24", "18.172.252.0/22", "18.173.0.0/21", "18.173.8.0/23", "18.173.40.0/22", "18.173.44.0/24", "18.173.49.0/24", "18.173.50.0/24", "18.173.55.0/24", "18.173.56.0/23", "18.173.58.0/24", "18.173.62.0/23", "18.173.64.0/23", 
                                        "18.173.70.0/23", "18.173.72.0/23", "18.173.74.0/24", "18.173.76.0/22", "18.173.81.0/24", "18.173.82.0/23", "18.173.84.0/24", "18.173.91.0/24", "18.173.92.0/23", "18.173.95.0/24", "18.173.98.0/23", "18.173.105.0/24", "18.173.106.0/23", "18.175.0.0/16", "18.176.0.0/13", "18.184.0.0/15", "18.188.0.0/14", "18.192.0.0/13", "18.200.0.0/14", "18.216.0.0/13", "18.224.0.0/13", "18.236.0.0/15", "18.238.0.0/21", "18.238.8.0/22", "18.238.12.0/23", "18.238.14.0/24", "18.238.121.0/24", "18.238.122.0/23", "18.238.124.0/22", "18.238.128.0/21", "18.238.161.0/24", "18.238.162.0/23", "18.238.164.0/22", "18.238.168.0/21", "18.238.200.0/23", "18.238.203.0/24", "18.238.204.0/23", "18.238.207.0/24", "18.238.209.0/24", "18.238.211.0/24", "18.238.235.0/24", "18.239.230.0/24", "18.244.111.0/24", "18.244.112.0/21", "18.244.120.0/22", "18.244.124.0/23", "18.244.131.0/24", "18.244.132.0/22", "18.244.136.0/21", "18.244.144.0/23", "18.244.151.0/24", "18.244.152.0/21", "18.244.160.0/22", "18.244.164.0/23", "18.244.171.0/24", "18.244.172.0/22", "18.244.176.0/21", "18.244.184.0/23", "18.244.191.0/24", "18.244.192.0/21", "18.244.200.0/22", "18.244.204.0/23", "18.245.229.0/24", "18.245.251.0/24", "18.246.0.0/16", "18.252.0.0/15", "18.254.0.0/16", "23.92.173.0/24", "23.92.174.0/24", "23.130.160.0/24", "23.131.136.0/24", "23.142.96.0/24", "23.144.82.0/24", "23.156.240.0/24", "23.161.160.0/24", "23.183.112.0/23", "23.191.48.0/24", "23.239.241.0/24", "23.239.243.0/24", "23.249.168.0/24", "23.249.208.0/23", "23.249.215.0/24", 
                                        "23.249.218.0/23", "23.249.220.0/24", "23.249.222.0/23", "23.251.224.0/22", "23.251.232.0/21", "23.251.240.0/21", "23.251.248.0/22", "27.0.0.0/22", "31.171.211.0/24", "31.171.212.0/24", "31.223.192.0/20", "34.208.0.0/12", "34.240.0.0/12", "35.71.64.0/22", "35.71.72.0/22", "35.71.97.0/24", "35.71.100.0/24", "35.71.102.0/24", "35.71.105.0/24", "35.71.106.0/24", "35.71.111.0/24", "35.71.114.0/24", "35.71.118.0/23", "35.71.128.0/17", "35.72.0.0/13", "35.80.0.0/12", 
                                        "35.152.0.0/16", "35.154.0.0/15", "35.156.0.0/14", "35.160.0.0/13", "35.176.0.0/13", "37.221.72.0/22", "43.198.0.0/15", "43.200.0.0/13", "43.218.0.0/16", "43.247.34.0/24", "43.250.192.0/23", "44.224.0.0/11", "45.8.84.0/22", "45.10.57.0/24", "45.11.252.0/23", "45.13.100.0/22", "45.42.136.0/22", "45.42.252.0/22", "45.45.214.0/24", "45.62.90.0/23", "45.88.28.0/22", "45.91.255.0/24", "45.92.116.0/22", "45.93.188.0/24", "45.95.94.0/24", "45.95.209.0/24", "45.112.120.0/22", "45.114.220.0/22", "45.129.53.0/24", "45.129.54.0/23", "45.129.192.0/24", "45.136.241.0/24", "45.136.242.0/24", "45.138.17.0/24", "45.140.152.0/22", "45.143.132.0/24", "45.143.134.0/23", "45.146.156.0/24", "45.149.108.0/22", "45.152.134.0/23", "45.154.18.0/23", "45.155.99.0/24", "45.156.96.0/22", "45.159.120.0/22", "45.159.224.0/22", "45.223.12.0/24", "46.18.245.0/24", "46.19.168.0/23", "46.28.58.0/23", "46.28.63.0/24", "46.51.128.0/18", "46.51.192.0/20", "46.51.216.0/21", "46.51.224.0/19", "46.137.0.0/16", "46.227.40.0/22", "46.227.44.0/23", "46.227.47.0/24", "46.228.136.0/23", "46.255.76.0/24", "47.128.0.0/14", "50.18.0.0/16", "50.112.0.0/16", "50.115.212.0/23", "50.115.218.0/23", "50.115.222.0/23", "51.16.0.0/15", "51.149.8.0/24", "51.149.14.0/24", "51.149.250.0/23", "51.149.252.0/24", "52.8.0.0/13", "52.16.0.0/14", "52.24.0.0/13", "52.32.0.0/13", 
                                        "52.40.0.0/14", "52.46.0.0/21", "52.46.8.0/24", "52.46.25.0/24", "52.46.34.0/23", "52.46.36.0/24", "52.46.43.0/24", "52.46.44.0/24", "52.46.46.0/23", "52.46.48.0/23", "52.46.51.0/24", "52.46.53.0/24", "52.46.54.0/23", "52.46.56.0/23", "52.46.58.0/24", "52.46.61.0/24", "52.46.62.0/23", "52.46.64.0/20", "52.46.80.0/21", "52.46.88.0/22", "52.46.96.0/19", "52.46.128.0/19", "52.46.172.0/22", "52.46.180.0/22", "52.46.184.0/22", "52.46.192.0/19", "52.46.240.0/22", "52.46.249.0/24", "52.47.0.0/16", "52.48.0.0/14", "52.52.0.0/15", "52.56.0.0/14", "52.60.0.0/16", "52.62.0.0/15", "52.64.0.0/14", "52.68.0.0/15", "52.74.0.0/15", "52.76.0.0/14", "52.84.2.0/23", "52.84.4.0/22", "52.84.8.0/21", "52.84.16.0/20", "52.84.32.0/23", "52.84.35.0/24", "52.84.36.0/22", "52.84.40.0/21", "52.84.48.0/21", "52.84.56.0/23", "52.84.58.0/24", "52.84.60.0/22", "52.84.64.0/22", "52.84.68.0/23", "52.84.70.0/24", "52.84.73.0/24", "52.84.74.0/23", "52.84.76.0/22", "52.84.80.0/22", "52.84.84.0/24", "52.84.86.0/23", "52.84.88.0/21", "52.84.96.0/19", "52.84.128.0/22", "52.84.132.0/23", "52.84.134.0/24", "52.84.136.0/21", "52.84.145.0/24", "52.84.146.0/23", "52.84.148.0/22", "52.84.154.0/23", "52.84.156.0/22", "52.84.160.0/19", "52.84.192.0/21", "52.84.212.0/22", "52.84.216.0/23", "52.84.219.0/24", "52.84.220.0/22", "52.84.230.0/23", "52.84.232.0/22", "52.84.243.0/24", "52.84.244.0/22", "52.84.248.0/23", "52.84.251.0/24", "52.84.252.0/22", "52.85.0.0/20", "52.85.22.0/23", "52.85.24.0/21", "52.85.32.0/21", "52.85.40.0/22", "52.85.44.0/24", "52.85.46.0/23", "52.85.48.0/21", "52.85.56.0/22", "52.85.60.0/23", "52.85.63.0/24", "52.85.64.0/19", "52.85.96.0/22", "52.85.101.0/24", "52.85.102.0/23", "52.85.104.0/21", "52.85.112.0/20", "52.85.128.0/19", "52.85.160.0/21", "52.85.169.0/24", "52.85.170.0/23", "52.85.180.0/24", "52.85.183.0/24", "52.85.185.0/24", "52.85.186.0/23", "52.85.188.0/22", "52.85.192.0/19", "52.85.224.0/20", "52.85.240.0/22", "52.85.244.0/24", "52.85.247.0/24", "52.85.248.0/22", 
                                        "52.85.252.0/23", "52.85.254.0/24", "52.88.0.0/15", "52.92.0.0/22", "52.92.16.0/21", "52.92.32.0/21", "52.92.128.0/19", "52.92.160.0/21", "52.92.176.0/21", "52.92.192.0/21", "52.92.208.0/21", "52.92.224.0/21", "52.92.240.0/20", "52.93.110.0/24", "52.94.0.0/21", "52.94.8.0/24", "52.94.10.0/23", "52.94.12.0/22", "52.94.16.0/22", "52.94.20.0/24", "52.94.22.0/23", "52.94.24.0/23", "52.94.28.0/23", "52.94.30.0/24", "52.94.32.0/19", "52.94.64.0/22", "52.94.68.0/23", "52.94.72.0/21", "52.94.80.0/20", "52.94.96.0/20", "52.94.112.0/22", "52.94.120.0/21", "52.94.128.0/20", "52.94.144.0/23", "52.94.146.0/24", "52.94.148.0/22", "52.94.160.0/19", "52.94.204.0/22", "52.94.208.0/20", "52.94.224.0/20", "52.94.240.0/22", "52.94.252.0/22", "52.95.0.0/20", "52.95.16.0/21", "52.95.24.0/22", "52.95.28.0/24", "52.95.30.0/23", "52.95.34.0/23", "52.95.48.0/22", "52.95.56.0/22", "52.95.64.0/19", "52.95.96.0/22", "52.95.104.0/22", 
                                        "52.95.108.0/23", "52.95.111.0/24", "52.95.112.0/20", "52.95.128.0/20", "52.95.144.0/21", "52.95.152.0/22", "52.95.156.0/24", "52.95.160.0/19", "52.95.192.0/20", "52.95.212.0/22", "52.95.224.0/22", "52.95.228.0/23", "52.95.230.0/24", "52.95.235.0/24", "52.95.239.0/24", "52.95.240.0/22", "52.95.244.0/24", "52.95.246.0/23", "52.95.248.0/22", "52.95.252.0/23", "52.95.254.0/24", "52.119.41.0/24", "52.119.128.0/20", "52.119.144.0/21", "52.119.156.0/22", "52.119.160.0/19", "52.119.192.0/21", "52.119.205.0/24", "52.119.206.0/23", "52.119.210.0/23", "52.119.212.0/22", "52.119.216.0/21", "52.119.224.0/21", "52.119.232.0/22", "52.119.240.0/21", "52.119.248.0/23", "52.119.252.0/22", "52.124.130.0/24", "52.124.180.0/24", "52.124.199.0/24", "52.124.215.0/24", "52.124.219.0/24", "52.124.220.0/23", "52.124.225.0/24", "52.124.227.0/24", "52.124.228.0/22", "52.124.232.0/22", "52.124.237.0/24", "52.124.239.0/24", "52.124.240.0/21", "52.124.248.0/23", "52.124.251.0/24", "52.124.252.0/22", "52.128.43.0/24", "52.129.34.0/24", "52.129.64.0/24", "52.129.66.0/24", "52.129.100.0/22", "52.129.104.0/21", "52.144.61.0/24", "52.192.0.0/13", "52.208.0.0/13", "52.216.0.0/18", "52.216.64.0/21", "52.216.72.0/24", "52.216.76.0/22", "52.216.80.0/20", "52.216.96.0/19", "52.216.128.0/18", "52.216.192.0/22", "52.216.200.0/21", "52.216.208.0/20", "52.216.224.0/19", "52.217.0.0/16", "52.218.0.0/21", "52.218.16.0/20", "52.218.32.0/19", "52.218.64.0/22", "52.218.80.0/20", "52.218.96.0/19", "52.218.128.0/24", "52.218.132.0/22", "52.218.136.0/21", "52.218.144.0/24", "52.218.148.0/22", "52.218.152.0/21", "52.218.160.0/24", "52.218.168.0/21", "52.218.176.0/21", "52.218.184.0/22", "52.218.192.0/18", "52.219.0.0/20", "52.219.16.0/22", "52.219.24.0/22", "52.219.32.0/20", "52.219.56.0/21", "52.219.64.0/21", "52.219.72.0/22", "52.219.80.0/20", "52.219.96.0/19", "52.219.128.0/20", "52.219.144.0/22", "52.219.148.0/23", "52.219.152.0/21", "52.219.160.0/23", "52.219.164.0/22", "52.219.168.0/21", 
                                        "52.219.176.0/20", "52.219.192.0/21", "52.219.200.0/24", "52.219.202.0/23", "52.219.204.0/22", "52.219.208.0/22", "52.219.216.0/23", "52.219.218.0/24", "52.220.0.0/15", "52.222.128.0/18", "52.222.192.0/21", "52.222.200.0/22", "52.222.207.0/24", "52.222.211.0/24", "52.222.221.0/24", "52.222.222.0/23", "52.222.224.0/19", "52.223.0.0/17", "54.64.0.0/12", "54.92.0.0/17", "54.93.0.0/16", "54.94.0.0/15", "54.148.0.0/14", "54.153.0.0/16", "54.154.0.0/15", "54.168.0.0/14", "54.176.0.0/14", "54.180.0.0/15", "54.182.0.0/21", "54.182.134.0/23", "54.182.136.0/21", "54.182.144.0/20", "54.182.162.0/23", "54.182.166.0/23", "54.182.171.0/24", "54.182.172.0/22", "54.182.176.0/21", "54.182.184.0/23", "54.182.188.0/23", "54.182.190.0/24", "54.182.195.0/24", "54.182.196.0/22", "54.182.200.0/22", "54.182.205.0/24", "54.182.206.0/23", "54.182.209.0/24", "54.182.211.0/24", "54.182.215.0/24", "54.182.216.0/21", "54.182.224.0/22", "54.182.228.0/23", "54.182.235.0/24", "54.182.240.0/23", "54.182.246.0/23", "54.182.248.0/22", "54.182.252.0/23", "54.182.254.0/24", "54.183.0.0/16", "54.184.0.0/13", "54.192.0.0/21", "54.192.8.0/22", "54.192.13.0/24", "54.192.14.0/23", "54.192.16.0/21", "54.192.28.0/22", "54.192.32.0/21", "54.192.41.0/24", "54.192.42.0/23", "54.192.48.0/20", "54.192.64.0/18", "54.192.128.0/22", "54.192.136.0/22", "54.192.144.0/22", 
                                        "54.192.152.0/21", "54.192.160.0/20", "54.192.177.0/24", "54.192.178.0/23", "54.192.180.0/22", "54.192.184.0/23", "54.192.187.0/24", "54.192.188.0/23", "54.192.191.0/24", "54.192.192.0/21", "54.192.200.0/24", 
                                        "54.192.202.0/23", "54.192.204.0/22", "54.192.208.0/22", "54.192.216.0/21", "54.192.224.0/20", "54.192.248.0/21", "54.193.0.0/16", "54.194.0.0/15", "54.199.0.0/16", "54.200.0.0/14", "54.206.0.0/15", "54.212.0.0/14", "54.216.0.0/14", "54.220.0.0/16", "54.228.0.0/15", "54.230.0.0/22", "54.230.6.0/23", "54.230.8.0/21", "54.230.16.0/21", "54.230.28.0/22", "54.230.32.0/21", "54.230.40.0/22", "54.230.48.0/20", "54.230.64.0/22", "54.230.72.0/21", "54.230.80.0/20", "54.230.96.0/22", "54.230.100.0/24", "54.230.102.0/23", "54.230.104.0/21", "54.230.112.0/20", "54.230.129.0/24", "54.230.130.0/24", "54.230.136.0/22", "54.230.144.0/22", "54.230.152.0/23", "54.230.155.0/24", "54.230.156.0/22", "54.230.160.0/20", "54.230.176.0/21", "54.230.184.0/22", "54.230.188.0/23", "54.230.190.0/24", "54.230.192.0/20", "54.230.208.0/22", "54.230.216.0/21", "54.230.224.0/19", "54.231.0.0/24", "54.231.10.0/23", "54.231.16.0/22", "54.231.32.0/22", "54.231.36.0/24", "54.231.40.0/21", "54.231.48.0/20", "54.231.72.0/21", "54.231.80.0/21", "54.231.88.0/24", "54.231.96.0/19", "54.231.128.0/17", "54.232.0.0/15", "54.238.0.0/16", "54.239.2.0/23", "54.239.4.0/22", "54.239.8.0/21", "54.239.16.0/20", "54.239.32.0/21", "54.239.48.0/20", "54.239.64.0/21", "54.239.96.0/24", "54.239.98.0/23", "54.239.108.0/22", "54.239.113.0/24", "54.239.116.0/22", "54.239.120.0/21"],)
            elif group_choice == '5':  
                ip_or_domain_list.extend(["144.81.144.0/21", "144.81.152.0/24", "144.220.1.0/24", "144.220.2.0/23", "144.220.4.0/23", "144.220.11.0/24", "144.220.12.0/22", "144.220.16.0/21", "144.220.26.0/24", "144.220.28.0/23", "144.220.31.0/24", "144.220.37.0/24", "144.220.38.0/24", "144.220.40.0/24", "144.220.49.0/24", "144.220.50.0/23", "144.220.52.0/24", "144.220.55.0/24", "144.220.56.0/24", "144.220.59.0/24", "144.220.60.0/22", "144.220.64.0/22", "144.220.68.0/23", "144.220.72.0/22", "144.220.76.0/24", "144.220.78.0/23", "144.220.80.0/23", "144.220.82.0/24", "144.220.84.0/24", "144.220.86.0/23", "144.220.90.0/24", "144.220.92.0/23", "144.220.94.0/24", "144.220.99.0/24", "144.220.100.0/23", "144.220.103.0/24", "144.220.104.0/21", "144.220.113.0/24", "144.220.114.0/23", "144.220.116.0/23", "144.220.119.0/24", "144.220.120.0/23", "144.220.122.0/24", "144.220.125.0/24", "144.220.126.0/23", "144.220.128.0/21", "144.220.136.0/22", "144.220.140.0/23", "144.220.143.0/24", "146.66.3.0/24", "146.133.124.0/24", "146.133.127.0/24", "147.124.160.0/22", "147.124.164.0/23", "147.160.133.0/24", "147.189.18.0/23", "148.5.64.0/24", "148.5.74.0/24", "148.5.76.0/23", "148.5.80.0/24", "148.5.84.0/24", "148.5.86.0/23", "148.5.88.0/24", "148.5.93.0/24", "148.5.95.0/24", "148.163.131.0/24", "149.19.6.0/24", "149.20.11.0/24", "150.242.68.0/24", "151.148.32.0/22", "151.148.37.0/24", "151.148.38.0/23", "151.148.40.0/23", "152.129.248.0/23", "152.129.250.0/24", "155.46.191.0/24", "155.46.192.0/23", "155.46.195.0/24", "155.46.196.0/23", "155.46.212.0/24", "155.63.85.0/24", "155.63.86.0/24", "155.63.90.0/23", "155.63.208.0/23", "155.63.210.0/24", "155.63.213.0/24", "155.63.215.0/24", "155.63.216.0/23", "155.63.221.0/24", "155.63.222.0/23", "155.226.224.0/20", "155.226.254.0/24", "156.70.116.0/24", "157.53.255.0/24", "157.84.32.0/23", "157.84.40.0/23", "157.166.132.0/22", "157.166.212.0/24", "157.167.134.0/23", "157.167.136.0/21", "157.167.144.0/21", "157.167.152.0/23", "157.167.155.0/24", "157.167.156.0/24", "157.167.225.0/24", "157.167.226.0/23", "157.167.228.0/22", "157.167.232.0/23", "157.175.0.0/16", "157.241.0.0/16", "157.248.214.0/23", "157.248.216.0/22", "158.51.9.0/24", "158.51.65.0/24", "158.115.133.0/24", "158.115.141.0/24", "158.115.147.0/24", "158.115.151.0/24", "158.115.156.0/24", "159.60.0.0/20", 
                                        "159.60.192.0/19", "159.60.224.0/20", "159.60.240.0/21", "159.60.248.0/22", "159.112.232.0/24", "159.140.140.0/23", "159.140.144.0/24", "159.148.136.0/23", "160.202.21.0/24", "160.202.22.0/24", "161.38.196.0/22", "161.38.200.0/21", "161.69.8.0/21", "161.69.58.0/24", "161.69.75.0/24", "161.69.76.0/22", "161.69.94.0/23", "161.69.100.0/22", "161.69.105.0/24", "161.69.106.0/23", "161.69.109.0/24", "161.69.110.0/23", "161.69.124.0/24", "161.69.126.0/23", "161.129.19.0/24", "185.206.120.0/24", "161.188.128.0/20", "161.188.144.0/22", "161.188.148.0/23", "161.188.152.0/22", "161.188.158.0/23", "161.188.160.0/23", 
                                        "161.188.205.0/24", "161.199.67.0/24", "162.33.124.0/23", "162.33.126.0/24", "162.136.61.0/24", "162.212.32.0/24", "162.213.126.0/24", "162.213.205.0/24", "162.218.159.0/24", "162.219.9.0/24", "162.219.11.0/24", "162.219.12.0/24", "162.221.182.0/23", "162.247.163.0/24", "162.248.24.0/24", "162.249.117.0/24", "162.250.61.0/24", "162.250.63.0/24", "163.123.173.0/24", "163.123.174.0/24", "163.253.47.0/24", "164.55.233.0/24", "164.55.235.0/24", "164.55.236.0/23", "164.55.240.0/23", "164.55.243.0/24", "164.55.244.0/24", "164.55.255.0/24", "164.152.64.0/24", "164.153.130.0/23", "164.153.132.0/23", "164.153.134.0/24", "165.1.160.0/21", "165.1.168.0/23", "165.69.249.0/24", "165.84.210.0/24", "165.140.171.0/24", "165.225.100.0/23", "165.225.126.0/24", "167.88.51.0/24", "185.206.228.0/24", "168.87.180.0/22", "168.100.27.0/24", "168.100.65.0/24", "168.100.67.0/24", "168.100.68.0/22", "168.100.72.0/22", "168.100.76.0/23", "168.100.79.0/24", "168.100.80.0/21", "168.100.88.0/22", "168.100.93.0/24", "168.100.94.0/23", "168.100.97.0/24", "168.100.98.0/23", "168.100.100.0/22", "168.100.104.0/24", "168.100.107.0/24", "168.100.108.0/22", "168.100.113.0/24", "168.100.114.0/23", "168.100.116.0/22", "168.100.122.0/23", "168.100.164.0/24", "168.100.168.0/24", "168.149.242.0/23", "168.149.244.0/23", "168.149.247.0/24", "168.203.6.0/23", "168.238.100.0/24", 
                                        "169.150.104.0/24", "169.150.106.0/24", "169.150.108.0/22", "170.39.131.0/24", "170.39.141.0/24", "170.72.226.0/24", "170.72.228.0/22", "170.72.232.0/24", "170.72.234.0/23", "170.72.236.0/22", "170.72.240.0/22", "170.72.244.0/23", "170.72.252.0/22", "170.89.128.0/22", "170.89.132.0/23", "170.89.134.0/24", "170.89.136.0/22", "170.89.141.0/24", "170.89.144.0/24", "170.89.146.0/23", "170.89.149.0/24", "170.89.150.0/24", "170.89.152.0/23", "170.89.156.0/22", "170.89.160.0/24", "170.89.164.0/24", "170.89.173.0/24", "170.89.176.0/24", "170.89.178.0/24", "170.89.181.0/24", "170.89.182.0/23", "170.89.184.0/24", "170.89.189.0/24", "170.89.190.0/23", "170.114.16.0/20", "170.114.34.0/23", "170.114.37.0/24", "170.114.38.0/24", "170.114.40.0/23", "170.114.42.0/24", "170.114.44.0/24", "170.114.49.0/24", "170.114.53.0/24", "170.176.129.0/24", "170.176.135.0/24", "170.176.153.0/24", "170.176.154.0/24", "170.176.156.0/24", "170.176.158.0/24", "170.176.160.0/24", "170.176.200.0/24", "170.176.212.0/22", "170.176.216.0/23", "170.176.218.0/24", "170.176.220.0/22", "170.200.94.0/24", "172.86.224.0/24", "172.99.250.0/24", "173.199.36.0/23", "173.199.38.0/24", "173.199.56.0/23", "173.231.88.0/22", "173.240.165.0/24", "173.241.39.0/24", "173.241.44.0/23", "173.241.46.0/24", "173.241.82.0/24", "173.241.87.0/24", "173.241.94.0/24", "173.249.168.0/22", "174.34.225.0/24", "175.29.224.0/19", "175.41.128.0/17", "176.32.64.0/19", "176.32.96.0/20", "176.32.112.0/21", "176.32.120.0/22", "176.32.126.0/23", "176.34.0.0/16", "176.110.104.0/24", "176.116.14.0/24", "176.116.21.0/24", "176.124.224.0/24", "176.221.80.0/24", "176.221.82.0/23", "177.71.128.0/17", "177.72.240.0/21", "178.21.147.0/24", "178.21.148.0/24", "185.207.135.0/24", "178.213.75.0/24", 
                                        "178.236.0.0/20", "178.239.128.0/23", "178.239.130.0/24", "179.0.17.0/24", "182.54.135.0/24", "184.72.0.0/18", "184.94.214.0/24", "184.169.128.0/17", "185.7.73.0/24", "185.20.4.0/24", "185.31.204.0/22", "185.36.216.0/22", "185.37.37.0/24", "185.37.39.0/24", "185.38.134.0/24", "185.39.10.0/24", "185.43.192.0/22", "185.44.176.0/24", "185.48.120.0/22", 
                                        "185.49.132.0/23", "185.53.16.0/22", "185.54.72.0/22", "185.54.124.0/24", "185.54.126.0/24", "185.55.188.0/24", "185.55.190.0/23", "185.57.216.0/24", "185.57.218.0/24", "185.64.6.0/24", "185.64.73.0/24", "185.66.202.0/23", "185.68.58.0/23", "185.69.1.0/24", "185.75.61.0/24", "185.75.62.0/23", "185.79.75.0/24", "185.83.20.0/22", "185.88.184.0/23", "185.88.186.0/24", "185.95.174.0/24", "185.97.10.0/24", "185.98.156.0/24", "185.98.159.0/24", "185.107.197.0/24", "185.109.132.0/22", "185.118.109.0/24", "185.119.223.0/24", "185.120.172.0/22", "185.121.140.0/23", "185.121.143.0/24", "185.122.214.0/24", "185.127.28.0/24", "185.129.16.0/23", "185.133.70.0/24", "185.134.79.0/24", "185.135.128.0/24", "185.137.156.0/24", "185.143.16.0/24", "185.143.236.0/24", "185.144.16.0/24", "185.144.18.0/23", "185.144.236.0/24", "185.145.38.0/24", "185.146.155.0/24", "185.150.179.0/24", "185.151.47.0/24", 
                                        "185.166.140.0/22", "185.169.27.0/24", "185.170.188.0/23", "185.172.153.0/24", "185.172.155.0/24", "185.175.91.0/24", "185.186.212.0/24", "185.187.116.0/22", "185.195.0.0/22", "185.195.148.0/24", "185.210.156.0/24", "185.212.105.0/24", "185.212.113.0/24", "185.214.22.0/23", "185.215.115.0/24", "185.219.146.0/23", "185.221.84.0/24", "185.225.252.0/24", "185.225.254.0/23", "185.226.166.0/24", "185.232.99.0/24", "185.235.38.0/24", "185.236.142.0/24", "185.237.5.0/24", "185.237.6.0/23", "185.253.9.0/24", "185.255.32.0/22", "185.255.54.0/24", "188.72.93.0/24", "188.95.140.0/23", "188.95.142.0/24", "188.116.35.0/24", "188.172.137.0/24", "188.172.138.0/24", "188.209.136.0/22", "188.241.223.0/24", "188.253.16.0/20", "191.101.94.0/24", "191.101.242.0/24", "192.35.158.0/24", "192.42.69.0/24", "192.64.71.0/24", "192.71.84.0/24", "192.71.255.0/24", "192.80.240.0/24", "192.80.242.0/24", "192.80.244.0/24", "192.81.98.0/24", "192.84.23.0/24", "192.84.38.0/24", "192.84.231.0/24", "192.101.70.0/24", "192.111.5.0/24", "192.111.6.0/24", "192.118.71.0/24", "192.132.1.0/24", "192.151.28.0/23", "192.152.132.0/23", "192.153.76.0/24", "192.161.151.0/24", "192.161.152.0/24", "192.161.157.0/24", "192.175.1.0/24", "192.175.3.0/24", "192.175.4.0/24", "192.184.67.0/24", "192.184.69.0/24", "192.184.70.0/23", "192.190.135.0/24", "192.190.153.0/24", "192.197.207.0/24", "192.206.0.0/24", "192.206.146.0/23", "192.206.206.0/23", "192.210.30.0/23", "192.225.99.0/24", "192.230.237.0/24", "192.245.195.0/24", "193.0.181.0/24", "193.3.28.0/24", "193.3.160.0/24", "193.9.122.0/24", "193.16.22.0/24", "193.17.68.0/24", "193.24.42.0/23", "193.25.48.0/24", "193.25.51.0/24", "193.25.52.0/23", "193.25.54.0/24", "193.25.60.0/22", "193.30.161.0/24", "193.31.111.0/24", "193.33.137.0/24", "193.35.157.0/24", "193.37.39.0/24", "193.37.132.0/24", "193.39.114.0/24", "193.47.187.0/24", "193.57.172.0/24", "193.84.26.0/24", "193.100.64.0/24", "193.104.169.0/24", "193.105.212.0/24", "193.107.65.0/24", "193.110.146.0/24", "193.111.200.0/24", "193.131.114.0/23", "193.138.90.0/24", "193.150.164.0/24", "193.151.92.0/24", "193.151.94.0/24", "193.160.155.0/24", "193.176.54.0/24", "193.200.30.0/24", "193.200.156.0/24", "193.207.0.0/24", "193.219.118.0/24", "193.221.125.0/24", "193.227.82.0/24", "193.234.120.0/22", "193.239.162.0/23", "193.239.236.0/24", "193.243.129.0/24", "194.5.67.0/24", "194.5.147.0/24", "194.29.54.0/24", "194.29.58.0/24", 
                                        "194.30.175.0/24", "194.33.184.0/24", "194.42.96.0/23", "194.42.104.0/23", "194.53.200.0/24", "194.99.96.0/23", "194.104.235.0/24", "194.140.230.0/24", "194.165.43.0/24", "194.176.117.0/24", "194.195.101.0/24", "194.230.56.0/24", "194.247.26.0/23", "195.8.103.0/24", "195.42.240.0/24", "195.46.38.0/24", "195.60.86.0/24", "195.69.163.0/24", "195.74.60.0/24", "195.82.97.0/24", "195.85.12.0/24", "195.88.213.0/24", "195.88.246.0/24", "195.93.178.0/24", "195.191.165.0/24", "195.200.230.0/23", "195.234.155.0/24", "195.244.28.0/24", "195.245.230.0/23", "198.99.2.0/24", "198.137.150.0/24", "198.154.180.0/23", "198.160.151.0/24", "198.169.0.0/24", "198.176.120.0/23", "198.176.123.0/24", "198.176.124.0/23", "198.176.126.0/24", "198.183.226.0/24", "198.202.176.0/24", "198.204.13.0/24", "198.207.147.0/24", "198.212.50.0/24", "198.251.128.0/18", "198.251.192.0/19", "198.251.224.0/21", "199.43.186.0/24", "199.47.130.0/23", "199.59.243.0/24", "199.65.20.0/22", "199.65.24.0/23", "199.65.26.0/24", "199.65.242.0/24", "199.65.245.0/24", "199.65.246.0/24", "199.65.249.0/24", "199.65.250.0/24", "199.65.252.0/23", "199.68.157.0/24", "199.85.125.0/24", "199.87.145.0/24", "199.91.52.0/23", "199.115.200.0/24", "199.127.232.0/22", 
                                        "199.165.143.0/24", "199.187.168.0/22", "199.192.13.0/24", "199.196.235.0/24", "199.250.16.0/24", "199.255.32.0/24", "199.255.192.0/22", "199.255.240.0/24", "202.8.25.0/24", "202.44.120.0/23", "202.44.127.0/24", "202.45.131.0/24", "202.50.194.0/24", "202.52.43.0/24", "202.92.192.0/23", "202.93.249.0/24", "202.128.99.0/24", "202.160.113.0/24", "202.160.115.0/24", "202.160.117.0/24", "202.160.119.0/24", "202.173.24.0/24", "202.173.26.0/23", "202.173.31.0/24", "203.12.218.0/24", "203.20.242.0/23", "203.27.115.0/24", "203.27.226.0/23", "203.55.215.0/24", "203.57.88.0/24", "203.83.220.0/22", "203.175.1.0/24", "203.175.2.0/23", "203.210.75.0/24", "204.10.96.0/21", "204.11.174.0/23", "204.15.172.0/24", "204.15.215.0/24", "204.27.244.0/24", "204.48.63.0/24", "204.77.168.0/24", "204.90.106.0/24", "204.110.220.0/23", "204.110.223.0/24", "204.154.231.0/24", "204.236.128.0/18", "204.239.0.0/24", "204.246.160.0/22", "204.246.166.0/24", "204.246.169.0/24", "204.246.175.0/24", "204.246.177.0/24", "204.246.178.0/24", "204.246.180.0/23", "204.246.182.0/24", "204.246.187.0/24", "204.246.188.0/22", "205.147.81.0/24", "205.157.218.0/23", "205.166.195.0/24", "205.201.44.0/23", "205.220.188.0/24", "205.235.121.0/24", "205.251.192.0/21",
                                        "205.251.200.0/24", "205.251.203.0/24", "205.251.206.0/23", "205.251.212.0/23", "205.251.216.0/24", "205.251.218.0/23", "205.251.222.0/23", "205.251.224.0/21", "205.251.232.0/22", "205.251.240.0/22", "205.251.244.0/23", "205.251.247.0/24", "205.251.248.0/23", "205.251.251.0/24", "205.251.253.0/24", "206.108.41.0/24", "206.130.88.0/23", "206.166.248.0/23", "206.195.217.0/24", "206.195.218.0/24", "206.195.220.0/24", "206.198.37.0/24", "206.198.131.0/24", "206.225.200.0/23", "206.225.203.0/24", "206.225.217.0/24", "206.225.219.0/24", "207.2.117.0/24", "207.2.118.0/23", "207.34.11.0/24", "207.45.79.0/24", "207.90.252.0/23", "207.167.92.0/22", "207.167.126.0/23", "207.171.160.0/19", "207.189.185.0/24", "207.202.17.0/24", "207.202.18.0/24", "207.202.20.0/24", "207.207.176.0/22", "207.230.151.0/24", "207.230.156.0/24", "208.56.44.0/23", "208.56.47.0/24", "208.56.48.0/20", "208.71.22.0/24", "208.71.106.0/24", "208.71.210.0/24", "208.71.245.0/24", "208.73.7.0/24", "208.81.250.0/24", "208.82.220.0/22", "208.89.247.0/24", "208.90.238.0/24", "208.91.36.0/23", "208.95.53.0/24", "208.127.200.0/21", "209.51.32.0/21", "209.54.160.0/19", "209.94.75.0/24", "209.126.65.0/24", "209.127.220.0/24", "209.160.100.0/22", "209.163.96.0/24", "209.169.228.0/24", "209.169.242.0/24", "209.182.220.0/24", "209.222.82.0/24", "211.44.103.0/24", "212.4.240.0/22", "212.8.241.0/24", "212.19.235.0/24", "212.19.236.0/24", "212.104.208.0/24", "212.192.221.0/24", "213.5.226.0/24", "213.109.176.0/22", "213.170.156.0/24", 
                                        "213.170.158.0/24", "213.217.29.0/24", "216.9.204.0/24", "216.24.45.0/24", "216.73.153.0/24", "216.73.154.0/23", "216.74.122.0/24", "216.75.96.0/22", "216.75.104.0/21", "216.99.220.0/24", "216.115.17.0/24", "216.115.20.0/24", "216.115.23.0/24", "216.120.142.0/24", "216.120.187.0/24", "216.122.176.0/22", "216.137.32.0/24", "216.137.34.0/23", "216.137.36.0/22", "216.137.40.0/21", "216.137.48.0/21", "216.137.56.0/23", "216.137.58.0/24", "216.137.60.0/23", "216.137.63.0/24", "216.147.0.0/23", "216.147.3.0/24", "216.147.4.0/22", "216.147.9.0/24", "216.147.10.0/23", "216.147.12.0/23", "216.147.15.0/24", "216.147.16.0/23", "216.147.19.0/24", "216.147.20.0/23", "216.147.23.0/24", "216.147.24.0/22", "216.147.29.0/24", "216.147.30.0/23", "216.147.32.0/23", "216.157.133.0/24", "216.157.139.0/24", "216.169.145.0/24", "216.170.100.0/24", "216.182.236.0/23", "216.198.2.0/23", "216.198.17.0/24", 
                                        "216.198.18.0/24", "216.198.33.0/24", "216.198.34.0/23", "216.198.36.0/24", "216.198.49.0/24", "216.211.162.0/24", "216.219.113.0/24", "216.238.188.0/23", "216.238.190.0/24", "216.241.208.0/20", "217.8.118.0/24", "217.117.65.0/24", "217.117.71.0/24", "217.117.76.0/24", "217.119.96.0/24", "217.119.98.0/24", "217.119.104.0/23", "217.169.73.0/24", "218.33.0.0/18" ],)
            elif group_choice == '6':  
                ip_or_domain_list.extend(["54.239.130.0/23", "54.239.132.0/23", "54.239.135.0/24", "54.239.142.0/23", "54.239.152.0/23", "54.239.158.0/23", "54.239.162.0/23", "54.239.164.0/23", "54.239.168.0/23", "54.239.171.0/24", "54.239.172.0/24", "54.239.174.0/23", "54.239.180.0/23", "54.239.186.0/24", "54.239.192.0/24", "54.239.195.0/24", "54.239.200.0/24", "54.239.204.0/22", "54.239.208.0/21", "54.239.216.0/23", "54.239.219.0/24", "54.239.220.0/23", "54.239.223.0/24", "54.240.0.0/21", "54.240.16.0/24", "54.240.24.0/22", "54.240.50.0/23", "54.240.52.0/22", "54.240.56.0/21", "54.240.80.0/20", "54.240.96.0/20", "54.240.112.0/21", "54.240.129.0/24", "54.240.130.0/23", "54.240.160.0/23", "54.240.166.0/23", "54.240.168.0/21", "54.240.184.0/21", "54.240.192.0/21", "54.240.200.0/24", "54.240.202.0/24", "54.240.204.0/22", "54.240.208.0/20", "54.240.225.0/24", "54.240.226.0/23", "54.240.228.0/22", "54.240.232.0/22", "54.240.244.0/22", "54.240.248.0/21", "54.241.0.0/16", "54.244.0.0/14", "54.248.0.0/13", "57.180.0.0/14", "58.181.95.0/24", "62.133.34.0/24", "63.32.0.0/14", "63.140.32.0/22", "63.140.36.0/23", "63.140.48.0/22", "63.140.52.0/24", "63.140.55.0/24", "63.140.56.0/23", "63.140.61.0/24", "63.140.62.0/23", "63.246.112.0/24", "64.35.162.0/24", "64.45.129.0/24", "64.45.130.0/23", "64.52.111.0/24", "64.56.212.0/24", "64.65.61.0/24", "64.69.212.0/24", "64.69.223.0/24", "64.186.3.0/24", "64.187.128.0/20", "64.190.110.0/24", "64.190.237.0/24", "64.207.194.0/24", "64.207.196.0/24", "64.207.198.0/23", "64.207.204.0/23", "64.234.115.0/24", "64.238.2.0/24", "64.238.5.0/24", "64.238.6.0/24", "64.238.14.0/24", "64.252.65.0/24", "64.252.70.0/23", "64.252.72.0/21", "64.252.80.0/21", "64.252.88.0/23", "64.252.98.0/23", "64.252.100.0/22", "64.252.104.0/21", "64.252.112.0/23", "64.252.114.0/24", "64.252.118.0/23", "64.252.120.0/22", "64.252.124.0/24", "64.252.129.0/24", "64.252.130.0/23", "64.252.132.0/22", "64.252.136.0/21", "64.252.144.0/23", "64.252.147.0/24", "64.252.148.0/23", "64.252.151.0/24", "64.252.152.0/24", "64.252.154.0/23", "64.252.156.0/24", "64.252.159.0/24", "64.252.161.0/24", "64.252.162.0/23", "64.252.164.0/24", "64.252.166.0/23", "64.252.168.0/22", "64.252.172.0/23", "64.252.175.0/24", "64.252.176.0/22", "64.252.180.0/24", "64.252.182.0/23", "64.252.185.0/24", "64.252.186.0/23", "64.252.188.0/23", "64.252.190.0/24", "65.0.0.0/14", "65.8.0.0/23", "65.8.2.0/24", "65.8.4.0/22", "65.8.8.0/23", "65.8.11.0/24", "65.8.12.0/24", "65.8.14.0/23", "65.8.16.0/20", "65.8.32.0/19", "65.8.64.0/20", "65.8.80.0/21", "65.8.88.0/22", "65.8.92.0/23", "65.8.94.0/24", "65.8.96.0/20", "65.8.112.0/21", "65.8.120.0/22", "65.8.124.0/23", "65.8.129.0/24", "65.8.130.0/23", "65.8.132.0/22", "65.8.136.0/22", "65.8.140.0/23", "65.8.142.0/24", "65.8.146.0/23", "65.8.148.0/23", "65.8.150.0/24", "65.8.152.0/23", "65.8.154.0/24", "65.8.158.0/23", "65.8.160.0/19", "65.8.192.0/18", "65.9.4.0/24", "65.9.6.0/23", "65.9.9.0/24", "65.9.11.0/24", "65.9.14.0/23", "65.9.17.0/24", "65.9.19.0/24", "65.9.20.0/22", "65.9.24.0/21", "65.9.32.0/19", "65.9.64.0/19", "65.9.96.0/20", "65.9.112.0/23", "65.9.129.0/24", "65.9.130.0/23", "65.9.132.0/22", "65.9.136.0/21", "65.9.144.0/20", "65.9.160.0/19", "65.20.48.0/24", "65.37.240.0/24", "65.110.52.0/23", "65.110.54.0/24", "66.22.176.0/24", "66.22.190.0/24", "66.37.128.0/24", "66.51.208.0/24", "66.51.210.0/23", "66.51.212.0/22", "66.51.216.0/23", "66.54.74.0/23", "66.81.8.0/24", "66.81.227.0/24", "66.81.241.0/24", "66.117.20.0/24", "66.117.22.0/23", "66.117.24.0/23", "66.117.26.0/24", "66.117.30.0/23", "66.129.247.0/24", "66.129.248.0/24", "66.159.226.0/24", "66.159.230.0/24", "66.178.130.0/24", "66.178.132.0/23", "66.178.134.0/24", "66.178.136.0/23", "66.178.139.0/24", "66.182.132.0/23", "66.187.204.0/23", "66.206.173.0/24", "66.232.20.0/23", "66.235.151.0/24", "66.235.152.0/22", "67.20.60.0/24", "67.199.239.0/24", "67.219.241.0/24", "67.219.247.0/24", "67.219.250.0/24", "67.220.224.0/19", "67.221.38.0/24", "67.222.249.0/24", "67.222.254.0/24", "67.226.222.0/23", "68.64.5.0/24", "68.66.112.0/20", "68.70.127.0/24", "69.10.24.0/24", "69.58.24.0/24", "69.59.247.0/24", "69.59.248.0/24", "69.59.250.0/23", "69.64.150.0/24", "69.64.152.0/24", "69.72.44.0/22", "69.80.226.0/23", "69.94.8.0/23", "69.166.42.0/24", "69.169.224.0/20", "70.132.0.0/20", "70.132.16.0/22", "70.132.20.0/23", "70.132.23.0/24", "70.132.24.0/23", "70.132.27.0/24", "70.132.28.0/22", "70.132.32.0/21", "70.132.40.0/24", "70.132.42.0/23", "70.132.44.0/24", "70.132.46.0/24", "70.132.48.0/22", "70.132.52.0/23", "70.132.55.0/24", "70.132.58.0/23", "70.132.60.0/22", "70.224.192.0/18", "70.232.64.0/20", "70.232.80.0/21", "70.232.88.0/22", "70.232.96.0/20", "70.232.112.0/21", "70.232.120.0/22", "71.141.0.0/21", "71.152.0.0/22", "71.152.4.0/23", "71.152.7.0/24", "71.152.8.0/24", "71.152.10.0/23", "71.152.13.0/24", "71.152.14.0/23", "71.152.16.0/21", "71.152.24.0/22", 
                                        "71.152.28.0/24", "71.152.30.0/23", "71.152.33.0/24", "71.152.35.0/24", "71.152.36.0/22", "71.152.40.0/23", "71.152.43.0/24", "71.152.46.0/23", "71.152.48.0/22", "71.152.53.0/24", "71.152.55.0/24", "71.152.56.0/22", "71.152.61.0/24", "71.152.62.0/23", "71.152.64.0/21", "71.152.72.0/22", "71.152.76.0/23", "71.152.79.0/24", "71.152.80.0/21", "71.152.88.0/22", "71.152.92.0/24", "71.152.94.0/23", "71.152.96.0/22", "71.152.100.0/24", "71.152.102.0/23", "71.152.105.0/24", "71.152.106.0/23", "71.152.108.0/23", "71.152.110.0/24", "71.152.112.0/21", "71.152.122.0/23", "71.152.124.0/24", "71.152.126.0/23", "72.1.32.0/21", "72.13.121.0/24", "72.13.124.0/24", "72.18.76.0/23", "72.18.222.0/24", "72.21.192.0/19", "72.41.0.0/20", "72.46.77.0/24", "72.167.168.0/24", "74.80.247.0/24", "74.116.145.0/24", "74.116.147.0/24", "74.117.148.0/24", "74.118.105.0/24", "74.118.106.0/23", "74.200.120.0/24", "74.221.129.0/24", "74.221.130.0/24", "74.221.133.0/24", "74.221.135.0/24", "74.221.137.0/24", "74.221.139.0/24", "74.221.141.0/24", "75.2.0.0/17", "75.104.19.0/24", "76.76.17.0/24", "76.76.19.0/24", "76.76.21.0/24", "76.223.0.0/17", "76.223.128.0/22", "76.223.132.0/23", "76.223.160.0/22", "76.223.164.0/23", "76.223.166.0/24", "76.223.172.0/22", "76.223.176.0/21", "76.223.184.0/22", "76.223.188.0/23", "76.223.190.0/24", "77.73.208.0/23", "78.108.124.0/23", "79.125.0.0/17", "79.143.156.0/24", "80.210.95.0/24", "81.20.41.0/24", "81.90.143.0/24", "82.145.126.0/24", "82.192.96.0/23", "82.192.100.0/23", "82.192.108.0/23", "83.97.100.0/22", "83.137.245.0/24", "83.147.240.0/22", "83.151.192.0/23", "83.151.194.0/24", "84.254.134.0/24", "85.92.101.0/24", "85.113.84.0/24", "85.113.88.0/24", "85.158.142.0/24", "85.194.254.0/23", "85.236.136.0/21", "87.236.67.0/24", "87.238.80.0/21", "87.238.140.0/24", "88.202.208.0/23", "88.202.210.0/24", "88.212.156.0/22", "89.37.140.0/24", "89.116.141.0/24", "89.116.244.0/24", "89.117.129.0/24", "89.251.12.0/24", "91.102.186.0/24", "91.193.42.0/24", "91.194.25.0/24", "91.194.104.0/24", "91.198.107.0/24", "91.198.117.0/24", "91.207.12.0/23", "91.208.21.0/24", "91.209.81.0/24", "91.213.115.0/24", "91.213.126.0/24", "91.213.146.0/24", "91.218.37.0/24", "91.223.161.0/24", "91.227.75.0/24", "91.228.72.0/24", "91.228.74.0/24", "91.230.237.0/24", "91.231.35.0/24", "91.233.61.0/24", "91.233.120.0/24", "91.236.18.0/24", "91.236.66.0/24", "91.237.174.0/24", "91.240.18.0/23", "91.241.6.0/23", "93.93.224.0/22", "93.94.3.0/24", "93.191.148.0/23", "93.191.219.0/24", "94.124.112.0/24", "94.140.18.0/24", "94.142.252.0/24", "95.82.16.0/20", "95.130.184.0/23", "96.0.0.0/18", "96.0.64.0/21", "96.0.84.0/22", "96.0.88.0/22", "96.0.92.0/23", "96.0.96.0/22", "96.0.100.0/23", "96.0.104.0/22", "96.9.221.0/24", "98.97.248.0/22", "98.97.253.0/24", "98.97.254.0/23", "98.142.155.0/24", "99.77.0.0/18", "99.77.130.0/23", "99.77.132.0/22", "99.77.136.0/21", "99.77.144.0/23", "99.77.147.0/24", "99.77.148.0/23", "99.77.150.0/24", "99.77.152.0/21", "99.77.160.0/23", "99.77.183.0/24", "99.77.186.0/24", "99.77.188.0/23", "99.77.190.0/24", "99.77.233.0/24", "99.77.234.0/23", "99.77.238.0/23", "99.77.240.0/24", "99.77.242.0/24", "99.77.244.0/22", "99.77.248.0/22", "99.77.252.0/23", "99.78.128.0/19", "99.78.160.0/21", "99.78.168.0/22", "99.78.172.0/24", "99.78.176.0/21", "99.78.192.0/18", "99.79.0.0/16", "99.80.0.0/15", "99.82.128.0/19", "99.82.160.0/20", "99.82.184.0/21", "99.83.72.0/21", "99.83.80.0/21", "99.83.96.0/22", "99.83.100.0/23", "99.83.102.0/24", "99.83.120.0/22", "99.83.128.0/17", "99.84.0.0/19", "99.84.32.0/20", "99.84.48.0/24", "99.84.50.0/23", "99.84.52.0/22", "99.84.56.0/21", "99.84.64.0/18", "99.84.128.0/24", "99.84.130.0/23", "99.84.132.0/22", "99.84.136.0/21", "99.84.144.0/20", "99.84.160.0/19", "99.84.192.0/18", "99.86.0.0/17", "99.86.128.0/21", "99.86.136.0/24", "99.86.144.0/21", "99.86.153.0/24", "99.86.154.0/23", "99.86.156.0/22", "99.86.160.0/20", "99.86.176.0/21", "99.86.185.0/24", "99.86.186.0/23", "99.86.188.0/22", "99.86.192.0/21", "99.86.201.0/24", "99.86.202.0/23", "99.86.204.0/22", "99.86.217.0/24", "99.86.218.0/23", "99.86.220.0/22", "99.86.224.0/20", "99.86.240.0/21", "99.86.249.0/24", "99.86.250.0/23", "99.86.252.0/22", "99.87.0.0/19", "99.87.32.0/22", "99.150.0.0/21", "99.150.16.0/20", "99.150.32.0/19", "99.150.64.0/18", "99.151.64.0/18", "99.151.128.0/19", "99.151.186.0/23", "100.20.0.0/14", "103.4.8.0/21", "103.8.172.0/22", "103.10.127.0/24", "103.16.56.0/24", "103.16.59.0/24", "103.16.101.0/24", "103.19.244.0/22", "103.23.68.0/23", "103.39.40.0/24", "103.43.38.0/23", "103.53.55.0/24", "103.58.192.0/24", "103.70.20.0/22", "103.70.49.0/24", "103.80.6.0/24", "103.85.213.0/24", "103.104.86.0/24", "103.107.56.0/24", "103.119.213.0/24", "103.123.219.0/24", "103.124.134.0/23", "103.127.75.0/24", "103.136.10.0/24", "103.143.45.0/24", "103.145.182.0/24", "103.145.192.0/24", "103.147.71.0/24", 
                                        "103.149.112.0/24", "103.150.47.0/24", "103.150.161.0/24", "103.151.39.0/24", "103.151.192.0/23", "103.152.248.0/24", "103.161.77.0/24", "103.165.160.0/24", "103.166.180.0/24", "103.167.153.0/24", "103.168.156.0/23", "103.168.209.0/24", "103.175.120.0/23", "103.179.36.0/23", "103.180.30.0/24", "103.181.194.0/24", "103.181.240.0/24", "103.182.250.0/23", "103.187.14.0/24", "103.188.89.0/24", "103.190.166.0/24", "103.193.9.0/24", "103.195.60.0/22", "103.196.32.0/24", "103.211.172.0/24", "103.229.8.0/23", "103.229.10.0/24", "103.235.88.0/24", "103.238.120.0/24", "103.246.148.0/22", "103.246.251.0/24", "104.36.33.0/24", "104.153.112.0/23", "104.171.198.0/23", "104.192.136.0/23", "104.192.138.0/24", "104.192.140.0/23", "104.192.143.0/24", "104.193.186.0/24", "104.193.205.0/24", "104.193.207.0/24", "104.207.162.0/24", "104.207.170.0/23", "104.207.172.0/23", "104.207.174.0/24", "104.218.202.0/24", "104.232.45.0/24", "104.234.23.0/24", "104.238.244.0/23", "104.238.247.0/24", "104.249.160.0/23", "104.249.162.0/24", "104.253.192.0/24", "104.255.56.0/22", "104.255.60.0/24", "107.162.252.0/24", "108.128.0.0/13", "108.136.0.0/15", "108.138.0.0/16", "108.139.0.0/19", "108.139.32.0/20", "108.139.48.0/21", "108.139.56.0/24", "108.139.72.0/21", "108.139.80.0/22", "108.139.84.0/23", "108.139.86.0/24", "108.139.102.0/23", "108.139.104.0/21", "108.139.112.0/20", "108.139.128.0/20", "108.139.144.0/23", "108.139.146.0/24", "108.139.162.0/23", "108.139.164.0/22", "108.139.168.0/21", "108.139.176.0/20", "108.139.207.0/24", "108.139.208.0/20", "108.139.224.0/19", "108.156.0.0/17", "108.156.128.0/23", "108.156.130.0/24", "108.156.146.0/23", "108.156.148.0/22", "108.156.152.0/21", "108.156.160.0/19", "108.156.192.0/18", "108.157.0.0/21", "108.157.8.0/23", "108.157.85.0/24", "108.157.86.0/23", "108.157.88.0/21", "108.157.96.0/20", "108.157.112.0/23", "108.157.114.0/24", "108.157.130.0/23", "108.157.132.0/22", "108.157.136.0/21", "108.157.144.0/20", "108.157.160.0/21", "108.157.168.0/22", "108.157.172.0/23", "108.157.174.0/24", "108.157.205.0/24", "108.157.206.0/23", "108.157.208.0/20", "108.157.224.0/21", "108.157.232.0/23", "108.157.234.0/24", "108.158.39.0/24", "108.158.40.0/21", "108.158.48.0/20", "108.158.64.0/22", "108.158.68.0/24", "108.158.114.0/23", "108.158.116.0/22", "108.158.120.0/21", "108.158.128.0/20", "108.158.144.0/21", "108.158.152.0/22", "108.158.156.0/23", "108.158.158.0/24", "108.158.219.0/24", "108.158.220.0/22", "108.158.224.0/19", "108.159.0.0/18", "108.159.64.0/19", "108.159.96.0/23", "108.159.128.0/21", "108.159.136.0/22", "108.159.144.0/23", "108.159.155.0/24", "108.159.156.0/24", "108.159.160.0/23", "108.159.163.0/24", "108.159.164.0/24", "108.159.166.0/23", "108.159.168.0/21", "108.159.181.0/24", "108.159.182.0/23", "108.159.184.0/24", "108.159.188.0/22", "108.159.192.0/24", "108.159.197.0/24", "108.159.198.0/23", "108.159.200.0/21", "108.159.208.0/24", "108.159.213.0/24", "108.159.214.0/23", "108.159.216.0/21", "108.159.224.0/21", "108.159.247.0/24", "108.159.248.0/23", "108.159.250.0/24", "108.159.255.0/24", "108.175.52.0/23", "108.175.54.0/24", "109.68.71.0/24", "109.95.191.0/24", "109.224.233.0/24", "109.232.88.0/21", "116.214.100.0/23", "116.214.120.0/23", "122.248.192.0/18", "122.252.145.0/24", "122.252.146.0/23", "122.252.148.0/22", "129.33.138.0/23", "129.33.243.0/24", "129.41.76.0/23", "129.41.88.0/23", "129.41.167.0/24", "129.41.174.0/23", "129.41.222.0/24", "130.50.35.0/24", "130.137.20.0/24", "130.137.78.0/24", "130.137.81.0/24", "130.137.86.0/24", "130.137.99.0/24", "130.137.112.0/24", "130.137.124.0/24", "130.137.136.0/24", "130.137.150.0/24", "130.137.178.0/24", "130.137.215.0/24", "130.176.0.0/21", "130.176.9.0/24", "130.176.10.0/23", "130.176.13.0/24", "130.176.14.0/24", "130.176.16.0/23", "130.176.24.0/23", "130.176.27.0/24", "130.176.28.0/22", "130.176.32.0/21", "130.176.40.0/24", "130.176.43.0/24", "130.176.45.0/24", "130.176.48.0/24", "130.176.50.0/24", "130.176.53.0/24", "130.176.54.0/24", "130.176.56.0/24", "130.176.65.0/24", "130.176.66.0/23", "130.176.68.0/24", "130.176.71.0/24", "130.176.75.0/24", "130.176.76.0/22", "130.176.80.0/21", "130.176.88.0/22", "130.176.92.0/23", "130.176.96.0/22", "130.176.100.0/24", "130.176.102.0/23", "130.176.104.0/22", "130.176.108.0/23", "130.176.111.0/24", "130.176.112.0/23", "130.176.116.0/24", "130.176.118.0/23", "130.176.120.0/24", "130.176.125.0/24", "130.176.126.0/23", "130.176.129.0/24", "130.176.130.0/23", "130.176.132.0/22", "130.176.136.0/23", "130.176.139.0/24", "130.176.140.0/22", "130.176.144.0/23", "130.176.146.0/24", "130.176.148.0/22", "130.176.152.0/24", "130.176.155.0/24", "130.176.156.0/22", "130.176.160.0/21", "130.176.168.0/24", "130.176.170.0/23", "130.176.172.0/24", "130.176.174.0/23", "130.176.179.0/24", "130.176.182.0/23", "130.176.184.0/21", "130.176.192.0/24", "130.176.194.0/23", "130.176.196.0/22", 
                                        "130.176.200.0/21", "130.176.208.0/21", "130.176.217.0/24", "130.176.218.0/23", "130.176.220.0/22", "130.176.224.0/24", "130.176.226.0/23", "130.176.231.0/24", "130.176.232.0/24", "130.176.254.0/23", "130.193.2.0/24", "131.232.37.0/24", "131.232.76.0/23", "131.232.78.0/24", "132.75.97.0/24", "134.224.0.0/17", "134.224.128.0/18", "134.224.192.0/19", "134.224.224.0/20", "134.224.242.0/23", "134.224.244.0/22", "134.224.248.0/22", "135.84.124.0/24", "136.18.18.0/23", "136.18.20.0/22", "136.175.24.0/23", "136.175.106.0/23", "136.175.113.0/24", "136.184.226.0/23", "136.184.229.0/24", "136.184.230.0/23", "136.184.232.0/23", "136.184.235.0/24", "136.226.219.0/24", "136.226.220.0/23", "137.83.193.0/24", "137.83.195.0/24", "137.83.196.0/22", "137.83.202.0/23", "137.83.204.0/23", "137.83.208.0/22", "137.83.212.0/24", "137.83.214.0/24", "137.83.252.0/22", "138.43.114.0/24", "139.60.2.0/24", "139.60.113.0/24", "139.60.114.0/24", "139.64.232.0/24", "139.138.105.0/24", "139.180.31.0/24", "139.180.242.0/23", "139.180.246.0/23", "139.180.248.0/22", "140.19.64.0/24", "140.99.123.0/24", "140.228.26.0/24", "141.11.12.0/22", "141.163.128.0/20", "141.193.32.0/23", "141.193.208.0/23", "142.0.189.0/24", "142.0.190.0/24", "142.4.160.0/22", "142.4.177.0/24", "142.54.40.0/24", "142.202.20.0/24", "142.202.36.0/22", "142.202.40.0/24", "142.202.42.0/23", "142.202.46.0/24", "143.55.151.0/24", "143.204.0.0/19", "143.204.32.0/21", "143.204.40.0/24", "143.204.57.0/24", "143.204.58.0/23", "143.204.60.0/22", "143.204.64.0/20", "143.204.80.0/21", "143.204.89.0/24", "143.204.90.0/23", "143.204.92.0/22", "143.204.96.0/20", "143.204.112.0/21", "143.204.121.0/24", "143.204.122.0/23", "143.204.124.0/22", "143.204.128.0/18", "143.204.192.0/19", "143.204.224.0/20", "143.204.240.0/21", "143.204.249.0/24", "143.204.250.0/23", "143.204.252.0/22", "143.244.81.0/24", "143.244.82.0/23", "143.244.84.0/22", "144.2.170.0/24"],
    )
            elif group_choice == '7':  
                ip_or_domain_list.extend(["173.245.48.0/20","103.21.244.0/22", "103.22.200.0/22", "103.31.4.0/22", "141.101.64.0/18", "108.162.192.0/18", "190.93.240.0/20", "188.114.96.0/20", 
                                        "197.234.240.0/22", "198.41.128.0/17", "162.158.0.0/15", "104.16.0.0/13", "104.24.0.0/14", "172.64.0.0/13", "131.0.72.0/22"])  # Replace with actual IPs
            else:
                print("Invalid group choice.")
                return

        else:
            print("Invalid choice.")
            return

        if not ip_or_domain_list:
            print("No WebSocket domains or IPs provided.")
            return

        output_file_name = input("Enter the name of the output file to save valid connections (or leave blank to skip saving): ")

        if not output_file_name.strip():
            print("No output file specified. Exiting.")
            return

        successful_connections = 0

        with concurrent.futures.ThreadPoolExecutor(max_workers=60) as executor:
            results = [
                executor.submit(establish_websocket_connection, ip_or_domain.strip(), output_file_name)
                for ip_or_domain in ip_or_domain_list
            ]

            for future in concurrent.futures.as_completed(results):
                result = future.result()
                if result:
                    successful_connections += result

        if successful_connections > 0:
            print(f"{Fore.GREEN}Total {successful_connections} valid connections saved to {output_file_name}.")
        else:
            print(f"{Fore.RED}No valid WebSocket connections found.")

    if __name__ == "__main__":
        k()
        time.sleep(1)

        print("""
        ===================================
                    Menu                
        ===================================
        1. Return to main menu
        2. Proceed to the script
        """)

        while True:
            choice = input("Enter your choice (1): ")
            if choice == '1':
                print("Returning to BUGHUNTERS PRO...")
                time.sleep(1)
                os.system('cls' if os.name == 'nt' else 'clear')
                break
            elif choice == '2':
                k()
            else:
                break

#===WEBSOCKER SCANNER OLD===#
def websocket_scanner_old():
                    
    import configparser

    bg=''
    #G = bg+'\033[32m'
    OP = bg+'\033[33m'
    GR = bg+'\033[37m'
    R = bg+'\033[31m'

    print(OP+'''  
    \t#####################################################################
    \t#                                                                   #          
    \t#   KING'S WEBSOCKET SCANNER                                        #          
    \t#                                                                   #          
    \t#  This script is used to scan a range of IP addresses              #
    \t#  to find ones that are running a server with the cloudflare       #
    \t#  string in the Server field of the HTTP header.                   #
    \t#  It does this by creating a list of IP addresses using the        #
    \t#  ipaddress module and then using multiprocessing to create a      #
    \t#  specified number of threads to scan the addresses concurrently.  # 
    \t#                                                                   #
    \t#  Built for speed (using threading)                                #
    \t#                                                                   #
    \t#####################################################################
            
        ██╗    ██╗███████╗██████╗ ███████╗ ██████╗  ██████╗██╗  ██╗███████╗████████╗    
        ██║    ██║██╔════╝██╔══██╗██╔════╝██╔═══██╗██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝    
        ██║ █╗ ██║█████╗  ██████╔╝███████╗██║   ██║██║     █████╔╝ █████╗     ██║       
        ██║███╗██║██╔══╝  ██╔══██╗╚════██║██║   ██║██║     ██╔═██╗ ██╔══╝     ██║       
        ╚███╔███╔╝███████╗██████╔╝███████║╚██████╔╝╚██████╗██║  ██╗███████╗   ██║       
        ╚══╝╚══╝ ╚══════╝╚═════╝ ╚══════╝ ╚═════╝  ╚═════╝╚═╝  ╚═╝╚══════╝   ╚═╝       
                                                                                            
            ███████╗ ██████╗ █████╗ ███╗   ██╗███╗   ██╗███████╗██████╗                     
            ██╔════╝██╔════╝██╔══██╗████╗  ██║████╗  ██║██╔════╝██╔══██╗                    
            ███████╗██║     ███████║██╔██╗ ██║██╔██╗ ██║█████╗  ██████╔╝                    
            ╚════██║██║     ██╔══██║██║╚██╗██║██║╚██╗██║██╔══╝  ██╔══██╗                    
            ███████║╚██████╗██║  ██║██║ ╚████║██║ ╚████║███████╗██║  ██║                    
            ╚══════╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝                    
                                                                                        '''+GR)
    import socket
    import ssl
    import base64
    import random
    import ipaddress
    import os
    from concurrent.futures import ThreadPoolExecutor, as_completed
    from time import sleep

    # ANSI color codes
    RED = '\033[91m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RESET = '\033[0m'

    def check_websocket(host, port, path="/", use_ssl=False):
        global output_file  # Ensure access to global variable

        key = base64.b64encode(bytes(random.getrandbits(8) for _ in range(16))).decode()

        headers = [
            f"GET {path} HTTP/1.1",
            f"Host: {host}:{port}",
            "Upgrade: websocket",
            "Connection: Upgrade",
            f"Sec-WebSocket-Key: {key}",
            "Sec-WebSocket-Version: 13",
            "\r\n"
        ]

        request_data = "\r\n".join(headers)

        try:
            sock = socket.create_connection((host, port), timeout=5)
            if use_ssl:
                context = ssl.create_default_context()
                sock = context.wrap_socket(sock, server_hostname=host)

            sock.sendall(request_data.encode())
            response = sock.recv(2048).decode(errors="ignore")
            sock.close()

            status_line = response.splitlines()[0] if response else ""
            status_code = status_line.split()[1] if len(status_line.split()) >= 2 else "???"

            result = f"{'wss' if use_ssl else 'ws'}://{host}:{port}{path}"

            if status_code == "101" and "upgrade: websocket" in response.lower():
                print(f"{GREEN}[+] {result} — WebSocket Supported (Status: {status_code}){RESET}")
                if output_file:
                    try:
                        with open(output_file, "a", encoding="utf-8") as f:
                            f.write(result + f" (Status: {status_code})\n")
                            f.flush()  # Immediately flush to disk
                            os.fsync(f.fileno())  # Ensure physical write
                    except Exception as write_err:
                        print(f"{RED}[!] Failed to write result: {write_err}{RESET}")
            elif status_code.isdigit():
                print(f"{YELLOW}[-] {result} — WebSocket NOT supported (Status: {status_code}){RESET}")
            else:
                print(f"{RED}[-] {result} — Invalid or Unknown Response (Status: {status_code}){RESET}")
        except Exception as e:
            print(f"{RED}[!] {host}:{port} - Error: {RESET}")


    def process_input(input_data):
        targets = []

        if os.path.isfile(input_data):
            with open(input_data, 'r') as f:
                lines = f.read().splitlines()
                for line in lines:
                    targets.extend(process_input(line.strip()))
        else:
            try:
                net = ipaddress.ip_network(input_data, strict=False)
                for ip in net.hosts():
                    targets.append(str(ip))
            except ValueError:
                # Treat as domain or single IP
                if input_data.startswith("http://") or input_data.startswith("https://"):
                    input_data = input_data.split("//")[1].split("/")[0]
                targets.append(input_data)

        return targets

    def scan_batch(batch, port, path, use_ssl):
        with ThreadPoolExecutor(max_workers=100) as executor:
            futures = [executor.submit(check_websocket, ip, port, path, use_ssl) for ip in batch]
            for _ in as_completed(futures):
                pass  # Output is handled inside check_websocket

    def chunked(lst, n):
        for i in range(0, len(lst), n):
            yield lst[i:i + n]

    def mj4():
        global output_file

        input_data = input("Enter IP / domain / CIDR / filename: ").strip()
        path = input("Enter WebSocket path (default is '/'): ").strip()
        if not path:
            path = "/"

        save_results = input("Do you want to save successful connections? (yes/no): ").strip().lower()
        if save_results in ["yes", "y", "true", "1"]:
            output_file = input("Enter filename to save (e.g., results.txt): ").strip()
            print(f"[✓] Saving successful WebSocket connections to {output_file}\n")

        targets = process_input(input_data)
        print(f"[+] Total targets: {len(targets)} — scanning ports 80 and 443 in batches of 500...\n")

        for batch in chunked(targets, 500):
            print("[*] Scanning port 80 (ws://)...")
            scan_batch(batch, 80, path, use_ssl=False)

            print("[*] Scanning port 443 (wss://)...")
            scan_batch(batch, 443, path, use_ssl=True)

            sleep(0.5)

    if __name__ == "__main__":
        try:
            mj4()
        except KeyboardInterrupt:
            print("\n[!] Scan interrupted by user.")
        except Exception as e:
            print(f"[!] An error occurred: {e}")
            if output_file:
                print(f"[!] Results saved to {output_file}")
            else:
                print("[!] No results saved.")
            if output_file and os.path.exists(output_file):
                os.remove(output_file)
                print(f"[!] Temporary file {output_file} removed.")
            else:
                print("[!] No temporary file to remove.")
        finally:
            print("[!] Exiting...")
            time.sleep(1)
            return

#===SUBDOmain TAKEOVER===#
def access_control():

    generate_ascii_banner("ACCESS", "CONTROL")
    THREAD_COUNT = 100

    LOCK = threading.Lock()
    user_input = input("Enter a domain or .txt file: ").strip()
    OUTPUT_FILE = input("Enter output file name (default is x_requested_with_results.txt): ").strip() or "x_requested_with_results.txt"
    def check_domain(domain, progress):
        preflight_headers = {
            'Origin': 'https://yahoo.com/',
            'Access-Control-Request-Method': 'GET',
            'Access-Control-Request-Headers': 'X-Requested-With, X-Online-Host, X-Forwarded-For',
            'User-Agent': 'Mozilla/5.0'
        }

        for protocol in ['http://', 'https://']:
            url = protocol + domain
            try:
                response = requests.options(url, headers=preflight_headers, timeout=5)
                status = response.status_code
                allowed_headers = response.headers.get('Access-Control-Allow-Headers', '').lower()

                allowed = []
                if 'x-requested-with' in allowed_headers:
                    allowed.append('X-Requested-With')
                if 'x-online-host' in allowed_headers:
                    allowed.append('X-Online-Host')
                if 'x-forwarded-for' in allowed_headers:
                    allowed.append('X-Forwarded-For')

                if allowed:
                    server = response.headers.get('Server', 'Unknown')
                    print(f"✅ {url} - ALLOWS: {', '.join(allowed)} | Status: {status}")
                    with LOCK:
                        with open(OUTPUT_FILE, "a") as f:
                            f.write(f"{url} | Status: {status} | Server: {server} | Allowed Headers: {', '.join(allowed)}\n")
                else:
                    print(f"⚠️ {url} - None of the desired X-* headers allowed.")

            except requests.exceptions.RequestException as e:
                print(f"❌ {url} - Request failed: {e}")
            finally:
                with LOCK:
                    progress.update(1)


    def worker(domain_queue, progress):
        while not domain_queue.empty():
            domain = domain_queue.get()
            check_domain(domain, progress)
            domain_queue.task_done()

    def access_main():


        if os.path.isfile(user_input) and user_input.endswith('.txt'):
            with open(user_input, 'r') as file:
                domains = [line.strip() for line in file if line.strip()]
        else:
            domains = [user_input]

        if os.path.exists(OUTPUT_FILE):
            os.remove(OUTPUT_FILE)

        domain_queue = Queue()
        for domain in domains:
            domain_queue.put(domain)

        progress = tqdm(total=len(domains) * 2, desc="Checking", ncols=80)

        threads = []
        for _ in range(THREAD_COUNT):
            t = threading.Thread(target=worker, args=(domain_queue, progress))
            t.start()
            threads.append(t)

        for t in threads:
            t.join()

        progress.close()
        print(f"\n✅ Finished checking. Results saved to {OUTPUT_FILE}")

    if __name__ == "__main__":
        access_main()

#===IP GEN===#
def ipgen():
    
    generate_ascii_banner("IP", "GEN")

    def validate_ip_range(ip_range):
        try:
            ipaddress.ip_network(ip_range)
        except ValueError:
            raise argparse.ArgumentTypeError("Invalid IP range")
        return ip_range

    def calculate_ipv4_addresses(ip_ranges, num_threads, pbar):
        addresses = []

        def calculate_ipv4_addresses_thread(ip_range):
            ip_network = ipaddress.ip_network(ip_range)
            for address in ip_network:
                addresses.append(address)
                pbar.update(1)

        threads = []
        for ip_range in ip_ranges:
            t = threading.Thread(target=calculate_ipv4_addresses_thread, args=(ip_range,))
            threads.append(t)
            t.start()

        # Wait for all threads to finish before returning the addresses
        for t in threads:
            t.join()

        return addresses

    def print_addresses(addresses, output_file):
        with open(output_file, "w") as f:
            for address in addresses:
                f.write(str(address) + "\n")

    def ipgen_main():
        input_choice = input("Enter '1' to input IP ranges or '2' to specify a file containing IP ranges: ")
        
        if input_choice == '1':
            ip_ranges_input = input("Enter a single IP range in CIDR notation or list of IP ranges separated by comma: ")
            ip_ranges = [ip_range.strip() for ip_range in ip_ranges_input.split(",")]

            for ip_range in ip_ranges:
                validate_ip_range(ip_range)
        elif input_choice == '2':
            file_name = input("Enter the name of the file containing IP ranges (must be in the same directory as the script): ")
            try:
                with open(file_name) as f:
                    ip_ranges = [line.strip() for line in f]
            except FileNotFoundError:
                print("Error: File not found.")
                return
        else:
            print("Invalid input.")
            return

        output_file = input("Enter the name of the output file: ")
        num_threads = int(input("Enter the number of threads to use: "))

        total_addresses = sum([2 ** (32 - ipaddress.ip_network(ip_range).prefixlen) for ip_range in ip_ranges])

        with tqdm(total=total_addresses, desc="Calculating addresses") as pbar:
            addresses = calculate_ipv4_addresses(ip_ranges, num_threads, pbar)

        print_addresses(addresses, output_file)

    ipgen_main()

#===OPEN PORT CHECKER===#
def open_port_checker():

    generate_ascii_banner("OPC", "")
    
    import socket
    import ssl

    def scan_port(target, port, timeout=0.5):
        """Scan a single port for a given target."""
        try:
            if port == 443:  # SSL/TLS port example
                context = ssl.create_default_context()
                with context.wrap_socket(socket.socket(socket.AF_INET), server_hostname=target) as sock:
                    sock.settimeout(timeout)
                    sock.connect((target, port))
                    return port, "Open"
            else:
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
                    sock.settimeout(timeout)
                    result = sock.connect_ex((target, port))
                    if result == 0:
                        return port, "Open"
                    elif result == 11:
                        return port, "Closed"
                    else:
                        return port, "Filtered"
        except Exception as e:
            return port, "Error"

    def scan_ports_for_target(target, ports, timeout=0.5):
        """Scan all ports for a given target using ThreadPoolExecutor."""
        results = {}
        with ThreadPoolExecutor(max_workers=len(ports)) as executor:
            future_to_port = {executor.submit(scan_port, target, port, timeout): port for port in ports}
            for future in as_completed(future_to_port):
                port, status = future.result()
                results[port] = status
        return results

    def scan_ports_threaded(targets, ports, num_threads=10, timeout=0.5):
        """Scan ports for multiple targets using multiple threads, processing them in chunks."""
        results_dict = {}
        with ThreadPoolExecutor(max_workers=num_threads) as executor:
            future_to_target = {executor.submit(scan_ports_for_target, target, ports, timeout): target for target in targets}
            for future in as_completed(future_to_target):
                target = future_to_target[future]
                results_dict[target] = future.result()
        return results_dict

    def print_results(results_dict, ports):
        """Print results in a table format with ports as columns and domains/IPs as rows."""
        headers = ['Domain/IP'] + [str(port) for port in ports]
        separator_line = "+" + "+".join(["-" * len(header) for header in headers]) + "+" 
        header_line = "|" + "|".join([f" {header} " for header in headers]) + "|"

        print(separator_line)
        print(header_line)
        print(separator_line.replace("-", "="))  # Double separator below headers

        rows = []
        for target, results in results_dict.items():
            open_ports = {port: status for port, status in results.items() if status == "Open"}
            if open_ports:
                row = [target] + [f"{port} {results[port]}" if results[port] == "Open" else "Closed" for port in ports]
                row_line = "|" + "|".join([f" {cell} " for cell in row]) + "|"
                rows.append(row_line)
                print(row_line)
                print(separator_line)

        return "\n".join([separator_line, header_line, separator_line.replace("-", "=")] + rows + [separator_line])

    def save_to_file(filename, data, results_dict, ports):
        """Save data to a file, including only targets with open ports."""
        with open(filename, "w") as file:
            headers = ['Domain/IP'] + [str(port) for port in ports]
            separator_line = "+" + "+".join(["-" * len(header) for header in headers]) + "+"
            header_line = "|" + "|".join([f" {header} " for header in headers]) + "|"

            file.write(separator_line + "\n")
            file.write(header_line + "\n")
            file.write(separator_line.replace("-", "=") + "\n")

            for target, results in results_dict.items():
                open_ports = {port: status for port, status in results.items() if status == "Open"}
                if open_ports:
                    row = [target] + [f"{port} Open" if results[port] == "Open" else "Closed" for port in ports]
                    row_line = "|" + "|".join([f" {cell} " for cell in row]) + "|"
                    file.write(row_line + "\n")
                    file.write(separator_line + "\n")

        print(f"Results saved to {filename}")

    def open_port_checker_main():
        ports = [80, 8080, 443, 21, 22, 53, 67, 68, 123, 161, 162, 500, 520, 514, 5353, 4500, 1900, 5000, 3000]
        """main function to handle user inputs and initiate scanning."""
        try:
            input_type = input("Select input type (1: Domain/IP, 2: Domain List/IP List): ")
            results_dict = {}

            if input_type == "1":  # Single domain
                target = input("Enter the domain or IP: ")
                num_threads = int(input("Enter the number of threads: "))
                results_dict = scan_ports_threaded([target], ports, num_threads)

            elif input_type == "2":  # Domain list from file
                filename = input("Enter the filename containing the domain list: ")
                with open(filename, "r") as file:
                    targets = [line.strip() for line in file]

                num_threads = int(input("Enter the number of threads: "))
                results_dict = scan_ports_threaded(targets, ports, num_threads)

            table_str = print_results(results_dict, ports)

            save_file = input("Do you want to save the results to a file? (Y/N): ")
            if save_file.lower() == "y":
                filename = input("Enter the filename to save the results: ")
                save_to_file(filename, table_str, results_dict, ports)

        except Exception as e:
            print("An error occurred:", e)

        # Define ports to scan

    open_port_checker_main()

#===UDP TCP===#
def udp_tcp():
    
    generate_ascii_banner("UDP", "TCP")

    import socket
    import ssl
    import os
    import re
    import requests
    import dns.resolver
    import ipaddress
    from concurrent.futures import ThreadPoolExecutor, as_completed
    import time

    # Constants
    SAVE_FILE = 'scan_results.txt'
    TIMEOUT = 1.5  # Reduced timeout from 2 to 1.5 seconds
    MAX_THREADS = 100  # Increased thread pool size

    # Optimized port list - focusing on most common ports first
    COMMON_PORTS = [
        80, 443, 22, 21, 25, 53, 110, 143, 465, 587, 993, 995,  # Common web/email
        3389, 3306, 5432, 27017, 1521, 1433,  # Database ports
        8080, 8443, 8888, 8000,  # Alternative web ports
        161, 162, 137, 139, 445,  # Network services
        23, 69, 123, 514,  # Misc services
    ]

    # Dictionary for common UDP ports with payloads (optimized for most common first)
    common_ports_payloads = {
        53: b'\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\x01\x00\x01',  # DNS
        123: b'\x1b' + 47 * b'\0',  # NTP
        161: b'\x30\x26\x02\x01\x00\x04\x06public\xa0\x19\x02\x04\x13\x79\xf9\xa9\x02\x01\x00\x02\x01\x00\x30\x0b\x30\x09\x06\x05\x2b\x06\x01\x02\x01\x05\x00',  # SNMP
        137: b'\x82\x28\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x20\x43\x4B\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x00\x00\x21\x00\x01',  # NetBIOS
        500: b'\x00' * 100,  # ISAKMP
        1900: b'M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:"ssdp:discover"\r\nMX:1\r\nST:ssdp:all\r\n',  # SSDP
        # Removed less common UDP ports to speed up scanning
    }

    def send_udp_packet(ip, port, payload):
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
            sock.settimeout(TIMEOUT)
            try:
                sock.sendto(payload, (ip, port))
                data, _ = sock.recvfrom(1024)
                return data
            except (socket.timeout, ConnectionResetError):
                return None
            except Exception as e:
                return None

    def detect_net_server(ip, port):
        try:
            with socket.create_connection((ip, port), timeout=TIMEOUT) as sock:
                sock.settimeout(TIMEOUT)
                sock.sendall(b"HEAD / HTTP/1.0\r\n\r\n")
                data = sock.recv(1024)
                return f"Inferred Net Server: {parse_net_server(data)}"
        except Exception:
            return "Unknown Net Server"

    def parse_net_server(data):
        try:
            text = data.decode('utf-8', errors='ignore').lower()
            return "Unknown Net Server"
        except Exception:
            return "Unknown Net Server"


    def service_detection(ip, port):
        try:
            # HTTP
            if port == 80:
                response = requests.head(f'http://{ip}', timeout=TIMEOUT, allow_redirects=True)
                server = response.headers.get('Server', '').strip()
                if not server:
                    return detect_net_server(ip, port)
                return f"HTTP Service: {server}"
            
            # HTTPS
            elif port == 443:
                response = requests.head(f'https://{ip}', timeout=TIMEOUT, verify=False, allow_redirects=True)
                server = response.headers.get('Server', '').strip()
                if not server:
                    return detect_net_server(ip, port)
                return f"HTTPS Service: {server}"
            
            # SSH
            elif port == 22:
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                    s.settimeout(TIMEOUT)
                    s.connect((ip, port))
                    banner = s.recv(1024).decode('utf-8', errors='ignore').strip()
                    return f"SSH Banner: {banner}"

            # Common TCP services with banners
            elif port in [21, 3306, 5432, 27017]:
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                    s.settimeout(TIMEOUT)
                    s.connect((ip, port))
                    banner = s.recv(1024).decode('utf-8', errors='ignore').strip()
                    return f"Banner: {banner[:100]}"

            # UDP - optional but fragile (SNMP, NTP)
            elif port in [53, 161, 123, 500, 1900]:
                with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
                    s.settimeout(TIMEOUT)
                    s.sendto(b'\x00', (ip, port))
                    data, _ = s.recvfrom(1024)
                    if data:
                        return f"UDP Response: {data[:100]}"
            
            # Generic TCP banner grabbing fallback
            elif port in COMMON_PORTS:
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                    s.settimeout(TIMEOUT)
                    s.connect((ip, port))
                    banner = s.recv(1024).decode(errors='ignore').strip()
                    return f"TCP Banner: {banner[:100]}"

        except Exception:
            return "Service detected"

        return "Unknown service"


    def fast_tcp_scan(ip, ports, scan_results):
        def check_port(ip, port):
            try:
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                    s.settimeout(TIMEOUT)
                    result = s.connect_ex((ip, port))
                    if result == 0:
                        service = service_detection(ip, port)
                        return port, f"TCP open - {service}"
            except Exception:
                pass
            return None, None

        with ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
            futures = [executor.submit(check_port, ip, port) for port in ports]
            for future in as_completed(futures):
                port, status = future.result()
                if port:
                    scan_results[port] = status

    def fast_udp_scan(ip, ports, scan_results):
        def check_udp_port(ip, port):
            payload = common_ports_payloads.get(port, b'')
            response = send_udp_packet(ip, port, payload)
            if response is not None:
                service = service_detection(ip, port)
                return port, f"UDP open - {service}"
            return None, None

        with ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
            futures = [executor.submit(check_udp_port, ip, port) for port in ports if port in common_ports_payloads]
            for future in as_completed(futures):
                port, status = future.result()
                if port:
                    scan_results[port] = status

    def scan_target(ip):
        scan_results = {}
        print(f"Scanning {ip}...", end='\r')
        
        # Scan TCP ports first (faster)
        fast_tcp_scan(ip, COMMON_PORTS, scan_results)
        
        # Only scan UDP if we found open TCP ports (heuristic to save time)
        if scan_results:
            fast_udp_scan(ip, COMMON_PORTS, scan_results)
        
        # SSL check only if 443 is open
        if 443 in COMMON_PORTS and any(p == 443 for p in scan_results):
            try:
                context = ssl.create_default_context()
                with socket.create_connection((ip, 443), timeout=TIMEOUT) as sock:
                    with context.wrap_socket(sock, server_hostname=ip) as sslsock:
                        cert = sslsock.getpeercert()
                        scan_results['SSL'] = f"Certificate: {cert.get('subject', '')}"
            except Exception:
                pass

        return scan_results

    def batch_scan(targets):
        all_results = {}
        with ThreadPoolExecutor(max_workers=100) as executor:  # Scan multiple IPs in parallel
            future_to_ip = {executor.submit(scan_target, ip): ip for ip in targets}
            for future in as_completed(future_to_ip):
                ip = future_to_ip[future]
                try:
                    results = future.result()
                    if results:
                        all_results[ip] = results
                except Exception as e:
                    print(f"Error scanning {ip}:")
        return all_results



    def get_targets_from_input(input_str):
        targets = set()
        try:
            if os.path.isfile(input_str):
                with open(input_str) as f:
                    lines = f.readlines()
                    for line in lines:
                        line = line.strip()
                        targets.update(get_targets_from_input(line))
            elif "/" in input_str:  # CIDR
                net = ipaddress.ip_network(input_str, strict=False)
                targets.update(str(ip) for ip in net.hosts())
            elif re.match(r"^\d{1,3}(\.\d{1,3}){3}$", input_str):  # IP
                targets.add(input_str)
            else:  # Domain
                try:
                    ip = socket.gethostbyname(input_str)
                    targets.add(ip)
                except:
                    print(f"Failed to resolve domain: {input_str}")
        except Exception as e:
            print(f"Error processing input:")
        return list(targets)

    def save_results_to_file(results):
        with open(SAVE_FILE, "w") as f:
            for ip, ports in results.items():
                f.write(f"\n[+] {ip}\n")
                for port, info in ports.items():
                    f.write(f"  {port}: {info}\n")


    def udp_tcp_main098():
        user_input = input("Enter IP/URL/CIDR or file path: ")
        targets = get_targets_from_input(user_input)
        
        if not targets:
            print("No valid targets found.")
            return
        
        start_time = time.time()
        all_results = batch_scan(targets)
        elapsed = time.time() - start_time
        
        save_results_to_file(all_results)
        print(f"\nScanned {len(targets)} targets in {elapsed:.2f} seconds")
        print(f"Results saved to '{SAVE_FILE}'")

    if __name__ == "__main__":
        udp_tcp_main098()

#===TCP SSL===#
def tcp_ssl():

    generate_ascii_banner("TCP", "SSL")
    # Supported SSL/TLS versions
    SSL_VERSIONS = {
        "SSLv1": ssl.PROTOCOL_SSLv23,  # Legacy compatibility
        "SSLv2": ssl.PROTOCOL_SSLv23,  # Python removed explicit SSLv2
        "SSLv3": ssl.PROTOCOL_SSLv23,  # Legacy fallback
        "TLSv1.0": ssl.PROTOCOL_TLSv1,
        "TLSv1.1": ssl.PROTOCOL_TLSv1_1,
        "TLSv1.2": ssl.PROTOCOL_TLSv1_2,
    }

    # Parse input for IPs, CIDRs, hostnames, or files
    def parse_input(user_input):
        try:
            if user_input.endswith(".txt"):  # If it's a file
                with open(user_input, 'r') as f:
                    entries = [line.strip() for line in f.readlines()]
                    targets = []
                    for entry in entries:
                        if '/' in entry:  # Handle CIDR
                            targets.extend([str(ip) for ip in ipaddress.IPv4Network(entry, strict=False)])
                        else:
                            targets.append(entry)
                    return targets
            elif '/' in user_input:  # CIDR range
                return [str(ip) for ip in ipaddress.IPv4Network(user_input, strict=False)]
            else:
                socket.gethostbyname(user_input)  # Validate hostname/IP
                return [user_input]
        except Exception as e:
            print(f"Invalid input: {e}")
            return []

    # Check if a port is open via TCP
    def tcp_connect(ip, port, timeout=3):
        try:
            with socket.create_connection((ip, port), timeout=timeout):
                return True
        except Exception:
            return False

    # Save results to a file
    def save_result(result, filename):
        try:
            with open(filename, "a") as f:
                f.write(result + "\n")
        except Exception as e:
            print(f"Error saving result: {e}")

    # Fetch SSL/TLS information
    def check_ssl_versions(ip, port):
        results = []
        for version_name, protocol in SSL_VERSIONS.items():
            try:
                context = ssl.SSLContext(protocol)
                with socket.create_connection((ip, port), timeout=5) as sock:
                    with context.wrap_socket(sock, server_hostname=ip) as ssock:
                        ssock.getpeercert()
                        results.append(f"{version_name} supported")
            except Exception:
                results.append(f"{version_name} not supported")
        return results

    # Extract HTTP status and banner
    def scan_target(ip, ports, output_file):
        for port in ports:
            if tcp_connect(ip, port):
                result = f"[+] {ip}:{port} is open"

                if port in [80, 443]:
                    try:
                        url = f"http://{ip}" if port == 80 else f"https://{ip}"
                        response = requests.get(url, timeout=5)
                        server = response.headers.get('Server', 'Unknown')
                        status = response.status_code

                        ssl_info = ""
                        if port == 443:
                            ssl_results = check_ssl_versions(ip, port)
                            ssl_info = " | ".join(ssl_results)

                        result = f"[+] {ip}:{port} - {server} - HTTP {status} - {ssl_info}"
                        print(result)
                        save_result(result, output_file)
                    except Exception:
                        result = f"[-] {ip}:{port} - Failed to fetch HTTP/HTTPS banner"
                        print(result)
                        save_result(result, output_file)


    # main function
    def tcp_ssl_main():
        user_input = input("Enter IP, CIDR, hostname, or file: ").strip()
        if not user_input:
            print("No input provided.")
            return
        targets = parse_input(user_input)

        if not targets:
            print("No valid targets found.")
            return

        ports = [80, 443, 22, 21, 3389, 53, 5353]  # Common ports to check

        output_file = input("Enter output file name (default: scan_results.txt): ").strip()
        if not output_file:
            output_file = "scan_results.txt"
        #if not output_file:
        #    output_file = "scan_results.txt"

        # Clear output file if it already exists
        if os.path.exists(output_file):
            os.remove(output_file)

        with ThreadPoolExecutor(max_workers=50) as executor:
            futures = [executor.submit(scan_target, target, ports, output_file) for target in targets]

            for _ in tqdm(as_completed(futures), total=len(futures), desc="Scanning Progress", unit="target"):
                pass

        print(f"Scan completed! Results saved to {output_file}")

    tcp_ssl_main()

#===DORK SCANNER===#
def dork_scanner():
    
    #GREEN, RED = '\033[1;32m', '\033[91m'
    
    generate_ascii_banner("DORK", "SCANNER")

    def get_user_input():
        url = input('[?] Enter the URL to look up: ')
        pages = input('[?] Enter the number of pages to search (Default: 1): ')
        if not pages:
            pages = 1
        output_file = input('[?] Enter the output file name: ')
        return url, int(pages), output_file

    def google_search(query, page):
        base_url = 'https://www.google.com/search'
        headers  = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0' }
        params   = { 'q': query, 'start': page * 10 }
        resp = requests.get(base_url, params=params, headers=headers)
        soup = bsoup(resp.text, 'html.parser')
        links  = soup.findAll('cite')
        result = [link.text for link in links]
        return result

    def bing_search(query, page):
        base_url = 'https://www.bing.com/search'
        headers  = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0' }
        params   = { 'q': query, 'first': page * 10 + 1 }
        resp = requests.get(base_url, params=params, headers=headers)
        soup = bsoup(resp.text, 'html.parser')
        links  = soup.findAll('cite')
        result = [link.text for link in links]
        return result

    def ask_search(query, page):
        base_url = 'https://www.ask.com/search'
        headers  = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0' }
        params   = { 'q': query, 'first': page * 10 + 1 }
        resp = requests.get(base_url, params=params, headers=headers)
        soup = bsoup(resp.text, 'html.parser')
        links  = soup.findAll('cite')
        result = [link.text for link in links]
        return result

    def yandex_search(query, page):
        base_url = 'https://www.yahoo.com/search'
        headers  = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0' }
        params   = { 'q': query, 'first': page * 10 + 1 }
        resp = requests.get(base_url, params=params, headers=headers)
        soup = bsoup(resp.text, 'html.parser')
        links  = soup.findAll('cite')
        result = [link.text for link in links]
        return result

    def duckgo_search(query, page):
        base_url = 'https://duckduckgo.com/html'
        headers  = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0' }
        params   = { 'q': query, 's': page * 30 }  # Adjusting page parameter here
        resp = requests.post(base_url, data=params, headers=headers)
        soup = bsoup(resp.text, 'html.parser')
        links  = soup.findAll('cite')
        result = [link.text for link in links]
        return result

    def save_results(filename, results):
        unique_urls = set()  # Create a set to store unique URLs
        with open(filename, 'w') as file:
            for result_list in tqdm(results, desc="Saving Results", unit="page"):
                for result in result_list:
                    if result not in unique_urls:  # Check if the URL is unique
                        file.write(result + '\n')
                        unique_urls.add(result)  # Add the URL to the set of unique URLs

    def dork_scanner_main():
        print()
        url, pages, output_file = get_user_input()

        engines = [google_search, bing_search, yandex_search, duckgo_search, ask_search]

        results = []
        for engine in tqdm(engines, desc="Search Engines", unit="engine"):
            result = []
            for page_num in range(pages):
                result.extend(engine(url, page_num))
            results.append(result)

        print('-' * 70)
        print(f'Searching for: {url} in {pages} page(s) of all engines')
        print('-' * 70)
        print()

        counter = 0
        for result in results:
            for r in result:
                print('[+] ' + r)
                counter += 1

        print()
        print('-' * 70)
        print(f'Number of URLs: {counter}')
        print('-' * 70)

        if output_file:
            save_results(output_file, results)
            print(f'Results saved to {output_file}')

    dork_scanner_main()

#===NS LOOKUP===#
def nslookup():
    from requests.exceptions import RequestException, Timeout
    
    generate_ascii_banner("NS", "LOOKUP")

    def generate_url(website, page):
        if page == 1:
            return f"http://www.sitedossier.com/nameserver/{website}/{page}",
        else:
            return f"http://www.sitedossier.com/nameserver/{website}/{(page-1)*100 + 1}"

    def fetch_table_data(url, proxies=None):
        try:
            response = requests.get(url, proxies=proxies, timeout=4)
            response.raise_for_status()
            if response.status_code == 404:
                print("Job done.")
                return False, None
            if "Please enter the unique \"word\" below to confirm" in response.text:
                return False, None
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')
                table = soup.find('table')
                if table:
                    rows = table.find_all('tr')
                    data = []
                    for row in rows:
                        cells = row.find_all('td')
                        if cells:
                            row_data = [cell.text.strip() for cell in cells if cell.text.strip()]
                            if row_data:
                                data.append('\n'.join(row_data))
                    return True, data
                else:
                    print("No table found on page:")
        except Timeout:
            print("Timeout occurred while fetching data")
        except RequestException as e:
            print("Error occurred while fetching data:")
        return False, None

    def load_domains_from_file(filename):
        domains = []
        with open(filename, 'r') as file:
            for line in file:
                domains.append(line.strip())
        return domains

    def load_proxies_from_file(filename):
        proxies = []
        with open(filename, 'r') as file:
            for line in file:
                proxies.append(line.strip())
        return proxies

    def save_to_file(filename, data):
        with open(filename, 'a') as file:
            for item in data:
                file.write(item.strip())
                file.write('\n')

    def fetch_data(url, proxies, save_file, output_file):
        if proxies:
            proxy_index = 0
            while True:
                success, data = fetch_table_data(url, proxies={'http': proxies[proxy_index], 'https': proxies[proxy_index]})
                if success:
                    print("Data fetched successfully from:", url)
                    for item in data:
                        print(item)
                    if save_file == "yes":
                        save_to_file(output_file, data)
                    break
                else:
                    print("Retrying with a different proxy...")
                    proxy_index = (proxy_index + 1) % len(proxies)
                    if proxy_index == 0:
                        print("No more proxies to try. Moving to the next URL.")
                        break
        else:
            success, data = fetch_table_data(url)
            if success:
                print("Data fetched successfully from:", url)
                for item in data:
                    print(item)
                if save_file == "yes":
                    save_to_file(output_file, data)

    def nslookup_main():
        input_type = input("Choose input type (single/file): ").lower()
        
        if input_type == "single":
            website = input("Enter the website (e.g., ns1.google.com): ")
            num_pages = int(input("Enter the number of pages to fetch: "))
            urls = [generate_url(website, page) for page in range(1, num_pages + 1)]
            
        elif input_type == "file":
            domain_list_file = input("Enter the filename containing list of domains: ")
            domains = load_domains_from_file(domain_list_file)
            num_pages = int(input("Enter the number of pages to fetch per domain: "))
            urls = []
            for domain in domains:
                urls.extend([generate_url(domain, page) for page in range(1, num_pages + 1)])
        else:
            print("Invalid input type. Exiting.")
            return
        
        use_proxy = input("Do you want to use a proxy? (yes/no): ").lower()
        if use_proxy == "yes":
            proxy_list_name = input("Enter the proxy list file name: ")
            proxies = load_proxies_from_file(proxy_list_name)
        else:
            proxies = None
        
        save_file = input("Do you want to save the output data to a file? (yes/no): ").lower()
        if save_file == "yes":
            output_file = input("Enter the filename to save the output data (without extension): ") + ".txt"
        else:
            output_file = None
            print("Output will not be saved to a file.")


        
        with ThreadPoolExecutor(max_workers=10) as executor:
            futures = []
            for url in urls:
                futures.append(executor.submit(fetch_data, url, proxies, save_file, output_file))

        for future in futures:
            future.result()

        print("All tasks completed.")

    nslookup_main()

#================ File Processing Menu ============================#
def Processing_menu():
    while True:
        clear_screen()
        banner()
        print(MAGENTA +"==============================="+ ENDC)
        print(MAGENTA +"               Menu            "+ ENDC)    
        print (MAGENTA +"=============================="+ ENDC)
        print("1. File Processing")
        print("2. File Explorer")
        print("Hit enter to return to the main menu",'\n')
        choice = input("Enter your choice: ")
        if choice == '':
            randomshit("Returning to BUGHUNTERS PRO...")
            time.sleep(2)
            return

        elif choice == '1':
            clear_screen()
            file_proccessing() 
        elif choice == '2':
            clear_screen()
            file_explorer()                                                                                        
        else:
            randomshit("Returning to BUGHUNTERS PRO...")
            return
    
def file_proccessing():
    
    generate_ascii_banner("FP", "")

    print("""
        ============================
        File Processing Script   
        ============================
        """)

    def split_input_file(filename, output_base):
        split_files = []  # List to store the names of split files
        with open(filename, 'r') as file:
            lines = file.readlines()
            num_lines = len(lines)
            print(f"The file '{filename}' has {num_lines} lines.")
            
            while True:
                try:
                    parts = int(input("How many parts do you want to split the file into? "))
                    if parts <= 0:
                        raise ValueError("Number of parts must be a positive integer.")
                    break
                except ValueError as e:
                    print("Error:", e)

            lines_per_part = num_lines // parts
            remainder = num_lines % parts

            start = 0
            for i in range(parts):
                end = start + lines_per_part + (1 if i < remainder else 0)
                part_filename = f"{output_base}_part_{i + 1}.txt"
                with open(part_filename, 'w') as out_file:
                    out_file.writelines(lines[start:end])
                split_files.append(part_filename)
                print(f"Wrote {end - start} lines to {part_filename}")
                start = end

        return split_files  # Return the list of split file names

    def calculate_cidr_blocks(ip_ranges):
        ipv4_cidr_blocks = []
        ipv6_cidr_blocks = []
        for start, end in ip_ranges:
            try:
                start_ip = ipaddress.ip_address(start)
                end_ip = ipaddress.ip_address(end)
                cidr = ipaddress.summarize_address_range(start_ip, end_ip)
                for block in cidr:
                    if block.version == 4:
                        ipv4_cidr_blocks.append(str(block))
                    elif block.version == 6:
                        ipv6_cidr_blocks.append(str(block))
            except ValueError:
                continue  # Skip invalid ranges
        return ipv4_cidr_blocks, ipv6_cidr_blocks

    def extract_ip_ranges(lines):
        ip_ranges = []
        for line in lines:
            parts = line.strip().split('\t')
            if len(parts) >= 2:
                ip_ranges.append((parts[0], parts[1]))
        return ip_ranges

    def save_cidr_blocks(output_file, cidr_blocks):
        with open(output_file, 'w') as file:
            for block in cidr_blocks:
                file.write(block + '\n')

    def remove_duplicates(lines):
        return list(set(lines))  # Remove duplicate lines

    def extract_domains(lines, output_file):
        domains = []
        for line in lines:
            domain_matches = re.findall(r'(?:(?:http|https)://)?(?:\*\\www\.)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,63})', line)
            domains.extend(domain_matches)
        
        domains = list(set(domains))  # Remove duplicate domains

        if domains:  # Only write if there are domains to save
            with open(output_file, 'w') as out_file:
                for domain in domains:
                    clean_domain = domain.lstrip('*.')  # Remove '*' and '.' from the start
                    out_file.write(f"{clean_domain}\n")

            print(f"Domains saved to {output_file}")
        else:
            print(f"No domains found. Skipping file creation for {output_file}.")


    def extract_ips(lines, output_file):
        ips = []
        for line in lines:
            ip_matches = re.findall(r'\b(?:\d{1,3}\.){3}\d{1,3}\b', line)
            ips.extend(ip_matches)
        
        ips = list(set(ips))  # Remove duplicate IPs

        if ips:  # Only write if there are IPs to save
            with open(output_file, 'w') as out_file:
                for ip in ips:
                    out_file.write(f"{ip}\n")

            print(f"IPs saved to {output_file}")
        else:
            print(f"No IPs found. Skipping file creation for {output_file}.")


    def process_file(input_filename):
        if not os.path.exists(input_filename):
            print("Error: File does not exist.")
            return

        base_filename, _ = os.path.splitext(input_filename)

        # Step 1: Read and remove duplicates from the entire file before splitting
        with open(input_filename, 'r') as f:
            lines = f.readlines()

        if not lines:  # Check if file is empty
            print("Error: File is empty.")
            return

        unique_lines = remove_duplicates(lines)  # Remove duplicates here

        if not unique_lines:  # If no unique lines remain, stop processing
            print("Error: No unique data found in the file.")
            return

        # Step 2: Write back the unique lines to a temporary file for splitting
        temp_file = f"{base_filename}_unique_temp.txt"
        with open(temp_file, 'w') as f:
            f.writelines(unique_lines)

        split_option = input("Do you want to split the file? (yes/no): ").lower()
        if split_option in ('yes', 'y'):
            split_output_files = split_input_file(temp_file, base_filename)
            print(f"Split output files: {split_output_files}")
        else:
            split_output_files = [temp_file]  # Use the unique temp file if no splitting

        # Process each split file (or the original if not split) as before
        for split_file in split_output_files:
            with open(split_file, 'r') as f:
                lines = f.readlines()

            if not lines:  # Skip empty split files
                continue

            unique_lines = remove_duplicates(lines)

            if not unique_lines:  # If after deduplication nothing remains, skip
                continue

            ip_ranges = extract_ip_ranges(unique_lines)
            ipv4_cidr_blocks, ipv6_cidr_blocks = calculate_cidr_blocks(ip_ranges)

            # Only save files if they have data
            if ipv4_cidr_blocks:
                ipv4_output_file = f"{base_filename}_ipv4_cidr.txt"
                save_cidr_blocks(ipv4_output_file, ipv4_cidr_blocks)

            if ipv6_cidr_blocks:
                ipv6_output_file = f"{base_filename}_ipv6_cidr.txt"
                save_cidr_blocks(ipv6_output_file, ipv6_cidr_blocks)

            if unique_lines:
                domain_output_file = f"{base_filename}_domains.txt"
                extract_domains(unique_lines, domain_output_file)

                ip_output_file = f"{base_filename}_ips.txt"
                extract_ips(unique_lines, ip_output_file)

        time.sleep(2)
        print("All operations completed.")

        # Cleanup: Optionally delete the temporary unique file
        if os.path.exists(temp_file):
            os.remove(temp_file)

    input_filename = input("Enter the name of the file to be processed: ")
    process_file(input_filename)

def file_explorer():

    generate_ascii_banner("File Explorer", "")

    import os
    import shutil
    from InquirerPy import prompt
    from InquirerPy.validator import PathValidator


    def list_files(directory="."):
        try:
            return [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]
        except Exception:
            return []


    def list_dirs(directory="."):
        try:
            return [d for d in os.listdir(directory) if os.path.isdir(os.path.join(directory, d))]
        except Exception:
            return []


    def navigate_directories(start_dir="."):
        clear_screen()
        current_dir = os.path.abspath(start_dir)

        while True:
            dirs = list_dirs(current_dir)
            choices = [".. (Go Up)", "✔ Select this directory", "⬅ Back to Main Menu"] + dirs

            answer = prompt([
                {
                    "type": "list",
                    "message": f"Current directory:\n{current_dir}",
                    "choices": choices,
                    "name": "selection",
                    "qmark": "📂"
                }
            ])["selection"]

            if answer == ".. (Go Up)":
                current_dir = os.path.dirname(current_dir)
            elif answer == "✔ Select this directory":
                return current_dir
            elif answer == "⬅ Back to Main Menu":
                return None
            else:
                current_dir = os.path.join(current_dir, answer)


    def select_file(start_dir="."):
        clear_screen()
        current_dir = os.path.abspath(start_dir)

        while True:
            files = list_files(current_dir)
            dirs = list_dirs(current_dir)
            choices = [".. (Go Up)", "⬅ Back to Main Menu"] + dirs + files

            if not choices:
                print("No files or directories found.")
                return None

            answer = prompt([
                {
                    "type": "list",
                    "message": f"Current directory:\n{current_dir}",
                    "choices": choices,
                    "name": "selection",
                    "qmark": "📁",
                    "amark": " ",
                }
            ])["selection"]

            if answer == ".. (Go Up)":
                current_dir = os.path.dirname(current_dir)
            elif answer == "⬅ Back to Main Menu":
                return None
            elif os.path.isdir(os.path.join(current_dir, answer)):
                current_dir = os.path.join(current_dir, answer)
            else:
                return os.path.join(current_dir, answer)


    def open_file():
        clear_screen()
        selected = select_file()
        if not selected or not os.path.isfile(selected):
            return

        try:
            with open(selected, 'r', encoding="utf-8") as file:
                print(f"\n📄 Contents of {selected}:\n")
                print(file.read())
        except Exception as e:
            print(f"❌ Error reading file: {e}")

        input("\nPress Enter to return to menu...")


    def move_file():
        clear_screen()
        src = select_file()
        if not src:
            return

        dst = navigate_directories()
        if not dst:
            return

        try:
            shutil.move(src, dst)
            print(f"✅ Moved '{src}' to '{dst}'")
        except Exception as e:
            print(f"❌ Failed to move file: {e}")
        input("\nPress Enter to return to menu...")


    def rename_file():
        clear_screen()
        file = select_file()
        if not file:
            return

        new_name = prompt([
            {
                "type": "input",
                "message": f"Rename '{os.path.basename(file)}' to:",
                "name": "newname",
                "validate": lambda x: len(x.strip()) > 0
            }
        ])["newname"]

        new_path = os.path.join(os.path.dirname(file), new_name)
        try:
            os.rename(file, new_path)
            print(f"✅ Renamed to {new_path}")
        except Exception as e:
            print(f"❌ Failed to rename: {e}")
        input("\nPress Enter to return to menu...")


    def remove_file():
        clear_screen()
        file = select_file()
        if not file:
            return

        confirm = prompt([
            {
                "type": "confirm",
                "message": f"Are you sure you want to delete:\n{file}?",
                "name": "confirm",
                "default": False
            }
        ])["confirm"]

        if confirm:
            try:
                os.remove(file)
                print(f"✅ Deleted {file}")
            except Exception as e:
                print(f"❌ Error deleting file: {e}")
        input("\nPress Enter to return to menu...")


    def main():
        while True:
            clear_screen()
            answer = prompt([
                {
                    "type": "list",
                    "message": "🛠 File Manager - Choose an action:",
                    "choices": ["📂 Move", "🗑 Remove", "✏ Rename", "📖 Open", "❌ Exit"],
                    "name": "action",
                    "qmark": ""
                }
            ])["action"]

            if "Move" in answer:
                move_file()
            elif "Remove" in answer:
                remove_file()
            elif "Rename" in answer:
                rename_file()
            elif "Open" in answer:
                open_file()
            elif "Exit" in answer:
                clear_screen()
                print("👋 Goodbye!")
                break


    if __name__ == "__main__":
        main()

#================ V2ray configs menu ==============================#
def Configs_V2ray_menu():
    while True:
        clear_screen()
        banner()
        print(MAGENTA +"=================================="+ ENDC)
        print(MAGENTA +"               Menu            "+ ENDC)    
        print (MAGENTA +"=================================="+ ENDC)

        print("1. [new]Vmess/Trojan/Vless       2. [old]Vmess/Trojan/Vless")
        print("Hit enter to return to the main menu",'\n')
        choice = input("Enter your choice: ")
        if choice == '':
            randomshit("Returning to BUGHUNTERS PRO...")
            time.sleep(1)
            clear_screen()
            banner()
            main_menu()
            main()

        elif choice == '1':
            clear_screen()
            teamerror_new()  
        elif choice == '2':
            clear_screen()
            teamerror()                                                                                  
        else:
            randomshit("Returning to BUGHUNTERS PRO...")
            time.sleep(2)
            return  # Return to the main men
    
def teamerror_new():
    
    generate_ascii_banner("404", "ERROR")

    class V2RayConfigUpdater:
        def __init__(self):
            self.cache_timeout = 300
            self.timeout_duration = 10
            self.subscription_urls = {
                "vless": "https://github.com/Epodonios/v2ray-configs/raw/main/Splitted-By-Protocol/vless.txt",
                "vmess": "https://github.com/Epodonios/v2ray-configs/raw/main/Splitted-By-Protocol/vmess.txt",
                "trojan": "https://github.com/Epodonios/v2ray-configs/raw/main/Splitted-By-Protocol/trojan.txt"
            }
            self.new_server_ips = self.prompt_for_ip()
            self.last_fetch_time = 0
            self.cached_configs = None
            self.modified_configs = {'vmess': [], 'vless': [], 'trojan': []}

        def prompt_for_ip(self):
            new_ips = []
            while True:
                ip = input("Enter a new host or IP address (or type 'done' to finish): ").strip()
                if ip.lower() == 'done':
                    break
                new_ips.append(ip)
            return new_ips

        def prompt_for_configuration_choice(self):
            print(MAGENTA + "Available configuration types:" + ENDC)
            for i, key in enumerate(self.subscription_urls.keys(), start=1):
                print(CYAN + f"{i}. {key.upper()}" + ENDC)
            
            while True:
                try:
                    choice = int(input("Enter the number corresponding to the configuration type you want to fetch: "))
                    if 1 <= choice <= len(self.subscription_urls):
                        selected_key = list(self.subscription_urls.keys())[choice - 1]
                        return selected_key
                    else:
                        print(FAIL + "Invalid choice. Please enter a number from the list.")
                except ValueError:
                    print(FAIL + "Invalid input. Please enter a valid number.")

        def extract_vless_server_ip(self, vless_url):
            try:
                at_symbol_index = vless_url.index('vless://') + len('vless://')
                server_ip_start = vless_url.index('@', at_symbol_index) + 1
                server_ip_end = vless_url.index(':', server_ip_start)
                return vless_url[server_ip_start:server_ip_end]
            except (ValueError, IndexError):
                return None

        def remove_duplicates(self, configs):
            return list(set(configs))

        def fetch_configs(self, url, methods=('GET',)):
            current_time = time.time()
            if current_time - self.last_fetch_time < self.cache_timeout and self.cached_configs:
                print(YELLOW + "USING CACHED CONFIGURATIONS." + ENDC)
                return self.cached_configs

            for method in methods:
                print(random.choice([FAIL, LIME, BLUE]) + f"TRYING {method} METHOD..." + ENDC)
                try:
                    response = requests.request(method, url, timeout=self.timeout_duration)
                    response.raise_for_status()
                    content = response.content.strip()
                    decoded_content = None
                    for encoding in ('utf-8', 'ISO-8859-1'):
                        try:
                            decoded_content = content.decode(encoding)
                            break
                        except UnicodeDecodeError:
                            continue
                    if decoded_content:
                        print(LIME+ "SUCCESSFULL" + ENDC)
                        self.cached_configs = decoded_content
                        self.last_fetch_time = current_time
                        return decoded_content
                except requests.RequestException as err:
                    print(FAIL + "ERROR" + ENDC)
                    continue

            print(FAIL + "FAILED." + ENDC)
            return None

        def modify_vless_configurations(self, configs):
            unique_configs = self.remove_duplicates(configs)
            for config in unique_configs:
                if config.startswith('vless://'):
                    old_server_ip = self.extract_vless_server_ip(config)
                    if old_server_ip:
                        if ':8080' not in config:
                            if ':80' in config or ':443' in config:
                                for new_ip in self.new_server_ips:
                                    new_config = config.replace(f'@{old_server_ip}', f'@{new_ip}')
                                    self.modified_configs['vless'].append(new_config)
                            else:
                                print(FAIL + "SKIPPING" + ENDC)
                        else:
                            print(FAIL + "SKIPPING" + ENDC)
                    else:
                        print(FAIL + "SKIPPING" + ENDC)

        def modify_vmess_configurations(self, configs):
            unique_configs = self.remove_duplicates(configs)
            for config in unique_configs:
                if config.startswith('vmess://'):
                    try:
                        base64_content = config.split('://', 1)[1]
                        config_dict = json.loads(base64.b64decode(base64_content).decode('utf-8'))
                        for new_ip in self.new_server_ips:
                            updated_config_dict = config_dict.copy()
                            updated_config_dict['add'] = new_ip
                            new_config = f"vmess://{base64.b64encode(json.dumps(updated_config_dict).encode()).decode('utf-8')}"
                            self.modified_configs['vmess'].append(new_config)
                    except Exception as e:
                        print("Error processing configuration:")
                        print(FAIL + "CONFIGURATION ERROR:" + ENDC)

        def modify_trojan_configurations(self, configs):
            unique_configs = self.remove_duplicates(configs)
            for config in unique_configs:
                if config.startswith('trojan://'):
                    parts = config.split('@')
                    if len(parts) == 2:
                        header = parts[0]
                        address = parts[1].split('/')[0]
                        if ':8080' not in address:
                            if ':80' in address or ':443' in address:
                                for new_ip in self.new_server_ips:
                                    new_config = f"{header}@{new_ip}:{address.split(':')[1]}/"
                                    self.modified_configs['trojan'].append(new_config)
                            else:
                                print(FAIL + "SKIPPING" + ENDC)
                        else:
                            print(FAIL + "SKIPPING" + ENDC)
                    else:
                        print(FAIL + "SKIPPING" + ENDC)

        def save_modified_configs(self):
            for protocol, configs in self.modified_configs.items():
                if configs:
                    file_path = f"{protocol}_configurations.txt"
                    try:
                        all_configs = '\n'.join(configs)
                        with open(file_path, 'w', encoding='utf-8') as file:
                            file.write(all_configs)
                        print(CYAN + "MODIFIED {protocol.upper()} CONFIGURATIONS HAVE BEEN SAVED IN '{file_path}'." + ENDC)
                    except Exception as e:
                        print(FAIL + "ERROR SAVING MODIFIED" + ENDC)

        def main(self):
            try:
                print(MAGENTA + "CONFIGURATIONS UPDATE..." + ENDC)
                
                # Prompt user to choose configuration type
                config_choice = self.prompt_for_configuration_choice()
                url = self.subscription_urls[config_choice]
                
                print(MAGENTA + "FETCHING CONFIGURATIONS FROM SELECTED URL..." + ENDC)
                initial_configs = self.fetch_configs(url, methods=('GET', 'POST', 'PUT'))
                if initial_configs is None:
                    print(FAIL + "FAILED TO FETCH INITIAL CONFIGURATIONS. EXITING..." + ENDC)
                    return

                try:
                    decoded_content = base64.b64decode(initial_configs).decode('utf-8')
                    print(LIME + "CONTENT IS ENCODED FORMAT." + ENDC)
                except Exception:
                    decoded_content = initial_configs
                    print(LIME + "CONTENT IS IN PLAIN TEXT FORMAT." + ENDC)

                initial_protocols = {'vmess': [], 'vless': [], 'trojan': []}
                for line in decoded_content.splitlines():
                    if line.strip().startswith(('vmess://', 'vless://', 'trojan://')):
                        protocol = line.strip().split('://', 1)[0]
                        initial_protocols[protocol].append(line.strip())

                print(YELLOW + "INITIAL CONFIGURATIONS:" + ENDC)
                for protocol, configs in initial_protocols.items():
                    print(random.choice([FAIL, LIME, BLUE]) + f"{protocol.upper()}  ➤ {len(configs)}" + ENDC)

                print(MAGENTA + "PLEASE WAIT... UPDATING CONFIGURATIONS...." + ENDC)
                time.sleep(3)

                updated_configs = self.fetch_configs(url, methods=('GET', 'POST', 'PUT'))
                if updated_configs is None:
                    print(FAIL + "FAILED TO UPDATE CONFIGURATIONS. EXITING..." + ENDC)
                    return

                try:
                    decoded_content = base64.b64decode(updated_configs).decode('utf-8')
                    print(LIME + "CONTENT IS IN BASE-64 FORMAT." + ENDC)
                except Exception:
                    decoded_content = updated_configs
                    print(LIME + "CONTENT IS IN PLAIN TEXT FORMAT." + ENDC)

                updated_protocols = {'vmess': [], 'vless': [], 'trojan': []}
                for line in decoded_content.splitlines():
                    if line.strip().startswith(('vmess://', 'vless://', 'trojan://')):
                        protocol = line.strip().split('://', 1)[0]
                        updated_protocols[protocol].append(line.strip())

                print(YELLOW + "UPDATED CONFIGURATIONS:" + ENDC)
                for protocol, configs in updated_protocols.items():
                    print(random.choice([FAIL, LIME, BLUE]) + f"{protocol.upper()}  ➤ {len(configs)}" + ENDC)

                self.modify_vless_configurations(updated_protocols['vless'])
                self.modify_vmess_configurations(updated_protocols['vmess'])
                self.modify_trojan_configurations(updated_protocols['trojan'])

                self.save_modified_configs()

            except Exception as e:
                print(FAIL + "ERROR:" + ENDC)

    updater = V2RayConfigUpdater()
    updater.main()

    time.sleep(2)
        
def teamerror():
    import requests
    import time
    import base64
    import os
    from tqdm import tqdm
    import json
    from concurrent.futures import ThreadPoolExecutor
    
    os.system('cls' if os.name == 'nt' else 'clear')
    
    banner = [
        "██╗  ██╗ ██████╗ ██╗  ██╗    ███████╗██████╗ ██████╗  ██████╗ ██████╗ ",
        "██║  ██║██╔═████╗██║  ██║    ██╔════╝██╔══██╗██╔══██╗██╔═══██╗██╔══██╗",
        "███████║██║██╔██║███████║    █████╗  ██████╔╝██████╔╝██║   ██║██████╔╝",
        "╚════██║████╔╝██║╚════██║    ██╔══╝  ██╔══██╗██╔══██╗██║   ██║██╔══██╗",
        "     ██║╚██████╔╝     ██║    ███████╗██║  ██║██║  ██║╚██████╔╝██║  ██║",
        "     ╚═╝ ╚═════╝      ╚═╝    ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝ ╚═╝  ╚═╝",
    ]

    def print_banner_seamless_horizontal(banner):
        for row in banner:
            for char in row:
                print(char, end='', flush=True)
                time.sleep(0.001)
            print()
            time.sleep(0.05)

    print_banner_seamless_horizontal(banner)

    def script001():

        def fetch_and_save_data(urls, output_filename):
            all_contents = []

            for url in urls:
                response = requests.get(url)
                if response.status_code == 200:
                    content = response.text
                    all_contents.append(content)
                else:
                    print(f"Failed to retrieve content from {url}. Status code: {response.status_code}")

            if all_contents:
                with open(output_filename, 'w', encoding="utf-8") as file:
                    file.writelines(all_contents)
                print(f"Data saved to {output_filename}")
            else:
                print("No data retrieved. Output file not created.")

        def decode_base64_file(input_file):
            try:
                with open(input_file, "r", encoding="utf-8") as file:
                    data = file.read()
                decoded_data = base64.urlsafe_b64decode(data).decode('utf-8')
                with open(input_file, "a", encoding="utf-8") as file:
                    file.write(decoded_data)
                print(f"Decoded data saved to {input_file}")

            except FileNotFoundError:
                print("Input file not found.")
            except Exception as e:
                print(f"An error occurred: {str(e)}")
        

        def a1():
            link_groups = {
                "Vless Configurations": [
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/subscribe/protocols/vless",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/protocols/vless",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/channels/protocols/vless",
                ],
                "Vmess Configurations": [
                   "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/subscribe/protocols/vmess",
                   "https://raw.githubusercontent.com/barry-far/V2ray-Configs/main/Splitted-By-Protocol/vmess.txt",
                   "https://raw.githubusercontent.com/resasanian/Mirza/main/best",
                   "https://raw.githubusercontent.com/hkpc/V2ray-Configs/main/Splitted-By-Protocol/vmess.txt",
                               
                ],
                "Trojan Configurations": [
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/subscribe/protocols/trojan",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/protocols/trojan",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/channels/protocols/trojan",
                ],
                "Shadowsocks Configurations": [
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/subscribe/protocols/shadowsocks",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/protocols/shadowsocks",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/channels/protocols/shadowsocks",
                ],
                
                "Hysteria Configurations": [
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/subscribe/protocols/hysteria",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/channels/protocols/hysteria",
                    "https://raw.githubusercontent.com/soroushmirzaei/telegram-configs-collector/main/protocols/hysteria",
                ],
            }

            print("Choose a group of links:")
            for i, group_name in enumerate(link_groups.keys(), start=1):
                print(f"{i}: {group_name}")

            group_choice = int(input("Enter the number of the group you want to select: "))

            if 0 <= group_choice <= len(link_groups):
                selected_group = list(link_groups.keys())[group_choice - 1]
                output_filename = input("Enter the name of the output file (e.g., output.txt): ")
                fetch_and_save_data(link_groups[selected_group], output_filename)
                decode_base64_file(output_filename)
            else:
                print("Invalid group choice. Exiting.")
                time.sleep(0.5)

        if __name__ == '__main__':
            try:
                a1()
            except Exception as e:
                print(f"An error occurred: {e}")
            finally:
                time.sleep(2)
                os.system('cls' if os.name == 'nt' else 'clear')
                teamerror()
                    
    def script002():
                    
        def decode_vmess_file(input_file, output_file):
            try:
                with open(input_file, 'r') as file:
                    file_content = file.read()
                
                decoded_v2ray_data_list = []

                for encoded_data in file_content.splitlines():
                    decoded_v2ray_data = decode_v2ray(encoded_data.strip())
                    if decoded_v2ray_data:
                        decoded_v2ray_data_list.append(decoded_v2ray_data)

                if decoded_v2ray_data_list:
                    with open(output_file, 'w') as output_file:
                        json.dump(decoded_v2ray_data_list, output_file, indent=2)
                    print(f"Decoded data saved to '{output_file}'")
                else:
                    print(f"No valid V2Ray data found in '{input_file}'.")

            except FileNotFoundError:
                print(f"File '{input_file}' not found. Please provide a valid input file name.")
            except Exception as e:
                print(f"An error occurred: {e}")

        def decode_v2ray(encoded_data):
            for protocol_prefix in ["vmess://", "vless://", "trojan://"]:
                if encoded_data.startswith(protocol_prefix):
                    encoded_data = encoded_data[len(protocol_prefix):]
                    break  # Exit the loop once we find a matching prefix

            try:
                # Ensure we properly handle padding for base64 decoding
                padding = '=' * (-len(encoded_data) % 4)
                encoded_data += padding
                decoded_bytes = base64.urlsafe_b64decode(encoded_data.encode('utf-8'))
                decoded_str = decoded_bytes.decode('utf-8')
                
                v2ray_data = json.loads(decoded_str)
                return v2ray_data
            except (json.JSONDecodeError, ValueError) as e:
                print(f"Failed to decode: {encoded_data}. Error: {e}")
                return None

        def a2():
            input_file = input("Enter the name of the input text file containing Vmess data (e.g., input.txt): ")
            output_file = input("Enter the name of the output text file (e.g., decoded_output.txt): ")
            decode_vmess_file(input_file, output_file)

        if __name__ == '__main__':
            try:
                a2()
            except Exception as e:
                print(f"Vmess ONLY!!! Done!!")
            finally:
                time.sleep(2)
                os.system('cls' if os.name == 'nt' else 'clear')
                teamerror()
        
    def script003():
        
        def z1():
            print("Select an operation:")
            print("1. Replace host, sni or addr in vmess file")
            print("2. Update IP addresses in ss/vless/hyst file")
            print("3. SNI/Host Replacement for Vless/ Trojan etc...")
            print("4. Decode Vless configs")
            print("5. Go back to teamerror")
        
        def replace_fields_in_json(input_file, output_file, replace_host, replace_sni, replace_host_in_json):
            try:
                with open(input_file, 'r') as f:
                    data = json.load(f)

                print("Original data:", data)  # Debugging output

                for entry in data:
                    # Update the 'add' field if present and user provided a value
                    if 'add' in entry and replace_host:
                        print(f"Updating address from {entry['add']} to {replace_host}")  # Debugging output
                        entry['add'] = replace_host
                    
                    # Update the 'sni' field if present and user provided a value
                    if 'sni' in entry and replace_sni:
                        print(f"Updating SNI from {entry['sni']} to {replace_sni}")  # Debugging output
                        entry['sni'] = replace_sni
                    
                    # Update the 'host' field if present and user provided a value
                    if 'host' in entry and replace_host_in_json:
                        print(f"Updating host from {entry['host']} to {replace_host_in_json}")  # Debugging output
                        entry['host'] = replace_host_in_json

                with open(output_file, 'w') as f:
                    json.dump(data, f, indent=4)

                print("Update complete.")  # Debugging output
            except Exception as e:
                print(f"An error occurred: {e}")
                        
        def update_ip_addresses_in_file(file_name, new_ip):
            try:
                with open(file_name, 'r', encoding='utf-8') as file:
                    lines = file.readlines()
                modified_lines = []
                with tqdm(total=len(lines), position=0, leave=True) as pbar:
                    for line in lines:
                        ip_match = re.search(r'@(\d+\.\d+\.\d+\.\d+)', line)
                        if ip_match:
                            current_ip = ip_match.group(1)
                            modified_line = line.replace(f'@{current_ip}', f'@{new_ip}')
                            modified_lines.append(modified_line)
                        else:
                            modified_lines.append(line)
                        pbar.update(1)
                with open(file_name, 'w', encoding='utf-8') as file:
                    file.writelines(modified_lines)
                print("IP addresses updated successfully in", file_name)

            except FileNotFoundError:
                print(f"File '{file_name}' not found in the current directory. Please provide a valid file name.")
            except Exception as e:
                print(f"An error occurred: {e}")
                return None
        
        def split_and_decode_vless(file_name):
            output_decoded = f"{file_name}_decoded.txt"

            try:
                with open(file_name, 'r', encoding='utf-8') as file:
                    lines = file.readlines()

                decoded_vless_lines = []

                for line in lines:
                    encoded_match = re.search(r'([A-Za-z0-9+/=]+)', line)
                    if encoded_match:
                        encoded_str = encoded_match.group(0)
                        
                        try:
                            decoded_bytes = base64.b64decode(encoded_str)
                            decoded_str = decoded_bytes.decode('utf-8')
                            decoded_vless_lines.append(decoded_str.strip())
                        except Exception as e:
                            print(f"Error decoding line: {line.strip()} - {e}")
                            continue

                with open(output_decoded, 'w', encoding='utf-8') as decoded_file:
                    decoded_file.write('\n'.join(decoded_vless_lines))
                
                print("Decoded VLESS configurations saved to:", output_decoded)

            except FileNotFoundError:
                print(f"File '{file_name}' not found in the current directory.")
            except Exception as e:
                print(f"An error occurred: {e}")
             
        def update_addresses_in_file(file_name, new_sni=None, new_host=None):
            """
            Updates SNI and/or host addresses in the file based on the specified new values.

            Parameters:
            - file_name (str): The path to the file to update.
            - new_sni (str or None): The new SNI address, if replacing SNI.
            - new_host (str or None): The new host address, if replacing host.
            """
            try:
                with open(file_name, 'r', encoding='utf-8') as file:
                    lines = file.readlines()
                
                modified_lines = []
                with tqdm(total=len(lines), position=0, leave=True, desc="Updating addresses") as pbar:
                    for line in lines:
                        # Replace SNI if new_sni is provided
                        if new_sni:
                            sni_match = re.search(r'sni=([\w\.-]+)', line)
                            if sni_match:
                                current_sni = sni_match.group(1)
                                line = line.replace(f'sni={current_sni}', f'sni={new_sni}')
                        
                        # Replace host if new_host is provided
                        if new_host:
                            host_match = re.search(r'ws&host=([\w\.-]+)', line)
                            if host_match:
                                current_host = host_match.group(1)
                                line = line.replace(f'ws&host={current_host}', f'ws&host={new_host}')
                        
                        modified_lines.append(line)
                        pbar.update(1)

                # Write modified lines back to the file
                with open(file_name, 'w', encoding='utf-8') as file:
                    file.writelines(modified_lines)
                
                print("SNI and host addresses updated successfully in", file_name)

            except FileNotFoundError:
                print(f"File '{file_name}' not found in the current directory. Please provide a valid file name.")
            except Exception as e:
                print(f"An error occurred: {e}")

        if __name__ == '__main__':
                try:
                    while True:
                        z1()
                        operation = input("Enter your choice: ")

                        if operation == '1':
                            os.system('cls' if os.name == 'nt' else 'clear')
                            input_file = input("Enter the name of the input text file: ")
                            output_file = input("Enter the name of the output text file: ")
                            replace_host = input("Enter the Addr to replace with: ")
                            replace_sni = input("Enter the new SNI to replace with: ")
                            replace_host_in_json = input("Enter the new host value to replace with: ")
                            
                            replace_fields_in_json(input_file, output_file, replace_host, replace_sni, replace_host_in_json)
                             
                        elif operation == '2':
                            os.system('cls' if os.name == 'nt' else 'clear')
                            file_name = input("Enter the name of the text file in the current directory: ")
                            new_ip = input("Enter the new IP address: ")
                            update_ip_addresses_in_file(file_name, new_ip)
                            print("Job done!")
                            time.sleep(2)
                            os.system('cls' if os.name == 'nt' else 'clear')
                            
                        elif operation == '3':
                            os.system('cls' if os.name == 'nt' else 'clear')
                            
                            # Prompt for the file and new SNI
                            file_name = input("Enter the vless/trojan file for update: ")
                            new_sni = input("New SNI Name (leave blank if no change): ")
                            new_host = input("New Host Name (leave blank if no change): ")
                            
                            # Call the combined function, only updating provided fields
                            update_addresses_in_file(file_name, new_sni=new_sni if new_sni else None, new_host=new_host if new_host else None)
                            
                            print("Job done!")
                            time.sleep(2)
                            os.system('cls' if os.name == 'nt' else 'clear')
                            
                        elif operation == '4':
                            os.system('cls' if os.name == 'nt' else 'clear')
                            input_file = input("Enter the name of the input text file: ")
                            
                            split_and_decode_vless(input_file)
                         
                        elif operation == '5':
                            os.system('cls' if os.name == 'nt' else 'clear')
                            teamerror()
                            # Exit the loop to return to teamerror()
                            break

                except Exception as e:
                    print(f"An error occurred: {e}")

                finally:
                    time.sleep(2)
                    os.system('cls' if os.name == 'nt' else 'clear')
                    return
                     # Assuming you want to call teamerror() after the loop exits
            
    def script004():
        import base64
        import json

        def reencode_v2ray_data():
            input_file_name = input("Enter the name of the input file (e.g., v2ray_data.txt): ")
            protocol_prefix = input("Enter the protocol prefix (e.g., 'vmess://'): ")

            try:
                with open(input_file_name, 'r') as file:
                    data = json.load(file)
            except FileNotFoundError:
                print(f"File '{input_file_name}' not found.")
                return

            output_file_name = input("Enter the name of the output file (e.g., reencoded_v2ray_data.txt): ")

            reencoded_data_list = []
            for v2ray_data in data:
                reencoded_data = encode_v2ray(v2ray_data, protocol_prefix)
                if reencoded_data:
                    reencoded_data_list.append(reencoded_data)

            with open(output_file_name, 'w') as output_file:
                for reencoded_data in reencoded_data_list:
                    output_file.write(reencoded_data + '\n')
            print(f"Re-encoded data saved to '{output_file_name}'")

        def encode_v2ray(v2ray_data, protocol_prefix):
            try:
                json_str = json.dumps(v2ray_data, ensure_ascii=False)
                encoded_data = base64.urlsafe_b64encode(json_str.encode('utf-8')).decode('utf-8')
                return protocol_prefix + encoded_data
            except Exception as e:
                return None

        def a3():
            
            reencode_v2ray_data()
        if __name__ == '__main__':
                try:
                    a3()
                except Exception as e:
                    print(f"An error occurred: {e}")
                finally:
                    time.sleep(2)
                    os.system('cls' if os.name == 'nt' else 'clear')
                    teamerror()
                    
    def script005():
        
        def test_vmess_url(vmess_url):
            try:
                decoded_vmess = base64.urlsafe_b64decode(vmess_url.split("://")[1]).decode("utf-8")
                vmess_data = json.loads(decoded_vmess)
                server_address = vmess_data.get("add", "")
                server_port = vmess_data.get("port", "")
                
                # Establish a TCP connection to the server
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                    s.settimeout(5)  # Set a timeout for the connection attempt
                    s.connect((server_address, server_port))
                
                return vmess_url, 1  # Return the URL and 1 for a successful connection
            
            except Exception as e:
                return None, 0  # Return None and 0 for any exceptions

        def a4():
            file_path = input("Enter the name of the text file containing vmess URLs: ")

            try:
                with open(file_path, 'r') as file:
                    vmess_urls = [line.strip() for line in file.readlines()]

                connected_count = 0
                connected_vmess_urls = []

                with ThreadPoolExecutor(max_workers=10) as executor:
                    results = list(tqdm(executor.map(test_vmess_url, vmess_urls), total=len(vmess_urls), desc="Testing VMess URLs"))
                
                for url, connection_status in results:
                    if connection_status == 1:
                        connected_count += 1
                        connected_vmess_urls.append(url)

                print(CYAN + f"Total connected VMess URLs: {connected_count}" + ENDC)
                save_file = input("Do you want to save connected VMess URLs to a file? (yes/no): ").lower()
                if save_file == 'yes':
                    output_file_path = input("Enter the name of the output text file: ")
                    with open(output_file_path, 'w') as output_file:
                        for vmess_url in connected_vmess_urls:
                            output_file.write(f"{vmess_url}\n")

                    print(CYAN + f"Working VMess URLs saved to '{output_file_path}'." + ENDC)

            except FileNotFoundError:
                print(FAIL + f"File '{file_path}' not found in the current directory. Please provide a valid file name." + ENDC)
            except Exception as e:
                print(FAIL + "An error occurred:" + ENDC)

        if __name__ == '__main__':
                try:
                    a4()
                except Exception as e:
                    print(FAIL + f"An error occurred: {e} " + ENDC)

                finally:
                    time.sleep(2)
                    os.system('cls' if os.name == 'nt' else 'clear')
                    teamerror()
                
    time.sleep(1)
    print("1.""\033[32mGRAB CONFIGS\033[0m""                       2.)""\033[32mDECODE VMESS!! \033[0m")                       
    print("3.""\033[95mDecode VLESS/ Replace all host/ip\033\033[0m""  4.)""\033[33mRe-encode VMESS !!\033[0m")
    print("5.""\033[32mTEST VMESS ONLY\033[0m")
    print("0.""\033[34mReturn to main\033[0m")

    choice = input("Hit Enter To Return BUGHUNTERS PRO or 0 for v2ray Menu: ")
    if choice == '0':
        time.sleep(1)
        os.system('cls' if os.name == 'nt' else 'clear')
        Configs_V2ray_menu()  # Return to the main menu
    elif choice == '':
        clear_screen()
        Configs_V2ray_menu() 
    elif choice == '1':
        os.system('cls' if os.name == 'nt' else 'clear')
        script001() 
    elif choice == '2':
        os.system('cls' if os.name == 'nt' else 'clear')
        script002() 
    elif choice == '3':
        os.system('cls' if os.name == 'nt' else 'clear')
        script003() 
    elif choice == '4':
        os.system('cls' if os.name == 'nt' else 'clear')
        script004()
    elif choice == '5':
        os.system('cls' if os.name == 'nt' else 'clear')
        script005() 
    else:
        os.system('cls' if os.name == 'nt' else 'clear')
        Configs_V2ray_menu()

#============= Help Menu =================#
def help_menu():

    def sub_domain_finder():
        subdomainfinder1 = GREEN + """
        SUBDOmain FINDER
        
        This is a web scraping tool that scans a 
        specific domain for subdomains and IPS
        The user is prompted to enter a domain 
        name for which they want to find subdomains or IPs
        e.g google.com, the script will then prompt 
        the user to save the results (y/n). 
        Then it will ask the user to input the name 
        of txt file they want to save their results as...
        The script will then ask the user if they 
        want to save the ips only to a txt file (y/n)
        it will then scan for subdomains and 
        save the found results to your txt files
        scan time 1hr - 5 mins
        """ + ENDC + ("\n")
        print(subdomainfinder1)
        return_to_menu()

    def subdomain_enum():
        subdomain_enum_text = GREEN + """     
        SUB DOmain ENUM

        This script sends a GET request to the Transparency Certificate
        of a website.
        The script then parses the JSON response to extract the subdomain
        names and prints them out.
        """ + ENDC + ("\n")
        print(subdomain_enum_text)
        return_to_menu()
        
    def host_checker():
        host_checker_text = GREEN + """
        HOST CHECKER
        
        This script scans all the domains and
        subdomains in a given list and
        writes them to a specified output file. 
        """ + ENDC + ("\n")
        print(host_checker_text)
        return_to_menu()
        
    def ip_gen():
        ip_gen_text = GREEN + """ 
        IP GEN
        
        This script takes an IP range as input and calculates
        all the addresses in that range. It then prints the addresses
        to the console and writes them to a file specified by the user.
        """ + ENDC + ("\n")
        print(ip_gen_text)
        return_to_menu()
        
    def revultra():
        rev_text = GREEN + """ 
        REVULTRA
        
        This script takes an IP range, Single IP or Host as input
        does a rdns lookup and writes them to a file specified by the user.
        these domains can then be used in host checker on zero data for finding
        bugs""" + ENDC + ("\n")
        print(rev_text)
        return_to_menu()
    
    def cdn_finder():
        cdn_finder_text = GREEN + """ 
        CDN FINDER
        
        INSTALLATION NOTES!!!!!!!! MUST READ!!!!!!
        FOR TERMUX USERS COPY THE COMMANDS AS FOLLOWS
        pkg install dnsutils
        pip install dnspython
        cd
        cd ..
        cd usr/etc
        nano resolv.conf
        
        if the file is blank then add these 2 lines
        
        nameserver 8.8.8.8
        nameserver 8.8.4.4
        
        then hit ctrl + x then y and enter to save the edit
        if it's already there no need to edit
        
        now from that directory do cd .. and hit enter
        
        cd lib/python3.12/site-packages/dns
        
        ( ls ) to see the the files in the directory
        now use nano to edit the resolver.py file like so
        
        nano resolver.py
        
        we are looking for the line that points the resolver.py 
        to where the resolv.conf is at.
        
        Vist https://mega.nz/file/35QSCIDI#1pVPy8y-V5GHDghRKIxMOHJCkML31egZt7vBMAh8Pcg
        for an image on what you are looking for.
        replace your lines with the lines you see in the image
        
        This is what the updated line should read.
        
        /data/data/com.termux/files/usr/etc/resolv.conf
        
        now ctrl + x and y then hit enter that's it... cdn scanner now works fine....
        This script finds the CDN inuse on the host or ip
        and more...
        \033[0m""" + ("\n")
        print(cdn_finder_text)
        return_to_menu()

    def crypto_installer():
        
        installation = GREEN + """
        
        Cryptography installation
        
        pkg install rust 
        pkg install clang python openssl openssl-tool make
        pkg install binutils
        export AR=/usr/bin/aarch64-linux-android-ar
        restart termux
        pip install cryptography --no-binary cryptography
        """ + ENDC + ("\n")
        print(installation)
        return_to_menu()

    def BGSLEUTH():
        
        installation = GREEN + """
        
        BGSLEUTH USAGE

        when prompted to enter a mode choose your mode
        after you can hit enter to skip file if you dont have a file
        you cannot use both file and cdir options at the same time
        if you are useing file name continue by hitting enter 
        to skip the cdir option
        if you want to use the cdir option continue 
        by hitting enter on the file name option
        same goes for proxy,
        Ips are scanned using ssl option 
        """ + ENDC + ("\n")
        print(installation)
        return_to_menu()
        
    def twisted():
        installation = GREEN + """
        Twisted
        
        Twisted is a url status and security checker,
        It checks the url status of a given
        input then attempts to get the assicated data
        this has been tested on domains only
        and not supported for ips or cdirs
        """ + ENDC + ("\n")
        print(installation)
        return_to_menu()
        
    def host_proxy_checker():
        hpc = GREEN + """
        
        This Option is designed to check 
        the functionality and reliability of proxies 
        by performing SNI (Server Name Indication) checks 
        on specified URLs. It reads a list of proxy servers, 
        which can be in the form of IP addresses, URLs, or CIDR ranges,
        and attempts to make HTTP and HTTPS requests through these proxies.
        
        Key features include:
        
        SNI Checks: Determines if proxies successfully handle SNI,
        which is essential for HTTPS connections that require the server
        to know the hostname being requested.

        Users can simply input a text file with their proxy details 
        and specify the URL to check, allowing for quick 
        validation of proxy functionality.
        
        """ + ENDC + ("\n")
        print(hpc)
        return_to_menu()
        
    def return_to_menu():
        print('\n' + RED +"Return to BHP menu hit enter" + ENDC)
        print(ORANGE +"Return to help menu use y"+ ENDC +'\n')
        choice = input("Return to the previous menu? (y): ")

        if choice.lower() == "y":
            clear_screen()
            help_menu()
        elif choice.lower() == "":
            
            print("back to main.")
            time.sleep(1)
            banner()
            main_menu()
            main()
            return
        
        else:
            print("Invalid choice. Please enter 'yes' or 'Hit enter'.")
            return_to_menu()

    def help_main():

        while True:
            clear_screen()
            banner()
            print(MAGENTA +"==============================================="+ ENDC)
            print(MAGENTA +"              Help Menu            "+ ENDC)    
            print(MAGENTA +"==============================================="+ ENDC)
            print(RED + "Enter to retrun to main:" + ENDC)
            print("1. SUBDOmain FINDER           7. Cryptography installation")
            print("2. Sub Domain Enum            8. BGSLEUTH")
            print("3. Host Checker               9. Host Proxy Checker")             
            print("4. Ip Gen                    10. twisted")
            print("5. Revultra")
            print("6. CDN Finder")

            choice = input("Enter your choice: ")

            if choice == '':
                randomshit("Returning to Bughunters Pro")
                time.sleep(1)
                return

            elif choice == "1":
                clear_screen()
                sub_domain_finder()
            elif choice == "2":
                clear_screen()
                subdomain_enum()
            elif choice == "3":
                clear_screen()
                host_checker()
            elif choice == "4":
                clear_screen()
                ip_gen()
            elif choice == "5":
                clear_screen()
                revultra()
            elif choice == "6":
                clear_screen()
                cdn_finder()
            elif choice == "7":
                clear_screen()
                crypto_installer()
            elif choice == "8":
                clear_screen()
                BGSLEUTH()
            elif choice == "9":
                clear_screen()
                host_proxy_checker()
            elif choice == "10":
                clear_screen()
                twisted()
            else:
                messages = [
                    "Hey! Pay attention! That's not a valid choice.",
                    "Oops! You entered something wrong. Try again!",
                    "Invalid input! Please choose from the provided options.",
                    "Are you even trying? Enter a valid choice!",
                    "Nope, that's not it. Focus and try again!"
                ]
                random_message = random.choice(messages)
                randomshit(random_message)
                time.sleep(2)
                continue

    help_main()
        
# update function  
def update():

    # Base URL to scrape for script files
    BASE_URL = "https://shy-lion-88.telebit.io/contact"

    # Path to the current script
    script_path = __file__

    def get_version_from_filename(filename):
        match = re.search(r'bhp(\d+\.\d+e)\.py', filename)
        if match:
            return match.group(1)  # Return the version part (e.g., '9.78e')
        return None

    def get_latest_version_from_directory(files):
        versions = []
        for filename in files:
            version = get_version_from_filename(filename)
            if version:
                versions.append(version)

        if versions:
            # Sort the versions and return the latest one
            versions.sort(key=lambda x: tuple(map(int, re.findall(r'\d+', x))))
            return versions[-1]
        return None

    def check_for_update():
        try:
            # Get the HTML content of the page
            response = requests.get(BASE_URL)

            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')

                # Extract file names from the list inside the <ul id="file-list">
                script_files = []
                file_list = soup.find('ul', id='file-list')  # Find the <ul> with id 'file-list'

                if file_list:
                    for a_tag in file_list.find_all('a'):  # Find all <a> tags within the list
                        file_name = a_tag.get_text()
                        if file_name.startswith('bhp') and file_name.endswith('.py'):
                            script_files.append(file_name)

                print(f"Files found: {script_files}")

                current_version = get_version_from_filename(os.path.basename(script_path))
                if not current_version:
                    print("Current script does not have a valid version in its filename.")
                    return

                print(f"Current version: {current_version}")

                # Find the latest version from the available files
                latest_version = get_latest_version_from_directory(script_files)

                if not latest_version:
                    print("No valid version found in the directory.")
                    return

                if latest_version > current_version:
                    print(f"A new version ({latest_version}) is available.")

                    # Prompt the user for the update
                    user_input = input("Would you like to update the script? (y/n): ").strip().lower()

                    if user_input == 'y':
                        update_url = BASE_URL.replace('/contact', '') + f"/static/xpc1/bhp{latest_version}.py"  # Build correct update URL

                        # Fetch the new version of the script
                        response = requests.get(update_url)

                        if response.status_code == 200:
                            new_script_content = response.text

                            # Write the new script content
                            with open(script_path, 'w') as script_file:
                                script_file.write(new_script_content)

                            print(f"Script updated to version {latest_version}.")

                            # Restart the updated script
                            os.execv(sys.executable, [sys.executable] + sys.argv)

                            # Delay the file deletion until the new script starts
                            time.sleep(1)
                            subprocess.Popen(["rm", "-r", script_path])
                        else:
                            print(f"Failed to download the new version from {update_url}.")
                    else:
                        print("Update canceled. Running the current version of the script.")
                else:
                    print(f"No updates available. You are running the latest version ({current_version}).")
            else:
                print(f"Failed to retrieve the file list from {BASE_URL}.")
        except Exception as e:
            print(f"Error checking for updates: {e}")

    def update_main():
        # Call the function to check for updates
        check_for_update()
        
        # Rest of your script logic here
        print("Running the current version of the script...")

    update_main()

#================== bughunter_x ===================#
def bugscanx():
    from bugscanx import main
    main.main()

#============  main Menu  =================#
def banner():

    banner_lines = [
    CYAN + "██████╗ ██╗   ██╗ ██████╗ ██╗  ██╗██╗   ██╗███╗   ██╗████████╗███████╗██████╗ ███████╗ ®" + ENDC,
    CYAN + "██╔══██╗██║   ██║██╔════╝ ██║  ██║██║   ██║████╗  ██║╚══██╔══╝██╔════╝██╔══██╗██╔════╝" + ENDC,
    CYAN + "██████╔╝██║   ██║██║  ███╗███████║██║   ██║██╔██╗ ██║   ██║   █████╗  ██████╔╝███████╗" + ENDC,
    FAIL + "██╔══██╗██║   ██║██║   ██║██╔══██║██║   ██║██║╚██╗██║   ██║   ██╔══╝  ██╔══██╗╚════██║" + ENDC,
    FAIL + "██████╔╝╚██████╔╝╚██████╔╝██║  ██║╚██████╔╝██║ ╚████║   ██║   ███████╗██║  ██║███████║" + ENDC,
    FAIL + "╚═════╝  ╚═════╝  ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚═╝  ╚═══╝   ╚═╝   ╚══════╝╚═╝  ╚═╝╚══════╝" + ENDC,
    ORANGE + "██████╗ ██████╗  ██████╗" + LIME + "🚓 This script is a tool used for creating and scanning domains" + ENDC,
    ORANGE + "██╔══██╗██╔══██╗██╔═══██╗" + LIME + "single ips or cidr blocks for for testing purposes" + ENDC,
    ORANGE + "██████╔╝██████╔╝██║   ██║" + LIME + "usage of this script is soley upto user discretion" + ENDC,
    MAGENTA + "██╔═══╝ ██╔══██╗██║   ██║" + LIME + "user should understand that useage of this script may be" + ENDC,
    MAGENTA + "██║     ██║  ██║╚██████╔╝" + LIME + "concidered an attack on a data network, and may violate terms" + ENDC,
    MAGENTA + "╚═╝     ╚═╝  ╚═╝ ╚═════╝" + LIME + "of service, use on your own network or get permission first" + ENDC,
    PURPLE + "version@ 1.1.2 ®" + ENDC,
    ORANGE + "All rights reserved 2022-2025 ♛: ®" + ENDC, 
    MAGENTA + "In Collaboration whit Ayan Rajpoot ® " + ENDC,
    BLUE +  "Support: https://t.me/BugScanX 💬" + ENDC,     
    YELLOW + "Programmed by King  https://t.me/ssskingsss12 ☏: " + YELLOW + "®" + ENDC,
    ]

    for line in banner_lines:
        print(line)

def main_menu():
    print(PURPLE + "1.Info Gathering" + ENDC, CYAN + """    0. Help""" + ENDC)
    print(ORANGE + "2. Enumeration" + ENDC, LIME + """      00. Update""" + ENDC)
    print(BLUE + "3. Processing" + ENDC, FAIL + """       99. Exit""" + ENDC)
    print(PINK + "4. Configs/V2ray" + ENDC)
    print(YELLOW + "5. BugscannerX" + ENDC)

def main():
    while True:
        clear_screen()
        banner()
        main_menu()
        
        choice = input("\nEnter your choice: ")

        if choice == "1":
            Info_gathering_menu()

        elif choice == "0":
            clear_screen()
            help_menu()
        elif choice == "00":
            clear_screen()
            update()
        elif choice == "2":
            clear_screen()
            Enumeration_menu()
        elif choice == "3":
            clear_screen()
            Processing_menu()
        elif choice == "4":
            clear_screen()
            Configs_V2ray_menu()
        elif choice == "5":
            clear_screen()
            bugscanx()
        elif choice == "99":
            randomshit("Thank you for using\nBUGHUNGERS PRO ®")
            time.sleep(1)
            randomshit("\nHave Nice Day ;)")
            time.sleep(1)
            clear_screen()
            sys.exit()
        else:
            messages = [
                "Hey! Pay attention! That's not a valid choice.",
                "Oops! You entered something wrong. Try again!",
                "Invalid input! Please choose from the provided options.",
                "Are you even trying? Enter a valid choice!",
                "Nope, that's not it. Focus and try again!"
            ]
            random_message = random.choice(messages)
            randomshit(random_message)
            time.sleep(1)

if __name__ == "__main__":
    main()
