import argparse
import socket # for connecting
from colorama import init, Fore

from threading import Thread, Lock
from queue import Queue

# some colors
init()
Red = Fore.MAGENTA
GREEN = Fore.GREEN
RESET = Fore.RESET
GRAY = Fore.LIGHTBLACK_EX

# number of threads, feel free to tune this parameter as you wish
N_THREADS = 200
# thread queue
q = Queue()
print_lock = Lock()

def port_scan(port):
    """
    Scan a port on the global variable `host`
    """
    try:
        s = socket.socket()
        s.connect((host, port))
    except:
        with print_lock:
            print(f"{GRAY}{host:15}:{port:5} is closed  {RESET}", end='\r')
    else:
        with print_lock:
            print(f"{GREEN}{host:15}:{port:5} is open    {RESET}")
    finally:
        s.close()


def scan_thread():
    global q
    while True:
        # get the port number from the queue
        worker = q.get()
        # scan that port number
        port_scan(worker)
        # tells the queue that the scanning for that port 
        # is done
        q.task_done()


def main(host, ports):
    global q
    for t in range(N_THREADS):
        # for each thread, start it
        t = Thread(target=scan_thread)
        # when we set daemon to true, that thread will end when the main thread ends
        t.daemon = True
        # start the daemon thread
        t.start()

    for worker in ports:
        # for each port, put that port into the queue
        # to start scanning
        q.put(worker)
    
    # wait the threads ( port scanners ) to finish
    q.join()


if __name__ == "__main__":
    print(f"""{Red}
 _______  _______  ______   _______    _______  _______  _______  __    _  __    _  _______  ______  
|       ||       ||    _ | |       |  |       ||       ||   _   ||  |  | ||  |  | ||       ||    _ | 
|    _  ||   _   ||   | || |_     _|  |  _____||       ||  |_|  ||   |_| ||   |_| ||    ___||   | || 
|   |_| ||  | |  ||   |_||   |   |    | |_____ |       ||       ||       ||       ||   |___ |   |_|| 
|    ___||  |_|  ||    __ |  |   |    |_____  ||      _||       ||  _    ||  _    ||    ___||    __ |
|   |    |       ||   |  ||  |   |     _____| ||     |_ |   _   || | |   || | |   ||   |___ |   |  ||
|___|    |_______||___|  ||  |___|    |_______||_______||__| |__||_|  |__||_|  |__||_______||___|  ||
    
    Please select a port range
    1. Common ports
    2. All ports (slow)
    """)
    p1 = input(": ")
    ip = input("Please enter the ip you which to scan: ")
    if p1 == "1":
        start_port, end_port = 1, 1000
 
    if p1 == "2":
        start_port, end_port = 1, 65535


    host = ip
    ports = [ p for p in range(start_port, end_port)]

    main(host, ports)