Added libs

This commit is contained in:
Lucas
2026-01-25 13:55:46 +10:00
parent 575c682afc
commit f70af3c4ea
229 changed files with 26983 additions and 0 deletions

4
app/BKP/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
__pycache__
.venv
*.log
app.zip

75
app/BKP/config.json Normal file
View File

@@ -0,0 +1,75 @@
{
"app":{
"id":"app",
"checkUpdates": true,
"repositories":["http://error/data"],
"version": 0
},
"main":{
"terminalWindow": true
},
"passwordManager":{
"package": "lockbox",
"client": "lockboxClient"
},
"updater":{
"autoUpdate": true,
"checkUpdates": true,
"repositories":[
"http://n0sys.duckdns.org:40404/libs"
]
},
"packages":[
{
"id":"fspn",
"checkUpdates": true,
"repositories":["http://error/data"],
"version": 0
},
{
"id":"noSys",
"checkUpdates": true
},
{
"id":"fileTransfer",
"checkUpdates": true
},
{
"id":"api",
"checkUpdates": true,
"server": {
"host": "127.0.0.1",
"port": "5050"
}
},
{
"id":"vueNoSys",
"checkUpdates": true,
"server": {
"host": "127.0.0.1",
"port": "3001"
}
},
{
"id":"lockbox",
"checkUpdates": true,
"servers": {
"api": {
"port": "5001"
}
}
},
{
"id":"rendezvous",
"checkUpdates": true,
"server": {
"host": "0.0.0.0",
"port": 40441
}
},
{
"id":"p2post",
"checkUpdates": true
}
]
}

5
app/BKP/info.json Normal file
View File

@@ -0,0 +1,5 @@
{
"id":"app",
"version":0,
"modules":[]
}

70
app/BKP/main.py Normal file
View File

@@ -0,0 +1,70 @@
import os, sys
import time
import logging
import traceback
# TODO NOT SURE IF SYS PATH IS A GOOD PRACTICE
root_dir = os.path.normpath(__file__.split("libs")[0])
sys.path.append(root_dir)
from libs.app.utils import Utils, kargs_to_array, get_logger, is_http_running, config_root_logger
logger = None
try:
config_root_logger()
logger = get_logger()
utils = Utils()
except Exception:
logging.exception("ERROR")
from libs.app.updater import Updater
def main():
log_ascii_art()
logger.debug(f"Readable params: {kargs_to_array()}")
if not is_noSys_running():
updater = Updater(utils)
utils.configs.read_packages()
from libs.noSys.noSysCore import NoSysCore
noSys = NoSysCore(updater)
else:
logger.debug(f"NoSys already running")
# TODO open url frontend
logger.info(f"---------------- Main ended ----------------")
def is_noSys_running():
try:
api_config = utils.configs.packages["api"].config
api_port = api_config["server"]["port"]
api_health_check_url = f"http://localhost:{api_port}/api/health"
logger.debug(f"Checking url: {api_health_check_url}")
return is_http_running(api_health_check_url)
except Exception:
logger.exception("ERROR")
def log_ascii_art():
logger.info("""
_ __ ____
/ |/ /__ / __/_ _____
/ / _ \ _\ \/ // (_-<
/_/|_/\___/ /___/\_, /___/
/___/
Every man must have freedom, must have the scope to form, test, and act upon his own choices, for any sort of development of his own personality to take place. He must, in short, be free in order that he may be fully human.
- Murray Rothbard
""")
if __name__ == '__main__':
try:
main()
time.sleep(30)
except Exception:
logger.exception("ERROR")
for sec in range(30):
logger.info(f"Closing in {30-sec}")
time.sleep(1)

59
app/BKP/start.py Normal file
View File

@@ -0,0 +1,59 @@
import os, sys
import logging
import shutil
import pathlib
import urllib.request
import time
from pathlib import Path
import zipfile
root_dir = pathlib.Path(__file__).parent.resolve()
logger = logging.getLogger("start")
def start():
global logger
logger.debug(f"---------------- START ----------------")
logger.debug(f"Root path: {root_dir}")
pathlib.Path(os.path.join(root_dir, "libs")).mkdir(parents=True, exist_ok=True)
download_app()
from libs.app.utils import Utils, get_logger, create_venv, download_file, kargs_to_array
create_venv()
args = kargs_to_array()
# args.append("updateApp=False") # NEVER SET TRUE
# args.append("updateLibs=True")
utils = Utils()
main_file_path = os.path.join(root_dir, "libs","app", "main.py")
pid = utils.new_python_process(main_file_path, args)
logger.info(f"Main process running. PID {pid} - Args: {args}")
logger.info(f"---------------- END ----------------")
def download_app():
url = f"{default_repository}/app/app.zip"
path = os.path.join(root_dir, "libs", "app.zip")
if(not os.path.exists(path)):
logger.debug(f"Downloading from URL: {url} to {path}")
urllib.request.urlretrieve(url, path)
logger.debug(f"Extracting all from {path}")
with zipfile.ZipFile(path, 'r') as zip_ref:
zip_ref.extractall(Path(path).parent.absolute())
default_repository = "http://n0sys.duckdns.org:30303/libs"
logger.addHandler(logging.StreamHandler())
app_logs_path = os.path.join(root_dir, "logs", "app")
shutil.rmtree(os.path.join(root_dir, "logs"), ignore_errors=True)
pathlib.Path(app_logs_path).mkdir(parents=True, exist_ok=True)
logger.addHandler(logging.FileHandler(os.path.join(app_logs_path,'start.log'), mode="a", encoding="utf-8"))
logger.setLevel(logging.DEBUG)
if __name__ == '__main__':
try:
start()
except Exception as e:
logger.exception("ERROR")
time.sleep(30)

124
app/BKP/updater.py Normal file
View File

@@ -0,0 +1,124 @@
import sys
import subprocess
import urllib.parse
import urllib.request
import os
from pathlib import Path
import pathlib
import time
import json
import logging
import zipfile
from threading import Thread
from libs.app.utils import Utils, Package, get_logger, root_dir
logger = get_logger("updater")
class Updater():
def __init__(self, utils:Utils):
self.utils = utils
self.libs_path = os.path.join(root_dir, 'libs')
self.start()
def start(self):
logger.info(f"---------------- Updater Started ----------------")
# Create better validation code
if("updateApp" in self.utils.kargs):
if(self.utils.kargs["updateApp"]):
self.update_app()
elif(self.utils.configs.data["updater"]["autoUpdate"]):
self.update_app()
if("restart" in self.utils.flags and self.utils.flags["restart"]):
self.utils.kargs["updateApp"] = False
self.utils.restart_app()
if("updateLibs" in self.utils.kargs):
if(self.utils.kargs["updateLibs"]):
self.update_libs()
elif(self.utils.configs.data["updater"]["checkUpdates"]):
self.update_libs()
logger.info(f"---------------- Updater Ended ----------------")
def update_app(self):
latest_version_repository = (self.utils.configs.data["app"]["version"],None)
logger.info(f"App current version: {latest_version_repository[0]}")
logger.info(f"Updating app files")
# TODO FIX THIS
self.check_package_update(Package(config=self.utils.configs.data["app"]))
logger.info(f"App updated to version {latest_version_repository[0]}")
self.utils.flags["restart"] = True
def update_libs(self):
logger.info(f"Checking packages update")
threads:list[Thread] = []
for package in self.utils.configs.packages.values():
# Default is check updates
if(not "checkUpdates" in package.config or package.config["checkUpdates"]):
thread = Thread(target=self.check_package_update, args=(package,))
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
def check_package_update(self, package:Package):
logger.info(f"Updating package {package.config['id']}")
package_id = package.config['id']
package_path = os.path.join(self.libs_path, package_id)
if(package.info):
latest_version_repository = (package.info["version"],None)
else:
logger.info(f"Creating package directory: {package_path}")
Path(package_path).mkdir(parents=True, exist_ok=True)
latest_version_repository = (-1,None)
repositories = self.utils.configs.data["updater"]["repositories"][:]
if "repositories" in package.config:
for repository in package.config["repositories"]:
repositories.append(repository)
for repository in repositories:
try:
package_url = f"{repository}/{package_id}"
info_url = f'{package_url}/info.json'
logger.info(f"Reading remote info of {package_id} from repository {repository}")
with urllib.request.urlopen(info_url, timeout=2) as data:
remote_info = json.load(data)
logger.debug(f"{package_id} remote info: {remote_info}")
# TODO Remove 'or' condition -> "or remote_info["version"]==0"
if remote_info["version"] > latest_version_repository[0] or remote_info["version"]==0:
latest_version_repository = (remote_info["version"], package_url)
except Exception as e:
logger.error(f"Error reading remote info of {package_id} from repository {repository}: {e}")
if latest_version_repository[1]:
package_zip = f"{latest_version_repository[1]}/{package_id}.zip"
package_local_file = os.path.join(self.libs_path, f"{package_id}.zip")
logger.debug(f"Downloading package from {package_zip} to local file {package_local_file}")
self.download_package(package_zip, package_local_file)
self.pip_install_requirements(package_path)
def download_package(self, url, path):
urllib.request.urlretrieve(url, path)
logger.info(f"Extracting all from {path}")
with zipfile.ZipFile(path, 'r') as zip_ref:
zip_ref.extractall(Path(path).parent.absolute())
def pip_install_requirements(self, package_path):
path = os.path.join(package_path, "requirements.txt")
if(os.path.exists(path)):
logger.info(f"Pip installing requirements in {path}")
subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", path])
else:
logger.info(f"{package_path} no requirements.txt")
def check_module_requirements(self, package_path):
pass

256
app/BKP/utils.py Normal file
View File

@@ -0,0 +1,256 @@
import os, sys
import uuid
import pathlib
import json
import subprocess
root_dir = os.path.normpath(__file__.split("libs")[0])
node_id = str(uuid.uuid4())
### LOGGER ###
import logging, inspect
class CustomLoggingFormatter(logging.Formatter):
grey = "\x1b[0;37m"
green = "\x1b[1;32m"
yellow = "\x1b[1;33m"
red = "\x1b[1;31m"
purple = "\x1b[1;35m"
blue = "\x1b[1;34m"
light_blue = "\x1b[1;36m"
bold_red = "\x1b[31;1m"
blink_red = "\x1b[5m\x1b[1;31m"
reset = "\x1b[0m"
prefix = light_blue + '%(asctime)s' + reset + ' |'
colored_level = '%(levelname)-8s'
message = '| %(message)s' + ''
suffix = purple + ' (%(name)s %(filename)s:%(lineno)d)' + reset
FORMATS = {
logging.DEBUG: prefix + grey + colored_level + reset + message + suffix,
logging.INFO: prefix + blue + colored_level + reset + message + suffix,
logging.WARNING: prefix + yellow + colored_level + reset + message + suffix,
logging.ERROR: prefix + red + colored_level + reset + message + suffix,
logging.CRITICAL: prefix + bold_red + colored_level + reset + message + suffix
}
file_format = '%(asctime)s | %(levelname)-8s | %(message)s | %(name)s (%(filename)s:%(lineno)d)'
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
# class FileFilter(logging.Filter):
# def filter(self, record):
# file_path = os.path.normpath(inspect.stack()[1].filename)
# head = os.path.split(file_path)[0]
# tail = os.path.split(file_path)[1]
# if head == os.path.normpath(root_dir):
# name = "app"
# else:
# after_lib = head.replace(os.path.join(root_dir, "libs"), "")
# name = after_lib.split(os.sep)[1]
# record.name = name
# print(name)
# return True
def add_logging_console_handler(logger:logging.Logger, logging_level=logging.DEBUG):
sh = logging.StreamHandler()
sh.setLevel(logging_level)
sh.setFormatter(CustomLoggingFormatter())
logger.addHandler(sh)
def add_logging_file_handler(logger:logging.Logger, directory, file_name, logging_level=logging.DEBUG):
file_path = os.path.join(root_dir, "logs", directory, f"{file_name}.log")
pathlib.Path(file_path).parent.mkdir(parents=True, exist_ok=True)
fh = logging.FileHandler(file_path)
fh.setLevel(logging_level)
fh.setFormatter(logging.Formatter(CustomLoggingFormatter().file_format))
logger.addHandler(fh)
def config_root_logger():
logger = get_logger(name="root")
# TODO Get lib that is calling logging
# logger.addFilter(FileFilter())
def get_logger(name=""):
file_path = os.path.normpath(inspect.stack()[1].filename)
head = os.path.split(file_path)[0]
tail = os.path.split(file_path)[1]
if head == os.path.normpath(root_dir):
lib = "root"
else:
after_lib = head.replace(os.path.join(root_dir, "libs"), "")
lib = after_lib.split(os.sep)[1]
if name == "root":
logger_name = name
elif name:
logger_name = f"{lib}.{name}"
else:
logger_name = lib
file_name = name if name else lib
logger = logging.getLogger(logger_name)
logger.propagate = False
if not logger.hasHandlers():
logger.setLevel(logging.DEBUG)
add_logging_console_handler(logger=logger, logging_level=logging.DEBUG)
add_logging_file_handler(logger=logger, directory=lib, file_name=file_name, logging_level=logging.DEBUG)
return logger
logger = get_logger()
logger.debug(f"Root dir: {root_dir}")
### VENV ###
import venv
def create_venv():
venv_dir = os.path.join(root_dir, ".venv")
if not os.path.exists(venv_dir):
logger.debug(f"Creating python venv: {venv_dir}")
venv.create(venv_dir, with_pip=True)
### DOWNLOADS ###
import urllib.request
def download_file(url, path):
head = os.path.split(path)[0]
if not os.path.exists(head):
logger.debug(f"Creating repository {head}")
pathlib.Path(head).mkdir(parents=True, exist_ok=True)
logger.debug(f"Downloading from URL: {url} to {path}")
urllib.request.urlretrieve(url, path)
### KARGS ###
def read_kargs():
kargs = {}
params = sys.argv
for param in params:
if "=" in param:
split = param.split("=")
key = split[0]
value = split[1]
if value == "true" or value == "True":
value = True
elif value == "false" or value == "False":
value = False
kargs[key] = value
kargs["rootDir"] = root_dir
return kargs
def kargs_to_array(kargs={}):
if not kargs:
kargs = read_kargs()
array = []
for key, value in kargs.items():
array.append(f"{key}={value}")
return array
### HTTP UTILS ###
def is_http_running(url):
try:
u:urllib.request.URLopener = urllib.request.urlopen(url)
u.close()
return True
except:
return False
### UTILS ###
class Utils:
def __init__(self):
self.kargs = read_kargs()
self.configs = Config()
self.flags = {}
# def get_env():
# return os.environ.get('NOSYS_ENV', "PROD")
# def download_file(self, package, file, destination, repository=None):
# if not repository:
# repository = self.default_repository
# url = f"{repository}/{package}/{file}"
# logger.debug(f"Downloading {file} from URL: {url}")
# urllib.request.urlretrieve(url, destination)
# def download_main_file(self, ignoreIfExists=True):
# main_path = os.path.join(self.root_dir, "libs","app", "main.py")
# if (not os.path.exists(main_path)) or (os.path.exists(main_path) and not ignoreIfExists):
# self.download_file(package="app", file="main.py", destination=main_path)
def is_terminal_visible(self):
try:
return self.configs.data["main"]["terminalWindow"]
except Exception as e:
return True
# def _create_log_dir(self):
# logs_path = os.path.join(self.root_dir, "logs")
# if not os.path.exists(logs_path):
# logger.debug(f"Creating logs directory: {logs_path}")
# pathlib.Path(logs_path).mkdir(parents=True, exist_ok=True)
def new_python_process(self, file_path, args):
python_executable = "python" if self.is_terminal_visible() else "pythonw"
args = [f"{root_dir}/.venv/scripts/{python_executable}", file_path] + args
logger.debug(f"Starting a new process: {args}")
process = subprocess.Popen(args, cwd=root_dir, creationflags=subprocess.CREATE_NEW_CONSOLE)
logger.debug(f"Process PID {process.pid} - {args}")
return process.pid
def restart_app(self):
args = [sys.executable, "start.py"] + kargs_to_array(self.kargs)
subprocess.Popen(args, cwd=root_dir, creationflags=subprocess.CREATE_NEW_CONSOLE)
logger.info(f"Restarting app: {args}")
self.exit_app()
def exit_app(self, exit_code=1):
os._exit(exit_code)
# sys.exit(exit_code)
class Config:
def __init__(self):
self.data = None
self.packages:dict[str, Package] = {}
self.read_config()
def read_config(self):
config_path = os.path.join(root_dir, "libs", "app", "config.json")
if(os.path.exists(config_path)):
with open(config_path) as f:
data = json.load(f)
self.data = data
self.read_packages()
else:
raise Exception(f"Config file {config_path} not exist")
def read_packages(self):
for package in self.data["packages"]:
try:
with open(os.path.join(root_dir,'libs',package["id"],'info.json')) as f:
self.packages[package["id"]] = Package(config=package, info=json.load(f))
except Exception as e:
self.packages[package["id"]] = Package(config=package, info={})
logger.error(e)
class Package:
def __init__(self, config={}, info={}):
self.config = config
self.info = info
self.modules:dict[str, any] = {}
self.read_modules()
def read_modules(self):
if "modules" in self.info:
for module in self.info["modules"]:
self.modules[module["id"]] = module