MigrateRatingLevels.cs 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System;
  2. using System.Globalization;
  3. using System.IO;
  4. using Emby.Server.Implementations.Data;
  5. using MediaBrowser.Controller;
  6. using MediaBrowser.Model.Globalization;
  7. using Microsoft.Data.Sqlite;
  8. using Microsoft.Extensions.Logging;
  9. namespace Jellyfin.Server.Migrations.Routines
  10. {
  11. /// <summary>
  12. /// Migrate rating levels to new rating level system.
  13. /// </summary>
  14. internal class MigrateRatingLevels : IMigrationRoutine
  15. {
  16. private const string DbFilename = "library.db";
  17. private readonly ILogger<MigrateRatingLevels> _logger;
  18. private readonly IServerApplicationPaths _applicationPaths;
  19. private readonly ILocalizationManager _localizationManager;
  20. public MigrateRatingLevels(
  21. IServerApplicationPaths applicationPaths,
  22. ILoggerFactory loggerFactory,
  23. ILocalizationManager localizationManager)
  24. {
  25. _applicationPaths = applicationPaths;
  26. _localizationManager = localizationManager;
  27. _logger = loggerFactory.CreateLogger<MigrateRatingLevels>();
  28. }
  29. /// <inheritdoc/>
  30. public Guid Id => Guid.Parse("{73DAB92A-178B-48CD-B05B-FE18733ACDC8}");
  31. /// <inheritdoc/>
  32. public string Name => "MigrateRatingLevels";
  33. /// <inheritdoc/>
  34. public bool PerformOnNewInstall => false;
  35. /// <inheritdoc/>
  36. public void Perform()
  37. {
  38. var dbPath = Path.Combine(_applicationPaths.DataPath, DbFilename);
  39. // Back up the database before modifying any entries
  40. for (int i = 1; ; i++)
  41. {
  42. var bakPath = string.Format(CultureInfo.InvariantCulture, "{0}.bak{1}", dbPath, i);
  43. if (!File.Exists(bakPath))
  44. {
  45. try
  46. {
  47. File.Copy(dbPath, bakPath);
  48. _logger.LogInformation("Library database backed up to {BackupPath}", bakPath);
  49. break;
  50. }
  51. catch (Exception ex)
  52. {
  53. _logger.LogError(ex, "Cannot make a backup of {Library} at path {BackupPath}", DbFilename, bakPath);
  54. throw;
  55. }
  56. }
  57. }
  58. // Migrate parental rating strings to new levels
  59. _logger.LogInformation("Recalculating parental rating levels based on rating string.");
  60. using var connection = new SqliteConnection($"Filename={dbPath}");
  61. connection.Open();
  62. using (var transaction = connection.BeginTransaction())
  63. {
  64. var queryResult = connection.Query("SELECT DISTINCT OfficialRating FROM TypedBaseItems");
  65. foreach (var entry in queryResult)
  66. {
  67. if (!entry.TryGetString(0, out var ratingString) || string.IsNullOrEmpty(ratingString))
  68. {
  69. connection.Execute("UPDATE TypedBaseItems SET InheritedParentalRatingValue = NULL WHERE OfficialRating IS NULL OR OfficialRating='';");
  70. }
  71. else
  72. {
  73. var ratingValue = _localizationManager.GetRatingLevel(ratingString)?.ToString(CultureInfo.InvariantCulture) ?? "NULL";
  74. using var statement = connection.PrepareStatement("UPDATE TypedBaseItems SET InheritedParentalRatingValue = @Value WHERE OfficialRating = @Rating;");
  75. statement.TryBind("@Value", ratingValue);
  76. statement.TryBind("@Rating", ratingString);
  77. statement.ExecuteNonQuery();
  78. }
  79. }
  80. transaction.Commit();
  81. }
  82. }
  83. }
  84. }