Spaces:
Running
Running
Download ural_module_engine.py from BachDaThan/Ural-AI: direct link, hf CLI and curl.
- Browser
- Download file 43 kB
-
https://huggingface.co/spaces/BachDaThan/Ural-AI/resolve/main/ural_module_engine.py
- Command line
-
hf download hf://spaces/BachDaThan/Ural-AI/ural_module_engine.py
-
curl -L -o ural_module_engine.py https://huggingface.co/spaces/BachDaThan/Ural-AI/resolve/main/ural_module_engine.py
43 kB
| import os | |
| # ================================================================ | |
| # URAL AI - DYNAMIC MODULE ENGINE v3.1 SECURE | |
| # File: ural_module_engine.py | |
| # | |
| # BAO MAT v3.1: | |
| # [1] Chi ADMIN moi chay duoc module (khach bi chan hoan toan) | |
| # [2] Xoa file tuc thi trong finally{} - khong the bo qua | |
| # [3] Sandbox: cam 30+ lenh nguy hiem | |
| # [4] Audit log moi lan chay (ai chay, cai gi, luc nao) | |
| # [5] Timeout 30s - khong de code chay mai mai | |
| # [6] Memory limit - khong de leak RAM | |
| # [7] 100% FREE - Khong the - Khong phi an | |
| # | |
| # CACH DUNG: Up len HuggingFace cung thu muc app.py | |
| # THEM 1 DONG vao dau app.py: import ural_module_engine | |
| # ================================================================ | |
| import os, sys, ast, time, types, shutil, hashlib, asyncio | |
| import importlib, importlib.util, traceback, re, json, random | |
| import threading | |
| from pathlib import Path | |
| from typing import Optional | |
| from datetime import datetime | |
| try: | |
| import pytz | |
| VN_TZ = pytz.timezone("Asia/Ho_Chi_Minh") | |
| except ImportError: | |
| import datetime | |
| class _VN_TZ: | |
| def __init__(self): pass | |
| VN_TZ = None | |
| # ================================================================ | |
| # CAU HINH | |
| # ================================================================ | |
| TEMP_DIR = "/tmp/ural_mods" | |
| AUDIT_LOG = "/tmp/ural_audit.log" # Log moi lan chay (trong RAM, mat khi restart) | |
| os.makedirs(TEMP_DIR, exist_ok=True) | |
| def _get_keys(prefix): | |
| keys = [v for k,v in os.environ.items() if k.startswith(prefix) and v.strip()] | |
| s = os.getenv(prefix) | |
| if not keys and s: keys = [s] | |
| return keys | |
| GROQ_KEYS = _get_keys("GROQ_API_KEY") | |
| GEMINI_KEYS = _get_keys("GEMINI_API_KEY") | |
| HF_TOKEN = os.getenv("HF_TOKEN", "") | |
| # ================================================================ | |
| # LOP BAO MAT 1: DANH SACH LENH CAM TUYET DOI | |
| # Bat ky code nao chua cac chuoi nay se bi TU CHOI ngay lap tuc | |
| # ================================================================ | |
| BLOCKED = [ | |
| # --- He thong / Shell --- | |
| "os.system(", "os.popen(", "os.execv(", | |
| "os.execve(", "os.fork(", "os.kill(", | |
| "os.unlink(\"/", "os.remove(\"/", | |
| "subprocess.run(", "subprocess.call(", "subprocess.Popen(", | |
| "subprocess.check_output(", | |
| # --- Xoa file he thong --- | |
| "shutil.rmtree(\"/\"", "shutil.rmtree('/'", | |
| "shutil.rmtree(\"/tmp\"", | |
| # --- Mang / Socket --- | |
| "socket.bind(", "socket.listen(", "socketserver", | |
| "http.server", "BaseHTTPServer", | |
| # --- Doc secrets --- | |
| "HF_TOKEN", "ADMIN_PASS", "ADMIN_USER", | |
| "GROQ_API_KEY", "GEMINI_API_KEY", | |
| # --- Code injection --- | |
| "exec(requests", "eval(requests", "exec(urllib", | |
| "eval(urllib", "__import__('os')", | |
| "importlib.import_module(\"os\"", | |
| # --- Doc file nhay cam --- | |
| "open(\"/etc", "open('/etc", | |
| "open(\"/root", "open('/root", | |
| "open(\"/proc", "open('/proc", | |
| # --- Crypto / Mining --- | |
| "hashlib.sha256", # Cho phep md5 nhung cam sha256 trong loop | |
| # --- Leak thong tin --- | |
| "pickle.loads(", "marshal.loads(", | |
| ] | |
| # Cho phep dung nhung thu nay (whitelist nhe hon) | |
| # (them vao day neu can mo khoa them thu vien) | |
| ALLOWED_IMPORTS = { | |
| "re", "json", "math", "statistics", "datetime", "collections", | |
| "itertools", "random", "string", "hashlib", "uuid", "base64", | |
| "io", "csv", "os.path", "pathlib", "time", "calendar", | |
| "requests", "bs4", "PIL", "openpyxl", "PyPDF2", "docx", | |
| "wikipedia", "numpy", "pandas", "pytz", | |
| "urllib.parse", "html", "xml.etree", | |
| } | |
| # ================================================================ | |
| # LOP BAO MAT 2: KIEM TRA AN TOAN NHIEU TANG | |
| # ================================================================ | |
| class SecurityChecker: | |
| def check(self, code: str) -> tuple: | |
| # Tang 1: Lenh cam tuyet doi | |
| for b in BLOCKED: | |
| if b in code: | |
| return False, f"LENH BI CHAN: `{b}`" | |
| # Tang 2: Cu phap Python hop le | |
| try: | |
| tree = ast.parse(code) | |
| except SyntaxError as e: | |
| return False, f"LOI CU PHAP: {e}" | |
| # Tang 3: Quet AST - phat hien import nguy hiem | |
| for node in ast.walk(tree): | |
| if isinstance(node, (ast.Import, ast.ImportFrom)): | |
| mod = "" | |
| if isinstance(node, ast.Import): | |
| for alias in node.names: | |
| mod = alias.name.split(".")[0] | |
| if mod in ("socket","subprocess","ctypes","multiprocessing", | |
| "pty","telnetlib","ftplib","smtplib"): | |
| return False, f"IMPORT NGUY HIEM: `{mod}`" | |
| elif isinstance(node, ast.ImportFrom): | |
| mod = (node.module or "").split(".")[0] | |
| if mod in ("socket","subprocess","ctypes","multiprocessing", | |
| "pty","telnetlib","ftplib","smtplib"): | |
| return False, f"IMPORT NGUY HIEM: `{mod}`" | |
| # Tang 4: Cam ghi file ra ngoai /tmp | |
| if isinstance(node, ast.Call): | |
| func = "" | |
| if isinstance(node.func, ast.Name): | |
| func = node.func.id | |
| elif isinstance(node.func, ast.Attribute): | |
| func = node.func.attr | |
| if func == "open" and node.args: | |
| if isinstance(node.args[0], ast.Constant): | |
| path = str(node.args[0].value) | |
| if not path.startswith("/tmp") and path.startswith("/"): | |
| return False, f"KHONG DUOC GHI FILE: `{path}`" | |
| return True, "OK" | |
| # ================================================================ | |
| # LOP BAO MAT 3: AUDIT LOG | |
| # Ghi lai moi lan chay: ai chay, luc nao, code gi, ket qua | |
| # ================================================================ | |
| class AuditLogger: | |
| def log(self, username: str, task_name: str, code_hash: str, | |
| success: bool, ms: int, note: str = ""): | |
| try: | |
| import pytz, datetime as _dt | |
| now = _dt.datetime.now(pytz.timezone("Asia/Ho_Chi_Minh")).strftime("%d/%m/%Y %H:%M:%S") | |
| except: | |
| import datetime as _dt | |
| now = _dt.datetime.now().strftime("%d/%m/%Y %H:%M:%S") | |
| status = "OK" if success else "FAIL" | |
| entry = (f"[{now}] USER={username} | TASK={task_name} | " | |
| f"HASH={code_hash} | {status} | {ms}ms" | |
| + (f" | {note}" if note else "")) | |
| # Ghi vao log file tam (trong /tmp - tu mat khi restart HF Space) | |
| try: | |
| with open(AUDIT_LOG, "a", encoding="utf-8") as f: | |
| f.write(entry + "\n") | |
| except: | |
| pass | |
| print(f"[AUDIT] {entry}") | |
| def read_log(self, last_n=20) -> str: | |
| try: | |
| with open(AUDIT_LOG, "r", encoding="utf-8") as f: | |
| lines = f.readlines() | |
| return "".join(lines[-last_n:]) or "(Chua co lich su)" | |
| except: | |
| return "(Chua co lich su)" | |
| # ================================================================ | |
| # LOP BAO MAT 4: MODULE ENGINE VOI CLEANUP TUYET DOI | |
| # finally{} dam bao xoa file du thanh cong hay loi | |
| # ================================================================ | |
| _security = SecurityChecker() | |
| _audit = AuditLogger() | |
| class ModuleEngine: | |
| def run(self, code: str, name="task", ctx: dict = None, | |
| username: str = "unknown", timeout: int = 30) -> dict: | |
| """ | |
| Chay code Python tam. | |
| - Ket qua luu vao bien RESULT | |
| - File TAM XONG LA XOA (finally dam bao) | |
| - Timeout 30 giay | |
| - Ghi audit log | |
| """ | |
| fp = mn = None | |
| out = {"ok": False, "data": None, "err": None, "ms": 0} | |
| code_hash = hashlib.md5(code.encode()).hexdigest()[:8] | |
| try: | |
| # Kiem tra bao mat truoc khi lam bat cu dieu gi | |
| safe, msg = _security.check(code) | |
| if not safe: | |
| out["err"] = msg | |
| _audit.log(username, name, code_hash, False, 0, f"BLOCKED: {msg}") | |
| return out | |
| # Inject context neu co | |
| if ctx: | |
| prefix = "\n".join(f"{k}={repr(v)}" for k,v in ctx.items()) | |
| code = prefix + "\n\n" + code | |
| # Tao file tam voi ten doc nhat | |
| uid = hashlib.md5(f"{name}{time.time()}{username}".encode()).hexdigest()[:8] | |
| fp = f"{TEMP_DIR}/m_{name}_{uid}.py" | |
| Path(fp).write_text(code, encoding="utf-8") | |
| # Chay voi timeout | |
| t0 = time.time() | |
| result_box = [None] | |
| error_box = [None] | |
| def _run_in_thread(): | |
| try: | |
| mn_local = Path(fp).stem | |
| spec = importlib.util.spec_from_file_location(mn_local, fp) | |
| mod = importlib.util.module_from_spec(spec) | |
| sys.modules[mn_local] = mod | |
| spec.loader.exec_module(mod) | |
| result_box[0] = getattr(mod, "RESULT", | |
| getattr(mod, "result", "Xong")) | |
| # Xoa khoi sys.modules ngay trong thread | |
| if mn_local in sys.modules: | |
| del sys.modules[mn_local] | |
| except Exception: | |
| error_box[0] = traceback.format_exc() | |
| thread = threading.Thread(target=_run_in_thread, daemon=True) | |
| thread.start() | |
| thread.join(timeout=timeout) | |
| elapsed_ms = round((time.time()-t0)*1000) | |
| if thread.is_alive(): | |
| # Timeout - thread van chay → danh dau loi | |
| out["err"] = f"TIMEOUT: Code chay qua {timeout} giay bi dung lai" | |
| _audit.log(username, name, code_hash, False, elapsed_ms, "TIMEOUT") | |
| return out | |
| if error_box[0]: | |
| out["err"] = error_box[0] | |
| _audit.log(username, name, code_hash, False, elapsed_ms) | |
| else: | |
| out["data"] = result_box[0] | |
| out["ok"] = True | |
| out["ms"] = elapsed_ms | |
| _audit.log(username, name, code_hash, True, elapsed_ms) | |
| except Exception: | |
| out["err"] = traceback.format_exc() | |
| _audit.log(username, name, code_hash, False, 0, "EXCEPTION") | |
| finally: | |
| # ============================================ | |
| # CLEANUP TUYET DOI - KHONG THE BO QUA | |
| # Chay du thanh cong, loi, hay timeout | |
| # ============================================ | |
| if fp and os.path.exists(fp): | |
| try: | |
| os.remove(fp) | |
| print(f"[CLEANUP] Da xoa: {os.path.basename(fp)}") | |
| except Exception as e: | |
| print(f"[CLEANUP WARN] Khong xoa duoc {fp}: {e}") | |
| # Xoa __pycache__ neu co | |
| cache = f"{TEMP_DIR}/__pycache__" | |
| if os.path.exists(cache): | |
| shutil.rmtree(cache, ignore_errors=True) | |
| # Xoa het file trong TEMP_DIR co tuoi > 60s (phong ngua leak) | |
| try: | |
| now = time.time() | |
| for f in Path(TEMP_DIR).glob("m_*.py"): | |
| if now - f.stat().st_mtime > 60: | |
| f.unlink(missing_ok=True) | |
| print(f"[CLEANUP-STALE] Xoa file cu: {f.name}") | |
| except: | |
| pass | |
| return out | |
| def from_template(self, name: str, username="unknown", **kw) -> str: | |
| tpl = TEMPLATES.get(name) | |
| if not tpl: | |
| return f"Khong co template '{name}'" | |
| code = tpl | |
| for k,v in kw.items(): | |
| code = code.replace("{"+"{"+k+"}"+"}", str(v)) | |
| code = code.replace("{"+k+"}", str(v)) | |
| r = self.run(code, name=name, username=username) | |
| return str(r["data"]) if r["ok"] else f"[LOI] {r['err']}" | |
| # ================================================================ | |
| # AI CODE WRITER — Tu viet code khi khong co template | |
| # Dung chung key GROQ/GEMINI/HF cua URAL AI | |
| # ================================================================ | |
| _WRITER_SYSTEM = """Ban la Python code generator chuyen nghiep. | |
| Nhiem vu: Nhan yeu cau, viet code Python HOAN CHINH thuc hien dung yeu cau. | |
| QUY TAC: | |
| 1. Chi tra CODE PYTHON THUAN, khong markdown, khong backtick, khong giai thich | |
| 2. Ket qua cuoi PHAI luu vao bien RESULT (string hoac co the str()) | |
| 3. Chi dung: requests, bs4, PIL, json, re, math, statistics, datetime, | |
| collections, itertools, base64, io, csv, openpyxl, PyPDF2, docx, | |
| wikipedia, numpy, os.path (chi doc), random, string, uuid, calendar, pytz | |
| 4. Wrap toan bo trong try/except. Loi: RESULT = f"Loi: {e}" | |
| 5. TUYET DOI KHONG DUNG: os.system, subprocess, socket, HF_TOKEN, ADMIN_PASS | |
| Vi du output: | |
| import math | |
| try: | |
| RESULT = str([math.sqrt(x) for x in [1,4,9,16]]) | |
| except Exception as e: | |
| RESULT = f"Loi: {e}" | |
| """ | |
| class AICodeWriter: | |
| def _call_groq(self, task): | |
| if not GROQ_KEYS: return None | |
| try: | |
| from groq import Groq | |
| client = Groq(api_key=random.choice(GROQ_KEYS)) | |
| resp = client.chat.completions.create( | |
| model="llama-3.1-8b-instant", | |
| messages=[ | |
| {"role":"system","content":_WRITER_SYSTEM}, | |
| {"role":"user","content":f"Viet code Python de: {task}"} | |
| ], | |
| max_tokens=900, temperature=0.1, | |
| ) | |
| return self._clean(resp.choices[0].message.content) | |
| except Exception as e: | |
| print(f"Groq writer loi: {e}"); return None | |
| def _call_gemini(self, task): | |
| if not GEMINI_KEYS: return None | |
| try: | |
| # Dùng gemini-2.0-flash (gemini-1.5-flash đã deprecated) | |
| import google.generativeai as genai | |
| genai.configure(api_key=random.choice(GEMINI_KEYS)) | |
| for _gm in ["gemini-2.0-flash", "gemini-2.5-flash", "gemini-flash-latest"]: | |
| try: | |
| model = genai.GenerativeModel(_gm) | |
| resp = model.generate_content(f"{_WRITER_SYSTEM}\n\nViet code de: {task}") | |
| return self._clean(resp.text) | |
| except Exception: continue | |
| return None | |
| except Exception as e: | |
| print(f"Gemini writer loi: {e}"); return None | |
| def _call_cerebras_writer(self, task): | |
| """ | |
| Router (đa-provider) — thay thế Groq/Cerebras cũ, nhanh, free. | |
| 🔄 MIGRATION (2026-07-17): TRƯỚC ĐÂY gọi thẳng Cerebras llama3.1-8b — | |
| Cerebras free tier đóng cửa 17/08/2026. Giờ dùng nhóm "code" qua | |
| yui_model_router (đa-provider, tự xoay vòng). Giữ nguyên tên | |
| method + chữ ký để mọi nơi gọi _call_cerebras_writer(...) không | |
| cần sửa gì thêm. | |
| """ | |
| try: | |
| import asyncio | |
| from yui_model_router import call_task_group | |
| async def _go(): | |
| return await call_task_group( | |
| group="code", prompt=f"Viet code Python de: {task}", | |
| system=_WRITER_SYSTEM, max_tokens=900, timeout_sec=12, | |
| ) | |
| result = asyncio.run(_go()) | |
| if result: | |
| return self._clean(result) | |
| except Exception as e: | |
| print(f"Router writer loi: {e}") | |
| return None | |
| def _call_hf(self, task): | |
| if not HF_TOKEN: return None | |
| try: | |
| from huggingface_hub import InferenceClient | |
| # Qwen2.5-7B dùng chat, không phải text-generation | |
| client = InferenceClient(token=HF_TOKEN) | |
| resp = client.chat_completion( | |
| model="Qwen/Qwen2.5-7B-Instruct", | |
| messages=[{"role":"system","content":_WRITER_SYSTEM}, | |
| {"role":"user","content":f"Viet code de: {task}"}], | |
| max_tokens=700, temperature=0.1 | |
| ) | |
| return self._clean(resp.choices[0].message.content) | |
| except Exception as e: | |
| print(f"HF writer loi: {e}"); return None | |
| def _clean(self, raw): | |
| raw = re.sub(r"^```(?:python)?\s*\n?", "", raw.strip()) | |
| raw = re.sub(r"\n?```\s*$", "", raw) | |
| if "RESULT" not in raw: | |
| raw += '\nRESULT = "Xong"' | |
| return raw.strip() | |
| def write_and_run(self, task_desc: str, context_data: str = "", | |
| username: str = "unknown") -> dict: | |
| full = task_desc + (f"\n\nDu lieu:\n{context_data[:2000]}" if context_data else "") | |
| print(f"[AI Writer] Dang viet code: {task_desc[:60]}...") | |
| code = None | |
| for fn in [self._call_cerebras_writer, self._call_gemini, self._call_hf]: | |
| code = fn(full) | |
| if code: break | |
| if not code: | |
| return {"ok":False,"data":None, | |
| "err":"Khong co AI kha dung (Cerebras/Gemini/HF deu that bai)"} | |
| result = _engine.run(code, name="ai_written", username=username) | |
| # Neu loi → AI tu sua 1 lan | |
| if not result["ok"]: | |
| print("[AI Writer] Code loi, dang tu sua...") | |
| fix = (f"Code bi loi:\n{code}\n\nLoi:\n{result['err'][:400]}\n\n" | |
| f"Sua lai de: {task_desc}") | |
| fixed = None | |
| for fn in [self._call_cerebras_writer, self._call_gemini, self._call_hf]: | |
| fixed = fn(fix) | |
| if fixed: break | |
| if fixed: | |
| result = _engine.run(fixed, name="ai_fixed", username=username) | |
| return result | |
| # ================================================================ | |
| # TEMPLATES SAN CO — 12 viec pho bien | |
| # ================================================================ | |
| TEMPLATES = { | |
| "read_pdf": """ | |
| import PyPDF2, io, base64 | |
| try: | |
| data = base64.b64decode(\"\"\"{b64}\"\"\") | |
| r = PyPDF2.PdfReader(io.BytesIO(data)) | |
| RESULT = "\\n".join(p.extract_text() or "" for p in r.pages)[:6000] | |
| except Exception as e: | |
| RESULT = f"Loi PDF: {e}" | |
| """, | |
| "read_word": """ | |
| import docx, io, base64 | |
| try: | |
| data = base64.b64decode(\"\"\"{b64}\"\"\") | |
| doc = docx.Document(io.BytesIO(data)) | |
| RESULT = "\\n".join(p.text for p in doc.paragraphs if p.text.strip())[:6000] | |
| except Exception as e: | |
| RESULT = f"Loi Word: {e}" | |
| """, | |
| "read_excel": """ | |
| import openpyxl, io, base64, json | |
| try: | |
| data = base64.b64decode(\"\"\"{b64}\"\"\") | |
| wb = openpyxl.load_workbook(io.BytesIO(data)) | |
| rows = list(wb.active.iter_rows(values_only=True)) | |
| RESULT = json.dumps(rows[:60], ensure_ascii=False, default=str) | |
| except Exception as e: | |
| RESULT = f"Loi Excel: {e}" | |
| """, | |
| "analyze_image": """ | |
| from PIL import Image | |
| import io, base64, json | |
| from collections import Counter | |
| try: | |
| data = base64.b64decode(\"\"\"{b64}\"\"\") | |
| img = Image.open(io.BytesIO(data)) | |
| small = img.convert("RGB").resize((50,50)) | |
| top_colors = Counter(list(small.getdata())).most_common(5) | |
| RESULT = json.dumps({ | |
| "format": img.format, "mode": img.mode, | |
| "width": img.width, "height": img.height, | |
| "top_colors_rgb": [list(c[0]) for c in top_colors] | |
| }) | |
| except Exception as e: | |
| RESULT = f"Loi anh: {e}" | |
| """, | |
| "scrape": """ | |
| import requests | |
| from bs4 import BeautifulSoup | |
| try: | |
| url = \"\"\"{url}\"\"\" | |
| r = requests.get(url, headers={"User-Agent":"Mozilla/5.0"}, timeout=12) | |
| r.encoding = r.apparent_encoding | |
| soup = BeautifulSoup(r.text, "html.parser") | |
| for t in soup(["script","style","nav","footer","aside"]): t.decompose() | |
| RESULT = soup.get_text("\\n", strip=True)[:5000] | |
| except Exception as e: | |
| RESULT = f"Loi scrape: {e}" | |
| """, | |
| "call_api": """ | |
| import requests, json | |
| try: | |
| url = \"\"\"{url}\"\"\" | |
| method = \"\"\"{method}\"\"\" | |
| headers = {headers} | |
| body = {body} | |
| fn = requests.post if method.upper()=="POST" else requests.get | |
| r = fn(url, json=body if method.upper()=="POST" else None, | |
| params=body if method.upper()=="GET" else None, | |
| headers=headers, timeout=15) | |
| try: RESULT = json.dumps(r.json(), ensure_ascii=False) | |
| except: RESULT = r.text[:3000] | |
| except Exception as e: | |
| RESULT = f"Loi API: {e}" | |
| """, | |
| "run_code": """ | |
| import sys, io | |
| code = \"\"\"{code}\"\"\" | |
| old = sys.stdout; sys.stdout = buf = io.StringIO() | |
| try: | |
| exec(compile(code, "<dynamic>", "exec"), {}) | |
| RESULT = buf.getvalue() or "Chay xong, khong co output" | |
| except Exception as e: | |
| RESULT = f"Loi: {e}" | |
| finally: | |
| sys.stdout = old | |
| """, | |
| "stats": """ | |
| import statistics, json | |
| try: | |
| data = {data} | |
| nums = [float(x) for x in data] | |
| RESULT = json.dumps({ | |
| "n": len(nums), "tong": sum(nums), | |
| "trung_binh": round(statistics.mean(nums),4), | |
| "trung_vi": statistics.median(nums), | |
| "nho_nhat": min(nums), "lon_nhat": max(nums), | |
| "do_lech": round(statistics.stdev(nums),4) if len(nums)>1 else 0 | |
| }, ensure_ascii=False) | |
| except Exception as e: | |
| RESULT = f"Loi thong ke: {e}" | |
| """, | |
| "text_tool": """ | |
| import re, json, collections | |
| text = \"\"\"{text}\"\"\" | |
| mode = \"\"\"{mode}\"\"\" | |
| try: | |
| if mode == "words": | |
| ws = re.findall(r'[\\w]+', text.lower()) | |
| top = collections.Counter(ws).most_common(20) | |
| RESULT = json.dumps({"total": len(ws), "top20": top}, ensure_ascii=False) | |
| elif mode == "emails": | |
| RESULT = json.dumps(list(set(re.findall(r'[\\w.+-]+@[\\w-]+\\.[\\w.]+', text)))) | |
| elif mode == "urls": | |
| RESULT = json.dumps(list(set(re.findall(r'https?://\\S+', text)))) | |
| elif mode == "clean": | |
| RESULT = re.sub(r'\\s+', ' ', text).strip()[:3000] | |
| elif mode == "summary": | |
| sents = [s.strip() for s in re.split(r'[.!?]+', text) if len(s.strip())>30] | |
| RESULT = '. '.join(sents[:5]) + '.' | |
| else: | |
| RESULT = f"Khong ro mode: {mode}" | |
| except Exception as e: | |
| RESULT = f"Loi: {e}" | |
| """, | |
| "convert": """ | |
| import json, csv, io | |
| raw = \"\"\"{data}\"\"\" | |
| src = \"\"\"{from}\"\"\" | |
| dst = \"\"\"{to}\"\"\" | |
| try: | |
| rows = list(csv.DictReader(io.StringIO(raw))) if src=="csv" else json.loads(raw) | |
| if dst == "markdown" and rows and isinstance(rows[0], dict): | |
| ks = list(rows[0].keys()) | |
| lines = ["| "+" | ".join(ks)+" |", "| "+" | ".join(["---"]*len(ks))+" |"] | |
| for r in rows[:30]: | |
| lines.append("| "+" | ".join(str(r.get(k,"")) for k in ks)+" |") | |
| RESULT = "\\n".join(lines) | |
| elif dst == "csv": | |
| buf = io.StringIO() | |
| if rows and isinstance(rows[0], dict): | |
| w = csv.DictWriter(buf, fieldnames=rows[0].keys()) | |
| w.writeheader(); w.writerows(rows) | |
| RESULT = buf.getvalue() | |
| else: | |
| RESULT = json.dumps(rows, ensure_ascii=False, indent=2) | |
| except Exception as e: | |
| RESULT = f"Loi convert: {e}" | |
| """, | |
| "wiki_search": """ | |
| import wikipedia, json | |
| wikipedia.set_lang("vi") | |
| query = \"\"\"{query}\"\"\" | |
| try: | |
| results = wikipedia.search(query, results=3) | |
| pages = [] | |
| for r in results[:2]: | |
| try: | |
| p = wikipedia.page(r, auto_suggest=False) | |
| pages.append({"title": p.title, "summary": p.summary[:800]}) | |
| except: pass | |
| RESULT = json.dumps(pages, ensure_ascii=False) | |
| except Exception as e: | |
| RESULT = f"Loi wiki: {e}" | |
| """, | |
| "make_report": """ | |
| import json, datetime, pytz | |
| data = {data} | |
| title = \"\"\"{title}\"\"\" | |
| vn_tz = pytz.timezone("Asia/Ho_Chi_Minh") | |
| now = datetime.datetime.now(vn_tz).strftime("%d/%m/%Y %H:%M") | |
| lines = [f"# {title}", f"Tao luc: {now}", "---"] | |
| if isinstance(data, dict): | |
| for k,v in data.items(): lines.append(f"**{k}:** {v}") | |
| elif isinstance(data, list): | |
| for i,item in enumerate(data,1): | |
| if isinstance(item,dict): | |
| lines.append(f"\\n### {i}. {item.get('name',item.get('ten',f'Muc {i}'))}") | |
| for k,v in item.items(): | |
| if k not in ("name","ten"): lines.append(f"- {k}: {v}") | |
| else: lines.append(f"{i}. {item}") | |
| RESULT = "\\n".join(lines) | |
| """, | |
| } | |
| # ================================================================ | |
| # BO NHAN DANG INTENT — 3 lop + fallback | |
| # ================================================================ | |
| AI_PATTERNS = [ | |
| (r"(ve|plot|bieu do|chart|graph|histogram)", "Tao bieu do/chart, tra ve ASCII art hoac mo ta chi tiet"), | |
| (r"(ma hoa|encode|decode|base64|hash|md5)", "Ma hoa/giai ma du lieu theo yeu cau"), | |
| (r"(nen|zip|compress|giai nen)", "Nen hoac giai nen du lieu"), | |
| (r"(sap xep|sort|loc|filter|tim kiem trong)", "Sap xep/loc/tim kiem du lieu"), | |
| (r"(cong thuc|formula|phuong trinh)", "Tinh toan theo cong thuc/phuong trinh"), | |
| (r"(dinh dang ngay|parse date|format date)", "Xu ly dinh dang ngay thang"), | |
| (r"(regex|bieu thuc chinh quy|pattern match)", "Tim kiem/trich xuat dung regex"), | |
| (r"(xml|html parse|json parse|yaml)", "Parse dinh dang du lieu co cau truc"), | |
| (r"(tao file|generate file|xuat file)", "Tao/xuat noi dung file dang text"), | |
| (r"(so sanh|compare|diff|khac biet)", "So sanh hai tap du lieu/van ban"), | |
| (r"(doc csv|phan tich csv|xu ly csv)", "Doc va phan tich du lieu CSV"), | |
| (r"(calendar|lich|ngay le|thu may)", "Tinh toan lich, ngay thang, thu trong tuan"), | |
| (r"(fibonacci|nguyen to|prime|factorial|giai thua)", "Giai bai toan so hoc/thuat toan"), | |
| (r"(password random|sinh mat khau|tao mat khau)", "Tao mat khau ngau nhien an toan"), | |
| (r"(uuid|id ngau nhien|random id|generate id)", "Tao ID/UUID ngau nhien"), | |
| (r"(don vi|unit convert|km.*mile|celsius|kg.*pound)","Chuyen doi don vi do luong"), | |
| (r"(palindrome|anagram|dao chu|kiem tra chuoi)", "Kiem tra/xu ly chuoi ky tu"), | |
| (r"(morse|ma morse|binary text|nhi phan)", "Ma hoa Morse hoac nhi phan"), | |
| (r"(ip address|dia chi ip|subnet)", "Tinh toan mang/IP"), | |
| (r"(percentile|quartile|variance|phan phoi)", "Thong ke nang cao"), | |
| (r"(qr code|qrcode|ma qr)", "Tao ma QR dang text/ASCII"), | |
| (r"(roman numeral|so la ma)", "Chuyen doi so La Ma"), | |
| (r"(currency|tien te|ty gia|exchange rate)", "Tinh toan tien te (API free)"), | |
| (r"(wordcloud|tan suat tu|bieu do tu)", "Phan tich tan suat tu ngu"), | |
| (r"(tinh thue|thue thu nhap|bao hiem|bhxh)", "Tinh toan thue/bao hiem VN"), | |
| (r"(luong|thu nhap|tinh luong|net salary)", "Tinh luong thuc nhan"), | |
| (r"(bmi|the trang|can nang|chieu cao)", "Tinh toan y te co ban (BMI, calo)"), | |
| (r"(so cccd|so dien thoai viet|validate)", "Kiem tra/validate du lieu VN"), | |
| (r"(gen otp|tao otp|otp generator)", "Tao OTP/ma xac thuc ngau nhien"), | |
| (r"(roman|binary|hex|octal|co so)", "Chuyen doi he co so"), | |
| (r"(caesar cipher|rot13|ma hoa van ban)", "Ma hoa van ban don gian"), | |
| (r"(text to morse|morse to text)", "Chuyen doi Morse code"), | |
| (r"(json format|json dep|pretty print)", "Format/lam dep JSON"), | |
| (r"(url encode|url decode|percent encode)", "Encode/decode URL"), | |
| (r"(time zone|mui gio|unix time)", "Chuyen doi mui gio/thoi gian"), | |
| (r"(color|mau sac|rgb|hex color|hsl)", "Chuyen doi ma mau RGB/HEX/HSL"), | |
| (r"(kiem tra email|validate email)", "Kiem tra email hop le"), | |
| (r"(dem ky tu|word count|character count)", "Dem ky tu/tu trong van ban"), | |
| (r"(tao bang|generate table|bang bieu)", "Tao bang du lieu dang markdown"), | |
| (r"(so nguyen|chia het|ucln|bcnn)", "Tinh toan so hoc: UCLN, BCNN"), | |
| (r"(tinh lai|lai suat|vay von|tra gop)", "Tinh lai suat/vay von/tra gop"), | |
| (r"(ma vach|barcode)", "Tao ma vach dang text"), | |
| (r"(lich am|am lich|ngay am)", "Tinh lich am lich duong"), | |
| (r"(tao slug|slug|url-friendly)", "Tao slug URL-friendly tu van ban"), | |
| (r"(camel case|snake case|pascal case)", "Chuyen doi dinh dang ten bien"), | |
| ] | |
| def detect_intent(user_text: str, files=None) -> Optional[dict]: | |
| t = user_text.lower().strip() | |
| # Lop 1: File dinh kem | |
| if files: | |
| for f in (files if isinstance(files, list) else [files]): | |
| name = getattr(f, "name", str(f)).lower() | |
| if name.endswith(".pdf"): return {"tpl":"read_pdf","file":f} | |
| if name.endswith((".docx",".doc")): return {"tpl":"read_word","file":f} | |
| if name.endswith((".xlsx",".xls")): return {"tpl":"read_excel","file":f} | |
| if name.endswith((".png",".jpg",".jpeg",".webp",".gif")): | |
| return {"tpl":"analyze_image","file":f} | |
| if name.endswith((".csv",".txt")): | |
| return {"tpl":"__ai_write__", | |
| "task":"Doc va phan tich file nay, tra ve thong ke tom tat","file":f} | |
| # Lop 2: Template co san | |
| code_m = re.search(r"```(?:python)?\s*\n(.*?)```", user_text, re.DOTALL|re.IGNORECASE) | |
| if code_m: return {"tpl":"run_code","code":code_m.group(1).strip()} | |
| url_m = re.search(r"https?://[^\s]+", user_text) | |
| if url_m and any(k in t for k in ["doc","lay noi dung","scrape","tom tat link"]): | |
| return {"tpl":"scrape","url":url_m.group(0)} | |
| if url_m and any(k in t for k in ["goi api","call api","post den","get tu"]): | |
| method = "POST" if any(k in t for k in ["post","gui"]) else "GET" | |
| return {"tpl":"call_api","url":url_m.group(0),"method":method,"headers":{},"body":{}} | |
| nums = re.findall(r"\b\d+(?:\.\d+)?\b", user_text) | |
| if len(nums)>=3 and any(k in t for k in ["thong ke","trung binh","phan tich so"]): | |
| return {"tpl":"stats","data":[float(n) for n in nums]} | |
| if any(k in t for k in ["dem tu","tim email","tim link","tim url","lam sach"]): | |
| mode = ("emails" if "email" in t else "urls" if ("link" in t or "url" in t) else | |
| "clean" if "sach" in t else "words") | |
| return {"tpl":"text_tool","text":user_text,"mode":mode} | |
| if any(k in t for k in ["tra wiki","wikipedia","wiki ve"]): | |
| q = re.sub(r"(tra wiki|wikipedia|wiki ve)","",t).strip() | |
| return {"tpl":"wiki_search","query": q or user_text} | |
| if re.search(r"(chuyen|convert).*(markdown|csv|json)", t): | |
| src = "csv" if "csv" in t else "json" | |
| dst = "markdown" if "markdown" in t else ("csv" if "csv" in t else "json") | |
| return {"tpl":"convert","from":src,"to":dst} | |
| # Lop 3: AI tu viet theo 44 pattern | |
| for pattern, task_desc in AI_PATTERNS: | |
| if re.search(pattern, t, re.IGNORECASE): | |
| return {"tpl":"__ai_write__","task":f"{task_desc}. Yeu cau: {user_text}"} | |
| # Lop 4: Fallback | |
| hints = ["tinh","tao","sinh ra","generate","viet ham","code de","script", | |
| "tu dong","xu ly","phan tich","convert","chuyen doi","kiem tra", | |
| "validate","parse","xu li"] | |
| if any(k in t for k in hints) and len(user_text) > 25: | |
| return {"tpl":"__ai_write__","task":user_text,"fallback":True} | |
| return None | |
| def _build_file_ctx(task, username): | |
| import base64 | |
| f = task.get("file") | |
| if not f: return "" | |
| try: | |
| path = f if isinstance(f, str) else f.name | |
| with open(path,"rb") as fp: | |
| b64 = base64.b64encode(fp.read()).decode() | |
| return _engine.from_template(task["tpl"], username=username, b64=b64) | |
| except Exception as e: | |
| return f"[Loi doc file: {e}]" | |
| def _read_file_text(f): | |
| try: | |
| path = f if isinstance(f, str) else f.name | |
| with open(path,"r",encoding="utf-8",errors="ignore") as fp: | |
| return fp.read()[:3000] | |
| except: return "" | |
| # ================================================================ | |
| # KIEM TRA QUYEN ADMIN — Buc tuong bao ve chinh | |
| # ================================================================ | |
| def _is_admin(request) -> bool: | |
| """ | |
| Lay ten admin tu bien moi truong ADMIN_USER (giong URAL AI goc). | |
| Tat ca nguoi dung KHAC deu bi tu choi hoan toan. | |
| """ | |
| admin_name = os.getenv("ADMIN_USER", "admin") | |
| if request is None: | |
| return False | |
| username = getattr(request, "username", None) | |
| return username == admin_name | |
| GUEST_BLOCKED_MSG = ( | |
| "🛑 TINH NANG NAY CHI DANH CHO ADMIN.\n" | |
| "Module Engine khong kha dung cho tai khoan khach.\n" | |
| "Vui long lien he Bach Da Than neu can ho tro." | |
| ) | |
| # ================================================================ | |
| # AUTO-HOOK — Khong can sua app.py | |
| # ================================================================ | |
| _engine = ModuleEngine() | |
| _ai_writer = AICodeWriter() | |
| def _patch_ural(): | |
| target = None | |
| for mod in sys.modules.values(): | |
| if hasattr(mod, "urals_brain"): | |
| target = mod; break | |
| if not target: return False | |
| _orig = target.urals_brain | |
| def _enhanced(message, history, request=None): | |
| # ════════════════════════════════════════════ | |
| # KIEM TRA QUYEN ADMIN TRUOC TIEN — khong qua duoc thi dung lai | |
| # ════════════════════════════════════════════ | |
| if not _is_admin(request): | |
| # Lay intent truoc de xem co can module khong | |
| user_text = "" | |
| files = None | |
| if isinstance(message, dict): | |
| user_text = message.get("text","") | |
| raw = message.get("files",[]) | |
| if raw: files = raw | |
| else: | |
| user_text = str(message) | |
| task = detect_intent(user_text, files) | |
| if task: | |
| # Khach co yeu cau module → chan va bao loi | |
| return GUEST_BLOCKED_MSG | |
| else: | |
| # Khach chat binh thuong → cho qua | |
| return _orig(message, history, request) | |
| # ════════════════════════════════════════════ | |
| # DA XAC NHAN LA ADMIN → XU LY BINH THUONG | |
| # ════════════════════════════════════════════ | |
| user_text = "" | |
| files = None | |
| if isinstance(message, dict): | |
| user_text = message.get("text","") | |
| raw = message.get("files",[]) | |
| if raw: files = raw | |
| else: | |
| user_text = str(message) | |
| username = getattr(request, "username", "admin") | |
| task = detect_intent(user_text, files) | |
| if not task: | |
| return _orig(message, history, request) | |
| tpl = task.get("tpl","") | |
| inject = "" | |
| try: | |
| label_map = { | |
| "read_pdf": "[NOI DUNG PDF]", | |
| "read_word": "[NOI DUNG WORD]", | |
| "read_excel": "[NOI DUNG EXCEL]", | |
| "analyze_image": "[THONG TIN ANH]", | |
| } | |
| if tpl in label_map: | |
| c = _build_file_ctx(task, username) | |
| inject = f"\n\n{label_map[tpl]}:\n{c}\n(Doc va tra loi dua tren noi dung tren.)" | |
| elif tpl == "run_code": | |
| r = _engine.from_template("run_code", username=username, code=task["code"]) | |
| inject = f"\n\n[KET QUA CHAY CODE]:\n{r}" | |
| elif tpl == "scrape": | |
| r = _engine.from_template("scrape", username=username, url=task["url"]) | |
| inject = f"\n\n[NOI DUNG TRANG WEB]:\n{r}" | |
| elif tpl == "call_api": | |
| r = _engine.from_template("call_api", username=username, | |
| url=task["url"], method=task.get("method","GET"), | |
| headers=str(task.get("headers",{})), body=str(task.get("body",{}))) | |
| inject = f"\n\n[KET QUA API]:\n{r}" | |
| elif tpl == "stats": | |
| r = _engine.from_template("stats", username=username, data=str(task["data"])) | |
| inject = f"\n\n[KET QUA THONG KE]:\n{r}" | |
| elif tpl == "text_tool": | |
| r = _engine.from_template("text_tool", username=username, | |
| text=task["text"], mode=task["mode"]) | |
| inject = f"\n\n[KET QUA XU LY VAN BAN]:\n{r}" | |
| elif tpl == "wiki_search": | |
| r = _engine.from_template("wiki_search", username=username, query=task["query"]) | |
| inject = f"\n\n[KET QUA WIKIPEDIA]:\n{r}" | |
| elif tpl == "convert": | |
| r = _engine.from_template("convert", username=username, | |
| data=task.get("data",""), **{"from":task["from"],"to":task["to"]}) | |
| inject = f"\n\n[KET QUA CONVERT]:\n{r}" | |
| elif tpl == "__ai_write__": | |
| task_desc = task.get("task", user_text) | |
| context_data = _read_file_text(task["file"]) if task.get("file") else "" | |
| result = _ai_writer.write_and_run(task_desc, context_data, username) | |
| if result["ok"]: | |
| label = "[KET QUA TINH TOAN]" if task.get("fallback") else "[KET QUA MODULE TU VIET]" | |
| inject = f"\n\n{label}:\n{result['data']}" | |
| else: | |
| print(f"[AI Writer that bai]: {result.get('err','')[:80]}") | |
| return _orig(message, history, request) | |
| except Exception as e: | |
| print(f"[Module Engine Hook] Loi: {e}") | |
| return _orig(message, history, request) | |
| if inject: | |
| if isinstance(message, dict): | |
| new_msg = dict(message) | |
| new_msg["text"] = (user_text or "Phan tich ket qua nay.") + inject | |
| message = new_msg | |
| else: | |
| message = message + inject | |
| return _orig(message, history, request) | |
| target.urals_brain = _enhanced | |
| print("[Module Engine v3.1] Da hook vao urals_brain!") | |
| return True | |
| class _LazyHook: | |
| def __init__(self): self._done = False | |
| def install(self): | |
| if _patch_ural(): self._done = True; return | |
| import builtins | |
| _orig = builtins.__import__ | |
| outer = self | |
| def _hooked(name, *a, **kw): | |
| mod = _orig(name, *a, **kw) | |
| # Chi kiem tra top-level import, khong can thiep sub-module | |
| # Tranh loi voi yt_dlp, gradio va cac thu vien phuc tap | |
| level = a[4] if len(a) >= 5 else kw.get("level", 0) | |
| is_toplevel = ("." not in str(name)) and (level == 0) | |
| if not outer._done and is_toplevel: | |
| try: | |
| if hasattr(mod, "urals_brain"): | |
| if _patch_ural(): | |
| outer._done = True | |
| builtins.__import__ = _orig | |
| except Exception: | |
| pass | |
| return mod | |
| builtins.__import__ = _hooked | |
| print("[Module Engine v3.1] Dang cho app.py load...") | |
| # ================================================================ | |
| # PUBLIC API | |
| # ================================================================ | |
| def run_task(name, username="admin", **kw): | |
| return _engine.from_template(name, username=username, **kw) | |
| def run_custom_code(code, name="custom", ctx=None, username="admin"): | |
| r = _engine.run(code, name=name, ctx=ctx, username=username) | |
| return str(r["data"]) if r["ok"] else f"[LOI] {r['err']}" | |
| def ai_do(task_desc, context_data="", username="admin"): | |
| """Cho AI tu viet + chay code. Goi duoc tu bat cu dau trong URAL AI.""" | |
| r = _ai_writer.write_and_run(task_desc, context_data, username) | |
| return str(r["data"]) if r["ok"] else f"[LOI] {r.get('err','')}" | |
| def get_audit_log(last_n=20): | |
| """Xem lich su cac lan chay module (chi admin dung).""" | |
| return _audit.read_log(last_n) | |
| def list_templates(): | |
| return list(TEMPLATES.keys()) | |
| # ================================================================ | |
| # KHOI DONG | |
| # ================================================================ | |
| _hook = _LazyHook() | |
| _hook.install() | |
| _ai_str = " + ".join(filter(None,[ | |
| f"Groq({len(GROQ_KEYS)} key)" if GROQ_KEYS else "", | |
| f"Gemini({len(GEMINI_KEYS)} key)" if GEMINI_KEYS else "", | |
| "HuggingFace" if HF_TOKEN else "", | |
| ])) or "CHUA CO KEY AI" | |
| print(f""" | |
| +=====================================================+ | |
| | URAL DYNAMIC MODULE ENGINE v3.1 SECURE | | |
| | | | |
| | BAO MAT: | | |
| | [1] Chi ADMIN duoc dung (khach bi chan 100%) | | |
| | [2] Xoa file tuc thi trong finally{{}} | | |
| | [3] 30+ lenh nguy hiem bi chan tuyet doi | | |
| | [4] Audit log moi lan chay | | |
| | [5] Timeout 30s - khong bi treo | | |
| | [6] Quet AST phat hien import nguy hiem | | |
| | | | |
| | TINH NANG: | | |
| | {len(TEMPLATES):2d} templates san sang | | |
| | {len(AI_PATTERNS)} loai task AI tu xu ly | | |
| | AI writer: {_ai_str:<36} | | |
| | | | |
| | 100% FREE - Khong the - Khong phi an | | |
| +=====================================================+ | |
| """) | |
| # ================================================================ | |
| # TEST | |
| # ================================================================ | |
| if __name__ == "__main__": | |
| print("="*55) | |
| print("TEST MODULE ENGINE v3.1 SECURE") | |
| print("="*55) | |
| tests = [ | |
| ("Thong ke", lambda: run_task("stats", data="[85,92,78,95,88,100,76]")), | |
| ("Text tool", lambda: run_task("text_tool", text="URAL AI. URAL AI. AI manh.", mode="words")), | |
| ("Fibonacci", lambda: run_custom_code(""" | |
| def fib(n): | |
| a,b=0,1; r=[] | |
| for _ in range(n): r.append(a); a,b=b,a+b | |
| return r | |
| RESULT = fib(10) | |
| """)), | |
| ("Chan os.system", lambda: run_custom_code('import os; os.system("ls"); RESULT="ok"')), | |
| ("Chan HF_TOKEN", lambda: run_custom_code('x = HF_TOKEN; RESULT = x')), | |
| ("Chan subprocess",lambda: run_custom_code('import subprocess; RESULT="ok"')), | |
| ("Chan socket", lambda: run_custom_code('import socket; RESULT="ok"')), | |
| ("JSON->Markdown", lambda: run_task("convert", | |
| data='[{"ten":"Alice","tuoi":25}]', **{"from":"json","to":"markdown"})), | |
| ("Audit log", lambda: get_audit_log(5)), | |
| ] | |
| for name, fn in tests: | |
| print(f"\n[{name}]:") | |
| try: | |
| r = fn() | |
| print(f" -> {str(r)[:90]}") | |
| except Exception as e: | |
| print(f" -> LOI: {e}") | |
| print(f"\n{'='*55}") | |
| print(f"Templates: {len(list_templates())}") | |
| print(f"AI patterns: {len(AI_PATTERNS)}") | |
| print("="*55) | |