neuralworm's picture
fix: Convert embedded repo to regular directory
e8510d3
Raw
History Blame
9.64 kB
import json
import os
import logging
import sqlite3
import re
from typing import Dict, List, Any
from gematria import calculate_gematria, strip_diacritics
from deep_translator import GoogleTranslator
logger = logging.getLogger(__name__)
def process_bible_files(start: int, end: int) -> Dict[int, Dict[str, Any]]:
"""
Processes Bible JSON files and returns a dictionary mapping book IDs to their data.
Args:
start: The starting book ID (inclusive).
end: The ending book ID (inclusive).
Returns:
A dictionary where keys are book IDs and values are dictionaries
containing 'title' and 'text' fields.
"""
base_path = "texts/bible"
results = {}
for i in range(start, end + 1):
file_name = f"{base_path}/{i}.json"
try:
with open(file_name, 'r', encoding='utf-8') as file:
data = json.load(file)
if data:
# Extract title and verses
title = data.get("title", "No title")
text = data.get("text", [])
# Store book ID as key and book data as value
results[i] = {"title": title, "text": text}
except FileNotFoundError:
logger.warning(f"File {file_name} not found.")
except json.JSONDecodeError as e:
logger.warning(f"File {file_name} could not be read as JSON: {e}")
except Exception as e:
logger.warning(f"Error processing {file_name}: {e}")
return results
def process_json_files(start, end, step, rounds="1", length=0, tlang="en", strip_spaces=True, strip_in_braces=True,
strip_diacritics_value=True, translate=False):
"""
Processes Bible JSON files and performs ELS (Equidistant Letter Sequence) search.
Parameters:
- start (int): Start number of the Bible book.
- end (int): End number of the Bible book.
- step (int): Step size for character selection.
- rounds (str): Comma-separated list of round numbers (can include negative values).
- length (int): Maximum length of the result text.
- tlang (str): Target language for translation.
- strip_spaces (bool): Whether to remove spaces from the text.
- strip_in_braces (bool): Whether to remove text within braces.
- strip_diacritics_value (bool): Whether to remove diacritics from the text.
- translate (bool): Whether to translate the result text.
Returns:
- list: A list of dictionaries containing processed data or error messages.
"""
logger.debug(f"Processing Bible files {start}-{end} with step {step}, rounds {rounds}")
results = []
try:
bible_data = process_bible_files(start, end)
if not bible_data:
return [{"error": f"No Bible data found for books {start}-{end}"}]
rounds_list = [int(r.strip()) for r in rounds.split(",")]
for book_id, book_info in bible_data.items():
book_title = book_info.get("title", "Unknown")
chapters = book_info.get("text", [])
if not chapters:
results.append({"error": f"No text found for book {book_title} (ID: {book_id})"})
continue
# Flatten the text
flattened_text = ""
for chapter_idx, chapter in enumerate(chapters, 1):
for verse_idx, verse in enumerate(chapter, 1):
if verse:
flattened_text += verse + " "
# Clean the text based on parameters
processed_text = flattened_text.lower()
if strip_in_braces:
# Remove content within brackets or parentheses
processed_text = re.sub(r'\[.*?\]|\(.*?\)', '', processed_text)
if strip_spaces:
# Remove spaces and other whitespace
processed_text = re.sub(r'\s+', '', processed_text)
if strip_diacritics_value:
# Remove diacritics from letters
processed_text = strip_diacritics(processed_text)
# To match daily_psalm, process round 1 first, then other rounds
sorted_rounds = sorted(rounds_list, key=lambda r: 0 if r == 1 else abs(r))
# Perform ELS search for each round
for round_num in sorted_rounds:
if round_num == 0:
continue
direction = 1 if round_num > 0 else -1
abs_round = abs(round_num)
# Calculate step size
actual_step = step * abs_round
# Apply ELS algorithm
els_result = None
# Determine start index based on direction
start_idx = 0 if direction > 0 else len(processed_text) - 1
# Loop through possible starting positions
for i in range(abs_round):
# Skip if starting position is out of bounds
if start_idx + i >= len(processed_text) or start_idx - i < 0:
continue
# Get starting position for this round
pos = start_idx + i if direction > 0 else start_idx - i
# Extract letters at intervals
result_text = ""
while 0 <= pos < len(processed_text) and (length == 0 or len(result_text) < length):
result_text += processed_text[pos]
pos += actual_step * direction
# Only record non-empty results
if result_text:
# Prepare result object
result = {
"result_text": result_text,
"step": actual_step * direction,
"start_pos": i,
"book_id": book_id,
"book_title": book_title,
"round": round_num,
"gematria": calculate_gematria(result_text)
}
# Translate result if requested
if translate and result_text and tlang != "en":
try:
translator = GoogleTranslator(source='en', target=tlang)
result["translated_text"] = translator.translate(result_text)
except Exception as e:
logger.warning(f"Translation error: {e}")
result["translated_text"] = result_text
# Add result to results list
results.append(result)
# For efficiency, once we find a valid result for this round, break the loop
# This ensures we get one result per round but don't waste time on additional calculations
break
except Exception as e:
logger.error(f"Error processing Bible files: {e}", exc_info=True)
results.append({"error": f"Error processing Bible files: {str(e)}"})
return results
def create_bible_display_iframe(book_title, book_id, chapter=None, verse=None):
"""
Creates an iframe HTML string for BibleGateway.
Args:
book_title (str): The title of the book.
book_id (int): The ID of the book.
chapter (int, optional): The chapter number.
verse (int, optional): The verse number.
Returns:
str: An iframe HTML string for displaying the specified Bible passage.
"""
from urllib.parse import quote_plus
# Format the passage reference
if chapter and verse:
reference = f"{book_title}+{chapter}:{verse}"
elif chapter:
reference = f"{book_title}+{chapter}"
else:
reference = book_title
encoded_reference = quote_plus(reference)
url = f"https://www.biblegateway.com/passage/?search={encoded_reference}&version=CJB"
iframe = f'<iframe src="{url}" width="800" height="600"></iframe>'
return iframe
def find_bible_verse_by_gematria(gematria_sum, db_file="bible.db"):
"""
Finds a Bible verse with a matching gematria sum.
Args:
gematria_sum (int): The gematria sum to match.
db_file (str): Path to the database file.
Returns:
dict or None: Dictionary with verse details or None if no match found.
"""
try:
with sqlite3.connect(db_file) as conn:
cursor = conn.cursor()
cursor.execute('''
SELECT book, chapter, verse, words
FROM verses
WHERE gematria_sum = ?
ORDER BY LENGTH(words) ASC
LIMIT 1
''', (gematria_sum,))
result = cursor.fetchone()
if result:
book, chapter, verse, words = result
return {
"book": book,
"chapter": chapter,
"verse": verse,
"words": words
}
return None
except sqlite3.Error as e:
logger.error(f"Database error: {e}")
return None