#!/usr/bin/env python3

class Colours:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

try:
    import os
    import re
    import sys
    import getopt
    import requests
    from clint.textui import progress
    from bs4 import BeautifulSoup
except Exception as err:
    print(Colours.FAIL + "Error: {}".format(err) + Colours.ENDC)

def Usage():
    use_msg = '''
---------- Usage ---------- 
leak-lookup [options] [search term]
--------------------------- 
Options:
    -h: Prints this help message
    -p: Searches haveibeenpwned.com 
    -d: Searches for leaked database
--------------------------- 
'''
    print(use_msg)

def DownloadDatabase(url, name):
    try:
        r = requests.get(url, stream=True)
        with open(name, 'wb') as f:
            total_length = int(r.headers.get('content-length'))
            for chunk in progress.bar(r.iter_content(chunk_size=1024), expected_size=(total_length/1024) + 1): 
                if chunk:
                    f.write(chunk)
                    f.flush()
    except (KeyboardInterrupt, SystemExit, EOFError):
        print(Colours.FAIL + "An error occurred, cleaning up" + Colours.ENDC)
        os.remove(name)

def DatabaseQuery(database):
    r = requests.get("https://www.databases.today/search-nojs.php?for=" + database)
    if r.reason != "OK":
        print(Colours.FAIL + "Error code: {}".format(r.status_code) + Colours.ENDC)
        sys.exit(1)
    soup = BeautifulSoup(r.text, "html.parser")
    dbs = soup.find(id="myTable").find_all("tr")
    entries = []
    for table in dbs:
        entry = table.find_all("td")
        if len(entry) != 0:
            entries.append([entry[0].text, entry[4].a.get("href")])
    print("Which file would you like to download?")
    for index, dllink in enumerate(entries):
        print("{}) {}".format(index + 1, dllink[0]))
    print("a) All")
    print("q) Quit")
    download_choice = input(">> ")
    if download_choice == "q":
        sys.exit(0)
    elif download_choice == "a":
        for x in dllink:
            DownloadDatabase(x[1], x[0])
    else:
        try:
            download_choice = int(download_choice) - 1
            DownloadDatabase(dllink[1], dllink[0].split(" (")[0])
        except:
            print(Colours.FAIL + "Error: Invalid selection" + Colours.ENDC)
            sys.exit(1)


def QueryHaveIBeenPwned(email):
    r = requests.post("https://haveibeenpwned.com/", data={"Account": email})
    if r.reason != "OK":
        print(Colours.FAIL + "Error code: {}".format(r.status_code) + Colours.ENDC)
        sys.exit(1)
    soup = BeautifulSoup(r.text, "html.parser")
    pwnCount = re.match("Pwned on \d+", soup.find(id="pwnCount").text)
    if pwnCount == None:
        print(Colours.OKGREEN + "{} has no public leaks".format(email) + Colours.ENDC)
        return
    print(Colours.FAIL + "{} has {} public leaks avalible".format(email, pwnCount.group().split(" ")[-1]) + Colours.ENDC)
    leaks = []
    for leak in soup.find_all(class_="pwnedWebsite"):
        leak_name = None
        leak_status = None
        compromised_data = None
        leak_name_html = leak.find(class_="pwnedCompanyTitle")
        if leak_name_html:
            if "(" in leak_name_html.text:
                leak_name = leak_name_html.text.split("  (")[0]
                leak_status = leak_name_html.text.split("  (")[1][:-2]
            else:
                leak_name = leak_name_html.text[:-1]
                leak_status = None
        compromised_data_html = leak.find(class_="dataClasses")
        if compromised_data_html:
            compromised_data = compromised_data_html.text
        if leak_name:
            leaks.append([leak_name, leak_status, compromised_data])
    print("\nDownload databases:")
    for index, leak in enumerate(leaks):
        if leak[1] == None:
            print("{}) {}: {}".format(index + 1, leak[0], leak[2]))
        else:
            print("{}) {} ({}): {}".format(index + 1, leak[0], leak[1], leak[2]))
    print("a) Download all")
    print("q) Quit")
    download_choice = input(">> ")
    if download_choice == "q":
        sys.exit(0)
    elif download_choice == "a":
        for leak in leaks:
            DatabaseQuery(leak[0])
    try:
        download_choice = int(download_choice) - 1
        DatabaseQuery(leaks[download_choice][0])
    except:
        print(Colours.FAIL + "Error: Invalid selection" + Colours.ENDC)
        sys.exit(1)


def main():
    if len(sys.argv[1:]) == 0:
        Usage()
        sys.exit(1)
    try:
        options, remainder = getopt.getopt(sys.argv[1:],'hpd',['h', 'p','d',])
    except getopt.GetoptError as err:
        print(Colours.FAIL + "Error: {}".format(err) + Colours.ENDC)
        sys.exit(1)

    for opt, arg in options:
        if opt == "-h":
            Usage()
            sys.exit(0)
        elif opt == "-p":
            if len(remainder) == 0:
                Usage()
                sys.exit(1)
            QueryHaveIBeenPwned(" ".join(remainder))
        elif opt == "-d":
            if len(remainder) == 0:
                Usage()
                sys.exit(1)
            DatabaseQuery(" ".join(remainder))


if __name__ == "__main__":
    try:
        main()
    except (KeyboardInterrupt, SystemExit, EOFError):
        sys.exit(0)
