From a0f13b19cdbca1a3529111194df34d843473fb1a Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 18 Aug 2023 22:32:54 -0700 Subject: [PATCH] New: Parse language tags from existing subtitles files (cherry picked from commit b20e247feb24084348261ef2fad61a05f1fd69e8) --- ...ags_from_existing_subtitle_filesFixture.cs | 113 ++++++++++++++++++ ...guage_tags_from_existing_subtitle_files.cs | 60 ++++++++++ 2 files changed, 173 insertions(+) create mode 100644 src/NzbDrone.Core.Test/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_filesFixture.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_files.cs diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_filesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_filesFixture.cs new file mode 100644 index 000000000..7c0efdf37 --- /dev/null +++ b/src/NzbDrone.Core.Test/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_filesFixture.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dapper; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Datastore.Migration; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.Datastore.Migration +{ + [TestFixture] + public class parse_language_tags_from_existing_subtitle_filesFixture : MigrationTest + { + [Test] + public void should_process_file_with_missing_null_language_tags() + { + var now = DateTime.UtcNow; + + var db = WithDapperMigrationTestDb(c => + { + c.Insert.IntoTable("SubtitleFiles").Row(new + { + SeriesId = 1, + SeasonNumber = 1, + EpisodeFileId = 1, + RelativePath = "S01E05.eng.srt", + Added = now, + LastUpdated = now, + Extension = ".srt", + Language = 1 + }); + }); + + var files = db.Query("SELECT * FROM \"SubtitleFiles\"").ToList(); + + files.Should().HaveCount(1); + files.First().LanguageTags.Should().HaveCount(0); + } + + [Test] + public void should_process_file_with_missing_language_tags() + { + var now = DateTime.UtcNow; + + var db = WithDapperMigrationTestDb(c => + { + c.Insert.IntoTable("SubtitleFiles").Row(new + { + SeriesId = 1, + SeasonNumber = 1, + EpisodeFileId = 1, + RelativePath = "S01E05.eng.forced.srt", + Added = now, + LastUpdated = now, + Extension = ".srt", + Language = 1 + }); + }); + + var files = db.Query("SELECT * FROM \"SubtitleFiles\"").ToList(); + + files.Should().HaveCount(1); + + var languageTags = files.First().LanguageTags; + + languageTags.Should().HaveCount(1); + languageTags.Should().Contain("forced"); + } + + [Test] + public void should_not_process_file_with_empty_language_tags() + { + var now = DateTime.UtcNow; + + var db = WithDapperMigrationTestDb(c => + { + c.Insert.IntoTable("SubtitleFiles").Row(new + { + SeriesId = 1, + SeasonNumber = 1, + EpisodeFileId = 1, + RelativePath = "S01E05.eng.srt", + Added = now, + LastUpdated = now, + Extension = ".srt", + Language = 1, + LanguageTags = "[]" + }); + }); + + var files = db.Query("SELECT * FROM \"SubtitleFiles\"").ToList(); + + files.Should().HaveCount(1); + files.First().LastUpdated.Should().BeCloseTo(now, TimeSpan.FromMilliseconds(999)); + files.First().LanguageTags.Should().HaveCount(0); + } + } + + public class SubtitleFile195 + { + public int Id { get; set; } + public int SeriesId { get; set; } + public int? EpisodeFileId { get; set; } + public int? SeasonNumber { get; set; } + public string RelativePath { get; set; } + public DateTime Added { get; set; } + public DateTime LastUpdated { get; set; } + public string Extension { get; set; } + public int Language { get; set; } + public List LanguageTags { get; set; } + } +} diff --git a/src/NzbDrone.Core/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_files.cs b/src/NzbDrone.Core/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_files.cs new file mode 100644 index 000000000..b49bfaae5 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/195_parse_language_tags_from_existing_subtitle_files.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Text.Json; +using System.Text.Json.Serialization; +using Dapper; +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; +using NzbDrone.Core.Parser; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(195)] + public class parse_language_tags_from_existing_subtitle_files : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Execute.WithConnection(UpdateLanguageTags); + } + + private void UpdateLanguageTags(IDbConnection conn, IDbTransaction tran) + { + var updatedLanguageTags = new List(); + var now = DateTime.Now; + + using (var cmd = conn.CreateCommand()) + { + cmd.Transaction = tran; + cmd.CommandText = "SELECT \"Id\", \"RelativePath\" FROM \"SubtitleFiles\" WHERE \"LanguageTags\" IS NULL"; + + using var reader = cmd.ExecuteReader(); + while (reader.Read()) + { + var id = reader.GetInt32(0); + var relativePath = reader.GetString(1); + var languageTags = LanguageParser.ParseLanguageTags(relativePath); + + updatedLanguageTags.Add(new + { + Id = id, + LanguageTags = languageTags + }); + } + } + + var serializerSettings = new JsonSerializerOptions + { + AllowTrailingCommas = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNameCaseInsensitive = true, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true + }; + + var updateSubtitleFilesSql = "UPDATE \"SubtitleFiles\" SET \"LanguageTags\" = @LanguageTags, \"LastUpdated\" = CURRENT_TIMESTAMP WHERE \"Id\" = @Id"; + conn.Execute(updateSubtitleFilesSql, updatedLanguageTags, transaction: tran); + } + } +}