robot/modules/get_bible.py

167 lines
5.6 KiB
Python

# import the Telegram API token from config.py
from config import (
TRANSLATION,
DEFAULT_VERSE,
GETBIBLE_URL
)
# import the GetBible librarian
from getbible import GetBible
import re
import logging
# start getBible
_getBible = GetBible()
def _get_translation(input_string):
"""
Extracts the translation from the input string.
:param input_string: The string from which to extract the translation.
:return: 'kjv' if the last word contains numbers, indicating it's not a translation,
otherwise returns the possible translation.
"""
try:
# Extract the last word which might be the translation or a part of the reference
possible_translation = input_string.split()[-1]
except IndexError:
logging.info(f"No translation found, used default: {TRANSLATION}")
return TRANSLATION
# Check if the possible translation is valid
if _getBible.valid_translation(possible_translation):
return possible_translation
else:
logging.info(f"No valid translation found, used default: {TRANSLATION}")
return TRANSLATION
def _get_references(input_string, translation):
"""
Extracts and validates references from the input string, excluding the translation at the end if it's not 'kjv'.
If the input string is empty, returns a default verse.
:param input_string: The string containing references.
:param translation: The translation to be excluded if present.
:return: The validated references string, or raises ValueError if any reference is invalid.
"""
# Check if input_string is empty or consists only of whitespace
if not input_string.strip():
logging.info(f"No reference found, used default: {DEFAULT_VERSE}")
return DEFAULT_VERSE
# Remove translation from the end if it's not 'kjv'
references_string = re.sub(f' {translation}$', '', input_string) if translation != "kjv" else input_string
# Split references_string by ';' and validate each reference
references = references_string.split(';')
for reference in references:
if not _getBible.valid_reference(reference.strip(), translation):
raise ValueError("Invalid reference found:", reference)
return references_string
def _get_verse_reference(verses):
"""
Generates a reference string for the verses.
:param verses: A list of verse dictionaries.
:return: A string representing the verse reference range.
"""
verse_numbers = sorted([verse['verse'] for verse in verses])
ranges = []
range_start = None
range_end = None
for verse in verse_numbers:
if range_start is None:
range_start = verse
elif verse == range_end + 1:
range_end = verse
else:
if range_end:
ranges.append(f"{range_start}-{range_end}")
else:
ranges.append(str(range_start))
range_start = verse
range_end = None
if range_end is None:
range_end = verse
# Handling the case for the last verse or a single-verse range
if range_start is not None:
if range_start != range_end:
ranges.append(f"{range_start}-{range_end}")
else:
ranges.append(str(range_start))
return ','.join(ranges)
def _format_verses(result):
"""
Formats the result from GetBible.select into nicely formatted paragraphs,
including the translation name and verse reference range in the header.
:param result: The dictionary result from GetBible.select
:return: A string with the verses formatted as paragraphs.
"""
formatted_paragraphs = []
for key, value in result.items():
book_name = value.get('book_name', '')
chapter = value.get('chapter', '')
abbreviation = value.get('abbreviation', '')
verses = value.get('verses', [])
# Generate verse reference range
verse_ref = _get_verse_reference(verses)
header = (f"[{book_name} {chapter}:{verse_ref}]({GETBIBLE_URL}{abbreviation}"
f"/{book_name}/{chapter}/{verse_ref}) ({abbreviation})")
formatted_paragraphs.append(header)
for verse in verses:
verse_text = verse.get('text', '').strip()
verse_number = verse.get('verse', '')
verse_line = f"{verse_number}. {verse_text}"
formatted_paragraphs.append(verse_line)
formatted_paragraphs.append("")
return "\n".join(formatted_paragraphs)
def _remove_prefix_case_insensitive(input_string, prefixes):
# Join the prefixes into a regex pattern, making it case-insensitive
# The ^ character ensures the match is at the start of the string
regex_pattern = r'^(?:' + '|'.join(re.escape(prefix) for prefix in prefixes) + ')'
# Use re.sub() to replace the matched prefix with '', case-insensitively
cleaned_string = re.sub(regex_pattern, '', input_string, flags=re.IGNORECASE).strip()
return cleaned_string
def _clean_string(input_string):
# Define the prefixes you want to remove
prefixes = ['/getBible', 'getBible', '/bible', 'Bible', '/get', 'Get']
# Remove whitespace from both ends
cleaned_string = _remove_prefix_case_insensitive(input_string, prefixes)
return cleaned_string
def bible(text):
try:
text = _clean_string(text)
translation = _get_translation(text)
references = _get_references(text, translation)
result = _getBible.select(references, translation)
scripture = _format_verses(result)
except Exception as e:
logging.error(str(e))
scripture = str(e)
return scripture