282 lines
5.3 KiB
Go
282 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
)
|
|
|
|
var BibleRegex = regexp.MustCompile(`(?P<prefix>\w*?)? *(?P<book>[a-zA-Z]+?)\s?(?P<chapter>\d{1,3})(?::(?P<startverse>\d{1,3})(?:-(?P<endverse>\d{1,3})?)?)`)
|
|
|
|
var MatchError = errors.New("Error matching verse")
|
|
|
|
var CanonicalName = map[int]string{
|
|
1: "Genesis",
|
|
2: "Exodus",
|
|
3: "Leviticus",
|
|
4: "Numbers",
|
|
5: "Deuteronomy",
|
|
6: "Joshua",
|
|
7: "Judges",
|
|
8: "Ruth",
|
|
9: "1 Samuel",
|
|
10: "2 Samuel",
|
|
11: "1 Kings",
|
|
12: "2 Kings",
|
|
13: "1 Chronicles",
|
|
14: "2 Chronicles",
|
|
15: "Ezra",
|
|
16: "Nehemiah",
|
|
17: "Esther",
|
|
18: "Job",
|
|
19: "Psalms",
|
|
20: "Proverbs",
|
|
21: "Ecclesiastes",
|
|
22: "Song of Solomon",
|
|
23: "Isaiah",
|
|
24: "Jeremiah",
|
|
25: "Lamentations",
|
|
26: "Ezekiel",
|
|
27: "Daniel",
|
|
28: "Hosea",
|
|
29: "Joel",
|
|
30: "Amos",
|
|
31: "Obadiah",
|
|
32: "Jonah",
|
|
33: "Micah",
|
|
34: "Nahum",
|
|
35: "Habakkuk",
|
|
36: "Zephaniah",
|
|
37: "Haggai",
|
|
38: "Zechariah",
|
|
39: "Malachi",
|
|
40: "Matthew",
|
|
41: "Mark",
|
|
42: "Luke",
|
|
43: "John",
|
|
44: "Acts",
|
|
45: "Romans",
|
|
46: "1 Corinthians",
|
|
47: "2 Corinthians",
|
|
48: "Galatians",
|
|
49: "Ephesians",
|
|
50: "Philippians",
|
|
51: "Colossians",
|
|
52: "1 Thessalonians",
|
|
53: "2 Thessalonians",
|
|
54: "1 Timothy",
|
|
55: "2 Timothy",
|
|
56: "Titus",
|
|
57: "Philemon",
|
|
58: "Hebrews",
|
|
59: "James",
|
|
60: "1 Peter",
|
|
61: "2 Peter",
|
|
62: "1 John",
|
|
63: "2 John",
|
|
64: "3 John",
|
|
65: "Jude",
|
|
66: "Revelation",
|
|
}
|
|
|
|
var Books = map[string]int{
|
|
"GEN": 1,
|
|
"EXO": 2,
|
|
"EX": 2,
|
|
"LEV": 3,
|
|
"LV": 3,
|
|
"NUM": 4,
|
|
"DEU": 5,
|
|
"DT": 5,
|
|
"JOS": 6,
|
|
"JUDGES": 7,
|
|
"JDG": 7,
|
|
"JDGS": 7,
|
|
"JG": 7,
|
|
"RUT": 8,
|
|
"1 SAM": 9,
|
|
"2 SAM": 10,
|
|
"1 KIN": 11,
|
|
"2 KIN": 12,
|
|
"1 CHR": 13,
|
|
"2 CHR": 14,
|
|
"EZR": 15,
|
|
"NEH": 16,
|
|
"EST": 17,
|
|
"JOB": 18,
|
|
"PSA": 19,
|
|
"PS": 19,
|
|
"PRO": 20,
|
|
"PRV": 20,
|
|
"ECC": 21,
|
|
"SOL": 22,
|
|
"SON": 22,
|
|
"ISA": 23,
|
|
"JER": 24,
|
|
"LAM": 25,
|
|
"EZE": 26,
|
|
"DAN": 27,
|
|
"HOS": 28,
|
|
"JOE": 29,
|
|
"AMO": 30,
|
|
"OBA": 31,
|
|
"JON": 32,
|
|
"MIC": 33,
|
|
"NAH": 34,
|
|
"HAB": 35,
|
|
"ZEP": 36,
|
|
"HAG": 37,
|
|
"ZEC": 38,
|
|
"MAL": 39,
|
|
"MAT": 40,
|
|
"MAR": 41,
|
|
"LUK": 42,
|
|
"JOH": 43,
|
|
"ACT": 44,
|
|
"ROM": 45,
|
|
"1 COR": 46,
|
|
"2 COR": 47,
|
|
"GAL": 48,
|
|
"EPH": 49,
|
|
"PHILIPPIANS": 50,
|
|
"COL": 51,
|
|
"1 THE": 52,
|
|
"2 THE": 53,
|
|
"1 TIM": 54,
|
|
"2 TIM": 55,
|
|
"TIT": 56,
|
|
"PHILEMON": 57,
|
|
"HEB": 58,
|
|
"JAM": 59,
|
|
"1 PET": 60,
|
|
"2 PET": 61,
|
|
"1 JOH": 62,
|
|
"2 JOH": 63,
|
|
"3 JOH": 64,
|
|
"JUDE": 65,
|
|
"REV": 66,
|
|
}
|
|
|
|
var FirstPrefixes = []string{
|
|
"FIRST",
|
|
"1ST",
|
|
"1",
|
|
"I",
|
|
}
|
|
var SecondPrefixes = []string{
|
|
"SECOND",
|
|
"2nd",
|
|
"2",
|
|
"II",
|
|
}
|
|
|
|
type BibleReference struct {
|
|
RegexMatch string
|
|
Prefix string
|
|
Book string
|
|
BookNum int
|
|
Chapter string
|
|
StartVerse string
|
|
EndVerse string
|
|
StartKey string // key format is BBCCCVVV
|
|
EndKey string
|
|
}
|
|
|
|
func GetReferences(text string) []*BibleReference {
|
|
matches := BibleRegex.FindAllStringSubmatch(text, -1)
|
|
refs := make([]*BibleReference, 0, len(matches))
|
|
for _, match := range matches {
|
|
ref, err := NewBibleReference(match)
|
|
if err != nil {
|
|
fmt.Printf(`Couldn't parse "%s"
|
|
`, match[0])
|
|
continue
|
|
}
|
|
|
|
fmt.Printf(`parsed "%s": %s - %s
|
|
`, ref.RegexMatch, ref.StartKey, ref.EndKey)
|
|
refs = append(refs, ref)
|
|
}
|
|
return refs
|
|
}
|
|
|
|
func NewBibleReference(match []string) (*BibleReference, error) {
|
|
if len(match) < 6 {
|
|
return nil, MatchError
|
|
}
|
|
ref := &BibleReference{
|
|
RegexMatch: match[0],
|
|
Prefix: match[1],
|
|
Book: match[2],
|
|
Chapter: match[3],
|
|
StartVerse: match[4],
|
|
EndVerse: match[5],
|
|
}
|
|
err := ref.Validate()
|
|
return ref, err
|
|
}
|
|
|
|
func contains(s []string, str string) bool {
|
|
for _, v := range s {
|
|
if v == str {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (b *BibleReference) CanonicalName() (string, error) {
|
|
book, ok := CanonicalName[b.BookNum]
|
|
if !ok {
|
|
return "", errors.New("Can't find book, maybe you're Catholic?")
|
|
}
|
|
if b.StartKey == b.EndKey {
|
|
return fmt.Sprintf("%s %s:%s", book, b.Chapter, b.StartVerse), nil
|
|
}
|
|
return fmt.Sprintf("%s %s:%s-%s", book, b.Chapter, b.StartVerse, b.EndVerse), nil
|
|
}
|
|
|
|
func (b *BibleReference) Validate() error {
|
|
if contains(FirstPrefixes, b.Prefix) {
|
|
b.Prefix = "1"
|
|
} else if contains(SecondPrefixes, b.Prefix) {
|
|
b.Prefix = "2"
|
|
} else {
|
|
b.Prefix = ""
|
|
}
|
|
if b.Prefix != "" {
|
|
b.Book = fmt.Sprintf("%s %s", b.Prefix, b.Book)
|
|
}
|
|
num, ok := Books[b.Book]
|
|
if !ok {
|
|
num, ok = Books[fmt.Sprintf("%.5s", b.Book)]
|
|
}
|
|
if !ok {
|
|
num, ok = Books[fmt.Sprintf("%.3s", b.Book)]
|
|
}
|
|
if !ok {
|
|
return MatchError
|
|
}
|
|
b.BookNum = num
|
|
|
|
chapter, err := strconv.Atoi(b.Chapter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
startverse, err := strconv.Atoi(b.StartVerse)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
endverse, err := strconv.Atoi(b.EndVerse)
|
|
if err != nil {
|
|
endverse = startverse
|
|
}
|
|
|
|
b.StartKey = fmt.Sprintf("%02d%03d%03d", num, chapter, startverse)
|
|
b.EndKey = fmt.Sprintf("%02d%03d%03d", num, chapter, endverse)
|
|
return nil
|
|
|
|
}
|