waha-shared 1.0.305 → 1.0.307
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/areas/areas.json +50 -48
- package/dist/data/areas/areas.schema.json +2 -2
- package/dist/data/areas/areas.zod.d.ts +1 -1
- package/dist/data/areas/areas.zod.js +1 -1
- package/dist/data/areas/index.d.ts +1 -1
- package/dist/data/bibleAudios/bibleAudios.json +581 -314
- package/dist/data/bibleAudios/bibleAudios.schema.json +17 -8
- package/dist/data/bibleAudios/bibleAudios.zod.d.ts +43 -2
- package/dist/data/bibleAudios/bibleAudios.zod.js +16 -7
- package/dist/data/bibleAudios/index.d.ts +2 -1
- package/dist/data/bibleBooks/bibleBooks.json +792 -790
- package/dist/data/bibleStatuses/bibleStatuses.json +7981 -8480
- package/dist/data/bibleStatuses/bibleStatuses.schema.json +6 -0
- package/dist/data/bibleStatuses/bibleStatuses.zod.d.ts +1 -0
- package/dist/data/bibleStatuses/bibleStatuses.zod.js +4 -0
- package/dist/data/bibleStatuses/index.d.ts +1 -0
- package/dist/data/bibleTexts/bibleTexts.json +269 -184
- package/dist/data/bibleTexts/bibleTexts.schema.json +7 -0
- package/dist/data/bibleTexts/bibleTexts.zod.d.ts +28 -0
- package/dist/data/bibleTexts/bibleTexts.zod.js +10 -3
- package/dist/data/bibleTexts/index.d.ts +2 -0
- package/dist/data/clones/clones.json +2 -0
- package/dist/data/countries/countries.json +480 -480
- package/dist/data/countriesAndLanguages/countriesAndLanguages.json +6812 -6810
- package/dist/data/crowdinLanguages/crowdinLanguages.json +1440 -1438
- package/dist/data/crowdinLanguages/crowdinLanguages.schema.json +3 -3
- package/dist/data/crowdinLanguages/crowdinLanguages.zod.d.ts +2 -2
- package/dist/data/crowdinLanguages/crowdinLanguages.zod.js +2 -2
- package/dist/data/crowdinLanguages/index.d.ts +2 -2
- package/dist/data/curriculumFoundations/curriculumFoundations.json +86 -69
- package/dist/data/curriculumQuestions/curriculumQuestions.json +194 -192
- package/dist/data/curriculumTopics/curriculumTopics.json +51 -8
- package/dist/data/dblAudioLicenses/dblAudioLicenses.json +36 -7
- package/dist/data/dblTextLicenses/dblTextLicenses.json +4 -4
- package/dist/data/firebase.d.ts +1 -0
- package/dist/data/firebase.js +4 -0
- package/dist/data/iosVoiceOverLanguages/iosVoiceOverLanguages.json +1 -1
- package/dist/data/iso6933LanguageCodes/iso6933LanguageCodes.json +1 -1
- package/dist/data/languages/index.d.ts +20 -10
- package/dist/data/languages/languages.json +2983 -2008
- package/dist/data/languages/languages.schema.json +93 -47
- package/dist/data/languages/languages.zod.d.ts +93 -30
- package/dist/data/languages/languages.zod.js +59 -37
- package/dist/data/lessonPauses/index.d.ts +0 -1
- package/dist/data/lessonPauses/lessonPauses.json +2 -3
- package/dist/data/lessonPauses/lessonPauses.schema.json +1 -11
- package/dist/data/lessonPauses/lessonPauses.zod.d.ts +0 -1
- package/dist/data/lessonPauses/lessonPauses.zod.js +0 -3
- package/dist/data/mediaDurations/mediaDurations.json +35291 -6076
- package/dist/data/mediaDurations/mediaDurations.schema.json +1 -1
- package/dist/data/mediaDurations/mediaDurations.zod.js +1 -1
- package/dist/data/notification/index.d.ts +1 -1
- package/dist/data/notification/notification.json +93 -169
- package/dist/data/phoneLanguages/phoneLanguages.json +637 -635
- package/dist/data/questions/questions.json +149 -147
- package/dist/data/releaseNotes/releaseNotes.json +126 -124
- package/dist/data/screenshots/screenshots.json +1 -1
- package/dist/data/scripts/scripts.json +6 -1
- package/dist/data/sets/index.d.ts +3 -3
- package/dist/data/sets/sets.json +1770 -480
- package/dist/data/sets/sets.schema.json +1 -1
- package/dist/data/sets/sets.zod.d.ts +3 -3
- package/dist/data/sets/sets.zod.js +3 -6
- package/dist/data/translationsApp/index.d.ts +1 -0
- package/dist/data/translationsApp/translationsApp.json +1836 -1628
- package/dist/data/translationsApp/translationsApp.schema.json +1 -0
- package/dist/data/translationsApp/translationsApp.zod.d.ts +2 -0
- package/dist/data/translationsApp/translationsApp.zod.js +1 -0
- package/dist/data/translationsFtb/translationsFtb.json +122 -666
- package/dist/data/translationsIntroduction/translationsIntroduction.json +1 -1
- package/dist/data/translationsQuestion/translationsQuestion.json +65 -33
- package/dist/data/translationsSet/translationsSet.json +30155 -19418
- package/dist/data/translationsSet/translationsSet.schema.json +3 -4
- package/dist/data/translationsSet/translationsSet.zod.js +4 -4
- package/dist/data/translationsSolarSpeaker/translationsSolarSpeaker.json +1 -1
- package/dist/data/translationsSpokenQuestion/translationsSpokenQuestion.json +67 -35
- package/dist/data/youtubePlaylists/youtubePlaylists.json +10 -10
- package/dist/data/youtubeVideos/youtubeVideos.json +82 -82
- package/dist/functions/bibleBooks.d.ts +16 -0
- package/dist/functions/bibleBooks.js +101 -0
- package/dist/functions/bibles.d.ts +44 -0
- package/dist/functions/bibles.js +291 -0
- package/dist/functions/languages.d.ts +6 -7
- package/dist/functions/languages.js +51 -53
- package/dist/functions/scripturePassages.d.ts +34 -49
- package/dist/functions/scripturePassages.js +167 -304
- package/dist/functions/sets.d.ts +13 -52
- package/dist/functions/sets.js +193 -205
- package/dist/functions/utils.d.ts +2 -0
- package/dist/functions/utils.js +8 -0
- package/dist/types/bibleChapters.d.ts +2 -2
- package/dist/types/bibleChapters.js +1 -1
- package/dist/types/languages.d.ts +39 -9
- package/dist/types/languages.js +2 -0
- package/dist/types/sets.d.ts +21 -11
- package/package.json +1 -1
- package/dist/data/languageAssets/index.d.ts +0 -1
- package/dist/data/languageAssets/index.js +0 -7
- package/dist/data/languageAssets/languageAssets.json +0 -45406
- package/dist/data/languageAssets/languageAssets.schema.json +0 -19
- package/dist/data/languageAssets/languageAssets.zod.d.ts +0 -3
- package/dist/data/languageAssets/languageAssets.zod.js +0 -7
|
@@ -1,61 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseVerseRange =
|
|
3
|
+
exports.parseVerseRange = void 0;
|
|
4
4
|
exports.getChapterUrl = getChapterUrl;
|
|
5
5
|
exports.getPassagesString = getPassagesString;
|
|
6
6
|
exports.getScripturePassage = getScripturePassage;
|
|
7
7
|
exports.getLessonScripture = getLessonScripture;
|
|
8
|
-
exports.parseBibleSnapshot = parseBibleSnapshot;
|
|
9
8
|
exports.verseToSuperscript = verseToSuperscript;
|
|
10
|
-
exports.
|
|
9
|
+
exports.getFtbDuration = getFtbDuration;
|
|
10
|
+
exports.enrichSections = enrichSections;
|
|
11
11
|
exports.normalizeVerseTimings = normalizeVerseTimings;
|
|
12
12
|
const bibleStatuses_1 = require("../data/bibleStatuses");
|
|
13
|
-
const
|
|
13
|
+
const firebase_1 = require("../data/firebase");
|
|
14
14
|
const mediaDurations_1 = require("../data/mediaDurations");
|
|
15
|
-
const specialIds_1 = require("../data/specialIds");
|
|
16
15
|
const languages_1 = require("../functions/languages");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*/
|
|
23
|
-
function parseVerseRange(passageId) {
|
|
24
|
-
// Handle single verse: "GEN.1.1" -> "GEN.1.1-GEN.1.1"
|
|
25
|
-
const parts = passageId.includes('-')
|
|
26
|
-
? passageId.split('-')
|
|
27
|
-
: [passageId, passageId];
|
|
28
|
-
const startParts = parts[0].split('.');
|
|
29
|
-
const endParts = parts[1].split('.');
|
|
30
|
-
const startBook = startParts[0];
|
|
31
|
-
const startChapter = startParts[1];
|
|
32
|
-
const startVerse = startParts.length > 2 ? startParts[2] : '1';
|
|
33
|
-
const endBook = endParts[0];
|
|
34
|
-
const endChapter = endParts[1];
|
|
35
|
-
const endVerse = endParts.length > 2 ? endParts[2] : '1';
|
|
36
|
-
return {
|
|
37
|
-
startBook,
|
|
38
|
-
startChapter,
|
|
39
|
-
startVerse,
|
|
40
|
-
endBook,
|
|
41
|
-
endChapter,
|
|
42
|
-
endVerse,
|
|
43
|
-
startChapterId: `${startBook}.${startChapter}`,
|
|
44
|
-
endChapterId: `${endBook}.${endChapter}`,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
16
|
+
const sets_1 = require("../types/sets");
|
|
17
|
+
const bibleBooks_1 = require("./bibleBooks");
|
|
18
|
+
const bibles_1 = require("./bibles");
|
|
19
|
+
var bibleBooks_2 = require("./bibleBooks");
|
|
20
|
+
Object.defineProperty(exports, "parseVerseRange", { enumerable: true, get: function () { return bibleBooks_2.parseVerseRange; } });
|
|
47
21
|
function getChapterUrl(params) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
: parseVerseRange(params.passageId).startChapter;
|
|
54
|
-
return (sets_1.firebaseUrl +
|
|
22
|
+
const book = 'book' in params ? params.book : (0, bibleBooks_1.parseVerseRange)(params.passageId).book;
|
|
23
|
+
const chapter = 'chapter' in params
|
|
24
|
+
? params.chapter
|
|
25
|
+
: (0, bibleBooks_1.parseVerseRange)(params.passageId).chapter;
|
|
26
|
+
return (firebase_1.firebaseUrl +
|
|
55
27
|
encodeURIComponent('audio_bibles' +
|
|
56
28
|
`/${params.bibleAudioId}` +
|
|
57
|
-
`/${
|
|
58
|
-
`/${
|
|
29
|
+
`/${book}` +
|
|
30
|
+
`/${book}_${chapter.padStart(3, '0')}.mp3`) +
|
|
59
31
|
`?alt=media`);
|
|
60
32
|
}
|
|
61
33
|
/** Extracts verses from a chapter based on verse numbers */
|
|
@@ -85,170 +57,90 @@ function extractVersesFromChapter(chapter, startVerse, endVerse) {
|
|
|
85
57
|
* ["GEN.1.1-GEN.1.25", "GEN.2.4-GEN.2.7", "EXO.3.3-EXO.3.25"] -> "Genesis 1: 1-25, 2: 4-7, Exodus 3: 3-25"
|
|
86
58
|
* ["JHN.1.1"] -> "John 1: 1"
|
|
87
59
|
*/
|
|
88
|
-
function getPassagesString(
|
|
89
|
-
if (!passageIds || passageIds.length === 0)
|
|
90
|
-
return '';
|
|
60
|
+
function getPassagesString(passages) {
|
|
91
61
|
const parts = [];
|
|
92
62
|
let currentBook = null;
|
|
93
|
-
for (const
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// New book - include book name
|
|
106
|
-
if (currentBook !== startBook) {
|
|
107
|
-
currentBook = startBook;
|
|
108
|
-
// Same chapter
|
|
109
|
-
if (startChapter === endChapter) {
|
|
110
|
-
if (startVerse === endVerse) {
|
|
111
|
-
parts.push(`${bookName} ${startChapter}: ${startVerse}`);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
parts.push(`${bookName} ${startChapter}: ${startVerse}-${endVerse}`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
// Different chapters
|
|
119
|
-
parts.push(`${bookName} ${startChapter}: ${startVerse}-${endChapter}: ${endVerse}`);
|
|
120
|
-
}
|
|
63
|
+
for (const passage of passages) {
|
|
64
|
+
const bibleInfo = (0, bibles_1.getBibleInfo)(passage.bibleId);
|
|
65
|
+
if (!bibleInfo)
|
|
66
|
+
continue;
|
|
67
|
+
const { book, chapter, startVerse, endVerse } = (0, bibleBooks_1.parseVerseRange)(passage.passageId);
|
|
68
|
+
const bookName = bibleInfo.bookNames[book];
|
|
69
|
+
if (!bookName)
|
|
70
|
+
continue;
|
|
71
|
+
const verseRange = startVerse === endVerse ? startVerse : `${startVerse}-${endVerse}`;
|
|
72
|
+
if (currentBook !== book) {
|
|
73
|
+
currentBook = book;
|
|
74
|
+
parts.push((0, languages_1.numerals)(`${bookName} ${chapter}: ${verseRange}`, bibleInfo.language.script));
|
|
121
75
|
}
|
|
122
76
|
else {
|
|
123
|
-
|
|
124
|
-
if (startChapter === endChapter) {
|
|
125
|
-
if (startVerse === endVerse) {
|
|
126
|
-
parts.push(`${startChapter}: ${startVerse}`);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
parts.push(`${startChapter}: ${startVerse}-${endVerse}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
// Different chapters
|
|
134
|
-
parts.push(`${startChapter}: ${startVerse}-${endChapter}: ${endVerse}`);
|
|
135
|
-
}
|
|
77
|
+
parts.push((0, languages_1.numerals)(`${chapter}: ${verseRange}`, bibleInfo.language.script));
|
|
136
78
|
}
|
|
137
79
|
}
|
|
138
|
-
return
|
|
80
|
+
return parts.join(', ');
|
|
139
81
|
}
|
|
140
82
|
/** Gets a scripture passage by extracting verses from chapters documents. */
|
|
141
|
-
async function getScripturePassage({ bibleId,
|
|
83
|
+
async function getScripturePassage({ bibleId, passageId, getChapter, noTextAvailableString, }) {
|
|
84
|
+
const bibleInfo = (0, bibles_1.getBibleInfo)(bibleId);
|
|
85
|
+
const { startVerse, endVerse, chapterId } = (0, bibleBooks_1.parseVerseRange)(passageId);
|
|
86
|
+
const noTextAvailableReturn = {
|
|
87
|
+
bibleId,
|
|
88
|
+
header: getPassagesString([{ passageId, bibleId }]),
|
|
89
|
+
passageId,
|
|
90
|
+
verses: [],
|
|
91
|
+
};
|
|
92
|
+
if (!bibleInfo)
|
|
93
|
+
return noTextAvailableReturn;
|
|
94
|
+
const returnExpected = bibleInfo.availableTextChapters.includes(chapterId) ||
|
|
95
|
+
bibleInfo.availableTimingsChapters.includes(chapterId);
|
|
96
|
+
/**
|
|
97
|
+
* In this case, we know the bible does not have text for this chapter, so the
|
|
98
|
+
* user will see a placeholder verse.
|
|
99
|
+
*/
|
|
100
|
+
if (!returnExpected) {
|
|
101
|
+
noTextAvailableReturn.verses = [
|
|
102
|
+
{ text: noTextAvailableString, verseId: '' },
|
|
103
|
+
];
|
|
104
|
+
return noTextAvailableReturn;
|
|
105
|
+
}
|
|
142
106
|
try {
|
|
143
|
-
const { startBook, startChapter, startVerse, endBook, endChapter, endVerse, } = parseVerseRange(passageId);
|
|
144
107
|
const startVerseNum = parseInt(startVerse);
|
|
145
108
|
const endVerseNum = parseInt(endVerse);
|
|
146
|
-
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
console.warn(`Chapter not found: ${bibleId}.${chapterId} for passage ${passageId}`);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
const verses = extractVersesFromChapter(chapter, startVerseNum, endVerseNum);
|
|
157
|
-
if (verses.length === 0) {
|
|
158
|
-
console.warn(`No verses found for passage ${passageId}`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
return {
|
|
162
|
-
passageId,
|
|
163
|
-
bibleId,
|
|
164
|
-
header: getPassagesString([passageId], languageInfo),
|
|
165
|
-
verses,
|
|
166
|
-
};
|
|
109
|
+
const chapter = await getChapter({ chapterId, bibleId });
|
|
110
|
+
if (!chapter)
|
|
111
|
+
return noTextAvailableReturn;
|
|
112
|
+
const verses = extractVersesFromChapter(chapter, startVerseNum, endVerseNum);
|
|
113
|
+
if (verses.length === 0) {
|
|
114
|
+
console.warn(`No verses found for passage ${bibleId};${passageId}`);
|
|
115
|
+
return noTextAvailableReturn;
|
|
167
116
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const chapters = [];
|
|
171
|
-
// Get all chapters in the range
|
|
172
|
-
const startChapterNum = parseInt(startChapter);
|
|
173
|
-
const endChapterNum = parseInt(endChapter);
|
|
174
|
-
for (let i = startChapterNum; i <= endChapterNum; i++) {
|
|
175
|
-
const chapterId = `${startBook}.${i}`;
|
|
176
|
-
let chapter = await getChapter({ chapterId, bibleId });
|
|
177
|
-
if (!chapter && bibleFallbackId)
|
|
178
|
-
chapter = await getChapter({ chapterId, bibleId: bibleFallbackId });
|
|
179
|
-
if (chapter) {
|
|
180
|
-
chapters.push(chapter);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
console.warn(`Missing chapter in range: ${bibleId}.${chapterId}`);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (chapters.length === 0) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
// Extract verses from each chapter
|
|
190
|
-
const allVerses = [];
|
|
191
|
-
chapters.forEach((chapter, index) => {
|
|
192
|
-
if (index === 0) {
|
|
193
|
-
// First chapter - from startVerse to end
|
|
194
|
-
const lastVerse = Math.max(...chapter.verses.map((v) => parseInt(v.verseId.split('.')[2])));
|
|
195
|
-
allVerses.push(...extractVersesFromChapter(chapter, startVerseNum, lastVerse));
|
|
196
|
-
}
|
|
197
|
-
else if (index === chapters.length - 1) {
|
|
198
|
-
// Last chapter - from beginning to endVerse
|
|
199
|
-
allVerses.push(...extractVersesFromChapter(chapter, 1, endVerseNum));
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
// Middle chapters - all verses
|
|
203
|
-
allVerses.push(...chapter.verses);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
117
|
+
if (!verses.some((v) => v.text))
|
|
118
|
+
verses[0].text = noTextAvailableString;
|
|
206
119
|
return {
|
|
207
120
|
passageId,
|
|
208
|
-
bibleId,
|
|
209
|
-
header: getPassagesString([passageId
|
|
210
|
-
verses
|
|
121
|
+
bibleId: chapter.translationId,
|
|
122
|
+
header: getPassagesString([{ passageId, bibleId }]),
|
|
123
|
+
verses,
|
|
211
124
|
};
|
|
212
125
|
}
|
|
213
126
|
catch (error) {
|
|
214
127
|
console.error(`Error getting scripture passage ${passageId} in ${bibleId}`, error);
|
|
215
|
-
|
|
128
|
+
throw error;
|
|
216
129
|
}
|
|
217
130
|
}
|
|
218
|
-
/**
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
else if (snapshot.empty) {
|
|
233
|
-
console.warn('Empty snapshot for', bible);
|
|
234
|
-
return [];
|
|
235
|
-
}
|
|
236
|
-
for (const doc of snapshot.docs) {
|
|
237
|
-
const chapterParse = bibleChapters_1.BibleChapter.safeParse(doc.data());
|
|
238
|
-
if (!chapterParse.success) {
|
|
239
|
-
console.warn('Skipping invalid bible chapter document', doc.id, chapterParse.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`));
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
validChapters.push(chapterParse.data);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
if (validChapters.length === 0) {
|
|
246
|
-
console.warn('No valid chapters for', bible);
|
|
247
|
-
return [];
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
return validChapters;
|
|
251
|
-
}
|
|
131
|
+
/** Gets all scripture passages for a lesson. */
|
|
132
|
+
async function getLessonScripture({ getChapter, lessonInfo, noTextAvailableString, }) {
|
|
133
|
+
return Promise.all(lessonInfo.sections
|
|
134
|
+
.filter((s) => s.chapter === sets_1.Chapter.STORY)
|
|
135
|
+
.map((s) => {
|
|
136
|
+
const [bibleId, passageId] = s.id.split(';');
|
|
137
|
+
return getScripturePassage({
|
|
138
|
+
bibleId,
|
|
139
|
+
passageId,
|
|
140
|
+
getChapter,
|
|
141
|
+
noTextAvailableString,
|
|
142
|
+
});
|
|
143
|
+
}));
|
|
252
144
|
}
|
|
253
145
|
/**
|
|
254
146
|
* Converts a verse number to a superscript string. This is useful for
|
|
@@ -285,131 +177,102 @@ function verseToSuperscript(num) {
|
|
|
285
177
|
.join('');
|
|
286
178
|
}
|
|
287
179
|
/**
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
* produce one chunk per chapter, with isPartOfPrevious=true on the 2nd+ chunks.
|
|
291
|
-
* This mirrors leviathan's passage_ids_by_chapter splitting logic.
|
|
180
|
+
* Returns the FTB audio duration + afterFtb pause for a section, or 0 if the
|
|
181
|
+
* section has no FTB.
|
|
292
182
|
*/
|
|
293
|
-
function
|
|
294
|
-
if (
|
|
295
|
-
return
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const parts = verse.verseId.split('.');
|
|
300
|
-
const chapterId = `${parts[0]}.${parts[1]}`;
|
|
301
|
-
if (chapterId !== currentChapterId) {
|
|
302
|
-
chunks.push({
|
|
303
|
-
verses: [verse],
|
|
304
|
-
bookId: parts[0],
|
|
305
|
-
isPartOfPrevious: currentChapterId !== null,
|
|
306
|
-
});
|
|
307
|
-
currentChapterId = chapterId;
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
chunks[chunks.length - 1].verses.push(verse);
|
|
311
|
-
}
|
|
183
|
+
function getFtbDuration(section, lessonInfo) {
|
|
184
|
+
if (!section.ftbFileName)
|
|
185
|
+
return 0;
|
|
186
|
+
const ftbDuration = mediaDurations_1.mediaDurations[lessonInfo.contentLanguages.ftbs]?.[section.ftbFileName];
|
|
187
|
+
if (ftbDuration == null) {
|
|
188
|
+
console.warn(`FTB duration not found for ${section.ftbFileName}`);
|
|
312
189
|
}
|
|
313
|
-
return
|
|
190
|
+
return (ftbDuration ?? 0) + lessonInfo.lessonPauses.afterFtb;
|
|
314
191
|
}
|
|
315
192
|
/**
|
|
316
|
-
*
|
|
317
|
-
*
|
|
193
|
+
* Fills in `length` (for verse-timed story sections) and `startTime` (for all
|
|
194
|
+
* sections) by accumulating forward through the lesson. After this, every
|
|
195
|
+
* section has both fields set.
|
|
318
196
|
*/
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
197
|
+
function enrichSections(lessonInfo, scripture) {
|
|
198
|
+
const storySections = lessonInfo.sections.filter((s) => s.chapter === sets_1.Chapter.STORY);
|
|
199
|
+
// Forward pass: compute lengths and start times for all non-application
|
|
200
|
+
// sections.
|
|
201
|
+
let currentTime = 0;
|
|
202
|
+
const enriched = lessonInfo.sections.map((section) => {
|
|
203
|
+
if (!section.chapter)
|
|
204
|
+
return { ...section, startTime: 0, length: 0 };
|
|
205
|
+
currentTime += section.pauseBefore ?? 0;
|
|
206
|
+
let length;
|
|
207
|
+
const startTime = currentTime;
|
|
208
|
+
if (section.chapter !== sets_1.Chapter.STORY) {
|
|
209
|
+
length = mediaDurations_1.mediaDurations[section.languageId]?.[section.fileName];
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
currentTime += getFtbDuration(section, lessonInfo);
|
|
213
|
+
const [bibleId, passageId] = section.id.split(';');
|
|
214
|
+
length = bibleStatuses_1.bibleStatuses[bibleId]?.customPassages?.[passageId];
|
|
215
|
+
if (!length) {
|
|
216
|
+
const passage = scripture[storySections.indexOf(section)];
|
|
217
|
+
if (passage) {
|
|
218
|
+
const firstTimed = passage.verses.find((v) => v.timings);
|
|
219
|
+
const lastTimed = [...passage.verses].reverse().find((v) => v.timings);
|
|
220
|
+
if (firstTimed?.timings && lastTimed?.timings) {
|
|
221
|
+
length = lastTimed.timings[1] - firstTimed.timings[0];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (length == null) {
|
|
227
|
+
console.warn(`Missing duration for section ${section.id} (${section.chapter}, ${section.fileName})`);
|
|
228
|
+
}
|
|
229
|
+
currentTime += length ?? 0;
|
|
230
|
+
return { ...section, length: length ?? 0, startTime };
|
|
231
|
+
});
|
|
232
|
+
// Backward pass: compute application section start times from the end of the
|
|
233
|
+
// lesson file, so they are always correct even if story durations are
|
|
234
|
+
// slightly off.
|
|
235
|
+
const fullFileName = lessonInfo.type === 'dbs'
|
|
236
|
+
? lessonInfo.full.localFileName
|
|
237
|
+
: lessonInfo.video.localFileName;
|
|
238
|
+
const totalDuration = mediaDurations_1.mediaDurations[lessonInfo.languageId]?.[fullFileName] ?? 0;
|
|
239
|
+
if (totalDuration > 0) {
|
|
240
|
+
let timeFromEnd = totalDuration;
|
|
241
|
+
const applicationSections = enriched.filter((s) => s.chapter === sets_1.Chapter.APPLICATION);
|
|
242
|
+
for (const section of [...applicationSections].reverse()) {
|
|
243
|
+
timeFromEnd -= section.length;
|
|
244
|
+
section.startTime = timeFromEnd;
|
|
245
|
+
timeFromEnd -= section.pauseBefore ?? 0;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return enriched;
|
|
336
249
|
}
|
|
337
250
|
/**
|
|
338
|
-
* Converts verse timings
|
|
339
|
-
*
|
|
340
|
-
* pauses, and from-the-book durations.
|
|
341
|
-
*
|
|
342
|
-
* Multi-chapter passages are split into per-chapter chunks internally, since
|
|
343
|
-
* the audio is clipped from individual chapter files.
|
|
251
|
+
* Converts verse timings from chapter-relative to lesson-relative using each
|
|
252
|
+
* section's `startTime` (set by {@link enrichSections}).
|
|
344
253
|
*/
|
|
345
|
-
function normalizeVerseTimings({
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
lessonInfo.type === 'dbs' &&
|
|
351
|
-
lessonInfo.introLength)
|
|
352
|
-
cumulativeTime += lessonInfo.introLength;
|
|
353
|
-
let lastBook = null;
|
|
354
|
-
/** Tracks the overall passage index (not chunk index) for FTB/pause logic. */
|
|
355
|
-
let globalChunkIndex = 0;
|
|
356
|
-
return scripture?.map((passage) => {
|
|
357
|
-
if (!passage)
|
|
358
|
-
return undefined;
|
|
359
|
-
const chunks = splitPassageIntoChunks(passage.verses);
|
|
360
|
-
if (chunks.length === 0)
|
|
254
|
+
function normalizeVerseTimings({ enrichedSections, scripture, lessonInfo, }) {
|
|
255
|
+
const storySections = enrichedSections.filter((s) => s.chapter === sets_1.Chapter.STORY);
|
|
256
|
+
return scripture.map((passage, passageIndex) => {
|
|
257
|
+
const section = storySections[passageIndex];
|
|
258
|
+
if (!section)
|
|
361
259
|
return passage;
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
const chunkAudioStart = firstTimedVerse.timings[0];
|
|
373
|
-
// Add FTB + pauses. Chunks that are continuations of a multi-chapter
|
|
374
|
-
// passage (isPartOfPrevious) get no pause — they are concatenated directly.
|
|
375
|
-
if (!chunk.isPartOfPrevious) {
|
|
376
|
-
if (lastBook !== chunk.bookId) {
|
|
377
|
-
if (globalChunkIndex !== 0) {
|
|
378
|
-
cumulativeTime += pauses.beforeFtb;
|
|
379
|
-
}
|
|
380
|
-
const ftbLanguage = languageInfo.titles ?? languageInfo.languageId;
|
|
381
|
-
const ftbKey = `${ftbLanguage}.${chunk.bookId}.mp3`;
|
|
382
|
-
const ftbDuration = mediaDurations_1.mediaDurations[ftbLanguage]?.[ftbKey];
|
|
383
|
-
if (ftbDuration != null)
|
|
384
|
-
cumulativeTime += ftbDuration;
|
|
385
|
-
else {
|
|
386
|
-
console.error(`FTB duration not found for ${ftbKey}`);
|
|
387
|
-
return passage;
|
|
388
|
-
}
|
|
389
|
-
cumulativeTime += pauses.afterFtb;
|
|
390
|
-
lastBook = chunk.bookId;
|
|
391
|
-
}
|
|
392
|
-
else if (globalChunkIndex !== 0) {
|
|
393
|
-
cumulativeTime += pauses.betweenPassages;
|
|
394
|
-
}
|
|
395
|
-
globalChunkIndex++;
|
|
396
|
-
}
|
|
397
|
-
const offset = cumulativeTime - chunkAudioStart;
|
|
398
|
-
for (const verse of chunk.verses) {
|
|
260
|
+
const firstTimedVerse = passage.verses.find((v) => v.timings);
|
|
261
|
+
if (!firstTimedVerse?.timings)
|
|
262
|
+
return passage;
|
|
263
|
+
const offset = section.startTime +
|
|
264
|
+
getFtbDuration(section, lessonInfo) -
|
|
265
|
+
firstTimedVerse.timings[0];
|
|
266
|
+
return {
|
|
267
|
+
...passage,
|
|
268
|
+
verses: passage.verses.map((verse) => {
|
|
399
269
|
if (!verse.timings)
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
// Advance cumulative time by this chunk's audio duration
|
|
408
|
-
const lastTimedVerse = [...chunk.verses].reverse().find((v) => v.timings);
|
|
409
|
-
if (lastTimedVerse?.timings) {
|
|
410
|
-
cumulativeTime += lastTimedVerse.timings[1] - chunkAudioStart;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
return { ...passage, verses: adjustedVerses };
|
|
270
|
+
return verse;
|
|
271
|
+
return {
|
|
272
|
+
...verse,
|
|
273
|
+
timings: [verse.timings[0] + offset, verse.timings[1] + offset],
|
|
274
|
+
};
|
|
275
|
+
}),
|
|
276
|
+
};
|
|
414
277
|
});
|
|
415
278
|
}
|
package/dist/functions/sets.d.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { TranslationsApp } from '../data/translationsApp/translationsApp.zod';
|
|
2
2
|
import type { LanguageInfo, MeetTranslations } from '../types/languages';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export declare const firebaseUrl = "https://firebasestorage.googleapis.com/v0/b/waha-app-db.appspot.com/o/";
|
|
6
|
-
export declare function getSetInfo({ setId, meetLanguageId, setIds, t, }: {
|
|
3
|
+
import { DbsInfo, EnrichedSection, Lesson, LessonInfo, SetInfo, VideoInfo } from '../types/sets';
|
|
4
|
+
export declare function getSetInfo({ setId, languageId, setIds, t, }: {
|
|
7
5
|
setId: string;
|
|
8
|
-
|
|
6
|
+
languageId: string;
|
|
9
7
|
t: MeetTranslations & TranslationsApp[string];
|
|
10
8
|
setIds: string[];
|
|
11
9
|
}): SetInfo | undefined;
|
|
12
|
-
export declare function getLessonInfo({ lessonId,
|
|
10
|
+
export declare function getLessonInfo({ lessonId, languageInfo, setInfo, t, useSpokenQuestions, }: {
|
|
13
11
|
lessonId: Lesson['lessonId'] | undefined;
|
|
14
|
-
|
|
12
|
+
languageInfo: LanguageInfo;
|
|
15
13
|
setInfo?: SetInfo;
|
|
16
14
|
t: MeetTranslations & TranslationsApp[string];
|
|
17
15
|
useSpokenQuestions?: boolean;
|
|
@@ -20,50 +18,13 @@ export declare function convertSToString(time: number): string;
|
|
|
20
18
|
/** Determines whether a lesson should be visible in Waha. */
|
|
21
19
|
export declare function shouldShowLesson(lessonInfo: LessonInfo | undefined, languageInfo: LanguageInfo): boolean;
|
|
22
20
|
/**
|
|
23
|
-
*
|
|
24
|
-
* audio duration.
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
thisLesson: DbsInfo | VideoInfo;
|
|
29
|
-
totalDuration: number;
|
|
30
|
-
languageInfo: LanguageInfo;
|
|
31
|
-
normalizedScripture: Array<ScripturePassage | undefined>;
|
|
32
|
-
/**
|
|
33
|
-
* Determine if the timings are valid to be used for section timings.
|
|
34
|
-
*
|
|
35
|
-
* Supports verse highlight example:
|
|
36
|
-
*
|
|
37
|
-
* - GEN.1.1-GEN.1.10 -> 83
|
|
38
|
-
* - GEN.2.1-GEN.2.4 -> 100
|
|
39
|
-
* - GEN.2.7-GEN.2.10 -> 120
|
|
40
|
-
*
|
|
41
|
-
* Doesn't support verse highlight example:
|
|
42
|
-
*
|
|
43
|
-
* - GEN.1.1-GEN.1.10 -> 83
|
|
44
|
-
* - GEN.2.1-GEN.2.4 -> undefined
|
|
45
|
-
* - GEN.2.7-GEN.2.10 -> undefined
|
|
46
|
-
*
|
|
47
|
-
* First passage is always valid because its start time is simply the length
|
|
48
|
-
* of the previous audio. Subsequent passages require good verse timing data.
|
|
49
|
-
*/
|
|
50
|
-
supportsVerseHighlight: boolean;
|
|
51
|
-
}): Map<string, number>;
|
|
52
|
-
/**
|
|
53
|
-
* Checks if pre-normalized verse timings for given scripture are valid. Does
|
|
54
|
-
* this by comparing the real duration of the full lesson mp3 file with the
|
|
55
|
-
* calculated duration based on individual question durations and verse timing
|
|
56
|
-
* data from bible chapter documents. For lessons generated programmatically
|
|
57
|
-
* with recent systems, they should be nearly identical. For older lessons that
|
|
58
|
-
* were made by hand, they may be off. If they're too off, they will be flagged
|
|
59
|
-
* as invalid and the lesson will default to not using verse timings.
|
|
21
|
+
* Validates that the computed lesson duration (from section lengths) matches
|
|
22
|
+
* the actual audio file duration. Sections must be enriched (all have `length`)
|
|
23
|
+
* via {@link enrichSections} before calling this.
|
|
24
|
+
*
|
|
25
|
+
* @returns The difference between the computed length and the total duration.
|
|
60
26
|
*/
|
|
61
|
-
export declare function
|
|
27
|
+
export declare function getExpectedLessonDuration({ enrichedSections, lessonInfo, }: {
|
|
28
|
+
enrichedSections: EnrichedSection[];
|
|
62
29
|
lessonInfo: DbsInfo | VideoInfo;
|
|
63
|
-
|
|
64
|
-
totalDuration: number | undefined;
|
|
65
|
-
}): {
|
|
66
|
-
computedLength: number;
|
|
67
|
-
diff: number;
|
|
68
|
-
passed: boolean;
|
|
69
|
-
};
|
|
30
|
+
}): number;
|