mirror of
https://github.com/sphildreth/roadie
synced 2025-02-17 21:48:27 +00:00
Beta v20180209.1
This commit is contained in:
parent
577dd3515d
commit
31e676392c
22 changed files with 775 additions and 86 deletions
Roadie.Api.Library.Tests
Roadie.Api.Library
Configuration
Engines
Enums
Factories
FilePlugins
Imaging
Roadie.Library.csprojSearchEngines/MetaData
Utility
Roadie.Api.Services
ArtistService.csIImageService.csImageService.csReleaseService.csRoadie.Api.Services.csprojServiceBase.cs
Roadie.Api
|
@ -395,6 +395,34 @@ namespace Roadie.Library.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Read_File_Test_Is_valid3()
|
||||
{
|
||||
var file = new FileInfo(@"C:\roadie_dev_root\inbound\Dreadful Fate - Vengeance (2018)\01-dreadful_fate-vengeance.mp3");
|
||||
if (file.Exists)
|
||||
{
|
||||
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||
Assert.True(tagLib.IsSuccess);
|
||||
var metaData = tagLib.Data;
|
||||
Assert.NotNull(metaData.Artist);
|
||||
Assert.Null(metaData.TrackArtist);
|
||||
Assert.False(metaData.TrackArtists.Any());
|
||||
Assert.NotNull(metaData.Release);
|
||||
Assert.NotNull(metaData.Title);
|
||||
Assert.True(metaData.Year > 0);
|
||||
Assert.NotNull(metaData.TrackNumber);
|
||||
Assert.True(metaData.TotalSeconds > 0);
|
||||
Assert.True(metaData.ValidWeight > 30);
|
||||
Assert.True(metaData.IsValid);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"skipping { file}");
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void ReadID3TagsFromFileWithTrackAndArtistTheSame()
|
||||
{
|
||||
|
|
250
Roadie.Api.Library.Tests/ImageHelperTests.cs
Normal file
250
Roadie.Api.Library.Tests/ImageHelperTests.cs
Normal file
|
@ -0,0 +1,250 @@
|
|||
using Roadie.Library.FilePlugins;
|
||||
using Roadie.Library.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Roadie.Library.Tests
|
||||
{
|
||||
public class ImageHelperTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("artist.jpeg")]
|
||||
[InlineData("artist.jpg")]
|
||||
[InlineData("artist.png")]
|
||||
[InlineData("Artist.Jpg")]
|
||||
[InlineData("Artist.JPG")]
|
||||
[InlineData("band.jpg")]
|
||||
[InlineData("group.jpg")]
|
||||
[InlineData("ARTIST.JPG")]
|
||||
[InlineData("GrOup.jpg")]
|
||||
[InlineData("aRtist.jpg")]
|
||||
public void Test_Should_Be_Artist_Images(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsArtistImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("logo.jpeg")]
|
||||
[InlineData("logo.jpg")]
|
||||
[InlineData("logo.png")]
|
||||
[InlineData("Logo.Jpg")]
|
||||
[InlineData("artist_logo.jpg")]
|
||||
[InlineData("Artist_logo.jpg")]
|
||||
[InlineData("ARTIST_LOGO.JPG")]
|
||||
[InlineData("artist 1.jpg")]
|
||||
[InlineData("artist_01.jpg")]
|
||||
[InlineData("artist 03.jpg")]
|
||||
public void Test_Should_Be_Artist_Secondary_Images(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsArtistSecondaryImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("cover.jpeg")]
|
||||
[InlineData("cover.jpg")]
|
||||
[InlineData("cover.png")]
|
||||
[InlineData("Cover.Jpg")]
|
||||
[InlineData("Release.JPG")]
|
||||
[InlineData("front.jpg")]
|
||||
[InlineData("FrOnt.jpg")]
|
||||
[InlineData("Art - front.jpg")]
|
||||
[InlineData("Art - Front.jpg")]
|
||||
[InlineData("Art-Front.jpg")]
|
||||
[InlineData("Art- Front.jpg")]
|
||||
[InlineData("Art -Front.jpg")]
|
||||
[InlineData("F1.jpg")]
|
||||
[InlineData("F 1.jpg")]
|
||||
[InlineData("F-1.jpg")]
|
||||
public void Test_Should_Be_Release_Images(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsReleaseImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("cover.png")]
|
||||
[InlineData("Cover.jpg")]
|
||||
[InlineData("batman.txt")]
|
||||
[InlineData("Song.mp3")]
|
||||
[InlineData("batman.jpg")]
|
||||
[InlineData("logo.jpg")]
|
||||
[InlineData("Release.JPG")]
|
||||
[InlineData("front.jpg")]
|
||||
[InlineData("F1.jpg")]
|
||||
[InlineData("logo.jpeg")]
|
||||
[InlineData("logo.png")]
|
||||
[InlineData("Logo.Jpg")]
|
||||
[InlineData("artist_logo.jpg")]
|
||||
[InlineData("Artist_logo.jpg")]
|
||||
[InlineData("ARTIST_LOGO.JPG")]
|
||||
[InlineData("Artist - Front.jpg")]
|
||||
[InlineData("Artist Front.jpg")]
|
||||
[InlineData("artist 1.jpg")]
|
||||
[InlineData("artist_01.jpg")]
|
||||
[InlineData("artist 03.jpg")]
|
||||
public void Test_Should_Not_Be_Artist_Images(string input)
|
||||
{
|
||||
var t = ImageHelper.IsArtistImage(new FileInfo(input));
|
||||
Assert.False(t);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("artist.jpeg")]
|
||||
[InlineData("artist.jpg")]
|
||||
[InlineData("artist.png")]
|
||||
[InlineData("Artist.Jpg")]
|
||||
[InlineData("Artist.JPG")]
|
||||
[InlineData("band.jpg")]
|
||||
[InlineData("group.jpg")]
|
||||
[InlineData("ARTIST.JPG")]
|
||||
[InlineData("GrOup.jpg")]
|
||||
[InlineData("aRtist.jpg")]
|
||||
[InlineData("batman.txt")]
|
||||
[InlineData("Song.mp3")]
|
||||
[InlineData("batman.jpg")]
|
||||
[InlineData("logo.jpg")]
|
||||
[InlineData("cover 1.jpg")]
|
||||
[InlineData("cover_01.jpg")]
|
||||
[InlineData("cover 03.jpg")]
|
||||
public void Test_Should_Not_Be_Release_Images(string input)
|
||||
{
|
||||
Assert.False(ImageHelper.IsReleaseImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData("label.jpeg")]
|
||||
[InlineData("label.jpg")]
|
||||
[InlineData("label.png")]
|
||||
[InlineData("Label.Jpg")]
|
||||
[InlineData("label.JPG")]
|
||||
[InlineData("record_label.jpg")]
|
||||
[InlineData("RecordLabel.jpg")]
|
||||
[InlineData("RECORDLABEL.JPG")]
|
||||
public void Test_Should_Be_Label_Images(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsLabelImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("artist.jpeg")]
|
||||
[InlineData("artist.jpg")]
|
||||
[InlineData("artist.png")]
|
||||
[InlineData("Artist.Jpg")]
|
||||
[InlineData("Artist.JPG")]
|
||||
[InlineData("band.jpg")]
|
||||
[InlineData("group.jpg")]
|
||||
[InlineData("ARTIST.JPG")]
|
||||
[InlineData("GrOup.jpg")]
|
||||
[InlineData("aRtist.jpg")]
|
||||
[InlineData("cover.jpeg")]
|
||||
[InlineData("cover.jpg")]
|
||||
[InlineData("cover.png")]
|
||||
[InlineData("Cover.Jpg")]
|
||||
[InlineData("Release.JPG")]
|
||||
[InlineData("front.jpg")]
|
||||
[InlineData("FrOnt.jpg")]
|
||||
public void Test_Should_NotBe_Label_Images(string input)
|
||||
{
|
||||
Assert.False(ImageHelper.IsLabelImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
[InlineData("Booklet-1.jpg")]
|
||||
[InlineData("Booklet-10.jpg")]
|
||||
[InlineData("Booklet_1.jpg")]
|
||||
[InlineData("Booklet.jpg")]
|
||||
[InlineData("Book.jpg")]
|
||||
[InlineData("Book_3.jpg")]
|
||||
[InlineData("Book_03.jpg")]
|
||||
[InlineData("Book-1.jpg")]
|
||||
[InlineData("Book-01.jpg")]
|
||||
[InlineData("Back.jpg")]
|
||||
[InlineData("Inside.jpg")]
|
||||
[InlineData("Cd.jpg")]
|
||||
[InlineData("CD.JPG")]
|
||||
[InlineData("Cd1.jpg")]
|
||||
[InlineData("CD3.jpg")]
|
||||
[InlineData("cover_01.jpg")]
|
||||
[InlineData("cover 03.jpg")]
|
||||
[InlineData("cover 1.jpg")]
|
||||
[InlineData("Encartes (11).jpg")]
|
||||
[InlineData("Encartes (1).png")]
|
||||
[InlineData("Encartes.jpg")]
|
||||
[InlineData("Art - Back.jpg")]
|
||||
[InlineData("disc.jpg")]
|
||||
[InlineData("inlay.jpg")]
|
||||
[InlineData("inside.jpg")]
|
||||
[InlineData("release 1.jpg")]
|
||||
[InlineData("release-1.jpg")]
|
||||
[InlineData("release_1.jpg")]
|
||||
[InlineData("release 3.jpg")]
|
||||
[InlineData("release 10.jpg")]
|
||||
public void Test_Should_Be_Release_Secondary_Images(string input)
|
||||
{
|
||||
Assert.True(ImageHelper.IsReleaseSecondaryImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("artist.jpeg")]
|
||||
[InlineData("artist.jpg")]
|
||||
[InlineData("artist.png")]
|
||||
[InlineData("Artist.Jpg")]
|
||||
[InlineData("Artist.JPG")]
|
||||
[InlineData("band.jpg")]
|
||||
[InlineData("group.jpg")]
|
||||
[InlineData("ARTIST.JPG")]
|
||||
[InlineData("GrOup.jpg")]
|
||||
[InlineData("aRtist.jpg")]
|
||||
[InlineData("cover.jpeg")]
|
||||
[InlineData("cover.jpg")]
|
||||
[InlineData("cover.png")]
|
||||
[InlineData("Cover.Jpg")]
|
||||
[InlineData("Release.JPG")]
|
||||
[InlineData("front.jpg")]
|
||||
[InlineData("FrOnt.jpg")]
|
||||
[InlineData("label.jpeg")]
|
||||
[InlineData("label.jpg")]
|
||||
[InlineData("label.png")]
|
||||
[InlineData("Label.Jpg")]
|
||||
[InlineData("label.JPG")]
|
||||
[InlineData("record_label.jpg")]
|
||||
[InlineData("RecordLabel.jpg")]
|
||||
[InlineData("RECORDLABEL.JPG")]
|
||||
public void Test_Should_Not_Be_Release_Secondary_Images(string input)
|
||||
{
|
||||
Assert.False(ImageHelper.IsReleaseSecondaryImage(new FileInfo(input)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_Release_Image_In_Folder()
|
||||
{
|
||||
var folder = new DirectoryInfo(@"C:\roadie_dev_root\image_tests");
|
||||
if(!folder.Exists)
|
||||
{
|
||||
Assert.True(true);
|
||||
return;
|
||||
}
|
||||
var cover = ImageHelper.FindImageTypeInDirectory(folder, Enums.ImageType.Release);
|
||||
Assert.NotNull(cover);
|
||||
Assert.Single(cover);
|
||||
Assert.Equal("cover.jpg", cover.First().Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_Artist_Image_In_Folder()
|
||||
{
|
||||
var folder = new DirectoryInfo(@"C:\roadie_dev_root\image_tests)");
|
||||
if (!folder.Exists)
|
||||
{
|
||||
Assert.True(true);
|
||||
return;
|
||||
}
|
||||
var artist = ImageHelper.FindImageTypeInDirectory(folder, Enums.ImageType.Artist);
|
||||
Assert.NotNull(artist);
|
||||
Assert.Single(artist);
|
||||
Assert.Equal("artist.jpg", artist.First().Name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ namespace Roadie.Library.Configuration
|
|||
string InboundFolder { get; set; }
|
||||
Integrations Integrations { get; set; }
|
||||
ImageSize LargeImageSize { get; set; }
|
||||
ImageSize MaximumImageSize { get; set; }
|
||||
string LibraryFolder { get; set; }
|
||||
string ListenAddress { get; set; }
|
||||
ImageSize MediumImageSize { get; set; }
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Roadie.Library.Configuration
|
|||
public string InboundFolder { get; set; }
|
||||
public Integrations Integrations { get; set; }
|
||||
public ImageSize LargeImageSize { get; set; }
|
||||
public ImageSize MaximumImageSize { get; set; }
|
||||
public string LibraryFolder { get; set; }
|
||||
public string ListenAddress { get; set; }
|
||||
public ImageSize MediumImageSize { get; set; }
|
||||
|
@ -59,7 +60,7 @@ namespace Roadie.Library.Configuration
|
|||
this.SmallImageSize = new ImageSize { Width = 160, Height = 160 };
|
||||
this.MediumImageSize = new ImageSize { Width = 320, Height = 320 };
|
||||
this.LargeImageSize = new ImageSize { Width = 500, Height = 500 };
|
||||
|
||||
this.MaximumImageSize = new ImageSize { Width = 1024, Height = 1024 };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -311,15 +311,15 @@ namespace Roadie.Library.Engines
|
|||
Name = metaData.Artist.ToTitleCase(false)
|
||||
};
|
||||
var resultsExceptions = new List<Exception>();
|
||||
var ArtistGenres = new List<string>();
|
||||
var ArtistImageUrls = new List<string>();
|
||||
var ArtistName = metaData.Artist;
|
||||
var artistGenres = new List<string>();
|
||||
var artistImageUrls = new List<string>();
|
||||
var artistName = metaData.Artist;
|
||||
|
||||
try
|
||||
{
|
||||
if (this.ITunesArtistSearchEngine.IsEnabled)
|
||||
{
|
||||
var iTunesResult = await this.ITunesArtistSearchEngine.PerformArtistSearch(ArtistName, 1);
|
||||
var iTunesResult = await this.ITunesArtistSearchEngine.PerformArtistSearch(artistName, 1);
|
||||
if (iTunesResult.IsSuccess)
|
||||
{
|
||||
var i = iTunesResult.Data.First();
|
||||
|
@ -341,11 +341,11 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
if (i.ImageUrls != null)
|
||||
{
|
||||
ArtistImageUrls.AddRange(i.ImageUrls);
|
||||
artistImageUrls.AddRange(i.ImageUrls);
|
||||
}
|
||||
if (i.ArtistGenres != null)
|
||||
{
|
||||
ArtistGenres.AddRange(i.ArtistGenres);
|
||||
artistGenres.AddRange(i.ArtistGenres);
|
||||
}
|
||||
result.CopyTo(new Artist
|
||||
{
|
||||
|
@ -396,11 +396,11 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
if (mb.ImageUrls != null)
|
||||
{
|
||||
ArtistImageUrls.AddRange(mb.ImageUrls);
|
||||
artistImageUrls.AddRange(mb.ImageUrls);
|
||||
}
|
||||
if (mb.ArtistGenres != null)
|
||||
{
|
||||
ArtistGenres.AddRange(mb.ArtistGenres);
|
||||
artistGenres.AddRange(mb.ArtistGenres);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(mb.ArtistName) && !mb.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
@ -455,11 +455,11 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
if (l.ImageUrls != null)
|
||||
{
|
||||
ArtistImageUrls.AddRange(l.ImageUrls);
|
||||
artistImageUrls.AddRange(l.ImageUrls);
|
||||
}
|
||||
if (l.ArtistGenres != null)
|
||||
{
|
||||
ArtistGenres.AddRange(l.ArtistGenres);
|
||||
artistGenres.AddRange(l.ArtistGenres);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(l.ArtistName) && !l.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
@ -506,11 +506,11 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
if (s.ImageUrls != null)
|
||||
{
|
||||
ArtistImageUrls.AddRange(s.ImageUrls);
|
||||
artistImageUrls.AddRange(s.ImageUrls);
|
||||
}
|
||||
if (s.ArtistGenres != null)
|
||||
{
|
||||
ArtistGenres.AddRange(s.ArtistGenres);
|
||||
artistGenres.AddRange(s.ArtistGenres);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(s.ArtistName) && !s.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
@ -553,7 +553,7 @@ namespace Roadie.Library.Engines
|
|||
}
|
||||
if (d.ImageUrls != null)
|
||||
{
|
||||
ArtistImageUrls.AddRange(d.ImageUrls);
|
||||
artistImageUrls.AddRange(d.ImageUrls);
|
||||
}
|
||||
if (d.AlternateNames != null)
|
||||
{
|
||||
|
@ -629,9 +629,9 @@ namespace Roadie.Library.Engines
|
|||
{
|
||||
result.Tags = string.Join("|", result.Tags.ToListFromDelimited().Distinct().OrderBy(x => x));
|
||||
}
|
||||
if (ArtistGenres.Any())
|
||||
if (artistGenres.Any())
|
||||
{
|
||||
var genreInfos = (from ag in ArtistGenres
|
||||
var genreInfos = (from ag in artistGenres
|
||||
join g in this.DbContext.Genres on ag equals g.Name into gg
|
||||
from g in gg.DefaultIfEmpty()
|
||||
select new
|
||||
|
@ -651,10 +651,10 @@ namespace Roadie.Library.Engines
|
|||
});
|
||||
}
|
||||
}
|
||||
if (ArtistImageUrls.Any())
|
||||
if (artistImageUrls.Any())
|
||||
{
|
||||
var imageBag = new ConcurrentBag<Image>();
|
||||
var i = ArtistImageUrls.Select(async url =>
|
||||
var i = artistImageUrls.Select(async url =>
|
||||
{
|
||||
imageBag.Add(await WebHelper.GetImageFromUrlAsync(url));
|
||||
});
|
||||
|
|
|
@ -488,6 +488,7 @@ namespace Roadie.Library.Engines
|
|||
ReleaseDate = result.ReleaseDate ?? mb.ReleaseDate,
|
||||
AmgId = mb.AmgId,
|
||||
Profile = mb.Profile,
|
||||
TrackCount = mb.ReleaseMedia != null ? (short)mb.ReleaseMedia.Sum(x => x.TrackCount) : (short)0,
|
||||
MusicBrainzId = mb.MusicBrainzId,
|
||||
ITunesId = mb.iTunesId,
|
||||
Title = result.Title ?? mb.ReleaseTitle,
|
||||
|
@ -852,23 +853,14 @@ namespace Roadie.Library.Engines
|
|||
if (!string.IsNullOrEmpty(artistFolder))
|
||||
{
|
||||
// If any file exist for cover that over-rides whatever if found in metadata providers.
|
||||
var releaseFolder = result.ReleaseFileFolder(artistFolder);
|
||||
if (Directory.Exists(releaseFolder))
|
||||
var releaseFolder = new DirectoryInfo(result.ReleaseFileFolder(artistFolder));
|
||||
if (releaseFolder.Exists)
|
||||
{
|
||||
// See if there is a cover file ("cover.jpg") if so set thumbnail image to that
|
||||
var coverFileName = Path.Combine(releaseFolder, ReleaseFactory.CoverFilename);
|
||||
if(!File.Exists(coverFileName))
|
||||
{
|
||||
// See if any file exists in the release folder with "cover" in the name
|
||||
var coverFiles = Directory.GetFiles(releaseFolder, "*cover*.jpg", new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive });
|
||||
if(coverFiles != null && coverFiles.Any())
|
||||
{
|
||||
coverFileName = coverFiles.First();
|
||||
}
|
||||
}
|
||||
if (File.Exists(coverFileName))
|
||||
var cover = ImageHelper.FindImageTypeInDirectory(releaseFolder, ImageType.Release);
|
||||
if(cover.Any())
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
var coverFileName = cover.First().FullName;
|
||||
result.Thumbnail = File.ReadAllBytes(coverFileName);
|
||||
this.Logger.LogDebug("Using Release Cover File [{0}]", coverFileName);
|
||||
}
|
||||
|
|
16
Roadie.Api.Library/Enums/ImageType.cs
Normal file
16
Roadie.Api.Library/Enums/ImageType.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Roadie.Library.Enums
|
||||
{
|
||||
public enum ImageType : short
|
||||
{
|
||||
Unknown = 0,
|
||||
Artist,
|
||||
ArtistSecondary,
|
||||
Release,
|
||||
ReleaseSecondary,
|
||||
Label
|
||||
}
|
||||
}
|
|
@ -27,8 +27,6 @@ namespace Roadie.Library.Factories
|
|||
|
||||
public sealed class ReleaseFactory : FactoryBase, IReleaseFactory
|
||||
{
|
||||
public const string CoverFilename = "cover.jpg";
|
||||
|
||||
private List<int> _addedTrackIds = new List<int>();
|
||||
|
||||
public IEnumerable<int> AddedTrackIds
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
|
@ -23,13 +24,7 @@ namespace Roadie.Library.FilePlugins
|
|||
|
||||
public IAudioMetaDataHelper AudioMetaDataHelper { get; }
|
||||
|
||||
public override string[] HandlesTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new string[1] { "audio/mpeg" };
|
||||
}
|
||||
}
|
||||
public override string[] HandlesTypes => new string[1] { "audio/mpeg" };
|
||||
|
||||
public Audio(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
|
@ -108,39 +103,125 @@ namespace Roadie.Library.FilePlugins
|
|||
return result;
|
||||
}
|
||||
|
||||
PluginBase.CheckMakeFolder(artistFolder);
|
||||
PluginBase.CheckMakeFolder(releaseFolder);
|
||||
|
||||
// See if folder has "cover" image if so then move to release folder for metadata
|
||||
var imageFiles = ImageHelper.ImageFilesInFolder(fileInfo.DirectoryName);
|
||||
if (imageFiles != null && imageFiles.Any())
|
||||
if(PluginBase.CheckMakeFolder(artistFolder))
|
||||
{
|
||||
foreach (var imageFile in imageFiles)
|
||||
this.Logger.LogTrace("Created ArtistFolder [{0}]", artistFolder);
|
||||
}
|
||||
if(PluginBase.CheckMakeFolder(releaseFolder))
|
||||
{
|
||||
this.Logger.LogTrace("Created ReleaseFolder [{0}]", releaseFolder);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// See if file folder parent folder (likely file is in release folder) has primary artist image if so then move to artist folder
|
||||
var artistImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.Artist);
|
||||
if (!artistImages.Any())
|
||||
{
|
||||
var i = new FileInfo(imageFile);
|
||||
var iName = i.Name.ToLower().Trim();
|
||||
this.Logger.LogDebug("Found Image File [{0}] [{1}]", imageFile, iName);
|
||||
var isCoverArtType = iName.Contains("cover") || iName.Contains("folder") || iName.Contains("front") || iName.Contains("release") || iName.Contains("album");
|
||||
if (isCoverArtType)
|
||||
artistImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory.Parent, Enums.ImageType.Artist);
|
||||
}
|
||||
if (artistImages.Any())
|
||||
{
|
||||
var artistImage = artistImages.First();
|
||||
var aristImageFilename = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
|
||||
if (aristImageFilename != artistImage.FullName)
|
||||
{
|
||||
var coverFileName = Path.Combine(releaseFolder, Factories.ReleaseFactory.CoverFilename);
|
||||
if (coverFileName != i.FullName)
|
||||
// Read image and convert to jpeg
|
||||
var imageBytes = File.ReadAllBytes(artistImage.FullName);
|
||||
imageBytes = ImageHelper.ConvertToJpegFormat(imageBytes);
|
||||
|
||||
// Move artist image to artist folder
|
||||
if (!doJustInfo)
|
||||
{
|
||||
File.WriteAllBytes(aristImageFilename, imageBytes);
|
||||
artistImage.Delete();
|
||||
}
|
||||
this.Logger.LogDebug("Found Artist Image File [{0}], Moved to artist folder.", artistImage.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// See if any secondary artist images if so then move to artist folder
|
||||
artistImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.ArtistSecondary);
|
||||
if (!artistImages.Any())
|
||||
{
|
||||
artistImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory.Parent, Enums.ImageType.Artist);
|
||||
}
|
||||
if (artistImages.Any())
|
||||
{
|
||||
var looper = 0;
|
||||
foreach (var artistImage in artistImages)
|
||||
{
|
||||
looper++;
|
||||
var aristImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
|
||||
if (aristImageFilename != artistImage.FullName)
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
var imageBytes = File.ReadAllBytes(i.FullName);
|
||||
var imageBytes = File.ReadAllBytes(artistImage.FullName);
|
||||
imageBytes = ImageHelper.ConvertToJpegFormat(imageBytes);
|
||||
|
||||
// Move artist image to artist folder
|
||||
if (!doJustInfo)
|
||||
{
|
||||
File.WriteAllBytes(aristImageFilename, imageBytes);
|
||||
artistImage.Delete();
|
||||
}
|
||||
this.Logger.LogDebug("Found Artist Secondary Image File [{0}], Moved to artist folder [{1}].", artistImage.Name, aristImageFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if file folder has release image if so then move to release folder
|
||||
var releaseImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.Release);
|
||||
if (releaseImages.Any())
|
||||
{
|
||||
var releaseImage = releaseImages.First();
|
||||
var coverFileName = Path.Combine(releaseFolder, ImageHelper.ReleaseCoverFilename);
|
||||
if (coverFileName != releaseImage.FullName)
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
var imageBytes = File.ReadAllBytes(releaseImage.FullName);
|
||||
imageBytes = ImageHelper.ConvertToJpegFormat(imageBytes);
|
||||
|
||||
// Move cover to release folder
|
||||
if (!doJustInfo)
|
||||
{
|
||||
File.WriteAllBytes(coverFileName, imageBytes);
|
||||
releaseImage.Delete();
|
||||
}
|
||||
this.Logger.LogDebug("Found Release Image File [{0}], Moved to release folder", releaseImage.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// See if folder has secondary release image if so then move to release folder
|
||||
releaseImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.ReleaseSecondary);
|
||||
if (releaseImages.Any())
|
||||
{
|
||||
var looper = 0;
|
||||
foreach (var releaseImage in releaseImages)
|
||||
{
|
||||
looper++;
|
||||
var releaseImageFilename = Path.Combine(releaseFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
|
||||
if (releaseImageFilename != releaseImage.FullName)
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
var imageBytes = File.ReadAllBytes(releaseImage.FullName);
|
||||
imageBytes = ImageHelper.ConvertToJpegFormat(imageBytes);
|
||||
|
||||
// Move cover to release folder
|
||||
if (!doJustInfo)
|
||||
{
|
||||
File.WriteAllBytes(coverFileName, imageBytes);
|
||||
i.Delete();
|
||||
File.WriteAllBytes(releaseImageFilename, imageBytes);
|
||||
releaseImage.Delete();
|
||||
}
|
||||
this.Logger.LogDebug("Found Image File [{0}], Moved to release folder", i.Name);
|
||||
break;
|
||||
this.Logger.LogDebug("Found Release Image File [{0}], Moved to release folder [{1}]", releaseImage.Name, releaseImageFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, "Error with Managing Images For [{0}]", fileInfo.FullName);
|
||||
}
|
||||
|
||||
var doesFileExistsForTrack = File.Exists(destinationName);
|
||||
|
@ -210,7 +291,7 @@ namespace Roadie.Library.FilePlugins
|
|||
}
|
||||
|
||||
sw.Stop();
|
||||
this.Logger.LogTrace("<< Audio: Process Complete. ElapsedTime [{0}]", sw.ElapsedMilliseconds);
|
||||
this.Logger.LogTrace("<< Audio: Process Complete. Result `{0}`, ElapsedTime [{1}]", JsonConvert.SerializeObject(result), sw.ElapsedMilliseconds);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Roadie.Library.SearchEngines.Imaging;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.SearchEngines.Imaging;
|
||||
using Roadie.Library.Utility;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats;
|
||||
|
@ -9,11 +10,17 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Roadie.Library.Imaging
|
||||
{
|
||||
public static class ImageHelper
|
||||
{
|
||||
public static string ArtistImageFilename = "artist.jpg";
|
||||
public static string ArtistSecondaryImageFilename = "artist {0}.jpg"; // Replace with counter of image
|
||||
public static string ReleaseCoverFilename = "cover.jpg";
|
||||
public static string ReleaseSecondaryImageFilename = "release {0}.jpg"; // Replace with counter of image
|
||||
public static string LabelImageFilename = "label.jpg";
|
||||
|
||||
public static byte[] ConvertToJpegFormat(byte[] imageBytes)
|
||||
{
|
||||
|
@ -52,7 +59,7 @@ namespace Roadie.Library.Imaging
|
|||
|
||||
public static string[] ImageFilesInFolder(string folder)
|
||||
{
|
||||
return ImageHelper.GetFiles(folder, ImageHelper.ImageExtensions());
|
||||
return ImageHelper.GetFiles(folder, ImageHelper.ImageExtensions(), SearchOption.AllDirectories);
|
||||
}
|
||||
|
||||
public static string[] ImageMimeTypes()
|
||||
|
@ -120,5 +127,106 @@ namespace Roadie.Library.Imaging
|
|||
return null;
|
||||
}
|
||||
|
||||
public static bool IsArtistImage(FileInfo fileinfo)
|
||||
{
|
||||
if (fileinfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Regex.IsMatch(fileinfo.Name, @"(band|artist|group)\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsArtistSecondaryImage(FileInfo fileinfo)
|
||||
{
|
||||
if (fileinfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Regex.IsMatch(fileinfo.Name, @"(artist_logo|logo|(artist[\s_-]+[0-9]+))\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsReleaseImage(FileInfo fileinfo, string releaseName = null)
|
||||
{
|
||||
if (fileinfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Regex.IsMatch(fileinfo.Name, @"((f[-_\s]*[0-9]*)|cover|release|front)\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsReleaseSecondaryImage(FileInfo fileinfo)
|
||||
{
|
||||
if (fileinfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Regex.IsMatch(fileinfo.Name, @"((book[let]*[-_]*[0-9]*)|(encartes[-_\s]*[(]*[0-9]*[)]*)|(cover[\s_-]+[0-9]+)|back|disc|inside|inlet|inlay|cd[0-9]*|inside|(release[\s_-]+[0-9]+))\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsLabelImage(FileInfo fileinfo)
|
||||
{
|
||||
if (fileinfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Regex.IsMatch(fileinfo.Name, @"(label|recordlabel|record_label)\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
public static IEnumerable<FileInfo> FindImageTypeInDirectory(DirectoryInfo directory, ImageType type)
|
||||
{
|
||||
var result = new List<FileInfo>();
|
||||
if (directory == null || !directory.Exists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var imageFilesInFolder = ImageFilesInFolder(directory.FullName);
|
||||
if (imageFilesInFolder == null || !imageFilesInFolder.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
foreach(var imageFile in imageFilesInFolder)
|
||||
{
|
||||
var image = new FileInfo(imageFile);
|
||||
switch (type)
|
||||
{
|
||||
case ImageType.Artist:
|
||||
if(IsArtistImage(image))
|
||||
{
|
||||
result.Add(image);
|
||||
}
|
||||
break;
|
||||
|
||||
case ImageType.ArtistSecondary:
|
||||
if (IsArtistSecondaryImage(image))
|
||||
{
|
||||
result.Add(image);
|
||||
}
|
||||
break;
|
||||
|
||||
case ImageType.Release:
|
||||
if (IsReleaseImage(image))
|
||||
{
|
||||
result.Add(image);
|
||||
}
|
||||
break;
|
||||
|
||||
case ImageType.ReleaseSecondary:
|
||||
if (IsReleaseSecondaryImage(image))
|
||||
{
|
||||
result.Add(image);
|
||||
}
|
||||
break;
|
||||
|
||||
case ImageType.Label:
|
||||
if (IsLabelImage(image))
|
||||
{
|
||||
result.Add(image);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.OrderBy(x => x.Name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CsvHelper" Version="12.1.2" />
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="2.3.9" />
|
||||
<PackageReference Include="FluentFTP" Version="19.2.4" />
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="2.4.0" />
|
||||
<PackageReference Include="FluentFTP" Version="21.0.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.8.14" />
|
||||
<PackageReference Include="IdSharp.Common" Version="1.0.1" />
|
||||
<PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" />
|
||||
<PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" />
|
||||
<PackageReference Include="Mapster" Version="3.3.0" />
|
||||
<PackageReference Include="Mapster" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
|
||||
|
|
|
@ -288,13 +288,17 @@ namespace Roadie.Library.MetaData.Audio
|
|||
}
|
||||
if (!this._trackArtist.Contains(AudioMetaData.ArtistSplitCharacter.ToString()))
|
||||
{
|
||||
if(string.IsNullOrEmpty(this.TrackArtist))
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
return new string[1] { this.TrackArtist };
|
||||
}
|
||||
if (!string.IsNullOrEmpty(this._artist) || !string.IsNullOrEmpty(this._trackArtist))
|
||||
{
|
||||
if (!this._artist.Equals(this._trackArtist, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return this._trackArtist.Split(AudioMetaData.ArtistSplitCharacter).Select(x => x.ToTitleCase()).ToArray();
|
||||
return this._trackArtist.Split(AudioMetaData.ArtistSplitCharacter).Where(x => !string.IsNullOrEmpty(x)).Select(x => x.ToTitleCase()).ToArray();
|
||||
}
|
||||
}
|
||||
return new string[0];
|
||||
|
@ -314,6 +318,9 @@ namespace Roadie.Library.MetaData.Audio
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TYER | TDRC | TORY | TDOR
|
||||
/// </summary>
|
||||
public int? Year
|
||||
{
|
||||
get
|
||||
|
|
|
@ -128,7 +128,8 @@ namespace Roadie.Library.MetaData.ID3Tags
|
|||
result.Title = id3v2.Title.ToTitleCase(false);
|
||||
result.TrackNumber = ID3TagsHelper.ParseTrackNumber(id3v2.TrackNumber);
|
||||
result.TotalTrackNumbers = ID3TagsHelper.ParseTotalTrackNumber(id3v2.TrackNumber);
|
||||
result.Year = ID3TagsHelper.ParseYear(id3v2.Year);
|
||||
var year = id3v2.Year ?? id3v2.RecordingTimestamp ?? id3v2.ReleaseTimestamp ?? id3v2.OriginalReleaseTimestamp;
|
||||
result.Year = ID3TagsHelper.ParseYear(year);
|
||||
isSuccess = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace Roadie.Library.Utility
|
|||
|
||||
var artistFolder = artistSortName.ToTitleCase(false);
|
||||
destinationFolder = destinationFolder ?? configuration.LibraryFolder;
|
||||
return Path.Combine(destinationFolder, artistFolder.ToFolderNameFriendly());
|
||||
var directoryInfo = new DirectoryInfo(Path.Combine(destinationFolder, artistFolder.ToFolderNameFriendly()));
|
||||
return directoryInfo.FullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -77,7 +78,8 @@ namespace Roadie.Library.Utility
|
|||
{
|
||||
return null;
|
||||
}
|
||||
return Path.Combine(destinationFolder, track.FilePath, track.FileName);
|
||||
var directoryInfo = new DirectoryInfo(Path.Combine(destinationFolder, track.FilePath, track.FileName));
|
||||
return directoryInfo.FullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -92,7 +94,8 @@ namespace Roadie.Library.Utility
|
|||
SimpleContract.Requires<ArgumentException>(!string.IsNullOrEmpty(releaseTitle), "Invalid Release Title");
|
||||
SimpleContract.Requires<ArgumentException>(releaseDate != DateTime.MinValue, "Invalid Release Date");
|
||||
|
||||
return Path.Combine(artistFolder, string.Format("{1}{0}", releaseTitle.ToTitleCase(false).ToFolderNameFriendly(), string.Format("[{0}] ", releaseDate.ToString("yyyy"))));
|
||||
var directoryInfo = new DirectoryInfo(Path.Combine(artistFolder, string.Format("{1}{0}", releaseTitle.ToTitleCase(false).ToFolderNameFriendly(), string.Format("[{0}] ", releaseDate.ToString("yyyy")))));
|
||||
return directoryInfo.FullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -195,8 +198,9 @@ namespace Roadie.Library.Utility
|
|||
var trackFileName = FolderPathHelper.TrackFileName(configuration, trackTitle, trackNumber, diskNumber, totalTrackNumber, fileExtension);
|
||||
|
||||
var result = Path.Combine(artistFolder, releaseFolder, trackFileName);
|
||||
Trace.WriteLine(string.Format("TrackPath [{0}] For ArtistName [{1}], ReleaseTitle [{2}], ReleaseDate [{3}], ReleaseYear [{4}], TrackNumber [{5}]", result, artistSortName, releaseTitle, releaseDate.ToString("s"), releaseDate.ToString("yyyy"), trackNumber));
|
||||
return result;
|
||||
var resultInfo = new DirectoryInfo(result);
|
||||
Trace.WriteLine(string.Format("TrackPath [{0}] For ArtistName [{1}], ReleaseTitle [{2}], ReleaseDate [{3}], ReleaseYear [{4}], TrackNumber [{5}]", resultInfo.FullName, artistSortName, releaseTitle, releaseDate.ToString("s"), releaseDate.ToString("yyyy"), trackNumber));
|
||||
return resultInfo.FullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -340,7 +340,7 @@ namespace Roadie.Api.Services
|
|||
var imageFile = imageFiles.First();
|
||||
var i = new FileInfo(imageFile);
|
||||
var iName = i.Name.ToLower().Trim();
|
||||
var isArtistImage = iName.Contains("artist") || iName.Contains(artist.Name.ToLower());
|
||||
var isArtistImage = iName.Contains("artist");
|
||||
if (isArtistImage)
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
|
@ -434,7 +434,7 @@ namespace Roadie.Api.Services
|
|||
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artistImage);
|
||||
|
||||
// Save unaltered image to cover file
|
||||
var artistImageName = Path.Combine(artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder), "artist.jpg");
|
||||
var artistImageName = Path.Combine(artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder), ImageHelper.ArtistImageFilename);
|
||||
File.WriteAllBytes(artistImageName, artist.Thumbnail);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
|
@ -730,6 +730,14 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
tsw.Restart();
|
||||
result.Images = this.DbContext.Images.Where(x => x.ArtistId == artist.Id).Select(x => MakeFullsizeImage(x.RoadieId, x.Caption)).ToArray();
|
||||
|
||||
var artistFolder = artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
var artistImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), ImageType.ArtistSecondary);
|
||||
if (artistImagesInFolder.Any())
|
||||
{
|
||||
result.Images = result.Images.Concat(artistImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(id, ImageType.ArtistSecondary, i)));
|
||||
}
|
||||
|
||||
tsw.Stop();
|
||||
timings.Add("images", tsw.ElapsedMilliseconds);
|
||||
}
|
||||
|
@ -892,8 +900,8 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
|
||||
// Save unaltered image to artist file
|
||||
var coverFileName = Path.Combine(artistFolder, "artist.jpg");
|
||||
File.WriteAllBytes(coverFileName, artist.Thumbnail);
|
||||
var artistImage = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
|
||||
File.WriteAllBytes(artistImage, artist.Thumbnail);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace Roadie.Api.Services
|
|||
public interface IImageService
|
||||
{
|
||||
Task<FileOperationResult<Library.Models.Image>> ArtistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Library.Models.Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
|
@ -25,6 +26,7 @@ namespace Roadie.Api.Services
|
|||
Task<FileOperationResult<Library.Models.Image>> PlaylistImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<FileOperationResult<Library.Models.Image>> ReleaseImage(Guid id, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
Task<FileOperationResult<Library.Models.Image>> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null);
|
||||
|
||||
Task<OperationResult<IEnumerable<ImageSearchResult>>> Search(string query, int resultsCount = 10);
|
||||
|
||||
|
|
|
@ -59,6 +59,20 @@ namespace Roadie.Api.Services
|
|||
etag: etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: $"ArtistSecondaryThumbnail-{imageId}",
|
||||
regionUrn: data.Release.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ArtistSecondaryImageAction(id, imageId, etag);
|
||||
},
|
||||
etag: etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: "ImageById",
|
||||
|
@ -187,6 +201,20 @@ namespace Roadie.Api.Services
|
|||
etag: etag);
|
||||
}
|
||||
|
||||
public async Task<FileOperationResult<Image>> ReleaseSecondaryImage(Guid id,int imageId, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
return await this.GetImageFileOperation(type: $"ReleaseSecondaryThumbnail-{imageId}",
|
||||
regionUrn: data.Release.CacheRegionUrn(id),
|
||||
id: id,
|
||||
width: width,
|
||||
height: height,
|
||||
action: async () =>
|
||||
{
|
||||
return await this.ReleaseSecondaryImageAction(id, imageId, etag);
|
||||
},
|
||||
etag: etag);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<IEnumerable<ImageSearchResult>>> Search(string query, int resultsCount = 10)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
@ -269,10 +297,10 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
else
|
||||
{
|
||||
var artistImages = Directory.GetFiles(artistFolder, "artist*.*");
|
||||
if (artistImages.Any())
|
||||
var artistImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), Library.Enums.ImageType.Artist);
|
||||
if(artistImages.Any())
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(artistImages.First());
|
||||
imageBytes = File.ReadAllBytes(artistImages.First().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -490,10 +518,10 @@ namespace Roadie.Api.Services
|
|||
}
|
||||
else
|
||||
{
|
||||
var coverArtFiles = Directory.GetFiles(releaseFolder, "cover*.*");
|
||||
if (coverArtFiles.Any())
|
||||
var releaseCoverFiles = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), Library.Enums.ImageType.Release);
|
||||
if(releaseCoverFiles.Any())
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(coverArtFiles.First());
|
||||
imageBytes = File.ReadAllBytes(releaseCoverFiles.First().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -522,6 +550,110 @@ namespace Roadie.Api.Services
|
|||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ReleaseSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var release = this.GetRelease(id);
|
||||
if (release == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
string releaseFolder = null;
|
||||
try
|
||||
{
|
||||
// See if cover art file exists in release folder
|
||||
artistFolder = release.Artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Artist Folder [{ artistFolder }], Not Found For Artist `{ release.Artist.ToString() }`");
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
if (!Directory.Exists(releaseFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Release Folder [{ releaseFolder }], Not Found For Release `{ release.ToString() }`");
|
||||
}
|
||||
else
|
||||
{
|
||||
var releaseSecondaryImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), Library.Enums.ImageType.ReleaseSecondary).ToArray();
|
||||
if(releaseSecondaryImages.Length >= imageId && releaseSecondaryImages[imageId] != null)
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(releaseSecondaryImages[imageId].FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"Error Reading Release Folder [{ releaseFolder }] Artist Folder [{ artistFolder }] For Artist `{ release.Artist.Id }`");
|
||||
}
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
CreatedDate = release.CreatedDate,
|
||||
LastUpdated = release.LastUpdated
|
||||
};
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Release Thumbnail [{ id }]", ex);
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
private Task<FileOperationResult<Image>> ArtistSecondaryImageAction(Guid id, int imageId, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var artist = this.GetArtist(id);
|
||||
if (artist == null)
|
||||
{
|
||||
return Task.FromResult(new FileOperationResult<Image>(true, string.Format("Release Not Found [{0}]", id)));
|
||||
}
|
||||
byte[] imageBytes = null;
|
||||
string artistFolder = null;
|
||||
try
|
||||
{
|
||||
// See if cover art file exists in release folder
|
||||
artistFolder = artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
if (!Directory.Exists(artistFolder))
|
||||
{
|
||||
this.Logger.LogWarning($"Artist Folder [{ artistFolder }], Not Found For Artist `{ artist }`");
|
||||
}
|
||||
else
|
||||
{
|
||||
var artistSecondaryImages = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(artistFolder), Library.Enums.ImageType.ArtistSecondary).ToArray();
|
||||
if (artistSecondaryImages.Length >= imageId && artistSecondaryImages[imageId] != null)
|
||||
{
|
||||
imageBytes = File.ReadAllBytes(artistSecondaryImages[imageId].FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, $"Error Reading Artist Folder [{ artistFolder }] For Artist `{ artist }`");
|
||||
}
|
||||
var image = new data.Image
|
||||
{
|
||||
Bytes = imageBytes,
|
||||
CreatedDate = artist.CreatedDate,
|
||||
LastUpdated = artist.LastUpdated
|
||||
};
|
||||
return Task.FromResult(GenerateFileOperationResult(id, image, etag));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError($"Error fetching Release Thumbnail [{ id }]", ex);
|
||||
}
|
||||
return Task.FromResult(new FileOperationResult<Image>(OperationMessages.ErrorOccured));
|
||||
}
|
||||
|
||||
|
||||
private async Task<FileOperationResult<Image>> TrackImageAction(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -834,6 +834,13 @@ namespace Roadie.Api.Services
|
|||
{
|
||||
result.Images = releaseImages;
|
||||
}
|
||||
var artistFolder = release.Artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
var releaseFolder = release.ReleaseFileFolder(artistFolder);
|
||||
var releaseImagesInFolder = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseFolder), ImageType.ReleaseSecondary);
|
||||
if(releaseImagesInFolder.Any())
|
||||
{
|
||||
result.Images = result.Images.Concat(releaseImagesInFolder.Select((x, i) => MakeFullsizeSecondaryImage(id, ImageType.ReleaseSecondary, i)));
|
||||
}
|
||||
}
|
||||
if (includes.Contains("playlists"))
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<PackageReference Include="Hashids.net" Version="1.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.9.2" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -5,6 +5,7 @@ using Roadie.Library;
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Utility;
|
||||
|
@ -278,6 +279,15 @@ namespace Roadie.Api.Services
|
|||
return new Image($"{this.HttpContext.ImageBaseUrl }/{id}", caption, $"{this.HttpContext.ImageBaseUrl }/{id}/{ this.Configuration.SmallImageSize.Width }/{ this.Configuration.SmallImageSize.Height }");
|
||||
}
|
||||
|
||||
protected Image MakeFullsizeSecondaryImage(Guid id, ImageType type, int imageId, string caption = null)
|
||||
{
|
||||
if(type == ImageType.ArtistSecondary)
|
||||
{
|
||||
return new Image($"{this.HttpContext.ImageBaseUrl }/artist-secondary/{id}/{imageId}", caption, $"{this.HttpContext.ImageBaseUrl }/artist-secondary/{id}/{ imageId }/{ this.Configuration.SmallImageSize.Width }/{ this.Configuration.SmallImageSize.Height }");
|
||||
}
|
||||
return new Image($"{this.HttpContext.ImageBaseUrl }/release-secondary/{id}/{imageId}", caption, $"{this.HttpContext.ImageBaseUrl }/release-secondary/{id}/{ imageId }/{ this.Configuration.SmallImageSize.Width }/{ this.Configuration.SmallImageSize.Height }");
|
||||
}
|
||||
|
||||
protected Image MakeImage(Guid id, int width = 200, int height = 200, string caption = null, bool includeCachebuster = false)
|
||||
{
|
||||
return new Image($"{this.HttpContext.ImageBaseUrl }/{id}/{ width }/{ height }/{ (includeCachebuster ? DateTime.UtcNow.Ticks.ToString() : string.Empty) }", caption, $"{this.HttpContext.ImageBaseUrl }/{id}/{ this.Configuration.SmallImageSize.Width }/{ this.Configuration.SmallImageSize.Height }");
|
||||
|
|
|
@ -54,6 +54,27 @@ namespace Roadie.Api.Controllers
|
|||
entityTag: result.ETag);
|
||||
}
|
||||
|
||||
[HttpGet("artist-secondary/{id}/{imageId}/{width:int?}/{height:int?}/{cacheBuster?}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> ArtistSecondaryImage(Guid id, int imageId, int? width, int? height)
|
||||
{
|
||||
var result = await this.ImageService.ArtistSecondaryImage(id, imageId, width ?? this.RoadieSettings.MaximumImageSize.Width, height ?? this.RoadieSettings.MaximumImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return File(fileContents: result.Data.Bytes,
|
||||
contentType: result.ContentType,
|
||||
fileDownloadName: $"{ result.Data.Caption ?? id.ToString()}.jpg",
|
||||
lastModified: result.LastModified,
|
||||
entityTag: result.ETag);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("collection/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
|
||||
[ProducesResponseType(200)]
|
||||
|
@ -177,6 +198,28 @@ namespace Roadie.Api.Controllers
|
|||
entityTag: result.ETag);
|
||||
}
|
||||
|
||||
[HttpGet("release-secondary/{id}/{imageId}/{width:int?}/{height:int?}/{cacheBuster?}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<IActionResult> ReleaseSecondaryImage(Guid id, int imageId, int? width, int? height)
|
||||
{
|
||||
var result = await this.ImageService.ReleaseSecondaryImage(id, imageId, width ?? this.RoadieSettings.MaximumImageSize.Width, height ?? this.RoadieSettings.MaximumImageSize.Height);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return File(fileContents: result.Data.Bytes,
|
||||
contentType: result.ContentType,
|
||||
fileDownloadName: $"{ result.Data.Caption ?? id.ToString()}.jpg",
|
||||
lastModified: result.LastModified,
|
||||
entityTag: result.ETag);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("track/{id}/{width:int?}/{height:int?}/{cacheBuster?}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt-Core" Version="2.0.0" />
|
||||
<PackageReference Include="Mapster" Version="3.3.0" />
|
||||
<PackageReference Include="Mapster" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.AspNet.SignalR" Version="2.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.1.0" />
|
||||
|
@ -34,7 +34,7 @@
|
|||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.RollingFileAlternate" Version="2.0.9" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.9.2" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
Loading…
Add table
Reference in a new issue