This commit is contained in:
Steven Hildreth 2019-11-03 21:19:04 -06:00
parent cb37aabf40
commit f385c8f6fc
44 changed files with 1084 additions and 635 deletions

View file

@ -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;

View file

@ -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();

View file

@ -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);

View file

@ -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)

View file

@ -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";

View file

@ -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
}
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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" />

View file

@ -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);

View file

@ -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);

View file

@ -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; }

View file

@ -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);

View file

@ -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; }

View file

@ -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
{

View file

@ -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}]";
}
}
}

View file

@ -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; }

View file

@ -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>();

View file

@ -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; }

View file

@ -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));

View file

@ -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();

View file

@ -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; }

View file

@ -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;
}
}

View file

@ -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; }
}
}

View 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();
}
}

View 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}";
}
}
}

View file

@ -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

View file

@ -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)

View file

@ -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; }

View file

@ -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,

View file

@ -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();

View file

@ -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),

View file

@ -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;
}

View file

@ -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),

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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));
}
}
}

View file

@ -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),

View file

@ -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();

View file

@ -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);

View file

@ -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)
{

View file

@ -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;
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}