Commit effe66c2ff590b8d1c783cc726c1d57d399c9f85
Commits[COMMIT BEGIN]commit effe66c2ff590b8d1c783cc726c1d57d399c9f85 Author: 0x4248 <[email protected]> Date: Wed Jan 21 00:02:21 2026 +0000 orion: Orion is moving home After weeks of development orion now lives in its own repository! This is due to the fact that orion has grown quite large and complex, and it makes sense to give it its own space. Signed-off-by: 0x4248 diff --git a/lab/orion/.gitignore b/lab/orion/.gitignore deleted file mode 100644 index b2dd115..0000000 --- a/lab/orion/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -!pages/ -!static/** \ No newline at end of file diff --git a/lab/orion/COPYRIGHT.txt b/lab/orion/COPYRIGHT.txt deleted file mode 100644 index 88808d9..0000000 --- a/lab/orion/COPYRIGHT.txt +++ /dev/null @@ -1,3 +0,0 @@ -© 2026 0x4248 and contributors © 2026 4248 Systems, a part of 0x4248. Orion is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -<br> -Orion uses Python, FastAPI, GNU Software, and Starlette, which are open source software. Python is a trademark of the Python Software Foundation. All other trademarks are the property of their respective owners. The 0x4248 logo, 4248 Systems logo, and Orion logo are intellectual property of 0x4248. Their use is not granted under this license but is not under any trademark in the United Kingdom. diff --git a/lab/orion/MOVED b/lab/orion/MOVED new file mode 100644 index 0000000..290a211 --- /dev/null +++ b/lab/orion/MOVED @@ -0,0 +1,5 @@ +This code has moved house! + +Please see this URL or git clone it: + +https://github.com/0x4248/Orion \ No newline at end of file diff --git a/lab/orion/commands/echo.py b/lab/orion/commands/echo.py deleted file mode 100644 index ea53490..0000000 --- a/lab/orion/commands/echo.py +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request -from core.registry import registry -from core.commands import Command -from core import page -import manpages.echo - -def echo(request: Request, text: str = ""): - if not text: - return page.message(request, "ECHO", "No text provided") - return page.message(request, "ECHO", text) - -registry.register(Command( - name="echo", - handler=echo, - summary="Echo back text", - mode="both", - form_fields=[ - {"name": "text", "type": "text"} - ] -)) diff --git a/lab/orion/commands/system/heartbeats.py b/lab/orion/commands/system/heartbeats.py deleted file mode 100644 index eda7494..0000000 --- a/lab/orion/commands/system/heartbeats.py +++ /dev/null @@ -1,96 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -import threading -import datetime -import time - -from fastapi import Request, UploadFile -from core.registry import registry -from core.commands import Command -from core import page - - -global heartbeats_database -heartbeats_database = { - "id": [], - "timestamp": [], - "status": [] -} - -def heartbeat(): - heartbeat_id = 0 - while True: - heartbeats_database["id"].append(heartbeat_id) - heartbeats_database["timestamp"].append(datetime.datetime.now().isoformat()) - heartbeats_database["status"].append("alive") - heartbeat_id += 1 - if not threading.main_thread().is_alive(): - break - time.sleep(0.75) - -def calculate_average_heartbeat_bpm(): - if len(heartbeats_database["timestamp"]) < 2: - return 0 - first_time = datetime.datetime.fromisoformat(heartbeats_database["timestamp"][0]) - last_time = datetime.datetime.fromisoformat(heartbeats_database["timestamp"][-1]) - total_seconds = (last_time - first_time).total_seconds() - total_beats = len(heartbeats_database["timestamp"]) - 1 - if total_seconds == 0: - return 0 - bpm = (total_beats / total_seconds) * 60 - return round(bpm, 2) -def return_bpm(request: Request): - bpm = calculate_average_heartbeat_bpm() - return page.message( - request, - "HEARTBEAT", - f"Average server heart rate: {bpm} BPM", - ) - -def return_heart_database(request: Request): - bpm = calculate_average_heartbeat_bpm() - return page.message( - request, - "HEARTBEAT", - f"{heartbeats_database}", - ) - -registry.register(Command( - name="heart.bpm", - handler=return_bpm, - summary="Show server heartbeat rate", - mode="cli", -)) - -registry.register(Command( - name="heart.db_debug", - handler=return_heart_database, - summary="Show server heartbeat database", - mode="cli", -)) - - - -heart = threading.Thread(target=heartbeat, daemon=True) -heart.start() - -MOD_META = { - "name": "System Heartbeats", - "loc": "commands.system.heartbeats", - "description": "Module that tracks server heartbeats.", - "author": "0x4248", - "version": "1.0.0", - "license": "GPLv3", -} \ No newline at end of file diff --git a/lab/orion/commands/system/manual.py b/lab/orion/commands/system/manual.py deleted file mode 100644 index 29b2c35..0000000 --- a/lab/orion/commands/system/manual.py +++ /dev/null @@ -1,79 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import APIRouter, Request -from fastapi.responses import RedirectResponse -from core.registry import registry -from core.commands import Command -from core import page - -from core.manual import manual_registry -from core.commands import Command - -router = APIRouter() [email protected]("/man/{name}") -def manual_page_api(request: Request, name: str): - return manual_page(request, name) - -def manual_page(request: Request, name: str = ""): - if name == "": - # show forum - return RedirectResponse(url="/forum/man") - man = manual_registry.get(name) - if not man: - return page.message( - request, - "MANUAL", - error=f"No manual page for: {name}" - ) - - return page.static(request, f"MANUAL PAGE FOR: {man.name.upper()}", html=f""" - <h1 style="text-align: center; text-transform: uppercase;">{man.name}</h1> -<pre>{man.text}</pre> - -<a href="javascript:history.back()" style="text-align:center">[ BACK ]</a> - """, buttons=page.with_nav(page.DEFAULT_NAV)) - -registry.register(Command( - name="man", - handler=manual_page, - summary="Show manual page for command", - mode="both", - form_fields=[ - {"name": "name", "type": "text"}, - ], -)) - -### ALIASES ### - -registry.register(Command( - name="?", - handler=manual_page, - summary="Show manual page for command", - mode="both", - form_fields=[ - {"name": "name", "type": "text"}, - ], -)) - - -registry.register(Command( - name="help", - handler=manual_page, - summary="Show manual page for command", - mode="both", - form_fields=[ - {"name": "name", "type": "text"}, - ], -)) diff --git a/lab/orion/commands/system/open.py b/lab/orion/commands/system/open.py deleted file mode 100644 index 1b65450..0000000 --- a/lab/orion/commands/system/open.py +++ /dev/null @@ -1,63 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request -from fastapi.responses import RedirectResponse -from core.registry import registry -from core.commands import Command -from core import page - - -def open_page(request: Request, name: str = ""): - if not name: - return page.message( - request, - "OPEN", - "usage: open <page>" - ) - - cmd = registry.get(name) - if not cmd or not cmd.supports_ui(): - return page.message( - request, - "OPEN", - f"No UI page for: {name}" - ) - - return RedirectResponse(f"/command/{name}", status_code=303) - -def goto(request: Request, name: str = ""): - return RedirectResponse(f"/{name}", status_code=303) - -registry.register(Command( - name="open", - handler=open_page, - summary="Open a UI page", - mode="cli", -)) - - -registry.register(Command( - name="goto", - handler=goto, - summary="Jumps to a url", - mode="cli", -)) - -registry.register(Command( - name="g", - handler=goto, - summary="Jumps to a url", - mode="cli", -)) diff --git a/lab/orion/commands/system/sqldb.py b/lab/orion/commands/system/sqldb.py deleted file mode 100644 index c0a7795..0000000 --- a/lab/orion/commands/system/sqldb.py +++ /dev/null @@ -1,124 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -import os -from fastapi import Request -from core.registry import registry -from core.commands import Command -from core import page -import sqlite3 -from core.auth import users as auth_users -from core.console import logger -DB_PATH = "data/orion.db" - -db = sqlite3.connect(DB_PATH) -cursor = db.cursor() - -# if tables dont exist make DEMO and ACCOUNTS tables for testing -cursor.execute(""" -CREATE TABLE IF NOT EXISTS DEMO ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - value TEXT NOT NULL -); -""") -cursor.execute(""" -CREATE TABLE IF NOT EXISTS ACCOUNTS ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL, - password TEXT NOT NULL -); -""") -db.commit() - -cursor.execute("INSERT INTO DEMO (name, value) VALUES ('example1', 'value1')") -cursor.execute("INSERT INTO DEMO (name, value) VALUES ('example2', 'value2')") -cursor.execute("INSERT INTO ACCOUNTS (username, password) VALUES ('admin', 'admin')") -cursor.execute("INSERT INTO ACCOUNTS (username, password) VALUES ('user', 'password')") -db.commit() - -def auth_check(request: Request): - logger.info(m="Checking auth for SQLDB command", caller="SQLDB_Command") - user = request.cookies.get('user', 'None') - if not user: - return False - elif 'admin' not in auth_users[user]["roles"] and 'db' not in auth_users[user]["roles"]: - return False - return True - -def sql_print_table(request: Request, *args): - if not auth_check(request): - return page.message(request, "SQL ERROR", error="Unauthorized: Admin/DB role required.") - if len(args) == 0 or args[0] == "*": - logger.info(m="Selecting all tables", caller="SQLDB_Command") - cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") - args = [row[0] for row in cursor.fetchall()] - logger.info(m=f"Found tables: {args}", caller="SQLDB_Command") - output = "<span class='grey-text'>F4 to exit table view.</span><br><br>" - for arg in args: - logger.info(m=f"Printing table: {arg}", caller="SQLDB_Command") - table_name = arg - - try: - cursor.execute(f"SELECT * FROM {table_name}") - rows = cursor.fetchall() - columns = [description[0] for description in cursor.description] - - output += f"<h2>{table_name}</h2><table style='width:100%; border-collapse: collapse;' border='1'><tr>" - for col in columns: - output += f"<th style='text-align:left'>{col}</th>" - output += "</tr>" - for row in rows: - output += "<tr>" - for cell in row: - output += f"<td>{cell}</td>" - output += "</tr>" - output += "</table><br>" - except sqlite3.Error as e: - output = f"Error accessing table '{table_name}': {e}" - return page.message(request, "SQL ERROR", output) - if output: - return page.static(request, "SQL TABLES", output) - else: - return page.message(request, "SQL TABLES", error="No tables found in search.") - -registry.register(Command( - name="db.table.print", - handler=sql_print_table, - summary="Print a database table", - mode="cli", -)) - -def sql_exec(request: Request, *args): - if not auth_check(request): - return page.message(request, "SQL ERROR", error="Unauthorized: Admin/DB role required.") - query = " ".join(args) - response = "" - try: - cursor.execute(query) - response = cursor.fetchall() - db.commit() - return page.message(request, "SQL EXECUTED", f"Successfully executed SQL command: {query}<br>Response: {response}") - except sqlite3.Error as e: - return page.message(request, "SQL ERROR", error=f"Error executing SQL command: {e}") - -registry.register(Command( - name="db.sql", - handler=sql_exec, - summary="Execute an SQL command", - mode="cli", - parse_mode="raw", -)) - -# E.G db.sql SELECT * FROM DEMO diff --git a/lab/orion/commands/templates/hello_both.py b/lab/orion/commands/templates/hello_both.py deleted file mode 100644 index 1115b5a..0000000 --- a/lab/orion/commands/templates/hello_both.py +++ /dev/null @@ -1,36 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request -from core.registry import registry -from core.commands import Command -from core import page - -def both(request: Request, value: str = "", extra: str = ""): - return page.message( - request, - "BOTH", - f"value = {value or '(none)'} | extra = {extra or '(none)'}" - ) - -registry.register(Command( - name="both", - handler=both, - summary="CLI + UI command", - mode="both", - form_fields=[ - {"name": "value", "type": "text"}, - {"name": "extra", "type": "date"} - ], -)) \ No newline at end of file diff --git a/lab/orion/commands/templates/hello_cli.py b/lab/orion/commands/templates/hello_cli.py deleted file mode 100644 index ec3a957..0000000 --- a/lab/orion/commands/templates/hello_cli.py +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request -from core.registry import registry -from core.commands import Command -from core import page - -def hello_cli(request: Request, *args): - name = args[0] if args else "world" - return page.message(request, "HELLO (CLI)", f"hello {name}") - -registry.register(Command( - name="hello.world", - handler=hello_cli, - summary="CLI-only hello", - mode="cli", -)) \ No newline at end of file diff --git a/lab/orion/commands/testing/demo.py b/lab/orion/commands/testing/demo.py deleted file mode 100644 index 42d15f2..0000000 --- a/lab/orion/commands/testing/demo.py +++ /dev/null @@ -1,118 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request, UploadFile -from core.registry import registry -from core.commands import Command -from core import page - - -def hello_cli(request: Request, *args): - name = args[0] if args else "world" - return page.message(request, "HELLO (CLI)", f"hello {name}") - -registry.register(Command( - name="hello", - handler=hello_cli, - summary="CLI-only hello", - mode="cli", -)) - -def ui_only(request: Request, text: str = ""): - return page.message( - request, - "UI ONLY", - f"You typed: {text or '(empty)'}" - ) - -registry.register(Command( - name="uionly", - handler=ui_only, - summary="UI-only command", - mode="ui", - form_fields=[ - {"name": "text", "type": "text"}, - ], -)) - -def both(request: Request, value: str = "", extra: str = ""): - return page.message( - request, - "BOTH", - f"value = {value or '(none)'} | extra = {extra or '(none)'}" - ) - -registry.register(Command( - name="both", - handler=both, - summary="CLI + UI command", - mode="both", - form_fields=[ - {"name": "value", "type": "text"}, - {"name": "extra", "type": "time"} - ], -)) - - -def both_plus( - request: Request, - value: str = "", - enable: str | None = None, - payload: UploadFile | None = None, -): - flags = [] - if enable: - flags.append("enable") - - file_info = "(none)" - - file_data = payload.file.read() if payload else None - if payload: - file_info = payload.filename - - return page.message( - request, - "BOTH+", - f"value={value}\nflags={flags}\nfile={file_data}" - ) - - -registry.register(Command( - name="both_plus", - handler=both_plus, - summary="CLI + UI + checkbox + file", - mode="both", - form_fields=[ - {"name": "value", "type": "text"}, - {"name": "enable", "type": "checkbox"}, - {"name": "payload", "type": "file"}, - ], -)) - - -def file_demo(request: Request, upload: UploadFile | None = None): - if not upload: - return page.message( - request, - "FILE DEMO", - error="No file uploaded" - ) - - data = upload.file.read() - return page.message( - request, - "FILE DEMO", - f"Uploaded file: {upload.filename} ({len(data)} bytes)" - ) - diff --git a/lab/orion/config/modules.py b/lab/orion/config/modules.py deleted file mode 100644 index 15f4620..0000000 --- a/lab/orion/config/modules.py +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Modules list configuration file -# This file tells orion which modules to load at startup. -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - -MODULES = [ - "commands.system.open", - "commands.system.heartbeats", - "commands.testing.demo", - "commands.echo", - "commands.system.sqldb" -] \ No newline at end of file diff --git a/lab/orion/core/auth.py b/lab/orion/core/auth.py deleted file mode 100644 index 90fde91..0000000 --- a/lab/orion/core/auth.py +++ /dev/null @@ -1,93 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import APIRouter, Request, Form -from fastapi.responses import RedirectResponse -from core import page as p -from core import console -router = APIRouter() - -# ---- users DB (placeholder) ---- - -users = { - "admin": { - "password": "admin", - "roles": ["admin", "user", "db"], - "email": "admin@orion", - "telephone": "101", - }, - "user": { - "password": "user", - "roles": ["user"], - "email": "user@orion", - "telephone": "111", - } -} - -# ---- middleware ---- - -async def auth_middleware(request: Request, call_next): - console.logger.info(m=f"{request.method} {request.url.path} from {request.client.host}. USER: {request.cookies.get('user', 'Anonymous')}", caller="HTTP_Middleware") - if request.url.path.startswith("/login"): - return await call_next(request) - - user = request.cookies.get("user") - if user in users: - return await call_next(request) - - return RedirectResponse(url="/login", status_code=303) - -# ---- routes ---- - [email protected]("/login") -async def login_page(request: Request): - return p.form( - request, - title="LOGIN", - action="/login", - fields=[ - {"name": "username"}, - {"name": "password", "type": "password"}, - ], - msg="Please login with your credentials.", - ) - [email protected]("/login") -async def login_submit( - request: Request, - username: str = Form(...), - password: str = Form(...) -): - user = users.get(username) - if user and user["password"] == password: - response = RedirectResponse(url="/", status_code=303) - response.set_cookie("user", username, httponly=True) - return response - - return p.form( - request, - title="LOGIN", - action="/login", - fields=[ - {"name": "username"}, - {"name": "password", "type": "password"}, - ], - error="Invalid username or password.", - ) - [email protected]("/logout") -async def logout(): - response = RedirectResponse("/login", status_code=303) - response.delete_cookie("user") - return response diff --git a/lab/orion/core/commands.py b/lab/orion/core/commands.py deleted file mode 100644 index 60cf404..0000000 --- a/lab/orion/core/commands.py +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from dataclasses import dataclass, field -from typing import Callable, Dict, List, Optional, Any, Literal - -Mode = Literal["cli", "ui", "both"] -ParseModes = Literal["shlex", "raw"] -@dataclass -class Command: - name: str - handler: Callable[..., Any] - summary: str = "" - mode: Mode = "cli" - form_fields: List[Dict[str, Any]] = field(default_factory=list) - parse_mode: ParseModes = "shlex" - custom_attributes: Dict[str, Any] = field(default_factory=dict) - - def supports_cli(self) -> bool: - return self.mode in ("cli", "both") - - def supports_ui(self) -> bool: - return self.mode in ("ui", "both") diff --git a/lab/orion/core/console.py b/lab/orion/core/console.py deleted file mode 100644 index cd71c99..0000000 --- a/lab/orion/core/console.py +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -import datetime -from typing import Dict -import traceback - -from core.page import message - -global logger -global log_db - -import sys - -def _get_caller(): - f = sys._getframe(2) - module = f.f_globals.get("__name__", "<unknown>") - func = f.f_code.co_name - return f"{module}.{func}()" - - -class LogDatabase: - def __init__(self): - self.logs = {} - - def add_entry(self, level: str, caller: str, message: str) -> int: - log_id = len(self.logs) + 1 - timestamp = datetime.datetime.now().isoformat() - self.logs[log_id] = { - "id": log_id, - "timestamp": timestamp, - "level": level, - "caller": caller, - "message": message - } - return log_id - -class Logger: - def __init__(self, bark: bool = True, log_db_inp: LogDatabase | None = None): - self.bark = bark - self.log_db = log_db_inp - def log(self, caller: str = "Unknown", m: str | None = None, level: str = "INFO") -> int: - if self.log_db is None: - raise ValueError("No log database provided") - if m is None: - m = "No message provided" - if self.bark: - print(f"[{level}] {caller}: {m}") - log_id = log_db.add_entry(level, caller, m) - return log_id - - def debug(self, caller: str | None = None, m: str | None = None) -> int: - if caller is None: - caller = _get_caller() - return self.log(caller, m, "DEBUG") - - def info(self, caller: str | None = None, m: str | None = None) -> int: - if caller is None: - caller = _get_caller() - return self.log(caller, m, "INFO") - - def warning(self, caller: str | None = None, m: str | None = None) -> int: - if caller is None: - caller = _get_caller() - return self.log(caller, m, "WARNING") - - def error(self, caller: str | None = None, m: str | None = None) -> int: - if caller is None: - caller = _get_caller() - return self.log(caller, m, "ERROR") - - def critical(self, caller: str | None = None, m: str | None = None) -> int: - if caller is None: - caller = _get_caller() - return self.log(caller, m, "CRITICAL") - - def alarm(self, caller: str | None = None, m: str | None = None) -> int: - if caller is None: - caller = _get_caller() - return self.log(caller, m, "ALARM") - -# If already imported dont reinit -if 'logger' not in globals(): - log_db = LogDatabase() - logger = Logger(bark=True, log_db_inp=log_db) - logger.info(m="Logger initialized successfully") -else: - logger.info(m="Logger already initialized, skipping reinitialization") \ No newline at end of file diff --git a/lab/orion/core/dispatcher.py b/lab/orion/core/dispatcher.py deleted file mode 100644 index 75e1f66..0000000 --- a/lab/orion/core/dispatcher.py +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -import inspect - -async def dispatch(handler, *args, **kwargs): - result = handler(*args, **kwargs) - if inspect.isawaitable(result): - return await result - return result diff --git a/lab/orion/core/layout.py b/lab/orion/core/layout.py deleted file mode 100644 index c3085b2..0000000 --- a/lab/orion/core/layout.py +++ /dev/null @@ -1,253 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request - -STYLE = """ -<style> -html, body { - background: #000000; - color: #ffffff; - margin: 0; - padding: 0.5em; -} - -* { - font-size: 16px; - font-family: "Departure Mono", monospace; -} - -body { - max-width: 800px; - margin: auto; -} - -a { - color: #4da6ff; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -.header { - margin-bottom: 0.5em; -} - -hr { - border: none; - border-top: 1px solid #444; - margin: 0.5em 0; -} - -pre { - white-space: pre-wrap; -} - -input, textarea { - background: #000000; - color: #ffffff; - border: 1px solid #444; - font-family: monospace; - padding: 0.2em; - margin-bottom: 0.5em; -} - -input[type=submit] { - width: 100%; - color: lime; - font-weight: bold; -} - -input[type=textline] { - width: 100%; -} - -label { - font-weight: bold; - text-transform: uppercase; -} - - -.grey-text { - color: gray; - font-style: italic; -} - -.log-debug { - color: gray; -} - -.log-info { - color: #4da6ff; -} -.log-warning { - color: black; - background-color: yellow; -} -.log-error { - color: white; - background-color: red; -} - -.log-error-flash { - background-color: red; - color: white; - padding-top: 0.5em; - padding-bottom: 0.5em; - animation: flash-text 1s infinite; -} - -.flash { - animation: flash-text 1s infinite; -} - -@keyframes flash-text { - 0% { opacity: 1; } - 49% { opacity: 1; } - 50% { opacity: 0; } - 100% { opacity: 0; } -} - -.error { - background-color: red; - color: white; - padding-top: 0.5em; - padding-bottom: 0.5em; - animation: pulse_error 1s; -} - -.error-flash { - background-color: red; - color: white; - padding-top: 0.5em; - padding-bottom: 0.5em; - animation: flash-text 1s infinite; -} - -@keyframes pulse_error { - 0% { background-color: #ff8f8f; } - 100% { background-color: red; } -} - -.error strong { - text-decoration: underline; - text-align: center; -} - -textarea { - width: 100%; - height: 6em; -} - -.center { - text-align: center; -} - -hr, input, textarea { - border: 1px solid #fff; -} - -a:focus, a:hover { - background-color: #0044cc; - color: #ffffff; - border-radius: 0px; - border: none; - # dont add default html stuff - outline: none; - -} - -input:focus, textarea:focus { - outline: none; - border: 1px solid #4da6ff; -} - -input[type=submit]:focus , input[type=submit]:hover { - border: 1px solid lime; - animation: pulse 1s infinite; -} -@keyframes pulse { - 0% { border: 1px solid lime; } - 50% { border: 1px solid white; } - 100% { border: 1px solid lime; } -} -</style> -""" - -SCRIPT = """ -<script> -document.addEventListener('keydown', function(event) { - if (event.key === 'Escape') { - document.activeElement.blur(); - } - - if (event.key === 'F1') { - const firstInput = document.querySelector('input, textarea'); - if (firstInput) { - const commandName = firstInput.value.trim(); - if (commandName) { - window.location.href = '/man/' + encodeURIComponent(commandName); - } - } - } - - - if (event.key === 'F2') { - window.location.href = '/command'; - } - - if (event.target.tagName.toLowerCase() === 'input' || event.target.tagName.toLowerCase() === 'textarea') { - return; - } - if (event.key === 'F4' || event.key === ',' || event.key === 'Backspace') { - window.history.back(); - } - if (event.key === '.') { - const firstInput = document.querySelector('input, textarea'); - if (firstInput) { - firstInput.focus(); - } - } - - if (event.key === '`') { - const homeLink = document.querySelector('a[href="/"]'); - if (homeLink) { - homeLink.focus(); - } - } - -}); -</script> -""" - - -def layout(request: Request, title: str, buttons: list[tuple[str, str]], header_html: str | None, body_html: str) -> str: - nav = " ".join(f"[<a href='{href}'>{label}</a>]" for label, href in buttons) - header = header_html if header_html is not None else f"<div class='header'><strong>ORION SYSTEM:</strong> {title}<br>{nav}</div>" - return f""" - <html> - <head> - <title>ORION SYSTEM: {title}</title> - {STYLE} - </head> - <body> - {header} - <hr/> - {body_html} - </body> - {SCRIPT} - </html> - """ diff --git a/lab/orion/core/logbridge.py b/lab/orion/core/logbridge.py deleted file mode 100644 index be2dcdf..0000000 --- a/lab/orion/core/logbridge.py +++ /dev/null @@ -1,31 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -import logging - -class logBridge(logging.Handler): - def __init__(self, orionLoggerBridge): - super().__init__() - self.orionLoggerBridge = orionLoggerBridge - - def emit(self, record: logging.LogRecord): - try: - msg = self.format(record) - self.orionLoggerBridge.log( - f"BRIDGE -> {record.name}.{record.funcName}()", - msg, - record.levelname, - ) - except Exception: - self.handleError(record) diff --git a/lab/orion/core/manual.py b/lab/orion/core/manual.py deleted file mode 100644 index 527447c..0000000 --- a/lab/orion/core/manual.py +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from typing import Dict, Optional, List - -# Manual funcions -# Commands can create manual pages by doing manual.register(NAME, TEXT, ALIASES (List, optional)) - -class ManualPage: - def __init__(self, name: str, text: str, aliases: Optional[List[str]] = None): - self.name = name - self.text = text - self.aliases = aliases if aliases is not None else [] -class ManualRegistry: - def __init__(self): - self._manuals: Dict[str, ManualPage] = {} - - def register(self, name: str, text: str, aliases: Optional[List[str]] = None): - if name in self._manuals: - raise ValueError(f"Duplicate manual page: {name}") - manual_page = ManualPage(name, text, aliases) - self._manuals[name] = manual_page - if aliases: - for alias in aliases: - if alias in self._manuals: - raise ValueError(f"Duplicate manual page alias: {alias}") - self._manuals[alias] = manual_page - - def get(self, name: str) -> Optional[ManualPage]: - return self._manuals.get(name) - - def all(self) -> List[ManualPage]: - # Return only unique manual pages (avoid duplicates from aliases) - unique_manuals = {mp.name: mp for mp in self._manuals.values()} - return list(unique_manuals.values()) - -manual_registry = ManualRegistry() diff --git a/lab/orion/core/page.py b/lab/orion/core/page.py deleted file mode 100644 index d8dfe24..0000000 --- a/lab/orion/core/page.py +++ /dev/null @@ -1,272 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import Request -from fastapi.responses import HTMLResponse -from core.layout import layout -from typing import Iterable, Sequence - - -# ============================================================================ -# Core render primitive -# ============================================================================ - -def render( - request: Request, - *, - title: str, - body: str, - buttons: Sequence[tuple[str, str]] | None = None, - header: str | None = None, -) -> HTMLResponse: - """ - Lowest-level page renderer. - Everything funnels through this. - """ - return HTMLResponse(layout(request, title, buttons, header, body)) - - -# ============================================================================ -# Navigation -# ============================================================================ - -DEFAULT_NAV: list[tuple[str, str]] = [ - ("HOME <span style='color:grey;'>`</span>", "/"), - ("RUN <span style='color:grey;'>F2</span>", "/command"), - ("UI", "/search_forms"), - ("LOGOUT", "/logout"), - ("EXIT <span style='color:grey;'>F4</span>", "/exit"), -] - - -def with_nav( - buttons: Sequence[tuple[str, str]] | None = None, -) -> Sequence[tuple[str, str]]: - return buttons if buttons is not None else DEFAULT_NAV - - -# ============================================================================ -# Simple pages -# ============================================================================ - -def static( - request: Request, - title: str, - html: str, - *, - buttons: Sequence[tuple[str, str]] | None = None, -): - return render( - request, - title=title, - body=html, - buttons=with_nav(buttons), - ) - - -def message( - request: Request, - title: str, - text: str = "", - *, - error: str | None = None, - ok_href: str = "javascript:history.back()", - center: bool = True, - buttons: Sequence[tuple[str, str]] | None = None, -): - err = ( - f"<pre class='error'><strong>ERROR:</strong>\n{error}</pre>" - if error - else "" - ) - - body = f""" - {err} - <div class='{'center' if center else ''}'> - <pre>{text}</pre> - <a href='{ok_href}' autofocus>[ OK ]</a> - </div> - """ - - return render( - request, - title=title, - body=body, - buttons=with_nav(buttons), - ) - - -# ============================================================================ -# Menus / lists -# ============================================================================ - -def menu( - request: Request, - title: str, - entries: Iterable[tuple[str, str]], - *, - buttons: Sequence[tuple[str, str]] | None = None, -): - lines = [] - first = True - for label, href in entries: - if first: - lines.append(f"<a href='{href}' autofocus>[{label}]</a>") - first = False - else: - lines.append(f"<a href='{href}'>[{label}]</a>") - - body = "<pre>" + "\n".join(lines) + "</pre>" - - return render( - request, - title=title, - body=body, - buttons=with_nav(buttons), - ) - - -def sectioned_menu( - request: Request, - title: str, - sections: Iterable[tuple[str, Iterable[tuple[str, str]]]], - *, - buttons: Sequence[tuple[str, str]] | None = None, -): - lines = [] - for section_title, entries in sections: - lines.append(f"<strong>{section_title}</strong>") - for label, href in entries: - lines.append(f"<a href='{href}'>[{label}]</a>") - lines.append("") - - body = "<pre>" + "\n".join(lines) + "</pre>" - - return render( - request, - title=title, - body=body, - buttons=with_nav(buttons), - ) - - -# ============================================================================ -# Forms -# ============================================================================ - -def form( - request: Request, - title: str, - action: str, - fields: list[dict], - error: str | None = None, - msg: str | None = None, -): - rows = [] - - has_file = any(f.get("type") == "file" for f in fields) - enctype = "multipart/form-data" if has_file else "application/x-www-form-urlencoded" - - for f in fields: - name = f["name"] - ftype = f.get("type", "text") - - if ftype == "textarea": - rows.append( - f"<label>{name}</label><br/>" - f"<textarea name='{name}'></textarea>" - ) - - elif ftype == "checkbox": - rows.append( - f"<label>" - f"<input type='checkbox' name='{name}' /> {name}" - f"</label>" - ) - - elif ftype == "file": - accept = f.get("accept") - accept_attr = f" accept='{accept}'" if accept else "" - rows.append( - f"<label>{name}</label><br/>" - f"<input type='file' name='{name}'{accept_attr} />" - ) - - else: - rows.append( - f"<label>{name}</label><br/>" - f"<input name='{name}' type='{ftype}' />" - ) - - err = ( - f"<pre class='error'><strong>ERROR:</strong>\n{error}</pre>" - if error else "" - ) - - body = f""" - {err} - {f"<pre class='msg'>{msg}</pre>" if msg else ""} - <form method="post" action="{action}" enctype="{enctype}"> - {'<br/>'.join(rows)} - <br/><input type="submit" value="SUBMIT" /> - </form> - """ - return render( - request, - title=title, - body=body, - buttons=with_nav(), - ) - - -# ============================================================================ -# Future-proof helpers (cheap, useful) -# ============================================================================ - -def redirect_notice( - request: Request, - title: str, - text: str, - href: str, -): - """ - Message page that explains a redirect target. - Useful for permissions, warnings, deprecations. - """ - body = f""" - <pre>{text}</pre> - <a href='{href}' autofocus>[ CONTINUE ]</a> - """ - return render( - request, - title=title, - body=body, - buttons=with_nav(), - ) - - -def empty( - request: Request, - title: str = "", -): - """ - Placeholder page. - Useful during development. - """ - return render( - request, - title=title, - body="", - buttons=with_nav(), - ) diff --git a/lab/orion/core/registry.py b/lab/orion/core/registry.py deleted file mode 100644 index aa810c4..0000000 --- a/lab/orion/core/registry.py +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from typing import Dict, Optional, List -from .commands import Command - -class CommandRegistry: - def __init__(self): - self._cmds: Dict[str, Command] = {} - - def register(self, cmd: Command): - if cmd.name in self._cmds: - raise ValueError(f"Duplicate command: {cmd.name}") - self._cmds[cmd.name] = cmd - - def get(self, name: str) -> Optional[Command]: - return self._cmds.get(name) - - def all(self) -> List[Command]: - return list(self._cmds.values()) - -registry = CommandRegistry() diff --git a/lab/orion/main.py b/lab/orion/main.py deleted file mode 100644 index 2c126df..0000000 --- a/lab/orion/main.py +++ /dev/null @@ -1,97 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import FastAPI, Request -from fastapi.responses import FileResponse - -from core.logbridge import logBridge -from pages import command, about, console -from core import auth, console -from core import page as p -from commands.system import manual -from config.modules import MODULES - -def load_commands(): - for module_path in MODULES: - console.logger.info(m=f"Loading module: {module_path}", caller="ModuleLoader") - __import__(module_path) - -load_commands() - -import logging - -handler = logBridge(console.logger) -handler.setFormatter(logging.Formatter("%(message)s")) - -root = logging.getLogger() -root.handlers.clear() -root.addHandler(handler) -root.setLevel(logging.WARNING) - -for name in ( - "uvicorn", - "uvicorn.error", - "uvicorn.access", - "fastapi", -): - log = logging.getLogger(name) - log.handlers.clear() - log.addHandler(handler) - log.propagate = False - - -app = FastAPI() - -console.logger.info(m="Starting Orion Web Application") - -app.middleware("http")(auth.auth_middleware) - -app.include_router(auth.router) -app.include_router(command.router) -app.include_router(about.router) -app.include_router(manual.router) - -console.logger.info(m=app.router.routes) - [email protected]_handler(404) -async def not_found(request: Request, exc): - return p.static( - request, - "404 NOT FOUND", - "<pre class='error'>404 NOT FOUND</pre>" - "<a href='javascript:history.back()'>[ BACK ]</a>", - ) - [email protected]_handler(500) -async def server_error(request: Request, exc): - return p.static( - request, - "500 SERVER ERROR", - "<pre class='error'>500 SERVER ERROR</pre><pre class='grey-text'>{}</pre>".format(str(exc)) + - "<a href='javascript:history.back()'>[ BACK ]</a>", - ) - [email protected]("/favicon.ico") -async def favicon(): - return FileResponse("./static/mascot.ico") - -if __name__ == "__main__": - import uvicorn - uvicorn.run( - app, - host="0.0.0.0", - port=8000, - log_config=None, - access_log=True, - ) diff --git a/lab/orion/manpages/echo.py b/lab/orion/manpages/echo.py deleted file mode 100644 index 8aa0a70..0000000 --- a/lab/orion/manpages/echo.py +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from core import manual - -manual.manual_registry.register( - name="echo", - text=""" -DESCRIPTION: - Echo back the provided text. - -USAGE: - echo <text> - -EXAMPLE: - $ echo Hello, World! - Hello, World! - -ALIASES: - none -""" -) \ No newline at end of file diff --git a/lab/orion/pages/about.py b/lab/orion/pages/about.py deleted file mode 100644 index b27b7f9..0000000 --- a/lab/orion/pages/about.py +++ /dev/null @@ -1,65 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import APIRouter, Request, Form -from fastapi.responses import RedirectResponse -from core import page as p -import base64 -from core.registry import registry -from core.commands import Command - - -router = APIRouter() - -# The mascot looks like Wheatley from Portal 2, Because hes cute! -mascot_image_path = "./static/mascot.png" -with open(f"{mascot_image_path}", "rb") as f: - mascot_image_data = base64.b64encode(f.read()).decode("utf-8") - -with open("COPYRIGHT.txt", "r") as f: - LEGAL = f.read() - [email protected]("/about") -async def about_page(request: Request): - return p.static( - request, - title="ABOUT", - html=f""" -<h1 style="text-align: center;">ORION SYSTEM</h1> -<img - src="data:image/png;base64,{mascot_image_data}" - alt="Orion Mascot" - style="display:block; width:400px; image-rendering: pixelated; margin: 0 auto;" -> -<br> -<p style="text-align: center">{LEGAL}</p> -<pre> - -Version: 0.8.4 -Engine: OrionEngine -Online Users: 1 -© 2026 0x4248 -</pre> -""" - ) - -async def about_alias(request: Request): - return RedirectResponse(url="/about", status_code=302) - -registry.register(Command( - name="about", - handler=about_alias, - summary="Show information about Orion", - mode="cli" -)) diff --git a/lab/orion/pages/command.py b/lab/orion/pages/command.py deleted file mode 100644 index 973b436..0000000 --- a/lab/orion/pages/command.py +++ /dev/null @@ -1,154 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -import difflib -import shlex -from fastapi import APIRouter, Request, Form -from fastapi.responses import RedirectResponse -from core.registry import registry -from core import page as p -from core import dispatcher - -router = APIRouter() - [email protected]("/command") -async def command_page(request: Request): - lines = [ - f"[{c.name}] - {c.summary}" - for c in registry.all() - if c.supports_cli() - ] - return p.static( - request, - title="COMMAND", - html=f""" -<p>Enter a command below to run. <i style="color:grey;">Usage: <COMMAND> [ARGS...]</i></p> -<form method="post"> -<span style="color:grey;">$</span><input name="command" autofocus style="width:98%;border:0;border-bottom:1px solid #fff;"> -</form> -<hr> -<pre>{chr(10).join(lines)}</pre> -""" - ) - -def find_similar_commands(name: str, cutoff: float = 0.6): - commands = [c.name for c in registry.all() if c.supports_cli()] - return difflib.get_close_matches(name, commands, n=3, cutoff=cutoff) - - [email protected]("/command") -async def command_submit(request: Request, command: str = Form(...)): - try: - parts = shlex.split(command) - except ValueError as e: - return p.message(request, "ERROR", error=str(e)) - - if not parts: - return p.message(request, "ERROR", error="Empty command") - - name, *args = parts - cmd = registry.get(name) - - if not cmd or not cmd.supports_cli(): - did_you_mean = find_similar_commands(name) - if did_you_mean: - hint = ", ".join(f"<a href='/command'>{cmd}</a>" for cmd in did_you_mean) - else: - hint = "no similar commands found" - return p.message(request, "UNKNOWN", error=f"'{name}' is not a valid CLI command <br>Did you mean? {hint}") - - if cmd.supports_ui() and not args and cmd.form_fields: - return RedirectResponse(f"/command/{name}", 303) - - if cmd.parse_mode == "raw": - raw_args = command[len(name):].lstrip() - args = [raw_args] - - return await dispatcher.dispatch(cmd.handler, request, *args) - - [email protected]("/command/{name}") -async def command_form(request: Request, name: str): - cmd = registry.get(name) - if not cmd or not cmd.supports_ui(): - return RedirectResponse("/command", 303) - - return p.form( - request, - title=name.upper(), - action=f"/command/{name}", - fields=cmd.form_fields, - msg=cmd.summary, - ) - [email protected]("/command/{name}") -async def command_form_submit(request: Request, name: str): - cmd = registry.get(name) - if not cmd or not cmd.supports_ui(): - return RedirectResponse("/command", 303) - - data = await request.form() - return await dispatcher.dispatch(cmd.handler, request, **data) - - [email protected]("/list_forms") -async def list_forms(request: Request): - cmds = [c for c in registry.all() if c.supports_ui()] - - links = "\n".join( - f"<li><a href='/command/{c.name}'>{c.name}</a> — {c.summary}</li>" - for c in cmds - ) - - return p.static( - request, - title="SEARCH PAGE", - html=f""" -<p>Select a page to open:</p> -<ul> -{links} -</ul> -""" - ) - [email protected]("/search_forms") -async def search_forms_page(request: Request): - cmds = [c for c in registry.all() if c.supports_ui()] - lines = [f"[{c.name}] - {c.summary}" for c in cmds] - - return p.static( - request, - title="SEARCH FORMS", - html=f""" -<p>Open a UI page:</p> -<form method="post" action="/search_forms"> - ?<input name="page" type="text" - style="width:98%;border:0;border-bottom:1px solid #fff;" autofocus /> -</form> -<hr/> -<pre>Available: -{chr(10).join(lines)}</pre> -""" -) - [email protected]("/search_forms") -async def search_forms_submit(request: Request, page: str = Form(...)): - name = page.strip() - - if not name: - return p.message(request, "ERROR", "No page name provided", ok_href="/search_forms") - cmd = registry.get(name) - if not cmd or not cmd.supports_ui(): - return p.message(request, "UNKNOWN", error=f"No UI page for: {name}", ok_href="/search_forms") - return RedirectResponse(f"/command/{name}", 303) diff --git a/lab/orion/pages/console.py b/lab/orion/pages/console.py deleted file mode 100644 index 939666d..0000000 --- a/lab/orion/pages/console.py +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-only -# Orion System -# -# Copyright (C) 2026 0x4248 -# Copyright (C) 2026 4248 Systems -# -# Orion is free software; you may redistribute it and/or modify it -# under the terms of the GNU General Public License version 3 only, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -from fastapi import APIRouter, Request, Form -from fastapi.responses import RedirectResponse -from core import page as p -from core.registry import registry -from core.commands import Command -from core import console - - -router = APIRouter() - [email protected]("/console") -async def console_page(request: Request): - body = "<h2>System Logs</h2>\n" - body += "<span class='grey-text'>Press F4 to exit</span>\n" - body += "<pre>\n" - for log_id in sorted(console.log_db.logs.keys(), reverse=True): - entry = console.log_db.logs[log_id] - level = entry['level'] - level_class = level.lower() - body += ( - f"[{entry['timestamp']}] " - f"<span class='log-{level_class}'>[{level}]</span> " - f"{entry['caller'].replace('BRIDGE', '<span style=\"color:lime;\">BRIDGE</span>')}: " - f"{entry['message']}\n" - ) - body += "</pre>\n" - return p.static( - request, - "SYSTEM CONSOLE", - body - ) - -registry.register(Command( - name="console", - handler=console_page, - summary="Show system logs", - mode="cli" -)) - -registry.register(Command( - name="c", - handler=console_page, - summary="Show system logs", - mode="cli" -)) diff --git a/lab/orion/static/logo.png b/lab/orion/static/logo.png deleted file mode 100644 index dcb1405..0000000 Binary files a/lab/orion/static/logo.png and /dev/null differ diff --git a/lab/orion/static/mascot.ico b/lab/orion/static/mascot.ico deleted file mode 100644 index ef1ad09..0000000 Binary files a/lab/orion/static/mascot.ico and /dev/null differ diff --git a/lab/orion/static/mascot.png b/lab/orion/static/mascot.png deleted file mode 100644 index cd0b2e9..0000000 Binary files a/lab/orion/static/mascot.png and /dev/null differ diff --git a/lab/orion/static/mascot_hd.png b/lab/orion/static/mascot_hd.png deleted file mode 100644 index 9cea2e7..0000000 Binary files a/lab/orion/static/mascot_hd.png and /dev/null differ[COMMIT END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.