Update configuration and README for improved setup and security; disable default API and emoji sync, and enhance Discord permission checks in API routes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
TheOnlyMace
2026-07-21 16:00:52 +02:00
commit fdfc8de44d
925 changed files with 75254 additions and 0 deletions

66
bot/utils/safe_parse.py Normal file
View File

@@ -0,0 +1,66 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ Safe parsing helpers — no eval() on untrusted data ║
# ╚══════════════════════════════════════════════════════════════════╝
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))