diff --git a/kjvstudy_org/data/bible_metadata.json b/kjvstudy_org/data/bible_metadata.json new file mode 100644 index 0000000..53e2283 --- /dev/null +++ b/kjvstudy_org/data/bible_metadata.json @@ -0,0 +1,259 @@ +{ + "old_testament_books": [ + "Genesis", + "Exodus", + "Leviticus", + "Numbers", + "Deuteronomy", + "Joshua", + "Judges", + "Ruth", + "1 Samuel", + "2 Samuel", + "1 Kings", + "2 Kings", + "1 Chronicles", + "2 Chronicles", + "Ezra", + "Nehemiah", + "Esther", + "Job", + "Psalms", + "Proverbs", + "Ecclesiastes", + "Solomon's Song", + "Isaiah", + "Jeremiah", + "Lamentations", + "Ezekiel", + "Daniel", + "Hosea", + "Joel", + "Amos", + "Obadiah", + "Jonah", + "Micah", + "Nahum", + "Habakkuk", + "Zephaniah", + "Haggai", + "Zechariah", + "Malachi" + ], + "new_testament_books": [ + "Matthew", + "Mark", + "Luke", + "John", + "Acts", + "Romans", + "1 Corinthians", + "2 Corinthians", + "Galatians", + "Ephesians", + "Philippians", + "Colossians", + "1 Thessalonians", + "2 Thessalonians", + "1 Timothy", + "2 Timothy", + "Titus", + "Philemon", + "Hebrews", + "James", + "1 Peter", + "2 Peter", + "1 John", + "2 John", + "3 John", + "Jude", + "Revelation" + ], + "book_abbreviations": { + "Psalm": "Psalms", + "I Samuel": "1 Samuel", + "II Samuel": "2 Samuel", + "I Kings": "1 Kings", + "II Kings": "2 Kings", + "I Chronicles": "1 Chronicles", + "II Chronicles": "2 Chronicles", + "I Corinthians": "1 Corinthians", + "II Corinthians": "2 Corinthians", + "I Thessalonians": "1 Thessalonians", + "II Thessalonians": "2 Thessalonians", + "I Timothy": "1 Timothy", + "II Timothy": "2 Timothy", + "I Peter": "1 Peter", + "II Peter": "2 Peter", + "I John": "1 John", + "II John": "2 John", + "III John": "3 John", + "First Samuel": "1 Samuel", + "Second Samuel": "2 Samuel", + "First Kings": "1 Kings", + "Second Kings": "2 Kings", + "First Chronicles": "1 Chronicles", + "Second Chronicles": "2 Chronicles", + "First Corinthians": "1 Corinthians", + "Second Corinthians": "2 Corinthians", + "First Thessalonians": "1 Thessalonians", + "Second Thessalonians": "2 Thessalonians", + "First Timothy": "1 Timothy", + "Second Timothy": "2 Timothy", + "First Peter": "1 Peter", + "Second Peter": "2 Peter", + "First John": "1 John", + "Second John": "2 John", + "Third John": "3 John", + "Song of Solomon": "Solomon's Song", + "Song of Songs": "Solomon's Song", + "Canticles": "Solomon's Song", + "Gen": "Genesis", + "Ge": "Genesis", + "Exo": "Exodus", + "Ex": "Exodus", + "Lev": "Leviticus", + "Le": "Leviticus", + "Num": "Numbers", + "Nu": "Numbers", + "Deut": "Deuteronomy", + "Dt": "Deuteronomy", + "Josh": "Joshua", + "Jos": "Joshua", + "Judg": "Judges", + "Jdg": "Judges", + "Ru": "Ruth", + "1Sam": "1 Samuel", + "1 Sam": "1 Samuel", + "1S": "1 Samuel", + "2Sam": "2 Samuel", + "2 Sam": "2 Samuel", + "2S": "2 Samuel", + "1Ki": "1 Kings", + "1 Ki": "1 Kings", + "1K": "1 Kings", + "2Ki": "2 Kings", + "2 Ki": "2 Kings", + "2K": "2 Kings", + "1Chr": "1 Chronicles", + "1 Chr": "1 Chronicles", + "1Ch": "1 Chronicles", + "2Chr": "2 Chronicles", + "2 Chr": "2 Chronicles", + "2Ch": "2 Chronicles", + "Ezr": "Ezra", + "Neh": "Nehemiah", + "Ne": "Nehemiah", + "Est": "Esther", + "Ps": "Psalms", + "Psa": "Psalms", + "Prov": "Proverbs", + "Pr": "Proverbs", + "Eccl": "Ecclesiastes", + "Ec": "Ecclesiastes", + "Song": "Song of Solomon", + "Sos": "Song of Solomon", + "SS": "Song of Solomon", + "Isa": "Isaiah", + "Is": "Isaiah", + "Jer": "Jeremiah", + "Je": "Jeremiah", + "Lam": "Lamentations", + "La": "Lamentations", + "Ezek": "Ezekiel", + "Eze": "Ezekiel", + "Ezk": "Ezekiel", + "Dan": "Daniel", + "Da": "Daniel", + "Hos": "Hosea", + "Ho": "Hosea", + "Joe": "Joel", + "Jl": "Joel", + "Am": "Amos", + "Ob": "Obadiah", + "Jon": "Jonah", + "Mic": "Micah", + "Mi": "Micah", + "Nah": "Nahum", + "Na": "Nahum", + "Hab": "Habakkuk", + "Hb": "Habakkuk", + "Zep": "Zephaniah", + "Zph": "Zephaniah", + "Hag": "Haggai", + "Hg": "Haggai", + "Zech": "Zechariah", + "Zec": "Zechariah", + "Zch": "Zechariah", + "Mal": "Malachi", + "Mat": "Matthew", + "Mt": "Matthew", + "Mar": "Mark", + "Mk": "Mark", + "Mrk": "Mark", + "Luk": "Luke", + "Lk": "Luke", + "Joh": "John", + "Jn": "John", + "Act": "Acts", + "Ac": "Acts", + "Rom": "Romans", + "Ro": "Romans", + "1Cor": "1 Corinthians", + "1 Cor": "1 Corinthians", + "1Co": "1 Corinthians", + "2Cor": "2 Corinthians", + "2 Cor": "2 Corinthians", + "2Co": "2 Corinthians", + "Gal": "Galatians", + "Ga": "Galatians", + "Eph": "Ephesians", + "Ep": "Ephesians", + "Phil": "Philippians", + "Php": "Philippians", + "Ph": "Philippians", + "Col": "Colossians", + "Co": "Colossians", + "1Thess": "1 Thessalonians", + "1 Thess": "1 Thessalonians", + "1Th": "1 Thessalonians", + "2Thess": "2 Thessalonians", + "2 Thess": "2 Thessalonians", + "2Th": "2 Thessalonians", + "1Tim": "1 Timothy", + "1 Tim": "1 Timothy", + "1Ti": "1 Timothy", + "2Tim": "2 Timothy", + "2 Tim": "2 Timothy", + "2Ti": "2 Timothy", + "Tit": "Titus", + "Ti": "Titus", + "Phm": "Philemon", + "Pm": "Philemon", + "Heb": "Hebrews", + "He": "Hebrews", + "Jam": "James", + "Jas": "James", + "Jm": "James", + "1Pet": "1 Peter", + "1 Pet": "1 Peter", + "1Pe": "1 Peter", + "1P": "1 Peter", + "2Pet": "2 Peter", + "2 Pet": "2 Peter", + "2Pe": "2 Peter", + "2P": "2 Peter", + "1Joh": "1 John", + "1 Joh": "1 John", + "1Jn": "1 John", + "2Joh": "2 John", + "2 Joh": "2 John", + "2Jn": "2 John", + "3Joh": "3 John", + "3 Joh": "3 John", + "3Jn": "3 John", + "Jud": "Jude", + "Rev": "Revelation", + "Re": "Revelation" + } +} diff --git a/kjvstudy_org/data/chapter_explanations.json b/kjvstudy_org/data/chapter_explanations.json new file mode 100644 index 0000000..c0fcaef --- /dev/null +++ b/kjvstudy_org/data/chapter_explanations.json @@ -0,0 +1,34 @@ +{ + "John": { + "3": "Contains John 3:16 - 'For God so loved the world' - the most quoted verse in Christianity", + "1": "The Word became flesh - Jesus as the eternal Logos and the calling of the first disciples" + }, + "1 Corinthians": { + "13": "The famous 'Love Chapter' - 'Love is patient, love is kind' - essential reading for weddings and Christian living" + }, + "Psalms": { + "23": "The beloved Shepherd Psalm - 'The Lord is my shepherd, I shall not want' - comfort in times of trouble", + "91": "Psalm of protection - 'He who dwells in the shelter of the Most High' - promises of God's care", + "1": "The blessed man - contrasts the righteous and wicked, foundation of wisdom literature", + "139": "God's omniscience and omnipresence - 'You have searched me and known me' - intimate knowledge of God" + }, + "Romans": { + "8": "No condemnation in Christ - 'All things work together for good' - assurance of salvation", + "3": "All have sinned - universal need for salvation and justification by faith", + "12": "Living sacrifice - practical Christian living and spiritual gifts" + }, + "Matthew": { + "5": "The Beatitudes - 'Blessed are the poor in spirit' - foundation of Christian ethics", + "6": "The Lord's Prayer and teachings on worry - 'Give us this day our daily bread'", + "7": "Golden Rule and narrow gate - 'Do unto others as you would have them do unto you'" + }, + "Genesis": { + "1": "Creation account - 'In the beginning God created the heavens and the earth'", + "3": "The Fall - Adam and Eve's disobedience and the first promise of redemption", + "22": "Abraham's ultimate test - the near-sacrifice of Isaac, foreshadowing Christ" + }, + "Isaiah": { + "53": "The Suffering Servant - 'He was wounded for our transgressions' - prophecy of Christ's crucifixion", + "40": "Comfort my people - 'Every valley shall be exalted' - hope and restoration" + } +} diff --git a/kjvstudy_org/data/featured_verses.json b/kjvstudy_org/data/featured_verses.json new file mode 100644 index 0000000..e7b0404 --- /dev/null +++ b/kjvstudy_org/data/featured_verses.json @@ -0,0 +1,35 @@ +{ + "verses": [ + {"book": "John", "chapter": 3, "verse": 16}, + {"book": "Psalms", "chapter": 23, "verse": 1}, + {"book": "Proverbs", "chapter": 3, "verse": 5}, + {"book": "Philippians", "chapter": 4, "verse": 13}, + {"book": "Romans", "chapter": 8, "verse": 28}, + {"book": "Isaiah", "chapter": 40, "verse": 31}, + {"book": "Jeremiah", "chapter": 29, "verse": 11}, + {"book": "Joshua", "chapter": 1, "verse": 9}, + {"book": "Matthew", "chapter": 11, "verse": 28}, + {"book": "Psalms", "chapter": 46, "verse": 10}, + {"book": "Romans", "chapter": 12, "verse": 2}, + {"book": "2 Timothy", "chapter": 1, "verse": 7}, + {"book": "Proverbs", "chapter": 22, "verse": 6}, + {"book": "1 Corinthians", "chapter": 13, "verse": 4}, + {"book": "Galatians", "chapter": 5, "verse": 22}, + {"book": "Hebrews", "chapter": 11, "verse": 1}, + {"book": "James", "chapter": 1, "verse": 2}, + {"book": "1 Peter", "chapter": 5, "verse": 7}, + {"book": "Psalms", "chapter": 119, "verse": 105}, + {"book": "Matthew", "chapter": 6, "verse": 33}, + {"book": "John", "chapter": 14, "verse": 6}, + {"book": "Romans", "chapter": 5, "verse": 8}, + {"book": "Ephesians", "chapter": 2, "verse": 8}, + {"book": "Psalms", "chapter": 27, "verse": 1}, + {"book": "Isaiah", "chapter": 41, "verse": 10}, + {"book": "Matthew", "chapter": 28, "verse": 19}, + {"book": "John", "chapter": 1, "verse": 1}, + {"book": "Psalms", "chapter": 51, "verse": 10}, + {"book": "Proverbs", "chapter": 18, "verse": 10}, + {"book": "2 Corinthians", "chapter": 5, "verse": 17}, + {"book": "Colossians", "chapter": 3, "verse": 23} + ] +} diff --git a/kjvstudy_org/data/popular_chapters.json b/kjvstudy_org/data/popular_chapters.json new file mode 100644 index 0000000..1197e5d --- /dev/null +++ b/kjvstudy_org/data/popular_chapters.json @@ -0,0 +1,145 @@ +{ + "popular_chapters": { + "John": { + "3": 10 + }, + "1 Corinthians": { + "13": 10 + }, + "Psalms": { + "23": 10, + "91": 9, + "1": 8, + "139": 8 + }, + "Romans": { + "8": 9, + "3": 8, + "12": 8 + }, + "Matthew": { + "5": 9, + "6": 8, + "7": 8 + }, + "Ephesians": { + "2": 8, + "6": 8 + }, + "Philippians": { + "4": 8 + }, + "Genesis": { + "1": 9, + "3": 8, + "22": 7 + }, + "Exodus": { + "20": 8, + "14": 7 + }, + "Isaiah": { + "53": 9, + "40": 8 + }, + "Jeremiah": { + "29": 7 + }, + "Proverbs": { + "31": 7, + "3": 7 + }, + "Ecclesiastes": { + "3": 8 + }, + "1 Peter": { + "5": 7 + }, + "James": { + "1": 7 + }, + "Hebrews": { + "11": 8, + "12": 7 + }, + "Revelation": { + "21": 8, + "22": 7 + }, + "Luke": { + "2": 9, + "15": 8 + }, + "2 Timothy": { + "3": 7 + }, + "Joshua": { + "1": 7 + }, + "Daniel": { + "3": 7, + "6": 7 + }, + "1 John": { + "4": 8 + }, + "Galatians": { + "5": 7 + }, + "Colossians": { + "3": 7 + }, + "1 Thessalonians": { + "4": 7 + }, + "Mark": { + "16": 7 + }, + "Acts": { + "2": 8 + }, + "1 Samuel": { + "17": 7 + }, + "Job": { + "19": 7 + }, + "2 Corinthians": { + "5": 7 + }, + "1 Kings": { + "3": 6, + "18": 6 + }, + "Malachi": { + "3": 6 + }, + "Joel": { + "2": 6 + }, + "Micah": { + "6": 6 + }, + "Habakkuk": { + "2": 6 + } + }, + "high_readership_books": [ + "Matthew", + "Mark", + "Luke", + "John", + "Acts", + "Romans", + "1 Corinthians", + "2 Corinthians", + "Galatians", + "Ephesians", + "Philippians", + "Colossians", + "Genesis", + "Exodus", + "Psalms", + "Proverbs" + ] +} diff --git a/kjvstudy_org/data/resource_slugs.json b/kjvstudy_org/data/resource_slugs.json new file mode 100644 index 0000000..ee22824 --- /dev/null +++ b/kjvstudy_org/data/resource_slugs.json @@ -0,0 +1,113 @@ +{ + "study_guides": [ + "sermon-on-the-mount", + "lords-prayer", + "beatitudes", + "fruit-of-spirit", + "armor-of-god", + "ten-commandments", + "parables-of-jesus", + "miracles-of-jesus", + "names-of-god", + "attributes-of-god", + "trinity", + "holy-spirit", + "salvation", + "justification", + "sanctification", + "redemption" + ], + "angels": [ + "michael", + "gabriel", + "lucifer", + "abaddon" + ], + "prophets": [ + "moses", + "elijah", + "isaiah", + "jeremiah", + "ezekiel", + "daniel", + "jonah", + "john-the-baptist" + ], + "names_of_god": [ + "elohim", + "yahweh", + "adonai", + "el-shaddai", + "yahweh-jireh", + "yahweh-rapha", + "yahweh-nissi", + "yahweh-shalom", + "yahweh-tsidkenu", + "yahweh-shammah" + ], + "parables": [ + "sower", + "wheat-tares", + "mustard-seed", + "good-samaritan", + "prodigal-son", + "lost-sheep", + "talents", + "wise-foolish-builders" + ], + "covenants": [ + "noahic", + "abrahamic", + "mosaic", + "davidic", + "new-covenant" + ], + "apostles": [ + "peter", + "andrew", + "james-son-of-zebedee", + "john", + "philip", + "bartholomew", + "thomas", + "matthew", + "james-son-of-alphaeus", + "thaddaeus", + "simon-zealot", + "judas-iscariot" + ], + "women": [ + "eve", + "sarah", + "rebekah", + "rachel", + "miriam", + "deborah", + "ruth", + "hannah", + "esther", + "mary-mother-of-jesus", + "mary-magdalene", + "martha" + ], + "festivals": [ + "passover", + "unleavened-bread", + "firstfruits", + "pentecost", + "trumpets", + "atonement", + "tabernacles" + ], + "fruits_of_spirit": [ + "love", + "joy", + "peace", + "longsuffering", + "gentleness", + "goodness", + "faith", + "meekness", + "temperance" + ] +} diff --git a/kjvstudy_org/routes/utility.py b/kjvstudy_org/routes/utility.py index d0730c0..c2ecfc8 100644 --- a/kjvstudy_org/routes/utility.py +++ b/kjvstudy_org/routes/utility.py @@ -1,5 +1,8 @@ """Utility routes for KJV Study - sitemap, robots.txt, health checks.""" +import json from datetime import datetime +from pathlib import Path +from functools import lru_cache from fastapi import APIRouter from fastapi.responses import Response @@ -13,13 +16,20 @@ router = APIRouter(tags=["Utility"]) _sitemap_cache = None _sitemap_cache_date = None -# Study guide slugs for sitemap (extracted from study_guides module) -STUDY_GUIDE_SLUGS = [ - "sermon-on-the-mount", "lords-prayer", "beatitudes", "fruit-of-spirit", - "armor-of-god", "ten-commandments", "parables-of-jesus", "miracles-of-jesus", - "names-of-god", "attributes-of-god", "trinity", "holy-spirit", - "salvation", "justification", "sanctification", "redemption", -] +# Path to resource slugs JSON file +_RESOURCE_SLUGS_PATH = Path(__file__).parent.parent / "data" / "resource_slugs.json" + + +@lru_cache(maxsize=1) +def _load_resource_slugs() -> dict: + """Load resource slugs from JSON file. Cached since data never changes.""" + with open(_RESOURCE_SLUGS_PATH, "r", encoding="utf-8") as f: + return json.load(f) + + +# Load slugs from JSON +_slugs = _load_resource_slugs() +STUDY_GUIDE_SLUGS = _slugs["study_guides"] @router.get("/health") @@ -236,8 +246,7 @@ def sitemap(): """ # Biblical angels, prophets, names of God, parables, covenants, apostles, women, festivals slugs - angel_slugs = ["michael", "gabriel", "lucifer", "abaddon"] - for slug in angel_slugs: + for slug in _slugs["angels"]: sitemap_xml += f""" {base_url}/biblical-angels/{slug} {current_date} @@ -246,8 +255,7 @@ def sitemap(): """ - prophet_slugs = ["moses", "elijah", "isaiah", "jeremiah", "ezekiel", "daniel", "jonah", "john-the-baptist"] - for slug in prophet_slugs: + for slug in _slugs["prophets"]: sitemap_xml += f""" {base_url}/biblical-prophets/{slug} {current_date} @@ -256,8 +264,7 @@ def sitemap(): """ - god_name_slugs = ["elohim", "yahweh", "adonai", "el-shaddai", "yahweh-jireh", "yahweh-rapha", "yahweh-nissi", "yahweh-shalom", "yahweh-tsidkenu", "yahweh-shammah"] - for slug in god_name_slugs: + for slug in _slugs["names_of_god"]: sitemap_xml += f""" {base_url}/names-of-god/{slug} {current_date} @@ -266,8 +273,7 @@ def sitemap(): """ - parable_slugs = ["sower", "wheat-tares", "mustard-seed", "good-samaritan", "prodigal-son", "lost-sheep", "talents", "wise-foolish-builders"] - for slug in parable_slugs: + for slug in _slugs["parables"]: sitemap_xml += f""" {base_url}/parables/{slug} {current_date} @@ -276,8 +282,7 @@ def sitemap(): """ - covenant_slugs = ["noahic", "abrahamic", "mosaic", "davidic", "new-covenant"] - for slug in covenant_slugs: + for slug in _slugs["covenants"]: sitemap_xml += f""" {base_url}/biblical-covenants/{slug} {current_date} @@ -286,8 +291,7 @@ def sitemap(): """ - apostle_slugs = ["peter", "andrew", "james-son-of-zebedee", "john", "philip", "bartholomew", "thomas", "matthew", "james-son-of-alphaeus", "thaddaeus", "simon-zealot", "judas-iscariot"] - for slug in apostle_slugs: + for slug in _slugs["apostles"]: sitemap_xml += f""" {base_url}/the-twelve-apostles/{slug} {current_date} @@ -296,8 +300,7 @@ def sitemap(): """ - women_slugs = ["eve", "sarah", "rebekah", "rachel", "miriam", "deborah", "ruth", "hannah", "esther", "mary-mother-of-jesus", "mary-magdalene", "martha"] - for slug in women_slugs: + for slug in _slugs["women"]: sitemap_xml += f""" {base_url}/women-of-the-bible/{slug} {current_date} @@ -306,8 +309,7 @@ def sitemap(): """ - festival_slugs = ["passover", "unleavened-bread", "firstfruits", "pentecost", "trumpets", "atonement", "tabernacles"] - for slug in festival_slugs: + for slug in _slugs["festivals"]: sitemap_xml += f""" {base_url}/biblical-festivals/{slug} {current_date} @@ -316,8 +318,7 @@ def sitemap(): """ - fruit_slugs = ["love", "joy", "peace", "longsuffering", "gentleness", "goodness", "faith", "meekness", "temperance"] - for slug in fruit_slugs: + for slug in _slugs["fruits_of_spirit"]: sitemap_xml += f""" {base_url}/fruits-of-the-spirit/{slug} {current_date} diff --git a/kjvstudy_org/utils/books.py b/kjvstudy_org/utils/books.py index ccfbc23..8e6d83a 100644 --- a/kjvstudy_org/utils/books.py +++ b/kjvstudy_org/utils/books.py @@ -1,227 +1,28 @@ """Book name normalization and categorization utilities.""" +import json +from pathlib import Path +from functools import lru_cache from typing import Optional -# Old Testament books -OT_BOOKS = [ - 'Genesis', 'Exodus', 'Leviticus', 'Numbers', 'Deuteronomy', - 'Joshua', 'Judges', 'Ruth', '1 Samuel', '2 Samuel', - '1 Kings', '2 Kings', '1 Chronicles', '2 Chronicles', - 'Ezra', 'Nehemiah', 'Esther', 'Job', 'Psalms', 'Proverbs', - 'Ecclesiastes', "Solomon's Song", 'Isaiah', 'Jeremiah', - 'Lamentations', 'Ezekiel', 'Daniel', 'Hosea', 'Joel', 'Amos', - 'Obadiah', 'Jonah', 'Micah', 'Nahum', 'Habakkuk', 'Zephaniah', - 'Haggai', 'Zechariah', 'Malachi' -] +# Path to bible metadata JSON file +_METADATA_PATH = Path(__file__).parent.parent / "data" / "bible_metadata.json" -# New Testament books -NT_BOOKS = [ - 'Matthew', 'Mark', 'Luke', 'John', 'Acts', - 'Romans', '1 Corinthians', '2 Corinthians', 'Galatians', 'Ephesians', - 'Philippians', 'Colossians', '1 Thessalonians', '2 Thessalonians', - '1 Timothy', '2 Timothy', 'Titus', 'Philemon', - 'Hebrews', 'James', '1 Peter', '2 Peter', - '1 John', '2 John', '3 John', 'Jude', 'Revelation' -] -# Comprehensive book name abbreviations and variations -BOOK_ABBREVIATIONS = { - # Psalm/Psalms - "Psalm": "Psalms", +@lru_cache(maxsize=1) +def _load_bible_metadata() -> dict: + """ + Load bible metadata from JSON file. + Cached since this data never changes and is accessed frequently. + """ + with open(_METADATA_PATH, "r", encoding="utf-8") as f: + return json.load(f) - # Roman numerals to Arabic numerals - "I Samuel": "1 Samuel", - "II Samuel": "2 Samuel", - "I Kings": "1 Kings", - "II Kings": "2 Kings", - "I Chronicles": "1 Chronicles", - "II Chronicles": "2 Chronicles", - "I Corinthians": "1 Corinthians", - "II Corinthians": "2 Corinthians", - "I Thessalonians": "1 Thessalonians", - "II Thessalonians": "2 Thessalonians", - "I Timothy": "1 Timothy", - "II Timothy": "2 Timothy", - "I Peter": "1 Peter", - "II Peter": "2 Peter", - "I John": "1 John", - "II John": "2 John", - "III John": "3 John", - # Full word numbers to Arabic numerals - "First Samuel": "1 Samuel", - "Second Samuel": "2 Samuel", - "First Kings": "1 Kings", - "Second Kings": "2 Kings", - "First Chronicles": "1 Chronicles", - "Second Chronicles": "2 Chronicles", - "First Corinthians": "1 Corinthians", - "Second Corinthians": "2 Corinthians", - "First Thessalonians": "1 Thessalonians", - "Second Thessalonians": "2 Thessalonians", - "First Timothy": "1 Timothy", - "Second Timothy": "2 Timothy", - "First Peter": "1 Peter", - "Second Peter": "2 Peter", - "First John": "1 John", - "Second John": "2 John", - "Third John": "3 John", - - # Alternative names (map to the name used in verses-1769.json) - "Song of Solomon": "Solomon's Song", - "Song of Songs": "Solomon's Song", - "Canticles": "Solomon's Song", - - # Common abbreviations - Old Testament - "Gen": "Genesis", - "Ge": "Genesis", - "Exo": "Exodus", - "Ex": "Exodus", - "Lev": "Leviticus", - "Le": "Leviticus", - "Num": "Numbers", - "Nu": "Numbers", - "Deut": "Deuteronomy", - "Dt": "Deuteronomy", - "Josh": "Joshua", - "Jos": "Joshua", - "Judg": "Judges", - "Jdg": "Judges", - "Ru": "Ruth", - "1Sam": "1 Samuel", - "1 Sam": "1 Samuel", - "1S": "1 Samuel", - "2Sam": "2 Samuel", - "2 Sam": "2 Samuel", - "2S": "2 Samuel", - "1Ki": "1 Kings", - "1 Ki": "1 Kings", - "1K": "1 Kings", - "2Ki": "2 Kings", - "2 Ki": "2 Kings", - "2K": "2 Kings", - "1Chr": "1 Chronicles", - "1 Chr": "1 Chronicles", - "1Ch": "1 Chronicles", - "2Chr": "2 Chronicles", - "2 Chr": "2 Chronicles", - "2Ch": "2 Chronicles", - "Ezr": "Ezra", - "Neh": "Nehemiah", - "Ne": "Nehemiah", - "Est": "Esther", - "Ps": "Psalms", - "Psa": "Psalms", - "Prov": "Proverbs", - "Pr": "Proverbs", - "Eccl": "Ecclesiastes", - "Ec": "Ecclesiastes", - "Song": "Song of Solomon", - "Sos": "Song of Solomon", - "SS": "Song of Solomon", - "Isa": "Isaiah", - "Is": "Isaiah", - "Jer": "Jeremiah", - "Je": "Jeremiah", - "Lam": "Lamentations", - "La": "Lamentations", - "Ezek": "Ezekiel", - "Eze": "Ezekiel", - "Ezk": "Ezekiel", - "Dan": "Daniel", - "Da": "Daniel", - "Hos": "Hosea", - "Ho": "Hosea", - "Joe": "Joel", - "Jl": "Joel", - "Am": "Amos", - "Ob": "Obadiah", - "Jon": "Jonah", - "Mic": "Micah", - "Mi": "Micah", - "Nah": "Nahum", - "Na": "Nahum", - "Hab": "Habakkuk", - "Hb": "Habakkuk", - "Zep": "Zephaniah", - "Zph": "Zephaniah", - "Hag": "Haggai", - "Hg": "Haggai", - "Zech": "Zechariah", - "Zec": "Zechariah", - "Zch": "Zechariah", - "Mal": "Malachi", - - # Common abbreviations - New Testament - "Mat": "Matthew", - "Mt": "Matthew", - "Mar": "Mark", - "Mk": "Mark", - "Mrk": "Mark", - "Luk": "Luke", - "Lk": "Luke", - "Joh": "John", - "Jn": "John", - "Act": "Acts", - "Ac": "Acts", - "Rom": "Romans", - "Ro": "Romans", - "1Cor": "1 Corinthians", - "1 Cor": "1 Corinthians", - "1Co": "1 Corinthians", - "2Cor": "2 Corinthians", - "2 Cor": "2 Corinthians", - "2Co": "2 Corinthians", - "Gal": "Galatians", - "Ga": "Galatians", - "Eph": "Ephesians", - "Ep": "Ephesians", - "Phil": "Philippians", - "Php": "Philippians", - "Ph": "Philippians", - "Col": "Colossians", - "Co": "Colossians", - "1Thess": "1 Thessalonians", - "1 Thess": "1 Thessalonians", - "1Th": "1 Thessalonians", - "2Thess": "2 Thessalonians", - "2 Thess": "2 Thessalonians", - "2Th": "2 Thessalonians", - "1Tim": "1 Timothy", - "1 Tim": "1 Timothy", - "1Ti": "1 Timothy", - "2Tim": "2 Timothy", - "2 Tim": "2 Timothy", - "2Ti": "2 Timothy", - "Tit": "Titus", - "Ti": "Titus", - "Phm": "Philemon", - "Pm": "Philemon", - "Heb": "Hebrews", - "He": "Hebrews", - "Jam": "James", - "Jas": "James", - "Jm": "James", - "1Pet": "1 Peter", - "1 Pet": "1 Peter", - "1Pe": "1 Peter", - "1P": "1 Peter", - "2Pet": "2 Peter", - "2 Pet": "2 Peter", - "2Pe": "2 Peter", - "2P": "2 Peter", - "1Joh": "1 John", - "1 Joh": "1 John", - "1Jn": "1 John", - "2Joh": "2 John", - "2 Joh": "2 John", - "2Jn": "2 John", - "3Joh": "3 John", - "3 Joh": "3 John", - "3Jn": "3 John", - "Jud": "Jude", - "Rev": "Revelation", - "Re": "Revelation", -} +# Load data from JSON +_metadata = _load_bible_metadata() +OT_BOOKS = _metadata["old_testament_books"] +NT_BOOKS = _metadata["new_testament_books"] +BOOK_ABBREVIATIONS = _metadata["book_abbreviations"] def normalize_book_name(book: str) -> Optional[str]: diff --git a/kjvstudy_org/utils/helpers.py b/kjvstudy_org/utils/helpers.py index 061a06b..c46c125 100644 --- a/kjvstudy_org/utils/helpers.py +++ b/kjvstudy_org/utils/helpers.py @@ -1,13 +1,61 @@ """Helper utilities for KJV Study.""" import re +import json import hashlib from datetime import datetime +from pathlib import Path from typing import Optional, Dict, List from functools import lru_cache from ..kjv import bible, VerseReference from ..topics import get_all_topics +# Paths to data files +_DATA_DIR = Path(__file__).parent.parent / "data" +_CHAPTER_EXPLANATIONS_PATH = _DATA_DIR / "chapter_explanations.json" +_POPULAR_CHAPTERS_PATH = _DATA_DIR / "popular_chapters.json" +_FEATURED_VERSES_PATH = _DATA_DIR / "featured_verses.json" + + +@lru_cache(maxsize=1) +def _load_chapter_explanations() -> dict: + """Load chapter explanations from JSON file. Cached since data never changes.""" + with open(_CHAPTER_EXPLANATIONS_PATH, "r", encoding="utf-8") as f: + data = json.load(f) + # Convert string keys to integers for chapter numbers + return { + book: {int(chapter): explanation for chapter, explanation in chapters.items()} + for book, chapters in data.items() + } + + +@lru_cache(maxsize=1) +def _load_popular_chapters() -> dict: + """Load popular chapters from JSON file. Cached since data never changes.""" + with open(_POPULAR_CHAPTERS_PATH, "r", encoding="utf-8") as f: + data = json.load(f) + # Convert string keys to integers for chapter numbers + popular = { + book: {int(chapter): score for chapter, score in chapters.items()} + for book, chapters in data["popular_chapters"].items() + } + return { + "popular_chapters": popular, + "high_readership_books": data["high_readership_books"] + } + + +@lru_cache(maxsize=1) +def _load_featured_verses() -> list: + """Load featured verses from JSON file. Cached since data never changes.""" + with open(_FEATURED_VERSES_PATH, "r", encoding="utf-8") as f: + data = json.load(f) + # Convert dict format to tuple format for compatibility + return [ + (verse["book"], verse["chapter"], verse["verse"]) + for verse in data["verses"] + ] + @lru_cache(maxsize=512) def create_slug(text: str) -> str: @@ -158,50 +206,10 @@ def get_related_content(book: str, chapter: int = None, verse: int = None) -> Di return related -# Popular/well-known chapters with their scores (1-10 scale) -POPULAR_CHAPTERS = { - "John": {3: 10}, - "1 Corinthians": {13: 10}, - "Psalms": {23: 10, 91: 9, 1: 8, 139: 8}, - "Romans": {8: 9, 3: 8, 12: 8}, - "Matthew": {5: 9, 6: 8, 7: 8}, - "Ephesians": {2: 8, 6: 8}, - "Philippians": {4: 8}, - "Genesis": {1: 9, 3: 8, 22: 7}, - "Exodus": {20: 8, 14: 7}, - "Isaiah": {53: 9, 40: 8}, - "Jeremiah": {29: 7}, - "Proverbs": {31: 7, 3: 7}, - "Ecclesiastes": {3: 8}, - "1 Peter": {5: 7}, - "James": {1: 7}, - "Hebrews": {11: 8, 12: 7}, - "Revelation": {21: 8, 22: 7}, - "Luke": {2: 9, 15: 8}, - "2 Timothy": {3: 7}, - "Joshua": {1: 7}, - "Daniel": {3: 7, 6: 7}, - "1 John": {4: 8}, - "Galatians": {5: 7}, - "Colossians": {3: 7}, - "1 Thessalonians": {4: 7}, - "Mark": {16: 7}, - "Acts": {2: 8}, - "1 Samuel": {17: 7}, - "Job": {19: 7}, - "2 Corinthians": {5: 7}, - "1 Kings": {3: 6, 18: 6}, - "Malachi": {3: 6}, - "Joel": {2: 6}, - "Micah": {6: 6}, - "Habakkuk": {2: 6}, -} - -HIGH_READERSHIP_BOOKS = [ - "Matthew", "Mark", "Luke", "John", "Acts", "Romans", - "1 Corinthians", "2 Corinthians", "Galatians", "Ephesians", - "Philippians", "Colossians", "Genesis", "Exodus", "Psalms", "Proverbs" -] +# Load popular chapters data from JSON +_popular_data = _load_popular_chapters() +POPULAR_CHAPTERS = _popular_data["popular_chapters"] +HIGH_READERSHIP_BOOKS = _popular_data["high_readership_books"] @lru_cache(maxsize=512) @@ -228,41 +236,8 @@ def get_chapter_popularity_score(book: str, chapter: int) -> int: return min(default_score, 6) -# Chapter explanations for popular chapters -CHAPTER_EXPLANATIONS = { - "John": { - 3: "Contains John 3:16 - 'For God so loved the world' - the most quoted verse in Christianity", - 1: "The Word became flesh - Jesus as the eternal Logos and the calling of the first disciples", - }, - "1 Corinthians": { - 13: "The famous 'Love Chapter' - 'Love is patient, love is kind' - essential reading for weddings and Christian living", - }, - "Psalms": { - 23: "The beloved Shepherd Psalm - 'The Lord is my shepherd, I shall not want' - comfort in times of trouble", - 91: "Psalm of protection - 'He who dwells in the shelter of the Most High' - promises of God's care", - 1: "The blessed man - contrasts the righteous and wicked, foundation of wisdom literature", - 139: "God's omniscience and omnipresence - 'You have searched me and known me' - intimate knowledge of God", - }, - "Romans": { - 8: "No condemnation in Christ - 'All things work together for good' - assurance of salvation", - 3: "All have sinned - universal need for salvation and justification by faith", - 12: "Living sacrifice - practical Christian living and spiritual gifts", - }, - "Matthew": { - 5: "The Beatitudes - 'Blessed are the poor in spirit' - foundation of Christian ethics", - 6: "The Lord's Prayer and teachings on worry - 'Give us this day our daily bread'", - 7: "Golden Rule and narrow gate - 'Do unto others as you would have them do unto you'", - }, - "Genesis": { - 1: "Creation account - 'In the beginning God created the heavens and the earth'", - 3: "The Fall - Adam and Eve's disobedience and the first promise of redemption", - 22: "Abraham's ultimate test - the near-sacrifice of Isaac, foreshadowing Christ", - }, - "Isaiah": { - 53: "The Suffering Servant - 'He was wounded for our transgressions' - prophecy of Christ's crucifixion", - 40: "Comfort my people - 'Every valley shall be exalted' - hope and restoration", - }, -} +# Load chapter explanations from JSON +CHAPTER_EXPLANATIONS = _load_chapter_explanations() def get_chapter_popularity_explanation(book: str, chapter: int) -> str: @@ -293,40 +268,8 @@ def get_chapter_popularity_explanation(book: str, chapter: int) -> str: return f"Part of {book} - explore this chapter to discover its significance" -# Featured verses for verse of the day -FEATURED_VERSES = [ - ("John", 3, 16), - ("Psalms", 23, 1), - ("Proverbs", 3, 5), - ("Philippians", 4, 13), - ("Romans", 8, 28), - ("Isaiah", 40, 31), - ("Jeremiah", 29, 11), - ("Joshua", 1, 9), - ("Matthew", 11, 28), - ("Psalms", 46, 10), - ("Romans", 12, 2), - ("2 Timothy", 1, 7), - ("Proverbs", 22, 6), - ("1 Corinthians", 13, 4), - ("Galatians", 5, 22), - ("Hebrews", 11, 1), - ("James", 1, 2), - ("1 Peter", 5, 7), - ("Psalms", 119, 105), - ("Matthew", 6, 33), - ("John", 14, 6), - ("Romans", 5, 8), - ("Ephesians", 2, 8), - ("Psalms", 27, 1), - ("Isaiah", 41, 10), - ("Matthew", 28, 19), - ("John", 1, 1), - ("Psalms", 51, 10), - ("Proverbs", 18, 10), - ("2 Corinthians", 5, 17), - ("Colossians", 3, 23), -] +# Load featured verses from JSON +FEATURED_VERSES = _load_featured_verses() def get_daily_verse() -> Dict: