mirror of
https://github.com/sphildreth/roadie
synced 2024-11-22 20:23:16 +00:00
Artist edit work
This commit is contained in:
parent
66badbd0a2
commit
0dd198d3f3
8 changed files with 359 additions and 28 deletions
|
@ -16,8 +16,8 @@ namespace Roadie.Library.Data
|
|||
[Column("artistType", TypeName = "enum")]
|
||||
public string ArtistType { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public virtual ICollection<ArtistAssociation> AssociatedArtists { get; set; }
|
||||
[InverseProperty("Artist")]
|
||||
public ICollection<ArtistAssociation> AssociatedArtists { get; set; }
|
||||
|
||||
[Column("bandStatus", TypeName = "enum")]
|
||||
public BandStatus? BandStatus { get; set; }
|
||||
|
@ -82,6 +82,8 @@ namespace Roadie.Library.Data
|
|||
public Artist()
|
||||
{
|
||||
this.Releases = new HashSet<Release>();
|
||||
this.Genres = new HashSet<ArtistGenre>();
|
||||
this.AssociatedArtists = new HashSet<ArtistAssociation>();
|
||||
this.Rating = 0;
|
||||
this.Status = Statuses.Ok;
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@ namespace Roadie.Library.Data
|
|||
[Table("artistAssociation")]
|
||||
public partial class ArtistAssociation
|
||||
{
|
||||
//[ForeignKey("artistId")]
|
||||
public Artist Artist { get; set; }
|
||||
|
||||
[Column("artistId")]
|
||||
[Required]
|
||||
public int ArtistId { get; set; }
|
||||
|
||||
//[ForeignKey("associatedArtistId")]
|
||||
public Artist AssociatedArtist { get; set; }
|
||||
|
||||
[Column("associatedArtistId")]
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Identity;
|
||||
using Roadie.Library.Models.Releases;
|
||||
using System;
|
||||
|
||||
namespace Roadie.Library.Data
|
||||
|
@ -30,17 +28,16 @@ namespace Roadie.Library.Data
|
|||
public DbSet<Submission> Submissions { get; set; }
|
||||
public DbSet<Track> Tracks { get; set; }
|
||||
public DbSet<UserArtist> UserArtists { get; set; }
|
||||
public DbSet<UserRelease> UserReleases { get; set; }
|
||||
public DbSet<ApplicationUser> Users { get; set; }
|
||||
public DbSet<ApplicationRole> UserRoles { get; set; }
|
||||
public DbSet<UserTrack> UserTracks { get; set; }
|
||||
public DbSet<UserQue> UserQues { get; set; }
|
||||
public DbSet<UserRelease> UserReleases { get; set; }
|
||||
public DbSet<ApplicationRole> UserRoles { get; set; }
|
||||
public DbSet<ApplicationUser> Users { get; set; }
|
||||
public DbSet<UserTrack> UserTracks { get; set; }
|
||||
|
||||
public RoadieDbContext(DbContextOptions<RoadieDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
|
@ -78,6 +75,14 @@ namespace Roadie.Library.Data
|
|||
v => string.IsNullOrEmpty(v) ? CollectionType.Unknown : (CollectionType)Enum.Parse(typeof(CollectionType), v))
|
||||
.HasDefaultValue(CollectionType.Unknown);
|
||||
|
||||
builder
|
||||
.Entity<Artist>()
|
||||
.Property(e => e.BandStatus)
|
||||
.HasConversion(
|
||||
v => v.ToString(),
|
||||
v => string.IsNullOrEmpty(v) ? BandStatus.Unknown : (BandStatus)Enum.Parse(typeof(BandStatus), v))
|
||||
.HasDefaultValue(BandStatus.Unknown);
|
||||
|
||||
//builder
|
||||
// .Entity<Bookmark>()
|
||||
// .Property(e => e.BookmarkType)
|
||||
|
@ -154,27 +159,10 @@ namespace Roadie.Library.Data
|
|||
.WithMany(u => u.Bookmarks)
|
||||
.HasForeignKey(b => b.UserId);
|
||||
|
||||
builder.Entity<ArtistAssociation>()
|
||||
.HasOne(aa => aa.Artist)
|
||||
.WithMany(a => a.AssociatedArtists)
|
||||
.HasForeignKey(aa => aa.AssociatedArtistId);
|
||||
|
||||
//builder.Entity<Track>()
|
||||
// .HasOne(t => t.TrackArtist)
|
||||
// .WithMany(a => a.Tracks)
|
||||
// .HasForeignKey(t => t.ArtistId);
|
||||
|
||||
|
||||
//// I dont understand why the "1" but without this self join generates "1" based columns on the selectd and blows up ef.
|
||||
//builder.Entity<Artist>()
|
||||
// .HasMany(e => e.AssociatedArtists)
|
||||
// .WithOne(e => e.Artist)
|
||||
// .HasForeignKey(e => e.ArtistId);
|
||||
|
||||
//builder.Entity<Artist>()
|
||||
// .HasMany(e => e.AssociatedArtists1)
|
||||
// .WithOne(e => e.AssociatedArtist)
|
||||
// .HasForeignKey(e => e.AssociatedArtistId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -266,6 +266,7 @@ namespace Roadie.Library.Factories
|
|||
};
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public async Task<OperationResult<bool>> ScanArtistReleasesFolders(Guid artistId, string destinationFolder, bool doJustInfo)
|
||||
{
|
||||
SimpleContract.Requires<ArgumentOutOfRangeException>(artistId != Guid.Empty, "Invalid ArtistId");
|
||||
|
@ -359,6 +360,7 @@ namespace Roadie.Library.Factories
|
|||
};
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public async Task<OperationResult<Artist>> Update(Artist Artist, IEnumerable<Image> ArtistImages, string destinationFolder = null)
|
||||
{
|
||||
SimpleContract.Requires<ArgumentNullException>(Artist != null, "Invalid Artist");
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace Roadie.Library.Models
|
|||
|
||||
public IEnumerable<ArtistList> AssociatedArtists { get; set; }
|
||||
|
||||
public IEnumerable<DataToken> AssociatedArtistsTokens { get; set; }
|
||||
|
||||
public string BandStatus { get; set; }
|
||||
|
||||
[MaxLength(65535)]
|
||||
|
@ -67,6 +69,9 @@ namespace Roadie.Library.Models
|
|||
[MaxLength(250)]
|
||||
public string Name { get; set; }
|
||||
|
||||
// When populated a "data:image" base64 byte array of an image to use as new Thumbnail
|
||||
public string NewThumbnailData { get; set; }
|
||||
|
||||
[MaxLength(65535)]
|
||||
public string Profile { get; set; }
|
||||
|
||||
|
|
|
@ -7,9 +7,16 @@ using Roadie.Library;
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Engines;
|
||||
using Roadie.Library.Enums;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Factories;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.MetaData.Audio;
|
||||
using Roadie.Library.MetaData.FileName;
|
||||
using Roadie.Library.MetaData.ID3Tags;
|
||||
using Roadie.Library.MetaData.LastFm;
|
||||
using mb = Roadie.Library.MetaData.MusicBrainz;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Models.Pagination;
|
||||
using Roadie.Library.Models.Releases;
|
||||
|
@ -24,6 +31,7 @@ using System.Linq;
|
|||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using data = Roadie.Library.Data;
|
||||
using Roadie.Library.Processors;
|
||||
|
||||
namespace Roadie.Api.Services
|
||||
{
|
||||
|
@ -34,21 +42,45 @@ namespace Roadie.Api.Services
|
|||
private IPlaylistService PlaylistService { get; } = null;
|
||||
private IBookmarkService BookmarkService { get; } = null;
|
||||
|
||||
private IArtistLookupEngine ArtistLookupEngine { get; }
|
||||
private IAudioMetaDataHelper AudioMetaDataHelper { get; }
|
||||
private IFileNameHelper FileNameHelper { get; }
|
||||
private IID3TagsHelper ID3TagsHelper { get; }
|
||||
private IImageFactory ImageFactory { get; }
|
||||
private ILabelFactory LabelFactory { get; }
|
||||
private ILabelLookupEngine LabelLookupEngine { get; }
|
||||
private ILastFmHelper LastFmHelper { get; }
|
||||
private mb.IMusicBrainzProvider MusicBrainzProvider { get; }
|
||||
private IReleaseFactory ReleaseFactory { get; }
|
||||
private IArtistFactory ArtistFactory { get; }
|
||||
private IReleaseLookupEngine ReleaseLookupEngine { get; }
|
||||
|
||||
public ArtistService(IRoadieSettings configuration,
|
||||
IHttpEncoder httpEncoder,
|
||||
IHttpContext httpContext,
|
||||
data.IRoadieDbContext context,
|
||||
data.IRoadieDbContext dbContext,
|
||||
ICacheManager cacheManager,
|
||||
ILogger<ArtistService> logger,
|
||||
ICollectionService collectionService,
|
||||
IPlaylistService playlistService,
|
||||
IBookmarkService bookmarkService
|
||||
)
|
||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
|
||||
{
|
||||
this.CollectionService = collectionService;
|
||||
this.PlaylistService = playlistService;
|
||||
this.BookmarkService = bookmarkService;
|
||||
|
||||
this.ArtistLookupEngine = new ArtistLookupEngine(configuration, httpEncoder, dbContext, cacheManager, logger);
|
||||
this.LabelLookupEngine = new LabelLookupEngine(configuration, httpEncoder, dbContext, cacheManager, logger);
|
||||
this.ReleaseLookupEngine = new ReleaseLookupEngine(configuration, httpEncoder, dbContext, cacheManager, logger, this.ArtistLookupEngine, this.LabelLookupEngine);
|
||||
this.ImageFactory = new ImageFactory(configuration, httpEncoder, dbContext, cacheManager, logger, this.ArtistLookupEngine, this.ReleaseLookupEngine);
|
||||
this.LabelFactory = new LabelFactory(configuration, httpEncoder, dbContext, cacheManager, logger, this.ArtistLookupEngine, this.ReleaseLookupEngine);
|
||||
this.AudioMetaDataHelper = new AudioMetaDataHelper(configuration, httpEncoder, dbContext, this.MusicBrainzProvider, this.LastFmHelper, cacheManager,
|
||||
logger, this.ArtistLookupEngine, this.ImageFactory, this.FileNameHelper, this.ID3TagsHelper);
|
||||
|
||||
this.ReleaseFactory = new ReleaseFactory(configuration, httpEncoder, dbContext, cacheManager, logger, this.ArtistLookupEngine, this.LabelFactory, this.AudioMetaDataHelper, this.ReleaseLookupEngine);
|
||||
this.ArtistFactory = new ArtistFactory(configuration, httpEncoder, dbContext, cacheManager, logger, this.ArtistLookupEngine, this.ReleaseFactory, this.ImageFactory, this.ReleaseLookupEngine, this.AudioMetaDataHelper);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<Artist>> ById(User roadieUser, Guid id, IEnumerable<string> includes)
|
||||
|
@ -272,6 +304,7 @@ namespace Roadie.Api.Services
|
|||
}).ToArray();
|
||||
|
||||
result.AssociatedArtists = associatedArtists.Union(associatedWithArtists).OrderBy(x => x.SortName);
|
||||
result.AssociatedArtistsTokens = result.AssociatedArtists.Select(x => x.Artist).ToArray();
|
||||
tsw.Stop();
|
||||
timings.Add("associatedartists", tsw.ElapsedMilliseconds);
|
||||
|
||||
|
@ -478,6 +511,282 @@ namespace Roadie.Api.Services
|
|||
return await this.SaveImageBytes(user, id, bytes);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> UpdateArtist(User user, Artist model)
|
||||
{
|
||||
var didRenameArtist = false;
|
||||
var didChangeThumbnail = false;
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var errors = new List<Exception>();
|
||||
var artist = this.DbContext.Artists
|
||||
.Include(x => x.Genres)
|
||||
.Include("Genres.Genre")
|
||||
.FirstOrDefault(x => x.RoadieId == model.Id);
|
||||
if (artist == null)
|
||||
{
|
||||
return new OperationResult<bool>(true, string.Format("Artist Not Found [{0}]", model.Id));
|
||||
}
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var originalArtistFolder = artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
artist.AlternateNames = model.AlternateNamesList.ToDelimitedList();
|
||||
artist.AmgId = model.AmgId;
|
||||
artist.BeginDate = model.BeginDate;
|
||||
artist.BioContext = model.BioContext;
|
||||
artist.BirthDate = model.BirthDate;
|
||||
artist.DiscogsId = model.DiscogsId;
|
||||
artist.EndDate = model.EndDate;
|
||||
artist.IsLocked = model.IsLocked;
|
||||
artist.ISNIList = model.ISNIList.ToDelimitedList();
|
||||
artist.ITunesId = model.ITunesId;
|
||||
artist.MusicBrainzId = model.MusicBrainzId;
|
||||
artist.Name = model.Name;
|
||||
artist.Profile = model.Profile;
|
||||
artist.Rating = model.Rating;
|
||||
artist.RealName = model.RealName;
|
||||
artist.SortName = model.SortName;
|
||||
artist.SpotifyId = model.SpotifyId;
|
||||
artist.Status = SafeParser.ToEnum<Statuses>(model.Status);
|
||||
artist.Tags = model.TagsList.ToDelimitedList();
|
||||
artist.URLs = model.URLsList.ToDelimitedList();
|
||||
|
||||
var newArtistFolder = artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
|
||||
if (!newArtistFolder.Equals(originalArtistFolder, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
didRenameArtist = true;
|
||||
|
||||
// Rename artist folder to reflect new artist name
|
||||
this.Logger.LogTrace("Moving Artist From Folder [{0}] To [{1}]", originalArtistFolder, newArtistFolder);
|
||||
Directory.Move(originalArtistFolder, newArtistFolder);
|
||||
|
||||
// Update artist tracks to have new artist name in ID3 metadata
|
||||
foreach (var mp3 in Directory.GetFiles(newArtistFolder, "*.mp3", SearchOption.AllDirectories))
|
||||
{
|
||||
var trackFileInfo = new FileInfo(mp3);
|
||||
var audioMetaData = await this.AudioMetaDataHelper.GetInfo(trackFileInfo);
|
||||
if (audioMetaData != null)
|
||||
{
|
||||
audioMetaData.Artist = artist.Name;
|
||||
this.AudioMetaDataHelper.WriteTags(audioMetaData, trackFileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
var artistImage = ImageHelper.ImageDataFromUrl(model.NewThumbnailData);
|
||||
if (artistImage != null)
|
||||
{
|
||||
// Ensure is jpeg first
|
||||
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artistImage);
|
||||
|
||||
// Save unaltered image to cover file
|
||||
var artistImageName = Path.Combine(artist.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder), "artist.jpg");
|
||||
File.WriteAllBytes(artistImageName, artist.Thumbnail);
|
||||
|
||||
// Resize to store in database as thumbnail
|
||||
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
didChangeThumbnail = true;
|
||||
}
|
||||
|
||||
if (model.Genres != null && model.Genres.Any())
|
||||
{
|
||||
// Remove existing Genres not in model list
|
||||
foreach (var genre in artist.Genres.ToList())
|
||||
{
|
||||
var doesExistInModel = model.Genres.Any(x => SafeParser.ToGuid(x.Value) == genre.Genre.RoadieId);
|
||||
if (!doesExistInModel)
|
||||
{
|
||||
artist.Genres.Remove(genre);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new Genres in model not in data
|
||||
foreach (var genre in model.Genres)
|
||||
{
|
||||
var genreId = SafeParser.ToGuid(genre.Value);
|
||||
var doesExistInData = artist.Genres.Any(x => x.Genre.RoadieId == genreId);
|
||||
if (!doesExistInData)
|
||||
{
|
||||
var g = this.DbContext.Genres.FirstOrDefault(x => x.RoadieId == genreId);
|
||||
if (g != null)
|
||||
{
|
||||
artist.Genres.Add(new data.ArtistGenre
|
||||
{
|
||||
ArtistId = artist.Id,
|
||||
GenreId = g.Id,
|
||||
Genre = g
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (model.Genres == null || !model.Genres.Any())
|
||||
{
|
||||
artist.Genres.Clear();
|
||||
}
|
||||
|
||||
if (model.AssociatedArtistsTokens != null && model.AssociatedArtistsTokens.Any())
|
||||
{
|
||||
var associatedArtists = this.DbContext.ArtistAssociations.Include(x => x.AssociatedArtist).Where(x => x.ArtistId == artist.Id).ToList();
|
||||
|
||||
// Remove existing AssociatedArtists not in model list
|
||||
foreach (var associatedArtist in associatedArtists)
|
||||
{
|
||||
var doesExistInModel = model.AssociatedArtistsTokens.Any(x => SafeParser.ToGuid(x.Value) == associatedArtist.AssociatedArtist.RoadieId);
|
||||
if (!doesExistInModel)
|
||||
{
|
||||
this.DbContext.ArtistAssociations.Remove(associatedArtist);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new AssociatedArtists in model not in data
|
||||
foreach (var associatedArtist in model.AssociatedArtistsTokens)
|
||||
{
|
||||
var associatedArtistId = SafeParser.ToGuid(associatedArtist.Value);
|
||||
var doesExistInData = associatedArtists.Any(x => x.AssociatedArtist.RoadieId == associatedArtistId);
|
||||
if (!doesExistInData)
|
||||
{
|
||||
var a = this.DbContext.Artists.FirstOrDefault(x => x.RoadieId == associatedArtistId);
|
||||
if (a != null)
|
||||
{
|
||||
this.DbContext.ArtistAssociations.Add(new data.ArtistAssociation
|
||||
{
|
||||
ArtistId = artist.Id,
|
||||
AssociatedArtistId = a.Id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (model.AssociatedArtistsTokens == null || !model.AssociatedArtistsTokens.Any())
|
||||
{
|
||||
artist.AssociatedArtists.Clear();
|
||||
}
|
||||
|
||||
|
||||
if (model.Images != null && model.Images.Any())
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
artist.LastUpdated = now;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
if (didRenameArtist) {
|
||||
await this.ScanArtistReleasesFolders(artist.RoadieId, this.Configuration.LibraryFolder, false);
|
||||
}
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
this.Logger.LogInformation($"UpdateArtist `{ artist }` By User `{ user }`: Renamed Artist [{ didRenameArtist }], Uploaded new image [{ didChangeThumbnail }]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex);
|
||||
errors.Add(ex);
|
||||
}
|
||||
sw.Stop();
|
||||
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
IsSuccess = !errors.Any(),
|
||||
Data = !errors.Any(),
|
||||
OperationTime = sw.ElapsedMilliseconds,
|
||||
Errors = errors
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<OperationResult<bool>> ScanArtistReleasesFolders(Guid artistId, string destinationFolder, bool doJustInfo)
|
||||
{
|
||||
SimpleContract.Requires<ArgumentOutOfRangeException>(artistId != Guid.Empty, "Invalid ArtistId");
|
||||
|
||||
var result = true;
|
||||
var resultErrors = new List<Exception>();
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
try
|
||||
{
|
||||
var artist = this.DbContext.Artists
|
||||
.Include("Releases")
|
||||
.Include("Releases.Labels")
|
||||
.FirstOrDefault(x => x.RoadieId == artistId);
|
||||
if (artist == null)
|
||||
{
|
||||
this.Logger.LogWarning("Unable To Find Artist [{0}]", artistId);
|
||||
return new OperationResult<bool>();
|
||||
}
|
||||
var releaseScannedCount = 0;
|
||||
var artistFolder = artist.ArtistFileFolder(this.Configuration, destinationFolder);
|
||||
var scannedArtistFolders = new List<string>();
|
||||
// Scan known releases for changes
|
||||
if (artist.Releases != null)
|
||||
{
|
||||
foreach (var release in artist.Releases)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = result && (await this.ReleaseFactory.ScanReleaseFolder(Guid.Empty, destinationFolder, doJustInfo, release)).Data;
|
||||
releaseScannedCount++;
|
||||
scannedArtistFolders.Add(release.ReleaseFileFolder(artistFolder));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, ex.Serialize());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Any folder found in Artist folder not already scanned scan
|
||||
var folderProcessor = new FolderProcessor(this.Configuration, this.HttpEncoder, destinationFolder, this.DbContext, this.CacheManager, this.Logger, this.ArtistLookupEngine, this.ArtistFactory, this.ReleaseFactory, this.ImageFactory, this.ReleaseLookupEngine, this.AudioMetaDataHelper);
|
||||
var nonReleaseFolders = (from d in Directory.EnumerateDirectories(artistFolder)
|
||||
where !(from r in scannedArtistFolders select r).Contains(d)
|
||||
orderby d
|
||||
select d);
|
||||
foreach (var folder in nonReleaseFolders)
|
||||
{
|
||||
await folderProcessor.Process(new DirectoryInfo(folder), doJustInfo);
|
||||
}
|
||||
if (!doJustInfo)
|
||||
{
|
||||
FolderProcessor.DeleteEmptyFolders(new DirectoryInfo(artistFolder), this.Logger);
|
||||
}
|
||||
|
||||
// Always update artist image if artist image is found on an artist rescan
|
||||
var imageFiles = ImageHelper.ImageFilesInFolder(artistFolder);
|
||||
if (imageFiles != null && imageFiles.Any())
|
||||
{
|
||||
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());
|
||||
if (isArtistImage)
|
||||
{
|
||||
// Read image and convert to jpeg
|
||||
artist.Thumbnail = File.ReadAllBytes(i.FullName);
|
||||
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
|
||||
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artist.Thumbnail);
|
||||
artist.LastUpdated = DateTime.UtcNow;
|
||||
await this.DbContext.SaveChangesAsync();
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
this.Logger.LogInformation("Update Thumbnail using Artist File [{0}]", iName);
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
this.CacheManager.ClearRegion(artist.CacheRegion);
|
||||
this.Logger.LogInformation("Scanned Artist [{0}], Releases Scanned [{1}], OperationTime [{2}]", artist.ToString(), releaseScannedCount, sw.ElapsedMilliseconds);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Logger.LogError(ex, ex.Serialize());
|
||||
resultErrors.Add(ex);
|
||||
}
|
||||
return new OperationResult<bool>
|
||||
{
|
||||
Data = result,
|
||||
IsSuccess = result,
|
||||
Errors = resultErrors,
|
||||
OperationTime = sw.ElapsedMilliseconds
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private async Task<OperationResult<Library.Models.Image>> SaveImageBytes(User user, Guid id, byte[] imageBytes)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
|
|
@ -16,5 +16,6 @@ namespace Roadie.Api.Services
|
|||
Task<PagedResult<ArtistList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, bool? onlyIncludeWithReleases = true);
|
||||
Task<OperationResult<Library.Models.Image>> SetReleaseImageByUrl(User user, Guid id, string imageUrl);
|
||||
Task<OperationResult<Library.Models.Image>> UploadArtistImage(User user, Guid id, IFormFile file);
|
||||
Task<OperationResult<bool>> UpdateArtist(User user, Artist artist);
|
||||
}
|
||||
}
|
|
@ -101,5 +101,27 @@ namespace Roadie.Api.Controllers
|
|||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("edit")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
[Authorize(Policy = "Editor")]
|
||||
public async Task<IActionResult> Update(models.Artist artist)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
var result = await this.ArtistService.UpdateArtist(await this.CurrentUserModel(), artist);
|
||||
if (result == null || result.IsNotFoundResult)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue