@@ -29,12 +29,29 @@ Task Harvest_Bible_Links(Dictionary<string, string> biblePublicationCodeToNameMa
2929 var jsonString = await DownloadUtility . GetAsync ( harvestLink ) ;
3030 using var doc = JsonDocument . Parse ( jsonString ) ;
3131 var root = doc . RootElement ;
32- var languages = root . GetProperty ( "languages" ) ;
32+
33+ if ( ! root . TryGetProperty ( "languages" , out var languages ) )
34+ {
35+ Console . WriteLine ( $ "Warning: 'languages' property not found in response for publication { publicationCode } . Skipping.") ;
36+ continue ;
37+ }
3338
3439 foreach ( var item in languages . EnumerateObject ( ) )
3540 {
3641 var languageCode = item . Name ;
37- var language = item . Value . GetProperty ( "name" ) . GetString ( ) ;
42+
43+ if ( ! item . Value . TryGetProperty ( "name" , out var nameElement ) )
44+ {
45+ Console . WriteLine ( $ "Warning: 'name' property not found for language { languageCode } . Skipping.") ;
46+ continue ;
47+ }
48+
49+ var language = nameElement . GetString ( ) ;
50+ if ( string . IsNullOrEmpty ( language ) )
51+ {
52+ Console . WriteLine ( $ "Warning: Language name is null or empty for language { languageCode } . Skipping.") ;
53+ continue ;
54+ }
3855
3956 languageCodeToNameMappings . TryAdd ( languageCode , language ) ;
4057
@@ -73,12 +90,20 @@ private static async Task<bool> harvestBibleLinks(string languageCode, string pu
7390 try
7491 {
7592 doc = JsonDocument . Parse ( jsonString ) ;
76- files = doc . RootElement . GetProperty ( "files" ) ;
93+ if ( ! doc . RootElement . TryGetProperty ( "files" , out files ) )
94+ {
95+ Console . WriteLine ( $ "Warning: 'files' property not found in response for book { bookNumber } , language { languageCode } . Skipping.") ;
96+ doc ? . Dispose ( ) ;
97+ bookNumber ++ ;
98+ harvestLink = $ "{ AppConstants . ApiEndpoints . JwOrgIndexServiceBaseUrl } ?output=json&pub={ publicationCode } &booknum={ bookNumber } &fileformat=MP3&alllangs=0&langwritten={ languageCode } &txtCMSLang=E";
99+ continue ;
100+ }
77101 }
78102 catch ( Exception e )
79103 {
80- if ( e is JsonException or ArgumentException )
104+ if ( e is JsonException or ArgumentException or KeyNotFoundException )
81105 {
106+ Console . WriteLine ( $ "Warning: Error parsing JSON for book { bookNumber } , language { languageCode } : { e . Message } . Skipping.") ;
82107 doc ? . Dispose ( ) ;
83108 bookNumber ++ ;
84109 harvestLink = $ "{ AppConstants . ApiEndpoints . JwOrgIndexServiceBaseUrl } ?output=json&pub={ publicationCode } &booknum={ bookNumber } &fileformat=MP3&alllangs=0&langwritten={ languageCode } &txtCMSLang=E";
@@ -90,30 +115,93 @@ private static async Task<bool> harvestBibleLinks(string languageCode, string pu
90115
91116 try
92117 {
93- var bookFiles = files . GetProperty ( languageCode ) . GetProperty ( "MP3" ) ;
118+ if ( ! files . TryGetProperty ( languageCode , out var languageFiles ) )
119+ {
120+ Console . WriteLine ( $ "Warning: Language '{ languageCode } ' not found in files. Skipping book { bookNumber } .") ;
121+ bookNumber ++ ;
122+ harvestLink = $ "{ AppConstants . ApiEndpoints . JwOrgIndexServiceBaseUrl } ?output=json&pub={ publicationCode } &booknum={ bookNumber } &fileformat=MP3&alllangs=0&langwritten={ languageCode } &txtCMSLang=E";
123+ continue ;
124+ }
125+
126+ if ( ! languageFiles . TryGetProperty ( "MP3" , out var bookFiles ) )
127+ {
128+ Console . WriteLine ( $ "Warning: 'MP3' property not found for language '{ languageCode } '. Skipping book { bookNumber } .") ;
129+ bookNumber ++ ;
130+ harvestLink = $ "{ AppConstants . ApiEndpoints . JwOrgIndexServiceBaseUrl } ?output=json&pub={ publicationCode } &booknum={ bookNumber } &fileformat=MP3&alllangs=0&langwritten={ languageCode } &txtCMSLang=E";
131+ continue ;
132+ }
133+
94134 foreach ( var bookFile in bookFiles . EnumerateArray ( ) )
95135 {
96- string url = bookFile . GetProperty ( "file" ) . GetProperty ( "url" ) . GetString ( ) ! ;
97- var track = bookFile . GetProperty ( "track" ) . GetInt32 ( ) ;
136+ if ( ! bookFile . TryGetProperty ( "file" , out var fileElement ) ||
137+ ! fileElement . TryGetProperty ( "url" , out var urlElement ) )
138+ {
139+ Console . WriteLine ( $ "Warning: Missing 'file.url' property in book file. Skipping.") ;
140+ continue ;
141+ }
142+
143+ string url = urlElement . GetString ( ) ;
144+ if ( string . IsNullOrEmpty ( url ) )
145+ {
146+ Console . WriteLine ( $ "Warning: URL is null or empty. Skipping.") ;
147+ continue ;
148+ }
149+
150+ if ( ! bookFile . TryGetProperty ( "track" , out var trackElement ) )
151+ {
152+ Console . WriteLine ( $ "Warning: Missing 'track' property in book file. Skipping.") ;
153+ continue ;
154+ }
98155
99- if ( track == 0
100- || url . EndsWith ( ".zip" ) ) continue ;
156+ var track = trackElement . GetInt32 ( ) ;
101157
102- bookNumber = bookFile . GetProperty ( "booknum" ) . GetInt32 ( ) ;
158+ if ( track == 0 || url . EndsWith ( ".zip" ) ) continue ;
159+
160+ if ( ! bookFile . TryGetProperty ( "booknum" , out var bookNumElement ) )
161+ {
162+ Console . WriteLine ( $ "Warning: Missing 'booknum' property in book file. Skipping.") ;
163+ continue ;
164+ }
165+
166+ bookNumber = bookNumElement . GetInt32 ( ) ;
103167
104168 if ( ! bookNumberBookMap . ContainsKey ( bookNumber ) )
105169 {
106- var name = harvestLink . Contains ( "booknum=" ) ? doc . RootElement . GetProperty ( "pubName" ) . GetString ( ) ! : bookFile . GetProperty ( "title" ) . GetString ( ) ! . Split ( '-' ) [ 0 ] . Trim ( ) ;
170+ string name ;
171+ if ( harvestLink . Contains ( "booknum=" ) )
172+ {
173+ if ( ! doc . RootElement . TryGetProperty ( "pubName" , out var pubNameElement ) )
174+ {
175+ Console . WriteLine ( $ "Warning: Missing 'pubName' property. Skipping book { bookNumber } .") ;
176+ continue ;
177+ }
178+ name = pubNameElement . GetString ( ) ! ;
179+ }
180+ else
181+ {
182+ if ( ! bookFile . TryGetProperty ( "title" , out var titleElement ) )
183+ {
184+ Console . WriteLine ( $ "Warning: Missing 'title' property. Skipping book { bookNumber } .") ;
185+ continue ;
186+ }
187+ name = titleElement . GetString ( ) ! . Split ( '-' ) [ 0 ] . Trim ( ) ;
188+ }
107189 name = name == "Psalm 1" ? "Psalms" : name ;
108190 bookNumberBookMap [ bookNumber ] = new BibleBook
109191 {
110- Number = bookFile . GetProperty ( "booknum" ) . GetInt32 ( ) ,
192+ Number = bookNumber ,
111193 Name = name
112194 } ;
113195 }
114196
115- var trackNumber = bookFile . GetProperty ( "track" ) . GetInt32 ( ) ;
116- var duration = bookFile . GetProperty ( "duration" ) . GetDouble ( ) ;
197+ var trackNumber = track ;
198+
199+ if ( ! bookFile . TryGetProperty ( "duration" , out var durationElement ) )
200+ {
201+ Console . WriteLine ( $ "Warning: Missing 'duration' property. Using default value.") ;
202+ }
203+ var duration = durationElement . ValueKind != JsonValueKind . Undefined ? durationElement . GetDouble ( ) : 0.0 ;
204+
117205 if ( ! bookNumberChapterMap . ContainsKey ( bookNumber ) )
118206 {
119207 bookNumberChapterMap [ bookNumber ] = new Dictionary < int , BibleChapter > ( ) ;
@@ -125,11 +213,18 @@ private static async Task<bool> harvestBibleLinks(string languageCode, string pu
125213 new BibleChapter
126214 {
127215 Number = trackNumber ,
128- Url = bookFile . GetProperty ( "file" ) . GetProperty ( " url" ) . GetString ( ) ! ,
216+ Url = url ,
129217 } ) ;
130218 }
131219 }
132220 }
221+ catch ( KeyNotFoundException ex )
222+ {
223+ Console . WriteLine ( $ "Warning: KeyNotFoundException in book processing: { ex . Message } . Skipping book { bookNumber } .") ;
224+ bookNumber ++ ;
225+ harvestLink = $ "{ AppConstants . ApiEndpoints . JwOrgIndexServiceBaseUrl } ?output=json&pub={ publicationCode } &booknum={ bookNumber } &fileformat=MP3&alllangs=0&langwritten={ languageCode } &txtCMSLang=E";
226+ continue ;
227+ }
133228 finally
134229 {
135230 doc ? . Dispose ( ) ;
0 commit comments