mirror of
https://github.com/sphildreth/roadie
synced 2024-11-22 04:03:10 +00:00
resolves #29
This commit is contained in:
parent
cb37aabf40
commit
f385c8f6fc
44 changed files with 1084 additions and 635 deletions
|
@ -45,7 +45,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Load_Root_Level_Configuration()
|
||||
public void LoadRootLevelConfiguration()
|
||||
{
|
||||
var inboundFolder = @"C:\roadie_dev_root\inbound";
|
||||
var configInboundFolder = this.Settings.InboundFolder;
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Roadie.Library.Tests
|
|||
public class EncryptionHelperTests
|
||||
{
|
||||
[Fact]
|
||||
public void Encrypt_And_Decrypt()
|
||||
public void EncryptAndDecrypt()
|
||||
{
|
||||
var key = Guid.NewGuid().ToString();
|
||||
var value = Guid.NewGuid().ToString();
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Roadie.Library.Tests
|
|||
{
|
||||
|
||||
[Fact]
|
||||
public void Shuffle_Unique_Order()
|
||||
public void ShuffleUniqueOrder()
|
||||
{
|
||||
var tracks = new List<Roadie.Library.Models.TrackList>
|
||||
{
|
||||
|
@ -225,12 +225,12 @@ namespace Roadie.Library.Tests
|
|||
lastTrack = track;
|
||||
}
|
||||
|
||||
Assert.Equal(tracks.Count(), shuffledTracks.Count());
|
||||
Assert.Equal(tracks.Count, shuffledTracks.Count());
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void From_Unix_Time()
|
||||
public void FromUnixTime()
|
||||
{
|
||||
var dateTime = new DateTime(2015, 05, 24, 10, 2, 0, DateTimeKind.Utc);
|
||||
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
@ -240,7 +240,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void To_Unix_Time()
|
||||
public void ToUnixTime()
|
||||
{
|
||||
var dateTime = new DateTime(2015, 05, 24, 10, 2, 0, DateTimeKind.Utc);
|
||||
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
@ -254,14 +254,14 @@ namespace Roadie.Library.Tests
|
|||
[InlineData(150, 0)]
|
||||
[InlineData(65000, 65)]
|
||||
[InlineData(143000, 143)]
|
||||
public void To_Seconds_From_Milliseconds_Decimal(int input, int shouldBe)
|
||||
public void ToSecondsFromMillisecondsDecimal(int input, int shouldBe)
|
||||
{
|
||||
var d = ((decimal?)input).ToSecondsFromMilliseconds();
|
||||
Assert.Equal(shouldBe, d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void To_Time_Span()
|
||||
public void ToTimeSpan()
|
||||
{
|
||||
var dateTime = new DateTime(2015, 05, 24, 10, 2, 0, DateTimeKind.Utc);
|
||||
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
@ -273,7 +273,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Or_Integers()
|
||||
public void OrIntegers()
|
||||
{
|
||||
int? test = null;
|
||||
int? shouldBe = 5;
|
||||
|
@ -285,7 +285,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData(150, 0)]
|
||||
[InlineData(65000, 65)]
|
||||
[InlineData(143000, 143)]
|
||||
public void To_Seconds_From_Milliseconds_Int(int? input, int? shouldBe)
|
||||
public void ToSecondsFromMillisecondsInt(int? input, int? shouldBe)
|
||||
{
|
||||
var d = input.ToSecondsFromMilliseconds();
|
||||
Assert.Equal(shouldBe, d);
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Roadie.Library.Tests
|
|||
public ID3TagsHelperTests()
|
||||
{
|
||||
this.MessageLogger = new EventMessageLogger<ID3TagsHelperTests>();
|
||||
this.MessageLogger.Messages += MessageLogger_Messages;
|
||||
this.MessageLogger.Messages += MessageLoggerMessages;
|
||||
|
||||
var settings = new RoadieSettings();
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||
|
@ -43,11 +43,11 @@ namespace Roadie.Library.Tests
|
|||
this.Configuration = settings;
|
||||
this.CacheManager = new DictionaryCacheManager(this.Logger, new CachePolicy(TimeSpan.FromHours(4)));
|
||||
var tagHelperLooper = new EventMessageLogger<ID3TagsHelper>();
|
||||
tagHelperLooper.Messages += MessageLogger_Messages;
|
||||
tagHelperLooper.Messages += MessageLoggerMessages;
|
||||
this.TagsHelper = new ID3TagsHelper(this.Configuration, this.CacheManager, tagHelperLooper);
|
||||
}
|
||||
|
||||
private void MessageLogger_Messages(object sender, EventMessage e)
|
||||
private void MessageLoggerMessages(object sender, EventMessage e)
|
||||
{
|
||||
Console.WriteLine($"Log Level [{ e.Level }] Log Message [{ e.Message }] ");
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromCue_Should_Be_Five()
|
||||
public void ReadTotalTrackNumbersFromCueShouldBeFive()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\cues1";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -224,7 +224,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromCue_Should_Be_Eight()
|
||||
public void ReadTotalTrackNumbersFromCueShouldBeEight()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\cues2";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -243,7 +243,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromCue_Should_Be_Six()
|
||||
public void ReadTotalTrackNumbersFromCueShouldBeSix()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\cues3";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -262,7 +262,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromCue_Should_Be_Nine()
|
||||
public void ReadTotalTrackNumbersFromCueShouldBeNine()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\cues4";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -281,7 +281,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromM3u_Should_Be_Eleven()
|
||||
public void ReadTotalTrackNumbersFromM3uShouldBeEleven()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\m3u1";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -300,7 +300,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromM3u_Should_Be_Four()
|
||||
public void ReadTotalTrackNumbersFromM3uShouldBeFour()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\m3u2";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -319,7 +319,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromM3u_Should_Be_Eight()
|
||||
public void ReadTotalTrackNumbersFromM3uShouldBeEight()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\m3u3";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -338,7 +338,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadTotalTrackNumbersFromM3u_Should_Be_Fourteen()
|
||||
public void ReadTotalTrackNumbersFromM3uShouldBeFourteen()
|
||||
{
|
||||
var cuesDir = @"C:\roadie_dev_root\test_cue_and_playlists\m3u4";
|
||||
var directory = new DirectoryInfo(cuesDir);
|
||||
|
@ -545,7 +545,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Read_File_Test_Is_valid()
|
||||
public void ReadFileTestIsvalid()
|
||||
{
|
||||
var file = new FileInfo(@"M:\unknown\2eec19bd-3575-4b7f-84dd-db2a0ec3e2f3~[2009] Dolly - Disc 1 Of 4~06 Nobody But You (Previously Unissued).mp3");
|
||||
if (file.Exists)
|
||||
|
@ -572,7 +572,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Read_File_Test_Is_valid2()
|
||||
public void ReadFileTestIsvalid2()
|
||||
{
|
||||
var file = new FileInfo(@"M:\library_old\Perverse\[2014] Champion Dub\01 Champion Dub (Original Mix).mp3");
|
||||
if (file.Exists)
|
||||
|
@ -599,7 +599,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Read_File_Test_Is_valid3()
|
||||
public void ReadFileTestIsvalid3()
|
||||
{
|
||||
var file = new FileInfo(@"C:\roadie_dev_root\inbound\Dreadful Fate - Vengeance (2018)\01-dreadful_fate-vengeance.mp3");
|
||||
if (file.Exists)
|
||||
|
@ -685,7 +685,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Write_Tags()
|
||||
public void WriteTags()
|
||||
{
|
||||
var file = new FileInfo(@"C:\roadie_dev_root\inbound\temp\01. Re1nstall 0verture.mp3");
|
||||
if (file.Exists)
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Roadie.Library.Tests
|
|||
public class ImageHasherTests
|
||||
{
|
||||
[Fact]
|
||||
public void Generate_Image_Hash()
|
||||
public void GenerateImageHash()
|
||||
{
|
||||
var imageFilename = @"C:\temp\image_tests\1.jpg";
|
||||
var secondImagFilename = @"C:\temp\image_tests\2.jpg";
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
using Roadie.Library.FilePlugins;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Data;
|
||||
using Roadie.Library.FilePlugins;
|
||||
using Roadie.Library.Imaging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
@ -20,7 +26,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("GrOup.jpg")]
|
||||
[InlineData("photo.jpg")]
|
||||
[InlineData("aRtist.jpg")]
|
||||
public void Test_Should_Be_Artist_Images(string input)
|
||||
public void TestShouldBeArtistImages(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsArtistImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -42,7 +48,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("band 1.jpg")]
|
||||
[InlineData("photo 1.jpg")]
|
||||
[InlineData("photo1.jpg")]
|
||||
public void Test_Should_Be_Artist_Secondary_Images(string input)
|
||||
public void TestShouldBeArtistSecondaryImages(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsArtistSecondaryImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -74,7 +80,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("BIG.JPg")]
|
||||
[InlineData("bigart.JPg")]
|
||||
[InlineData("BIG.PNG")]
|
||||
public void Test_Should_Be_Release_Images(string input)
|
||||
public void TestShouldBeReleaseImages(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsReleaseImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -102,7 +108,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("artist 1.jpg")]
|
||||
[InlineData("artist_01.jpg")]
|
||||
[InlineData("artist 03.jpg")]
|
||||
public void Test_Should_Not_Be_Artist_Images(string input)
|
||||
public void TestShouldNotBeArtistImages(string input)
|
||||
{
|
||||
var t = ImageHelper.IsArtistImage(new FileInfo(input));
|
||||
Assert.False(t);
|
||||
|
@ -127,7 +133,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("cover_01.jpg")]
|
||||
[InlineData("cover 03.jpg")]
|
||||
[InlineData("Dixieland-Front1.jpg")]
|
||||
public void Test_Should_Not_Be_Release_Images(string input)
|
||||
public void TestShouldNotBeReleaseImages(string input)
|
||||
{
|
||||
Assert.False(ImageHelper.IsReleaseImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -142,7 +148,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("record_label.jpg")]
|
||||
[InlineData("RecordLabel.jpg")]
|
||||
[InlineData("RECORDLABEL.JPG")]
|
||||
public void Test_Should_Be_Label_Images(string input)
|
||||
public void TestShouldBeLabelImages(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsLabelImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -165,7 +171,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("Release.JPG")]
|
||||
[InlineData("front.jpg")]
|
||||
[InlineData("FrOnt.jpg")]
|
||||
public void Test_Should_NotBe_Label_Images(string input)
|
||||
public void TestShouldNotBeLabelImages(string input)
|
||||
{
|
||||
Assert.False(ImageHelper.IsLabelImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -234,7 +240,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("Matrix-1.jpg")]
|
||||
[InlineData("Matrix 1.jpg")]
|
||||
[InlineData("IMG_20160921_0004.jpg")]
|
||||
public void Test_Should_Be_Release_Secondary_Images(string input)
|
||||
public void TestShouldBeReleaseSecondaryImages(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsReleaseSecondaryImage(new FileInfo(input)));
|
||||
}
|
||||
|
@ -265,13 +271,13 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("record_label.jpg")]
|
||||
[InlineData("RecordLabel.jpg")]
|
||||
[InlineData("RECORDLABEL.JPG")]
|
||||
public void Test_Should_Not_Be_Release_Secondary_Images(string input)
|
||||
public void TestShouldNotBeReleaseSecondaryImages(string input)
|
||||
{
|
||||
Assert.False(ImageHelper.IsReleaseSecondaryImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_Release_Image_In_Folder()
|
||||
public void GetReleaseImageInFolder()
|
||||
{
|
||||
var folder = new DirectoryInfo(@"C:\roadie_dev_root\image_tests");
|
||||
if(!folder.Exists)
|
||||
|
@ -287,7 +293,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_Artist_Image_In_Folder()
|
||||
public void GetArtistImageInFolder()
|
||||
{
|
||||
var folder = new DirectoryInfo(@"C:\roadie_dev_root\image_tests)");
|
||||
if (!folder.Exists)
|
||||
|
@ -300,5 +306,196 @@ namespace Roadie.Library.Tests
|
|||
Assert.Single(artist);
|
||||
Assert.Equal("artist.jpg", artist.First().Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtractImagesFromDatabase()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var now = DateTime.UtcNow;
|
||||
var optionsBuilder = new DbContextOptionsBuilder<RoadieDbContext>();
|
||||
optionsBuilder.UseMySql("server=viking;userid=roadie;password=MenAtW0rk668;persistsecurityinfo=True;database=roadie_dev;ConvertZeroDateTime=true");
|
||||
|
||||
var settings = new RoadieSettings();
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||
configurationBuilder.AddJsonFile("appsettings.test.json");
|
||||
IConfiguration configuration = configurationBuilder.Build();
|
||||
configuration.GetSection("RoadieSettings").Bind(settings);
|
||||
settings.ConnectionString = configuration.GetConnectionString("RoadieDatabaseConnection");
|
||||
|
||||
using (var context = new RoadieDbContext(optionsBuilder.Options))
|
||||
{
|
||||
foreach (var artist in context.Artists.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var artistFolder = artist.ArtistFileFolder(settings);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var artistImage = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
|
||||
if (!File.Exists(artistImage))
|
||||
{
|
||||
File.WriteAllBytes(artistImage, ImageHelper.ConvertToJpegFormat(artist.Thumbnail));
|
||||
}
|
||||
artist.Thumbnail = null;
|
||||
artist.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Artist Image `{artist}` path [{ artistImage }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
var artistImages = (from i in context.Images
|
||||
join a in context.Artists on i.ArtistId equals a.Id
|
||||
select new { i, a});
|
||||
foreach(var artistImage in artistImages)
|
||||
{
|
||||
var looper = 0;
|
||||
var artistFolder = artistImage.a.ArtistFileFolder(settings);
|
||||
var artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
while (File.Exists(artistImageFilename))
|
||||
{
|
||||
looper++;
|
||||
artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
File.WriteAllBytes(artistImageFilename, ImageHelper.ConvertToJpegFormat(artistImage.i.Bytes));
|
||||
context.Images.Remove(artistImage.i);
|
||||
Trace.WriteLine($"Saved Artist Secondary Image `{artistImage.a}` path [{ artistImageFilename }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
foreach (var collection in context.Collections.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var image = collection.PathToImage(settings);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(collection.Thumbnail));
|
||||
}
|
||||
collection.Thumbnail = null;
|
||||
collection.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Collection Image `{collection}` path [{ image }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
foreach (var genre in context.Genres.Where(x => x.Thumbnail != null).OrderBy(x => x.Name))
|
||||
{
|
||||
var image = genre.PathToImage(settings);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(genre.Thumbnail));
|
||||
}
|
||||
genre.Thumbnail = null;
|
||||
genre.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Genre Image `{genre}` path [{ image }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
foreach (var label in context.Labels.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var image = label.PathToImage(settings);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(label.Thumbnail));
|
||||
}
|
||||
label.Thumbnail = null;
|
||||
label.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Label Image `{label}` path [{ image }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
foreach (var playlist in context.Playlists.Where(x => x.Thumbnail != null).OrderBy(x => x.Name))
|
||||
{
|
||||
var image = playlist.PathToImage(settings);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(playlist.Thumbnail));
|
||||
}
|
||||
playlist.Thumbnail = null;
|
||||
playlist.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Playlist Image `{playlist}` path [{ image }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
foreach (var release in context.Releases.Include(x => x.Artist).Where(x => x.Thumbnail != null).OrderBy(x => x.Title))
|
||||
{
|
||||
var artistFolder = release.Artist.ArtistFileFolder(settings);
|
||||
var releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseImage = Path.Combine(releaseFolder, "cover.jpg");
|
||||
if (!File.Exists(releaseImage))
|
||||
{
|
||||
File.WriteAllBytes(releaseImage, ImageHelper.ConvertToJpegFormat(release.Thumbnail));
|
||||
}
|
||||
release.Thumbnail = null;
|
||||
release.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Release Image `{release}` path [{ releaseImage }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
var releaseImages = (from i in context.Images
|
||||
join r in context.Releases.Include(x => x.Artist) on i.ReleaseId equals r.Id
|
||||
select new { i, r });
|
||||
foreach (var releaseImage in releaseImages)
|
||||
{
|
||||
var looper = 0;
|
||||
var artistFolder = releaseImage.r.Artist.ArtistFileFolder(settings);
|
||||
var releaseFolder = releaseImage.r.ReleaseFileFolder(artistFolder);
|
||||
var releaseImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
while (File.Exists(releaseImageFilename))
|
||||
{
|
||||
looper++;
|
||||
releaseImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
File.WriteAllBytes(releaseImageFilename, ImageHelper.ConvertToJpegFormat(releaseImage.i.Bytes));
|
||||
context.Images.Remove(releaseImage.i);
|
||||
Trace.WriteLine($"Saved Release Secondary Image `{releaseImage.r}` path [{ releaseImageFilename }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
|
||||
foreach (var track in context.Tracks.Include(x => x.ReleaseMedia)
|
||||
.Include(x => x.ReleaseMedia.Release)
|
||||
.Include(x => x.ReleaseMedia.Release.Artist)
|
||||
.Where(x => x.Thumbnail != null).OrderBy(x => x.Title))
|
||||
{
|
||||
var artistFolder = track.ReleaseMedia.Release.Artist.ArtistFileFolder(settings);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = track.ReleaseMedia.Release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var trackImage = track.PathToTrackThumbnail(settings);
|
||||
if (!File.Exists(trackImage))
|
||||
{
|
||||
File.WriteAllBytes(trackImage, ImageHelper.ConvertToJpegFormat(track.Thumbnail));
|
||||
}
|
||||
track.Thumbnail = null;
|
||||
track.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved Track Image `{track}` path [{ trackImage }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
foreach (var user in context.Users.Where(x => x.Avatar != null).OrderBy(x => x.UserName))
|
||||
{
|
||||
var image = user.PathToImage(settings);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(user.Avatar));
|
||||
}
|
||||
user.Avatar = null;
|
||||
user.LastUpdated = now;
|
||||
Trace.WriteLine($"Saved User Image `{user}` path [{ image }]");
|
||||
}
|
||||
context.SaveChanges();
|
||||
|
||||
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ namespace Roadie.Library.Tests
|
|||
public InspectorTests()
|
||||
{
|
||||
this.MessageLogger = new EventMessageLogger<ID3TagsHelperTests>();
|
||||
this.MessageLogger.Messages += MessageLogger_Messages;
|
||||
this.MessageLogger.Messages += MessageLoggerMessages;
|
||||
|
||||
var settings = new configuration.RoadieSettings();
|
||||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||
|
@ -47,11 +47,11 @@ namespace Roadie.Library.Tests
|
|||
this.Configuration = settings;
|
||||
this.CacheManager = new DictionaryCacheManager(this.Logger, new CachePolicy(TimeSpan.FromHours(4)));
|
||||
var tagHelperLooper = new EventMessageLogger<ID3TagsHelper>();
|
||||
tagHelperLooper.Messages += MessageLogger_Messages;
|
||||
tagHelperLooper.Messages += MessageLoggerMessages;
|
||||
this.TagsHelper = new ID3TagsHelper(this.Configuration, this.CacheManager, tagHelperLooper);
|
||||
}
|
||||
|
||||
private void MessageLogger_Messages(object sender, EventMessage e)
|
||||
private void MessageLoggerMessages(object sender, EventMessage e)
|
||||
{
|
||||
Console.WriteLine($"Log Level [{ e.Level }] Log Message [{ e.Message }] ");
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("Bob Jones ", "Bob Jones")]
|
||||
[InlineData(" BoB Jones ", "Bob Jones")]
|
||||
[InlineData("Ain't NO THING", "Ain't No Thing")]
|
||||
public void Clean_Artist_Plugin(string artist, string shouldBe)
|
||||
public void CleanArtistPlugin(string artist, string shouldBe)
|
||||
{
|
||||
var plugin = new CleanUpArtists(Configuration, CacheManager, Logger, TagsHelper);
|
||||
Assert.Equal(shouldBe, plugin.CleanArtist(artist));
|
||||
|
@ -75,7 +75,7 @@ namespace Roadie.Library.Tests
|
|||
|
||||
[Theory]
|
||||
[InlineData("Ain't NO THING", "Ain't No Thing")]
|
||||
public void Clean_TrackTitle_Plugin(string title, string shouldBe)
|
||||
public void CleanTrackTitlePlugin(string title, string shouldBe)
|
||||
{
|
||||
var plugin = new CleanUpTrackTitle(Configuration, CacheManager, Logger, TagsHelper);
|
||||
var result = plugin.Process(new MetaData.Audio.AudioMetaData { Title = title});
|
||||
|
@ -84,7 +84,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Clean_Artist_Plugin_Remove_Artist_From_Track_Artist()
|
||||
public void CleanArtistPluginRemoveArtistFromTrackArtist()
|
||||
{
|
||||
var artist = "Bob Jones";
|
||||
var trackArtist = "Bob Jones;Mary Jones";
|
||||
|
@ -98,14 +98,14 @@ namespace Roadie.Library.Tests
|
|||
[Theory]
|
||||
[InlineData("Bob Jones")]
|
||||
[InlineData("Nancy Jones")]
|
||||
public void Generate_Inspector_Artist_Token(string artist)
|
||||
public void GenerateInspectorArtistToken(string artist)
|
||||
{
|
||||
var token = Inspector.ArtistInspectorToken(new MetaData.Audio.AudioMetaData { Artist = artist });
|
||||
Assert.NotNull(token);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Generate_Same_Token_Value()
|
||||
public void ShouldGenerateSameTokenValue()
|
||||
{
|
||||
var md = new MetaData.Audio.AudioMetaData { Artist = "Omniversum Fractum", Release = "Paradigm Of The Elementals Essence" };
|
||||
var artistToken = Inspector.ArtistInspectorToken(md);
|
||||
|
@ -122,7 +122,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Generate_Inspector_Tokens_Artist_And_Release_Unique()
|
||||
public void GenerateInspectorTokensArtistAndReleaseUnique()
|
||||
{
|
||||
var md = new MetaData.Audio.AudioMetaData { Artist = "Bob Jones", Release = "Bob's First Release" };
|
||||
var artistToken = Inspector.ArtistInspectorToken(md);
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData(@"2003 - Accelerated Evolution\CD 001\01 - Depth Charge.mp3")]
|
||||
[InlineData(@"Accelerated Evolution CD01\22 - Depth Charge.mp3")]
|
||||
[InlineData(@"Accelerated Evolution CD1\22 - Depth Charge.mp3")]
|
||||
public void Find_Disc_Number_Should_Be_One(string filename)
|
||||
public void FindDiscNumberShouldBeOne(string filename)
|
||||
{
|
||||
var n = ID3TagsHelper.DetermineDiscNumber(new AudioMetaData { Filename = filename });
|
||||
Assert.Equal(1, n);
|
||||
|
@ -35,24 +35,24 @@ namespace Roadie.Library.Tests
|
|||
[InlineData(@"2003 - Accelerated Evolution\CD 002\22 - Depth Charge.mp3")]
|
||||
[InlineData(@"Accelerated Evolution CD2\22 - Depth Charge.mp3")]
|
||||
[InlineData(@"Accelerated Evolution CD02\22 - Depth Charge.mp3")]
|
||||
public void Find_Disc_Number_Should_Be_Two(string filename)
|
||||
public void FindDiscNumberShouldBeTwo(string filename)
|
||||
{
|
||||
var n = ID3TagsHelper.DetermineDiscNumber(new AudioMetaData { Filename = filename });
|
||||
Assert.Equal(2, n);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Total_Discs_Should_Be_One()
|
||||
public void FindTotalDiscsShouldBeOne()
|
||||
{
|
||||
var three = new List<AudioMetaData>
|
||||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\02 - Not A Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
var n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
@ -62,11 +62,11 @@ namespace Roadie.Library.Tests
|
|||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD1\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD1\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD1\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD1\02 - Not A Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
@ -74,29 +74,29 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Total_Discs_Should_Be_Ten()
|
||||
public void FindTotalDiscsShouldBeTen()
|
||||
{
|
||||
var three = new List<AudioMetaData>
|
||||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\02 - Not A Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 04\01 - First.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 04\01 - First.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 06\02 - Second.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 06\02 - Second.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 10\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 10\01 - Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
var n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
@ -104,41 +104,41 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Total_Discs_Should_Be_Three()
|
||||
public void FindTotalDiscsShouldBeThree()
|
||||
{
|
||||
var three = new List<AudioMetaData>
|
||||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\02 - Not A Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\01 - First.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\01 - First.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\02 - Second.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\02 - Second.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\02 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\02 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\03 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\03 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\04 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 03\04 - Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
var n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
@ -146,29 +146,29 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Total_Discs_Should_Be_Two()
|
||||
public void FindTotalDiscsShouldBeTwo()
|
||||
{
|
||||
var three = new List<AudioMetaData>
|
||||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\02 - Not A Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - First.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - First.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\02 - Second.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 02\02 - Second.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 01\01 - Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
var n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
@ -178,11 +178,11 @@ namespace Roadie.Library.Tests
|
|||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD0\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD0\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD2\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD2\02 - Not A Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
@ -192,11 +192,11 @@ namespace Roadie.Library.Tests
|
|||
{
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 1\01 - Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 1\01 - Depth Charge.mp3"
|
||||
},
|
||||
new AudioMetaData
|
||||
{
|
||||
Filename = @"C:\roadie_dev_root\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 2\02 - Not A Depth Charge.mp3"
|
||||
Filename = @"C:\roadiedevroot\Devin Townsend (1996 - 2016)\The Devin Townsend Band (2003 - 2006)\2003 - Accelerated Evolution\CD 2\02 - Not A Depth Charge.mp3"
|
||||
}
|
||||
};
|
||||
n = ID3TagsHelper.DetermineTotalDiscNumbers(three);
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("1")]
|
||||
[InlineData("01")]
|
||||
[InlineData("001")]
|
||||
public void Parse_Int_ShouldBeOne(string input)
|
||||
public void ParseIntShouldBeOne(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToNumber<int>(input);
|
||||
Assert.Equal(1, parsed);
|
||||
|
@ -22,7 +22,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("")]
|
||||
[InlineData("0")]
|
||||
[InlineData("00")]
|
||||
public void Parse_Int_ShouldBeZero(string input)
|
||||
public void ParseIntShouldBeZero(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToNumber<int>(input);
|
||||
Assert.Equal(0, parsed);
|
||||
|
@ -31,7 +31,7 @@ namespace Roadie.Library.Tests
|
|||
|
||||
|
||||
[Fact]
|
||||
public void Parse_Larger_Int()
|
||||
public void ParseLargerInt()
|
||||
{
|
||||
var n = "12345";
|
||||
int n1 = 12345;
|
||||
|
@ -40,7 +40,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_NullablleInt()
|
||||
public void ParseNullablleInt()
|
||||
{
|
||||
var one = "1";
|
||||
var parsed = SafeParser.ToNumber<int?>(one);
|
||||
|
@ -56,7 +56,7 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_Short()
|
||||
public void ParseShort()
|
||||
{
|
||||
var n = "23";
|
||||
short n1 = 23;
|
||||
|
@ -84,7 +84,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("88")]
|
||||
[InlineData("1988-06-15T07:00:00Z")]
|
||||
[InlineData("1988-07-14T07:00:00Z")]
|
||||
public void Parse_Datetime_ShouldBe1988(string input)
|
||||
public void ParseDatetimeShouldBe1988(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToDateTime(input);
|
||||
Assert.NotNull(parsed);
|
||||
|
@ -99,7 +99,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("2004////2004")]
|
||||
[InlineData("2004\\2004")]
|
||||
[InlineData("2004\\\\2004")]
|
||||
public void Parse_Datetime_ShouldBe2004(string input)
|
||||
public void ParseDatetimeShouldBe2004(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToDateTime(input);
|
||||
Assert.NotNull(parsed);
|
||||
|
@ -111,7 +111,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("12d65c61-1b7d-4c43-9aab-7d398a1a880e")]
|
||||
[InlineData("A:8a951bc1-5ee5-4961-b72a-99d91d84c147")]
|
||||
[InlineData("R:0327eea7-b1cb-4ae9-9eb1-b74b4416aefb")]
|
||||
public void Parse_Guid(string input)
|
||||
public void ParseGuid(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToGuid(input);
|
||||
Assert.NotNull(parsed);
|
||||
|
@ -125,7 +125,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("Yes")]
|
||||
[InlineData("YES")]
|
||||
[InlineData("1")]
|
||||
public void Parse_Boolean_ShouldBeTrue(string input)
|
||||
public void ParseBooleanShouldBeTrue(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToBoolean(input);
|
||||
Assert.True(parsed);
|
||||
|
@ -142,7 +142,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("No")]
|
||||
[InlineData("NO")]
|
||||
[InlineData("0")]
|
||||
public void Parse_Boolean_ShouldBeFalse(string input)
|
||||
public void ParseBooleanShouldBeFalse(string input)
|
||||
{
|
||||
var parsed = SafeParser.ToBoolean(input);
|
||||
Assert.False(parsed);
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("Angie (2004 Remastered)")]
|
||||
[InlineData("Angie (Japan Ltd Dig")]
|
||||
[InlineData("Angie (Japan Release)")]
|
||||
public void CleanString_Release_Should_Be_Angie(string input)
|
||||
public void CleanStringReleaseShouldBeAngie(string input)
|
||||
{
|
||||
var r = @"(\s*(-\s)*((CD[_\-#\s]*[0-9]*)))|((\(|\[)+([0-9]|,|self|bonus|re(leas|master|(e|d)*)*|th|anniversary|cd|disc|deluxe|dig(ipack)*|vinyl|japan(ese)*|asian|remastered|limited|ltd|expanded|edition|\s)+(]|\)*))";
|
||||
var cleaned = input.CleanString(this.Configuration, r);
|
||||
|
@ -117,7 +117,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("Love.Mp3")]
|
||||
[InlineData("LOVE.Mp3")]
|
||||
[InlineData("love.mp3")]
|
||||
public void CleanString_Track(string input)
|
||||
public void CleanStringTrack(string input)
|
||||
{
|
||||
Assert.Equal("Love.Mp3", input.CleanString(Configuration, Configuration.Processing.TrackRemoveStringsRegex).ToTitleCase());
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ namespace Roadie.Library.Tests
|
|||
[InlineData("49 Batman Loves Robin")]
|
||||
[InlineData("54 Batman Loves Robin")]
|
||||
[InlineData("348 Batman Loves Robin")]
|
||||
public void Test_Regex_String(string input)
|
||||
public void TestRegexString(string input)
|
||||
{
|
||||
var t1 = Regex.Replace(input, "^([0-9]+)(\\.|-|\\s)*", "");
|
||||
Assert.NotNull(t1);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Imaging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
@ -32,8 +33,6 @@ namespace Roadie.Library.Data
|
|||
|
||||
public ICollection<ArtistGenre> Genres { get; set; }
|
||||
|
||||
public ICollection<Image> Images { get; set; }
|
||||
|
||||
[Column("isniList", TypeName = "text")]
|
||||
[MaxLength(65535)]
|
||||
public string ISNI { get; set; }
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
|
@ -20,6 +22,9 @@ namespace Roadie.Library.Data
|
|||
}
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public ICollection<Roadie.Library.Imaging.IImage> Images { get; set; }
|
||||
|
||||
public bool IsNew => Id < 1;
|
||||
|
||||
public bool IsValid => !string.IsNullOrEmpty(Name);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
@ -25,6 +26,7 @@ namespace Roadie.Library.Data
|
|||
[MaxLength(65535)]
|
||||
public string Tags { get; set; }
|
||||
|
||||
[Obsolete("Images moved to file system")]
|
||||
[Column("thumbnail", TypeName = "blob")]
|
||||
[MaxLength(65535)]
|
||||
public byte[] Thumbnail { get; set; }
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
{
|
||||
[Obsolete("Only here for transition. Will be removed in future release. Use Library.Imaging.Image")]
|
||||
[Table("image")]
|
||||
public partial class Image : EntityBase
|
||||
{
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
using Roadie.Library.Imaging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
{
|
||||
public partial class Image
|
||||
{
|
||||
public string CacheKey => Artist.CacheUrn(RoadieId);
|
||||
|
||||
public string CacheRegion => CacheRegionUrn(RoadieId);
|
||||
|
||||
public static string CacheRegionUrn(Guid Id)
|
||||
{
|
||||
return string.Format("urn:image:{0}", Id);
|
||||
}
|
||||
|
||||
public static string CacheUrn(Guid Id)
|
||||
{
|
||||
return $"urn:image_by_id:{Id}";
|
||||
}
|
||||
|
||||
public string GenerateSignature()
|
||||
{
|
||||
if (Bytes == null || !Bytes.Any()) return null;
|
||||
return ImageHasher.AverageHash(Bytes).ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Id [{Id}], RoadieId [{RoadieId}]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
|
@ -17,6 +18,7 @@ namespace Roadie.Library.Data
|
|||
[MaxLength(65535)]
|
||||
public string Tags { get; set; }
|
||||
|
||||
[Obsolete("Images moved to file system")]
|
||||
[Column("thumbnail", TypeName = "blob")]
|
||||
[MaxLength(65535)]
|
||||
public byte[] Thumbnail { get; set; }
|
||||
|
|
|
@ -3,6 +3,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
{
|
||||
|
@ -29,7 +30,10 @@ namespace Roadie.Library.Data
|
|||
|
||||
public ICollection<ReleaseGenre> Genres { get; set; }
|
||||
|
||||
public ICollection<Image> Images { get; set; }
|
||||
[NotMapped]
|
||||
public IEnumerable<Imaging.IImage> Images { get; set; } = Enumerable.Empty<Imaging.IImage>();
|
||||
|
||||
public Imaging.IImage ThumbnailImage => Images.OrderBy(x => x.SortOrder).FirstOrDefault();
|
||||
|
||||
[Column("isVirtual")] public bool? IsVirtual { get; set; }
|
||||
|
||||
|
@ -77,6 +81,7 @@ namespace Roadie.Library.Data
|
|||
[MaxLength(65535)]
|
||||
public string Tags { get; set; }
|
||||
|
||||
[Obsolete("Images moved to file system")]
|
||||
[Column("thumbnail", TypeName = "blob")]
|
||||
[MaxLength(65535)]
|
||||
public byte[] Thumbnail { get; set; }
|
||||
|
@ -96,7 +101,6 @@ namespace Roadie.Library.Data
|
|||
{
|
||||
Rating = 0;
|
||||
ReleaseType = Enums.ReleaseType.Release;
|
||||
Images = new HashSet<Image>();
|
||||
Medias = new HashSet<ReleaseMedia>();
|
||||
Labels = new HashSet<ReleaseLabel>();
|
||||
Collections = new HashSet<CollectionRelease>();
|
||||
|
|
|
@ -56,6 +56,7 @@ namespace Roadie.Library.Data
|
|||
[MaxLength(65535)]
|
||||
public string Tags { get; set; }
|
||||
|
||||
[Obsolete("Images moved to file system")]
|
||||
[Column("thumbnail", TypeName = "blob")]
|
||||
public byte[] Thumbnail { get; set; }
|
||||
|
||||
|
|
|
@ -139,18 +139,19 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
}
|
||||
|
||||
if (ArtistImages != null && ArtistImages.Any(x => x.Status == Statuses.New))
|
||||
{
|
||||
foreach (var ArtistImage in ArtistImages)
|
||||
DbContext.Images.Add(new Image
|
||||
{
|
||||
ArtistId = artist.Id,
|
||||
Url = ArtistImage.Url,
|
||||
Signature = ArtistImage.Signature,
|
||||
Bytes = ArtistImage.Bytes
|
||||
});
|
||||
inserted = await DbContext.SaveChangesAsync();
|
||||
}
|
||||
// TODO #29 save images to folder
|
||||
|
||||
//if (ArtistImages != null && ArtistImages.Any(x => x.Status == Statuses.New))
|
||||
//{
|
||||
// foreach (var ArtistImage in ArtistImages)
|
||||
// DbContext.Images.Add(new Library.Imaging.Image(artist.RoadieId)
|
||||
// {
|
||||
// Url = ArtistImage.Url,
|
||||
// Signature = ArtistImage.Signature,
|
||||
// Bytes = ArtistImage.Bytes
|
||||
// });
|
||||
// inserted = await DbContext.SaveChangesAsync();
|
||||
//}
|
||||
sw.Stop();
|
||||
Logger.LogTrace($"Added New Artist: Elapsed Time [{ sw.ElapsedMilliseconds }], Artist `{ artist }`");
|
||||
}
|
||||
|
@ -674,7 +675,7 @@ namespace Roadie.Library.Engines
|
|||
if (artistImageUrls.Any())
|
||||
{
|
||||
var sw2 = Stopwatch.StartNew();
|
||||
var imageBag = new ConcurrentBag<Image>();
|
||||
var imageBag = new ConcurrentBag<IImage>();
|
||||
var i = artistImageUrls.Select(async url =>
|
||||
{
|
||||
imageBag.Add(await WebHelper.GetImageFromUrlAsync(url));
|
||||
|
|
|
@ -78,17 +78,16 @@ namespace Roadie.Library.Engines
|
|||
try
|
||||
{
|
||||
var releaseGenreTables = release.Genres;
|
||||
var releaseImages = release.Images;
|
||||
var releaseMedias = release.Medias;
|
||||
var releaseLabels = release.Labels;
|
||||
var now = DateTime.UtcNow;
|
||||
release.AlternateNames = release.AlternateNames.AddToDelimitedList(new[] { release.Title.ToAlphanumericName() });
|
||||
release.Images = null;
|
||||
release.Labels = null;
|
||||
release.Medias = null;
|
||||
release.Genres = null;
|
||||
release.LibraryStatus = LibraryStatus.Incomplete;
|
||||
release.Status = Statuses.New;
|
||||
var releaseImages = new List<Library.Imaging.Image>();
|
||||
if (!release.IsValid)
|
||||
{
|
||||
return new OperationResult<Release>
|
||||
|
@ -96,10 +95,6 @@ namespace Roadie.Library.Engines
|
|||
Errors = new Exception[1] { new Exception("Release is Invalid") }
|
||||
};
|
||||
}
|
||||
if (release.Thumbnail != null)
|
||||
{
|
||||
release.Thumbnail = ImageHelper.ResizeToThumbnail(release.Thumbnail, Configuration);
|
||||
}
|
||||
DbContext.Releases.Add(release);
|
||||
var inserted = 0;
|
||||
try
|
||||
|
@ -153,27 +148,29 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
}
|
||||
|
||||
if (releaseImages != null && releaseImages.Any(x => x.Status == Statuses.New))
|
||||
{
|
||||
foreach (var releaseImage in releaseImages)
|
||||
{
|
||||
DbContext.Images.Add(new Image
|
||||
{
|
||||
ReleaseId = release.Id,
|
||||
Url = releaseImage.Url,
|
||||
Signature = releaseImage.Signature,
|
||||
Bytes = releaseImage.Bytes
|
||||
});
|
||||
}
|
||||
try
|
||||
{
|
||||
await DbContext.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
}
|
||||
// TODO #29 save release images to release folder
|
||||
|
||||
//if (releaseImages != null && releaseImages.Any(x => x.Status == Statuses.New))
|
||||
//{
|
||||
// foreach (var releaseImage in releaseImages)
|
||||
// {
|
||||
// DbContext.Images.Add(new Image
|
||||
// {
|
||||
// ReleaseId = release.Id,
|
||||
// Url = releaseImage.Url,
|
||||
// Signature = releaseImage.Signature,
|
||||
// Bytes = releaseImage.Bytes
|
||||
// });
|
||||
// }
|
||||
// try
|
||||
// {
|
||||
// await DbContext.SaveChangesAsync();
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Logger.LogError(ex);
|
||||
// }
|
||||
//}
|
||||
|
||||
if (releaseLabels != null && releaseLabels.Any(x => x.Status == Statuses.New))
|
||||
{
|
||||
|
@ -418,6 +415,7 @@ namespace Roadie.Library.Engines
|
|||
if (metaData.Genres != null) releaseGenres.AddRange(metaData.Genres);
|
||||
var releaseLabels = new List<ReleaseLabelSearchResult>();
|
||||
var releaseMedias = new List<ReleaseMediaSearchResult>();
|
||||
var releaseImages = new List<Imaging.IImage>();
|
||||
var releaseImageUrls = new List<string>();
|
||||
|
||||
var dontDoMetaDataProvidersSearchArtists = Configuration.DontDoMetaDataProvidersSearchArtists;
|
||||
|
@ -442,6 +440,13 @@ namespace Roadie.Library.Engines
|
|||
if (i.Urls != null) result.URLs = result.URLs.AddToDelimitedList(i.Urls);
|
||||
if (i.ImageUrls != null) releaseImageUrls.AddRange(i.ImageUrls);
|
||||
if (i.ReleaseGenres != null) releaseGenres.AddRange(i.ReleaseGenres);
|
||||
if(!string.IsNullOrEmpty(i.ReleaseThumbnailUrl))
|
||||
{
|
||||
releaseImages.Add(new Imaging.Image()
|
||||
{
|
||||
Bytes = WebHelper.BytesForImageUrl(i.ReleaseThumbnailUrl)
|
||||
});
|
||||
}
|
||||
result.CopyTo(new Release
|
||||
{
|
||||
ReleaseDate = result.ReleaseDate ?? i.ReleaseDate,
|
||||
|
@ -449,9 +454,6 @@ namespace Roadie.Library.Engines
|
|||
Profile = i.Profile,
|
||||
ITunesId = i.iTunesId,
|
||||
Title = result.Title ?? i.ReleaseTitle,
|
||||
Thumbnail = i.ReleaseThumbnailUrl != null
|
||||
? WebHelper.BytesForImageUrl(i.ReleaseThumbnailUrl)
|
||||
: null,
|
||||
ReleaseType = result.ReleaseType == ReleaseType.Unknown
|
||||
? SafeParser.ToEnum<ReleaseType>(i.ReleaseType)
|
||||
: result.ReleaseType
|
||||
|
@ -486,6 +488,13 @@ namespace Roadie.Library.Engines
|
|||
if (!string.IsNullOrEmpty(mb.ReleaseTitle) &&
|
||||
!mb.ReleaseTitle.Equals(result.Title, StringComparison.OrdinalIgnoreCase))
|
||||
result.AlternateNames.AddToDelimitedList(new[] { mb.ReleaseTitle });
|
||||
if (!string.IsNullOrEmpty(mb.ReleaseThumbnailUrl))
|
||||
{
|
||||
releaseImages.Add(new Imaging.Image()
|
||||
{
|
||||
Bytes = WebHelper.BytesForImageUrl(mb.ReleaseThumbnailUrl)
|
||||
});
|
||||
}
|
||||
result.CopyTo(new Release
|
||||
{
|
||||
ReleaseDate = result.ReleaseDate ?? mb.ReleaseDate,
|
||||
|
@ -497,9 +506,6 @@ namespace Roadie.Library.Engines
|
|||
MusicBrainzId = mb.MusicBrainzId,
|
||||
ITunesId = mb.iTunesId,
|
||||
Title = result.Title ?? mb.ReleaseTitle,
|
||||
Thumbnail = mb.ReleaseThumbnailUrl != null
|
||||
? WebHelper.BytesForImageUrl(mb.ReleaseThumbnailUrl)
|
||||
: null,
|
||||
ReleaseType = result.ReleaseType == ReleaseType.Unknown
|
||||
? SafeParser.ToEnum<ReleaseType>(mb.ReleaseType)
|
||||
: result.ReleaseType
|
||||
|
@ -535,6 +541,13 @@ namespace Roadie.Library.Engines
|
|||
if (!string.IsNullOrEmpty(l.ReleaseTitle) &&
|
||||
!l.ReleaseTitle.Equals(result.Title, StringComparison.OrdinalIgnoreCase))
|
||||
result.AlternateNames.AddToDelimitedList(new[] { l.ReleaseTitle });
|
||||
if (!string.IsNullOrEmpty(l.ReleaseThumbnailUrl))
|
||||
{
|
||||
releaseImages.Add(new Imaging.Image()
|
||||
{
|
||||
Bytes = WebHelper.BytesForImageUrl(l.ReleaseThumbnailUrl)
|
||||
});
|
||||
}
|
||||
result.CopyTo(new Release
|
||||
{
|
||||
ReleaseDate = result.ReleaseDate ?? l.ReleaseDate,
|
||||
|
@ -545,9 +558,6 @@ namespace Roadie.Library.Engines
|
|||
MusicBrainzId = l.MusicBrainzId,
|
||||
ITunesId = l.iTunesId,
|
||||
Title = result.Title ?? l.ReleaseTitle,
|
||||
Thumbnail = l.ReleaseThumbnailUrl != null
|
||||
? WebHelper.BytesForImageUrl(l.ReleaseThumbnailUrl)
|
||||
: null,
|
||||
ReleaseType = result.ReleaseType == ReleaseType.Unknown
|
||||
? SafeParser.ToEnum<ReleaseType>(l.ReleaseType)
|
||||
: result.ReleaseType
|
||||
|
@ -580,6 +590,13 @@ namespace Roadie.Library.Engines
|
|||
if (!string.IsNullOrEmpty(s.ReleaseTitle) &&
|
||||
!s.ReleaseTitle.Equals(result.Title, StringComparison.OrdinalIgnoreCase))
|
||||
result.AlternateNames.AddToDelimitedList(new[] { s.ReleaseTitle });
|
||||
if (!string.IsNullOrEmpty(s.ReleaseThumbnailUrl))
|
||||
{
|
||||
releaseImages.Add(new Imaging.Image()
|
||||
{
|
||||
Bytes = WebHelper.BytesForImageUrl(s.ReleaseThumbnailUrl)
|
||||
});
|
||||
}
|
||||
result.CopyTo(new Release
|
||||
{
|
||||
ReleaseDate = result.ReleaseDate ?? s.ReleaseDate,
|
||||
|
@ -589,9 +606,6 @@ namespace Roadie.Library.Engines
|
|||
MusicBrainzId = s.MusicBrainzId,
|
||||
ITunesId = s.iTunesId,
|
||||
Title = result.Title ?? s.ReleaseTitle,
|
||||
Thumbnail = s.ReleaseThumbnailUrl != null
|
||||
? WebHelper.BytesForImageUrl(s.ReleaseThumbnailUrl)
|
||||
: null,
|
||||
ReleaseType = result.ReleaseType == ReleaseType.Unknown
|
||||
? SafeParser.ToEnum<ReleaseType>(s.ReleaseType)
|
||||
: result.ReleaseType
|
||||
|
@ -624,14 +638,18 @@ namespace Roadie.Library.Engines
|
|||
if (!string.IsNullOrEmpty(d.ReleaseTitle) &&
|
||||
!d.ReleaseTitle.Equals(result.Title, StringComparison.OrdinalIgnoreCase))
|
||||
result.AlternateNames.AddToDelimitedList(new[] { d.ReleaseTitle });
|
||||
if (!string.IsNullOrEmpty(d.ReleaseThumbnailUrl))
|
||||
{
|
||||
releaseImages.Add(new Imaging.Image()
|
||||
{
|
||||
Bytes = WebHelper.BytesForImageUrl(d.ReleaseThumbnailUrl)
|
||||
});
|
||||
}
|
||||
result.CopyTo(new Release
|
||||
{
|
||||
Profile = HttpEncoder.HtmlEncode(d.Profile),
|
||||
DiscogsId = d.DiscogsId,
|
||||
Title = result.Title ?? d.ReleaseTitle,
|
||||
Thumbnail = d.ReleaseThumbnailUrl != null
|
||||
? WebHelper.BytesForImageUrl(d.ReleaseThumbnailUrl)
|
||||
: null,
|
||||
ReleaseType = result.ReleaseType == ReleaseType.Unknown
|
||||
? SafeParser.ToEnum<ReleaseType>(d.ReleaseType)
|
||||
: result.ReleaseType
|
||||
|
@ -700,29 +718,22 @@ namespace Roadie.Library.Engines
|
|||
if (releaseImageUrls.Any())
|
||||
{
|
||||
var sw2 = Stopwatch.StartNew();
|
||||
var imageBag = new ConcurrentBag<Image>();
|
||||
var imageBag = new ConcurrentBag<IImage>();
|
||||
var i = releaseImageUrls.Select(async url =>
|
||||
{
|
||||
imageBag.Add(await WebHelper.GetImageFromUrlAsync(url));
|
||||
});
|
||||
await Task.WhenAll(i);
|
||||
// If the release has images merge any fetched images
|
||||
var existingImages = result.Images != null ? result.Images.ToList() : new List<Image>();
|
||||
existingImages.AddRange(imageBag.ToList());
|
||||
// Now set release images to be unique image based on image hash
|
||||
result.Images = existingImages
|
||||
.Where(x => x != null && x.Bytes != null)
|
||||
.GroupBy(x => x.Signature)
|
||||
.Select(x => x.First()).Take(Configuration.Processing.MaximumReleaseImagesToAdd)
|
||||
.ToList();
|
||||
if (result.Thumbnail == null && result.Images != null)
|
||||
{
|
||||
result.Thumbnail = result.Images.First().Bytes;
|
||||
}
|
||||
releaseImages.AddRange(imageBag.ToList());
|
||||
sw2.Stop();
|
||||
Logger.LogTrace($"PerformMetaDataProvidersReleaseSearch: Image Url Processing Complete [{ sw2.ElapsedMilliseconds }]");
|
||||
}
|
||||
|
||||
result.Images = releaseImages.Where(x => x.Bytes != null)
|
||||
.GroupBy(x => x.Signature)
|
||||
.Select(x => x.First()).Take(Configuration.Processing.MaximumReleaseImagesToAdd)
|
||||
.ToList();
|
||||
|
||||
if (releaseLabels.Any())
|
||||
{
|
||||
var sw2 = Stopwatch.StartNew();
|
||||
|
|
|
@ -24,7 +24,9 @@ namespace Roadie.Library.Identity
|
|||
|
||||
public ICollection<UserArtist> ArtistRatings { get; set; }
|
||||
|
||||
[Column("avatar", TypeName = "blob")] public byte[] Avatar { get; set; }
|
||||
[Obsolete("Images moved to file system")]
|
||||
[Column("avatar", TypeName = "blob")]
|
||||
public byte[] Avatar { get; set; }
|
||||
|
||||
public ICollection<Bookmark> Bookmarks { get; set; }
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Data;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
@ -8,31 +7,31 @@ namespace Roadie.Library.Imaging
|
|||
{
|
||||
public class DefaultNotFoundImages : IDefaultNotFoundImages
|
||||
{
|
||||
private Image _artist;
|
||||
private Image _collection;
|
||||
private Image _label;
|
||||
private Image _genre;
|
||||
private Image _playlist;
|
||||
private Image _release;
|
||||
private Image _track;
|
||||
private Image _user;
|
||||
private IImage _artist;
|
||||
private IImage _collection;
|
||||
private IImage _label;
|
||||
private IImage _genre;
|
||||
private IImage _playlist;
|
||||
private IImage _release;
|
||||
private IImage _track;
|
||||
private IImage _user;
|
||||
|
||||
public Image Artist => _artist ?? (_artist = MakeImageFromFile(MakeImagePath(@"images/artist.jpg")));
|
||||
public IImage Artist => _artist ?? (_artist = MakeImageFromFile(MakeImagePath(@"images/artist.jpg")));
|
||||
|
||||
public Image Collection =>
|
||||
public IImage Collection =>
|
||||
_collection ?? (_collection = MakeImageFromFile(MakeImagePath(@"images/collection.jpg")));
|
||||
|
||||
public Image Label => _label ?? (_label = MakeImageFromFile(MakeImagePath(@"images/label.jpg")));
|
||||
public IImage Label => _label ?? (_label = MakeImageFromFile(MakeImagePath(@"images/label.jpg")));
|
||||
|
||||
public Image Genre => _genre ?? (_genre = MakeImageFromFile(MakeImagePath(@"images/genre.jpg")));
|
||||
public IImage Genre => _genre ?? (_genre = MakeImageFromFile(MakeImagePath(@"images/genre.jpg")));
|
||||
|
||||
public Image Playlist => _playlist ?? (_playlist = MakeImageFromFile(MakeImagePath(@"images/playlist.jpg")));
|
||||
public IImage Playlist => _playlist ?? (_playlist = MakeImageFromFile(MakeImagePath(@"images/playlist.jpg")));
|
||||
|
||||
public Image Release => _release ?? (_release = MakeImageFromFile(MakeImagePath(@"images/release.jpg")));
|
||||
public IImage Release => _release ?? (_release = MakeImageFromFile(MakeImagePath(@"images/release.jpg")));
|
||||
|
||||
public Image Track => _track ?? (_track = MakeImageFromFile(MakeImagePath(@"images/track.jpg")));
|
||||
public IImage Track => _track ?? (_track = MakeImageFromFile(MakeImagePath(@"images/track.jpg")));
|
||||
|
||||
public Image User => _user ?? (_user = MakeImageFromFile(MakeImagePath(@"images/user.jpg")));
|
||||
public IImage User => _user ?? (_user = MakeImageFromFile(MakeImagePath(@"images/user.jpg")));
|
||||
|
||||
private IRoadieSettings Configuration { get; }
|
||||
|
||||
|
@ -50,24 +49,31 @@ namespace Roadie.Library.Imaging
|
|||
Logger = logger;
|
||||
}
|
||||
|
||||
private static Image MakeImageFromFile(string filename)
|
||||
private static IImage MakeImageFromFile(string filename)
|
||||
{
|
||||
if (!File.Exists(filename)) return new Image();
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
return new Image();
|
||||
}
|
||||
var bytes = File.ReadAllBytes(filename);
|
||||
return new Image
|
||||
{
|
||||
Bytes = bytes,
|
||||
CreatedDate = DateTime.UtcNow,
|
||||
LastUpdated = DateTime.UtcNow
|
||||
CreatedDate = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
private string MakeImagePath(string filename)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename)) return null;
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var path = Path.Combine(Configuration.ContentPath, filename);
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Logger.LogWarning("Unable To Find Path [{0}], ContentPath [{1}]", path, Configuration.ContentPath);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ namespace Roadie.Library.Imaging
|
|||
{
|
||||
public interface IDefaultNotFoundImages
|
||||
{
|
||||
Image Artist { get; }
|
||||
Image Collection { get; }
|
||||
Image Label { get; }
|
||||
Image Genre { get; }
|
||||
Image Playlist { get; }
|
||||
Image Release { get; }
|
||||
Image Track { get; }
|
||||
Image User { get; }
|
||||
IImage Artist { get; }
|
||||
IImage Collection { get; }
|
||||
IImage Label { get; }
|
||||
IImage Genre { get; }
|
||||
IImage Playlist { get; }
|
||||
IImage Release { get; }
|
||||
IImage Track { get; }
|
||||
IImage User { get; }
|
||||
}
|
||||
}
|
21
Roadie.Api.Library/Imaging/IImage.cs
Normal file
21
Roadie.Api.Library/Imaging/IImage.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
using Roadie.Library.Enums;
|
||||
using System;
|
||||
|
||||
namespace Roadie.Library.Imaging
|
||||
{
|
||||
public interface IImage
|
||||
{
|
||||
short SortOrder { get; set; }
|
||||
byte[] Bytes { get; set; }
|
||||
DateTime CreatedDate { get; set; }
|
||||
Guid Id { get; }
|
||||
DateTime LastUpdated { get; set; }
|
||||
string Signature { get; set; }
|
||||
Statuses Status { get; set; }
|
||||
string Url { get; set; }
|
||||
string CacheKey { get; }
|
||||
string CacheRegion { get; }
|
||||
string GenerateSignature();
|
||||
string ToString();
|
||||
}
|
||||
}
|
56
Roadie.Api.Library/Imaging/Image.cs
Normal file
56
Roadie.Api.Library/Imaging/Image.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using Roadie.Library.Enums;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Roadie.Library.Imaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Image class used internally.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class Image : IImage
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public Statuses Status { get; set; }
|
||||
public short SortOrder { get; set; }
|
||||
public byte[] Bytes { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime LastUpdated { get; set; }
|
||||
public string Signature { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public string GenerateSignature()
|
||||
{
|
||||
if (Bytes == null || !Bytes.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ImageHasher.AverageHash(Bytes).ToString();
|
||||
}
|
||||
|
||||
public Image()
|
||||
{
|
||||
}
|
||||
|
||||
public Image(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public override string ToString() => $"Id [{Id}]";
|
||||
|
||||
public string CacheKey => CacheUrn(Id);
|
||||
|
||||
public string CacheRegion => CacheRegionUrn(Id);
|
||||
|
||||
public static string CacheRegionUrn(Guid Id)
|
||||
{
|
||||
return $"urn:artist:{Id}";
|
||||
}
|
||||
|
||||
public static string CacheUrn(Guid Id)
|
||||
{
|
||||
return $"urn:artist_by_id:{Id}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using SixLabors.ImageSharp;
|
||||
using sl = SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System.IO;
|
||||
|
@ -63,7 +63,7 @@ namespace Roadie.Library.Imaging
|
|||
/// <returns>Hash of Image</returns>
|
||||
public static ulong AverageHash(byte[] bytes)
|
||||
{
|
||||
using (var image = Image.Load(bytes))
|
||||
using (var image = sl.Image.Load(bytes))
|
||||
{
|
||||
image.Mutate(ctx => ctx.Resize(8, 8).Grayscale());
|
||||
using (var ms = new MemoryStream())
|
||||
|
@ -100,20 +100,11 @@ namespace Roadie.Library.Imaging
|
|||
/// </summary>
|
||||
/// <param name="path">Path to the input file.</param>
|
||||
/// <returns>The hash of the input file's image content.</returns>
|
||||
public static ulong AverageHash(string path)
|
||||
{
|
||||
return AverageHash(File.ReadAllBytes(path));
|
||||
}
|
||||
public static ulong AverageHash(string path) => AverageHash(File.ReadAllBytes(path));
|
||||
|
||||
public static bool ImagesAreSame(string path1, string path2)
|
||||
{
|
||||
return Similarity(path1, path2) == 100;
|
||||
}
|
||||
public static bool ImagesAreSame(string path1, string path2) => Similarity(path1, path2) == 100;
|
||||
|
||||
public static bool ImagesAreSame(byte[] image1, byte[] image2)
|
||||
{
|
||||
return Similarity(image1, image2) == 100;
|
||||
}
|
||||
public static bool ImagesAreSame(byte[] image1, byte[] image2) => Similarity(image1, image2) == 100;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a percentage-based similarity value between the two given hashes. The higher
|
||||
|
@ -122,10 +113,7 @@ namespace Roadie.Library.Imaging
|
|||
/// <param name="hash1">The first hash.</param>
|
||||
/// <param name="hash2">The second hash.</param>
|
||||
/// <returns>The similarity percentage.</returns>
|
||||
public static double Similarity(ulong hash1, ulong hash2)
|
||||
{
|
||||
return (64 - BitCount(hash1 ^ hash2)) * 100 / 64.0;
|
||||
}
|
||||
public static double Similarity(ulong hash1, ulong hash2) => (64 - BitCount(hash1 ^ hash2)) * 100 / 64.0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a percentage-based similarity value between the image content of the two given
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace Roadie.Library.Imaging
|
|||
using (var outStream = new MemoryStream())
|
||||
{
|
||||
IImageFormat imageFormat = null;
|
||||
using (var image = Image.Load(imageBytes, out imageFormat))
|
||||
using (var image = SixLabors.ImageSharp.Image.Load(imageBytes, out imageFormat))
|
||||
{
|
||||
image.Save(outStream, ImageFormats.Jpeg);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ namespace Roadie.Library.Imaging
|
|||
using (var outStream = new MemoryStream())
|
||||
{
|
||||
IImageFormat imageFormat = null;
|
||||
using (var image = Image.Load(imageBytes, out imageFormat))
|
||||
using (var image = SixLabors.ImageSharp.Image.Load(imageBytes, out imageFormat))
|
||||
{
|
||||
image.Save(outStream, ImageFormats.Gif);
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ namespace Roadie.Library.Imaging
|
|||
var result = new ImageSearchResult();
|
||||
var imageBytes = WebHelper.BytesForImageUrl(imageUrl);
|
||||
IImageFormat imageFormat = null;
|
||||
using (var image = Image.Load(imageBytes, out imageFormat))
|
||||
using (var image = SixLabors.ImageSharp.Image.Load(imageBytes, out imageFormat))
|
||||
{
|
||||
result.Height = image.Height.ToString();
|
||||
result.Width = image.Width.ToString();
|
||||
|
@ -254,7 +254,7 @@ namespace Roadie.Library.Imaging
|
|||
{
|
||||
var resized = false;
|
||||
IImageFormat imageFormat = null;
|
||||
using (var image = Image.Load(imageBytes, out imageFormat))
|
||||
using (var image = SixLabors.ImageSharp.Image.Load(imageBytes, out imageFormat))
|
||||
{
|
||||
var doForce = forceResize ?? false;
|
||||
if (doForce || image.Width > width || image.Height > height)
|
||||
|
|
|
@ -3,17 +3,20 @@ using System.ComponentModel.DataAnnotations;
|
|||
|
||||
namespace Roadie.Library.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Image class served to API consumers.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class Image : EntityModelBase
|
||||
{
|
||||
public Guid? ArtistId { get; set; }
|
||||
|
||||
public byte[] Bytes { get; set; }
|
||||
|
||||
[MaxLength(100)] public string Caption { get; set; }
|
||||
|
||||
[Obsolete("Only here for transition. Will be removed in future release.")]
|
||||
public Guid? ArtistId { get; set; }
|
||||
[Obsolete("Only here for transition. Will be removed in future release.")]
|
||||
public Guid? ReleaseId { get; set; }
|
||||
|
||||
[MaxLength(50)] public string Signature { get; set; }
|
||||
|
||||
[MaxLength(500)] public string ThumbnailUrl { get; set; }
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using HtmlAgilityPack;
|
||||
using Roadie.Library.Data;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Imaging;
|
||||
using System;
|
||||
|
@ -59,7 +58,7 @@ namespace Roadie.Library.Utility
|
|||
return null;
|
||||
}
|
||||
|
||||
public static async Task<Image> GetImageFromUrlAsync(string url)
|
||||
public static async Task<IImage> GetImageFromUrlAsync(string url)
|
||||
{
|
||||
byte[] imageBytes = null;
|
||||
try
|
||||
|
@ -80,7 +79,7 @@ namespace Roadie.Library.Utility
|
|||
{
|
||||
var signature = ImageHasher.AverageHash(imageBytes).ToString();
|
||||
var ib = ImageHelper.ConvertToJpegFormat(imageBytes);
|
||||
return new Image
|
||||
return new Image(Guid.NewGuid())
|
||||
{
|
||||
Url = url,
|
||||
Status = Statuses.New,
|
||||
|
|
|
@ -1012,6 +1012,225 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrate images from Images table and Thumbnails to file storage.
|
||||
/// </summary>
|
||||
public async Task<OperationResult<bool>> MigrateImages(ApplicationUser user)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var now = DateTime.UtcNow;
|
||||
foreach (var artist in DbContext.Artists.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var artistFolder = artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var artistImage = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
|
||||
if (!File.Exists(artistImage))
|
||||
{
|
||||
File.WriteAllBytes(artistImage, ImageHelper.ConvertToJpegFormat(artist.Thumbnail));
|
||||
}
|
||||
artist.Thumbnail = null;
|
||||
artist.LastUpdated = now;
|
||||
|
||||
Logger.LogInformation($"Saved Artist Image `{artist}` path [{ artistImage }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
var artistImages = (from i in DbContext.Images
|
||||
join a in DbContext.Artists on i.ArtistId equals a.Id
|
||||
select new { i, a });
|
||||
foreach (var artistImage in artistImages)
|
||||
{
|
||||
var looper = 0;
|
||||
var artistFolder = artistImage.a.ArtistFileFolder(Configuration);
|
||||
var artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
while (File.Exists(artistImageFilename))
|
||||
{
|
||||
looper++;
|
||||
artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
File.WriteAllBytes(artistImageFilename, ImageHelper.ConvertToJpegFormat(artistImage.i.Bytes));
|
||||
DbContext.Images.Remove(artistImage.i);
|
||||
Logger.LogInformation($"Saved Artist Secondary Image `{artistImage.a}` path [{ artistImageFilename }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var collection in DbContext.Collections.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var image = collection.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(collection.Thumbnail));
|
||||
}
|
||||
collection.Thumbnail = null;
|
||||
collection.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Collection Image `{collection}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var genre in DbContext.Genres.Where(x => x.Thumbnail != null).OrderBy(x => x.Name))
|
||||
{
|
||||
var image = genre.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(genre.Thumbnail));
|
||||
}
|
||||
genre.Thumbnail = null;
|
||||
genre.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Genre Image `{genre}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var label in DbContext.Labels.Where(x => x.Thumbnail != null).OrderBy(x => x.SortName ?? x.Name))
|
||||
{
|
||||
var image = label.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(label.Thumbnail));
|
||||
}
|
||||
label.Thumbnail = null;
|
||||
label.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Label Image `{label}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var playlist in DbContext.Playlists.Where(x => x.Thumbnail != null).OrderBy(x => x.Name))
|
||||
{
|
||||
var image = playlist.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(playlist.Thumbnail));
|
||||
}
|
||||
playlist.Thumbnail = null;
|
||||
playlist.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Playlist Image `{playlist}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var release in DbContext.Releases.Include(x => x.Artist).Where(x => x.Thumbnail != null).OrderBy(x => x.Title))
|
||||
{
|
||||
var artistFolder = release.Artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var releaseImage = Path.Combine(releaseFolder, "cover.jpg");
|
||||
if (!File.Exists(releaseImage))
|
||||
{
|
||||
File.WriteAllBytes(releaseImage, ImageHelper.ConvertToJpegFormat(release.Thumbnail));
|
||||
}
|
||||
release.Thumbnail = null;
|
||||
release.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Release Image `{release}` path [{ releaseImage }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error saving Release Image `{release}` folder [{ releaseFolder }]");
|
||||
}
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
var releaseImages = (from i in DbContext.Images
|
||||
join r in DbContext.Releases.Include(x => x.Artist) on i.ReleaseId equals r.Id
|
||||
select new { i, r });
|
||||
foreach (var releaseImage in releaseImages)
|
||||
{
|
||||
var looper = 0;
|
||||
var artistFolder = releaseImage.r.Artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = releaseImage.r.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var releaseImageFilename = Path.Combine(releaseFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
try
|
||||
{
|
||||
while (File.Exists(releaseImageFilename))
|
||||
{
|
||||
looper++;
|
||||
releaseImageFilename = Path.Combine(releaseFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
}
|
||||
File.WriteAllBytes(releaseImageFilename, ImageHelper.ConvertToJpegFormat(releaseImage.i.Bytes));
|
||||
DbContext.Images.Remove(releaseImage.i);
|
||||
Logger.LogInformation($"Saved Release Secondary Image `{releaseImage.r}` path [{ releaseImageFilename }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error saving Release Secondary Image [{releaseImageFilename}] folder [{ releaseFolder }]");
|
||||
}
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var track in DbContext.Tracks.Include(x => x.ReleaseMedia)
|
||||
.Include(x => x.ReleaseMedia.Release)
|
||||
.Include(x => x.ReleaseMedia.Release.Artist)
|
||||
.Where(x => x.Thumbnail != null).OrderBy(x => x.Title))
|
||||
{
|
||||
var artistFolder = track.ReleaseMedia.Release.Artist.ArtistFileFolder(Configuration);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
Directory.CreateDirectory(artistFolder);
|
||||
}
|
||||
var releaseFolder = track.ReleaseMedia.Release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
Directory.CreateDirectory(releaseFolder);
|
||||
}
|
||||
var trackImage = track.PathToTrackThumbnail(Configuration);
|
||||
try
|
||||
{
|
||||
if (!File.Exists(trackImage))
|
||||
{
|
||||
File.WriteAllBytes(trackImage, ImageHelper.ConvertToJpegFormat(track.Thumbnail));
|
||||
}
|
||||
track.Thumbnail = null;
|
||||
track.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved Track Image `{track}` path [{ trackImage }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error saving Track Image [{trackImage}] folder [{ releaseFolder }]");
|
||||
}
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
foreach (var usr in DbContext.Users.Where(x => x.Avatar != null).OrderBy(x => x.UserName))
|
||||
{
|
||||
var image = usr.PathToImage(Configuration);
|
||||
if (!File.Exists(image))
|
||||
{
|
||||
File.WriteAllBytes(image, ImageHelper.ConvertToJpegFormat(usr.Avatar));
|
||||
}
|
||||
usr.Avatar = null;
|
||||
usr.LastUpdated = now;
|
||||
Logger.LogInformation($"Saved User Image `{user}` path [{ image }]");
|
||||
}
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = true,
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> ValidateInviteToken(Guid? tokenId)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
|
|
@ -552,23 +552,6 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Services.FileDirectoryProcessorService.DeleteEmptyFolders(new DirectoryInfo(artistFolder), Logger);
|
||||
}
|
||||
// Always update artist image if artist image is found on an artist rescan
|
||||
var imageFiles = ImageHelper.ImageFilesInFolder(artistFolder, SearchOption.AllDirectories);
|
||||
if (imageFiles != null && imageFiles.Any())
|
||||
{
|
||||
var i = new FileInfo(imageFiles.First());
|
||||
var iName = i.Name.ToLower().Trim();
|
||||
if (ImageHelper.IsArtistImage(i))
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
artist.Thumbnail = ImageHelper.ResizeToThumbnail(File.ReadAllBytes(i.FullName), Configuration);
|
||||
artist.LastUpdated = DateTime.UtcNow;
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(artist.CacheRegion);
|
||||
Logger.LogTrace("Update Thumbnail using Artist File [{0}]", iName);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
CacheManager.ClearRegion(artist.CacheRegion);
|
||||
Logger.LogInformation("Scanned Artist [{0}], Releases Scanned [{1}], OperationTime [{2}]", artist.ToString(), releaseScannedCount, sw.ElapsedMilliseconds);
|
||||
|
@ -588,7 +571,7 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Image>> SetReleaseImageByUrl(ApplicationUser user, Guid id, string imageUrl)
|
||||
public async Task<OperationResult<Library.Models.Image>> SetReleaseImageByUrl(ApplicationUser user, Guid id, string imageUrl)
|
||||
{
|
||||
return await SaveImageBytes(user, id, WebHelper.BytesForImageUrl(imageUrl));
|
||||
}
|
||||
|
@ -596,7 +579,6 @@ namespace Roadie.Api.Services
|
|||
public async Task<OperationResult<bool>> UpdateArtist(ApplicationUser user, Artist model)
|
||||
{
|
||||
var didRenameArtist = false;
|
||||
var didChangeThumbnail = false;
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
|
@ -689,10 +671,6 @@ namespace Roadie.Api.Services
|
|||
// Save unaltered image to cover file
|
||||
var artistImageName = Path.Combine(newArtistFolder, ImageHelper.ArtistImageFilename);
|
||||
File.WriteAllBytes(artistImageName, ImageHelper.ConvertToJpegFormat(artistImage));
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
artist.Thumbnail = ImageHelper.ResizeToThumbnail(artistImage, Configuration);
|
||||
didChangeThumbnail = true;
|
||||
}
|
||||
|
||||
if (model.NewSecondaryImagesData != null && model.NewSecondaryImagesData.Any())
|
||||
|
@ -855,7 +833,7 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
CacheManager.ClearRegion(artist.CacheRegion);
|
||||
Logger.LogInformation($"UpdateArtist `{artist}` By User `{user}`: Renamed Artist [{didRenameArtist}], Uploaded new image [{didChangeThumbnail}]");
|
||||
Logger.LogInformation($"UpdateArtist `{artist}` By User `{user}`: Renamed Artist [{didRenameArtist}]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -874,7 +852,7 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Image>> UploadArtistImage(ApplicationUser user, Guid id, IFormFile file)
|
||||
public async Task<OperationResult<Library.Models.Image>> UploadArtistImage(ApplicationUser user, Guid id, IFormFile file)
|
||||
{
|
||||
var bytes = new byte[0];
|
||||
using (var ms = new MemoryStream())
|
||||
|
@ -1022,15 +1000,12 @@ namespace Roadie.Api.Services
|
|||
if (includes.Contains("images"))
|
||||
{
|
||||
tsw.Restart();
|
||||
result.Images = DbContext.Images.Where(x => x.ArtistId == artist.Id)
|
||||
.Select(x => MakeFullsizeImage(Configuration, HttpContext, x.RoadieId, x.Caption)).ToArray();
|
||||
|
||||
var artistFolder = artist.ArtistFileFolder(Configuration);
|
||||
var artistImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder),
|
||||
ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly);
|
||||
var artistImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly);
|
||||
if (artistImagesInFolder.Any())
|
||||
result.Images = result.Images.Concat(artistImagesInFolder.Select((x, i) =>
|
||||
MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ArtistSecondary, i)));
|
||||
{
|
||||
result.Images = artistImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ArtistSecondary, i));
|
||||
}
|
||||
|
||||
tsw.Stop();
|
||||
timings.Add("images", tsw.ElapsedMilliseconds);
|
||||
|
@ -1313,7 +1288,6 @@ namespace Roadie.Api.Services
|
|||
artistToMergeInto.ITunesId = artistToMergeInto.ITunesId ?? artistToMerge.ITunesId;
|
||||
artistToMergeInto.AmgId = artistToMergeInto.AmgId ?? artistToMerge.AmgId;
|
||||
artistToMergeInto.SpotifyId = artistToMergeInto.SpotifyId ?? artistToMerge.SpotifyId;
|
||||
artistToMergeInto.Thumbnail = artistToMergeInto.Thumbnail ?? artistToMerge.Thumbnail;
|
||||
artistToMergeInto.Profile = artistToMergeInto.Profile ?? artistToMerge.Profile;
|
||||
artistToMergeInto.BirthDate = artistToMergeInto.BirthDate ?? artistToMerge.BirthDate;
|
||||
artistToMergeInto.BeginDate = artistToMergeInto.BeginDate ?? artistToMerge.BeginDate;
|
||||
|
@ -1353,15 +1327,6 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
}
|
||||
}
|
||||
var artistImages = DbContext.Images.Where(x => x.ArtistId == artistToMerge.Id).ToArray();
|
||||
if (artistImages != null)
|
||||
{
|
||||
foreach (var artistImage in artistImages)
|
||||
{
|
||||
artistImage.ArtistId = artistToMergeInto.Id;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Move any Artist and Artist Secondary images from ArtistToMerge into ArtistToMergeInto folder
|
||||
|
@ -1407,13 +1372,6 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
var userArtists = DbContext.UserArtists.Where(x => x.ArtistId == artistToMerge.Id).ToArray();
|
||||
if (artistImages != null)
|
||||
{
|
||||
foreach (var userArtist in userArtists)
|
||||
{
|
||||
userArtist.ArtistId = artistToMergeInto.Id;
|
||||
}
|
||||
}
|
||||
var artistTracks = DbContext.Tracks.Where(x => x.ArtistId == artistToMerge.Id).ToArray();
|
||||
if (artistTracks != null)
|
||||
{
|
||||
|
@ -1465,18 +1423,17 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
private async Task<OperationResult<Image>> SaveImageBytes(ApplicationUser user, Guid id, byte[] imageBytes)
|
||||
private async Task<OperationResult<Library.Models.Image>> SaveImageBytes(ApplicationUser user, Guid id, byte[] imageBytes)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var artist = DbContext.Artists.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (artist == null) return new OperationResult<Image>(true, $"Artist Not Found [{id}]");
|
||||
if (artist == null) return new OperationResult<Library.Models.Image>(true, $"Artist Not Found [{id}]");
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
artist.Thumbnail = imageBytes;
|
||||
if (artist.Thumbnail != null)
|
||||
if (imageBytes != null)
|
||||
{
|
||||
// Ensure artist folder exists
|
||||
var artistFolder = artist.ArtistFileFolder(Configuration);
|
||||
|
@ -1489,11 +1446,7 @@ namespace Roadie.Api.Services
|
|||
// Save unaltered image to artist file
|
||||
var artistImage = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
|
||||
File.WriteAllBytes(artistImage, ImageHelper.ConvertToJpegFormat(imageBytes));
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
artist.Thumbnail = ImageHelper.ResizeToThumbnail(artist.Thumbnail, Configuration);
|
||||
}
|
||||
|
||||
artist.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(artist.CacheRegion);
|
||||
|
@ -1507,7 +1460,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<Image>
|
||||
return new OperationResult<Library.Models.Image>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = MakeThumbnailImage(Configuration, HttpContext, id, "artist", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
|
||||
|
|
|
@ -302,14 +302,10 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
// Save unaltered collection image
|
||||
File.WriteAllBytes(collection.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(collectionImage));
|
||||
// Update Thumbnail
|
||||
collection.Thumbnail = ImageHelper.ResizeToThumbnail(collectionImage, Configuration);
|
||||
}
|
||||
|
||||
if (model.Maintainer?.Value != null)
|
||||
{
|
||||
var maintainer =
|
||||
DbContext.Users.FirstOrDefault(x => x.RoadieId == SafeParser.ToGuid(model.Maintainer.Value));
|
||||
var maintainer = DbContext.Users.FirstOrDefault(x => x.RoadieId == SafeParser.ToGuid(model.Maintainer.Value));
|
||||
if (maintainer != null) collection.MaintainerId = maintainer.Id;
|
||||
}
|
||||
|
||||
|
|
|
@ -159,12 +159,12 @@ namespace Roadie.Api.Services
|
|||
});
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Image>> SetGenreImageByUrl(User user, Guid id, string imageUrl)
|
||||
public async Task<OperationResult<Library.Models.Image>> SetGenreImageByUrl(User user, Guid id, string imageUrl)
|
||||
{
|
||||
return await SaveImageBytes(user, id, WebHelper.BytesForImageUrl(imageUrl));
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Image>> UploadGenreImage(User user, Guid id, IFormFile file)
|
||||
public async Task<OperationResult<Library.Models.Image>> UploadGenreImage(User user, Guid id, IFormFile file)
|
||||
{
|
||||
var bytes = new byte[0];
|
||||
using (var ms = new MemoryStream())
|
||||
|
@ -230,24 +230,21 @@ namespace Roadie.Api.Services
|
|||
});
|
||||
}
|
||||
|
||||
private async Task<OperationResult<Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
private async Task<OperationResult<Library.Models.Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var genre = DbContext.Genres.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (genre == null) return new OperationResult<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;
|
||||
genre.Thumbnail = imageBytes;
|
||||
if (genre.Thumbnail != null)
|
||||
if (imageBytes != null)
|
||||
{
|
||||
// Save unaltered label image
|
||||
File.WriteAllBytes(genre.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(imageBytes));
|
||||
genre.Thumbnail = ImageHelper.ResizeToThumbnail(genre.Thumbnail, Configuration);
|
||||
}
|
||||
|
||||
genre.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(genre.CacheRegion);
|
||||
|
@ -261,7 +258,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<Image>
|
||||
return new OperationResult<Library.Models.Image>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = MakeThumbnailImage(Configuration, HttpContext, id, "genre", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
|
||||
|
|
|
@ -52,5 +52,7 @@ namespace Roadie.Api.Services
|
|||
Task<OperationResult<bool>> UpdateInviteTokenUsed(Guid? tokenId);
|
||||
|
||||
Task<OperationResult<bool>> ValidateInviteToken(Guid? tokenId);
|
||||
|
||||
Task<OperationResult<bool>> MigrateImages(ApplicationUser user);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using Microsoft.Net.Http.Headers;
|
||||
using Roadie.Library;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.SearchEngines.Imaging;
|
||||
using System;
|
||||
|
@ -15,30 +16,28 @@ namespace Roadie.Api.Services
|
|||
|
||||
string RequestIp { get; set; }
|
||||
|
||||
Task<FileOperationResult<Image>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<OperationResult<bool>> Delete(ApplicationUser user, Guid id);
|
||||
Task<FileOperationResult<IImage>> GenreImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> GenreImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<OperationResult<IEnumerable<ImageSearchResult>>> Search(string query, int resultsCount = 10);
|
||||
|
||||
Task<FileOperationResult<Image>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Image>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<IImage>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Roadie.Library;
|
||||
|
@ -51,7 +50,7 @@ namespace Roadie.Api.Services
|
|||
DefaultNotFoundImages = defaultNotFoundImages;
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("ArtistImage",
|
||||
data.Artist.CacheRegionUrn(id),
|
||||
|
@ -62,10 +61,10 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation($"ArtistSecondaryThumbnail-{imageId}",
|
||||
data.Release.CacheRegionUrn(id),
|
||||
return await GetImageFileOperation($"ArtistSecondaryThumbnail.{imageId}",
|
||||
data.Artist.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
|
@ -73,10 +72,10 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("ImageById",
|
||||
data.Image.CacheRegionUrn(id),
|
||||
Library.Imaging.Image.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
|
@ -84,7 +83,7 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> CollectionImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("CollectionThumbnail",
|
||||
data.Collection.CacheRegionUrn(id),
|
||||
|
@ -95,33 +94,10 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> Delete(ApplicationUser user, Guid id)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var image = DbContext.Images
|
||||
.Include("Release")
|
||||
.Include("Artist")
|
||||
.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (image == null) return new OperationResult<bool>(true, string.Format("Image Not Found [{0}]", id));
|
||||
DbContext.Images.Remove(image);
|
||||
await DbContext.SaveChangesAsync();
|
||||
if (image.ArtistId.HasValue) CacheManager.ClearRegion(data.Artist.CacheRegionUrn(image.Artist.RoadieId));
|
||||
if (image.ReleaseId.HasValue) CacheManager.ClearRegion(data.Release.CacheRegionUrn(image.Release.RoadieId));
|
||||
CacheManager.ClearRegion(data.Image.CacheRegionUrn(id));
|
||||
Logger.LogWarning("User `{0}` deleted Image `{1}]`", user, image);
|
||||
sw.Stop();
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Data = true,
|
||||
IsSuccess = true,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> GenreImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> GenreImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("GenreThumbnail",
|
||||
data.Label.CacheRegionUrn(id),
|
||||
data.Genre.CacheRegionUrn(id),
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
|
@ -129,7 +105,7 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> LabelImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("LabelThumbnail",
|
||||
data.Label.CacheRegionUrn(id),
|
||||
|
@ -140,7 +116,7 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("PlaylistThumbnail",
|
||||
data.Playlist.CacheRegionUrn(id),
|
||||
|
@ -151,7 +127,7 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("ReleaseThumbnail",
|
||||
data.Release.CacheRegionUrn(id),
|
||||
|
@ -162,7 +138,7 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation($"ReleaseSecondaryThumbnail-{imageId}",
|
||||
data.Release.CacheRegionUrn(id),
|
||||
|
@ -199,7 +175,7 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> TrackImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("TrackThumbnail",
|
||||
data.Track.CacheRegionUrn(id),
|
||||
|
@ -210,7 +186,7 @@ namespace Roadie.Api.Services
|
|||
etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
public async Task<FileOperationResult<IImage>> UserImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await GetImageFileOperation("UserById",
|
||||
ApplicationUser.CacheRegionUrn(id),
|
||||
|
@ -224,14 +200,14 @@ namespace Roadie.Api.Services
|
|||
/// <summary>
|
||||
/// Get image for an artist, see if the artist has an image in their folder and use that else use Artist.Thumbnail, is also not found use Artist DefaultNotFound image.
|
||||
/// </summary>
|
||||
private Task<FileOperationResult<Image>> ArtistImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> ArtistImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var artist = GetArtist(id);
|
||||
if (artist == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Artist Not Found [{0}]", id)));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Artist Not Found [{0}]", id)));
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
|
@ -257,12 +233,9 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError(ex, $"Error Reading Folder [{artistFolder}] For Artist [{artist.Id}]");
|
||||
}
|
||||
|
||||
imageBytes = imageBytes ?? artist.Thumbnail;
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
CreatedDate = artist.CreatedDate,
|
||||
LastUpdated = artist.LastUpdated
|
||||
};
|
||||
if (imageBytes == null || !imageBytes.Any())
|
||||
{
|
||||
|
@ -275,17 +248,18 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Artist Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ArtistSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> ArtistSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var artist = GetArtist(id);
|
||||
if (artist == null)
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Release Not Found [{0}]", id)));
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
try
|
||||
|
@ -310,11 +284,10 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError(ex, $"Error Reading Artist Folder [{artistFolder}] For Artist `{artist}`");
|
||||
}
|
||||
|
||||
var image = new data.Image
|
||||
var image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
CreatedDate = artist.CreatedDate,
|
||||
LastUpdated = artist.LastUpdated
|
||||
CreatedDate = artist.CreatedDate
|
||||
};
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
|
@ -323,23 +296,21 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> CollectionImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> CollectionImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var collection = GetCollection(id);
|
||||
if (collection == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Collection Not Found [{0}]", id)));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Collection Not Found [{0}]", id)));
|
||||
}
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = collection.Thumbnail,
|
||||
CreatedDate = collection.CreatedDate,
|
||||
LastUpdated = collection.LastUpdated
|
||||
CreatedDate = collection.CreatedDate
|
||||
};
|
||||
var collectionImageFilename = collection.PathToImage(Configuration);
|
||||
try
|
||||
|
@ -353,7 +324,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Logger.LogError(ex, $"Error Reading Image File [{collectionImageFilename}]");
|
||||
}
|
||||
if (collection.Thumbnail == null || !collection.Thumbnail.Any())
|
||||
if (image.Bytes == null || !image.Bytes.Any())
|
||||
{
|
||||
image = DefaultNotFoundImages.Collection;
|
||||
}
|
||||
|
@ -364,46 +335,44 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Collection Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private FileOperationResult<Image> GenerateFileOperationResult(Guid id, data.Image image, EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
|
||||
private FileOperationResult<IImage> GenerateFileOperationResult(Guid id, IImage image, EntityTagHeaderValue etag = null, string contentType = "image/jpeg")
|
||||
{
|
||||
var imageEtag = EtagHelper.GenerateETag(HttpEncoder, image.Bytes);
|
||||
if (EtagHelper.CompareETag(HttpEncoder, etag, imageEtag))
|
||||
{
|
||||
return new FileOperationResult<Image>(OperationMessages.NotModified);
|
||||
return new FileOperationResult<IImage>(OperationMessages.NotModified);
|
||||
}
|
||||
if (image?.Bytes?.Any() != true)
|
||||
{
|
||||
return new FileOperationResult<Image>(string.Format("ImageById Not Set [{0}]", id));
|
||||
return new FileOperationResult<IImage>(string.Format("ImageById Not Set [{0}]", id));
|
||||
}
|
||||
return new FileOperationResult<Image>(image?.Bytes?.Any() ?? false
|
||||
return new FileOperationResult<IImage>(image?.Bytes?.Any() ?? false
|
||||
? OperationMessages.OkMessage
|
||||
: OperationMessages.NoImageDataFound)
|
||||
{
|
||||
IsSuccess = true,
|
||||
Data = image.Adapt<Image>(),
|
||||
Data = image,
|
||||
ContentType = contentType,
|
||||
LastModified = image.LastUpdated ?? image.CreatedDate,
|
||||
LastModified = image.CreatedDate,
|
||||
ETag = imageEtag
|
||||
};
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> GenreImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> GenreImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var genre = GetGenre(id);
|
||||
if (genre == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Genre Not Found [{0}]", id)));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Genre Not Found [{0}]", id)));
|
||||
}
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = genre.Thumbnail,
|
||||
CreatedDate = genre.CreatedDate,
|
||||
LastUpdated = genre.LastUpdated
|
||||
CreatedDate = genre.CreatedDate
|
||||
};
|
||||
var genreImageFilename = genre.PathToImage(Configuration);
|
||||
try
|
||||
|
@ -417,7 +386,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Logger.LogError(ex, $"Error Reading Image File [{genreImageFilename}]");
|
||||
}
|
||||
if (genre.Thumbnail == null || !genre.Thumbnail.Any())
|
||||
if (image.Bytes == null || !image.Bytes.Any())
|
||||
{
|
||||
image = DefaultNotFoundImages.Genre;
|
||||
}
|
||||
|
@ -428,22 +397,23 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Label Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private async Task<FileOperationResult<Image>> GetImageFileOperation(string type, string regionUrn, Guid id, int? width, int? height, Func<Task<FileOperationResult<Image>>> action, EntityTagHeaderValue etag = null)
|
||||
private async Task<FileOperationResult<IImage>> GetImageFileOperation(string type, string regionUrn, Guid id, int? width, int? height, Func<Task<FileOperationResult<IImage>>> action, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = (await CacheManager.GetAsync($"urn:{type}_by_id_operation:{id}", action, regionUrn)).Adapt<FileOperationResult<Image>>();
|
||||
var sizeHash = (width ?? 0) + (height ?? 0);
|
||||
var result = await CacheManager.GetAsync($"urn:{type}_by_id_operation:{id}:{sizeHash}", action, regionUrn);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return new FileOperationResult<Image>(result.IsNotFoundResult, result.Messages);
|
||||
return new FileOperationResult<IImage>(result.IsNotFoundResult, result.Messages);
|
||||
}
|
||||
if (result.ETag == etag && etag != null)
|
||||
{
|
||||
return new FileOperationResult<Image>(OperationMessages.NotModified);
|
||||
return new FileOperationResult<IImage>(OperationMessages.NotModified);
|
||||
}
|
||||
var force = width.HasValue || height.HasValue;
|
||||
var newWidth = width ?? Configuration.MaximumImageSize.Width;
|
||||
|
@ -468,7 +438,7 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
sw.Stop();
|
||||
return new FileOperationResult<Image>(result.Messages)
|
||||
return new FileOperationResult<IImage>(result.Messages)
|
||||
{
|
||||
Data = result.Data,
|
||||
ETag = result.ETag,
|
||||
|
@ -484,43 +454,46 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError(ex, $"GetImageFileOperation Error, Type [{type}], id [{id}]");
|
||||
}
|
||||
|
||||
return new FileOperationResult<Image>("System Error");
|
||||
return new FileOperationResult<IImage>("System Error");
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ImageByIdAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> ImageByIdAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var image = DbContext.Images
|
||||
.Include("Release")
|
||||
.Include("Artist")
|
||||
.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (image == null)
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("ImageById Not Found [{0}]", id)));
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
// TODO #29; fetch image by ID
|
||||
|
||||
throw new NotImplementedException();
|
||||
|
||||
//var image = DbContext.Images
|
||||
// .Include("Release")
|
||||
// .Include("Artist")
|
||||
// .FirstOrDefault(x => x.RoadieId == id);
|
||||
//if (image == null)
|
||||
//{
|
||||
// return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("ImageById Not Found [{0}]", id)));
|
||||
//}
|
||||
//return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Error fetching Image [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> LabelImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> LabelImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var label = GetLabel(id);
|
||||
if (label == null)
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true,
|
||||
string.Format("Label Not Found [{0}]", id)));
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = label.Thumbnail,
|
||||
CreatedDate = label.CreatedDate,
|
||||
LastUpdated = label.LastUpdated
|
||||
CreatedDate = label.CreatedDate
|
||||
};
|
||||
var labelImageFilename = label.PathToImage(Configuration);
|
||||
try
|
||||
|
@ -534,7 +507,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Logger.LogError(ex, $"Error Reading Image File [{labelImageFilename}]");
|
||||
}
|
||||
if (label.Thumbnail == null || !label.Thumbnail.Any())
|
||||
if (image.Bytes == null || !image.Bytes.Any())
|
||||
{
|
||||
image = DefaultNotFoundImages.Label;
|
||||
}
|
||||
|
@ -545,22 +518,20 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Label Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> PlaylistImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> PlaylistImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var playlist = GetPlaylist(id);
|
||||
if (playlist == null)
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true,
|
||||
string.Format("Playlist Not Found [{0}]", id)));
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = playlist.Thumbnail,
|
||||
CreatedDate = playlist.CreatedDate,
|
||||
LastUpdated = playlist.LastUpdated
|
||||
CreatedDate = playlist.CreatedDate
|
||||
};
|
||||
var playlistImageFilename = playlist.PathToImage(Configuration);
|
||||
try
|
||||
|
@ -574,7 +545,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Logger.LogError(ex, $"Error Reading Image File [{playlistImageFilename}]");
|
||||
}
|
||||
if (playlist.Thumbnail == null || !playlist.Thumbnail.Any())
|
||||
if (image.Bytes == null || !image.Bytes.Any())
|
||||
{
|
||||
image = DefaultNotFoundImages.Playlist;
|
||||
}
|
||||
|
@ -585,20 +556,20 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Playlist Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get image for Release from Release folder, if not exists then use Release.Thumbnail if that is not set then use Release DefaultNotFound image.
|
||||
/// </summary>
|
||||
private Task<FileOperationResult<Image>> ReleaseImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> ReleaseImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var release = GetRelease(id);
|
||||
if (release == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
|
@ -632,15 +603,12 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Logger.LogError(ex, $"Error Reading Release Folder [{releaseFolder}] Artist Folder [{artistFolder}] For Artist `{release.Artist.Id}`");
|
||||
}
|
||||
|
||||
imageBytes = imageBytes ?? release.Thumbnail;
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
CreatedDate = release.CreatedDate,
|
||||
LastUpdated = release.LastUpdated
|
||||
CreatedDate = release.CreatedDate
|
||||
};
|
||||
if (release.Thumbnail?.Any() != true)
|
||||
if (imageBytes?.Any() != true)
|
||||
{
|
||||
image = DefaultNotFoundImages.Release;
|
||||
}
|
||||
|
@ -651,18 +619,19 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ReleaseSecondaryImageAction(Guid id, int imageId,
|
||||
private Task<FileOperationResult<IImage>> ReleaseSecondaryImageAction(Guid id, int imageId,
|
||||
EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var release = GetRelease(id);
|
||||
if (release == null)
|
||||
return Task.FromResult(new FileOperationResult<Image>(true,
|
||||
string.Format("Release Not Found [{0}]", id)));
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
string releaseFolder = null;
|
||||
|
@ -697,11 +666,10 @@ namespace Roadie.Api.Services
|
|||
$"Error Reading Release Folder [{releaseFolder}] Artist Folder [{artistFolder}] For Artist `{release.Artist.Id}`");
|
||||
}
|
||||
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
CreatedDate = release.CreatedDate,
|
||||
LastUpdated = release.LastUpdated
|
||||
CreatedDate = release.CreatedDate
|
||||
};
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
|
@ -710,31 +678,32 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Release Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private async Task<FileOperationResult<Image>> TrackImageAction(Guid id, int? width, int? height,
|
||||
EntityTagHeaderValue etag = null)
|
||||
private async Task<FileOperationResult<IImage>> TrackImageAction(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var track = GetTrack(id);
|
||||
if (track == null)
|
||||
return new FileOperationResult<Image>(true, string.Format("Track Not Found [{0}]", id));
|
||||
var imageBytes = track.Thumbnail;
|
||||
var trackThumbnailImages = ImageHelper.FindImageTypeInDirectory(
|
||||
new DirectoryInfo(track.PathToTrackThumbnail(Configuration)),
|
||||
ImageType.Track, SearchOption.TopDirectoryOnly);
|
||||
if (trackThumbnailImages.Any()) imageBytes = File.ReadAllBytes(trackThumbnailImages.First().FullName);
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = track.Thumbnail,
|
||||
CreatedDate = track.CreatedDate,
|
||||
LastUpdated = track.LastUpdated
|
||||
return new FileOperationResult<IImage>(true, string.Format("Track Not Found [{0}]", id));
|
||||
}
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
CreatedDate = track.CreatedDate
|
||||
};
|
||||
if (track.Thumbnail == null || !track.Thumbnail.Any())
|
||||
var trackThumbnailImages = ImageHelper.FindImageTypeInDirectory( new DirectoryInfo(track.PathToTrackThumbnail(Configuration)), ImageType.Track, SearchOption.TopDirectoryOnly);
|
||||
if (trackThumbnailImages.Any())
|
||||
{
|
||||
image.Bytes = File.ReadAllBytes(trackThumbnailImages.First().FullName);
|
||||
}
|
||||
if (image.Bytes == null || !image.Bytes.Any())
|
||||
{
|
||||
// If no track image is found then return image for release
|
||||
return await ReleaseImage(track.ReleaseMedia.Release.RoadieId, width, height, etag);
|
||||
}
|
||||
return GenerateFileOperationResult(id, image, etag);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -742,23 +711,21 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching Track Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return new FileOperationResult<Image>(OperationMessages.ErrorOccured);
|
||||
return new FileOperationResult<IImage>(OperationMessages.ErrorOccured);
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> UserImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
private Task<FileOperationResult<IImage>> UserImageAction(Guid id, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = GetUser(id);
|
||||
if (user == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("User Not Found [{0}]", id)));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(true, string.Format("User Not Found [{0}]", id)));
|
||||
}
|
||||
var image = new data.Image
|
||||
IImage image = new Library.Imaging.Image(id)
|
||||
{
|
||||
Bytes = user.Avatar,
|
||||
CreatedDate = user.CreatedDate.Value,
|
||||
LastUpdated = user.LastUpdated
|
||||
CreatedDate = user.CreatedDate.Value
|
||||
};
|
||||
var userImageFilename = user.PathToImage(Configuration);
|
||||
try
|
||||
|
@ -772,7 +739,7 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
Logger.LogError(ex, $"Error Reading Image File [{userImageFilename}]");
|
||||
}
|
||||
if (!(image?.Bytes?.Any() ?? false))
|
||||
if (image.Bytes == null || !image.Bytes.Any())
|
||||
{
|
||||
image = DefaultNotFoundImages.User;
|
||||
}
|
||||
|
@ -783,7 +750,7 @@ namespace Roadie.Api.Services
|
|||
Logger.LogError($"Error fetching User Thumbnail [{id}]", ex);
|
||||
}
|
||||
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
return Task.FromResult(new FileOperationResult<IImage>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -218,7 +218,6 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
label.MusicBrainzId = label.MusicBrainzId ?? labelToMerge.MusicBrainzId;
|
||||
label.SortName = label.SortName ?? labelToMerge.SortName;
|
||||
label.Thumbnail = label.Thumbnail ?? labelToMerge.Thumbnail;
|
||||
label.Profile = label.Profile ?? labelToMerge.Profile;
|
||||
label.BeginDate = label.BeginDate ?? labelToMerge.BeginDate;
|
||||
label.EndDate = label.EndDate ?? labelToMerge.EndDate;
|
||||
|
@ -259,7 +258,7 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Image>> SetLabelImageByUrl(User user, Guid id, string imageUrl)
|
||||
public async Task<OperationResult<Library.Models.Image>> SetLabelImageByUrl(User user, Guid id, string imageUrl)
|
||||
{
|
||||
return await SaveImageBytes(user, id, WebHelper.BytesForImageUrl(imageUrl));
|
||||
}
|
||||
|
@ -312,15 +311,12 @@ namespace Roadie.Api.Services
|
|||
File.Move(oldPathToImage, label.PathToImage(Configuration));
|
||||
}
|
||||
}
|
||||
|
||||
var labelImage = ImageHelper.ImageDataFromUrl(model.NewThumbnailData);
|
||||
if (labelImage != null)
|
||||
{
|
||||
// Save unaltered label image
|
||||
File.WriteAllBytes(label.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(labelImage));
|
||||
label.Thumbnail = ImageHelper.ResizeToThumbnail(labelImage, Configuration);
|
||||
}
|
||||
|
||||
label.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
|
@ -344,7 +340,7 @@ namespace Roadie.Api.Services
|
|||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Image>> UploadLabelImage(User user, Guid id, IFormFile file)
|
||||
public async Task<OperationResult<Library.Models.Image>> UploadLabelImage(User user, Guid id, IFormFile file)
|
||||
{
|
||||
var bytes = new byte[0];
|
||||
using (var ms = new MemoryStream())
|
||||
|
@ -452,24 +448,21 @@ namespace Roadie.Api.Services
|
|||
});
|
||||
}
|
||||
|
||||
private async Task<OperationResult<Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
private async Task<OperationResult<Library.Models.Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var label = DbContext.Labels.FirstOrDefault(x => x.RoadieId == id);
|
||||
if (label == null) return new OperationResult<Image>(true, string.Format("Label Not Found [{0}]", id));
|
||||
if (label == null) return new OperationResult<Library.Models.Image>(true, string.Format("Label Not Found [{0}]", id));
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
label.Thumbnail = imageBytes;
|
||||
if (label.Thumbnail != null)
|
||||
if (imageBytes != null)
|
||||
{
|
||||
// Save unaltered label image
|
||||
File.WriteAllBytes(label.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(imageBytes));
|
||||
label.Thumbnail = ImageHelper.ResizeToThumbnail(label.Thumbnail, Configuration);
|
||||
}
|
||||
|
||||
label.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(label.CacheRegion);
|
||||
|
@ -483,7 +476,7 @@ namespace Roadie.Api.Services
|
|||
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<Image>
|
||||
return new OperationResult<Library.Models.Image>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = MakeThumbnailImage(Configuration, HttpContext, id, "label", Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height, true),
|
||||
|
|
|
@ -353,8 +353,6 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
// Save unaltered playlist image
|
||||
File.WriteAllBytes(playlist.PathToImage(Configuration), ImageHelper.ConvertToJpegFormat(playlistImage));
|
||||
// Update thumbnail
|
||||
playlist.Thumbnail = ImageHelper.ResizeToThumbnail(playlistImage, Configuration);
|
||||
}
|
||||
playlist.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace Roadie.Api.Services
|
|||
var userBookmarkResult = await BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Release);
|
||||
if (userBookmarkResult.IsSuccess)
|
||||
{
|
||||
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Value == release.RoadieId.ToString()) != null;
|
||||
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark?.Value == release.RoadieId.ToString()) != null;
|
||||
}
|
||||
if (result.Data.Medias != null)
|
||||
{
|
||||
|
@ -297,9 +297,21 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex,
|
||||
string.Format("Error Deleting File [{0}] For Track [{1}] Exception [{2}]", trackPath,
|
||||
track.Id, ex.Serialize()));
|
||||
Logger.LogError(ex, $"Error Deleting File [{trackPath}] For Track `{track}` Exception [{ex}]");
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all image files for Release
|
||||
foreach(var file in ImageHelper.ImageFilesInFolder(release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration)), SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(file);
|
||||
Logger.LogWarning("For Release [{0}], Deleted File [{1}]", release.Id, file);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"Error Deleting File [{file}] Exception [{ex}]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,7 +910,6 @@ namespace Roadie.Api.Services
|
|||
if (mergeTrack.LastPlayed.HasValue && existingTrack.LastPlayed.HasValue &&
|
||||
mergeTrack.LastPlayed > existingTrack.LastPlayed)
|
||||
existingTrack.LastPlayed = mergeTrack.LastPlayed;
|
||||
existingTrack.Thumbnail = existingTrack.Thumbnail ?? mergeTrack.Thumbnail;
|
||||
existingTrack.MusicBrainzId = existingTrack.MusicBrainzId ?? mergeTrack.MusicBrainzId;
|
||||
existingTrack.Tags = existingTrack.Tags.AddToDelimitedList(mergeTrack.Tags.ToListFromDelimited());
|
||||
if (!mergeTrack.Title.Equals(existingTrack.Title,
|
||||
|
@ -962,7 +973,6 @@ namespace Roadie.Api.Services
|
|||
releaseToMergeInto.LastFMId = releaseToMergeInto.LastFMId ?? releaseToMerge.LastFMId;
|
||||
releaseToMergeInto.LastFMSummary = releaseToMergeInto.LastFMSummary ?? releaseToMerge.LastFMSummary;
|
||||
releaseToMergeInto.SpotifyId = releaseToMergeInto.SpotifyId ?? releaseToMerge.SpotifyId;
|
||||
releaseToMergeInto.Thumbnail = releaseToMergeInto.Thumbnail ?? releaseToMerge.Thumbnail;
|
||||
if (releaseToMergeInto.ReleaseType == ReleaseType.Unknown &&
|
||||
releaseToMerge.ReleaseType != ReleaseType.Unknown)
|
||||
releaseToMergeInto.ReleaseType = releaseToMerge.ReleaseType;
|
||||
|
@ -1466,29 +1476,15 @@ namespace Roadie.Api.Services
|
|||
|
||||
#endregion Scan Folder and Add or Update Existing Tracks from Files
|
||||
|
||||
if (release.Thumbnail == null)
|
||||
{
|
||||
var imageFiles = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releasePath), ImageType.Release, SearchOption.TopDirectoryOnly);
|
||||
if (imageFiles != null && imageFiles.Any())
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
var i = imageFiles.First();
|
||||
release.Thumbnail = ImageHelper.ResizeToThumbnail(File.ReadAllBytes(i.FullName), Configuration);
|
||||
|
||||
release.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(release.Artist.CacheRegion);
|
||||
CacheManager.ClearRegion(release.CacheRegion);
|
||||
Logger.LogInformation("Update Thumbnail using Release Cover File [{0}]", i.Name);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
await UpdateReleaseCounts(release.Id, now);
|
||||
await UpdateArtistCountsForRelease(release.Id, now);
|
||||
await UpdateReleaseRank(release.Id);
|
||||
|
||||
CacheManager.ClearRegion(release.Artist.CacheRegion);
|
||||
CacheManager.ClearRegion(release.CacheRegion);
|
||||
|
||||
if (release.Labels != null && release.Labels.Any())
|
||||
{
|
||||
foreach (var label in release.Labels)
|
||||
|
@ -1522,7 +1518,6 @@ namespace Roadie.Api.Services
|
|||
public async Task<OperationResult<bool>> UpdateRelease(ApplicationUser user, Release model, string originalReleaseFolder = null)
|
||||
{
|
||||
var didChangeArtist = false;
|
||||
var didChangeThumbnail = false;
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
|
@ -1595,10 +1590,6 @@ namespace Roadie.Api.Services
|
|||
// Save unaltered image to cover file
|
||||
var coverFileName = Path.Combine(release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration)), "cover.jpg");
|
||||
File.WriteAllBytes(coverFileName, ImageHelper.ConvertToJpegFormat(releaseImage));
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
release.Thumbnail = ImageHelper.ResizeToThumbnail(releaseImage, Configuration);
|
||||
didChangeThumbnail = true;
|
||||
}
|
||||
var releaseFolder = release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration));
|
||||
if (model.NewSecondaryImagesData != null && model.NewSecondaryImagesData.Any())
|
||||
|
@ -1667,11 +1658,6 @@ namespace Roadie.Api.Services
|
|||
// TODO
|
||||
}
|
||||
|
||||
if (model.Images != null && model.Images.Any())
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
release.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
await CheckAndChangeReleaseTitle(release, originalReleaseFolder);
|
||||
|
@ -1692,7 +1678,7 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
}
|
||||
CacheManager.ClearRegion(release.CacheRegion);
|
||||
Logger.LogInformation($"UpdateRelease `{release}` By User `{user}`: Edited Artist [{didChangeArtist}], Uploaded new image [{didChangeThumbnail}]");
|
||||
Logger.LogInformation($"UpdateRelease `{release}` By User `{user}`: Edited Artist [{didChangeArtist}]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1839,17 +1825,12 @@ namespace Roadie.Api.Services
|
|||
if (includes.Contains("images"))
|
||||
{
|
||||
tsw.Restart();
|
||||
var releaseImages = DbContext.Images.Where(x => x.ReleaseId == release.Id).Select(x => MakeFullsizeImage(Configuration, HttpContext, x.RoadieId, x.Caption)).ToArray();
|
||||
if (releaseImages != null && releaseImages.Any())
|
||||
{
|
||||
result.Images = releaseImages;
|
||||
}
|
||||
var artistFolder = release.Artist.ArtistFileFolder(Configuration);
|
||||
var releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary, SearchOption.TopDirectoryOnly);
|
||||
if (releaseImagesInFolder.Any())
|
||||
{
|
||||
result.Images = result.Images.Concat(releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ReleaseSecondary, i)));
|
||||
result.Images = releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(Configuration, HttpContext, id, ImageType.ReleaseSecondary, i));
|
||||
}
|
||||
tsw.Stop();
|
||||
timings.Add("images", tsw.ElapsedMilliseconds);
|
||||
|
@ -2045,17 +2026,12 @@ namespace Roadie.Api.Services
|
|||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
release.Thumbnail = imageBytes;
|
||||
if (release.Thumbnail != null)
|
||||
if (imageBytes != null)
|
||||
{
|
||||
// Save unaltered image to cover file
|
||||
var coverFileName = Path.Combine(release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration)), "cover.jpg");
|
||||
File.WriteAllBytes(coverFileName, ImageHelper.ConvertToJpegFormat(imageBytes));
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
release.Thumbnail = ImageHelper.ResizeToThumbnail(imageBytes, Configuration);
|
||||
}
|
||||
|
||||
release.LastUpdated = now;
|
||||
await DbContext.SaveChangesAsync();
|
||||
CacheManager.ClearRegion(release.CacheRegion);
|
||||
|
|
|
@ -825,7 +825,6 @@ namespace Roadie.Api.Services
|
|||
public async Task<OperationResult<bool>> UpdateTrack(User user, Track model)
|
||||
{
|
||||
var didChangeTrack = false;
|
||||
var didChangeThumbnail = false;
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
|
@ -883,10 +882,6 @@ namespace Roadie.Api.Services
|
|||
// Save unaltered image to cover file
|
||||
var trackThumbnailName = track.PathToTrackThumbnail(Configuration);
|
||||
File.WriteAllBytes(trackThumbnailName, ImageHelper.ConvertToJpegFormat(trackImage));
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
track.Thumbnail = ImageHelper.ResizeToThumbnail(trackImage, Configuration);
|
||||
didChangeThumbnail = true;
|
||||
}
|
||||
|
||||
// See if Title was changed if so then modify DB Filename and rename track
|
||||
|
@ -911,7 +906,7 @@ namespace Roadie.Api.Services
|
|||
AudioMetaDataHelper.WriteTags(audioMetaData, trackFileInfo);
|
||||
}
|
||||
CacheManager.ClearRegion(track.CacheRegion);
|
||||
Logger.LogInformation($"UpdateTrack `{track}` By User `{user}`: Edited Track [{didChangeTrack}], Uploaded new image [{didChangeThumbnail}]");
|
||||
Logger.LogInformation($"UpdateTrack `{track}` By User `{user}`: Edited Track [{didChangeTrack}]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -504,12 +504,6 @@ namespace Roadie.Api.Services
|
|||
|
||||
// Save unaltered user image
|
||||
File.WriteAllBytes(user.PathToImage(Configuration), imageData);
|
||||
// Update thumbnail
|
||||
user.Avatar = ImageHelper.ResizeImage(imageData, Configuration.ThumbnailImageSize.Width, Configuration.ThumbnailImageSize.Height);
|
||||
if (user.Avatar.Length >= ImageHelper.MaximumThumbnailByteSize)
|
||||
{
|
||||
user.Avatar = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -337,5 +337,22 @@ namespace Roadie.Api.Controllers
|
|||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("migrateimages")]
|
||||
[ProducesResponseType(200)]
|
||||
public async Task<IActionResult> MigrateImages()
|
||||
{
|
||||
var result = await AdminService.MigrateImages(await UserManager.GetUserAsync(User));
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
if (result.Messages?.Any() ?? false)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.BadRequest, result.Messages);
|
||||
}
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -33,13 +34,19 @@ namespace Roadie.Api.Controllers
|
|||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> ArtistImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.ArtistImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width,
|
||||
height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
var result = await ImageService.ArtistImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -50,11 +57,18 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.ArtistSecondaryImage(id, imageId, width, height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -64,39 +78,41 @@ namespace Roadie.Api.Controllers
|
|||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> CollectionImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.CollectionImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width,
|
||||
height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
var result = await ImageService.CollectionImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
||||
[HttpPost("delete/{id}")]
|
||||
[Authorize(Policy = "Editor")]
|
||||
[ProducesResponseType(200)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var result = await ImageService.Delete(await UserManager.GetUserAsync(User), id);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> Get(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.ById(id, width, height);
|
||||
if (result == null) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
if (result == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -106,13 +122,19 @@ namespace Roadie.Api.Controllers
|
|||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> LabelImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.LabelImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width,
|
||||
height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
var result = await ImageService.LabelImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -123,11 +145,18 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> GenreImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.GenreImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -137,13 +166,19 @@ namespace Roadie.Api.Controllers
|
|||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> PlaylistImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.PlaylistImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width,
|
||||
height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
var result = await ImageService.PlaylistImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -154,11 +189,18 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> ReleaseImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.ReleaseImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -168,13 +210,19 @@ namespace Roadie.Api.Controllers
|
|||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.ReleaseSecondaryImage(id, imageId,
|
||||
width ?? RoadieSettings.MaximumImageSize.Width, height ?? RoadieSettings.MaximumImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
var result = await ImageService.ReleaseSecondaryImage(id, imageId, width ?? RoadieSettings.MaximumImageSize.Width, height ?? RoadieSettings.MaximumImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -185,8 +233,14 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> SearchForArtistImage(string query, int? resultsCount)
|
||||
{
|
||||
var result = await ImageService.Search(query, resultsCount ?? 10);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
@ -196,8 +250,14 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> SearchForLabelImage(string query, int? resultsCount)
|
||||
{
|
||||
var result = await ImageService.Search(query, resultsCount ?? 10);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
|
@ -229,11 +289,18 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> TrackImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.TrackImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.jpg",
|
||||
$"{model.Caption ?? id.ToString()}.jpg",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
@ -247,11 +314,18 @@ namespace Roadie.Api.Controllers
|
|||
public async Task<IActionResult> UserImage(Guid id, int? width, int? height)
|
||||
{
|
||||
var result = await ImageService.UserImage(id, width ?? RoadieSettings.ThumbnailImageSize.Width, height ?? RoadieSettings.ThumbnailImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult) return NotFound();
|
||||
if (!result.IsSuccess) return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
return File(result.Data.Bytes,
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
var model = result.Data.Adapt<Library.Models.Image>();
|
||||
return File(model.Bytes,
|
||||
result.ContentType,
|
||||
$"{result.Data.Caption ?? id.ToString()}.gif",
|
||||
$"{model.Caption ?? id.ToString()}.gif",
|
||||
result.LastModified,
|
||||
result.ETag);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue