Files
TheOnlyMace b4110c3d66
Some checks failed
CI / Bot (Python) (push) Failing after 49s
CI / Dashboard (Next.js) (push) Failing after 11s
Update project configuration files, and API routes accordingly. Add SQLite runtime file ignores to .gitignore for better file management.
2026-07-21 17:11:38 +02:00

76 lines
3.1 KiB
Python

# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ |H|e|x|a|H|o|s|t| ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ ║
# ║ © 2026 HexaHost — All Rights Reserved ║
# ║ ║
# ║ discord ── https://discord.gg/hexahost ║
# ║ github ── https://github.com/theoneandonlymace ║
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
from __future__ import annotations
import ast
import json
import operator
import re
from typing import Any
def parse_role_id_list(raw: str | None) -> list[int]:
"""Parse a stored role-ID list (JSON or legacy Python repr)."""
if not raw:
return []
try:
parsed = json.loads(raw)
except json.JSONDecodeError:
try:
parsed = ast.literal_eval(raw)
except (ValueError, SyntaxError):
return []
if not isinstance(parsed, list):
return []
return [int(x) for x in parsed if str(x).isdigit()]
def dump_role_id_list(ids: list[int]) -> str:
return json.dumps(ids)
_MATH_ALLOWED = re.compile(r"^[\d+\-*/().\s]+$")
def _eval_math_node(node: ast.AST) -> float:
if isinstance(node, ast.Expression):
return _eval_math_node(node.body)
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
return float(node.value)
if isinstance(node, ast.UnaryOp) and isinstance(node.op, (ast.UAdd, ast.USub)):
value = _eval_math_node(node.operand)
return value if isinstance(node.op, ast.UAdd) else -value
if isinstance(node, ast.BinOp) and isinstance(node.op, (ast.Add, ast.Sub, ast.Mult, ast.Div)):
left = _eval_math_node(node.left)
right = _eval_math_node(node.right)
ops = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
}
if isinstance(node.op, ast.Div) and right == 0:
raise ZeroDivisionError("division by zero")
return ops[type(node.op)](left, right)
raise ValueError("unsupported expression")
def safe_math_eval(expression: str) -> str:
"""Evaluate basic arithmetic safely (digits, +, -, *, /, parentheses)."""
expr = expression.strip()
if not expr or not _MATH_ALLOWED.match(expr):
raise ValueError("invalid characters in expression")
tree = ast.parse(expr, mode="eval")
return str(_eval_math_node(tree))