import os, sqlite3, config, re, json, base64 from shutil import copyfile from BiblesSqlite import BiblesSqlite from BibleVerseParser import BibleVerseParser class Converter: # create UniqueBible.app commentary module def createCommentaryModule(self, abbreviation, title, description, content): ubCommentary = os.path.join(config.marvelData, "commentaries", "c{0}.commentary".format(abbreviation)) if os.path.isfile(ubCommentary): os.remove(ubCommentary) with sqlite3.connect(ubCommentary) as connection: # create a cusor object cursor = connection.cursor() # create two tables: "Details" & "Commentary" statements = ( "CREATE TABLE Details (Title NVARCHAR(100), Abbreviation NVARCHAR(50), Information TEXT, Version INT, OldTestament BOOL, NewTestament BOOL, Apocrypha BOOL, Strongs BOOL)", "CREATE TABLE Commentary (Book INT, Chapter INT, Scripture TEXT)", ) for create in statements: cursor.execute(create) connection.commit() # insert data to table "Details" insert = "INSERT INTO Details (Title, Abbreviation, Information, Version, OldTestament, NewTestament, Apocrypha, Strongs) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(insert, (title, abbreviation, description, 1, 1, 1, 0, 0)) connection.commit() # insert data to table "Commentary" if content: insert = "INSERT INTO Commentary (Book, Chapter, Scripture) VALUES (?, ?, ?)" cursor.executemany(insert, content) connection.commit() def createBookModuleFromImages(self, folder): module = os.path.basename(folder) bookContent = [] for filepath in sorted([f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f)) and not re.search("^[\._]", f)]): fileBasename = os.path.basename(filepath) fileName, fileExtension = os.path.splitext(fileBasename) if fileExtension.lower() in (".png", ".jpg", ".jpeg", ".bmp", ".gif"): # read a binary file with open(os.path.join(folder, filepath), "rb") as fileObject: binaryData = fileObject.read() encodedData = base64.b64encode(binaryData) binaryString = encodedData.decode("ascii") htmlTag = '<img src="data:image/{2};base64,{0}" alt="{1}">'.format(binaryString, fileBasename, fileExtension[1:]) bookContent.append((fileName, htmlTag)) if bookContent and module: self.createBookModule(module, bookContent) return True else: return False def createBookModuleFromHTML(self, folder): module = os.path.basename(folder) bookContent = [] for filepath in sorted([f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f)) and not re.search("^[\._]", f)]): fileBasename = os.path.basename(filepath) fileName, fileExtension = os.path.splitext(fileBasename) if fileExtension.lower() in (".htm", ".html", ".xhtml"): with open(os.path.join(folder, filepath), "r", encoding="utf-8") as fileObject: html = fileObject.read() html = BibleVerseParser(config.parserStandarisation).parseText(html) bookContent.append((fileName, html)) if bookContent and module: self.createBookModule(module, bookContent) return True else: return False def createBookModuleFromNotes(self, folder): module = os.path.basename(folder) bookContent = [] for filepath in sorted([f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f)) and not re.search("^[\._]", f)]): fileBasename = os.path.basename(filepath) fileName, fileExtension = os.path.splitext(fileBasename) if fileExtension.lower() == ".uba": with open(os.path.join(folder, filepath), "r", encoding="utf-8") as fileObject: note = fileObject.read() note = BibleVerseParser(config.parserStandarisation).parseText(note) bookContent.append((fileName, note)) if bookContent and module: self.createBookModule(module, bookContent) return True else: return False # create UniqueBible.app book modules def createBookModule(self, module, content, blobData=None): content = [(re.sub("['{0}]".format('"'), "_", chapter), chapterContent) for chapter, chapterContent in content] book = os.path.join(config.marvelData, "books", "{0}.book".format(module)) if os.path.isfile(book): os.remove(book) with sqlite3.connect(book) as connection: cursor = connection.cursor() # Create table for book content create = "CREATE TABLE Reference (Chapter NVARCHAR(100), Content TEXT)" cursor.execute(create) connection.commit() # insert data for book content insert = "INSERT INTO Reference (Chapter, Content) VALUES (?, ?)" cursor.executemany(insert, content) connection.commit() if blobData: # Create table for book content create = "CREATE TABLE data (Filename TEXT, Content BLOB)" cursor.execute(create) connection.commit() # insert data for book content insert = "INSERT INTO data (Filename, Content) VALUES (?, ?)" cursor.executemany(insert, blobData) connection.commit() # create UniqueBible.app dictionary module def createDictionaryModule(self, module, content): filename = os.path.join("thirdParty", "dictionaries", "{0}.dic.bbp".format(module)) if os.path.isfile(filename): os.remove(filename) with sqlite3.connect(filename) as connection: cursor = connection.cursor() # create table "Dictionary" create = "CREATE TABLE Dictionary (Topic NVARCHAR(100), Definition TEXT)" cursor.execute(create) connection.commit() # insert data to table "Dictionary" insert = "INSERT INTO Dictionary (Topic, Definition) VALUES (?, ?)" cursor.executemany(insert, content) connection.commit() # create UniqueBible.app lexicon modules def createLexiconModule(self, module, content): book = os.path.join(config.marvelData, "lexicons", "{0}.lexicon".format(module)) if os.path.isfile(book): os.remove(book) with sqlite3.connect(book) as connection: cursor = connection.cursor() # create table "Lexicon" create = "CREATE TABLE Lexicon (Topic NVARCHAR(100), Definition TEXT)" cursor.execute(create) connection.commit() # insert data to table "Lexicon insert = "INSERT INTO Lexicon (Topic, Definition) VALUES (?, ?)" cursor.executemany(insert, content) connection.commit() # export image files def exportImageData(self, module, images): module = module.replace(" ", "_") imageFolder = os.path.join("htmlResources", "images", module) if not os.path.isdir(imageFolder): os.makedirs(imageFolder) for filename, blobData in images: imageFilePath = os.path.join(imageFolder, filename) if not os.path.isfile(imageFilePath): with open(imageFilePath, "wb") as imagefile: imagefile.write(blobData) # Export from installed bibles into JSON format; for use with DartBible project. # usage: # from ThirdParty import Converter # Converter().exportJsonBible("KJV") def exportMultipleBibles(self, bibleList): for bible in bibleList: self.exportJsonBible(bible) def exportJsonBible(self, bible): filename = os.path.join(config.marvelData, "bibles", "{0}.bible".format(bible)) connection = sqlite3.connect(filename) cursor = connection.cursor() query = "SELECT * FROM Verses ORDER BY Book, Chapter, Verse" cursor.execute(query) verses = cursor.fetchall() jsonString = "[\n" for book, chapter, verse, scripture in verses: jsonString += "{\n" jsonString += '"bNo": {0},\n'.format(book) jsonString += '"cNo": {0},\n'.format(chapter) jsonString += '"vNo": {0},\n'.format(verse) jsonString += '"vText": "{0}"\n'.format(scripture.strip().replace('"', '\\"')) jsonString += "},\n" jsonString = jsonString[:-2] jsonString += "\n]\n" jsonFile = os.path.join(config.marvelData, "bibles", "{0}.json".format(bible)) fileObj = open(jsonFile, "w", encoding="utf-8") fileObj.write(jsonString) fileObj.close() # if exportMarvelBible doesn't work, use exportMarvelBible2 instead def exportJsonBible2(self, bible): filename = os.path.join(config.marvelData, "bibles", "{0}.bible".format(bible)) connection = sqlite3.connect(filename) cursor = connection.cursor() query = "SELECT * FROM Verses ORDER BY Book, Chapter, Verse" cursor.execute(query) verses = cursor.fetchall() jsonString = "[\n" jsonObject = [] for book, chapter, verse, scripture in verses: verseObject = {} verseObject["bNo"] = book verseObject["cNo"] = chapter verseObject["vNo"] = verse verseObject["vText"] = scripture jsonObject.append(verseObject) jsonString = json.dumps(jsonObject) # Please note that "json.dumps()" converts unicode characters. jsonFile = os.path.join(config.marvelData, "bibles", "{0}.json".format(bible)) fileObj = open(jsonFile, "w", encoding="utf-8") fileObj.write(jsonString) fileObj.close() # bible modules verse number format def formatVerseNumber(self, book, chapter, verse, text): text = '<vid id="v{0}.{1}.{2}" onclick="luV({2})">{2}</vid> {3}'.format(book, chapter, verse, text) p = re.compile("(<vid .*?</vid> )(<u><b>.*?</b></u>|<br>| | | )") s = p.search(text) while s: text = p.sub(r"\2\1", text) s = p.search(text) text = text.strip() if config.importAddVerseLinebreak: text = "<verse>{0}</verse><br>".format(text) else: text = "<verse>{0}</verse> ".format(text) return text def fixCommentaryScrolling(self, chapterText): p = re.compile('{}([^{}]*?)(<vid id="v[0-9]+?\.[0-9]+?\.[0-9]+?"></vid>)(<vid)') s = p.search(chapterText) while s: chapterText = p.sub(r"{}\2|\1\3", chapterText) s = p.search(chapterText) chapterText = chapterText.replace("{}", "<hr>") chapterText = chapterText.replace("</vid>|", "</vid>") return chapterText def importAllFilesInAFolder(self, folder): files = [filename for filename in os.listdir(folder) if os.path.isfile(os.path.join(folder, filename)) and not re.search("^[\._]", filename)] validFiles = [filename for filename in files if re.search('(\.dct\.mybible|\.dcti|\.lexi|\.dictionary\.SQLite3|\.bbl\.mybible|\.cmt\.mybible|\.bok\.mybible|\.bbli|\.cmti|\.refi|\.commentaries\.SQLite3|\.SQLite3)$', filename)] if validFiles: for filename in validFiles: filename = os.path.join(folder, filename) try: if re.search('(\.dct\.mybible|\.dcti|\.lexi|\.dictionary\.SQLite3)$', filename): self.importThirdPartyDictionary(filename) elif filename.endswith(".bbl.mybible"): self.importMySwordBible(filename) elif filename.endswith(".cmt.mybible"): self.importMySwordCommentary(filename) elif filename.endswith(".bok.mybible"): self.importMySwordBook(filename) elif filename.endswith(".bbli"): self.importESwordBible(filename) elif filename.endswith(".cmti"): self.importESwordCommentary(filename) elif filename.endswith(".refi"): self.importESwordBook(filename) elif filename.endswith(".commentaries.SQLite3"): self.importMyBibleCommentary(filename) elif filename.endswith(".SQLite3"): self.importMyBibleBible(filename) else: print("File type of '{0}' is not supported for conversion.".format(filename)) except: print("Failed to convert '{0}'.".format(filename)) return True def importThirdPartyDictionary(self, filename): *_, name = os.path.split(filename) destination = os.path.join("thirdParty", "dictionaries", name) try: copyfile(filename, destination) except: print("Failed to copy '{0}'.".format(filename)) # Import e-Sword Bibles [Apple / macOS / iOS] def importESwordBible(self, filename): connection = sqlite3.connect(filename) cursor = connection.cursor() query = "SELECT Title, Abbreviation FROM Details" cursor.execute(query) description, abbreviation = cursor.fetchone() abbreviation = abbreviation.replace("-", "") abbreviation = abbreviation.replace("'", "") abbreviation = abbreviation.replace('"', "") abbreviation = abbreviation.replace("+", "x") query = "SELECT * FROM Bible ORDER BY Book, Chapter, Verse" cursor.execute(query) verses = cursor.fetchall() # check existing table names query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, ("table",)) tables = cursor.fetchall() tables = [table[0] for table in tables] if "Notes" in tables: query = "SELECT * FROM Notes" cursor.execute(query) notes = cursor.fetchall() self.eSwordBibleToRichFormat(description, abbreviation, verses, notes) else: self.eSwordBibleToRichFormat(description, abbreviation, verses, []) self.eSwordBibleToPlainFormat(description, abbreviation, verses) connection.close() if config.importRtlOT: config.rtlTexts.append(abbreviation) def eSwordBibleToPlainFormat(self, description, abbreviation, verses): verses = [(book, chapter, verse, self.stripESwordBibleTags(scripture)) for book, chapter, verse, scripture in verses] biblesSqlite = BiblesSqlite() biblesSqlite.importBible(description, abbreviation, verses) del biblesSqlite def eSwordBibleToRichFormat(self, description, abbreviation, verses, notes): formattedBible = os.path.join(config.marvelData, "bibles", "{0}.bible".format(abbreviation)) if os.path.isfile(formattedBible): os.remove(formattedBible) connection = sqlite3.connect(formattedBible) cursor = connection.cursor() statements = ( "CREATE TABLE Bible (Book INT, Chapter INT, Scripture TEXT)", "CREATE TABLE Notes (Book INT, Chapter INT, Verse INT, ID TEXT, Note TEXT)" ) for create in statements: cursor.execute(create) connection.commit() noteList = [] formattedChapters = {} for book, chapter, verse, scripture in verses: scripture = self.convertESwordBibleTags(scripture) if scripture: # fix bible note links if notes: scripture = re.sub("<not>([^\n<>]+?)</not>", r"<sup><ref onclick='bn({0}, {1}, {2}, {3}\1{3})'>⊕</ref></sup>".format(book, chapter, verse, '"'), scripture) # verse number formatting scripture = self.formatVerseNumber(book, chapter, verse, scripture) if (book, chapter) in formattedChapters: formattedChapters[(book, chapter)] = formattedChapters[(book, chapter)] + scripture else: formattedChapters[(book, chapter)] = scripture if notes: insert = "INSERT INTO Notes (Book, Chapter, Verse, ID, Note) VALUES (?, ?, ?, ?, ?)" notes = [(book, chapter, verse, id, self.formatNonBibleESwordModule(note)) for book, chapter, verse, id, note in notes] cursor.executemany(insert, notes) connection.commit() formattedChapters = [(book, chapter, formattedChapters[(book, chapter)]) for book, chapter in formattedChapters] insert = "INSERT INTO Bible (Book, Chapter, Scripture) VALUES (?, ?, ?)" cursor.executemany(insert, formattedChapters) connection.commit() connection.close() def stripESwordBibleTags(self, text): if config.importDoNotStripStrongNo: text = re.sub("[ ]*?<num>([GH][0-9]+?[a-z]*?)</num>", r" \1 ", text) else: text = re.sub("[ ]*?<num>([GH][0-9]+?[a-z]*?)</num>", "", text) if config.importDoNotStripMorphCode: text = re.sub("[ ]*?<tvm>([^\n<>]*?)</tvm>", r" \1 ", text) else: text = re.sub("[ ]*?<tvm>([^\n<>]*?)</tvm>", "", text) searchReplace = ( ("<p>|</p>|<h[0-9]+?>|</h[0-9]+?>|<sup>", " "), ("<not>.*?</not>|<[^\n<>]*?>", ""), (" [ ]+?([^ ])", r" \1"), ) text = text.strip() for search, replace in searchReplace: text = re.sub(search, replace, text) text = text.strip() return text def convertESwordBibleTags(self, text): searchReplace = ( ("[ ]*?<num>([GH][0-9]+?[a-z]*?)</num>", r"<sup><ref onclick='lex({0}\1{0})'>\1</ref></sup>".format('"')), ("[ ]*?<tvm>([^\n<>]*?)</tvm>", r"<sup><ref onclick='rmac({0}\1{0})'>\1</ref></sup>".format('"')), ("<red>", "<woj>"), ("</red>", "</woj>"), ("<blu>", "<esblu>"), ("</blu>", "</esblu>"), ("</ref><ref", "</ref>; <ref"), ("</ref></sup>[ ]*?<sup><ref", "</ref> <ref"), ) for search, replace in searchReplace: text = re.sub(search, replace, text) text = text.strip() return text # Import e-Sword Commentaries def importESwordCommentary(self, filename): # connect e-Sword commentary with sqlite3.connect(filename) as connection: cursor = connection.cursor() # process 4 tables: Details, BookCommentary, ChapterCommentary, VerseCommentary # table: Details query = "SELECT Title, Abbreviation, Information FROM Details" cursor.execute(query) title, abbreviation, description = cursor.fetchone() abbreviation = abbreviation.replace(" ", "_") # check availability tables query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, ("table",)) tables = cursor.fetchall() tables = [table[0] for table in tables] # commentary content commentaryContent = [] # table: BookCommentary if "BookCommentary" in tables: query = "SELECT Book, Comments FROM BookCommentary ORDER BY Book" cursor.execute(query) bookCommentaries = cursor.fetchall() if bookCommentaries: commentaryContent += [(bookBook, 0, bookComments) for bookBook, bookComments in bookCommentaries] # distinct chapters from table: ChapterCommentary distinctChapters1 = [] if "ChapterCommentary" in tables: query = "SELECT DISTINCT Book, Chapter FROM ChapterCommentary ORDER BY Book, Chapter" cursor.execute(query) distinctChapters1 = cursor.fetchall() # distinct chapters from table: VerseCommentary distinctChapters2 = [] if "VerseCommentary" in tables: query = "SELECT DISTINCT Book, ChapterBegin FROM VerseCommentary ORDER BY Book, ChapterBegin, VerseBegin, ChapterEnd, VerseEnd" cursor.execute(query) distinctChapters2 = cursor.fetchall() # combine distinct chapters distinctChapters = list(set().union(distinctChapters1, distinctChapters2)) # draw data on distinct chapters bibleSqlite = BiblesSqlite() for b, c in distinctChapters: # check KJV verse list with a specific book and chapter verseList = bibleSqlite.getVerseList(b, c, "kjvbcv") # create a temporary verse dictionary verseDict = {v: ['<vid id="v{0}.{1}.{2}"></vid>'.format(b, c, v)] for v in verseList} # create a temporary list for holding content verses = [] # data from table: ChapterCommentary if "ChapterCommentary" in tables: query = "SELECT Book, Chapter, Comments FROM ChapterCommentary WHERE Book=? AND Chapter=? ORDER BY Book, Chapter" cursor.execute(query, (b, c)) chapterCommentary = cursor.fetchone() if chapterCommentary: chapterBook, chapterChapter, chapterComments = chapterCommentary verses += [(chapterBook, chapterChapter, 0, chapterChapter, 0, chapterComments)] # data from table: VerseCommentary if "VerseCommentary" in tables: query = "SELECT Book, ChapterBegin, VerseBegin, ChapterEnd, VerseEnd, Comments FROM VerseCommentary WHERE Book=? AND ChapterBegin=? ORDER BY Book, ChapterBegin, VerseBegin, ChapterEnd, VerseEnd" cursor.execute(query, (b, c)) verses += cursor.fetchall() # formating the content for verse in verses: verseContent = '<ref onclick="bcv({0},{1},{2})"><u><b>{1}:{2}-{3}:{4}</b></u></ref><br>{5}'.format(*verse) # check fromverse is a key in verseDict fromverse = verse[2] item = verseDict.get(fromverse, "not found") if item == "not found": verseDict[fromverse] = ['<vid id="v{0}.{1}.{2}"></vid>'.format(b, c, fromverse), verseContent] else: item.append(verseContent) # sort the verse numbers sortedVerseNo = sorted(verseDict.keys()) # format chapter text chapterText = "" for verseNo in sortedVerseNo: chapterText += "{}".join(verseDict[verseNo]) # fix commentary scrolling chapterText = self.fixCommentaryScrolling(chapterText) # add data to commentary content commentaryContent.append((b, c, chapterText)) # convert e-Sword format to UniqueBible format commentaryContent = [(b, c, self.formatESwordCommentaryVerse(chapterText)) for b, c, chapterText in commentaryContent] # write to a UB commentary file self.createCommentaryModule(abbreviation, title, description, commentaryContent) def formatESwordCommentaryVerse(self, text): text = re.sub(r"<u><b>([0-9]+?:[0-9]+?)-\1</b></u>", r"<u><b>\1</b></u>", text) text = re.sub(r"<u><b>([0-9]+?):([0-9]+?)-\1:([0-9]+?)</b></u>", r"<u><b>\1:\2-\3</b></u>", text) text = self.formatNonBibleESwordModule(text) return text def formatNonBibleESwordModule(self, text): searchReplace = { ("<ref>(.+?)</ref>", self.convertESwordBibleReference), ("<num>(.*?)</num>", r"<ref onclick='lex({0}\1{0})'>\1</ref>".format('"')), ("<tvm>(.*?)</tvm>", r"<ref onclick='rmac({0}\1{0})'>\1</ref>".format('"')), } for search, replace in searchReplace: text = re.sub(search, replace, text) return text def convertESwordBibleReference(self, match): value = match.group(1).replace("_", " ") return "<ref onclick='document.title={0}BIBLE:::{1}{0}'>{1}</ref>".format('"', value) # reference = self.parseESwordReference("{0} ".format(value)) # if reference: # return "{0}{1}</ref>".format(reference, value) # else: # return "<ref onclick='document.title={0}BIBLE:::{1}{0}'>{1}</ref>".format('"', value) def parseESwordReference(self, text): if re.search("^([1-9A-Z][A-Za-z][a-z]) ([0-9]+?):([0-9]+?)[^0-9].*?$", text): b, cv = text.split(" ", 1) b = self.convertESwordBookAbb(b) if b == 0: return "" else: c, v = re.sub("^([0-9]+?):([0-9]+?)[^0-9].*?$", r"\1,\2", cv).split(",") return "<ref onclick='bcv({0}, {1}, {2})'>".format(b, c, v) elif re.search("^([1-9A-Z][A-Za-z][a-z]) ([0-9]+?)[^0-9].*?$", text): b, c = text.split(" ", 1) b = self.convertESwordBookAbb(b) if b == 0: return "" else: c = re.sub("^([0-9]+?)[^0-9].*?$", r"\1", c) return "<ref onclick='bcv({0}, {1}, {2})'>".format(b, c, 1) else: return "" def convertESwordBookAbb(self, eSwordAbb): ubNo = { "Gen": 1, "Exo": 2, "Lev": 3, "Num": 4, "Deu": 5, "Jos": 6, "Jdg": 7, "Rth": 8, "1Sa": 9, "2Sa": 10, "1Ki": 11, "2Ki": 12, "1Ch": 13, "2Ch": 14, "Ezr": 15, "Neh": 16, "Est": 17, "Job": 18, "Psa": 19, "Pro": 20, "Ecc": 21, "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, "1Co": 46, "2Co": 47, "Gal": 48, "Eph": 49, "Php": 50, "Col": 51, "1Th": 52, "2Th": 53, "1Ti": 54, "2Ti": 55, "Tit": 56, "Phm": 57, "Heb": 58, "Jas": 59, "1Pe": 60, "2Pe": 61, "1Jn": 62, "2Jn": 63, "3Jn": 64, "Jud": 65, "Rev": 66, "1Es": 76, "2Es": 77, "Tob": 88, "Jdt": 80, "1Ma": 81, "2Ma": 82, "3Ma": 83, "4Ma": 84, "Man": 85, "Wis": 89, "Sir": 87, "Bar": 70, } if eSwordAbb in ubNo: return ubNo[eSwordAbb] else: return 0 # Import MySword Bibles def importMySwordBible(self, filename): connection = sqlite3.connect(filename) cursor = connection.cursor() query = "SELECT Description, Abbreviation FROM Details" cursor.execute(query) description, abbreviation = cursor.fetchone() abbreviation = abbreviation.replace("-", "") abbreviation = abbreviation.replace("'", "") abbreviation = abbreviation.replace('"', "") abbreviation = abbreviation.replace("+", "x") query = "SELECT * FROM Bible ORDER BY Book, Chapter, Verse" cursor.execute(query) verses = cursor.fetchall() connection.close() self.mySwordBibleToRichFormat(description, abbreviation, verses) self.mySwordBibleToPlainFormat(description, abbreviation, verses) if config.importRtlOT: config.rtlTexts.append(abbreviation) def mySwordBibleToPlainFormat(self, description, abbreviation, verses): verses = [(book, chapter, verse, self.stripMySwordBibleTags(scripture)) for book, chapter, verse, scripture in verses] biblesSqlite = BiblesSqlite() biblesSqlite.importBible(description, abbreviation, verses) del biblesSqlite def mySwordBibleToRichFormat(self, description, abbreviation, verses): formattedBible = os.path.join(config.marvelData, "bibles", "{0}.bible".format(abbreviation)) if os.path.isfile(formattedBible): os.remove(formattedBible) connection = sqlite3.connect(formattedBible) cursor = connection.cursor() statements = ( "CREATE TABLE Bible (Book INT, Chapter INT, Scripture TEXT)", "CREATE TABLE Notes (Book INT, Chapter INT, Verse INT, ID TEXT, Note TEXT)" ) for create in statements: cursor.execute(create) connection.commit() noteList = [] formattedChapters = {} for book, chapter, verse, scripture in verses: scripture, notes = self.convertMySwordBibleTags(scripture) if notes: for counter, note in enumerate(notes): noteList.append((book, chapter, verse, str(counter), note)) if scripture: # fix bible note links scripture = re.sub("{([0-9]+?)}", r"{0}, {1}, {2}, \1".format(book, chapter, verse), scripture) # verse number formatting scripture = self.formatVerseNumber(book, chapter, verse, scripture) if (book, chapter) in formattedChapters: formattedChapters[(book, chapter)] = formattedChapters[(book, chapter)] + scripture else: formattedChapters[(book, chapter)] = scripture insert = "INSERT INTO Notes (Book, Chapter, Verse, ID, Note) VALUES (?, ?, ?, ?, ?)" cursor.executemany(insert, noteList) connection.commit() formattedChapters = [(book, chapter, formattedChapters[(book, chapter)]) for book, chapter in formattedChapters] insert = "INSERT INTO Bible (Book, Chapter, Scripture) VALUES (?, ?, ?)" cursor.executemany(insert, formattedChapters) connection.commit() connection.close() def stripMySwordBibleTags(self, text): if config.importDoNotStripStrongNo: text = re.sub("<W([GH][0-9]+?[a-z]*?)>", r" \1 ", text) if config.importDoNotStripMorphCode: text = re.sub("<WT([^\n<>]*?)>", r" \1 ", text) searchReplace = ( ("<CM>|<CL>|<PI[0-9]*?>|<PF[0-9]*?>|<TS[0-9]*?>.*?<Ts>", " "), ("<sup><a.*?</a></sup>|<RF[^\n<>]*?>.*?<Rf>|<[^\n<>]*?>", ""), (" [ ]+?([^ ])", r" \1"), ) text = text.strip() for search, replace in searchReplace: text = re.sub(search, replace, text) text = text.strip() return text def convertMySwordBibleTags(self, text): searchReplace = ( ("<CI>(<CL>|<CM>)", r"\1"), ("(<CL>|<CM>)<CI>", r"\1"), ("<CI>", " "), ("<CL><CM>|<CM><CL>|<CM>", "<br><br>"), ("<CL>", "<br>"), ("<PI[0-9]*?><PF[0-9]*?>|<PF[0-9]*?><PI[0-9]*?>|<PF[0-9]*?>|<PI[0-9]*?>", "<br>  "), ("<TS[0-9]*?>(.*?)<Ts>", r"<u><b>\1</b></u><br><br>"), ("[ ]+?<br>", "<br>"), ("<br><br><br><br><br>|<br><br><br><br>|<br><br><br>", "<br><br>"), ("</b></u><br><br><u><b>", "</b></u><br><u><b>"), ("<FI>", "<i>"), ("<Fi>", "</i>"), ("<FO>", "<ot>"), ("<Fo>", "</ot>"), ("<FR>", "<woj>"), ("<Fr>", "</woj>"), ("<FU>", "<u>"), ("<Fu>", "</u>"), ("<W([GH][0-9]+?[a-z]*?)>", r"<sup><ref onclick='lex({0}\1{0})'>\1</ref></sup>".format('"')), ("<WT([^\n<>]*?)>", r"<sup><ref onclick='rmac({0}\1{0})'>\1</ref></sup>".format('"')), ("<RX ([0-9]+?)\.([0-9]+?)\.([0-9]+?)>", r"『\1|\2|\3』"), ("<RX ([0-9]+?)\.([0-9]+?)\.([0-9]+?)-[0-9]+?>", r"『\1|\2|\3』"), ("<RX ([0-9]+?)\.([0-9]+?)\.([0-9]+?)-[0-9]+?:[0-9]+?>", r"『\1|\2|\3』"), ("『([0-9]+?)|([0-9]+?)|([0-9]+?)』", self.convertMySwordRxTag), ("<sup>(<RF[^\n<>]*?>)|(<RF[^\n<>]*?>)<sup>", r"\1"), ("<Rf></sup>|</sup><Rf>", "<Rf>"), ) for search, replace in searchReplace: text = re.sub(search, replace, text) text, notes = self.convertMySwordRfTag(text) text = re.sub("</ref><ref", "</ref>; <ref", text) text = re.sub("</ref></sup>[ ]*?<sup><ref", "</ref> <ref", text) text = text.strip() return (text, notes) def convertMySwordRxTag(self, match): b, c, v = match.groups() bookName = BibleVerseParser(config.parserStandarisation).standardAbbreviation[b] return '<ref onclick="bcv({0},{1},{2})">{3} {1}:{2}</ref>'.format(b, c, v, bookName) def convertMySwordRfTag(self, text): notes = re.findall("<RF[^\n<>]*?>(.*?)<Rf>", text) p = re.compile("<RF[^\n<>]*?>.*?<Rf>") s = p.search(text) noteID = 0 while s: text = p.sub("<sup><ref onclick='bn({{0}})'>⊕</ref></sup>".format(noteID), text) noteID += 1 s = p.search(text) return (text, notes) # Import MySword Commentaries def importMySwordCommentary(self, filename): # variable to hold commentary content commentaryContent = [] # connect MySword commentary with sqlite3.connect(filename) as connection: cursor = connection.cursor() # process 2 tables: details, commentary query = "SELECT title, abbreviation, description FROM details" cursor.execute(query) title, abbreviation, description = cursor.fetchone() abbreviation = abbreviation.replace(" ", "_") query = "SELECT DISTINCT book, chapter FROM commentary ORDER BY book, chapter, fromverse, toverse" cursor.execute(query) chapters = cursor.fetchall() # check if table "data" exists; (mainly contain images) query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, ("table",)) tables = cursor.fetchall() tables = [table[0] for table in tables] if "data" in tables: query = "SELECT filename, content FROM data" cursor.execute(query) images = cursor.fetchall() if images: self.exportImageData(abbreviation, images) # format chapters biblesSqlite = BiblesSqlite() for chapter in chapters: b, c = chapter verseList = biblesSqlite.getVerseList(b, c, "kjvbcv") # create a dictionary to hold verse content verseDict = {v: ['<vid id="v{0}.{1}.{2}"></vid>'.format(b, c, v)] for v in verseList} # get verse data of a specific book and chapter query = "SELECT book, chapter, fromverse, toverse, data FROM commentary WHERE book=? AND chapter=? ORDER BY book, chapter, fromverse, toverse" cursor.execute(query, chapter) verses = cursor.fetchall() # format verse content for verse in verses: verseContent = '<ref onclick="bcv({0},{1},{2})"><u><b>{1}:{2}-{3}</b></u></ref><br>{4}'.format(*verse) # convert imageTag verseContent = re.sub(r"<img [^<>]*?src=(['{0}])([^<>]+?)\1[^<>]*?>".format('"'), r"<img src=\1images/{0}/\2\1/>".format(abbreviation.replace(" ", "_")), verseContent) # check if verse number is a standard kjv verse number fromverse = verse[2] item = verseDict.get(fromverse, "not found") if item == "not found": verseDict[fromverse] = ['<vid id="v{0}.{1}.{2}"></vid>'.format(b, c, fromverse), verseContent] else: item.append(verseContent) # sorty verse numbers sortedVerses = sorted(verseDict.keys()) # format chapter text chapterText = "" for sortedVerse in sortedVerses: chapterText += "{}".join(verseDict[sortedVerse]) chapterText = self.fixCommentaryScrolling(chapterText) # add to commentary content commentaryContent.append((b, c, chapterText)) # convert MySword format to UniqueBible format commentaryContent = [(b, c, self.formatMySwordCommentaryVerse(chapterText)) for b, c, chapterText in commentaryContent] # write to a UB commentary file self.createCommentaryModule(abbreviation, title, description, commentaryContent) def formatMySwordCommentaryVerse(self, text): text = re.sub(r"<u><b>([0-9]+?):([0-9]+?)-\2</b></u>", r"<u><b>\1:\2</b></u>", text) text = self.formatNonBibleMySwordModule(text) return text def importMySwordBook(self, filename): *_, module = os.path.split(filename) module = module[:-12] # connect MySword *.bok.mybible file with sqlite3.connect(filename) as connection: cursor = connection.cursor() query = "SELECT title, content FROM journal" cursor.execute(query) content = cursor.fetchall() content = [(chapter, self.formatNonBibleMySwordModule(chapterContent)) for chapter, chapterContent in content] # check if table "data" exists; (mainly contain images) query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, ("table",)) tables = cursor.fetchall() tables = [table[0] for table in tables] if "data" in tables: query = "SELECT filename, content FROM data" cursor.execute(query) images = cursor.fetchall() if images: # rework imgage link in book content content = [(chapter, re.sub(r"<img [^<>]*?src=(['{0}])([^<>]+?)\1[^<>]*?>".format('"'), r"<img src=\1images/{0}/\2\1/>".format(module.replace(" ", "_")), chapterContent)) for chapter, chapterContent in content] # export image data self.exportImageData(module, images) # send data to create a UniqueBible book module self.createBookModule(module, content) def formatNonBibleMySwordModule(self, text): # convert bible reference tag like <a class='bible' href='#bGen 1:1'> text = re.sub(r"<a [^<>]*?href=(['{0}])[#]*?b([0-9]*?[A-Za-z]+? [0-9][^<>]*?)\1>".format('"'), r"<a href='javascript:void(0)' onclick='document.title={0}BIBLE:::\2{0}'>".format('"'), text) # convert bible reference tag like <a class='bible' href='#b1.1.1'> text = re.sub("<a [^<>]*?href=['{0}][#]*?b([0-9]+?)\.([0-9]+?)\.([0-9]+?)[^0-9][^<>]*?>".format('"'), r'<a href="javascript:void(0)" onclick="bcv(\1,\2,\3)">', text) # convert commentary reference tag like <a href='#c-CSBC Gen 1:1'> text = re.sub("<a [^<>]*?href=(['{0}])[#]*?c\-([^ ]+?) ([0-9]*?[A-Za-z]+? [0-9][^<>]*?)\1>".format('"'), r"<a href='javascript:void(0)' onclick='document.title={0}COMMENTARY:::\2:::\3{0}'>".format('"'), text) # convert commentary reference tag like <a href='#cGen 1:1'> text = re.sub(r"<a [^<>]*?href=(['{0}])[#]*?c([0-9]*?[A-Za-z]+? [0-9][^<>]*?)\1>".format('"'), r"<a href='javascript:void(0)' onclick='document.title={0}COMMENTARY:::\2{0}'>".format('"'), text) # convert commentary reference tag like <a href='#c1.1.1'> text = re.sub("<a [^<>]*?href=['{0}][#]*?c([0-9]+?)\.([0-9]+?)\.([0-9]+?)[^0-9][^<>]*?>".format('"'), r'<a href="javascript:void(0)" onclick="cbcv(\1,\2,\3)">', text) # convert Strong's no tag, e.g. <a class='strong' href='#sH1'>H1</a> text = re.sub(r"<a [^<>]*?href=(['{0}])[#]*?s([HG][0-9a-z\.]+?)\1[^<>]*?>".format('"'), r'<a href="javascript:void(0)" onclick="lex({0}\2{0})">'.format("'"), text) # return formatted text return text # Import MyBible Bibles def importMyBibleBible(self, filename): connection = sqlite3.connect(filename) cursor = connection.cursor() query = "SELECT value FROM info WHERE name = 'description'" cursor.execute(query) description = cursor.fetchone()[0] inputFilePath, inputFileName = os.path.split(filename) originalModuleName = inputFileName[:-8] abbreviation = originalModuleName abbreviation = abbreviation.replace("-", "") abbreviation = abbreviation.replace("'", "") abbreviation = abbreviation.replace('"', "") abbreviation = abbreviation.replace("+", "x") query = "SELECT value FROM info WHERE name = 'strong_numbers_prefix'" cursor.execute(query) strong_numbers_prefix = cursor.fetchone() if strong_numbers_prefix: strong_numbers_prefix = strong_numbers_prefix[0] else: strong_numbers_prefix = "" # check existing table names query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, ("table",)) tables = cursor.fetchall() tables = [table[0] for table in tables] stories = [] if "stories" in tables: try: query = "SELECT book_number, chapter, verse, title FROM stories ORDER BY book_number, chapter, verse" cursor.execute(query) except: query = "SELECT book_number, chapter, verse, text FROM stories ORDER BY book_number, chapter, verse" cursor.execute(query) stories = cursor.fetchall() query = "SELECT * FROM verses ORDER BY book_number, chapter, verse" cursor.execute(query) verses = cursor.fetchall() if verses: verses = [(self.convertMyBibleBookNo(mbBook), mbChapter, mbVerse, mbText) for mbBook, mbChapter, mbVerse, mbText in verses] # check if notes are available in commentary format noteFile = os.path.join(inputFilePath, "{0}.commentaries.SQLite3".format(originalModuleName)) if os.path.isfile(noteFile): noteConnection = sqlite3.connect(noteFile) noteCursor = noteConnection.cursor() query = "SELECT book_number, chapter_number_from, verse_number_from, marker, text FROM commentaries" noteCursor.execute(query) notes = noteCursor.fetchall() self.myBibleBibleToRichFormat(description, abbreviation, verses, notes, strong_numbers_prefix, stories) noteConnection.close() else: self.myBibleBibleToRichFormat(description, abbreviation, verses, [], strong_numbers_prefix, stories) self.myBibleBibleToPlainFormat(description, abbreviation, verses, strong_numbers_prefix) connection.close() if config.importRtlOT: config.rtlTexts.append(abbreviation) def storiesToTitles(self, stories): titles = {} for story in stories: b, c, v, title = story if title: b = self.convertMyBibleBookNo(b) title = re.sub("<x>(.*?)</x>", self.convertMyBibleXRef, title) title = "<u><b>{0}</b></u>".format(title) item = titles.get((b, c, v), "not found") if item == "not found": titles[(b, c, v)] = [title] else: item.append(title) titles = {key: "<br>".join(titles[key]) for key in titles} return titles def convertMyBibleXRef(self, match): value = match.group(0) mbBookNoString, reference = match.group(1).split(" ", 1) if mbBookNoString and reference: ubBookNoString = str(self.convertMyBibleBookNo(int(mbBookNoString))) ubBookName = BibleVerseParser(config.parserStandarisation).standardAbbreviation[ubBookNoString] value = "<ref onclick='document.title={0}BIBLE:::{1} {2}{0}'>{1} {2}</ref>".format('"', ubBookName, reference) return value def myBibleBibleToPlainFormat(self, description, abbreviation, verses, strong_numbers_prefix): verses = [(book, chapter, verse, self.stripMyBibleBibleTags(scripture, book, strong_numbers_prefix)) for book, chapter, verse, scripture in verses] biblesSqlite = BiblesSqlite() biblesSqlite.importBible(description, abbreviation, verses) del biblesSqlite def myBibleBibleToRichFormat(self, description, abbreviation, verses, notes, strong_numbers_prefix, stories): formattedBible = os.path.join(config.marvelData, "bibles", "{0}.bible".format(abbreviation)) if os.path.isfile(formattedBible): os.remove(formattedBible) connection = sqlite3.connect(formattedBible) cursor = connection.cursor() statements = ( "CREATE TABLE Bible (Book INT, Chapter INT, Scripture TEXT)", "CREATE TABLE Notes (Book INT, Chapter INT, Verse INT, ID TEXT, Note TEXT)" ) for create in statements: cursor.execute(create) connection.commit() if stories: stories = self.storiesToTitles(stories) noteList = [] formattedChapters = {} for book, chapter, verse, scripture in verses: if scripture: # fix sub-heading(s) if (book, chapter, verse) in stories: if verse == 1: scripture = "{0}<br><br>{1}".format(stories[(book, chapter, verse)], scripture) else: scripture = "<br><br>{0}<br><br>{1}".format(stories[(book, chapter, verse)], scripture) scripture = self.convertMyBibleBibleTags(scripture, book, strong_numbers_prefix) # fix bible note links if notes: scripture = re.sub("<f>([^\n<>]+?)</f>", r"<sup><ref onclick='bn({0}, {1}, {2}, {3}\1{3})'>⊕</ref></sup>".format(book, chapter, verse, '"'), scripture) # verse number formatting scripture = self.formatVerseNumber(book, chapter, verse, scripture) if (book, chapter) in formattedChapters: formattedChapters[(book, chapter)] = formattedChapters[(book, chapter)] + scripture else: formattedChapters[(book, chapter)] = scripture if notes: insert = "INSERT INTO Notes (Book, Chapter, Verse, ID, Note) VALUES (?, ?, ?, ?, ?)" notes = [(self.convertMyBibleBookNo(book), chapter, verse, id, self.formatNonBibleMyBibleModule(note, abbreviation)) for book, chapter, verse, id, note in notes] cursor.executemany(insert, notes) connection.commit() formattedChapters = [(book, chapter, formattedChapters[(book, chapter)]) for book, chapter in formattedChapters] insert = "INSERT INTO Bible (Book, Chapter, Scripture) VALUES (?, ?, ?)" cursor.executemany(insert, formattedChapters) connection.commit() connection.close() def stripMyBibleBibleTags(self, text, book, strong_numbers_prefix): if text: if config.importDoNotStripStrongNo: if book >= 40 or strong_numbers_prefix == "G": text = re.sub("<S>([0-9]+?[a-z]*?)</S>", r" G\1 ", text) else: text = re.sub("<S>([0-9]+?[a-z]*?)</S>", r" H\1 ", text) else: text = re.sub("<S>([0-9]+?[a-z]*?)</S>", "", text) if config.importDoNotStripMorphCode: text = re.sub("<m>([^\n<>]*?)</m>", r" \1 ", text) else: text = re.sub("<m>([^\n<>]*?)</m>", "", text) searchReplace = ( ("<pb/>|<h>.*?</h>|<t>", " "), ("<f>.*?</f>|<[^\n<>]*?>", ""), (" [ ]+?([^ ])", r" \1"), ) text = text.strip() for search, replace in searchReplace: text = re.sub(search, replace, text) text = text.strip() else: text = "" return text def convertMyBibleBibleTags(self, text, book, strong_numbers_prefix): if config.importInterlinear: wordTag = "heb" if book >= 40 or strong_numbers_prefix == "G": wordTag = "grk" text = re.sub("<br/>|<br>", "@", text) text = re.sub("</n>([ ]*?)<n>", r"\1", text) # convert format like "The book <n>Βίβλος</n><S>976</S><m>N-NSF</m>" text = re.sub("([^@]+?)<n>([^<>]+?)</n>(<S>[^<>]+?</S>)(<m>[^<>]+?</m>)", r'<div class="int"><wgloss>\1</wgloss>@<wform><{0}>\2</{0}></wform>@\3@\4</div> '.format(wordTag), text) searchPattern = '</div> ([^@]+?)<n>([^<>]+?)</n>' p = re.compile(searchPattern, flags=re.M) while p.search(text): text = re.sub(searchPattern, r'</div> <div class="int"><wgloss>\1</wgloss>@<wform><{0}>\2</{0}></wform>@ @ </div> '.format(wordTag), text) searchPattern = '(<div class="int"><wgloss>)(<div class="int">.*?</div> )' p = re.compile(searchPattern, flags=re.M) while p.search(text): text = re.sub(searchPattern, r'\2\1', text) # convert format like "Βίβλος<S>976</S><m>N-NSF</m> <n>The book</n>" text = re.sub("([^@]+?)(<S>[^<>]+?</S>)(<m>[^<>]+?</m>)[ ]*?<n>([^@]+?)</n>", r'<div class="int"><wform><{0}>\1</{0}></wform>@\2@\3@<wgloss>\4</wgloss></div> '.format(wordTag), text) # deal with original words without corresponding translation searchPattern = '<div class="int"><wform><{0}>([^@]+?)(<S>[^<>]+?</S>)(<m>[^<>]+?</m>)'.format(wordTag) p = re.compile(searchPattern, flags=re.M) while p.search(text): text = re.sub(searchPattern, r'<div class="int"><wform><{0}>\1</{0}></wform>@\2@\3@ </div> <div class="int"><wform><{0}>'.format(wordTag), text) if book >= 40 or strong_numbers_prefix == "G": text = re.sub("<S>([0-9]+?[a-z]*?)</S>", r"<sup><ref onclick='lex({0}G\1{0})'>G\1</ref></sup>".format('"'), text) else: text = re.sub("<S>([0-9]+?[a-z]*?)</S>", r"<sup><ref onclick='lex({0}H\1{0})'>H\1</ref></sup>".format('"'), text) searchReplace = ( ("<m>([^\n<>]*?)</m>", r"<sup><ref onclick='rmac({0}\1{0})'>\1</ref></sup>".format('"')), ("<J>", "<woj>"), ("</J>", "</woj>"), ("<e>", "<mbe>"), ("</e>", "</mbe>"), ("<n>", "<mbn>"), ("</n>", "</mbn>"), ("<t>", "<br>  "), ("</t>", "<br>"), ("<h>(.*?)</h>", r"<u><b>\1</b></u><br><br>"), ("<br/>|@", "<br>"), ("[ ]+?<br>", "<br>"), ("<br><br><br><br><br>|<br><br><br><br>|<br><br><br>", "<br><br>"), ("</b></u><br><br><u><b>", "</b></u><br><u><b>"), ("</ref><ref", "</ref>; <ref"), ("</ref></sup>[ ]*?<sup><ref", "</ref> <ref"), ) for search, replace in searchReplace: text = re.sub(search, replace, text) text = text.strip() return text # Import MyBible Commentaries def importMyBibleCommentary(self, filename): # variable to hold commentary content commentaryContent = [] # connect MySword commentary with sqlite3.connect(filename) as connection: cursor = connection.cursor() # draw data from two tables: info, commentaries # table: info query = "SELECT value FROM info WHERE name = 'description'" cursor.execute(query) description = cursor.fetchone()[0] title = description *_, inputFileName = os.path.split(filename) abbreviation = inputFileName[:-21] abbreviation = re.sub("^(.*?)\-c$", r"\1", abbreviation) # table: commentaries # 6 columns in commentaries: book_number, chapter_number_from, verse_number_from, chapter_number_to, verse_number_to, text query = "SELECT DISTINCT book_number, chapter_number_from FROM commentaries ORDER BY book_number, chapter_number_from, verse_number_from, chapter_number_to, verse_number_to" cursor.execute(query) chapters = cursor.fetchall() # format chapters biblesSqlite = BiblesSqlite() for chapter in chapters: b, c = chapter b = self.convertMyBibleBookNo(b) # get standard kjv verse list for a chapter verseList = biblesSqlite.getVerseList(b, c, "kjvbcv") # use a dictionary to hold verse content verseDict = {v: ['<vid id="v{0}.{1}.{2}"></vid>'.format(b, c, v)] for v in verseList} # get verse data query = "SELECT book_number, chapter_number_from, verse_number_from, chapter_number_to, verse_number_to, text FROM commentaries WHERE book_number=? AND chapter_number_from=? ORDER BY book_number, chapter_number_from, verse_number_from, chapter_number_to, verse_number_to" cursor.execute(query, chapter) verses = cursor.fetchall() # format verses for verse in verses: book_number, chapter_number_from, verse_number_from, chapter_number_to, verse_number_to, text = verse book_number = self.convertMyBibleBookNo(book_number) verseContent = '<ref onclick="bcv({0},{1},{2})"><u><b>{1}:{2}-{3}:{4}</b></u></ref><br>{5}'.format(book_number, chapter_number_from, verse_number_from, chapter_number_to, verse_number_to, text) # check fromverse if it is included in a standard kjv verse list # convert to integer below, as some modules are found containing string, probably by mistake fromverse = int(verse_number_from) item = verseDict.get(fromverse, "not found") if item == "not found": verseDict[fromverse] = ['<vid id="v{0}.{1}.{2}"></vid>'.format(b, c, fromverse), verseContent] else: item.append(verseContent) # sort verse numbers in a chapter sortedVerses = sorted(verseDict.keys()) # combine verse content into a single chapter chapterText = "" for sortedVerse in sortedVerses: chapterText += "{}".join(verseDict[sortedVerse]) # fix scrolling for commentary modules chapterText = self.fixCommentaryScrolling(chapterText) # add to commentary content commentaryContent.append((b, c, chapterText)) # convert MyBible format to UniqueBible format commentaryContent = [(b, c, self.formatMyBibleCommentaryVerse(chapterText, abbreviation)) for b, c, chapterText in commentaryContent] # write to a UB commentary file self.createCommentaryModule(abbreviation, title, description, commentaryContent) def formatMyBibleCommentaryVerse(self, text, abbreviation): text = re.sub(r"<u><b>([0-9]+?:[0-9]+?)-\1</b></u>", r"<u><b>\1</b></u>", text) text = re.sub(r"<u><b>([0-9]+?):([0-9]+?)-\1:([0-9]+?)</b></u>", r"<u><b>\1:\2-\3</b></u>", text) text = text.replace("-None:None</b></u></ref><br>", "</b></u></ref><br>") text = text.replace(":0</b></u></ref><br>", "</b></u></ref><br>") text = text.replace(":0-0</b></u></ref><br>", "</b></u></ref><br>") # deal with internal links like <a class="contents" href="C:@1002 0:0"> text = re.sub("<a [^<>]*?href=['{0}]C:@([0-9]+?) ([\-0-9:]+?)[^\-0-9:][^<>]*?>".format('"'), self.formatMyBibleCommentaryLink, text) text = self.formatNonBibleMyBibleModule(text, abbreviation) return text def formatMyBibleCommentaryLink(self, match): bookNo, cv = match.groups() standardAbbreviation = BibleVerseParser(config.parserStandarisation).standardAbbreviation if bookNo in standardAbbreviation: return "<a href='javascript:void(0)' onclick='document.title={0}COMMENTARY:::{1} {2}{0}'>".format('"', standardAbbreviation[bookNo], cv) else: return "<a href='javascript:void(0)' onclick='document.title={0}COMMENTARY2:::{1}.{2}{0}'>".format('"', bookNo, cv.replace(":", ".")) def formatNonBibleMyBibleModule(self, text, abbreviation): searchReplace = ( ("<a [^<>]*?href=['{0}]B:([0-9]+?) ([0-9]+?):([0-9]+?)[^0-9][^<>]*?>".format('"'), r'<a href="javascript:void(0)" onclick="cr(\1,\2,\3)">'), ("<a [^<>]*?href=['{0}]B:([0-9]+?) ([0-9]+?)[^0-9:][^<>]*?>".format('"'), r'<a href="javascript:void(0)" onclick="cr(\1,\2,1)">'), ("<a [^<>]*?href=['{0}]B:([0-9]+?)[^0-9: ][^<>]*?>".format('"'), r'<a href="javascript:void(0)" onclick="cr(\1,1,1)">'), ("<a [^<>]*?href=['{0}]S:([GH][0-9]+?)[^0-9][^<>]*?>".format('"'), r"<a href='javascript:void(0)' onclick='lex({0}\1{0})'>".format('"')), ("<a [^<>]*?href=['{0}]S:([^'{0}<>]*?)['{0}]>".format('"'), r"<a href='javascript:void(0)' onclick='searchThirdDictionary({0}{1}{0}, {0}\1{0})'>".format('"', abbreviation)), ) for search, replace in searchReplace: text = re.sub(search, replace, text) return text def convertMyBibleBookNo(self, myBibleNo): # UB's book numbers: https://github.com/eliranwong/bible-verse-parser/blob/master/abbreviations/SBL-style-abbreviation.xlsx # official MyBible's references: https://mybible.zone/code-eng.php # notes from Oleg # 2 Ésdras (in Russian Orthodox Bible) = Έσδράς Α' (in Septuaguint) = 1 Esdras (English) # 3 Esdras (Russian) = 4 Esdras (Vulgata) = 2 Esdras (English) # Five extra non-standard numbers in Oleg's Barach module # 326 Susanna > 75 # 71 Judges > 7 # 171 Tobit > 88 # 235 Psalms of Solomon > 90 # 245 Odes > 91 # 341 Daniel > 71 # 346 Bel and Dragon > 73 # 61 Joshua > 6 # customised numbers used in some Eliran Wong's MyBible modules # e.g. https://github.com/eliranwong/LXX-Rahlfs-1935/tree/master/11_end-users_files/MyBible # Prayer of Manasseh = 469 > 85 # GreekEsth = 191 > 78 # Psalm 151 = 231 > 86 # Psalms of Solomon = 232 > 90 # Odes = 800 > 91 ubNo = { 10: 1, 20: 2, 30: 3, 40: 4, 50: 5, 60: 6, 61: 6, # Oleg's Barach module 70: 7, 71: 7, # Oleg's Barach module 80: 8, 90: 9, 100: 10, 110: 11, 120: 12, 130: 13, 140: 14, 150: 15, 160: 16, 190: 17, 220: 18, 230: 19, 240: 20, 250: 21, 260: 22, 290: 23, 300: 24, 310: 25, 330: 26, 340: 27, 350: 28, 360: 29, 370: 30, 380: 31, 390: 32, 400: 33, 410: 34, 420: 35, 430: 36, 440: 37, 450: 38, 460: 39, 470: 40, 480: 41, 490: 42, 500: 43, 510: 44, 520: 45, 530: 46, 540: 47, 550: 48, 560: 49, 570: 50, 580: 51, 590: 52, 600: 53, 610: 54, 620: 55, 630: 56, 640: 57, 650: 58, 660: 59, 670: 60, 680: 61, 690: 62, 700: 63, 710: 64, 720: 65, 730: 66, 165: 76, 468: 77, 170: 88, 171: 88, # Oleg's Barach module 180: 80, 270: 89, 280: 87, 305: 72, 315: 79, 320: 70, 325: 75, 326: 75, # Oleg's Barach module 345: 73, 346: 73, # Oleg's Barach module 462: 81, 464: 82, 466: 83, 467: 84, 780: 92, 790: 85, 469: 85, # Eliran's customised no. 191: 78, # Eliran's customised no. 231: 86, # Eliran's customised no. 232: 90, # Eliran's customised no. 235: 90, # Oleg's Barach module 800: 91, # Eliran's customised no. 245: 91, # Oleg's Barach module 341: 71, # Oleg's Barach module } if myBibleNo in ubNo: return ubNo[myBibleNo] else: # use source number if a mapped number is not found. return myBibleNo # Read BibleBento Plus Json files def readJsonFile(self, inputFile): try: f = open(inputFile, "r", encoding="utf-8") newData = f.read() f.close() newData = json.loads(newData) return newData except: print("File not found! Please make sure if you enter filename correctly and try again.") return [] def convertBibleBentoPlusTag(self, text): searchReplace = ( ("href=['{0}]ref://([0-9]+?)\.([0-9]+?)\.([0-9]+?);['{0}]".format('"'), r'href="javascript:void(0)" onclick="bcv(\1,\2,\3)"'), ("href=['{0}]lexi://(.*?)['{0}]".format('"'), r'href="javascript:void(0)" onclick="lex({0}\1{0})"'.format("'")), ("href=['{0}]gk://(.*?)['{0}]".format('"'), r'href="javascript:void(0)" onclick="lex({0}gk\1{0})"'.format("'")), ) for search, replace in searchReplace: text = re.sub(search, replace, text) return text def importBBPlusLexiconInAFolder(self, folder): files = [filename for filename in os.listdir(folder) if os.path.isfile(os.path.join(folder, filename)) and not re.search("^[\._]", filename)] validFiles = [filename for filename in files if re.search('^Dict.*?\.json$', filename)] if validFiles: for filename in validFiles: module = filename[4:-5] jsonList = self.readJsonFile(os.path.join(folder, filename)) jsonList = [(jsonEntry["top"], self.convertBibleBentoPlusTag(jsonEntry["def"])) for jsonEntry in jsonList] self.createLexiconModule(module, jsonList) return True def importBBPlusDictionaryInAFolder(self, folder): files = [filename for filename in os.listdir(folder) if os.path.isfile(os.path.join(folder, filename)) and not re.search("^[\._]", filename)] validFiles = [filename for filename in files if re.search('^Dict.*?\.json$', filename)] if validFiles: for filename in validFiles: module = filename[4:-5] jsonList = self.readJsonFile(os.path.join(folder, filename)) jsonList = [(jsonEntry["top"], jsonEntry["def"]) for jsonEntry in jsonList] self.createDictionaryModule(module, jsonList) return True def convertOldLexiconData(self): database = os.path.join(config.marvelData, "data", "lexicon.data") connection = sqlite3.connect(database) cursor = connection.cursor() t = ("table",) query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, t) versions = cursor.fetchall() exclude = ("Details") lexiconList = [version[0] for version in versions if not version[0] in exclude] for lexicon in lexiconList: query = "SELECT EntryID, Information FROM {0}".format(lexicon) cursor.execute(query) content = cursor.fetchall() self.createLexiconModule(lexicon, content) connection.close() def convertOldBookData(self): database = os.path.join(config.marvelData, "data", "book.data") connection = sqlite3.connect(database) cursor = connection.cursor() t = ("table",) query = "SELECT name FROM sqlite_master WHERE type=? ORDER BY name" cursor.execute(query, t) versions = cursor.fetchall() exclude = ("Details") bookList = [version[0] for version in versions if not version[0] in exclude] for book in bookList: query = "SELECT Topic, Note FROM {0}".format(book) cursor.execute(query) content = cursor.fetchall() self.createBookModule(book, content) connection.close() def importESwordBook(self, filename): *_, module = os.path.split(filename) module = module[:-5] # connect e-Sword *.refi file connection = sqlite3.connect(filename) cursor = connection.cursor() query = "SELECT Chapter, Content FROM Reference" cursor.execute(query) content = cursor.fetchall() content = [(chapter, self.formatNonBibleESwordModule(chapterContent)) for chapter, chapterContent in content] self.createBookModule(module, content) connection.close() class ThirdPartyDictionary: def __init__(self, moduleTuple): self.module, self.fileExtension = moduleTuple self.moduleList = self.getModuleList() if self.module in self.moduleList: self.database = os.path.join("thirdParty", "dictionaries", "{0}{1}".format(self.module, self.fileExtension)) self.connection = sqlite3.connect(self.database) self.cursor = self.connection.cursor() def __del__(self): self.connection.close() def getModuleList(self): moduleFolder = os.path.join("thirdParty", "dictionaries") bbPlusDictionaries = [f[:-8] for f in os.listdir(moduleFolder) if os.path.isfile(os.path.join(moduleFolder, f)) and f.endswith(".dic.bbp") and not re.search("^[\._]", f)] mySwordDictionaries = [f[:-12] for f in os.listdir(moduleFolder) if os.path.isfile(os.path.join(moduleFolder, f)) and f.endswith(".dct.mybible") and not re.search("^[\._]", f)] eSwordDictionaries = [f[:-5] for f in os.listdir(moduleFolder) if os.path.isfile(os.path.join(moduleFolder, f)) and f.endswith(".dcti") and not re.search("^[\._]", f)] eSwordLexicons = [f[:-5] for f in os.listdir(moduleFolder) if os.path.isfile(os.path.join(moduleFolder, f)) and f.endswith(".lexi") and not re.search("^[\._]", f)] myBibleDictionaries = [f[:-19] for f in os.listdir(moduleFolder) if os.path.isfile(os.path.join(moduleFolder, f)) and f.endswith(".dictionary.SQLite3") and not re.search("^[\._]", f)] moduleList = set(bbPlusDictionaries + mySwordDictionaries + eSwordDictionaries + eSwordLexicons + myBibleDictionaries) moduleList = sorted(list(moduleList)) return moduleList def search(self, entry): if not self.database: return "INVALID_COMMAND_ENTERED" else: exactMatch = self.getExactWord(entry) similarMatch = self.getSimilarWord(entry) action = "searchThirdDictionary(this.value, \"{0}\")".format(entry) optionList = [(m, m) for m in self.moduleList] selectList = self.formatSelectList(action, optionList) config.thirdDictionary = self.module return "<h2>Search <span style='color: brown;'>{0}</span> for <span style='color: brown;'>{1}</span></h2><p>{4}</p><p><b>Exact match:</b><br><br>{2}</p><p><b>Partial match:</b><br><br>{3}".format(self.module, entry, exactMatch, similarMatch, selectList) def formatSelectList(self, action, optionList): selectForm = "<select onchange='{0}'>".format(action) for value, description in optionList: if value == self.module: selectForm += "<option value='{0}' selected='selected'>{1}</option>".format(value, description) else: selectForm += "<option value='{0}'>{1}</option>".format(value, description) selectForm += "</select>" return selectForm def getExactWord(self, entry): if not self.database: return "INVALID_COMMAND_ENTERED" else: getDictionaryData = { ".dic.bbp": self.getBibleBentoPlusDicExactWord, ".dcti": self.getESwordDicExactWord, ".lexi": self.getESwordLexExactWord, ".dct.mybible": self.getMySwordExactWord, ".dictionary.SQLite3": self.getMyBibleExactWord, } return getDictionaryData[self.fileExtension](entry) def getSimilarWord(self, entry): if not self.database: return "INVALID_COMMAND_ENTERED" else: getDictionaryData = { ".dic.bbp": self.getBibleBentoPlusDicSimilarWord, ".dcti": self.getESwordDicSimilarWord, ".lexi": self.getESwordLexSimilarWord, ".dct.mybible": self.getMySwordSimilarWord, ".dictionary.SQLite3": self.getMyBibleSimilarWord, } return getDictionaryData[self.fileExtension](entry) def getData(self, entry): if not self.database: return "INVALID_COMMAND_ENTERED" else: getDictionaryData = { ".dic.bbp": self.getBibleBentoPlusDicDictionaryData, ".dcti": self.getESwordDicDictionaryData, ".lexi": self.getESwordLexDictionaryData, ".dct.mybible": self.getMySwordDictionaryData, ".dictionary.SQLite3": self.getMyBibleDictionaryData, } return getDictionaryData[self.fileExtension](entry) # BibleBentoPlus dictionaries def getBibleBentoPlusDicExactWord(self, entry): query = "SELECT Topic FROM Dictionary WHERE Topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: return "<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, content[0]) def getBibleBentoPlusDicSimilarWord(self, entry): query = "SELECT Topic FROM Dictionary WHERE Topic LIKE ? AND Topic != ?" self.cursor.execute(query, ("%{0}%".format(entry), entry)) contentList = ["<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, m[0]) for m in self.cursor.fetchall()] if not contentList: return "[not found]" else: return "<br>".join(contentList) def getBibleBentoPlusDicDictionaryData(self, entry): query = "SELECT Definition FROM Dictionary WHERE Topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: action = "searchThirdDictionary(this.value, \"{0}\")".format(entry) optionList = [(m, m) for m in self.moduleList] selectList = self.formatSelectList(action, optionList) config.thirdDictionary = self.module content = Converter().convertBibleBentoPlusTag(content[0]) return "<h2>{0}</h2><p>{1}</p><p>{2}</p>".format(entry, selectList, content) # e-Sword dictionaries def getESwordDicExactWord(self, entry): query = "SELECT Topic FROM Dictionary WHERE Topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: return "<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, content[0]) def getESwordDicSimilarWord(self, entry): query = "SELECT Topic FROM Dictionary WHERE Topic LIKE ? AND Topic != ?" self.cursor.execute(query, ("%{0}%".format(entry), entry)) contentList = ["<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, m[0]) for m in self.cursor.fetchall()] if not contentList: return "[not found]" else: return "<br>".join(contentList) def getESwordDicDictionaryData(self, entry): query = "SELECT Definition FROM Dictionary WHERE Topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: action = "searchThirdDictionary(this.value, \"{0}\")".format(entry) optionList = [(m, m) for m in self.moduleList] selectList = self.formatSelectList(action, optionList) config.thirdDictionary = self.module content = Converter().formatNonBibleESwordModule(content[0]) return "<h2>{0}</h2><p>{1}</p><p>{2}</p>".format(entry, selectList, content) # e-Sword lexicon def getESwordLexExactWord(self, entry): query = "SELECT Topic FROM Lexicon WHERE Topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: return "<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, content[0]) def getESwordLexSimilarWord(self, entry): query = "SELECT Topic FROM Lexicon WHERE Topic LIKE ? AND Topic != ?" self.cursor.execute(query, ("%{0}%".format(entry), entry)) contentList = ["<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, m[0]) for m in self.cursor.fetchall()] if not contentList: return "[not found]" else: return "<br>".join(contentList) def getESwordLexDictionaryData(self, entry): query = "SELECT Definition FROM Lexicon WHERE Topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: action = "searchThirdDictionary(this.value, \"{0}\")".format(entry) optionList = [(m, m) for m in self.moduleList] selectList = self.formatSelectList(action, optionList) config.thirdDictionary = self.module content = Converter().formatNonBibleESwordModule(content[0]) return "<h2>{0}</h2><p>{1}</p><p>{2}</p>".format(entry, selectList, content) # MySword dictionaries def getMySwordExactWord(self, entry): query = "SELECT word FROM dictionary WHERE word = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: return "<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, content[0]) def getMySwordSimilarWord(self, entry): query = "SELECT word FROM dictionary WHERE word LIKE ? AND word != ?" self.cursor.execute(query, ("%{0}%".format(entry), entry)) contentList = ["<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, m[0]) for m in self.cursor.fetchall()] if not contentList: return "[not found]" else: return "<br>".join(contentList) def getMySwordDictionaryData(self, entry): query = "SELECT data FROM dictionary WHERE word = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: action = "searchThirdDictionary(this.value, \"{0}\")".format(entry) optionList = [(m, m) for m in self.moduleList] selectList = self.formatSelectList(action, optionList) config.thirdDictionary = self.module content = content[0] content = re.sub(r"<a [^<>]*?href=(['{0}])[#]*?[ds]([^\n<>]*?)\1>(.*?)</a>".format('"'), r"<ref onclick='openThirdDictionary({1}{0}{1}, {1}\2{1})'>\3</ref>".format(self.module, '"'), content) content = Converter().formatNonBibleMySwordModule(content) return "<h2>{0}</h2><p>{1}</p><p>{2}</p>".format(entry, selectList, content) # MyBible Dictionaries def getMyBibleExactWord(self, entry): query = "SELECT topic FROM dictionary WHERE topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: return "<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, content[0]) def getMyBibleSimilarWord(self, entry): query = "SELECT topic FROM dictionary WHERE topic LIKE ? AND topic != ?" self.cursor.execute(query, ("%{0}%".format(entry), entry)) contentList = ["<ref onclick='openThirdDictionary(\"{0}\", \"{1}\")'>{1}</ref>".format(self.module, m[0]) for m in self.cursor.fetchall()] if not contentList: return "[not found]" else: return "<br>".join(contentList) def getMyBibleDictionaryData(self, entry): query = "SELECT definition FROM dictionary WHERE topic = ?" self.cursor.execute(query, (entry,)) content = self.cursor.fetchone() if not content: return "[not found]" else: action = "searchThirdDictionary(this.value, \"{0}\")".format(entry) optionList = [(m, m) for m in self.moduleList] selectList = self.formatSelectList(action, optionList) config.thirdDictionary = self.module content = Converter().formatNonBibleMyBibleModule(content[0], self.module) return "<h2>{0}</h2><p>{1}</p><p>{2}</p>".format(entry, selectList, content)