Browse Source

log nfo file name with nfo parsing errors (#2168)

pull/2169/head
Jason Dove 4 weeks ago committed by GitHub
parent
commit
1cbd48cea0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ArtistNfoReaderTests.cs
  2. 26
      ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/EpisodeNfoReaderTests.cs
  3. 12
      ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MovieNfoReaderTests.cs
  4. 16
      ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MusicVideoNfoReaderTests.cs
  5. 12
      ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/OtherVideoNfoReaderTests.cs
  6. 14
      ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ShowNfoReaderTests.cs
  7. 36
      ErsatzTV.Scanner/Core/Metadata/Nfo/ArtistNfoReader.cs
  8. 57
      ErsatzTV.Scanner/Core/Metadata/Nfo/EpisodeNfoReader.cs
  9. 65
      ErsatzTV.Scanner/Core/Metadata/Nfo/MovieNfoReader.cs
  10. 60
      ErsatzTV.Scanner/Core/Metadata/Nfo/MusicVideoNfoReader.cs
  11. 20
      ErsatzTV.Scanner/Core/Metadata/Nfo/NfoReader.cs
  12. 64
      ErsatzTV.Scanner/Core/Metadata/Nfo/OtherVideoNfoReader.cs
  13. 55
      ErsatzTV.Scanner/Core/Metadata/Nfo/ShowNfoReader.cs

10
ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ArtistNfoReaderTests.cs

@ -42,7 +42,7 @@ public class ArtistNfoReaderTests
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars")); new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream); Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream, string.Empty);
result.IsLeft.ShouldBeTrue(); result.IsLeft.ShouldBeTrue();
} }
@ -52,7 +52,7 @@ public class ArtistNfoReaderTests
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<artist></artist>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<artist></artist>"));
Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream); Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -65,7 +65,7 @@ public class ArtistNfoReaderTests
@"<artist></artist> @"<artist></artist>
https://www.themoviedb.org/movie/11-star-wars")); https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream); Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -119,7 +119,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
<path>F:\Music\ArtistInfoKodi\Billy Joel</path> <path>F:\Music\ArtistInfoKodi\Billy Joel</path>
</artist>"))); </artist>")));
Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream); Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
@ -165,7 +165,7 @@ Joel attended Hicksville High School in 1967, but he did not graduate with his c
await using var stream = new MemoryStream( await using var stream = new MemoryStream(
Encoding.UTF8.GetBytes(@"<artist><disambiguation>Test Disambiguation</disambiguation></artist>")); Encoding.UTF8.GetBytes(@"<artist><disambiguation>Test Disambiguation</disambiguation></artist>"));
Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream); Either<BaseError, ArtistNfo> result = await _artistNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (ArtistNfo nfo in result.RightToSeq()) foreach (ArtistNfo nfo in result.RightToSeq())

26
ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/EpisodeNfoReaderTests.cs

@ -46,7 +46,7 @@ public class EpisodeNfoReaderTests
<episodedetails> <episodedetails>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -75,7 +75,7 @@ public class EpisodeNfoReaderTests
<season>1</season> <season>1</season>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -100,7 +100,7 @@ public class EpisodeNfoReaderTests
<uniqueid default=""false"" type=""imdb"">tt54321</uniqueid> <uniqueid default=""false"" type=""imdb"">tt54321</uniqueid>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -123,7 +123,7 @@ public class EpisodeNfoReaderTests
<mpaa/> <mpaa/>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -147,7 +147,7 @@ public class EpisodeNfoReaderTests
<mpaa>US:Something / US:SomethingElse</mpaa> <mpaa>US:Something / US:SomethingElse</mpaa>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -169,7 +169,7 @@ public class EpisodeNfoReaderTests
<plot/> <plot/>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -190,7 +190,7 @@ public class EpisodeNfoReaderTests
<plot>Some Plot</plot> <plot>Some Plot</plot>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -220,7 +220,7 @@ public class EpisodeNfoReaderTests
</actor> </actor>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -249,7 +249,7 @@ public class EpisodeNfoReaderTests
<credits>Writer 3</credits> <credits>Writer 3</credits>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -276,7 +276,7 @@ public class EpisodeNfoReaderTests
<director>Director 3</director> <director>Director 3</director>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -304,7 +304,7 @@ public class EpisodeNfoReaderTests
<genre>Genre 3</genre> <genre>Genre 3</genre>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -330,7 +330,7 @@ public class EpisodeNfoReaderTests
<tag>Tag 3</tag> <tag>Tag 3</tag>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (List<EpisodeNfo> list in result.RightToSeq()) foreach (List<EpisodeNfo> list in result.RightToSeq())
@ -431,7 +431,7 @@ public class EpisodeNfoReaderTests
<dateadded>2021-02-02 11:57:44</dateadded> <dateadded>2021-02-02 11:57:44</dateadded>
</episodedetails>")); </episodedetails>"));
Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream); Either<BaseError, List<EpisodeNfo>> result = await _episodeNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();

12
ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MovieNfoReaderTests.cs

@ -27,7 +27,7 @@ public class MovieNfoReaderTests
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars")); new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream); Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream, string.Empty);
result.IsLeft.ShouldBeTrue(); result.IsLeft.ShouldBeTrue();
} }
@ -37,7 +37,7 @@ public class MovieNfoReaderTests
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<movie></movie>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<movie></movie>"));
Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream); Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -50,7 +50,7 @@ public class MovieNfoReaderTests
@"<movie></movie> @"<movie></movie>
https://www.themoviedb.org/movie/11-star-wars")); https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream); Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -168,7 +168,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
<dateadded>2021-03-26 11:35:50</dateadded> <dateadded>2021-03-26 11:35:50</dateadded>
</movie>")); </movie>"));
Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream); Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
@ -227,7 +227,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<movie><tag>Test Tag</tag></movie>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<movie><tag>Test Tag</tag></movie>"));
Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream); Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (MovieNfo nfo in result.RightToSeq()) foreach (MovieNfo nfo in result.RightToSeq())
@ -242,7 +242,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"<movie><outline>Test Outline</outline></movie>")); new MemoryStream(Encoding.UTF8.GetBytes(@"<movie><outline>Test Outline</outline></movie>"));
Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream); Either<BaseError, MovieNfo> result = await _movieNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (MovieNfo nfo in result.RightToSeq()) foreach (MovieNfo nfo in result.RightToSeq())

16
ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MusicVideoNfoReaderTests.cs

@ -27,7 +27,7 @@ public class MusicVideoNfoReaderTests
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars")); new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsLeft.ShouldBeTrue(); result.IsLeft.ShouldBeTrue();
} }
@ -37,7 +37,7 @@ public class MusicVideoNfoReaderTests
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<musicvideo></musicvideo>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<musicvideo></musicvideo>"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -50,7 +50,7 @@ public class MusicVideoNfoReaderTests
@"<musicvideo></musicvideo> @"<musicvideo></musicvideo>
https://www.themoviedb.org/movie/11-star-wars")); https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -113,7 +113,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
<dateadded>2018-09-10 09:46:06</dateadded> <dateadded>2018-09-10 09:46:06</dateadded>
</musicvideo>"))); </musicvideo>")));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
@ -140,7 +140,7 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d
await using var stream = new MemoryStream( await using var stream = new MemoryStream(
Encoding.UTF8.GetBytes(@"<musicvideo><tag>Test Tag</tag></musicvideo>")); Encoding.UTF8.GetBytes(@"<musicvideo><tag>Test Tag</tag></musicvideo>"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (MusicVideoNfo nfo in result.RightToSeq()) foreach (MusicVideoNfo nfo in result.RightToSeq())
@ -155,7 +155,7 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d
await using var stream = new MemoryStream( await using var stream = new MemoryStream(
Encoding.UTF8.GetBytes(@"<musicvideo><aired>2022-02-03</aired></musicvideo>")); Encoding.UTF8.GetBytes(@"<musicvideo><aired>2022-02-03</aired></musicvideo>"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (MusicVideoNfo nfo in result.RightToSeq()) foreach (MusicVideoNfo nfo in result.RightToSeq())
@ -174,7 +174,7 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d
await using var stream = new MemoryStream( await using var stream = new MemoryStream(
Encoding.UTF8.GetBytes(@"<musicvideo><studio>Test Studio</studio></musicvideo>")); Encoding.UTF8.GetBytes(@"<musicvideo><studio>Test Studio</studio></musicvideo>"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (MusicVideoNfo nfo in result.RightToSeq()) foreach (MusicVideoNfo nfo in result.RightToSeq())
@ -189,7 +189,7 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d
await using var stream = new MemoryStream( await using var stream = new MemoryStream(
Encoding.UTF8.GetBytes(@"<musicvideo><director>Test Director</director></musicvideo>")); Encoding.UTF8.GetBytes(@"<musicvideo><director>Test Director</director></musicvideo>"));
Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream); Either<BaseError, MusicVideoNfo> result = await _musicVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (MusicVideoNfo nfo in result.RightToSeq()) foreach (MusicVideoNfo nfo in result.RightToSeq())

12
ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/OtherVideoNfoReaderTests.cs

@ -27,7 +27,7 @@ public class OtherVideoNfoReaderTests
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars")); new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream); Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream, string.Empty);
result.IsLeft.ShouldBeTrue(); result.IsLeft.ShouldBeTrue();
} }
@ -40,7 +40,7 @@ public class OtherVideoNfoReaderTests
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@$"<{topLevel}></{topLevel}>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@$"<{topLevel}></{topLevel}>"));
Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream); Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -56,7 +56,7 @@ public class OtherVideoNfoReaderTests
@$"<{topLevel}></{topLevel}> @$"<{topLevel}></{topLevel}>
https://www.themoviedb.org/movie/11-star-wars")); https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream); Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -177,7 +177,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
<dateadded>2021-03-26 11:35:50</dateadded> <dateadded>2021-03-26 11:35:50</dateadded>
</{topLevel}>")); </{topLevel}>"));
Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream); Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
@ -240,7 +240,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@$"<{topLevel}><tag>Test Tag</tag></{topLevel}>")); new MemoryStream(Encoding.UTF8.GetBytes(@$"<{topLevel}><tag>Test Tag</tag></{topLevel}>"));
Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream); Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (OtherVideoNfo nfo in result.RightToSeq()) foreach (OtherVideoNfo nfo in result.RightToSeq())
@ -258,7 +258,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@$"<{topLevel}><outline>Test Outline</outline></{topLevel}>")); new MemoryStream(Encoding.UTF8.GetBytes(@$"<{topLevel}><outline>Test Outline</outline></{topLevel}>"));
Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream); Either<BaseError, OtherVideoNfo> result = await _otherVideoNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (OtherVideoNfo nfo in result.RightToSeq()) foreach (OtherVideoNfo nfo in result.RightToSeq())

14
ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ShowNfoReaderTests.cs

@ -27,7 +27,7 @@ public class ShowNfoReaderTests
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars")); new MemoryStream(Encoding.UTF8.GetBytes(@"https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsLeft.ShouldBeTrue(); result.IsLeft.ShouldBeTrue();
} }
@ -37,7 +37,7 @@ public class ShowNfoReaderTests
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow></tvshow>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow></tvshow>"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -50,7 +50,7 @@ public class ShowNfoReaderTests
@"<tvshow></tvshow> @"<tvshow></tvshow>
https://www.themoviedb.org/movie/11-star-wars")); https://www.themoviedb.org/movie/11-star-wars"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
} }
@ -153,7 +153,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
</seasons> </seasons>
</tvshow>")); </tvshow>"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
@ -201,7 +201,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow><outline>Test Outline</outline></tvshow>")); new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow><outline>Test Outline</outline></tvshow>"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (ShowNfo nfo in result.RightToSeq()) foreach (ShowNfo nfo in result.RightToSeq())
@ -216,7 +216,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
await using var stream = await using var stream =
new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow><tagline>Test Tagline</tagline></tvshow>")); new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow><tagline>Test Tagline</tagline></tvshow>"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (ShowNfo nfo in result.RightToSeq()) foreach (ShowNfo nfo in result.RightToSeq())
@ -230,7 +230,7 @@ https://www.themoviedb.org/movie/11-star-wars"));
{ {
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow><tag>Test Tag</tag></tvshow>")); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"<tvshow><tag>Test Tag</tag></tvshow>"));
Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream); Either<BaseError, ShowNfo> result = await _showNfoReader.Read(stream, string.Empty);
result.IsRight.ShouldBeTrue(); result.IsRight.ShouldBeTrue();
foreach (ShowNfo nfo in result.RightToSeq()) foreach (ShowNfo nfo in result.RightToSeq())

36
ErsatzTV.Scanner/Core/Metadata/Nfo/ArtistNfoReader.cs

@ -28,11 +28,11 @@ public class ArtistNfoReader : NfoReader<ArtistNfo>, IArtistNfoReader
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
await using (Stream s = await SanitizedStreamForFile(fileName)) await using (Stream s = await SanitizedStreamForFile(fileName))
{ {
return await Read(s); return await Read(s, fileName);
} }
} }
internal async Task<Either<BaseError, ArtistNfo>> Read(Stream input) internal async Task<Either<BaseError, ArtistNfo>> Read(Stream input, string fileName)
{ {
ArtistNfo? nfo = null; ArtistNfo? nfo = null;
@ -53,28 +53,42 @@ public class ArtistNfoReader : NfoReader<ArtistNfo>, IArtistNfoReader
nfo = new ArtistNfo(); nfo = new ArtistNfo();
break; break;
case "name": case "name":
await ReadStringContent(reader, nfo, (artist, name) => artist.Name = name); await ReadStringContent(reader, nfo, (artist, name) => artist.Name = name, fileName);
break; break;
case "disambiguation": case "disambiguation":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(artist, disambiguation) => artist.Disambiguation = disambiguation); (artist, disambiguation) => artist.Disambiguation = disambiguation,
fileName);
break; break;
case "genre": case "genre":
await ReadStringContent(reader, nfo, (artist, genre) => artist.Genres.Add(genre)); await ReadStringContent(
reader,
nfo,
(artist, genre) => artist.Genres.Add(genre),
fileName);
break; break;
case "style": case "style":
await ReadStringContent(reader, nfo, (artist, style) => artist.Styles.Add(style)); await ReadStringContent(
reader,
nfo,
(artist, style) => artist.Styles.Add(style),
fileName);
break; break;
case "mood": case "mood":
await ReadStringContent(reader, nfo, (artist, mood) => artist.Moods.Add(mood)); await ReadStringContent(
reader,
nfo,
(artist, mood) => artist.Moods.Add(mood),
fileName);
break; break;
case "biography": case "biography":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(artist, biography) => artist.Biography = biography); (artist, biography) => artist.Biography = biography,
fileName);
break; break;
} }
@ -89,12 +103,12 @@ public class ArtistNfoReader : NfoReader<ArtistNfo>, IArtistNfoReader
} }
} }
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (XmlException) catch (XmlException)
{ {
_logger.LogWarning("Invalid XML detected; returning incomplete metadata"); _logger.LogWarning("Invalid XML detected in file {FileName}; returning incomplete metadata", fileName);
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (Exception ex) catch (Exception ex)
{ {

57
ErsatzTV.Scanner/Core/Metadata/Nfo/EpisodeNfoReader.cs

@ -28,11 +28,11 @@ public class EpisodeNfoReader : NfoReader<EpisodeNfo>, IEpisodeNfoReader
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
await using (Stream s = await SanitizedStreamForFile(fileName)) await using (Stream s = await SanitizedStreamForFile(fileName))
{ {
return await Read(s); return await Read(s, fileName);
} }
} }
internal async Task<Either<BaseError, List<EpisodeNfo>>> Read(Stream input) internal async Task<Either<BaseError, List<EpisodeNfo>>> Read(Stream input, string fileName)
{ {
var result = new List<EpisodeNfo>(); var result = new List<EpisodeNfo>();
@ -54,58 +54,83 @@ public class EpisodeNfoReader : NfoReader<EpisodeNfo>, IEpisodeNfoReader
result.Add(nfo); result.Add(nfo);
break; break;
case "title": case "title":
await ReadStringContent(reader, nfo, (episode, title) => episode.Title = title); await ReadStringContent(
reader,
nfo,
(episode, title) => episode.Title = title,
fileName);
break; break;
case "showtitle": case "showtitle":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(episode, showTitle) => episode.ShowTitle = showTitle); (episode, showTitle) => episode.ShowTitle = showTitle,
fileName);
break; break;
case "episode": case "episode":
await ReadIntContent( await ReadIntContent(
reader, reader,
nfo, nfo,
(episode, episodeNumber) => episode.Episode = episodeNumber); (episode, episodeNumber) => episode.Episode = episodeNumber,
fileName);
break; break;
case "season": case "season":
await ReadIntContent( await ReadIntContent(
reader, reader,
nfo, nfo,
(episode, seasonNumber) => episode.Season = seasonNumber); (episode, seasonNumber) => episode.Season = seasonNumber,
fileName);
break; break;
case "uniqueid": case "uniqueid":
await ReadUniqueId(reader, nfo, (episode, uniqueId) => episode.UniqueIds.Add(uniqueId)); await ReadUniqueId(
reader,
nfo,
(episode, uniqueId) => episode.UniqueIds.Add(uniqueId),
fileName);
break; break;
case "mpaa": case "mpaa":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(episode, contentRating) => episode.ContentRating = contentRating); (episode, contentRating) => episode.ContentRating = contentRating,
fileName);
break; break;
case "aired": case "aired":
await ReadDateTimeContent(reader, nfo, (episode, aired) => episode.Aired = aired); await ReadDateTimeContent(
reader,
nfo,
(episode, aired) => episode.Aired = aired,
fileName);
break; break;
case "plot": case "plot":
await ReadStringContent(reader, nfo, (episode, plot) => episode.Plot = plot); await ReadStringContent(reader, nfo, (episode, plot) => episode.Plot = plot, fileName);
break; break;
case "genre": case "genre":
await ReadStringContent(reader, nfo, (episode, genre) => episode.Genres.Add(genre)); await ReadStringContent(
reader,
nfo,
(episode, genre) => episode.Genres.Add(genre),
fileName);
break; break;
case "tag": case "tag":
await ReadStringContent(reader, nfo, (episode, tag) => episode.Tags.Add(tag)); await ReadStringContent(reader, nfo, (episode, tag) => episode.Tags.Add(tag), fileName);
break; break;
case "actor": case "actor":
ReadActor(reader, nfo, (episode, actor) => episode.Actors.Add(actor)); ReadActor(reader, nfo, (episode, actor) => episode.Actors.Add(actor), fileName);
break; break;
case "credits": case "credits":
await ReadStringContent(reader, nfo, (episode, writer) => episode.Writers.Add(writer)); await ReadStringContent(
reader,
nfo,
(episode, writer) => episode.Writers.Add(writer),
fileName);
break; break;
case "director": case "director":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(episode, director) => episode.Directors.Add(director)); (episode, director) => episode.Directors.Add(director),
fileName);
break; break;
} }
@ -117,7 +142,7 @@ public class EpisodeNfoReader : NfoReader<EpisodeNfo>, IEpisodeNfoReader
} }
catch (XmlException) catch (XmlException)
{ {
_logger.LogWarning("Invalid XML detected; returning incomplete metadata"); _logger.LogWarning("Invalid XML detected in file {FileName}; returning incomplete metadata", fileName);
return result; return result;
} }
catch (Exception ex) catch (Exception ex)

65
ErsatzTV.Scanner/Core/Metadata/Nfo/MovieNfoReader.cs

@ -28,11 +28,11 @@ public class MovieNfoReader : NfoReader<MovieNfo>, IMovieNfoReader
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
await using (Stream s = await SanitizedStreamForFile(fileName)) await using (Stream s = await SanitizedStreamForFile(fileName))
{ {
return await Read(s); return await Read(s, fileName);
} }
} }
internal async Task<Either<BaseError, MovieNfo>> Read(Stream input) internal async Task<Either<BaseError, MovieNfo>> Read(Stream input, string fileName)
{ {
MovieNfo? nfo = null; MovieNfo? nfo = null;
@ -53,55 +53,82 @@ public class MovieNfoReader : NfoReader<MovieNfo>, IMovieNfoReader
nfo = new MovieNfo(); nfo = new MovieNfo();
break; break;
case "title": case "title":
await ReadStringContent(reader, nfo, (movie, title) => movie.Title = title); await ReadStringContent(reader, nfo, (movie, title) => movie.Title = title, fileName);
break; break;
case "sorttitle": case "sorttitle":
await ReadStringContent(reader, nfo, (movie, sortTitle) => movie.SortTitle = sortTitle); await ReadStringContent(
reader,
nfo,
(movie, sortTitle) => movie.SortTitle = sortTitle,
fileName);
break; break;
case "outline": case "outline":
await ReadStringContent(reader, nfo, (movie, outline) => movie.Outline = outline); await ReadStringContent(
reader,
nfo,
(movie, outline) => movie.Outline = outline,
fileName);
break; break;
case "year": case "year":
await ReadIntContent(reader, nfo, (movie, year) => movie.Year = year); await ReadIntContent(reader, nfo, (movie, year) => movie.Year = year, fileName);
break; break;
case "mpaa": case "mpaa":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(movie, contentRating) => movie.ContentRating = contentRating); (movie, contentRating) => movie.ContentRating = contentRating,
fileName);
break; break;
case "premiered": case "premiered":
await ReadDateTimeContent( await ReadDateTimeContent(
reader, reader,
nfo, nfo,
(movie, premiered) => movie.Premiered = premiered); (movie, premiered) => movie.Premiered = premiered,
fileName);
break; break;
case "plot": case "plot":
await ReadStringContent(reader, nfo, (movie, plot) => movie.Plot = plot); await ReadStringContent(reader, nfo, (movie, plot) => movie.Plot = plot, fileName);
break; break;
case "genre": case "genre":
await ReadStringContent(reader, nfo, (movie, genre) => movie.Genres.Add(genre)); await ReadStringContent(
reader,
nfo,
(movie, genre) => movie.Genres.Add(genre),
fileName);
break; break;
case "tag": case "tag":
await ReadStringContent(reader, nfo, (movie, tag) => movie.Tags.Add(tag)); await ReadStringContent(reader, nfo, (movie, tag) => movie.Tags.Add(tag), fileName);
break; break;
case "studio": case "studio":
await ReadStringContent(reader, nfo, (movie, studio) => movie.Studios.Add(studio)); await ReadStringContent(
reader,
nfo,
(movie, studio) => movie.Studios.Add(studio),
fileName);
break; break;
case "actor": case "actor":
ReadActor(reader, nfo, (movie, actor) => movie.Actors.Add(actor)); ReadActor(reader, nfo, (movie, actor) => movie.Actors.Add(actor), fileName);
break; break;
case "credits": case "credits":
await ReadStringContent(reader, nfo, (movie, writer) => movie.Writers.Add(writer)); await ReadStringContent(
reader,
nfo,
(movie, writer) => movie.Writers.Add(writer),
fileName);
break; break;
case "director": case "director":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(movie, director) => movie.Directors.Add(director)); (movie, director) => movie.Directors.Add(director),
fileName);
break; break;
case "uniqueid": case "uniqueid":
await ReadUniqueId(reader, nfo, (movie, uniqueid) => movie.UniqueIds.Add(uniqueid)); await ReadUniqueId(
reader,
nfo,
(movie, uniqueid) => movie.UniqueIds.Add(uniqueid),
fileName);
break; break;
} }
@ -116,12 +143,12 @@ public class MovieNfoReader : NfoReader<MovieNfo>, IMovieNfoReader
} }
} }
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (XmlException) catch (XmlException)
{ {
_logger.LogWarning("Invalid XML detected; returning incomplete metadata"); _logger.LogWarning("Invalid XML detected in file {FileName}; returning incomplete metadata", fileName);
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (Exception ex) catch (Exception ex)
{ {

60
ErsatzTV.Scanner/Core/Metadata/Nfo/MusicVideoNfoReader.cs

@ -28,11 +28,11 @@ public class MusicVideoNfoReader : NfoReader<MusicVideoNfo>, IMusicVideoNfoReade
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
await using (Stream s = await SanitizedStreamForFile(fileName)) await using (Stream s = await SanitizedStreamForFile(fileName))
{ {
return await Read(s); return await Read(s, fileName);
} }
} }
internal async Task<Either<BaseError, MusicVideoNfo>> Read(Stream input) internal async Task<Either<BaseError, MusicVideoNfo>> Read(Stream input, string fileName)
{ {
MusicVideoNfo? nfo = null; MusicVideoNfo? nfo = null;
@ -56,46 +56,74 @@ public class MusicVideoNfoReader : NfoReader<MusicVideoNfo>, IMusicVideoNfoReade
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(musicVideo, artist) => musicVideo.Artists.Add(artist)); (musicVideo, artist) => musicVideo.Artists.Add(artist),
fileName);
break; break;
case "title": case "title":
await ReadStringContent(reader, nfo, (musicVideo, title) => musicVideo.Title = title); await ReadStringContent(
reader,
nfo,
(musicVideo, title) => musicVideo.Title = title,
fileName);
break; break;
case "album": case "album":
await ReadStringContent(reader, nfo, (musicVideo, album) => musicVideo.Album = album); await ReadStringContent(
reader,
nfo,
(musicVideo, album) => musicVideo.Album = album,
fileName);
break; break;
case "plot": case "plot":
await ReadStringContent(reader, nfo, (musicVideo, plot) => musicVideo.Plot = plot); await ReadStringContent(
reader,
nfo,
(musicVideo, plot) => musicVideo.Plot = plot,
fileName);
break; break;
case "track": case "track":
await ReadIntContent(reader, nfo, (musicVideo, track) => musicVideo.Track = track); await ReadIntContent(
reader,
nfo,
(musicVideo, track) => musicVideo.Track = track,
fileName);
break; break;
case "year": case "year":
await ReadIntContent(reader, nfo, (musicVideo, year) => musicVideo.Year = year); await ReadIntContent(
reader,
nfo,
(musicVideo, year) => musicVideo.Year = year,
fileName);
break; break;
case "aired": case "aired":
await ReadDateTimeContent(reader, nfo, (show, aired) => show.Aired = aired); await ReadDateTimeContent(reader, nfo, (show, aired) => show.Aired = aired, fileName);
break; break;
case "genre": case "genre":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(musicVideo, genre) => musicVideo.Genres.Add(genre)); (musicVideo, genre) => musicVideo.Genres.Add(genre),
fileName);
break; break;
case "tag": case "tag":
await ReadStringContent(reader, nfo, (musicVideo, tag) => musicVideo.Tags.Add(tag)); await ReadStringContent(
reader,
nfo,
(musicVideo, tag) => musicVideo.Tags.Add(tag),
fileName);
break; break;
case "studio": case "studio":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(musicVideo, studio) => musicVideo.Studios.Add(studio)); (musicVideo, studio) => musicVideo.Studios.Add(studio),
fileName);
break; break;
case "director": case "director":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(musicVideo, director) => musicVideo.Directors.Add(director)); (musicVideo, director) => musicVideo.Directors.Add(director),
fileName);
break; break;
} }
@ -110,12 +138,12 @@ public class MusicVideoNfoReader : NfoReader<MusicVideoNfo>, IMusicVideoNfoReade
} }
} }
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (XmlException) catch (XmlException)
{ {
_logger.LogWarning("Invalid XML detected; returning incomplete metadata"); _logger.LogWarning("Invalid XML detected in file {FileName}; returning incomplete metadata", fileName);
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (Exception ex) catch (Exception ex)
{ {

20
ErsatzTV.Scanner/Core/Metadata/Nfo/NfoReader.cs

@ -37,7 +37,7 @@ public abstract class NfoReader<T> : NfoReaderBase
return ms; return ms;
} }
protected async Task ReadStringContent(XmlReader reader, T? nfo, Action<T, string> action) protected async Task ReadStringContent(XmlReader reader, T? nfo, Action<T, string> action, string fileName)
{ {
try try
{ {
@ -49,11 +49,11 @@ public abstract class NfoReader<T> : NfoReaderBase
} }
catch (XmlException ex) catch (XmlException ex)
{ {
_logger.LogWarning(ex, "Error reading string content from NFO {ElementName}", reader.Name); _logger.LogWarning(ex, "Error reading string content from NFO {ElementName} file {FileName}", reader.Name, fileName);
} }
} }
protected async Task ReadIntContent(XmlReader reader, T? nfo, Action<T, int> action) protected async Task ReadIntContent(XmlReader reader, T? nfo, Action<T, int> action, string fileName)
{ {
try try
{ {
@ -64,11 +64,11 @@ public abstract class NfoReader<T> : NfoReaderBase
} }
catch (XmlException ex) catch (XmlException ex)
{ {
_logger.LogWarning(ex, "Error reading int content from NFO {ElementName}", reader.Name); _logger.LogWarning(ex, "Error reading int content from NFO {ElementName} file {FileName}", reader.Name, fileName);
} }
} }
protected async Task ReadDateTimeContent(XmlReader reader, T? nfo, Action<T, DateTime> action) protected async Task ReadDateTimeContent(XmlReader reader, T? nfo, Action<T, DateTime> action, string fileName)
{ {
try try
{ {
@ -81,11 +81,11 @@ public abstract class NfoReader<T> : NfoReaderBase
} }
catch (XmlException ex) catch (XmlException ex)
{ {
_logger.LogWarning(ex, "Error reading date content from NFO {ElementName}", reader.Name); _logger.LogWarning(ex, "Error reading date content from NFO {ElementName} file {FileName}", reader.Name, fileName);
} }
} }
protected void ReadActor(XmlReader reader, T? nfo, Action<T, ActorNfo> action) protected void ReadActor(XmlReader reader, T? nfo, Action<T, ActorNfo> action, string fileName)
{ {
try try
{ {
@ -123,11 +123,11 @@ public abstract class NfoReader<T> : NfoReaderBase
} }
catch (XmlException ex) catch (XmlException ex)
{ {
_logger.LogWarning(ex, "Error reading actor content from NFO {ElementName}", reader.Name); _logger.LogWarning(ex, "Error reading actor content from NFO {ElementName} file {FileName}", reader.Name, fileName);
} }
} }
protected async Task ReadUniqueId(XmlReader reader, T? nfo, Action<T, UniqueIdNfo> action) protected async Task ReadUniqueId(XmlReader reader, T? nfo, Action<T, UniqueIdNfo> action, string fileName)
{ {
try try
{ {
@ -146,7 +146,7 @@ public abstract class NfoReader<T> : NfoReaderBase
} }
catch (XmlException ex) catch (XmlException ex)
{ {
_logger.LogWarning(ex, "Error reading uniqueid content from NFO {ElementName}", reader.Name); _logger.LogWarning(ex, "Error reading uniqueid content from NFO {ElementName} file {FileName}", reader.Name, fileName);
} }
} }
} }

64
ErsatzTV.Scanner/Core/Metadata/Nfo/OtherVideoNfoReader.cs

@ -28,11 +28,11 @@ public class OtherVideoNfoReader : NfoReader<OtherVideoNfo>, IOtherVideoNfoReade
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
await using (Stream s = await SanitizedStreamForFile(fileName)) await using (Stream s = await SanitizedStreamForFile(fileName))
{ {
return await Read(s); return await Read(s, fileName);
} }
} }
internal async Task<Either<BaseError, OtherVideoNfo>> Read(Stream input) internal async Task<Either<BaseError, OtherVideoNfo>> Read(Stream input, string fileName)
{ {
OtherVideoNfo? nfo = null; OtherVideoNfo? nfo = null;
@ -60,55 +60,81 @@ public class OtherVideoNfoReader : NfoReader<OtherVideoNfo>, IOtherVideoNfoReade
nfo = new OtherVideoNfo(); nfo = new OtherVideoNfo();
break; break;
case "title": case "title":
await ReadStringContent(reader, nfo, (movie, title) => movie.Title = title); await ReadStringContent(reader, nfo, (movie, title) => movie.Title = title, fileName);
break; break;
case "sorttitle": case "sorttitle":
await ReadStringContent(reader, nfo, (movie, sortTitle) => movie.SortTitle = sortTitle); await ReadStringContent(
reader,
nfo,
(movie, sortTitle) => movie.SortTitle = sortTitle,
fileName);
break; break;
case "outline": case "outline":
await ReadStringContent(reader, nfo, (movie, outline) => movie.Outline = outline); await ReadStringContent(
reader,
nfo,
(movie, outline) => movie.Outline = outline,
fileName);
break; break;
case "year": case "year":
await ReadIntContent(reader, nfo, (movie, year) => movie.Year = year); await ReadIntContent(reader, nfo, (movie, year) => movie.Year = year, fileName);
break; break;
case "mpaa": case "mpaa":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(movie, contentRating) => movie.ContentRating = contentRating); (movie, contentRating) => movie.ContentRating = contentRating, fileName);
break; break;
case "premiered": case "premiered":
await ReadDateTimeContent( await ReadDateTimeContent(
reader, reader,
nfo, nfo,
(movie, premiered) => movie.Premiered = premiered); (movie, premiered) => movie.Premiered = premiered,
fileName);
break; break;
case "plot": case "plot":
await ReadStringContent(reader, nfo, (movie, plot) => movie.Plot = plot); await ReadStringContent(reader, nfo, (movie, plot) => movie.Plot = plot, fileName);
break; break;
case "genre": case "genre":
await ReadStringContent(reader, nfo, (movie, genre) => movie.Genres.Add(genre)); await ReadStringContent(
reader,
nfo,
(movie, genre) => movie.Genres.Add(genre),
fileName);
break; break;
case "tag": case "tag":
await ReadStringContent(reader, nfo, (movie, tag) => movie.Tags.Add(tag)); await ReadStringContent(reader, nfo, (movie, tag) => movie.Tags.Add(tag), fileName);
break; break;
case "studio": case "studio":
await ReadStringContent(reader, nfo, (movie, studio) => movie.Studios.Add(studio)); await ReadStringContent(
reader,
nfo,
(movie, studio) => movie.Studios.Add(studio),
fileName);
break; break;
case "actor": case "actor":
ReadActor(reader, nfo, (movie, actor) => movie.Actors.Add(actor)); ReadActor(reader, nfo, (movie, actor) => movie.Actors.Add(actor), fileName);
break; break;
case "credits": case "credits":
await ReadStringContent(reader, nfo, (movie, writer) => movie.Writers.Add(writer)); await ReadStringContent(
reader,
nfo,
(movie, writer) => movie.Writers.Add(writer),
fileName);
break; break;
case "director": case "director":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(movie, director) => movie.Directors.Add(director)); (movie, director) => movie.Directors.Add(director),
fileName);
break; break;
case "uniqueid": case "uniqueid":
await ReadUniqueId(reader, nfo, (movie, uniqueid) => movie.UniqueIds.Add(uniqueid)); await ReadUniqueId(
reader,
nfo,
(movie, uniqueid) => movie.UniqueIds.Add(uniqueid),
fileName);
break; break;
} }
@ -123,12 +149,12 @@ public class OtherVideoNfoReader : NfoReader<OtherVideoNfo>, IOtherVideoNfoReade
} }
} }
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (XmlException) catch (XmlException)
{ {
_logger.LogWarning("Invalid XML detected; returning incomplete metadata"); _logger.LogWarning("Invalid XML detected in file {FileName}; returning incomplete metadata", fileName);
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (Exception ex) catch (Exception ex)
{ {

55
ErsatzTV.Scanner/Core/Metadata/Nfo/ShowNfoReader.cs

@ -28,11 +28,11 @@ public class ShowNfoReader : NfoReader<ShowNfo>, IShowNfoReader
// ReSharper disable once ConvertToUsingDeclaration // ReSharper disable once ConvertToUsingDeclaration
await using (Stream s = await SanitizedStreamForFile(fileName)) await using (Stream s = await SanitizedStreamForFile(fileName))
{ {
return await Read(s); return await Read(s, fileName);
} }
} }
internal async Task<Either<BaseError, ShowNfo>> Read(Stream input) internal async Task<Either<BaseError, ShowNfo>> Read(Stream input, string fileName)
{ {
ShowNfo? nfo = null; ShowNfo? nfo = null;
@ -57,45 +57,66 @@ public class ShowNfoReader : NfoReader<ShowNfo>, IShowNfoReader
case "title": case "title":
if (reader.Depth == showDepth + 1) if (reader.Depth == showDepth + 1)
{ {
await ReadStringContent(reader, nfo, (show, title) => show.Title = title); await ReadStringContent(reader, nfo, (show, title) => show.Title = title, fileName);
} }
break; break;
case "year": case "year":
await ReadIntContent(reader, nfo, (show, year) => show.Year = year); await ReadIntContent(reader, nfo, (show, year) => show.Year = year, fileName);
break; break;
case "plot": case "plot":
await ReadStringContent(reader, nfo, (show, plot) => show.Plot = plot); await ReadStringContent(reader, nfo, (show, plot) => show.Plot = plot, fileName);
break; break;
case "outline": case "outline":
await ReadStringContent(reader, nfo, (show, outline) => show.Outline = outline); await ReadStringContent(
reader,
nfo,
(show, outline) => show.Outline = outline,
fileName);
break; break;
case "tagline": case "tagline":
await ReadStringContent(reader, nfo, (show, tagline) => show.Tagline = tagline); await ReadStringContent(
reader,
nfo,
(show, tagline) => show.Tagline = tagline,
fileName);
break; break;
case "mpaa": case "mpaa":
await ReadStringContent( await ReadStringContent(
reader, reader,
nfo, nfo,
(show, contentRating) => show.ContentRating = contentRating); (show, contentRating) => show.ContentRating = contentRating,
fileName);
break; break;
case "premiered": case "premiered":
await ReadDateTimeContent(reader, nfo, (show, premiered) => show.Premiered = premiered); await ReadDateTimeContent(
reader,
nfo,
(show, premiered) => show.Premiered = premiered,
fileName);
break; break;
case "genre": case "genre":
await ReadStringContent(reader, nfo, (show, genre) => show.Genres.Add(genre)); await ReadStringContent(reader, nfo, (show, genre) => show.Genres.Add(genre), fileName);
break; break;
case "tag": case "tag":
await ReadStringContent(reader, nfo, (show, tag) => show.Tags.Add(tag)); await ReadStringContent(reader, nfo, (show, tag) => show.Tags.Add(tag), fileName);
break; break;
case "studio": case "studio":
await ReadStringContent(reader, nfo, (show, studio) => show.Studios.Add(studio)); await ReadStringContent(
reader,
nfo,
(show, studio) => show.Studios.Add(studio),
fileName);
break; break;
case "actor": case "actor":
ReadActor(reader, nfo, (episode, actor) => episode.Actors.Add(actor)); ReadActor(reader, nfo, (episode, actor) => episode.Actors.Add(actor), fileName);
break; break;
case "uniqueid": case "uniqueid":
await ReadUniqueId(reader, nfo, (episode, uniqueid) => episode.UniqueIds.Add(uniqueid)); await ReadUniqueId(
reader,
nfo,
(episode, uniqueid) => episode.UniqueIds.Add(uniqueid),
fileName);
break; break;
} }
@ -110,12 +131,12 @@ public class ShowNfoReader : NfoReader<ShowNfo>, IShowNfoReader
} }
} }
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (XmlException) catch (XmlException)
{ {
_logger.LogWarning("Invalid XML detected; returning incomplete metadata"); _logger.LogWarning("Invalid XML detected in file {FileName}; returning incomplete metadata", fileName);
return Optional(nfo).ToEither((BaseError)new FailedToReadNfo()); return Optional(nfo).ToEither<BaseError>(new FailedToReadNfo());
} }
catch (Exception ex) catch (Exception ex)
{ {

Loading…
Cancel
Save