Skip to content

Commit c82d68f

Browse files
committed
Fix a crash that happens when importing a Yomichan dictionary fails (Fixes #159)
Skip importing malformed Yomichan records If a Yomichan dictionary has no valid records, disable it
1 parent 03bc77e commit c82d68f

File tree

2 files changed

+74
-15
lines changed

2 files changed

+74
-15
lines changed

JL.Core/Dicts/DictUtils.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -560,22 +560,22 @@ public static async Task LoadDictionaries()
560560
switch (dict.Type)
561561
{
562562
case DictType.JMdict:
563-
LoadJmdict(dict, tasks, dictDBPaths, ref rebuildingAnyDB, ref dictCleared);
563+
LoadJmdict(dict, tasks, dictDBPaths, dictsToBeRemoved, ref rebuildingAnyDB, ref dictCleared);
564564
break;
565565

566566
case DictType.JMnedict:
567-
LoadJmnedict(dict, tasks, dictDBPaths, ref rebuildingAnyDB, ref dictCleared);
567+
LoadJmnedict(dict, tasks, dictDBPaths, dictsToBeRemoved, ref rebuildingAnyDB, ref dictCleared);
568568
break;
569569

570570
case DictType.Kanjidic:
571-
LoadKanjidic(dict, tasks, dictDBPaths, ref rebuildingAnyDB, ref dictCleared);
571+
LoadKanjidic(dict, tasks, dictDBPaths, dictsToBeRemoved, ref rebuildingAnyDB, ref dictCleared);
572572
break;
573573

574574
case DictType.NonspecificWordYomichan:
575575
case DictType.NonspecificKanjiWithWordSchemaYomichan:
576576
case DictType.NonspecificNameYomichan:
577577
case DictType.NonspecificYomichan:
578-
LoadYomichanDict(dict, tasks, dictDBPaths, ref rebuildingAnyDB, ref dictCleared);
578+
LoadYomichanDict(dict, tasks, dictDBPaths, dictsToBeRemoved, ref rebuildingAnyDB, ref dictCleared);
579579
break;
580580

581581
case DictType.NonspecificKanjiYomichan:
@@ -740,7 +740,7 @@ private static DBState PrepareDictDB(Dict dict, Dictionary<string, string> dictD
740740
return new DBState(useDB, dbExists, dbExisted);
741741
}
742742

743-
private static void LoadJmdict(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ref bool rebuildingAnyDB, ref bool dictCleared)
743+
private static void LoadJmdict(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ConcurrentBag<Dict> dictsToBeRemoved, ref bool rebuildingAnyDB, ref bool dictCleared)
744744
{
745745
if (dict.Updating)
746746
{
@@ -795,6 +795,7 @@ private static void LoadJmdict(Dict dict, List<Task> tasks, Dictionary<string, s
795795
LoggerManager.Logger.Error(ex, "Couldn't import '{DictType}'-'{DictName}' from '{FullDictPath}'", dict.Type.GetDescription(), dict.Name, fullDictPath);
796796
FrontendManager.Frontend.Alert(AlertLevel.Error, $"Couldn't import {dict.Name}");
797797
File.Delete(fullDictPath);
798+
dictsToBeRemoved.Add(dict);
798799
}
799800
finally
800801
{
@@ -830,7 +831,7 @@ private static void LoadJmdict(Dict dict, List<Task> tasks, Dictionary<string, s
830831
}
831832
}
832833

833-
private static void LoadJmnedict(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ref bool rebuildingAnyDB, ref bool dictCleared)
834+
private static void LoadJmnedict(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ConcurrentBag<Dict> dictsToBeRemoved, ref bool rebuildingAnyDB, ref bool dictCleared)
834835
{
835836
if (dict.Updating)
836837
{
@@ -878,6 +879,7 @@ private static void LoadJmnedict(Dict dict, List<Task> tasks, Dictionary<string,
878879
LoggerManager.Logger.Error(ex, "Couldn't import '{DictType}'-'{DictName}' from '{FullDictPath}'", dict.Type.GetDescription(), dict.Name, fullDictPath);
879880
FrontendManager.Frontend.Alert(AlertLevel.Error, $"Couldn't import {dict.Name}");
880881
File.Delete(fullDictPath);
882+
dictsToBeRemoved.Add(dict);
881883
}
882884
finally
883885
{
@@ -913,7 +915,7 @@ private static void LoadJmnedict(Dict dict, List<Task> tasks, Dictionary<string,
913915
}
914916
}
915917

916-
private static void LoadKanjidic(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ref bool rebuildingAnyDB, ref bool dictCleared)
918+
private static void LoadKanjidic(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ConcurrentBag<Dict> dictsToBeRemoved, ref bool rebuildingAnyDB, ref bool dictCleared)
917919
{
918920
if (dict.Updating)
919921
{
@@ -968,6 +970,7 @@ private static void LoadKanjidic(Dict dict, List<Task> tasks, Dictionary<string,
968970
LoggerManager.Logger.Error(ex, "Couldn't import '{DictType}'-'{DictName}' from '{FullDictPath}'", dict.Type.GetDescription(), dict.Name, fullDictPath);
969971
FrontendManager.Frontend.Alert(AlertLevel.Error, $"Couldn't import {dict.Name}");
970972
File.Delete(fullDictPath);
973+
dictsToBeRemoved.Add(dict);
971974
}
972975
finally
973976
{
@@ -1003,7 +1006,7 @@ private static void LoadKanjidic(Dict dict, List<Task> tasks, Dictionary<string,
10031006
}
10041007
}
10051008

1006-
private static void LoadYomichanDict(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ref bool rebuildingAnyDB, ref bool dictCleared)
1009+
private static void LoadYomichanDict(Dict dict, List<Task> tasks, Dictionary<string, string> dictDBPaths, ConcurrentBag<Dict> dictsToBeRemoved, ref bool rebuildingAnyDB, ref bool dictCleared)
10071010
{
10081011
if (dict.Updating)
10091012
{
@@ -1041,7 +1044,13 @@ private static void LoadYomichanDict(Dict dict, List<Task> tasks, Dictionary<str
10411044
await EpwingYomichanLoader.Load(dict).ConfigureAwait(false);
10421045
dict.Size = dict.Contents.Count;
10431046

1044-
if (!dbExists && (useDB || dbExisted))
1047+
if (dict.Size is 0)
1048+
{
1049+
LoggerManager.Logger.Warning("No valid records found for '{DictType}'-'{DictName}' from '{FullDictPath}'. The dict has been deactivated.", dict.Type.GetDescription(), dict.Name, fullDictPath);
1050+
FrontendManager.Frontend.Alert(AlertLevel.Warning, $"No valid records found for {dict.Name}");
1051+
dictsToBeRemoved.Add(dict);
1052+
}
1053+
else if (!dbExists && (useDB || dbExisted))
10451054
{
10461055
EpwingYomichanDBManager.CreateDB(dict.Name);
10471056
EpwingYomichanDBManager.InsertRecordsToDB(dict);
@@ -1058,6 +1067,7 @@ private static void LoadYomichanDict(Dict dict, List<Task> tasks, Dictionary<str
10581067
{
10591068
LoggerManager.Logger.Error(ex, "Couldn't import '{DictType}'-'{DictName}' from '{FullDictPath}'", dict.Type.GetDescription(), dict.Name, fullDictPath);
10601069
FrontendManager.Frontend.Alert(AlertLevel.Error, $"Couldn't import {dict.Name}");
1070+
dictsToBeRemoved.Add(dict);
10611071
}
10621072
finally
10631073
{

JL.Core/Dicts/EPWING/Yomichan/EpwingYomichanLoader.cs

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,28 @@ public static async Task Load(Dict dict)
4444

4545
private static EpwingYomichanRecord? GetEpwingYomichanRecord(JsonElement[] jsonElements, Dict dict)
4646
{
47-
string primarySpelling = jsonElements[0].GetString()!.GetPooledString();
48-
string? reading = jsonElements[1].GetString();
47+
string primarySpelling;
48+
try
49+
{
50+
primarySpelling = jsonElements[0].GetString()!.GetPooledString();
51+
}
52+
catch (InvalidOperationException ex)
53+
{
54+
LoggerManager.Logger.Error(ex, "Failed to get the primary spelling for EPWING Yomichan record: {JsonElements}", jsonElements);
55+
return null;
56+
}
57+
58+
string? reading;
59+
try
60+
{
61+
reading = jsonElements[1].GetString();
62+
}
63+
catch (InvalidOperationException ex)
64+
{
65+
LoggerManager.Logger.Error(ex, "Failed to get the reading for EPWING Yomichan record: {JsonElements}", jsonElements);
66+
return null;
67+
}
68+
4969
reading = string.IsNullOrWhiteSpace(reading) || reading == primarySpelling
5070
? null
5171
: reading.GetPooledString();
@@ -65,9 +85,18 @@ public static async Task Load(Dict dict)
6585
ref readonly JsonElement definitionTagsElement = ref jsonElements[2];
6686
if (definitionTagsElement.ValueKind is JsonValueKind.String)
6787
{
68-
string? definitionTagsStr = definitionTagsElement.GetString();
69-
Debug.Assert(definitionTagsStr is not null);
88+
string? definitionTagsStr;
89+
try
90+
{
91+
definitionTagsStr = definitionTagsElement.GetString();
92+
}
93+
catch (InvalidOperationException ex)
94+
{
95+
LoggerManager.Logger.Error(ex, "Failed to get definition tags for EPWING Yomichan record: {JsonElements}", jsonElements);
96+
return null;
97+
}
7098

99+
Debug.Assert(definitionTagsStr is not null);
71100
definitionTags = definitionTagsStr.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
72101
if (definitionTags.Length is 0)
73102
{
@@ -85,7 +114,17 @@ public static async Task Load(Dict dict)
85114
}
86115

87116
List<string> imagePaths = [];
88-
string[]? definitions = EpwingYomichanUtils.GetDefinitions(jsonElements[5], dict, imagePaths);
117+
string[]? definitions;
118+
try
119+
{
120+
definitions = EpwingYomichanUtils.GetDefinitions(jsonElements[5], dict, imagePaths);
121+
}
122+
catch (InvalidOperationException ex)
123+
{
124+
LoggerManager.Logger.Error(ex, "Failed to get definitions for EPWING Yomichan record: {JsonElements}", jsonElements);
125+
return null;
126+
}
127+
89128
definitions?.DeduplicateStringsInArray();
90129

91130
if (definitions is null
@@ -95,7 +134,17 @@ public static async Task Load(Dict dict)
95134
return null;
96135
}
97136

98-
string? wordClassesStr = jsonElements[3].GetString();
137+
string? wordClassesStr;
138+
try
139+
{
140+
wordClassesStr = jsonElements[3].GetString();
141+
}
142+
catch (InvalidOperationException ex)
143+
{
144+
LoggerManager.Logger.Error(ex, "Failed to get word classes for EPWING Yomichan record: {JsonElements}", jsonElements);
145+
return null;
146+
}
147+
99148
Debug.Assert(wordClassesStr is not null);
100149
string[]? wordClasses = wordClassesStr.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
101150
if (wordClasses.Length is 0)

0 commit comments

Comments
 (0)