Spaces:
Sleeping
Sleeping
Commit
ยท
41387a4
1
Parent(s):
71fa3d9
app
Browse files- .gitignore +3 -0
- app-webshell.py +114 -0
- app.py +279 -101
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
venv-xor-tanakh2
|
| 2 |
+
__pycache__
|
| 3 |
+
.gradio
|
app-webshell.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app.py
|
| 2 |
+
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import subprocess
|
| 5 |
+
|
| 6 |
+
# --- SICHERHEITSHINWEIS ---
|
| 7 |
+
# Diese Webshell fรผhrt beliebigen Code auf dem Server aus.
|
| 8 |
+
# Machen Sie diesen Space NICHT รถffentlich, es sei denn, Sie verstehen die Risiken.
|
| 9 |
+
# Jeder, der Zugriff auf diesen Space hat, kann Befehle ausfรผhren.
|
| 10 |
+
# Am besten nur fรผr private oder organisatorische Spaces verwenden.
|
| 11 |
+
# -------------------------
|
| 12 |
+
|
| 13 |
+
WARNING_MESSAGE = """
|
| 14 |
+
โ ๏ธ **SICHERHEITSWARNUNG** โ ๏ธ
|
| 15 |
+
|
| 16 |
+
Dies ist eine funktionierende Web-Shell. Jeder Befehl, den Sie hier eingeben,
|
| 17 |
+
wird direkt auf dem Server des Hugging Face Space ausgefรผhrt.
|
| 18 |
+
|
| 19 |
+
- **Machen Sie diesen Space nicht รถffentlich!** Fremde kรถnnten ihn missbrauchen, um den Container zu beschรคdigen, Angriffe zu starten oder Ihre Daten (falls vorhanden) zu kompromittieren.
|
| 20 |
+
- Nutzen Sie diesen Space nur fรผr private Zwecke oder innerhalb Ihrer Organisation.
|
| 21 |
+
- Seien Sie vorsichtig mit den Befehlen, die Sie ausfรผhren (z. B. `rm -rf /`).
|
| 22 |
+
"""
|
| 23 |
+
|
| 24 |
+
def execute_command(command):
|
| 25 |
+
"""
|
| 26 |
+
Fรผhrt einen Shell-Befehl sicher aus und gibt stdout und stderr zurรผck.
|
| 27 |
+
"""
|
| 28 |
+
if not command:
|
| 29 |
+
return "Bitte geben Sie einen Befehl ein.", ""
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
# Fรผhre den Befehl aus.
|
| 33 |
+
# shell=True ist notwendig, um eine "echte" Shell-Umgebung zu haben
|
| 34 |
+
# (z.B. fรผr Pipes | oder cd), aber es ist auch ein Sicherheitsrisiko.
|
| 35 |
+
# Deswegen die groรe Warnung oben!
|
| 36 |
+
process = subprocess.run(
|
| 37 |
+
command,
|
| 38 |
+
shell=True,
|
| 39 |
+
capture_output=True,
|
| 40 |
+
text=True,
|
| 41 |
+
timeout=600 # Timeout von 60 Sekunden, um Endlos-Prozesse zu verhindern
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Kombiniere Standardausgabe und Standardfehler fรผr die Anzeige
|
| 45 |
+
stdout = process.stdout
|
| 46 |
+
stderr = process.stderr
|
| 47 |
+
|
| 48 |
+
# Gib eine informative Nachricht zurรผck, wenn kein Output kam
|
| 49 |
+
if not stdout and not stderr:
|
| 50 |
+
return "Befehl ausgefรผhrt, keine Ausgabe.", ""
|
| 51 |
+
|
| 52 |
+
return stdout, stderr
|
| 53 |
+
|
| 54 |
+
except subprocess.TimeoutExpired:
|
| 55 |
+
return "", "Fehler: Der Befehl hat das Zeitlimit von 60 Sekunden รผberschritten."
|
| 56 |
+
except Exception as e:
|
| 57 |
+
return "", f"Ein unerwarteter Fehler ist aufgetreten: {str(e)}"
|
| 58 |
+
|
| 59 |
+
# Wir definieren das Gradio Interface
|
| 60 |
+
with gr.Blocks(theme=gr.themes.Monochrome(), css=".gradio-container {background-color: #1a1a1a;}") as demo:
|
| 61 |
+
gr.Markdown(f"# ๐ Python Web-Shell fรผr Hugging Face Spaces")
|
| 62 |
+
gr.Markdown(WARNING_MESSAGE)
|
| 63 |
+
|
| 64 |
+
with gr.Row():
|
| 65 |
+
command_input = gr.Textbox(
|
| 66 |
+
label="Shell-Befehl eingeben",
|
| 67 |
+
placeholder="z.B. ls -l, whoami, pwd, pip list"
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
execute_button = gr.Button("๐ Ausfรผhren")
|
| 71 |
+
|
| 72 |
+
with gr.Row():
|
| 73 |
+
with gr.Column(scale=2):
|
| 74 |
+
gr.Markdown("### โ
Standardausgabe (stdout)")
|
| 75 |
+
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
| 76 |
+
output_stdout = gr.Code(label="stdout", interactive=False)
|
| 77 |
+
|
| 78 |
+
with gr.Column(scale=1):
|
| 79 |
+
gr.Markdown("### โ Standardfehler (stderr)")
|
| 80 |
+
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
| 81 |
+
output_stderr = gr.Code(label="stderr", interactive=False)
|
| 82 |
+
|
| 83 |
+
# Verknรผpfe die Button-Klicks und die Eingabe mit der Funktion
|
| 84 |
+
execute_button.click(
|
| 85 |
+
fn=execute_command,
|
| 86 |
+
inputs=command_input,
|
| 87 |
+
outputs=[output_stdout, output_stderr]
|
| 88 |
+
)
|
| 89 |
+
command_input.submit(
|
| 90 |
+
fn=execute_command,
|
| 91 |
+
inputs=command_input,
|
| 92 |
+
outputs=[output_stdout, output_stderr]
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
gr.Markdown("---")
|
| 96 |
+
gr.Markdown("### Nรผtzliche Beispielbefehle:")
|
| 97 |
+
gr.Examples(
|
| 98 |
+
examples=[
|
| 99 |
+
"ls -la",
|
| 100 |
+
"pwd",
|
| 101 |
+
"whoami",
|
| 102 |
+
"env",
|
| 103 |
+
"pip list",
|
| 104 |
+
"df -h",
|
| 105 |
+
"cat /proc/cpuinfo",
|
| 106 |
+
"uname -a"
|
| 107 |
+
],
|
| 108 |
+
inputs=command_input
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# Starte die App
|
| 113 |
+
if __name__ == "__main__":
|
| 114 |
+
demo.launch()
|
app.py
CHANGED
|
@@ -1,114 +1,292 @@
|
|
| 1 |
-
# app.py
|
| 2 |
-
|
| 3 |
import gradio as gr
|
| 4 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
# ---
|
| 7 |
-
#
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
# -------------------------
|
| 12 |
|
| 13 |
-
|
| 14 |
-
โ ๏ธ **SICHERHEITSWARNUNG** โ ๏ธ
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
"""
|
| 28 |
-
if
|
| 29 |
-
return "
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
try:
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
# Deswegen die groรe Warnung oben!
|
| 36 |
-
process = subprocess.run(
|
| 37 |
-
command,
|
| 38 |
-
shell=True,
|
| 39 |
-
capture_output=True,
|
| 40 |
-
text=True,
|
| 41 |
-
timeout=600 # Timeout von 60 Sekunden, um Endlos-Prozesse zu verhindern
|
| 42 |
-
)
|
| 43 |
-
|
| 44 |
-
# Kombiniere Standardausgabe und Standardfehler fรผr die Anzeige
|
| 45 |
-
stdout = process.stdout
|
| 46 |
-
stderr = process.stderr
|
| 47 |
-
|
| 48 |
-
# Gib eine informative Nachricht zurรผck, wenn kein Output kam
|
| 49 |
-
if not stdout and not stderr:
|
| 50 |
-
return "Befehl ausgefรผhrt, keine Ausgabe.", ""
|
| 51 |
-
|
| 52 |
-
return stdout, stderr
|
| 53 |
-
|
| 54 |
-
except subprocess.TimeoutExpired:
|
| 55 |
-
return "", "Fehler: Der Befehl hat das Zeitlimit von 60 Sekunden รผberschritten."
|
| 56 |
except Exception as e:
|
| 57 |
-
return
|
| 58 |
-
|
| 59 |
-
# Wir definieren das Gradio Interface
|
| 60 |
-
with gr.Blocks(theme=gr.themes.Monochrome(), css=".gradio-container {background-color: #1a1a1a;}") as demo:
|
| 61 |
-
gr.Markdown(f"# ๐ Python Web-Shell fรผr Hugging Face Spaces")
|
| 62 |
-
gr.Markdown(WARNING_MESSAGE)
|
| 63 |
-
|
| 64 |
-
with gr.Row():
|
| 65 |
-
command_input = gr.Textbox(
|
| 66 |
-
label="Shell-Befehl eingeben",
|
| 67 |
-
placeholder="z.B. ls -l, whoami, pwd, pip list"
|
| 68 |
-
)
|
| 69 |
-
|
| 70 |
-
execute_button = gr.Button("๐ Ausfรผhren")
|
| 71 |
-
|
| 72 |
-
with gr.Row():
|
| 73 |
-
with gr.Column(scale=2):
|
| 74 |
-
gr.Markdown("### โ
Standardausgabe (stdout)")
|
| 75 |
-
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
| 76 |
-
output_stdout = gr.Code(label="stdout", interactive=False)
|
| 77 |
-
|
| 78 |
-
with gr.Column(scale=1):
|
| 79 |
-
gr.Markdown("### โ Standardfehler (stderr)")
|
| 80 |
-
# KORREKTUR: Der Parameter `language="bash"` wurde entfernt.
|
| 81 |
-
output_stderr = gr.Code(label="stderr", interactive=False)
|
| 82 |
-
|
| 83 |
-
# Verknรผpfe die Button-Klicks und die Eingabe mit der Funktion
|
| 84 |
-
execute_button.click(
|
| 85 |
-
fn=execute_command,
|
| 86 |
-
inputs=command_input,
|
| 87 |
-
outputs=[output_stdout, output_stderr]
|
| 88 |
-
)
|
| 89 |
-
command_input.submit(
|
| 90 |
-
fn=execute_command,
|
| 91 |
-
inputs=command_input,
|
| 92 |
-
outputs=[output_stdout, output_stderr]
|
| 93 |
-
)
|
| 94 |
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
"
|
| 102 |
-
"
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
-
# Starte die App
|
| 113 |
if __name__ == "__main__":
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
import json
|
| 3 |
+
import logging
|
| 4 |
+
import argparse
|
| 5 |
+
import sys
|
| 6 |
+
import os
|
| 7 |
+
import math
|
| 8 |
+
import pickle
|
| 9 |
+
from deep_translator import GoogleTranslator
|
| 10 |
+
from gematria import calculate_gematria
|
| 11 |
+
from collections import defaultdict
|
| 12 |
+
from typing import Dict, List, Any, Optional
|
| 13 |
|
| 14 |
+
# --- Configuration ---
|
| 15 |
+
# Logging is kept for file-based or production logging, but we'll use print() for immediate console debug
|
| 16 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 17 |
+
BOOK_RANGE = range(1, 40)
|
| 18 |
+
CACHE_FILE = "tanakh_phrasedict.cache"
|
|
|
|
| 19 |
|
| 20 |
+
# --- Core Logic Functions ---
|
|
|
|
| 21 |
|
| 22 |
+
def get_power_result(total_sum: int, query_value: int) -> int:
|
| 23 |
+
"""Calculates the power or root result."""
|
| 24 |
+
if total_sum <= 0 or query_value <= 1:
|
| 25 |
+
return 1
|
| 26 |
+
if query_value <= total_sum:
|
| 27 |
+
try:
|
| 28 |
+
exponent = int(math.floor(math.log(total_sum, query_value)))
|
| 29 |
+
return query_value ** exponent
|
| 30 |
+
except (ValueError, OverflowError):
|
| 31 |
+
return 1
|
| 32 |
+
else:
|
| 33 |
+
for n in range(2, 65):
|
| 34 |
+
try:
|
| 35 |
+
root_result = query_value ** (1.0 / n)
|
| 36 |
+
if root_result <= total_sum:
|
| 37 |
+
return math.ceil(root_result)
|
| 38 |
+
except (ValueError, OverflowError):
|
| 39 |
+
return 1
|
| 40 |
+
return 1
|
| 41 |
|
| 42 |
+
def find_all_matching_phrases(target_sum: int, phrase_dictionary: Dict[int, List[Dict]]) -> List[Dict]:
|
| 43 |
+
"""Finds all phrases matching a target Gematria."""
|
| 44 |
+
return phrase_dictionary.get(int(target_sum), [])
|
| 45 |
+
|
| 46 |
+
# --- Global State: Load dictionary once at startup ---
|
| 47 |
+
try:
|
| 48 |
+
if not os.path.exists(CACHE_FILE):
|
| 49 |
+
raise FileNotFoundError(f"ERROR: Cache file '{CACHE_FILE}' not found. Please run 'build_indices.py' first.")
|
| 50 |
+
logging.info(f"Loading phrase dictionary from cache: {CACHE_FILE}")
|
| 51 |
+
with open(CACHE_FILE, 'rb') as f:
|
| 52 |
+
phrase_dictionary: Optional[Dict[int, List[Dict]]] = pickle.load(f)
|
| 53 |
+
logging.info("Phrase dictionary loaded successfully for the Gradio app.")
|
| 54 |
+
except (FileNotFoundError, IOError, pickle.UnpicklingError) as e:
|
| 55 |
+
logging.error(str(e))
|
| 56 |
+
phrase_dictionary = None
|
| 57 |
|
| 58 |
+
# --- Main Analysis Function for Gradio ---
|
| 59 |
+
|
| 60 |
+
def run_analysis(query: str, translate: bool, process_verses: int, results_per_verse: int, xor_depth: int, progress=gr.Progress(track_tqdm=True)):
|
| 61 |
+
"""The main analysis function called by the Gradio interface."""
|
| 62 |
+
if phrase_dictionary is None:
|
| 63 |
+
return "## Fatal Error\nCould not start analysis. The phrase dictionary cache file (`tanakh_phrasedict.cache`) is missing or corrupt. Please run `build_indices.py` and restart the app."
|
| 64 |
+
|
| 65 |
+
print("\n--- NEW ANALYSIS RUN ---") # Console Debug
|
| 66 |
+
output_lines = []
|
| 67 |
|
| 68 |
try:
|
| 69 |
+
query_value = calculate_gematria(query)
|
| 70 |
+
if query_value <= 1 and query:
|
| 71 |
+
return f"## Error\nQuery '{query}' has an invalid Gematria value ({query_value}). Please enter a valid query."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
except Exception as e:
|
| 73 |
+
return f"## Error\nCould not calculate Gematria for query '{query}'. Details: {e}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
+
progress(0, desc="Initializing...")
|
| 76 |
+
translator = None
|
| 77 |
+
if translate:
|
| 78 |
+
try:
|
| 79 |
+
translator = GoogleTranslator(source='iw', target='en')
|
| 80 |
+
except Exception as e:
|
| 81 |
+
logging.error(f"Could not initialize translator: {e}")
|
| 82 |
+
output_lines.append(f"**Warning:** Could not initialize translator: {e}")
|
| 83 |
+
|
| 84 |
+
output_lines.append(f"## XOR Gematria Resonance Analysis for: `{query}`")
|
| 85 |
+
|
| 86 |
+
verses_processed = 0
|
| 87 |
+
resonance_count = 0
|
| 88 |
+
|
| 89 |
+
# Using a generator to handle the nested loops cleanly and break out
|
| 90 |
+
def get_verses():
|
| 91 |
+
for book_num in BOOK_RANGE:
|
| 92 |
+
filepath = f"texts/torah/{book_num:02}.json"
|
| 93 |
+
if not os.path.exists(filepath): continue
|
| 94 |
+
with open(filepath, 'r', encoding='utf-8') as f:
|
| 95 |
+
data = json.load(f)
|
| 96 |
+
for chap_idx, chapter in enumerate(data.get("text", []), start=1):
|
| 97 |
+
for verse_idx, verse_text in enumerate(chapter, start=1):
|
| 98 |
+
yield (book_num, chap_idx, verse_idx, verse_text)
|
| 99 |
+
|
| 100 |
+
for book_num, chap_idx, verse_idx, verse_text in get_verses():
|
| 101 |
+
# Correctly handle the processing limit
|
| 102 |
+
if process_verses and verses_processed >= process_verses:
|
| 103 |
+
print(f"DEBUG: Processing limit of {process_verses} verses reached. Stopping analysis.")
|
| 104 |
+
break
|
| 105 |
+
verses_processed += 1
|
| 106 |
+
progress(verses_processed / process_verses, desc=f"Analyzing Verse {verses_processed}/{process_verses}")
|
| 107 |
+
|
| 108 |
+
verse_sum = calculate_gematria(verse_text)
|
| 109 |
+
if verse_sum <= 1: continue
|
| 110 |
+
|
| 111 |
+
power_result = get_power_result(verse_sum, query_value)
|
| 112 |
+
main_target_sum = verse_sum ^ power_result
|
| 113 |
+
main_matches = find_all_matching_phrases(main_target_sum, phrase_dictionary)
|
| 114 |
+
|
| 115 |
+
verse_ref = f"B{book_num:02d}, C{chap_idx}, V{verse_idx}"
|
| 116 |
+
print(f"DEBUG: Analyzing [{verse_ref}] | Verse Sum: {verse_sum}, Power/Root: {power_result}, Main Target: {main_target_sum}") # Console Debug
|
| 117 |
+
|
| 118 |
+
if not main_matches:
|
| 119 |
+
print("DEBUG: No main resonance found. Skipping.") # Console Debug
|
| 120 |
+
continue
|
| 121 |
+
|
| 122 |
+
resonance_count += 1
|
| 123 |
+
print(f"DEBUG: Found Resonance #{resonance_count}!") # Console Debug
|
| 124 |
+
|
| 125 |
+
output_lines.append("\n---\n")
|
| 126 |
+
output_lines.append(f"### Resonance #{resonance_count} in [{verse_ref}]")
|
| 127 |
+
output_lines.append(f"> {verse_text.strip()}\n")
|
| 128 |
+
|
| 129 |
+
output_lines.append("```")
|
| 130 |
+
output_lines.append(f"Verse Sum (X) : {verse_sum} | Query: \"{query}\" (G: {query_value}) | Power/Root (Y): {power_result}")
|
| 131 |
+
output_lines.append("```\n")
|
| 132 |
+
|
| 133 |
+
def format_matches(matches: List[Dict], title: str, calculation_str: str):
|
| 134 |
+
if not matches: return
|
| 135 |
+
|
| 136 |
+
matches.sort(key=lambda p: (p.get('freq', 0) / p.get('words', 99)), reverse=True)
|
| 137 |
+
matches_to_show = matches[:results_per_verse]
|
| 138 |
|
| 139 |
+
output_lines.append(f"**{title}:** `{calculation_str}`")
|
| 140 |
+
|
| 141 |
+
for match in matches_to_show:
|
| 142 |
+
translation_str = ""
|
| 143 |
+
if translator:
|
| 144 |
+
try:
|
| 145 |
+
translation_str = translator.translate(match['text'])
|
| 146 |
+
except Exception:
|
| 147 |
+
translation_str = "[Translation failed]"
|
| 148 |
+
|
| 149 |
+
score = (p.get('freq', 0) / p.get('words', 99)) if (p:=match).get('words') else 0
|
| 150 |
+
gematria_val = calculate_gematria(match['text'])
|
| 151 |
+
|
| 152 |
+
output_lines.append(f" * **{match['text']}**")
|
| 153 |
+
output_lines.append(f" `G: {gematria_val}, Words: {match.get('words', 'N/A')}, Freq: {match.get('freq', 'N/A')}, Score: {score:.2f}`")
|
| 154 |
+
if translation_str:
|
| 155 |
+
output_lines.append(f"\n*Translation: \"{translation_str}\"*")
|
| 156 |
+
output_lines.append("")
|
| 157 |
+
|
| 158 |
+
calc_str = f"[{verse_sum}] ^ [{power_result}] โ [G_target:{main_target_sum}]"
|
| 159 |
+
format_matches(main_matches, "Main Resonance", calc_str)
|
| 160 |
+
|
| 161 |
+
if xor_depth > 0:
|
| 162 |
+
output_lines.append(f"**Bitplane Variations of the Result ({main_target_sum}):**")
|
| 163 |
+
for depth in range(xor_depth):
|
| 164 |
+
bit_flip = 1 << depth
|
| 165 |
+
target_sum = main_target_sum ^ bit_flip
|
| 166 |
+
bitplane_matches = find_all_matching_phrases(target_sum, phrase_dictionary)
|
| 167 |
+
|
| 168 |
+
if bitplane_matches:
|
| 169 |
+
bitplane_calc_str = f"[{main_target_sum}] ^ [Bit {depth+1}] โ [G_target:{target_sum}]"
|
| 170 |
+
format_matches(bitplane_matches, f"Variation (Depth {depth + 1})", bitplane_calc_str)
|
| 171 |
+
|
| 172 |
+
if resonance_count == 0:
|
| 173 |
+
output_lines.append("\n**No resonances found. Consider increasing 'Verses to Process' or trying a different query.**")
|
| 174 |
+
|
| 175 |
+
print("--- ANALYSIS COMPLETE ---") # Console Debug
|
| 176 |
+
return "\n".join(output_lines)
|
| 177 |
+
|
| 178 |
+
# --- Gradio UI Definition ---
|
| 179 |
+
# Custom CSS for a professional dark theme inspired by the screenshot
|
| 180 |
+
custom_css = """
|
| 181 |
+
#output_markdown h3 {
|
| 182 |
+
color: #f97316; /* Vibrant orange for main resonance headers */
|
| 183 |
+
border-bottom: 2px solid #374151;
|
| 184 |
+
padding-bottom: 8px;
|
| 185 |
+
margin-top: 24px;
|
| 186 |
+
}
|
| 187 |
+
#output_markdown blockquote {
|
| 188 |
+
background-color: #1f2937;
|
| 189 |
+
border-left: 5px solid #f97316;
|
| 190 |
+
padding: 12px;
|
| 191 |
+
font-style: italic;
|
| 192 |
+
color: #d1d5db;
|
| 193 |
+
}
|
| 194 |
+
#output_markdown code {
|
| 195 |
+
background-color: #374151;
|
| 196 |
+
color: #e5e7eb;
|
| 197 |
+
padding: 3px 6px;
|
| 198 |
+
border-radius: 5px;
|
| 199 |
+
font-size: 0.9em;
|
| 200 |
+
}
|
| 201 |
+
"""
|
| 202 |
+
|
| 203 |
+
# Using the robust Default theme and customizing it for the desired dark look
|
| 204 |
+
dark_theme = gr.themes.Default(
|
| 205 |
+
primary_hue=gr.themes.colors.orange,
|
| 206 |
+
secondary_hue=gr.themes.colors.blue,
|
| 207 |
+
neutral_hue=gr.themes.colors.slate
|
| 208 |
+
).set(
|
| 209 |
+
body_background_fill="#0f172a",
|
| 210 |
+
background_fill_primary="#1e293b",
|
| 211 |
+
background_fill_secondary="#334155",
|
| 212 |
+
body_text_color="#e2e8f0",
|
| 213 |
+
color_accent_soft="#1e293b",
|
| 214 |
+
border_color_accent="#334155",
|
| 215 |
+
border_color_primary="#334155",
|
| 216 |
+
button_primary_background_fill="#f97316",
|
| 217 |
+
button_primary_text_color="#ffffff",
|
| 218 |
+
button_secondary_background_fill="#334155",
|
| 219 |
+
button_secondary_text_color="#e2e8f0",
|
| 220 |
+
)
|
| 221 |
+
|
| 222 |
+
with gr.Blocks(theme=dark_theme, css=custom_css, title="Tanakh XOR Gematria Resonance") as demo:
|
| 223 |
+
gr.Markdown("# ๐ Tanakh XOR Gematria Resonance")
|
| 224 |
+
|
| 225 |
+
with gr.Tabs():
|
| 226 |
+
with gr.TabItem("XOR Gematria Resonance"):
|
| 227 |
+
with gr.Row():
|
| 228 |
+
with gr.Column(scale=1):
|
| 229 |
+
query = gr.Textbox(
|
| 230 |
+
label="Query Phrase",
|
| 231 |
+
placeholder="e.g., ืืืื, ืืืืื, light...",
|
| 232 |
+
)
|
| 233 |
+
run_button = gr.Button("๐ฎ Divine Resonance", variant="primary")
|
| 234 |
+
|
| 235 |
+
with gr.Accordion("Advanced Parameters", open=False):
|
| 236 |
+
process_verses = gr.Slider(
|
| 237 |
+
label="Verses to Process", minimum=1, maximum=35000, step=1, value=10,
|
| 238 |
+
info="How many verses to analyze from the start of the Tanakh."
|
| 239 |
+
)
|
| 240 |
+
results_per_verse = gr.Slider(
|
| 241 |
+
label="Results per Resonance", minimum=1, maximum=10, step=1, value=1,
|
| 242 |
+
info="How many top phrases to show for each found resonance type."
|
| 243 |
+
)
|
| 244 |
+
xor_depth = gr.Slider(
|
| 245 |
+
label="Bitplane Variation Depth", minimum=0, maximum=16, step=1, value=2,
|
| 246 |
+
info="How many bit-levels of the main result to vary and analyze."
|
| 247 |
+
)
|
| 248 |
+
translate = gr.Checkbox(label="Translate to English", value=True)
|
| 249 |
+
|
| 250 |
+
gr.Examples(
|
| 251 |
+
examples=[
|
| 252 |
+
["ืืืื"], ["ืืืืื"], ["ืฉืืื ื"],
|
| 253 |
+
["ืืฉืื ืืฉืืขืื"], ["ืืื ืฉืืืฉืื ืืฉืืข"], ["ืฆืืง ืืืฉืคื"]
|
| 254 |
+
],
|
| 255 |
+
inputs=[query]
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
with gr.Column(scale=3):
|
| 259 |
+
output_markdown = gr.Markdown(label="Resonances", elem_id="output_markdown")
|
| 260 |
+
|
| 261 |
+
with gr.TabItem("About & Help"):
|
| 262 |
+
gr.Markdown(
|
| 263 |
+
"""
|
| 264 |
+
### How It Works
|
| 265 |
+
This tool explores the numerological and structural connections within the Tanakh based on Gematria and bitwise XOR operations. It is an instrument for textual exploration, not a historical or theological authority.
|
| 266 |
+
|
| 267 |
+
1. **Gematria Calculation:** The Gematria (numerical value) of your **Query Phrase** and each **Verse** in the Tanakh is calculated.
|
| 268 |
+
2. **Power/Root Operator (Y):** To create a non-obvious link, the Query's Gematria is transformed. If it's smaller than the Verse's Gematria, its highest possible power is taken. If larger, its n-th root is taken. This becomes the "Operator" (Y).
|
| 269 |
+
3. **Main Resonance:** The core operation is `Verse_Gematria (X) ^ Operator (Y)`. The result is a **Target Gematria**. The app then finds all phrases in the Tanakh with this exact numerical value. This is the "Main Resonance".
|
| 270 |
+
4. **Bitplane Variations:** To explore the "fractal neighborhood" of the Main Resonance, the app then "flips" each bit of the result, one by one. For each flipped bit (`depth`), it calculates a new Target Gematria (`Main_Result ^ 2^depth`) and finds corresponding phrases. This reveals concepts that are numerologically "close" to the main result.
|
| 271 |
+
5. **Scoring:** Results are sorted by a relevance score calculated as `Frequency / Word_Count` to prioritize short, common phrases.
|
| 272 |
+
|
| 273 |
+
### Parameters
|
| 274 |
+
- **Verses to Process:** Limits how many verses the script analyzes. Higher numbers take longer.
|
| 275 |
+
- **Results per Resonance:** Limits how many phrases are shown for the main resonance and each variation.
|
| 276 |
+
- **Bitplane Variation Depth:** Controls how many "bit-flips" are tested. A depth of 5 will test flipping Bit 1, Bit 2, Bit 3, Bit 4, and Bit 5.
|
| 277 |
+
"""
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
run_button.click(
|
| 281 |
+
fn=run_analysis,
|
| 282 |
+
inputs=[query, translate, process_verses, results_per_verse, xor_depth],
|
| 283 |
+
outputs=[output_markdown]
|
| 284 |
+
)
|
| 285 |
|
|
|
|
| 286 |
if __name__ == "__main__":
|
| 287 |
+
if phrase_dictionary is None:
|
| 288 |
+
print("CRITICAL: Phrase dictionary could not be loaded. The application cannot start.")
|
| 289 |
+
print("Please ensure 'tanakh_phrasedict.cache' exists and is valid. Run 'build_indices.py' if necessary.")
|
| 290 |
+
else:
|
| 291 |
+
# The share=True argument creates a public link for easy sharing. Remove it if you only want local access.
|
| 292 |
+
demo.launch()
|