mirror of
https://github.com/sphildreth/roadie
synced 2024-11-22 04:03:10 +00:00
resolves #31
This commit is contained in:
parent
a370108b64
commit
48dd411ffb
17 changed files with 164 additions and 22 deletions
|
@ -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")]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
2
Upgrade0008.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- New SortName columns
|
||||
ALTER TABLE `genre` ADD sortName varchar(100) NULL;
|
|
@ -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`),
|
||||
|
|
Loading…
Reference in a new issue