• commandhandler.py
  • from inners.classes import *
    from inners.script import AutoReload
    from time import sleep
    from os import system
    import os
    import os.path
    import threading
    from selenium import webdriver
    import tldextract
    import argparse
    import inners.phpserver as phpserver
    import sys
    def fignore(self: AutoReload, string): 
        exists = False
        res = string.split(" ")
        for file in res:
            type = "path" if os.path.isdir(file) or file[-1] == '/' else "file"; 
            file = file.removeprefix(".").removeprefix("/")
            if file == "":
                continue
            if not os.path.isfile(file) and not os.path.isdir(file):
                print(f"{msgHeaders.FAIL} {type.capitalize()} \"{file}\" does not exist!")
                continue
            for ignoring in self.ignoreArr: 
                if ignoring in file or file in ignoring: 
                    print(f"{msgHeaders.WARNING} The {type} \"{file}\" is already being ignored!")
                    exists = True
                    break
            if exists: 
                exists = False
                continue
            self.ignoreArr.append(file)
            print(f"{msgHeaders.INFO} Ignoring {type} \"{file}\".")
    
    
    def handleArgs(self: AutoReload):
        parser = argparse.ArgumentParser(description="Auto Reloader")
        parser.add_argument("--Server", action="store_true", help="Sets a PHP Sever. Default is localhost:80/")
        
        reloader_group = parser.add_argument_group("Reloader Starting Arguments")
        reloader_group.add_argument("-r", "--root", help="sets the url (this argument can't be used while Server is set)")
        reloader_group.add_argument("-s", "--start_page", help="sets the start page")
    
        reloader_util_group = parser.add_argument_group("Reloader Utility Arguments")
        reloader_util_group.add_argument("-i", "--ignore", help="ignores provided files or paths. instead reloads the current page")
        reloader_util_group.add_argument("--ignore_html",action="store_true", help="ignores changes happened in html files. instead reloads the current page.")
        reloader_util_group.add_argument("-l", "--log", action="store_true", help="prints log to stdout")
    
        server_group = parser.add_argument_group("PHP Server Arguments")
        server_group.add_argument("-a", "--address", help="sets server address")
        server_group.add_argument("-p", "--port", help="sets server port")
        server_group.add_argument("-P", "--php_path", help="sets php executable path")
        server_group.add_argument("-t", "--target", help="sets php server target directory")
    
        args = parser.parse_args()
    
    
        if not args.Server:
            if args.address or args.target:
                parser.error("--allow flag is required to use restricted arguments")
            if args.root: 
                self._root = args.root
            if args.ignore_html: 
                self.ignore = True
            if args.log: 
                self.print = True
            if args.ignore: 
                fignore(self, args.ignore)
            
        else:
            address, target, php_path, port = "", "", "", ""
            if args.root: 
                parser.error("This argument can not be used while Server is set!")
            if args.address:
                address = args.address
                self._root = args.address
            if args.target: 
                target = args.target
            if args.php_path: 
                php_path = args.php_path
            if args.port: 
                port = args.port
    
            self._Server = phpserver.Server()
            self._Server.startServer(_root=target, ip_addr=address, port=port, php_path=php_path)
            
            
            
    
        if args.root:
            if not "http://" in args.root or not "https://" in args.root:
                parser.error("Please enter a valid URL! ie: https://localhost:80")
            self._root = args.root
        if args.start_page: 
            self._start_page = args.start_page
        if args.log: 
            self.print = True
        
        
        
    def get_logs(log_path = "", row_count = 1000, hint = "", live = False):
        if os.name == "nt": 
            if log_path == "":
                log_path = "C:\\xampp\\apache\\logs\\error.log"
            system(f"powershell.exe \"Get-Content {log_path} -tail {row_count} " + ("" if not live else "-wait") + ("\"" if hint == "" else f"| Select-String '{hint}'\""))
            return 
        if log_path == "":
            log_path = "/opt/lampp/logs/error_log"
        system("tail" + ("" if not live else "-f") + f" {log_path} -n {row_count}" + ("" if hint == "" else f" | grep {hint}"))
    
    
    def helpcommand():
        print("\nhelp : Prints this message. its changed") 
        print("log [keys] <values> : As default prints last 1000 lines of the apache error log file. Use -n to specify row count, -h to search a text/hint, -l to follow file changes, -p to set log path. Example usage: log -n 10 -h error -p /path/to/logFile")
        print("sys(<command>) : will use the python's system function to run commands. Be careful with this one. IT HAS DIRECT ACCESS TO YOUR SHELL AND WILL EXECUTE EVERY COMMAND EVEN IF THEY ARE DANGEROUS. DO NOT RUN THIS SCRIPT AS ROOT OR SU IF YOU WANT TO BE SAFE!")
        print("ignore <keyword(s)> : Ignores changes happened at file paths contains the keyword. Reloads the current page instead. (Use \"ignore html\" to ignore changes happened in html files. Reusing will stop ignoring.)")
        print("exit : Closes the script")
        print("driver <keyword>: Will get ChromeDriver's status and can close or start it. Keywords: start | restart | close | status")
        print("cls: Will clear terminal's output")
        print("clearfetch : will clear terminal output then execute \"neofetch\"")
        print("<file path> : If you solely enter a file path script will check for the file and if it exist it will direct you to that file. If you want to redirect a page that isn't a file in the folder use \"page <pageName>\" instead.")
        print("get <url> : Directs ChromeDriver to specified URL.")
        print("page <pageName> : Direct ChromeDriver to specified page on the specified URL.")
        print("clear ignore : Clears ignore list that's been specified by the user")
    
    
    def driverStart(self: AutoReload): 
        self.driver = webdriver.Chrome(options=self.opt)
        driverT = threading.Thread(target=self.driver.get, args=(self._root + self._start_page, ))
        driverT.start()
        self.checkT = threading.Thread(target=self.continuousCheck)
        self.checkT.start()
    
    def server(self: AutoReload, command: str):
        if command[0] == "status": 
            if not hasattr(self, "_Server") or not self._Server.isAlive():
                print(f"{msgHeaders.INFO} Server is dead!")
                return 0
            print(f"{msgHeaders.INFO} Server alive!")
            return 0
        if command[0] == "start":
            for i,arg in enumerate(command): 
                if (i+1) < len(command) and (arg == "-t" or arg == "-target"):
                    target = command[i + 1]
                    continue
                if (i+1) < len(command) and (arg == "-a" or arg == "-address"):
                    address = command[i + 1]
                    continue
                if (i+1) < len(command) and (arg == "-p" or arg == "-port"):
                    port = command[i + 1]
                    continue
                if (i+1) < len(command) and (arg == "-P" or arg == "-php_address"):
                    php_path = command[i + 1]
                    continue
            if hasattr(self, "_Server") and self._Server.isAlive():
                print(f"{msgHeaders.WARNING} A server is already running!")
                print(f"{msgHeaders.FAIL} Can't open server!")
                return 0
            if not hasattr(self, "_Server"): 
                self._Server = phpserver.Server()
            self._Server.startServer(_root= target if "target" in locals() else "",
                                     ip_addr= address if "address" in locals() else "",
                                     port= port if "port" in locals() else "",
                                     php_path= php_path if "php_path" in locals() else "")
            print(f"{msgHeaders.INFO} Server started!")
            return 0
        if command[0] == "stop": 
            if not hasattr(self, "_Server") or not self._Server.isAlive(): 
                print(f"{msgHeaders.FAIL} Server already closed!")
                return 0
            self._Server.stopServer()
            return 0
        if command[0] == "log":
            if hasattr(self, "_Server") and self._Server.isAlive():
                if not hasattr(self, "ServerLog"): 
                    self.ServerLog = True
                print(f"{msgHeaders.INFO} Server logging " + ("enabled!" if self.ServerLog else "disabled!"))
                self._Server.setLogDestination(sys.stdout) if self.ServerLog else self._Server.setLogDestination(open(os.devnull, "w"))
                self.ServerLog = not self.ServerLog
            return 0
        return 1
                
    
            
    def driver(self: AutoReload, command: str): 
        if command == "close":
            if not self.isBrowserAlive():
                print(f"{msgHeaders.FAIL} Driver is already closed!")
                return 0
            self.driver.close()
            self.checkT.join()
            return 0
        if command == "start": 
            if self.isBrowserAlive() :
                print(f"{msgHeaders.FAIL} A driver instance is already open! Please run \"close driver\" first then execute this command. Or try \"restart driver\"")
                return 0
            driverStart(self)
            print(f"{msgHeaders.INFO} Driver started!")
            return 0
        if command == "restart":
            if self.isBrowserAlive():
                self.driver.close()
                self.checkT.join()
            driverStart(self)
            print(f"{msgHeaders.INFO} Driver restarted!")
            return 0
        if "status" == command:
            print(f"{msgHeaders.INFO} Driver Status: " + (f"{bcolors.OKGREEN}Alive{bcolors.ENDC}" if self.isBrowserAlive() else f"{bcolors.FAIL}Died{bcolors.ENDC}"))
            return 0
        return 1
    
    def log(self: AutoReload, res): 
        i = 0
        rowcount = "1000"
        hint = ""
        live = False 
        path = ""
        for arg in res:
            if(arg == "-n"):
                if((i + 1) < len(res) and not "-" in res[i + 1]):
                    rowcount = res[i + 1]
            if(arg == "-h"):
                if((i + 1) < len(res) and not "-" in res[i + 1]):
                    hint = res[i + 1]
            if(arg == "-l"): 
                live = True
            if(arg == "-p"):
                if((i + 1) < len(res) and not "-" in res[i + 1]):
                    path = res[i + 1]
            i += 1
        get_logs(row_count=int(rowcount), hint=hint, live=live, log_path=path)
        return 0
    
    @staticmethod
    def commandHandler(self: AutoReload, command: str):
        if command.startswith("server"):
            if len(command) == len("server") or command[len("server")] == " ":
                command = command.lstrip().removeprefix("server ").rstrip().split()
                if not server(self, command):
                    return
                print(f"{msgHeaders.FAIL} Invalid usage of command!")
                print(f"{msgHeaders.INFO} Usage: \"server <keyword>\"\n       Keywords: stop, start, log and status")
                return
        
        if command.startswith("get"):
            if not len(command) == len("get") or command[len("get")] == " ":
                command = command.lstrip().removeprefix("get ").rstrip()
                if not "http" in command: 
                    command = "http://" + command
                self.driver.get(command)
                self._root = command
                return 
        
        if command.startswith("page"):
            if len(command) == len("page") or command[len("page")] == " ":
                command = command.lstrip().removeprefix("page ").rstrip()
                if command[0] != '/':
                    command = "/" + command
                if tldextract.extract(command).suffix != "": 
                    print(f"{msgHeaders.FAIL} Please use get command to open a web site! Page command works for pages for the provided root! {tldextract.extract(command)} ")
                    return
                self.driver.get(self._root + command)
                return
        
        if command.startswith("driver"):
            if not len(command) > len("driver") or command[len("driver")] == " ":
                command = command.lstrip().removeprefix("driver ").rstrip()
                if not driver(self, command): 
                    return
                print(f"{msgHeaders.FAIL} Invalid usage of command!")
                print(f"{msgHeaders.INFO} Usage: \"driver <keyword>\"\n       Keywords: close, start, restart and status")
                return
    
        if "clearfetch" == command:
            if os.name == "nt": 
                system("cls")
                system("neofetch")
                system("echo AutoReloader"),
                return
            system("clear && neofetch && echo AutoReloader")
            return
    
        if command.startswith("log"):
            if len(command) == len("log") or command[len("log")] == " ": 
                res = command.removeprefix("log ").split()
                log(self, res) 
                return
        
        if command.startswith("sys(") and command.endswith(")"):
            system(f"{command.removeprefix('sys(').removesuffix(')')}")
            return 
        if command == "cls":
            if os.name == "nt": 
                system("cls")
                return
            system("clear")
            return
       
        if command == "help": 
            helpcommand()
            return
        
        if command == "exit":
            if self.isBrowserAlive():
                self.driver.close()
            self.checkT.join()
            
            if hasattr(self, "_Server"): 
                self._Server.stopServer()
            self.close()
    
        if command == "ignore html" or command == "i-html":
            self.ignore = not self.ignore
            print(f"{msgHeaders.INFO} HTML Ignore Status: {self.ignore}\n")
            return
        
        if command == "clear ignore":
            self.ignoreArr.clear()
            print(f"{msgHeaders.WARNING}{msgHeaders.INFO} Ignore list cleared.\n")
            return
        if command.startswith("ignore"):
            if len(command) == len("ignore") or command[len("ignore")] == " ":
                fignore(self,command.removeprefix("ignore "))
                return
        if "clear cache" == command: 
            self.driver.execute_script("location.reload(true);")
            return
        if command != "":
            clear = command.split("?")
            if not os.path.isfile(clear[0]): 
                print(f"{msgHeaders.FAIL} File \"{command}\" does not exists in this directory! Also no command found with this alias! If you meant a page that isn't in directory, try \"page <target>\"")
                return
            self.driver.get(self._root + command)
            self.lastEVENT = command
            return