This commit is contained in:
Steven Hildreth 2019-11-10 08:48:07 -06:00
parent a370108b64
commit 48dd411ffb
17 changed files with 164 additions and 22 deletions

View file

@ -105,6 +105,22 @@ namespace Roadie.Library.Tests
Assert.Equal(t.FullName, artistFolder);
}
[Theory]
[InlineData("!SÖmëthing el$e", @"S\SO")]
[InlineData("Alternative Singer/Songwriter", @"A\AL")]
[InlineData("Adult Alternative", @"A\AD")]
[InlineData("Progressive Bluegrass", @"P\PR")]
[InlineData("Western European Traditions", @"W\WE")]
[InlineData("2-Step/British Garage", @"0\2S")]
[InlineData("80's/synthwave/outrun/new retro wave", @"0\80")]
[InlineData("Western Swing Revival", @"W\WE")]
public void GenerateGenreFolderNames(string input, string shouldBe)
{
var artistFolder = FolderPathHelper.GenrePath(Configuration, input);
var t = new DirectoryInfo(Path.Combine(Configuration.GenreImageFolder, shouldBe));
Assert.Equal(t.FullName, artistFolder);
}
[Theory]
[InlineData("What Dreams May Come", "01/15/2004", @"D\DR\Dream Theater [99]", @"D\DR\Dream Theater [99]\[2004] What Dreams May Come")]
[InlineData("Killers", "01/01/1980", @"I\IR\Iron Maiden [9909]", @"I\IR\Iron Maiden [9909]\[1980] Killers")]

View file

@ -44,9 +44,14 @@ namespace Roadie.Library.Data
/// <summary>
/// Returns a full file path to the Collection Image
/// </summary>
public string PathToImage(IRoadieSettings configuration)
public string PathToImage(IRoadieSettings configuration, bool makeFolderIfNotExist = false)
{
return Path.Combine(configuration.CollectionImageFolder, $"{ (SortName ?? Name).ToFileNameFriendly() } [{ Id }].jpg");
var folder = configuration.CollectionImageFolder;
if (!Directory.Exists(folder) && makeFolderIfNotExist)
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, $"{ (SortName ?? Name).ToFileNameFriendly() } [{ Id }].jpg");
}
public int PositionColumn

View file

@ -12,7 +12,16 @@ namespace Roadie.Library.Data
public ICollection<Comment> Comments { get; set; }
[Column("name")] [MaxLength(100)] public string Name { get; set; }
[Column("name")]
[MaxLength(100)]
[Required]
public string Name { get; set; }
[Column("sortName")]
[MaxLength(100)]
public string SortName { get; set; }
public string SortNameValue => string.IsNullOrEmpty(SortName) ? Name : SortName;
[Column("description")]
[MaxLength(4000)]

View file

@ -1,5 +1,6 @@
using Roadie.Library.Configuration;
using Roadie.Library.Extensions;
using Roadie.Library.Utility;
using System;
using System.IO;
@ -11,14 +12,37 @@ namespace Roadie.Library.Data
public string CacheRegion => CacheRegionUrn(RoadieId);
///// <summary>
///// Returns a full file path to the Genre Image
///// </summary>
//public string PathToImage(IRoadieSettings configuration)
//{
// return Path.Combine(configuration.GenreImageFolder, $"{ Name.ToFileNameFriendly() } [{ Id }].jpg");
//}
/// <summary>
/// Returns a full file path to the Genre Image
/// </summary>
public string PathToImage(IRoadieSettings configuration)
public string PathToImage(IRoadieSettings configuration, bool makeFolderIfNotExist = false)
{
return Path.Combine(configuration.GenreImageFolder, $"{ Name.ToFileNameFriendly() } [{ Id }].jpg");
var folder = FolderPathHelper.GenrePath(configuration, SortNameValue);
if(!Directory.Exists(folder) && makeFolderIfNotExist)
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, $"{ SortNameValue.ToFileNameFriendly() } [{ Id }].jpg");
}
/// <summary>
/// Returns a full file path to the Label Image
/// </summary>
[Obsolete("This is only here for migration will be removed in future release.")]
public string OldPathToImage(IRoadieSettings configuration)
{
return Path.Combine(configuration.GenreImageFolder, $"{ SortNameValue.ToFileNameFriendly() } [{ Id }].jpg");
}
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:genre:{0}", Id);

View file

@ -28,9 +28,14 @@ namespace Roadie.Library.Data
/// <summary>
/// Returns a full file path to the Label Image
/// </summary>
public string PathToImage(IRoadieSettings configuration)
public string PathToImage(IRoadieSettings configuration, bool makeFolderIfNotExist = false)
{
return Path.Combine(FolderPathHelper.LabelPath(configuration, SortNameValue), $"{ SortNameValue.ToFileNameFriendly() } [{ Id }].jpg");
var folder = FolderPathHelper.LabelPath(configuration, SortNameValue);
if (!Directory.Exists(folder) && makeFolderIfNotExist)
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, $"{ SortNameValue.ToFileNameFriendly() } [{ Id }].jpg");
}
/// <summary>

View file

@ -25,9 +25,14 @@ namespace Roadie.Library.Data
/// <summary>
/// Returns a full file path to the Playlist Image
/// </summary>
public string PathToImage(IRoadieSettings configuration)
public string PathToImage(IRoadieSettings configuration, bool makeFolderIfNotExist = false)
{
return Path.Combine(configuration.PlaylistImageFolder, $"{ (SortName ?? Name).ToFileNameFriendly() } [{ Id }].jpg");
var folder = configuration.PlaylistImageFolder;
if (!Directory.Exists(folder) && makeFolderIfNotExist)
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, $"{ (SortName ?? Name).ToFileNameFriendly() } [{ Id }].jpg");
}
public override string ToString()

View file

@ -20,9 +20,14 @@ namespace Roadie.Library.Identity
/// <summary>
/// Returns a full file path to the User Image
/// </summary>
public string PathToImage(IRoadieSettings configuration)
public string PathToImage(IRoadieSettings configuration, bool makeFolderIfNotExist = false)
{
return Path.Combine(configuration.UserImageFolder, $"{ UserName.ToFileNameFriendly() } [{ Id }].gif");
var folder = configuration.UserImageFolder;
if (!Directory.Exists(folder) && makeFolderIfNotExist)
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, $"{ UserName.ToFileNameFriendly() } [{ Id }].gif");
}
public ApplicationUser()

View file

@ -19,7 +19,8 @@ namespace Roadie.Library.Utility
public static int MaximumLibraryFolderNameLength = 44;
public static int MaximumArtistFolderNameLength = 100;
public static int MaximumReleaseFolderNameLength = 100;
public static int MaximumLabelFolderNameLength = 100;
public static int MaximumLabelFolderNameLength = 80;
public static int MaximumGenreFolderNameLength = 80;
public static int MaximumTrackFileNameLength = 500;
public static IEnumerable<string> FolderSpaceReplacements = new List<string> { ".", "~", "_", "=", "-" };
@ -78,11 +79,10 @@ namespace Roadie.Library.Utility
return directoryInfo.FullName;
}
public static string LabelPath(IRoadieSettings configuration, string labelSortName)
{
SimpleContract.Requires<ArgumentException>(!string.IsNullOrEmpty(labelSortName), "Invalid Label Sort Name");
SimpleContract.Requires<ArgumentException>(configuration.LibraryFolder.Length < MaximumLibraryFolderNameLength, $"Library Folder maximum length is [{ MaximumLibraryFolderNameLength }]");
SimpleContract.Requires<ArgumentException>(configuration.LabelImageFolder.Length < MaximumLabelFolderNameLength, $"Label Image Folder maximum length is [{ MaximumLibraryFolderNameLength }]");
var lsn = new StringBuilder(labelSortName);
foreach (var stringReplacement in FolderSpaceReplacements)
@ -122,6 +122,50 @@ namespace Roadie.Library.Utility
return directoryInfo.FullName;
}
public static string GenrePath(IRoadieSettings configuration, string genreSortName)
{
SimpleContract.Requires<ArgumentException>(!string.IsNullOrEmpty(genreSortName), "Invalid Genre Sort Name");
SimpleContract.Requires<ArgumentException>(configuration.GenreImageFolder.Length < MaximumGenreFolderNameLength, $"Genre Image Folder maximum length is [{ MaximumLibraryFolderNameLength }]");
var lsn = new StringBuilder(genreSortName);
foreach (var stringReplacement in FolderSpaceReplacements)
{
if (!lsn.Equals(stringReplacement))
{
lsn.Replace(stringReplacement, " ");
}
}
var genreFolder = lsn.ToString().ToAlphanumericName(false, false).ToFolderNameFriendly().ToTitleCase(false);
if (string.IsNullOrEmpty(genreFolder))
{
throw new Exception($"GenreFolder [{ genreFolder }] is invalid. GenreSortName [{ genreSortName }].");
}
var lfUpper = genreFolder.ToUpper();
var fnSubPart1 = lfUpper.ToUpper().ToCharArray().Take(1).First();
if (!char.IsLetterOrDigit(fnSubPart1))
{
fnSubPart1 = '#';
}
else if (char.IsNumber(fnSubPart1))
{
fnSubPart1 = '0';
}
var fnSubPart2 = lfUpper.Length > 2 ? lfUpper.Substring(0, 2) : lfUpper;
if (fnSubPart2.EndsWith(" "))
{
var pos = 1;
while (fnSubPart2.EndsWith(" "))
{
pos++;
fnSubPart2 = fnSubPart2.Substring(0, 1) + lfUpper.Substring(pos, 1);
}
}
var fnSubPart = Path.Combine(fnSubPart1.ToString(), fnSubPart2);
var directoryInfo = new DirectoryInfo(Path.Combine(configuration.GenreImageFolder, fnSubPart));
return directoryInfo.FullName;
}
[Obsolete("This is only here for migration will be removed in future release.")]
public static string ArtistPathOld(IRoadieSettings configuration, string artistSortName)
{

View file

@ -1110,6 +1110,28 @@ namespace Roadie.Api.Services
}
Logger.LogInformation($"Label Migration Complete. Migrated [{ labelsMigrated }] Labels.");
var genresMigrated = 0;
foreach (var genre in DbContext.Genres.Where(x => x.Status == Statuses.ReadyToMigrate).ToArray())
{
var oldGenreImageFileName = genre.OldPathToImage(Configuration);
var genreImageFileName = genre.PathToImage(Configuration);
if (File.Exists(oldGenreImageFileName))
{
var genreFileInfo = new FileInfo(genreImageFileName);
if (!genreFileInfo.Directory.Exists)
{
Directory.CreateDirectory(genreFileInfo.Directory.FullName);
}
File.Move(oldGenreImageFileName, genreImageFileName, true);
genre.Status = Statuses.Migrated;
genre.LastUpdated = now;
await DbContext.SaveChangesAsync();
Logger.LogInformation($"Migrated Genre Storage `{ genre}` From [{ oldGenreImageFileName }] => [{ genreImageFileName }]");
genresMigrated++;
}
}
Logger.LogInformation($"Genre Migration Complete. Migrated [{ genresMigrated }] Genres.");
var releases = DbContext.Releases
.Include(x => x.Artist)
.Include(x => x.Medias)

View file

@ -301,7 +301,7 @@ namespace Roadie.Api.Services
if (collectionImage != null)
{
// Save unaltered collection image
File.WriteAllBytes(collection.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(collectionImage));
File.WriteAllBytes(collection.PathToImage(Configuration, true), ImageHelper.ConvertToJpegFormat(collectionImage));
}
if (model.Maintainer?.Value != null)
{

View file

@ -236,14 +236,17 @@ namespace Roadie.Api.Services
sw.Start();
var errors = new List<Exception>();
var genre = DbContext.Genres.FirstOrDefault(x => x.RoadieId == id);
if (genre == null) return new OperationResult<Library.Models.Image>(true, string.Format("Genre Not Found [{0}]", id));
if (genre == null)
{
return new OperationResult<Library.Models.Image>(true, string.Format("Genre Not Found [{0}]", id));
}
try
{
var now = DateTime.UtcNow;
if (imageBytes != null)
{
// Save unaltered label image
File.WriteAllBytes(genre.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(imageBytes));
// Save unaltered genre image
File.WriteAllBytes(genre.PathToImage(Configuration, true), ImageHelper.ConvertToJpegFormat(imageBytes));
}
genre.LastUpdated = now;
await DbContext.SaveChangesAsync();

View file

@ -461,7 +461,7 @@ namespace Roadie.Api.Services
if (imageBytes != null)
{
// Save unaltered label image
File.WriteAllBytes(label.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(imageBytes));
File.WriteAllBytes(label.PathToImage(Configuration, true), ImageHelper.ConvertToJpegFormat(imageBytes));
}
label.LastUpdated = now;
await DbContext.SaveChangesAsync();

View file

@ -352,7 +352,7 @@ namespace Roadie.Api.Services
if (playlistImage != null)
{
// Save unaltered playlist image
File.WriteAllBytes(playlist.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(playlistImage));
File.WriteAllBytes(playlist.PathToImage(Configuration, true), ImageHelper.ConvertToJpegFormat(playlistImage));
}
playlist.LastUpdated = now;
await DbContext.SaveChangesAsync();

View file

@ -503,7 +503,7 @@ namespace Roadie.Api.Services
imageData = ImageHelper.ConvertToGifFormat(imageData);
// Save unaltered user image
File.WriteAllBytes(user.PathToImage(Configuration), imageData);
File.WriteAllBytes(user.PathToImage(Configuration, true), imageData);
}
}

View file

@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{1BA7
Upgrade0005.sql = Upgrade0005.sql
Upgrade0006.sql = Upgrade0006.sql
Upgrade0007.sql = Upgrade0007.sql
Upgrade0008.sql = Upgrade0008.sql
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roadie.Api.Services", "Roadie.Api.Services\Roadie.Api.Services.csproj", "{7B37031E-F2AE-4BE2-9F6F-005CA7A6FDF1}"

2
Upgrade0008.sql Normal file
View file

@ -0,0 +1,2 @@
-- New SortName columns
ALTER TABLE `genre` ADD sortName varchar(100) NULL;

View file

@ -337,6 +337,7 @@ CREATE TABLE `genre` (
`createdDate` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`sortName` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`normalizedName` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`thumbnail` blob DEFAULT NULL,
`alternateNames` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
@ -511,6 +512,7 @@ CREATE TABLE `release` (
`lastUpdated` datetime DEFAULT NULL,
`isVirtual` tinyint(1) DEFAULT NULL,
`title` varchar(250) COLLATE utf8mb4_unicode_ci NOT NULL,
`sortTitle` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`alternateNames` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`releaseDate` date DEFAULT NULL,
`rating` smallint(6) NOT NULL,
@ -534,7 +536,6 @@ CREATE TABLE `release` (
`playedCount` int(11) DEFAULT NULL,
`duration` int(11) DEFAULT NULL,
`rank` decimal(9,2) DEFAULT NULL,
`sortTitle` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_releaseArtistAndTitle` (`artistId`,`title`),
KEY `ix_release_roadieId` (`roadieId`),