#!/usr/bin/python3
import os, random, string, sys, time, io

if sys.version_info.major != 3:
    print("Please run with python3.")
    sys.exit(1)

rPackages = ["mariadb-server"]
rRemove = ["mysql-server"]
rMySQLCnf = '# XUI\n[client]\nport                            = 3306\n\n[mysqld_safe]\nnice                            = 0\n\n[mysqld]\nuser                            = mysql\nport                            = 3306\nbasedir                         = /usr\ndatadir                         = /var/lib/mysql\ntmpdir                          = /tmp\nlc-messages-dir                 = /usr/share/mysql\nskip-external-locking\nskip-name-resolve\nbind-address                    = *\n\nkey_buffer_size                 = 128M\nmyisam_sort_buffer_size         = 4M\nmax_allowed_packet              = 64M\nmyisam-recover-options          = BACKUP\nmax_length_for_sort_data        = 8192\nquery_cache_limit               = 0\nquery_cache_size                = 0\nquery_cache_type                = 0\nexpire_logs_days                = 10\nmax_binlog_size                 = 100M\nmax_connections                 = 8192\nback_log                        = 4096\nopen_files_limit                = 20240\ninnodb_open_files               = 20240\nmax_connect_errors              = 3072\ntable_open_cache                = 4096\ntable_definition_cache          = 4096\ntmp_table_size                  = 1G\nmax_heap_table_size             = 1G\n\ninnodb_buffer_pool_size         = 10G\ninnodb_buffer_pool_instances    = 10\ninnodb_read_io_threads          = 64\ninnodb_write_io_threads         = 64\ninnodb_thread_concurrency       = 0\ninnodb_flush_log_at_trx_commit  = 0\ninnodb_flush_method             = O_DIRECT\nperformance_schema              = 0\ninnodb-file-per-table           = 1\ninnodb_io_capacity              = 20000\ninnodb_table_locks              = 0\ninnodb_lock_wait_timeout        = 0\n\nsql_mode                        = "NO_ENGINE_SUBSTITUTION"\n\n[mariadb]\n\nthread_cache_size               = 8192\nthread_handling                 = pool-of-threads\nthread_pool_size                = 12\nthread_pool_idle_timeout        = 20\nthread_pool_max_threads         = 1024\n\n[mysqldump]\nquick\nquote-names\nmax_allowed_packet              = 16M\n\n[mysql]\n\n[isamchk]\nkey_buffer_size                 = 16M'
rChoice = "23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"

rVersions = {
    "14.04": "trusty",
    "16.04": "xenial",
    "18.04": "bionic",
    "20.04": "focal",
    "20.10": "groovy",
    "21.04": "hirsute"
}

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

def generate(length=32): return ''.join(random.choice(rChoice) for i in range(length))

def printc(rText, rColour=col.OKBLUE, rPadding=0):
    rLeft = int(30-(len(rText)/2))
    rRight = (60-rLeft-len(rText))
    print("%s |--------------------------------------------------------------| %s" % (rColour, col.ENDC))
    for i in range(rPadding): print ("%s |                                                              | %s" % (rColour, col.ENDC))
    print("%s | %s%s%s | %s" % (rColour, " " * rLeft, rText, " " * rRight, col.ENDC))
    for i in range(rPadding): print ("%s |                                                              | %s" % (rColour, col.ENDC))
    print("%s |--------------------------------------------------------------| %s" % (rColour, col.ENDC))
    print(" ")

if __name__ == "__main__":
    printc("MySQL Only", col.OKGREEN, 2)
    rHost = "127.0.0.1" ; rServerID = 1 ; rUsername = generate() ; rPassword = generate()
    rDatabase = "xui"
    rPort = 3306

    ##################################################
    # PREPARATION                                    #
    ##################################################
    
    printc("Preparing Installation")
    for rFile in ["/var/lib/dpkg/lock-frontend", "/var/cache/apt/archives/lock", "/var/lib/dpkg/lock", "/var/lib/apt/lists/lock"]:
        if os.path.exists(rFile):
            try: os.remove(rFile)
            except: pass
    rVersion = os.popen('lsb_release -sr').read().strip()
    if rVersion in rVersions:
        printc("Adding repo: Ubuntu %s" % rVersion)
        os.system("sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8")
        os.system("sudo add-apt-repository -y 'deb [arch=amd64,arm64,ppc64el] http://ams2.mirrors.digitalocean.com/mariadb/repo/10.6/ubuntu %s main'" % rVersions[rVersion])
    os.system("sudo apt-get update")
    for rPackage in rRemove:
        printc("Removing %s" % rPackage)
        os.system("sudo apt-get remove %s -y" % rPackage)
    for rPackage in rPackages:
        printc("Installing %s" % rPackage)
        os.system("sudo DEBIAN_FRONTEND=noninteractive apt-get -yq install %s" % rPackage)

    ##################################################
    # MYSQL                                          #
    ##################################################
    
    if not os.path.exists("/etc/mysql/"):
        printc("Error! Failed to install MariaDB")
        sys.exit(1)
    
    printc("Configuring MySQL")
    rCreate = True
    if os.path.exists("/etc/mysql/my.cnf"):
        if open("/etc/mysql/my.cnf", "r").read(5) == "# XUI": rCreate = False
    if rCreate:
        rFile = io.open("/etc/mysql/my.cnf", "w", encoding="utf-8")
        rFile.write(rMySQLCnf)
        rFile.close()
        os.system("sudo service mariadb restart")
    rExtra = ""
    rRet = os.system("mysql -u root -e \"SELECT VERSION();\"")
    if rRet != 0:
        while True:
            rExtra = " -p%s" %  input("Root MySQL Password: ")
            rRet = os.system("mysql -u root%s -e \"SELECT VERSION();\"" % rExtra)
            if rRet == 0: break
            else: printc("Invalid password! Please try again.")
    while True:
        rRet = input("Install a blank XUI database and generate credentials? This is required for new installs, but not updates (Y / N): ").upper()
        if rRet == "Y":
            os.system('sudo mysql -u root%s -e "DROP DATABASE IF EXISTS xui; CREATE DATABASE IF NOT EXISTS xui;"' % rExtra)
            os.system('sudo mysql -u root%s -e "DROP DATABASE IF EXISTS xui_migrate; CREATE DATABASE IF NOT EXISTS xui_migrate;"' % rExtra)
            if os.path.exists("database.sql"): os.system('sudo mysql -u root%s xui < database.sql' % rExtra)
            break
        elif rRet == "N": break
    rNewCredentials = False
    while True:
        rRet = input("Generate a new MySQL user? If you have already done this, you can skip (Y / N): ").upper()
        if rRet == "Y":
            os.system('sudo mysql -u root%s -e "CREATE USER \'%s\'@\'localhost\' IDENTIFIED BY \'%s\';"' % (rExtra, rUsername, rPassword))
            os.system('sudo mysql -u root%s -e "GRANT ALL PRIVILEGES ON xui.* TO \'%s\'@\'localhost\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "GRANT ALL PRIVILEGES ON xui_migrate.* TO \'%s\'@\'localhost\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "GRANT ALL PRIVILEGES ON mysql.* TO \'%s\'@\'localhost\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "GRANT GRANT OPTION ON xui.* TO \'%s\'@\'localhost\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "CREATE USER \'%s\'@\'127.0.0.1\' IDENTIFIED BY \'%s\';"' % (rExtra, rUsername, rPassword))
            os.system('sudo mysql -u root%s -e "GRANT ALL PRIVILEGES ON xui.* TO \'%s\'@\'127.0.0.1\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "GRANT ALL PRIVILEGES ON xui_migrate.* TO \'%s\'@\'127.0.0.1\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "GRANT ALL PRIVILEGES ON mysql.* TO \'%s\'@\'127.0.0.1\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "GRANT GRANT OPTION ON xui.* TO \'%s\'@\'127.0.0.1\';"' % (rExtra, rUsername))
            os.system('sudo mysql -u root%s -e "FLUSH PRIVILEGES;"' % rExtra)
            rNewCredentials = True
            break
        elif rRet == "N": break
    
    ##################################################
    # FINISHED                                       #
    ##################################################
    
    printc("Configuration completed!", col.OKGREEN, 2)
    if rNewCredentials:
        print(" ")
        printc("MySQL Username: %s" % rUsername)
        printc("MySQL Password: %s" % rPassword)
        print(" ")
        printc("You will not see these credentials again!")
        printc("You should probably save them somewhere.")